pleroma-cli.sh 26 KB

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