My build of nnn with minor changes
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 
 

558 lignes
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