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.
 
 
 
 
 
 

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