Compare commits

...

28 Commits

Author SHA1 Message Date
8cd519fe75 Don't include git history in package whoops 2024-07-02 15:20:57 +10:00
b1cb700ef7 Lemmy finally fixed auth tokens to not be in the fucking query params 2024-07-02 14:51:50 +10:00
ba29b1491d pretty.sh uses consistent naming now. Also finally did following command to show communities you are subscribed to. 2023-11-26 18:27:03 +11:00
b3185b2d25 Having a default account setter is handy, instead of having to mod the creds file constantly. 2023-11-26 17:45:42 +11:00
261f125761 Probably should version bump it 2023-10-13 20:59:34 +11:00
e9ed7b3e11 jq now gets upset if passed an empty argument (which is, in fact, distinct to not being passed an argument\!) 2023-10-13 20:57:42 +11:00
07950c0be7 can create communities at least now, and delete them, but that's not tested. Pagination next, then I'll do options stuff so you can actually add descriptions and images. 2023-09-20 04:26:15 +10:00
840ec2723b oh yeah I figured out what that was a while ago. I guess I should have just looked at the name lol 2023-07-29 19:12:35 +10:00
c0ab52f1c3 Fixed a bunch of annoying backslashes. 2023-07-02 19:28:33 +10:00
eb656567cf haha should take out that reference line 2023-06-19 02:08:03 +10:00
92fb247756 maybe can process applications now, I haven't tested it yet 2023-06-19 02:06:49 +10:00
b31c474ff0 Can use http without ssl now. I use it internally for my instance. Maybe I'll also allow ignoring specific SSL errors, maybe some passthrough to curl. 2023-06-19 00:47:48 +10:00
bcd456e55b haha yeah actually vars is a good idea 2023-06-19 00:07:45 +10:00
ebd79fc601 Comment parent IDs are back (server now supplies a full path instead), and newest comments are shown (in order) instead of whatever default is. That should become configurable, and better in other ways, later. 2023-06-02 11:16:28 +10:00
555ef1db3a ah, heh, right, yes, links 2023-06-02 11:02:49 +10:00
0629575417 I guess those don't need to be installed 2023-06-02 10:59:29 +10:00
f7c329af97 PKGBUILD should work now. 2023-06-02 10:58:31 +10:00
64672de712 Now fetches comments the new way, but doesn't fetch *all* comments... 2023-06-02 10:38:41 +10:00
aec63608a5 whoops 2023-04-25 03:25:22 +10:00
3831900f53 Right yeah I can just look at some other PKGBUILD 2023-04-25 03:14:22 +10:00
890087df08 now works from other dirs, and PKGBUILD might work 2023-04-25 03:08:54 +10:00
b7159cecef creating credentials file should no longer get an intermediate error whoops 2023-01-17 03:36:47 +11:00
8488962826 Readme a bit more useful 2023-01-17 03:35:15 +11:00
39671dab91 version bump 2023-01-17 03:31:35 +11:00
21a9042fcf I think registration works now 2023-01-17 03:30:28 +11:00
c6a7ceb005 MORE refactor 2023-01-17 01:46:39 +11:00
7a94bcd2bf oops 2023-01-17 01:07:40 +11:00
e1abd7f2f2 refactor done, AND fixed connecting to the first instance regardless of which was requested - still needs further improvement though. Onward to registration! 2023-01-17 01:07:15 +11:00
14 changed files with 207 additions and 87 deletions

View File

