|
|
|
|
|
by Arathorn
2470 days ago
|
|
Ooooh... sounds like a fun challenge :D I've typed this out straight into the HN input box so it almost certainly doesn't work and will be full of typos and escaping bugs, but for illustrative purposes: here's what a ~8 line Matrix client for basic bi-directional chat in a given room could look like (complete with login) in almost-bash, with deps only on curl and jq: USERNAME='@whoever:matrix.org'; SERVER='https://matrix.org'; ROOM='#test:matrix.org'
read -s -p "Password for $USERNAME:" PASSWORD
TOKEN=`curl -X POST $SERVER/_matrix/client/r0/login --data "{ 'type': 'm.login.password', 'login': '$USERNAME', 'password': '$PASSWORD' }" | jq .access_token`
ROOM_ID=`curl $SERVER/_matrix/client/r0/directory/room/$ROOM | jq .room_id`; curl "$SERVER/_matrix/client/r0/join/$ROOM_ID?access_token=$TOKEN"
(while true; do SYNC=`curl -s $SERVER/_matrix/client/r0/sync?access_token=$TOKEN&timeout=30000&since=$SINCE`
echo $SYNC | jq ".rooms.join.$ROOM_ID.timeline"
SINCE=`echo $SYNC | jq .next_batch`; done) &
while true; do read -p "<$USERNAME> " INPUT; `curl -s -X POST $SERVER/_matrix/client/r0/rooms/$ROOM_ID/m.room.message?access_token=$TOKEN --data "{ 'body': '$INPUT', 'msgtype': 'm.text'}"`; done
Spread out a bit more with comments: # set your matrix ID & server URL, and the room you want to chat in:
USERNAME='@whoever:matrix.org'
SERVER='https://matrix.org'
ROOM='#test:matrix.org'
# prompt for a password; log in and grab an access_token
read -s -p "Password for $USERNAME:" PASSWORD
TOKEN=`curl -X POST $SERVER/_matrix/client/r0/login --data "{ 'type': 'm.login.password', 'login': '$USERNAME', 'password': '$PASSWORD' }" | jq .access_token`
# resolve the room alias (#test:matrix.org) to a room ID (!vfFxDRtZSSdspfTSEr:matrix.org)
ROOM_ID=`curl $SERVER/_matrix/client/r0/directory/room/$ROOM | jq .room_id`
# check that you're joined to the room (redundant if you know you're already there)
curl "$SERVER/_matrix/client/r0/join/$ROOM_ID?access_token=$TOKEN"
# set a background loop running to receive messages, and use jq to filter out the
# messages for the room you care about from the sync response. For now we print them
# as JSON pretty-printed by jq, but that's not too bad.
(while true;
do SYNC=`curl -s $SERVER/_matrix/client/r0/sync?access_token=$TOKEN&timeout=30000&since=$SINCE`
echo $SYNC | jq ".rooms.join.$ROOM_ID.timeline"
SINCE=`echo $SYNC | jq .next_batch`
done) &
# set a foreground loop running to prompt for your own messages and send them
# into the room as plaintext.
while true;
do read -p "<$USERNAME> " INPUT;
`curl -s -X POST $SERVER/_matrix/client/r0/rooms/$ROOM_ID/m.room.message?access_token=$TOKEN --data "{ 'body': '$INPUT', 'msgtype': 'm.text'}"`
done
If I have time I'll actually try running & debugging this to be usable and edit the post (but got to run into a meeting now :( ).Needless to say, this'd be much prettier on Python - and you'd prolly want to use a nice SDK like https://github.com/poljar/matrix-nio (see https://matrix.org/blog/2019/07/03/usage-of-matrix-nio/) so you get things like E2E Encryption for free. But doing it in plain bash hopefully gives more of an idea. |
|
I think it’s important to not be “using a library” since the test case is hopefully that the protocol is easy enough to get something barebones with even super baseline tools. Your bash script obviously matches this requirement
My reference here is the excellent Haskell Wiki “Build tour own IRC bot”. Really captures the simplicity of the protocol
https://wiki.haskell.org/Roll_your_own_IRC_bot