Skip to content

Commit

Permalink
refactor: normalized interfacing with ziggy
Browse files Browse the repository at this point in the history
  • Loading branch information
tomasklaen committed Sep 4, 2024
1 parent 3ee3d47 commit c00fbfa
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 70 deletions.
90 changes: 32 additions & 58 deletions src/uosc/lib/menus.lua
Original file line number Diff line number Diff line change
Expand Up @@ -895,49 +895,40 @@ function open_subtitle_downloader()
end
end

local handle_select, handle_search

-- Ensures response is valid, and returns its payload, or handles error reporting,
-- and returns `nil`, indicating the consumer should abort response handling.
local function ensure_response_data(success, result, error, check)
local data
if success and result and result.status == 0 then
data = utils.parse_json(result.stdout)
if not data or not check(data) then
data = (data and data.error == true) and data or {
error = true,
message = t('invalid response json (see console for details)'),
message_verbose = 'invalid response json: ' .. utils.to_string(result.stdout),
}
end
else
data = {
error = true,
message = error or t('process exited with code %s (see console for details)', result.status),
message_verbose = result.stdout .. result.stderr,
}
end

if data.error then
local message, message_verbose = data.message or t('unknown error'), data.message_verbose or data.message
if message_verbose then msg.error(message_verbose) end
local handle_download, handle_search

-- Checks if there an error, or data is invalid. If true, reports the error,
-- updates menu to inform about it, and returns true.
---@param error string|nil
---@param data any
---@param check_is_valid? fun(data: any):boolean
---@return boolean abort Whether the further response handling should be aborted.
local function should_abort(error, data, check_is_valid)
if error or not data or (not check_is_valid or not check_is_valid(data)) then
menu:update_items({
{
title = message,
hint = t('error'),
title = t('Something went wrong.'),
align = 'center',
muted = true,
italic = true,
selectable = false,
},
{
title = t('See console for details.'),
align = 'center',
muted = true,
italic = true,
selectable = false,
},
})
return
msg.error(error or ('Invalid response: ' .. (utils.format_json(data) or tostring(data))))
return true
end

return data
return false
end

---@param data {kind: 'file', id: number}|{kind: 'page', query: string, page: number}
handle_select = function(data)
handle_download = function(data)
if data.kind == 'page' then
handle_search(data.query, data.page)
return
Expand All @@ -953,25 +944,14 @@ function open_subtitle_downloader()
end
end)

local args = itable_join({config.ziggy_path, 'download-subtitles'}, credentials, {
local args = itable_join({'download-subtitles'}, credentials, {
'--file-id', tostring(data.id),
'--destination', destination_directory,
})

mp.command_native_async({
name = 'subprocess',
capture_stderr = true,
capture_stdout = true,
playback_only = false,
args = args,
}, function(success, result, error)
call_ziggy_async(args, function(error, data)
if not menu:is_alive() then return end

local data = ensure_response_data(success, result, error, function(data)
return type(data.file) == 'string'
end)

if not data then return end
if should_abort(error, data, function(data) return type(data.file) == 'string' end) then return end

load_track('sub', data.file)

Expand Down Expand Up @@ -1008,7 +988,7 @@ function open_subtitle_downloader()

menu:update_items({{icon = 'spinner', align = 'center', selectable = false, muted = true}})

local args = itable_join({config.ziggy_path, 'search-subtitles'}, credentials)
local args = itable_join({'search-subtitles'}, credentials)

local languages = itable_filter(get_languages(), function(lang) return lang:match('.json$') == nil end)
args[#args + 1] = '--languages'
Expand All @@ -1027,20 +1007,14 @@ function open_subtitle_downloader()
args[#args + 1] = query
end

mp.command_native_async({
name = 'subprocess',
capture_stderr = true,
capture_stdout = true,
playback_only = false,
args = args,
}, function(success, result, error)
call_ziggy_async(args, function(error, data)
if not menu:is_alive() then return end

local data = ensure_response_data(success, result, error, function(data)
local function check_is_valid(data)
return type(data.data) == 'table' and data.page and data.total_pages
end)
end

if not data then return end
if should_abort(error, data, check_is_valid) then return end

local subs = itable_filter(data.data, function(sub)
return sub and sub.attributes and sub.attributes.release and type(sub.attributes.files) == 'table' and
Expand Down Expand Up @@ -1131,7 +1105,7 @@ function open_subtitle_downloader()
end
end)
elseif not event.action then
handle_select(event.value)
handle_download(event.value)
end
elseif event.type == 'search' then
handle_search(event.query)
Expand Down
79 changes: 67 additions & 12 deletions src/uosc/lib/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -814,30 +814,85 @@ function load_track(type, path)
end
end

---@return string|nil
function get_clipboard()
---@param args (string|number)[]
---@return string|nil error
---@return table data
function call_ziggy(args)
local result = mp.command_native({
name = 'subprocess',
capture_stderr = true,
capture_stdout = true,
playback_only = false,
args = {config.ziggy_path, 'get-clipboard'},
args = itable_join({config.ziggy_path}, args),
})

local function print_error(message)
msg.error('Getting clipboard data failed. Error: ' .. message)
if result.status ~= 0 then
return 'Calling ziggy failed. Exit code ' .. result.status .. ': ' .. result.stdout .. result.stderr, {}
end

local data = utils.parse_json(result.stdout)
if not data then
return 'Ziggy response error. Couldn\'t parse json: ' .. result.stdout, {}
elseif data.error then
return 'Ziggy error: ' .. data.message, {}
else
return nil, data
end
end

if result.status == 0 then
local data = utils.parse_json(result.stdout)
if data and data.payload then
return data.payload
---@param args (string|number)[]
---@param callback fun(error: string|nil, data: table)
---@return fun() abort Function to abort the request.
function call_ziggy_async(args, callback)
local abort_signal = mp.command_native_async({
name = 'subprocess',
capture_stderr = true,
capture_stdout = true,
playback_only = false,
args = itable_join({config.ziggy_path}, args),
}, function(success, result, error)
if not success or not result or result.status ~= 0 then
local exit_code = (result and result.status or 'unknown')
local message = error or (result and result.stdout .. result.stderr) or ''
callback('Calling ziggy failed. Exit code: ' .. exit_code .. ' Error: ' .. message, {})
return
end

local json = result and type(result.stdout) == 'string' and result.stdout or ''
local data = utils.parse_json(json)
if not data then
callback('Ziggy response error. Couldn\'t parse json: ' .. json, {})
elseif data.error then
callback('Ziggy error: ' .. data.message, {})
else
print_error(data and (data.error and data.message or 'unknown error') or 'couldn\'t parse json')
return callback(nil, data)
end
else
print_error('exit code ' .. result.status .. ': ' .. result.stdout .. result.stderr)
end)

return function()
mp.abort_async_command(abort_signal)
end
end

---@return string|nil
function get_clipboard()
local err, data = call_ziggy({'get-clipboard'})
if err then
mp.commandv('show-text', 'Get clipboard error. See console for details.')
msg.error(err)
end
return data and data.payload
end

---@param payload any
---@return string|nil payload String that was copied to clipboard.
function set_clipboard(payload)
local err, data = call_ziggy({'set-clipboard', tostring(payload)})
if err then
mp.commandv('show-text', 'Set clipboard error. See console for details.')
msg.error(err)
end
return data and data.payload
end

--[[ RENDERING ]]
Expand Down

0 comments on commit c00fbfa

Please sign in to comment.