@@ -1,18 +1,23 @@
# Maintainer: Zergling_man, from fedora.email
#Well, it seems to work now.
pkgname=clemmy
pkgver=0.1.0
pkgrel=1
pkgver=0.2.0
pkgrel=2
pkgdesc='A pure bash client for lemmy, with multiaccount support.'
arch=('any')
url='https://gitea.rakka.tk/Zergling_man/clemmy'
url='http://precious.harpy.faith/Zergling_man/clemmy'
license=('GPL' 'custom:plusnigger.autism.exposed')
depends=('curl' 'jq')
source=('https://gitea.rakka.tk/Zergling_man/clemmy/raw/branch/master/shitty_api.sh')
sha256sums=('f3a3c9453158ca713b5a5fb21e0510a681a143ae74fc105364901248ad2f86b9')
makedepends=('git')
source=('git+http://precious.harpy.faith/Zergling_man/clemmy.git')
sha256sums=('SKIP') #Don't know how to use this on a repo.
package() {
install -d ${pkgdir}/usr/bin
cp ${srcdir}/shitty_api.sh ${pkgdir}/usr/bin/shitty_api
chmod +x ${pkgdir}/usr/bin/shitty_api
}
cd ${pkgname}
install -d ${pkgdir}/usr/bin ${pkgdir}/opt/clemmy
rm -rf README.txt .git
cp -r . ${pkgdir}/opt/clemmy
ln -s /opt/clemmy/clemmy.sh ${pkgdir}/usr/bin/clemmy
chmod +x ${pkgdir}/opt/clemmy/clemmy.sh
}

View File

@@ -1 +1,2 @@
A bash client for lemmy. Lots TODO, user guide will be in the program itself.
Entry point is clemmy.sh, -h is not very useful yet (but it's better than nothing).

7
api.sh Normal file
View File

@@ -0,0 +1,7 @@
baseurl(){ if [ -z $INSEC ]; then sec=s; fi; echo "http$sec://$INSTANCE/api/v3/"; } # This needs to be a function so updates to INSTANCE affect it. This is a very old bug lmao
#Generics
get(){ curl -sH "Cookie:jwt=$TOKE" "$(baseurl)$1?${*:3}" | jq "${2:-.}"; }
post(){ curl -sH "Cookie:jwt=$TOKE" "$(baseurl)$1" --json "${*:2}"; }
# I'm just gonna clone this thing rather than try to palm the -X PUT into post. I can fix it later.
put(){ curl -sX PUT "$(baseurl)$1" --json "$(echo ${*:2} | jq '.+{"auth":"'$TOKE'"}')"; }

19
clemmy.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/sh
imps=$(dirname $(realpath $0))
source $imps/api.sh
source $imps/commands/commands.sh
source $imps/pretty.sh
source $imps/creds.sh
source $imps/utils.sh
while getopts "a:hi:v" o;do case "${o}" in
a) select_account $OPTARG;;
i) INSTANCE=$OPTARG;;
h) echo $actions; exit;;
v) echo 0.1.7; exit;;
esac done
shift $((OPTIND-1))
$*

31
commands/accounts.sh Normal file
View File

@@ -0,0 +1,31 @@
#Account hoardan
whoami(){ echo $INSTANCE $TOKE; }
login()
{
post "user/login" '{"username_or_email":"'$1'","password":"'$2'"}'
}
register()
{
get "site" ".site_view.site | .open_registration,.require_email_verification,.require_application,.application_question" | jq -r . | read reg em app appq
if [ $reg == false ]; then
echo "Sorry, this instance does not accept registrations; try to contact them to ask for an account."; exit
fi
if [ $em == true ]; then em="(required)"; else em=""; fi
namedget reg_username "Desired username (required)"
namedget reg_pw "Password (required)"
namedget reg_pw2 "Verify password"
if [ ! reg_pw == reg_pw2 ]; then echo "passwords don't match (continuing anyway, expect failure later though)"; fi
namedget reg_email "Email address $em"
if [ $app == true ]; then namedget reg_appa "Application question: $appq"; fi
result="$(post "user/register" '{"username":"'$reg_username'","password":"'$reg_pw'","password_verify":"'$reg_pw2'","email":"'$reg_email'","answer":"'$reg_appa'"}')"
if [ ! $(jq .error <<< "$result") == "captcha_incorrect" ]; then
jq <<< "$result"; exit;
fi
a="$(get "user/get_captcha" ".ok")"
reg_uuid=$(jq -r '.uuid' <<< "$a")
jq -r '.wav' <<< "$a" | base64 -d > "captcha.wav"
jq -r '.png' <<< "$a" | base64 -d > "captcha.png"
namedget reg_captcha "Please open captcha.wav and captcha.png and input the text - in that order, no spaces"
post "user/register" '{"username":"'$reg_username'","password":"'$reg_pw'","password_verify":"'$reg_pw2'","email":"'$reg_email'","answer":"'$reg_appa'","captcha_uuid":"'$reg_uuid'","captcha_answer":"'$reg_captcha'"}'
}

