My build of nnn with minor changes
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 
 
 

558 řádky
19 KiB

  1. #!/usr/bin/env bash
  2. # https://github.com/jomo/imgur-screenshot
  3. # https://imgur.com/tools
  4. #
  5. # Slightly modified for `nnn` integration
  6. #
  7. # Shell: bash
  8. # Description: Upload an image file to imgur
  9. if [ "${1}" = "--debug" ]; then
  10. echo "########################################"
  11. echo "Enabling debug mode"
  12. echo "Please remove credentials before pasting"
  13. echo "########################################"
  14. echo ""
  15. uname -a
  16. for arg in ${0} "${@}"; do
  17. echo -n "'${arg}' "
  18. done
  19. echo -e "\n"
  20. shift
  21. set -x
  22. fi
  23. current_version="v1.7.4"
  24. function is_mac() {
  25. uname | grep -q "Darwin"
  26. }
  27. ### IMGUR-SCREENSHOT DEFAULT CONFIG ####
  28. # You can override the config in ~/.config/imgur-screenshot/settings.conf
  29. imgur_anon_id="ea6c0ef2987808e"
  30. imgur_icon_path="${HOME}/Pictures/imgur.png"
  31. imgur_acct_key=""
  32. imgur_secret=""
  33. login="false"
  34. album_title=""
  35. album_id=""
  36. credentials_file="${HOME}/.config/imgur-screenshot/credentials.conf"
  37. file_name_format="imgur-%Y_%m_%d-%H:%M:%S.png" # when using scrot, must end with .png!
  38. file_dir="${HOME}/Pictures"
  39. upload_connect_timeout="5"
  40. upload_timeout="120"
  41. upload_retries="1"
  42. if is_mac; then
  43. screenshot_select_command="screencapture -i %img"
  44. screenshot_window_command="screencapture -iWa %img"
  45. screenshot_full_command="screencapture %img"
  46. open_command="open %url"
  47. else
  48. screenshot_select_command="scrot -s %img"
  49. screenshot_window_command="scrot %img"
  50. screenshot_full_command="scrot %img"
  51. open_command="xdg-open %url"
  52. fi
  53. open="true"
  54. mode="select"
  55. edit_command="gimp %img"
  56. edit="false"
  57. exit_on_album_creation_fail="true"
  58. log_file="${HOME}/.imgur-screenshot.log"
  59. auto_delete=""
  60. copy_url="true"
  61. keep_file="true"
  62. check_update="true"
  63. # NOTICE: if you make changes here, also edit the docs at
  64. # https://github.com/jomo/imgur-screenshot/wiki/Config
  65. # You can override the config in ~/.config/imgur-screenshot/settings.conf
  66. ############## END CONFIG ##############
  67. settings_path="${HOME}/.config/imgur-screenshot/settings.conf"
  68. if [ -f "${settings_path}" ]; then
  69. source "${settings_path}"
  70. fi
  71. # dependency check
  72. if [ "${1}" = "--check" ]; then
  73. (which grep &>/dev/null && echo "OK: found grep") || echo "ERROR: grep not found"
  74. if is_mac; then
  75. if which growlnotify &>/dev/null; then
  76. echo "OK: found growlnotify"
  77. elif which terminal-notifier &>/dev/null; then
  78. echo "OK: found terminal-notifier"
  79. else
  80. echo "ERROR: growlnotify nor terminal-notifier found"
  81. fi
  82. (which screencapture &>/dev/null && echo "OK: found screencapture") || echo "ERROR: screencapture not found"
  83. (which pbcopy &>/dev/null && echo "OK: found pbcopy") || echo "ERROR: pbcopy not found"
  84. else
  85. (which notify-send &>/dev/null && echo "OK: found notify-send") || echo "ERROR: notify-send (from libnotify-bin) not found"
  86. (which scrot &>/dev/null && echo "OK: found scrot") || echo "ERROR: scrot not found"
  87. (which xclip &>/dev/null && echo "OK: found xclip") || echo "ERROR: xclip not found"
  88. fi
  89. (which curl &>/dev/null && echo "OK: found curl") || echo "ERROR: curl not found"
  90. exit 0
  91. fi
  92. # notify <'ok'|'error'> <title> <text>
  93. function notify() {
  94. if is_mac; then
  95. if which growlnotify &>/dev/null; then
  96. growlnotify --icon "${imgur_icon_path}" --iconpath "${imgur_icon_path}" --title "${2}" --message "${3}"
  97. else
  98. terminal-notifier -appIcon "${imgur_icon_path}" -contentImage "${imgur_icon_path}" -title "imgur: ${2}" -message "${3}"
  99. fi
  100. else
  101. if [ "${1}" = "error" ]; then
  102. notify-send -a ImgurScreenshot -u critical -c "im.error" -i "${imgur_icon_path}" -t 500 "imgur: ${2}" "${3}"
  103. else
  104. notify-send -a ImgurScreenshot -u low -c "transfer.complete" -i "${imgur_icon_path}" -t 500 "imgur: ${2}" "${3}"
  105. fi
  106. fi
  107. }
  108. function take_screenshot() {
  109. echo "Please select area"
  110. is_mac || sleep 0.1 # https://bbs.archlinux.org/viewtopic.php?pid=1246173#p1246173
  111. cmd="screenshot_${mode}_command"
  112. cmd=${!cmd//\%img/${1}}
  113. shot_err="$(${cmd} &>/dev/null)" #takes a screenshot with selection
  114. if [ "${?}" != "0" ]; then
  115. echo "Failed to take screenshot '${1}': '${shot_err}'. For more information visit https://github.com/jomo/imgur-screenshot/wiki/Troubleshooting" | tee -a "${log_file}"
  116. notify error "Something went wrong :(" "Information has been logged"
  117. exit 1
  118. fi
  119. }
  120. function check_for_update() {
  121. # exit non-zero on HTTP error, output only the body (no stats) but output errors, follow redirects, output everything to stdout
  122. remote_version="$(curl --compressed -fsSL --stderr - "https://api.github.com/repos/jomo/imgur-screenshot/releases" | egrep -m 1 --color 'tag_name":\s*".*"' | cut -d '"' -f 4)"
  123. if [ "${?}" -eq "0" ]; then
  124. if [ ! "${current_version}" = "${remote_version}" ] && [ ! -z "${current_version}" ] && [ ! -z "${remote_version}" ]; then
  125. echo "Update found!"
  126. echo "Version ${remote_version} is available (You have ${current_version})"
  127. notify ok "Update found" "Version ${remote_version} is available (You have ${current_version}). https://github.com/jomo/imgur-screenshot"
  128. echo "Check https://github.com/jomo/imgur-screenshot/releases/${remote_version} for more info."
  129. elif [ -z "${current_version}" ] || [ -z "${remote_version}" ]; then
  130. echo "Invalid empty version string"
  131. echo "Current (local) version: '${current_version}'"
  132. echo "Latest (remote) version: '${remote_version}'"
  133. else
  134. echo "Version ${current_version} is up to date."
  135. fi
  136. else
  137. echo "Failed to check for latest version: ${remote_version}"
  138. fi
  139. }
  140. function check_oauth2_client_secrets() {
  141. if [ -z "${imgur_acct_key}" ] || [ -z "${imgur_secret}" ]; then
  142. echo "In order to upload to your account, register a new application at:"
  143. echo "https://api.imgur.com/oauth2/addclient"
  144. echo "Select 'OAuth 2 authorization without a callback URL'"
  145. echo "Then, set the imgur_acct_key (Client ID) and imgur_secret in your config."
  146. exit 1
  147. fi
  148. }
  149. function load_access_token() {
  150. token_expire_time=0
  151. # check for saved access_token and its expiration date
  152. if [ -f "${credentials_file}" ]; then
  153. source "${credentials_file}"
  154. fi
  155. current_time="$(date +%s)"
  156. preemptive_refresh_time="$((10*60))"
  157. expired="$((current_time > (token_expire_time - preemptive_refresh_time)))"
  158. if [ ! -z "${refresh_token}" ]; then
  159. # token already set
  160. if [ "${expired}" -eq "0" ]; then
  161. # token expired
  162. refresh_access_token "${credentials_file}"
  163. fi
  164. else
  165. acquire_access_token "${credentials_file}"
  166. fi
  167. }
  168. function acquire_access_token() {
  169. check_oauth2_client_secrets
  170. # prompt for a PIN
  171. authorize_url="https://api.imgur.com/oauth2/authorize?client_id=${imgur_acct_key}&response_type=pin"
  172. echo "Go to"
  173. echo "${authorize_url}"
  174. echo "and grant access to this application."
  175. read -rp "Enter the PIN: " imgur_pin
  176. if [ -z "${imgur_pin}" ]; then
  177. echo "PIN not entered, exiting"
  178. exit 1
  179. fi
  180. # exchange the PIN for access token and refresh token
  181. response="$(curl --compressed -fsSL --stderr - \
  182. -F "client_id=${imgur_acct_key}" \
  183. -F "client_secret=${imgur_secret}" \
  184. -F "grant_type=pin" \
  185. -F "pin=${imgur_pin}" \
  186. https://api.imgur.com/oauth2/token)"
  187. save_access_token "${response}" "${1}"
  188. }
  189. function refresh_access_token() {
  190. check_oauth2_client_secrets
  191. token_url="https://api.imgur.com/oauth2/token"
  192. # exchange the refresh token for access_token and refresh_token
  193. response="$(curl --compressed -fsSL --stderr - -F "client_id=${imgur_acct_key}" -F "client_secret=${imgur_secret}" -F "grant_type=refresh_token" -F "refresh_token=${refresh_token}" "${token_url}")"
  194. if [ ! "${?}" -eq "0" ]; then
  195. # curl failed
  196. handle_upload_error "${response}" "${token_url}"
  197. exit 1
  198. fi
  199. save_access_token "${response}" "${1}"
  200. }
  201. function save_access_token() {
  202. if ! grep -q "access_token" <<<"${1}"; then
  203. # server did not send access_token
  204. echo "Error: Something is wrong with your credentials:"
  205. echo "${1}"
  206. exit 1
  207. fi
  208. access_token="$(egrep -o 'access_token":".*"' <<<"${1}" | cut -d '"' -f 3)"
  209. refresh_token="$(egrep -o 'refresh_token":".*"' <<<"${1}" | cut -d '"' -f 3)"
  210. expires_in="$(egrep -o 'expires_in":[0-9]*' <<<"${1}" | cut -d ':' -f 2)"
  211. token_expire_time="$(( $(date +%s) + expires_in ))"
  212. # create dir if not exist
  213. mkdir -p "$(dirname "${2}")" 2>/dev/null
  214. touch "${2}" && chmod 600 "${2}"
  215. cat <<EOF > "${2}"
  216. access_token="${access_token}"
  217. refresh_token="${refresh_token}"
  218. token_expire_time="${token_expire_time}"
  219. EOF
  220. }
  221. function fetch_account_info() {
  222. response="$(curl --compressed --connect-timeout "${upload_connect_timeout}" -m "${upload_timeout}" --retry "${upload_retries}" -fsSL --stderr - -H "Authorization: Bearer ${access_token}" https://api.imgur.com/3/account/me)"
  223. if egrep -q '"success":\s*true' <<<"${response}"; then
  224. username="$(egrep -o '"url":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
  225. echo "Logged in as ${username}."
  226. echo "https://${username}.imgur.com"
  227. else
  228. echo "Failed to fetch info: ${response}"
  229. fi
  230. }
  231. function delete_image() {
  232. response="$(curl --compressed -X DELETE -fsSL --stderr - -H "Authorization: Client-ID ${1}" "https://api.imgur.com/3/image/${2}")"
  233. if egrep -q '"success":\s*true' <<<"${response}"; then
  234. echo "Image successfully deleted (delete hash: ${2})." >> "${3}"
  235. else
  236. echo "The Image could not be deleted: ${response}." >> "${3}"
  237. fi
  238. }
  239. function upload_authenticated_image() {
  240. echo "Uploading '${1}'..."
  241. title="$(echo "${1}" | rev | cut -d "/" -f 1 | cut -d "." -f 2- | rev)"
  242. if [ -n "${album_id}" ]; then
  243. response="$(curl --compressed --connect-timeout "${upload_connect_timeout}" -m "${upload_timeout}" --retry "${upload_retries}" -fsSL --stderr - -F "title=${title}" -F "image=@\"${1}\"" -F "album=${album_id}" -H "Authorization: Bearer ${access_token}" https://api.imgur.com/3/image)"
  244. else
  245. response="$(curl --compressed --connect-timeout "${upload_connect_timeout}" -m "${upload_timeout}" --retry "${upload_retries}" -fsSL --stderr - -F "title=${title}" -F "image=@\"${1}\"" -H "Authorization: Bearer ${access_token}" https://api.imgur.com/3/image)"
  246. fi
  247. # JSON parser premium edition (not really)
  248. if egrep -q '"success":\s*true' <<<"${response}"; then
  249. img_id="$(egrep -o '"id":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
  250. img_ext="$(egrep -o '"link":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4 | rev | cut -d "." -f 1 | rev)" # "link" itself has ugly '\/' escaping and no https!
  251. del_id="$(egrep -o '"deletehash":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
  252. if [ ! -z "${auto_delete}" ]; then
  253. export -f delete_image
  254. echo "Deleting image in ${auto_delete} seconds."
  255. nohup /bin/bash -c "sleep ${auto_delete} && delete_image ${imgur_anon_id} ${del_id} ${log_file}" &
  256. fi
  257. handle_upload_success "https://i.imgur.com/${img_id}.${img_ext}" "https://imgur.com/delete/${del_id}" "${1}"
  258. else # upload failed
  259. err_msg="$(egrep -o '"error":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
  260. test -z "${err_msg}" && err_msg="${response}"
  261. handle_upload_error "${err_msg}" "${1}"
  262. fi
  263. }
  264. function upload_anonymous_image() {
  265. echo "Uploading '${1}'..."
  266. title="$(echo "${1}" | rev | cut -d "/" -f 1 | cut -d "." -f 2- | rev)"
  267. if [ -n "${album_id}" ]; then
  268. response="$(curl --compressed --connect-timeout "${upload_connect_timeout}" -m "${upload_timeout}" --retry "${upload_retries}" -fsSL --stderr - -H "Authorization: Client-ID ${imgur_anon_id}" -F "title=${title}" -F "image=@\"${1}\"" -F "album=${album_id}" https://api.imgur.com/3/image)"
  269. else
  270. response="$(curl --compressed --connect-timeout "${upload_connect_timeout}" -m "${upload_timeout}" --retry "${upload_retries}" -fsSL --stderr - -H "Authorization: Client-ID ${imgur_anon_id}" -F "title=${title}" -F "image=@\"${1}\"" https://api.imgur.com/3/image)"
  271. fi
  272. # JSON parser premium edition (not really)
  273. if egrep -q '"success":\s*true' <<<"${response}"; then
  274. img_id="$(egrep -o '"id":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
  275. img_ext="$(egrep -o '"link":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4 | rev | cut -d "." -f 1 | rev)" # "link" itself has ugly '\/' escaping and no https!
  276. del_id="$(egrep -o '"deletehash":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
  277. if [ ! -z "${auto_delete}" ]; then
  278. export -f delete_image
  279. echo "Deleting image in ${auto_delete} seconds."
  280. nohup /bin/bash -c "sleep ${auto_delete} && delete_image ${imgur_anon_id} ${del_id} ${log_file}" &
  281. fi
  282. handle_upload_success "https://i.imgur.com/${img_id}.${img_ext}" "https://imgur.com/delete/${del_id}" "${1}"
  283. else # upload failed
  284. err_msg="$(egrep -o '"error":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
  285. test -z "${err_msg}" && err_msg="${response}"
  286. handle_upload_error "${err_msg}" "${1}"
  287. fi
  288. }
  289. function handle_upload_success() {
  290. echo ""
  291. echo "image link: ${1}"
  292. echo "delete link: ${2}"
  293. if [ "${copy_url}" = "true" ] && [ -z "${album_title}" ]; then
  294. if is_mac; then
  295. echo -n "${1}" | pbcopy
  296. else
  297. echo -n "${1}" | xclip -selection clipboard
  298. fi
  299. echo "URL copied to clipboard"
  300. fi
  301. # print to log file: image link, image location, delete link
  302. echo -e "${1}\t${3}\t${2}" >> "${log_file}"
  303. notify ok "Upload done!" "${1}"
  304. # if [ ! -z "${open_command}" ] && [ "${open}" = "true" ]; then
  305. # open_cmd=${open_command//\%url/${1}}
  306. # open_cmd=${open_cmd//\%img/${2}}
  307. # echo "Opening '${open_cmd}'"
  308. # eval "${open_cmd}"
  309. # fi
  310. }
  311. function handle_upload_error() {
  312. error="Upload failed: \"${1}\""
  313. echo "${error}"
  314. echo -e "Error\t${2}\t${error}" >> "${log_file}"
  315. notify error "Upload failed :(" "${1}"
  316. }
  317. function handle_album_creation_success() {
  318. echo ""
  319. echo "Album link: ${1}"
  320. echo "Delete hash: ${2}"
  321. echo ""
  322. notify ok "Album created!" "${1}"
  323. if [ "${copy_url}" = "true" ]; then
  324. if is_mac; then
  325. echo -n "${1}" | pbcopy
  326. else
  327. echo -n "${1}" | xclip -selection clipboard
  328. fi
  329. echo "URL copied to clipboard"
  330. fi
  331. # print to log file: album link, album title, delete hash
  332. echo -e "${1}\t\"${3}\"\t${2}" >> "${log_file}"
  333. }
  334. function handle_album_creation_error() {
  335. error="Album creation failed: \"${1}\""
  336. echo -e "Error\t${2}\t${error}" >> "${log_file}"
  337. notify error "Album creation failed :(" "${1}"
  338. if [ ${exit_on_album_creation_fail} ]; then
  339. exit 1
  340. fi
  341. }
  342. while [ ${#} != 0 ]; do
  343. case "${1}" in
  344. -h | --help)
  345. echo "usage: ${0} [--debug] [-c | --check | -v | -h | -u]"
  346. echo " ${0} [--debug] [option]... [file]..."
  347. echo ""
  348. echo " --debug Enable debugging, must be first option"
  349. echo " -h, --help Show this help, exit"
  350. echo " -v, --version Show current version, exit"
  351. echo " --check Check if all dependencies are installed, exit"
  352. echo " -c, --connect Show connected imgur account, exit"
  353. echo " -o, --open <true|false> Override 'open' config"
  354. echo " -e, --edit <true|false> Override 'edit' config"
  355. echo " -i, --edit-command <command> Override 'edit_command' config (include '%img'), sets --edit 'true'"
  356. echo " -l, --login <true|false> Override 'login' config"
  357. echo " -a, --album <album_title> Create new album and upload there"
  358. echo " -A, --album-id <album_id> Override 'album_id' config"
  359. echo " -k, --keep-file <true|false> Override 'keep_file' config"
  360. echo " -d, --auto-delete <s> Automatically delete image after <s> seconds"
  361. echo " -u, --update Check for updates, exit"
  362. echo " file Upload file instead of taking a screenshot"
  363. exit 0;;
  364. -v | --version)
  365. echo "${current_version}"
  366. exit 0;;
  367. -s | --select)
  368. mode="select"
  369. shift;;
  370. -w | --window)
  371. mode="window"
  372. shift;;
  373. -f | --full)
  374. mode="full"
  375. shift;;
  376. -o | --open)
  377. open="${2}"
  378. shift 2;;
  379. -e | --edit)
  380. edit="${2}"
  381. shift 2;;
  382. -i | --edit-command)
  383. edit_command="${2}"
  384. edit="true"
  385. shift 2;;
  386. -l | --login)
  387. login="${2}"
  388. shift 2;;
  389. -c | --connect)
  390. load_access_token
  391. fetch_account_info
  392. exit 0;;
  393. -a | --album)
  394. album_title="${2}"
  395. shift 2;;
  396. -A | --album-id)
  397. album_id="${2}"
  398. shift 2;;
  399. -k | --keep-file)
  400. keep_file="${2}"
  401. shift 2;;
  402. -d | --auto-delete)
  403. auto_delete="${2}"
  404. shift 2;;
  405. -u | --update)
  406. check_for_update
  407. exit 0;;
  408. *)
  409. upload_files=("${@}")
  410. break;;
  411. esac
  412. done
  413. if [ "${login}" = "true" ]; then
  414. # load before changing directory
  415. load_access_token
  416. fi
  417. if [ -n "${album_title}" ]; then
  418. if [ "${login}" = "true" ]; then
  419. response="$(curl -fsSL --stderr - \
  420. -F "title=${album_title}" \
  421. -H "Authorization: Bearer ${access_token}" \
  422. https://api.imgur.com/3/album)"
  423. else
  424. response="$(curl -fsSL --stderr - \
  425. -F "title=${album_title}" \
  426. -H "Authorization: Client-ID ${imgur_anon_id}" \
  427. https://api.imgur.com/3/album)"
  428. fi
  429. if egrep -q '"success":\s*true' <<<"${response}"; then # Album creation successful
  430. echo "Album '${album_title}' successfully created"
  431. album_id="$(egrep -o '"id":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
  432. del_id="$(egrep -o '"deletehash":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
  433. handle_album_creation_success "http://imgur.com/a/${album_id}" "${del_id}" "${album_title}"
  434. if [ "${login}" = "false" ]; then
  435. album_id="${del_id}"
  436. fi
  437. else # Album creation failed
  438. err_msg="$(egrep -o '"error":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
  439. test -z "${err_msg}" && err_msg="${response}"
  440. handle_album_creation_error "${err_msg}" "${album_title}"
  441. fi
  442. fi
  443. if [ -z "${upload_files}" ]; then
  444. upload_files[0]=""
  445. fi
  446. for upload_file in "${upload_files[@]}"; do
  447. if [ -z "${upload_file}" ]; then
  448. cd "${file_dir}" || exit 1
  449. # new filename with date
  450. img_file="$(date +"${file_name_format}")"
  451. take_screenshot "${img_file}"
  452. else
  453. # upload file instead of screenshot
  454. img_file="${upload_file}"
  455. fi
  456. # get full path
  457. img_file="$(cd "$( dirname "${img_file}")" && echo "$(pwd)/$(basename "${img_file}")")"
  458. # check if file exists
  459. if [ ! -f "${img_file}" ]; then
  460. echo "file '${img_file}' doesn't exist !"
  461. exit 1
  462. fi
  463. # open image in editor if configured
  464. if [ "${edit}" = "true" ]; then
  465. edit_cmd=${edit_command//\%img/${img_file}}
  466. echo "Opening editor '${edit_cmd}'"
  467. if ! (eval "${edit_cmd}"); then
  468. echo "Error for image '${img_file}': command '${edit_cmd}' failed, not uploading. For more information visit https://github.com/jomo/imgur-screenshot/wiki/Troubleshooting" | tee -a "${log_file}"
  469. notify error "Something went wrong :(" "Information has been logged"
  470. exit 1
  471. fi
  472. fi
  473. if [ "${login}" = "true" ]; then
  474. upload_authenticated_image "${img_file}"
  475. else
  476. upload_anonymous_image "${img_file}"
  477. fi
  478. # delete file if configured
  479. if [ "${keep_file}" = "false" ] && [ -z "${1}" ]; then
  480. echo "Deleting temp file ${file_dir}/${img_file}"
  481. rm -rf "${img_file}"
  482. fi
  483. echo ""
  484. done
  485. if [ "${check_update}" = "true" ]; then
  486. check_for_update
  487. fi