pleroma-cli.sh 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  1. #!/bin/sh
  2. instance=$(jj -i config.json instance)
  3. alias default_auth_browser=links
  4. proxy_init()
  5. {
  6. main_proxy=$(jj -i config.json main_proxy)
  7. if [ -n "$main_proxy" ]; then
  8. default_connect_protocol=$(jj -i config.json connect_protocol_via_main_proxy)
  9. ALL_PROXY="$main_proxy"
  10. elif [ $(echo "$instance" | grep -q 'i2p$' ; echo $?) -eq 0 ]; then
  11. default_connect_protocol='http'
  12. ALL_PROXY=$(jj -i config.json i2p_http_proxy_addr)
  13. elif [ $(echo "$instance" | grep -q 'onion$'; echo $?) -eq 0 ]; then
  14. default_connect_protocol='https'
  15. ALL_PROXY=$(jj -i config.json tor_proxy_addr)
  16. else
  17. default_connect_protocol='https'
  18. ALL_PROXY=''
  19. fi
  20. export default_connect_protocol
  21. export ALL_PROXY
  22. }
  23. proxy_init
  24. instance_point="$default_connect_protocol://$instance/api/v1"
  25. instance_point_pleroma="$default_connect_protocol://$instance/api/pleroma"
  26. instance_hist='instance.hist'
  27. enabled_nsfw=$(jj -i config.json enabled_nsfw)
  28. nsfw_only=$(jj -i config.json nsfw_only)
  29. hide_reblogs=$(jj -i config.json hide_reblogs)
  30. max_statuses=$(jj -i config.json max_statuses)
  31. default_visibility=$(jj -i config.json default_visibility)
  32. default_content_type=$(jj -i config.json default_content_type)
  33. format_time=$(jj -i config.json format_time)
  34. boost_symbol=$(jj -i config.json boost_symbol)
  35. statuses_separator=$(jj -i config.json statuses_separator)
  36. reversed_statuses=$(jj -i config.json reversed_statuses)
  37. quoting_reply=$(jj -i config.json quoting_reply)
  38. copy_mentions=$(jj -i config.json copy_mentions)
  39. per_status_mode=$(jj -i config.json per_status_mode)
  40. default_media_player=$(jj -i config.json default_media_player)
  41. #[AUTH SECTION]
  42. mkdir -m 711 -p .app_sessions
  43. touch .auth.json
  44. chmod 600 .auth.json
  45. make_login()
  46. {
  47. auth="$(jj -i .auth.json "$(echo "$instance" | sed 's/\./\\\./g')")"
  48. echo "Instance: $instance"
  49. if [ -n "$auth" ]; then
  50. default_curl_opt()
  51. {
  52. curl -s --compressed -H "Authorization: Bearer $auth" "$@"
  53. }
  54. post_request()
  55. {
  56. curl -s --compressed -X POST -H "Authorization: Bearer $auth" "$@"
  57. }
  58. put_request()
  59. {
  60. curl -s --compressed -X PUT -H "Authorization: Bearer $auth" "$@"
  61. }
  62. delete_request()
  63. {
  64. curl -s --compressed -X DELETE -H "Authorization: Bearer $auth" "$@"
  65. }
  66. echo '+Authorized account+'
  67. export default_curl_opt
  68. export post_request
  69. export put_request
  70. export delete_request
  71. else
  72. default_curl_opt()
  73. {
  74. curl -s --compressed "$1"
  75. }
  76. export default_curl_opt
  77. export post_request=
  78. echo 'Please make auth and restart'
  79. fi
  80. }
  81. make_login
  82. auth_api_create_client()
  83. {
  84. if [ ! -e ".app_sessions/$instance" ]; then
  85. curl -s --compressed --url "$instance_point/apps" \
  86. --data-urlencode 'client_name=pleroma-cli' \
  87. --data-urlencode 'redirect_uris=urn:ietf:wg:oauth:2.0:oob' \
  88. --data-urlencode 'scopes=read write follow' \
  89. --data-urlencode 'website=https://gitea.phreedom.club/localhost_frssoft/pleroma-cli' \
  90. --output ".app_sessions/$instance" \
  91. --create-file-mode 0600
  92. fi
  93. }
  94. auth_api_get_code()
  95. {
  96. auth_api_create_client
  97. client_id=$(jj -i ".app_sessions/$instance" client_id)
  98. default_auth_browser "https://$instance/oauth/authorize?client_id=$client_id&response_type=code&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=read+write+follow"
  99. echo 'Input token-code:'
  100. read pass
  101. }
  102. auth_api_get_token()
  103. {
  104. auth_api_get_code
  105. clear
  106. client_id=$(jj -i ".app_sessions/$instance" client_id)
  107. client_secret=$(jj -i ".app_sessions/$instance" client_secret)
  108. token=$(curl -s --compressed --url "https://$instance/oauth/token" \
  109. --data-urlencode 'grant_type=authorization_code' \
  110. --data-urlencode "client_id=$client_id" \
  111. --data-urlencode "client_secret=$client_secret" \
  112. --data-urlencode "redirect_uri=urn:ietf:wg:oauth:2.0:oob" \
  113. --data-urlencode 'scope=read write follow' \
  114. --data-urlencode "code=$pass" | jj access_token)
  115. jj -p -i .auth.json -v "$token" "$(echo "$instance" | sed 's/\./\\\./g')" -o .auth.json
  116. }
  117. #[AUTH SECTION END]
  118. #[MIGRATION SECTION]
  119. backup_restore_menu()
  120. {
  121. clear
  122. echo "Backup/Restore menu
  123. Backups will be placed to folder backups_$instance
  124. Hint:
  125. For restore create folder 'restore' and copy 'friends.csv, blocks.csv, mutes.csv' in to folder
  126. Note: check selected instance before backup/restore"
  127. sub_menu_lvl=1
  128. entry1='Backup followings'
  129. entry2='Backup blocks'
  130. entry3='Backup mutes'
  131. entry4='Backup all'
  132. entry5='Restore followings'
  133. entry6='Restore blocks'
  134. entry7='Restore mutes'
  135. entry8='Restore all'
  136. while [ $sub_menu_lvl -eq 1 ]; do
  137. choice=$(echo "Main menu\n$entry1\n$entry2\n$entry3\n$entry4\n$entry5\n$entry6\n$entry7\n$entry8" | fzy)
  138. case $choice in
  139. "Main menu") sub_menu_lvl=0 ;;
  140. "$entry1") follow_api_export ;;
  141. "$entry2") blocks_api_export ;;
  142. "$entry3") mutes_api_export ;;
  143. "$entry4")
  144. echo 'Initialized... Please wait...'
  145. follow_api_export
  146. sleep 3
  147. blocks_api_export
  148. sleep 3
  149. mutes_api_export
  150. ;;
  151. "$entry5") follow_api_import ;;
  152. "$entry6") blocks_api_import ;;
  153. "$entry7") mutes_api_import ;;
  154. "$entry8")
  155. echo 'Initialized... Please wait...'
  156. follow_api_import
  157. sleep 5
  158. blocks_api_import
  159. sleep 5
  160. mutes_api_import
  161. ;;
  162. esac
  163. done
  164. }
  165. backup_api_create()
  166. {
  167. post_request "$instance_point/pleroma/backups"
  168. }
  169. backup_api_list()
  170. {
  171. default_curl_opt "$instance_point/pleroma/backups"
  172. }
  173. legacy_addr_preprocess()
  174. {
  175. sed -E "/^[a-zA-Z0-9+_.-]+@[a-zA-Z0-9.-]+$/! s/$/@$instance/"
  176. }
  177. follow_api_export()
  178. {
  179. count=40
  180. mkdir -m 711 -p backups_"$instance"
  181. account_info=$(account_api_me)
  182. acc_id=$(echo "$account_info" | jj id)
  183. acc_following_count=$(echo "$account_info" | jj following_count)
  184. while [ $count -gt 0 ]; do
  185. followings=$(followings_api_get "$acc_id")
  186. count=$(echo "$followings" | jj \#)
  187. if [ "$count" -eq 0 ]; then
  188. echo "$acc_following_count followings exported"
  189. elif [ "$count" -lt 40 ]; then
  190. countindex=$(expr "$count" - 1)
  191. echo "$followings" | jj -l \#.acct | delq | legacy_addr_preprocess >> "backups_$instance"/friends.csv
  192. offset=$(echo "$followings" | jj "$countindex".id)
  193. echo "+$count follows"
  194. count=0
  195. echo "$acc_following_count followings exported"
  196. elif [ $count -gt 0 ]; then
  197. countindex=$(expr $count - 1)
  198. echo "$followings" | jj -l \#.acct | delq | legacy_addr_preprocess >> "backups_$instance"/friends.csv
  199. offset=$(echo "$followings" | jj "$countindex".id)
  200. echo "+$count follows"
  201. fi
  202. sleep 1
  203. done
  204. }
  205. blocks_api_export()
  206. {
  207. count=40
  208. mkdir -m 711 -p "backups_$instance"
  209. while [ $count -gt 0 ]; do
  210. blocks=$(blocks_api_get)
  211. count=$(echo "$blocks" | jj \#)
  212. if [ "$count" -eq 0 ]; then
  213. echo "Blocks exported"
  214. elif [ "$count" -lt 40 ]; then
  215. countindex=$(expr "$count" - 1)
  216. echo "$blocks" | jj -l \#.acct | delq | legacy_addr_preprocess >> "backups_$instance"/blocks.csv
  217. offset=$(echo "$blocks" | jj "$countindex".id)
  218. echo "+$count blocks"
  219. count=0
  220. echo "Blocks exported"
  221. elif [ $count -gt 0 ]; then
  222. echo "$blocks" | jj -l \#.acct | delq | legacy_addr_preprocess >> "backups_$instance"/blocks.csv
  223. offset=$(echo "$blocks" | jj "$countindex".id)
  224. echo "+$count blocks"
  225. fi
  226. sleep 1
  227. done
  228. }
  229. mutes_api_export()
  230. {
  231. count=40
  232. mkdir -m 711 -p "backups_$instance"
  233. while [ $count -gt 0 ]; do
  234. mutes=$(mutes_api_get)
  235. count=$(echo "$mutes" | jj \#)
  236. if [ "$count" -eq 0 ]; then
  237. echo "Mutes exported"
  238. elif [ "$count" -lt 40 ]; then
  239. countindex=$(expr "$count" - 1)
  240. echo "$mutes" | jj -l \#.acct | delq | legacy_addr_preprocess >> "backups_$instance"/mutes.csv
  241. offset=$(echo "$mutes" | jj "$countindex".id)
  242. echo "+$count mutes"
  243. count=0
  244. echo "Mutes exported"
  245. elif [ $count -gt 0 ]; then
  246. echo "$mutes" | jj -l \#.acct | delq| legacy_addr_preprocess >> "backups_$instance"/mutes.csv
  247. offset=$(echo "$mutes" | jj "$countindex".id)
  248. echo "+$count mutes"
  249. fi
  250. sleep 1
  251. done
  252. }
  253. follow_api_import()
  254. {
  255. post_request "$instance_point_pleroma/follow_import" \
  256. --form 'list=@restore/friends.csv'
  257. }
  258. blocks_api_import()
  259. {
  260. post_request "$instance_point_pleroma/blocks_import" \
  261. --form 'list=@restore/blocks.csv'
  262. }
  263. mutes_api_import()
  264. {
  265. post_request "$instance_point_pleroma/mutes_import" \
  266. --form 'list=@restore/mutes.csv'
  267. }
  268. #[MIGRATION SECTION END]
  269. account_api_me()
  270. {
  271. default_curl_opt "$instance_point/accounts/verify_credentials"
  272. }
  273. me_acct=$(account_api_me | jj acct)
  274. followings_api_get()
  275. {
  276. default_curl_opt "$instance_point/accounts/$1/following?limit=40&max_id=$offset"
  277. }
  278. followings_menu()
  279. {
  280. account_info=$(account_api_me)
  281. acc_id=$(echo "$account_info" | jj id)
  282. acc_following_count=$(echo "$account_info" | jj following_count)
  283. echo "Followers: $acc_following_count"
  284. sub_menu_lvl=1
  285. while [ $sub_menu_lvl -eq 1 ]; do
  286. followings=$(followings_api_get "$acc_id")
  287. accts=$(echo "$followings" | jj -l \#.acct | nl -s: -v0 -w1)
  288. choice=$(echo "Main menu\n$accts\nNext" | fzy)
  289. case $choice in
  290. "Main menu") sub_menu_lvl=0 ;;
  291. "Next") offset=$(echo "$followings" | jj $(expr $(echo "$followings" | jj \#) - 1).id) ;;
  292. *)
  293. index=$(echo "$choice" | cut -f 1 -d:)
  294. case "$1" in
  295. 'Remove following') unfollow_account "$(echo "$followings" | jj "$index".id)" ;;
  296. '') statuses_view_menu "$(echo "$followings" | jj "$index".acct)" ;;
  297. esac
  298. ;;
  299. esac
  300. done
  301. }
  302. following_requests()
  303. {
  304. default_curl_opt "$instance_point/follow_requests"
  305. }
  306. accept_follow_request()
  307. {
  308. post_request "$instance_point/follow_requests/$1/authorize"
  309. }
  310. reject_follow_request()
  311. {
  312. post_request "$instance_point/follow_requests/$1/reject"
  313. }
  314. follow_account()
  315. {
  316. acct_id=$(account_api_get "$1" | jj id)
  317. post_request "$instance_point/accounts/$acct_id/follow"
  318. }
  319. unfollow_account()
  320. {
  321. post_request "$instance_point/accounts/$1/unfollow"
  322. }
  323. menu_follow_requests()
  324. {
  325. follow_req=$(following_requests)
  326. count=$(echo "$follow_req" | jj \#)
  327. ids=$(echo "$follow_req" | jj -l \#.id | delq)
  328. clear
  329. echo "Follow requests: $count"
  330. for id in $ids; do
  331. whoacct=$(echo "$follow_req" | jj "#[id=$id].acct")
  332. datecreate=$(echo "$follow_req" | jj "#[id=$id].created_at")
  333. acct_display=$(echo "$follow_req" | jj "#[id=$id].display_name")
  334. acct_bot=$(echo "$follow_req" | jj "#[id=$id].bot")
  335. note=$(echo "$follow_req" | jj "#[id=$id].note" | html_to_txt_render)
  336. echo "$acct_display $whoacct"
  337. echo "Account creation date: $(date -d "$datecreate" "$format_time")"
  338. echo "Bot: $acct_bot"
  339. echo "Note:\n $note"
  340. nonexit=1
  341. while [ "$nonexit" -eq 1 ]; do
  342. choice=$(echo 'Accept\nReject\nShow statuses\nNothing' | fzy)
  343. case "$choice" in
  344. "Accept") accept_follow_request "$id" && nonexit=0 ;;
  345. "Reject") reject_follow_request "$id" && nonexit=0 ;;
  346. "Show statuses") statuses_view_menu "$whoacct" ;;
  347. "Nothing") nonexit=0 ;;
  348. esac
  349. done
  350. clear
  351. done
  352. }
  353. blocks_api_get()
  354. {
  355. default_curl_opt "$instance_point/blocks?limit=40&max_id=$offset"
  356. }
  357. mutes_api_get()
  358. {
  359. default_curl_opt "$instance_point/mutes?limit=40&max_id=$offset"
  360. }
  361. thread_api_statuses()
  362. {
  363. default_curl_opt "$instance_point/statuses/$1/context"
  364. }
  365. html_to_txt_render()
  366. {
  367. sed -e "s/<br[^>]*>/\n/g ; s/<p[^>]*>/\n/g ; s/<[^>]*>//g ; s/&gt;*/>/g ; s/&lt;*/</g ; s/&quot;/\"/g ; s/&#39;/'/g"
  368. }
  369. find_pgp_message()
  370. {
  371. awk '/-----BEGIN PGP MESSAGE-----/,/-----END PGP MESSAGE----/'
  372. }
  373. delq()
  374. {
  375. sed 's/"//g'
  376. }
  377. delqse()
  378. {
  379. sed 's/^"//g; s/"$//g'
  380. }
  381. account_api_get()
  382. {
  383. default_curl_opt "$instance_point/accounts/$1"
  384. }
  385. statuses_api_account()
  386. {
  387. default_curl_opt "$instance_point/accounts/$1/statuses?limit=$max_statuses&max_id=$2&min_id=$3"
  388. }
  389. status_api_one()
  390. {
  391. default_curl_opt "$instance_point/statuses/$1"
  392. }
  393. statuses_render()
  394. {
  395. if [ "$reversed_statuses" = 'true' ]; then
  396. ids_massive=$(echo "$ids_massive" | tr ' ' '\n' | tac | tr '\n' ' ')
  397. fi
  398. for i in $ids_massive; do
  399. status=$(echo "$jsonmassive" | jj "#[id=$i]")
  400. reblog=$(echo "$status" | jj reblog.id)
  401. if [ "$hide_reblogs" = 'true' ] && [ -n "$reblog" ]; then
  402. continue
  403. fi
  404. sensitive=$(echo "$status" | jj sensitive)
  405. sensitive_reblog=$(echo "$status" | jj reblog.sensitive)
  406. if [ -n "$reblog" ]; then
  407. if [ "$enabled_nsfw" = 'false' ] && [ "$sensitive_reblog" = 'true' ]; then
  408. continue
  409. fi
  410. if [ "$nsfw_only" = 'true' ] && [ "$sensitive_reblog" = 'false' ]; then
  411. continue
  412. fi
  413. else
  414. if [ "$enabled_nsfw" = 'false' ] && [ "$sensitive" = 'true' ]; then
  415. continue
  416. fi
  417. if [ "$nsfw_only" = 'true' ] && [ "$sensitive" = 'false' ]; then
  418. continue
  419. fi
  420. fi
  421. whoacct=$(echo "$status" | jj account.acct)
  422. reblogacct=$(echo "$status" | jj reblog.account.acct)
  423. uri=$(echo "$status" | jj uri)
  424. id_status=$(echo "$status" | jj id)
  425. dateutc=$(echo "$status" | jj created_at)
  426. reply_to_id=$(echo "$status" | jj in_reply_to_id)
  427. visibility_status=$(echo "$status" | jj visibility)
  428. s_f_menu='\nShare\nShare and favorite'
  429. edit_del_menu=
  430. if [ "$whoacct" = "$me_acct" ]; then
  431. edit_del_menu='\nEdit\nDelete'
  432. fi
  433. if [ "$visibility_status" = "private" ] || [ "$visibility_status" = "direct" ]; then
  434. s_f_menu=
  435. fi
  436. echo "| $(date -d "$dateutc" "$format_time") $visibility_status $whoacct"
  437. echo "| <$id_status> $uri"
  438. if [ -n "$reply_to_id" ]; then
  439. echo "| Reply to: $reply_to_id"
  440. fi
  441. if [ -n "$reblog" ]; then
  442. echo "| $boost_symbol $reblog $reblogacct"
  443. id_status="$reblog"
  444. fi
  445. spoiler_text=$(echo "$status" | jj spoiler_text)
  446. if [ -n "$spoiler_text" ]; then
  447. echo "#[$spoiler_text]"
  448. fi
  449. if [ "$sensitive" = 'true' -o "$sensitive_reblog" = 'true' ]; then
  450. echo '[NSFW]'
  451. fi
  452. status_content=$(echo "$status" | jj -r content | delqse | html_to_txt_render)
  453. pgp_crypted=$(echo "$status_content" | find_pgp_message)
  454. if [ -n "$pgp_crypted" ]; then
  455. menu_pgp='\nDecrypt GPG'
  456. fi
  457. echo "$status_content"
  458. attachments=$(echo "$status" | jj -l 'media_attachments.#.remote_url' | delq)
  459. menuattachments=
  460. if [ -n "$attachments" ]; then
  461. echo "#EXTINF:-1, $uri" >> attachments.m3u8
  462. echo '[Attachments:]'
  463. menuattachments='\nMedia'
  464. echo "$attachments" | tee -a attachments.m3u8
  465. fi
  466. poll=$(echo "$status" | jj poll.id)
  467. if [ -n "$poll" ]; then
  468. echo '[Poll:]'
  469. echo "$(echo "$status" | jj -l 'poll.options.#.title')"
  470. fi
  471. echo "$statuses_separator"
  472. if [ "$per_status_mode" = 'true' ]; then
  473. next=0
  474. force_stop=0
  475. while [ "$next" -eq 0 ]; do
  476. per_status_menu=$(echo "Next$menuattachments"$menu_pgp"\nFavorite$s_f_menu\nBookmark\nReply$edit_del_menu\nBack" | fzy)
  477. case "$per_status_menu" in
  478. "Next")
  479. next=1
  480. clear
  481. ;;
  482. "Decrypt GPG") echo "$pgp_crypted" | gpg -d ;;
  483. "Media")
  484. for one_media in $attachments; do
  485. $default_media_player "$one_media"
  486. done
  487. ;;
  488. "Share and favorite") share_and_favorite_mode "$id_status" ;;
  489. "Share") share_api_status "$id_status" ;;
  490. "Favorite") favorite_api_status "$id_status" ;;
  491. "Bookmark") bookmark_api_status "$id_status" ;;
  492. "Reply") reply_mode "$id_status" ;;
  493. "Edit") reply_mode "$id_status" '1' ;;
  494. "Delete") delete_api_status "$id_status" ;;
  495. "Back")
  496. next=1
  497. force_stop=1
  498. ;;
  499. esac
  500. done
  501. if [ "$force_stop" -eq 1 ]; then break; fi
  502. fi
  503. done
  504. }
  505. statuses_view_menu()
  506. {
  507. sub_menu_lvl=2
  508. json=$(statuses_api_account "$1")
  509. while [ $sub_menu_lvl -eq 2 ]; do
  510. clear
  511. echo "[Statuses $1]"
  512. ids_massive=$(echo "$json" | jj -l \#.id | delq)
  513. jsonmassive=$json
  514. statuses_render
  515. menustatuses=$(echo 'Prev\nNext\nReverse\nReply\nShare\nFavorite\nShare and favorite\nThread\nBack' | fzy)
  516. case "$menustatuses" in
  517. "Back") sub_menu_lvl=1 ;;
  518. "Prev")
  519. indexator=$(expr $(echo "$json" | jj \#) - 1)
  520. echo '#EXTM3U' > attachments.m3u8
  521. clear
  522. offset=$(echo "$json" | jj "$indexator".id)
  523. json=$(statuses_api_account "$1" "$offset")
  524. ;;
  525. "Next")
  526. echo '#EXTM3U' > attachments.m3u8
  527. clear
  528. offset=$(echo "$json" | jj 0.id)
  529. json=$(statuses_api_account "$1" '' "$offset")
  530. ;;
  531. "Reverse")
  532. offset=1
  533. json=$(statuses_api_account "$1" '' "$offset")
  534. ;;
  535. "Reply") reply_mode ;;
  536. "Share") share_mode ;;
  537. "Favorite") favourite_mode ;;
  538. "Share and favorite") share_and_favorite_mode ;;
  539. "Thread") thread_open ;;
  540. esac
  541. done
  542. }
  543. thread_open()
  544. {
  545. echo 'Input id'
  546. read status_id
  547. thread_menu "$status_id"
  548. }
  549. thread_menu()
  550. {
  551. sub_menu_lvl=2
  552. jsonthread=$(thread_api_statuses "$1")
  553. ancestors=$(echo "$jsonthread" | jj ancestors)
  554. descendants=$(echo "$jsonthread" | jj descendants)
  555. if [ '[]' != "$ancestors" ] && [ '[]' != "$descendants" ]; then
  556. jsonthread=$(echo "$ancestors""$descendants")
  557. elif [ '[]' != "$ancestors" ]; then
  558. jsonthread="$ancestors"
  559. else
  560. jsonthread="$descendants"
  561. fi
  562. while [ $sub_menu_lvl -eq 2 ]; do
  563. clear
  564. echo '[Thread]'
  565. ids_massive=$(echo "$jsonthread" | jj -l \#.id | delq)
  566. jsonmassive=$jsonthread
  567. statuses_render
  568. menuthread=$(echo 'Back\nReply\nShare\nFavorite\nShare and favorite' | fzy)
  569. case "$menuthread" in
  570. "Back") sub_menu_lvl=1 ;;
  571. "Reply") reply_mode ;;
  572. "Share") share_mode ;;
  573. "Favorite") favourite_mode ;;
  574. "Share and favorite") share_and_favorite_mode ;;
  575. esac
  576. done
  577. }
  578. timeline_api()
  579. {
  580. timelines_params="limit=$max_statuses&max_id=$1&min_id=$2"
  581. case "$timeline" in
  582. "home") default_curl_opt "$instance_point/timelines/home?$timelines_params" ;;
  583. "home/local") default_curl_opt "$instance_point/timelines/home?local=true&$timelines_params" ;;
  584. "favourites") default_curl_opt "$instance_point/favourites?$timelines_params" ;;
  585. "bookmarks") default_curl_opt "$instance_point/bookmarks?$timelines_params" ;;
  586. "direct") default_curl_opt "$instance_point/timelines/direct?$timelines_params" ;;
  587. "public") default_curl_opt "$instance_point/timelines/public?$timelines_params" ;;
  588. "local") default_curl_opt "$instance_point/timelines/public?local=true&$timelines_params" ;;
  589. "search") echo "$results" ;;
  590. esac
  591. }
  592. search_api_statuses()
  593. {
  594. echo "Input query:"
  595. read query
  596. results=$(default_curl_opt --get \
  597. --data-urlencode "q=$query" \
  598. --data-urlencode 'type=statuses' \
  599. --data-urlencode "limit=$max_statuses" \
  600. "$instance_point/search" | jj 'statuses')
  601. timeline='search' timeline_menu
  602. }
  603. timeline_menu()
  604. {
  605. json=$(timeline_api)
  606. sub_menu_lvl=1
  607. echo '#EXTM3U' > attachments.m3u8
  608. if [ "$per_status_mode" = 'true' ]; then
  609. menuentryes='Prev\nNext\nMain menu'
  610. else
  611. menuentryes='Prev\nNext\nReply\nShare\nFavorite\nShare and favorite\nThread\nMain menu'
  612. fi
  613. while [ $sub_menu_lvl -eq 1 ]; do
  614. ids_massive=$(echo "$json" | jj -l \#.id | delq)
  615. jsonmassive=$json
  616. statuses_render
  617. menu=$(echo "$menuentryes" | fzy)
  618. case $menu in
  619. "Prev")
  620. indexator=$(expr $(echo "$json" | jj \#) - 1)
  621. echo '#EXTM3U' > attachments.m3u8
  622. clear
  623. offset=$(echo "$json" | jj "$indexator".id)
  624. json=$(timeline_api "$offset")
  625. ;;
  626. "Next")
  627. echo '#EXTM3U' > attachments.m3u8
  628. clear
  629. offset=$(echo "$json" | jj 0.id)
  630. json=$(timeline_api '' "$offset")
  631. ;;
  632. "Reply") reply_mode ;;
  633. "Share") share_mode ;;
  634. "Favorite") favourite_mode ;;
  635. "Share and favorite") share_and_favorite_mode ;;
  636. "Thread") thread_open ;;
  637. "Main menu") sub_menu_lvl=0 ;;
  638. esac
  639. done
  640. }
  641. reply_mode()
  642. {
  643. if [ -n "$1" ]; then
  644. reply_status=$(status_api_one "$1")
  645. else
  646. echo 'Input id'
  647. read status_id
  648. reply_status=$(status_api_one "$status_id")
  649. fi
  650. if [ "$quoting_reply" = 'true' ]; then
  651. echo "$reply_status" | jj -r content | html_to_txt_render | delqse | sed 's/^/> /' > tmp_status.md
  652. fi
  653. if [ "$2" = '1' ]; then
  654. echo "$reply_status" | jj -r content | html_to_txt_render | delqse > tmp_status.md
  655. fi
  656. if [ "$copy_mentions" = 'true' ]; then
  657. mentions_reply=$(echo "$reply_status" | jj -l 'mentions.#.acct' | delq)
  658. mentions_reply="$mentions_reply\n"
  659. acct_selfstatus=$(echo "$reply_status" | jj account.acct)
  660. mentions_reply=$(echo "$mentions_reply""$acct_selfstatus" | sort -u | tr '\n' ',' | sed -e 's/,$//g; s/^,//g')
  661. fi
  662. write_status_menu "$(echo "$reply_status" | jj id)"
  663. }
  664. share_and_favorite_mode()
  665. {
  666. if [ -n "$1" ]; then
  667. share_api_status "$1"
  668. echo "$http_code"
  669. favorite_api_status "$1"
  670. echo "$http_code"
  671. else
  672. echo 'Input id (s - stop)'
  673. shareandfavmode=1
  674. while [ $shareandfavmode -eq 1 ]; do
  675. read status_id
  676. if [ "$status_id" = 's' ]; then
  677. shareandfavmode=0
  678. else
  679. share_api_status "$status_id"
  680. echo "$http_code"
  681. favorite_api_status "$status_id"
  682. echo "$http_code"
  683. fi
  684. done
  685. fi
  686. }
  687. share_api_status()
  688. {
  689. post_request -w "%{http_code}" --url "$instance_point/statuses/$1/reblog" --output /dev/null
  690. }
  691. share_mode()
  692. {
  693. echo 'Input id (s - stop)'
  694. sharemode=1
  695. while [ $sharemode -eq 1 ]; do
  696. read status_id
  697. if [ "$status_id" = 's' ]; then
  698. sharemode=0
  699. else
  700. share_api_status "$status_id"
  701. echo "$http_code"
  702. fi
  703. done
  704. }
  705. favorite_api_status()
  706. {
  707. post_request -w "%{http_code}" --url "$instance_point/statuses/$1/favourite" --output /dev/null
  708. }
  709. favourite_mode()
  710. {
  711. echo 'Input id (s - stop)'
  712. favoritemode=1
  713. while [ $favoritemode -eq 1 ]; do
  714. read status_id
  715. if [ "$status_id" = 's' ]; then
  716. favoritemode=0
  717. else
  718. favorite_api_status "$status_id"
  719. echo "$http_code"
  720. fi
  721. done
  722. }
  723. bookmark_api_status()
  724. {
  725. mkdir -p -m 711 bookmarks/"$instance"
  726. post_request "$instance_point/statuses/$1/bookmark" | jj -p -o "bookmarks/$instance/$1"
  727. chmod 600 "bookmarks/$instance/$1"
  728. }
  729. delete_api_status()
  730. {
  731. remove_status=$(delete_request "$instance_point/statuses/$1" | jj id)
  732. if [ -n "$remove_status" ]; then
  733. echo "SUCCESS"
  734. sleep 1
  735. else
  736. echo "Failed"
  737. fi
  738. }
  739. write_api_status()
  740. {
  741. if [ -n "$mediaattach" ]; then
  742. media=$(upload_api_media | jj id)
  743. post_request --url "$instance_point"/statuses \
  744. --data-urlencode "status@$1" \
  745. --data-raw "content_type=$content_type" \
  746. --data-raw "visibility=$status_visibility" \
  747. --data-raw "in_reply_to_id=$replyto" \
  748. --data-raw "media_ids[]=$media" \
  749. --data-raw "to[]=$mentions_reply"
  750. else
  751. post_request --url "$instance_point"/statuses \
  752. --data-urlencode "status@$1" \
  753. --data-raw "content_type=$content_type" \
  754. --data-raw "visibility=$status_visibility" \
  755. --data-raw "in_reply_to_id=$replyto" \
  756. --data-raw "to[]=$mentions_reply"
  757. fi
  758. }
  759. edit_api_status()
  760. {
  761. put_request --url "$instance_point"/statuses/$1 \
  762. --data-urlencode "status@$2"
  763. }
  764. upload_api_media()
  765. {
  766. post_request --url "$instance_point"/media \
  767. --form "file=$mediaattach"
  768. }
  769. write_status_menu()
  770. {
  771. touch tmp_status.md
  772. content_type="$default_content_type"
  773. status_visibility="$default_visibility"
  774. replyto=$1
  775. mediaattach=
  776. status_data_send=
  777. if [ -n "$sub_menu_lvl" ]; then
  778. sub_menu_lvl=2
  779. level=2
  780. else
  781. sub_menu_lvl=1
  782. level=1
  783. fi
  784. while [ $sub_menu_lvl -eq $level ]; do
  785. clear
  786. echo 'Status:'
  787. cat tmp_status.md
  788. echo '\==========/'
  789. echo "Chars: $(cat tmp_status.md | wc -m)"
  790. echo "Visiblity: $status_visibility"
  791. echo "Content type: $content_type"
  792. if [ -n "$mentions_reply" ]; then
  793. echo "Mentions: $mentions_reply"
  794. fi
  795. if [ -n "$replyto" ]; then
  796. echo "Reply to: $replyto"
  797. fi
  798. if [ -n "$mediaattach" ]; then
  799. echo "Attachments: $mediaattach"
  800. fi
  801. if [ -n "$(echo "$status_data_send" | jj id)" ]; then
  802. echo 'Send state: OK'
  803. elif [ -n "$(echo "$status_data_send" | jj error)" ]; then
  804. echo "Send state: ERR: $(echo "$status_data_send" | jj error)"
  805. fi
  806. wrirepostmenu=$(echo "Edit\nSend\nSend-edited\nAdd attach\nAdd recipient\nChange type\nVisiblity\nReset\nBack\nMain menu" | fzy)
  807. case $wrirepostmenu in
  808. "Edit") $EDITOR tmp_status.md ;;
  809. "Send") status_data_send=$(write_api_status tmp_status.md) ;;
  810. "Send-edited") status_data_send=$(edit_api_status $replyto tmp_status.md) ;;
  811. "Add attach")
  812. echo 'Input path to attach (ex. @image.png or @/full/path/to/attach.png)'
  813. read mediaattach
  814. ;;
  815. "Add recipient")
  816. echo 'Input addr (ex. nick,nick_etc@domain.domain)'
  817. read mentions_reply
  818. ;;
  819. "Change type") content_type=$(echo 'text/plain\ntext/markdown\ntext/html' | fzy) ;;
  820. "Visiblity")
  821. status_visibility=$(echo 'public\nunlisted\nlocal\nprivate\ndirect\nlist' | fzy)
  822. ;;
  823. "Reset")
  824. echo > tmp_status.md
  825. mentions_reply=
  826. ;;
  827. "Back") sub_menu_lvl=$(expr $level - 1) ;;
  828. "Main menu") sub_menu_lvl=0 ;;
  829. esac
  830. done
  831. }
  832. notif_menu()
  833. {
  834. sub_menu_lvl=1
  835. clrnotif='Clear all notifications'
  836. json=$(notif_api_get_all)
  837. while [ $sub_menu_lvl -eq 1 ]; do
  838. clear
  839. count_new_notif=$(echo "$json" | jj -l '#[pleroma.is_seen=false]#.pleroma.is_seen' | wc -w)
  840. echo "New notifications: $count_new_notif"
  841. for i in $(echo "$json" | jj -l \#.id); do
  842. date_utc=$(echo "$json" | jj \#[id="$i"].created_at)
  843. date -d "$date_utc" "$format_time"
  844. acct=$(echo "$json" | jj \#[id="$i"].account.acct)
  845. status_id=$(echo "$json" | jj \#[id="$i"].status.id)
  846. typenotif=$(echo "$json" | jj \#[id="$i"].type)
  847. echo "<$status_id> $typenotif <- $acct"
  848. echo "$json" | jj -r \#[id="$i"].status.content | delqse | html_to_txt_render
  849. echo '___'
  850. done
  851. menu_choice=$(echo "Main menu\nRead\nRefresh\n$clrnotif" | fzy)
  852. case "$menu_choice" in
  853. "Main menu") sub_menu_lvl=0 ;;
  854. "Read")
  855. notif_api_read "$(echo "$json" | jj 0.id)"
  856. json=$(notif_api_get_all)
  857. ;;
  858. "Refresh") json=$(notif_api_get_all) ;;
  859. "$clrnotif") notif_api_remove_all && json=$(notif_api_get_all) ;;
  860. esac
  861. done
  862. }
  863. notif_api_get_all()
  864. {
  865. default_curl_opt "$instance_point/notifications?limit=$max_statuses" | jj -p
  866. }
  867. notif_api_read()
  868. {
  869. post_request --url "$instance_point/pleroma/notifications/read" \
  870. --data-urlencode "max_id=$1" \
  871. --output /dev/null
  872. }
  873. notif_api_remove_all()
  874. {
  875. post_request --url "$instance_point"/notifications/clear
  876. }
  877. custom_manual_api_request()
  878. {
  879. while true; do
  880. echo 'Select request method:'
  881. method=$(echo 'get\npost\nput' | fzy)
  882. echo 'Input api request: api/v1/...'
  883. case $method in
  884. 'get')
  885. read raw_api
  886. default_curl_opt "https://$instance/$raw_api" | jj -p
  887. ;;
  888. 'post')
  889. read raw_api
  890. echo 'input curl data flags: --data-urlencode "example=example"'
  891. read flags
  892. post_request $flags --url "https://$instance/$raw_api" | jj -p
  893. ;;
  894. 'put')
  895. read raw_api
  896. echo 'input curl data flags: --data-urlencode "example=example"'
  897. read flags
  898. put_request $flags --url "https://$instance/$raw_api" | jj -p
  899. ;;
  900. esac
  901. echo "Done, exit? (y/N)"
  902. read yn
  903. if [ "$yn" = 'y' ]; then
  904. break
  905. fi
  906. done
  907. }
  908. menu_write_status='Write status'
  909. menu_timeline='Timelines'
  910. notif='Notifications'
  911. my_account='Account'
  912. followingsmenu='Followings'
  913. followrequests='Follow requests'
  914. backup_restore='Backup/Restore'
  915. manage_followings='Manage followings'
  916. search_menu='Search'
  917. custom_request='Make custom api request'
  918. authmake='Auth'
  919. switchinstance='Switch instance'
  920. Exit='Exit'
  921. while true; do
  922. if [ -n "$auth" ]; then
  923. main_menu=$(echo "$menu_write_status\n$menu_timeline\n$notif\n$my_account\n$search_menu\n$custom_request\n$switchinstance\n$Exit" | fzy)
  924. else
  925. main_menu=$(echo "$authmake\n$menu_timeline\n$switchinstance\n$Exit" | fzy)
  926. fi
  927. case $main_menu in
  928. "$menu_write_status") write_status_menu ;;
  929. "$menu_timeline")
  930. timeline=$(echo 'home\nhome/local\nfavourites\nbookmarks\ndirect\nlocal\npublic' | fzy)
  931. timeline_menu
  932. ;;
  933. "$notif") notif_menu ;;
  934. "$my_account")
  935. my_account_menu=$(echo "$followingsmenu\n$followrequests\n$manage_followings\n$backup_restore" | fzy)
  936. case $my_account_menu in
  937. "$followingsmenu") followings_menu ;;
  938. "$followrequests") menu_follow_requests ;;
  939. "$manage_followings")
  940. action_manage=$(echo 'Add following\nRemove following' | fzy)
  941. if [ "$action_manage" = 'Add following' ]; then
  942. echo 'Input nick or full address (ex. example_nick or example@domain'
  943. read add_account
  944. follow_account "$add_account"
  945. else
  946. followings_menu "$action_manage"
  947. fi
  948. ;;
  949. "$backup_restore") backup_restore_menu ;;
  950. esac
  951. ;;
  952. "$search_menu") search_api_statuses ;;
  953. "$custom_request") custom_manual_api_request ;;
  954. "$switchinstance")
  955. empty=0
  956. case $(echo 'Recently used\nChoice from list\nManual input' | fzy) in
  957. "Recently used")
  958. if [ -s $instance_hist ]; then
  959. touch $instance_hist && instance=$(cat $instance_hist | fzy)
  960. else
  961. echo 'No recently used instances...'
  962. empty=1
  963. fi
  964. ;;
  965. "Choice from list") instance=$(jj -l -i config.json public_list_instances | sed 's/"//g' | fzy) ;;
  966. "Manual input") echo "Type instance (ex. $instance):" && read instance ;;
  967. esac
  968. if [ $empty -eq 0 ]; then
  969. echo "$instance" >> $instance_hist
  970. cat $instance_hist | sort | uniq | tee $instance_hist 1>>/dev/null
  971. proxy_init
  972. instance_point="$default_connect_protocol://$instance/api/v1"
  973. instance_point_pleroma="$default_connect_protocol://$instance/api/pleroma"
  974. conf_instance_state=$(echo 'Permanent\nTemporaly' | fzy)
  975. if [ "$conf_instance_state" = 'Permanent' ]; then
  976. jj -i config.json instance -v "$instance" -o config.json
  977. else
  978. echo ''
  979. fi
  980. clear
  981. make_login
  982. fi
  983. ;;
  984. "$authmake") auth_api_get_token ;;
  985. "$Exit") exit 0 ;;
  986. esac
  987. done