26
commands/admin.sh Normal file
View File

@@ -0,0 +1,26 @@
pendcount()
{
get "admin/registration_application/count" ".registration_applications"
}
pending()
{
applications=$(get "admin/registration_application/list" ".registration_applications" "unread_only=true")
i=0
app=$(jq ".[$i] // empty" <<< "$applications")
while [ -n "$app" ]; do
appid=$(jq -r .registration_application.id <<< "$app")
jq '.registration_application.id, (.creator | .name,.published,.bio,"bot: "+.bot_account,"matrix: "+.matrix_user_id,.avatar,.banner), "captcha: "+.registration_application.answer' <<< "$app"
ans= # Better make sure this resets lol
while [ ! ans = 'y' -a ! ans = 'n' -a ! ans = 's' ]; do
namedget ans "Accept? (y)es (n)o (s)kip"
done
case $ans in
y) put "admin/registration_application/approve" '{"id":'$appid',"approve":true}';;
n) namedget rejected "Why not?" true; put "admin/registration_application/approve" '{"id":'$appid',"deny_reason":"'$rejected'","approve":false}';;
esac
done
}
addadmin(){ echo "stub"; }
remadmin(){ echo "stub"; }

12
commands/commands.sh Normal file
View File

@@ -0,0 +1,12 @@
actions="notifs notifs2 comments freepost shitpost follow unfollow home deref whoami login pendcount pending"
#Endpoints in other files mostly.
imps=$(dirname $(realpath $0))
source $imps/commands/accounts.sh
source $imps/commands/communities.sh
source $imps/commands/lurking.sh
source $imps/commands/posts.sh
source $imps/commands/admin.sh
#Misc
deref(){ get "resolve_object" "" "q=$*"; }

10
commands/communities.sh Normal file
View File

@@ -0,0 +1,10 @@
#Community hoardan
follow(){ post "community/follow" '{"community_id":'$1',"follow":true}'; }
unfollow(){ post "community/follow" '{"community_id":'$1',"follow":false}'; }
following(){ get "community/list" ".communities | $communities_jq" "type_=Subscribed"; } # Alright it's time
comcreate(){ namedget desc "The community's display name (can be edited later)"; post "community" '{"name":"'$1'","title":"'"$desc"'"}'; }
comedit(){ echo "stub"; }
comdelete(){ namedget confirm "are you sure? (y/n)"; if [ confirm == "y" ]; then post "community/delete" '{"community_id":"'$1'","deleted":true}'; fi; }
addmod(){ echo "stub"; }
remmod(){ echo "stub"; }

7
commands/lurking.sh Normal file
View File

@@ -0,0 +1,7 @@
#Lurkan
notifs(){ get "user/replies" ".replies | reverse | $notifs_jq"; }
notifs2(){ echo "use mentions instead"; }
mentions(){ get "user/mention" ".mentions | reverse | $notifs_jq"; }
home(){ get "post/list" ".posts | $posts_jq" "type_=Subscribed"; }
#This has to get complex now -.-
comments(){ get "post" "(.post_view | $full_post_jq)" "id=$1"; get "comment/list" "(.comments | reverse | $comments_jq)" "post_id=$1&sort=New"; }

