Ideally you should be able to build a Matrix client in something like a Python REPL and like 20 lines of code with an `input` loop at the end. I don't know if that's the case at the moment.
Ideally you should be able to build a Matrix client in something like a Python REPL and like 20 lines of code with an `input` loop at the end. I don't know if that's the case at the moment.
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
> I used bashtrix for about 4 hours this morning. Why, you ask? I didn't have the bandwidth, latency or reliability to use Riot. I ended up using bashtrix on one of my servers through mosh...
> Could have done with scroll back (the screen fills up with 'null' and '[]' – the latter, I started to recognise as marking read receipts and/or perhaps presence) but shrank the font size down and made the most of it :p. Worked Rather well considering
This seems to indicate it's missing a register step, and then it fails to be as simple as IRC where you just set nickname and connect to a server. Sometimes the server asks you to identify yourself, but that's up to the server, not the protocol.
That said, Matrix also supports guest accounts (which are quite locked down to prevent abuse, but would work for this example) - so the /login request could be replaced by calling /register with type=guest which would then do what you want.
edit: it would look something like this (7 lines now!):
SERVER='https://matrix.org'; ROOM='#test:matrix.org'
TOKEN=`curl -X POST $SERVER/_matrix/client/r0/register --data "{ 'kind': 'guest' }" | 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 "> " INPUT; `curl -s -X POST $SERVER/_matrix/client/r0/rooms/$ROOM_ID/m.room.message?access_token=$TOKEN --data "{ 'body': '$INPUT', 'msgtype': 'm.text'}"`; doneDo take a look at https://gitlab.com/darnir/matrix-shell-suite
It's a basic matrix client written in pure POSIX sh.