diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..c695a77 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,32 @@ +name: Bug Report +description: File a bug report +body: + - type: input + attributes: + label: Workflow version + description: Open the Workflow in Alfred Preferences → click [𝓧] → Workflow Version + validations: + required: true + - type: input + attributes: + label: Alfred version + description: In the top left corner of Alfred Preferences → General + validations: + required: true + - type: input + attributes: + label: macOS version + description: Click  on the menubar → About This Mac → Overview + validations: + required: true + - type: textarea + attributes: + label: Debugger output + description: Open the Workflow in Alfred Preferences → click the bug icon → perform the failing action + render: alfred_debugger + validations: + required: true + - type: textarea + attributes: + label: More details + description: Explain what you did, what happened, and what you expected to happen diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7a9b687 --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, Running with Crayons Ltd +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..9b2805d --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# icon TinyPNG Alfred Workflow + +Compress images via TinyPNG + +## Instructions + +Use the File Action, File Filter, or External Trigger to compress PNG, JPEG, and WebP images via [TinyPNG](https://tinypng.com/). + +![](https://i.imgur.com/mlX713P.png) + +Before using the Workflow, [request an API key](https://tinypng.com/developers) and add it to the `api_key` Workflow Environment Variable. + +`backup_originals` takes a directory path to save the unmodified images. Use `~` to reference your home directory. Leave it empty to not save backups. + +## Download + +[Get the latest release.](https://github.com/alfredapp/tinypng-workflow/releases/latest/download/TinyPNG.alfredworkflow) + +## License + +3-Clause BSD diff --git a/Workflow/icon.png b/Workflow/icon.png new file mode 100644 index 0000000..29c1337 Binary files /dev/null and b/Workflow/icon.png differ diff --git a/Workflow/info.plist b/Workflow/info.plist new file mode 100644 index 0000000..9b31725 --- /dev/null +++ b/Workflow/info.plist @@ -0,0 +1,608 @@ + + + + + bundleid + com.alfredapp.tinypng + connections + + 392049EC-35AB-4C54-8A20-5565FBF67B32 + + + destinationuid + F2C7428D-06C2-4B70-8C70-8348AE71B137 + modifiers + 0 + modifiersubtext + + vitoclose + + + + 72DE7DEE-B771-41EA-9A7C-F10F4F7A5DC5 + + 7EA1CA9C-97FC-4B89-999A-7CFE3D8CB0AE + + + destinationuid + F2C7428D-06C2-4B70-8C70-8348AE71B137 + modifiers + 0 + modifiersubtext + + vitoclose + + + + C22E0CBD-0683-4E3A-80E5-6532D8E5440E + + + destinationuid + 4D6432C7-2943-4DB6-A25F-B0AC57D3C6F2 + modifiers + 0 + modifiersubtext + + sourceoutputuid + 2402FAA7-E693-486D-84EA-BF27BF8E4AFD + vitoclose + + + + destinationuid + 6D56D157-3EBC-41F6-A030-1C9A9E4490DF + modifiers + 0 + modifiersubtext + + vitoclose + + + + E4256C3E-6831-43F5-805C-F667A3D7E726 + + + destinationuid + 72DE7DEE-B771-41EA-9A7C-F10F4F7A5DC5 + modifiers + 0 + modifiersubtext + + vitoclose + + + + destinationuid + C22E0CBD-0683-4E3A-80E5-6532D8E5440E + modifiers + 0 + modifiersubtext + + vitoclose + + + + F2C7428D-06C2-4B70-8C70-8348AE71B137 + + + destinationuid + DB3CBD80-5AFA-4CF7-97B8-A9AAB1651C88 + modifiers + 0 + modifiersubtext + + vitoclose + + + + destinationuid + E4256C3E-6831-43F5-805C-F667A3D7E726 + modifiers + 0 + modifiersubtext + + vitoclose + + + + FD60CC76-3DD5-45D7-A184-5A5580E0790F + + + destinationuid + F2C7428D-06C2-4B70-8C70-8348AE71B137 + modifiers + 0 + modifiersubtext + + vitoclose + + + + + createdby + Vítor Galvão + description + Compress images via TinyPNG + disabled + + name + TinyPNG + objects + + + config + + concurrently + + escaping + 0 + script + # THESE VARIABLES MUST BE SET. SEE THE ONEUPDATER README FOR AN EXPLANATION OF EACH. +readonly remote_info_plist="https://raw.githubusercontent.com/alfredapp/tinypng-workflow/master/Workflow/info.plist" +readonly workflow_url="alfredapp/tinypng-workflow" +readonly download_type='github_release' +readonly frequency_check='4' + +# FROM HERE ON, CODE SHOULD BE LEFT UNTOUCHED! +function abort { + echo "${1}" >&2 + exit 1 +} + +function url_exists { + curl --silent --location --output /dev/null --fail --range 0-0 "${1}" +} + +function notification { + local -r notificator="$(find . -type d -name 'Notificator.app')" + if [[ -n "${notificator}" ]]; then + "${notificator}/Contents/Resources/Scripts/notificator" --message "${1}" --title "${alfred_workflow_name}" --subtitle 'A new version is available' + return + fi + + local -r terminal_notifier="$(find . -type f -name 'terminal-notifier')" + if [[ -n "${terminal_notifier}" ]]; then + "${terminal_notifier}" -title "${alfred_workflow_name}" -subtitle 'A new version is available' -message "${1}" + return + fi + + osascript -e "display notification \"${1}\" with title \"${alfred_workflow_name}\" subtitle \"A new version is available\"" +} + +# Local sanity checks +readonly local_info_plist='info.plist' +readonly local_version="$(/usr/libexec/PlistBuddy -c 'print version' "${local_info_plist}")" + +[[ -n "${local_version}" ]] || abort 'You need to set a workflow version in the configuration sheet.' +[[ "${download_type}" =~ ^(direct|page|github_release)$ ]] || abort "'download_type' (${download_type}) needs to be one of 'direct', 'page', or 'github_release'." +[[ "${frequency_check}" =~ ^[0-9]+$ ]] || abort "'frequency_check' (${frequency_check}) needs to be a number." + +# Check for updates +if [[ $(find "${local_info_plist}" -mtime +"${frequency_check}"d) ]]; then + if ! url_exists "${remote_info_plist}"; then abort "'remote_info_plist' (${remote_info_plist}) appears to not be reachable."; fi # Remote sanity check + + readonly tmp_file="$(mktemp)" + curl --silent --location --output "${tmp_file}" "${remote_info_plist}" + readonly remote_version="$(/usr/libexec/PlistBuddy -c 'print version' "${tmp_file}")" + + if [[ "${local_version}" == "${remote_version}" ]]; then + touch "${local_info_plist}" # Reset timer by touching local file + exit 0 + fi + + if [[ "${download_type}" == 'page' ]]; then + notification 'Opening download page…' + open "${workflow_url}" + exit 0 + fi + + download_url="$([[ "${download_type}" == 'github_release' ]] && curl --silent "https://api.github.com/repos/${workflow_url}/releases/latest" | grep 'browser_download_url' | head -1 | sed -E 's/.*browser_download_url": "(.*)"/\1/' || echo "${workflow_url}")" + + if url_exists "${download_url}"; then + notification 'Downloading and installing…' + curl --silent --location --output "${HOME}/Downloads/${alfred_workflow_name}.alfredworkflow" "${download_url}" + open "${HOME}/Downloads/${alfred_workflow_name}.alfredworkflow" + else + abort "'workflow_url' (${download_url}) appears to not be reachable." + fi +fi + scriptargtype + 1 + scriptfile + + type + 0 + + type + alfred.workflow.action.script + uid + DB3CBD80-5AFA-4CF7-97B8-A9AAB1651C88 + version + 2 + + + config + + concurrently + + escaping + 102 + script + # Constants +readonly backup_dir="${backup_originals/#\~/${HOME}}/$(date -u +'%Y.%m.%d.%H%M%S')" + +# Helpers +function get_json_key { + local -r json="${1}" # JSON string + local -r key="${2}" # Of the form ['first']['second'] or .first.second + + local -r result="$(osascript -l 'JavaScript' -e "function run(argv) { return JSON.parse(argv[0])${key} }" "${json}")" + + [[ -n "${key}" && -n "${result}" ]] || return 1 # If no valid result + + echo -n "${result}" +} + +function error { + echo "${1}" >&2 # For Alfred's debugger + echo "error|${1}" # For the notification and sound + exit 1 +} + +# Main +# Abort if backups are desirable but cannot create directory +if [[ -n "${backup_originals}" ]] && ! mkdir -p "${backup_dir}"; then + error "Could not create backups directory at ${backup_originals}!" +fi + +# Loop over images +for image in "${@}"; do + json_response="$(curl --silent --user api:"${api_key}" --data-binary @"${image}" -i 'https://api.tinify.com/shrink' | tail -1)" + + # On error + if [[ -n "$(get_json_key "${json_response}" '.error')" ]]; then + error "$(get_json_key "${json_response}" '.message')" + fi + + # Backup image + if [[ -d "${backup_dir}" ]]; then + cp "${image}" "${backup_dir}" + fi + + # Save result + compressed_url="$(get_json_key "${json_response}" '.output.url')" + curl --silent "${compressed_url}" --output "${image}" +done + +echo 'success|Finished compressing' + scriptargtype + 1 + scriptfile + + type + 0 + + type + alfred.workflow.action.script + uid + F2C7428D-06C2-4B70-8C70-8348AE71B137 + version + 2 + + + config + + acceptsmulti + 1 + filetypes + + org.webmproject.webp + public.jpeg + public.png + + name + TinyPNG Compression + + type + alfred.workflow.trigger.action + uid + 7EA1CA9C-97FC-4B89-999A-7CFE3D8CB0AE + version + 1 + + + config + + lastpathcomponent + + onlyshowifquerypopulated + + removeextension + + text + {var:split2} + title + TinyPNG + + type + alfred.workflow.output.notification + uid + 72DE7DEE-B771-41EA-9A7C-F10F4F7A5DC5 + version + 1 + + + config + + anchorfields + + argumenttrimmode + 0 + argumenttype + 0 + daterange + 0 + fields + + + field + kMDItemDisplayName + not + + split + + value + {query} + words + + + + field + kMDItemAlternateNames + not + + split + + value + {query} + words + + + + field + kMDItemFinderComment + not + + split + + value + {query} + words + + + + includesystem + + keyword + tinypng + limit + 0 + runningsubtext + + scopes + + sortmode + 0 + subtext + Filter for images to compress + title + TinyPNG Compression + types + + org.webmproject.webp + public.jpeg + public.png + + withspace + + + type + alfred.workflow.input.filefilter + uid + 392049EC-35AB-4C54-8A20-5565FBF67B32 + version + 2 + + + config + + delimiter + | + trimarguments + + variableprefix + split + + type + alfred.workflow.utility.split + uid + E4256C3E-6831-43F5-805C-F667A3D7E726 + version + 1 + + + config + + triggerid + compress + + type + alfred.workflow.trigger.external + uid + FD60CC76-3DD5-45D7-A184-5A5580E0790F + version + 1 + + + config + + soundname + Glass + systemsound + + + type + alfred.workflow.output.playsound + uid + 4D6432C7-2943-4DB6-A25F-B0AC57D3C6F2 + version + 1 + + + config + + conditions + + + inputstring + {var:split1} + matchcasesensitive + + matchmode + 0 + matchstring + success + outputlabel + Success + uid + 2402FAA7-E693-486D-84EA-BF27BF8E4AFD + + + elselabel + Error + + type + alfred.workflow.utility.conditional + uid + C22E0CBD-0683-4E3A-80E5-6532D8E5440E + version + 1 + + + config + + soundname + Basso + systemsound + + + type + alfred.workflow.output.playsound + uid + 6D56D157-3EBC-41F6-A030-1C9A9E4490DF + version + 1 + + + readme + Use the File Action, File Filter, or External Trigger to compress PNG, JPEG, and WebP images via [TinyPNG](https://tinypng.com/). + +![](https://i.imgur.com/mlX713P.png) + +Before using the Workflow, [request an API key](https://tinypng.com/developers) and add it to the `api_key` Workflow Environment Variable. + +`backup_originals` takes a directory path to save the unmodified images. Use `~` to reference your home directory. Leave it empty to not save backups. + uidata + + 392049EC-35AB-4C54-8A20-5565FBF67B32 + + xpos + 35 + ypos + 190 + + 4D6432C7-2943-4DB6-A25F-B0AC57D3C6F2 + + xpos + 575 + ypos + 320 + + 6D56D157-3EBC-41F6-A030-1C9A9E4490DF + + xpos + 575 + ypos + 455 + + 72DE7DEE-B771-41EA-9A7C-F10F4F7A5DC5 + + xpos + 575 + ypos + 190 + + 7EA1CA9C-97FC-4B89-999A-7CFE3D8CB0AE + + xpos + 35 + ypos + 40 + + C22E0CBD-0683-4E3A-80E5-6532D8E5440E + + xpos + 455 + ypos + 355 + + DB3CBD80-5AFA-4CF7-97B8-A9AAB1651C88 + + colorindex + 12 + note + OneUpdater + xpos + 455 + ypos + 40 + + E4256C3E-6831-43F5-805C-F667A3D7E726 + + xpos + 415 + ypos + 220 + + F2C7428D-06C2-4B70-8C70-8348AE71B137 + + xpos + 235 + ypos + 40 + + FD60CC76-3DD5-45D7-A184-5A5580E0790F + + xpos + 35 + ypos + 320 + + + variables + + api_key + + backup_originals + /tmp/com.alfredapp.tinypng_backups + + variablesdontexport + + api_key + + version + 2021.1 + webaddress + https://github.com/alfredapp/tinypng-workflow + +