7
commands/posts.sh Normal file
View File

@@ -0,0 +1,7 @@
#Post hoardan
save(){ put "post/save" '{"post_id":'$1',"save":true}'; }
unsave(){ put "post/save" '{"post_id":'$1',"save":false}'; }
load(){ get "post/list" ".posts | .[] | $short_post_jq" "type_=All&saved_only=true"; }
#Postan
freepost(){ getbody; post "post" '{"community_id":'$1',"name":"'${*:2}'","body":"'$body'"}'; }
shitpost(){ getbody; postid=$1; parentid=$2; if [ -z $parentid ]; then parentid=null; fi; post "comment" '{"post_id":'$postid',"parent_id":'$parentid',"content":"'$body'"}'; }

26
creds.sh Normal file
View File

@@ -0,0 +1,26 @@
if [ ! -f ~/.config/clemmy/accounts.csv ]; then
mkdir -p ~/.config/clemmy
touch ~/.config/clemmy/accounts.csv
echo "Do you already have an account? y/n"
read choice
if [ $choice == n ]; then
register
else
login
fi
exit
fi
touch ~/.config/clemmy/default_account
accsr=$(cat ~/.config/clemmy/accounts.csv)
i=0
for line in ${accsr[*]}; do
accs[$i]="$line"
i=$((i+1))
done
select_account(){ IFS=, read INSTANCE TOKE INSEC <<< "${accs[$1]}"; }
defaultacc(){ echo -n $1 > ~/.config/clemmy/default_account; }
select_account $(cat ~/.config/clemmy/default_account)

24
pretty.sh Normal file
View File

@@ -0,0 +1,24 @@
# Please don't abuse jq like this
full_post_jq='(.post | (.id | tostring)+" "+(.name | tostring)),
(.post.url)+", "+(.creator.display_name // .creator.name)+":",
((.comment // .post) | .published,
(.body // .content))'
short_post_jq='(.post | (.id | tostring)+" "+(.name | tostring)),
(.post.url)+", "+(.creator.display_name // .creator.name)+":",
((.comment // .post) | .published)'
comment_jq='(.comment | .path[2:])+", "+(.creator.display_name // .creator.name)+":",
((.comment // .post) | .published,
(.body // .content))'
#Split this out because I specifically do want to include post IDs in some places. Or rather, I only don't want to include them on the comments view.
notif_jq='(.comment | (.parent_id | tostring)+"->"+(.id | tostring))+" ("+(.post | (.id | tostring))+"), "+(.creator.display_name // .creator.name)+":",
((.comment // .post) | .published,
(.body // .content))'
community_jq='(.community | (.id | tostring)+" "+.actor_id,.description),
.subscribed,
(.counts | [.subscribers,.posts,.comments,.users_active_week] | join(" "))'
multi_jq(){ echo '.[] | '"$1"',""'; }
comments_jq=$(multi_jq "$comment_jq")
posts_jq=$(multi_jq "$full_post_jq")
notifs_jq=$(multi_jq "$notif_jq")
communities_jq=$(multi_jq "$community_jq")

View File

@@ -1,78 +0,0 @@
#!/bin/sh
accs=$(cat ~/.config/clemmy/accounts.csv)
i=0
for line in ${accs[*]}; do
IFS=, read insts[$i] tokes[$i] <<< $line
i=$((i+1))
done
INSTANCE=${insts[0]}
TOKE=${tokes[0]}
baseurl="https://$INSTANCE/api/v3/"
# Please don't abuse jq like this
showpost='(.post | (.id | tostring)+" "+(.name | tostring)),
(.post.url)+", "+(.creator.display_name // .creator.name)+":",
((.comment // .post) | .published,
(.body // .content)),
""'
postsummary='(.post | (.id | tostring)+" "+(.name | tostring)),
(.post.url)+", "+(.creator.display_name // .creator.name)+":",
((.comment // .post) | .published),
""'
showcomment='(.comment | (.parent_id | tostring)+"->"+(.id | tostring))+", "+(.creator.display_name // .creator.name)+":",
((.comment // .post) | .published,
(.body // .content)),
""'
#Split this out because I specifically do want to include post IDs in some places. Or rather, I only don't want to include them on the comments view.
notif='(.comment | (.parent_id | tostring)+"->"+(.id | tostring))+" ("+(.post | (.id | tostring))+"), "+(.creator.display_name // .creator.name)+":",
((.comment // .post) | .published,
(.body // .content)),
""'
comments=".[] | $showcomment"
posts=".[] | $showpost"
notifs=".[] | $notif"
#Generics
get(){ curl -s "$baseurl$1?${*:3}" | jq "$2"; }
getauth(){ get "$1" "$2" "auth=$TOKE&${*:3}"; }
post(){ curl -s "$baseurl$1" --json "$(echo ${*:2} | jq .+{\"auth\":\"$TOKE\"})"; }
# I'm just gonna clone this thing rather than try to palm the -X PUT into post. I can fix it later.
put(){ curl -sX PUT "$baseurl$1" --json "$(echo ${*:2} | jq .+{\"auth\":\"$TOKE\"})"; }
#Utils
getbody(){ a=$(cat); while read n; do b="$b\n$n"; done <<< "$a"; c=${b//\"/\\\"}; body="${c:2}"; }
actions="notifs notifs2 comments freepost shitpost follow unfollow home deref whoami login"
#Endpoints.
#Lurkan
notifs(){ getauth "user/replies" ".replies | reverse | $notifs"; }
notifs2(){ getauth "user/mention" ".mentions | reverse | $notifs"; }
following(){ echo "use <home> instead"; } # Maybe this will help.
home(){ getauth "post/list" ".posts | $posts" "type_=Subscribed"; }
comments(){ getauth "post" "(.post_view | $showpost), (.comments | reverse | $comments)" "id=$1"; }
#Postan
freepost(){ getbody; post "post" "{\"community_id\":$1,\"name\":\"${*:2}\",\"body\":\"$body\"}"; }
shitpost(){ getbody; postid=$1; parentid=$2; post "comment" "{\"post_id\":$postid,\"parent_id\":$parentid,\"content\":\"$body\"}"; }
#Post hoardan
save(){ put "post/save" "{\"post_id\":$1,\"save\":true}"; }
unsave(){ put "post/save" "{\"post_id\":$1,\"save\":false}"; }
load(){ getauth "post/list" ".posts | .[] | $postsummary" "type_=All&saved_only=true"; }
#Community hoardan
follow(){ post "community/follow" "{\"community_id\":$1,\"follow\":true}"; }
unfollow(){ post "community/follow" "{\"community_id\":$1,\"follow\":false}"; }
#Account hoardan
whoami(){ echo $INSTANCE $TOKE; }
login(){ post "user/login" "{\"username_or_email\":\"$1\",\"password\":\"$2\"}"; }
#Misc
deref(){ getauth "resolve_object" "" "q=$*"; }
while getopts "a:hv" o;do case "${o}" in
a) INSTANCE=${insts[$OPTARG]}; TOKE=${tokes[$OPTARG]};;
h) echo $actions; exit;;
v) echo 0.1.0; exit;;
esac done
shift $((OPTIND-1))
$*

23
utils.sh Normal file
View File

@@ -0,0 +1,23 @@
#Utils
getbody()
{
echo "Write your comment, press ctrl+d on a blank line to submit"
a=$(cat)
while read n; do
b="$b\n$n"
done <<< "$a"
c=${b//\"/\\\"}
body="${c:2}"
}
namedget()
{
echo $2:
if [ $3 ]; then
echo "(Press ctrl+d on a blank line to submit)"
read $1 <<< $(cat)
else
read $1
fi
}