From 7be9fa68bef82a7576344a6e8cc1e51154c6b3bf Mon Sep 17 00:00:00 2001 From: Matias Linares Date: Mon, 11 Jan 2021 22:20:09 -0300 Subject: Response & Exception refactor --- lib/Matrix/Client.rakumod | 371 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 371 insertions(+) create mode 100644 lib/Matrix/Client.rakumod (limited to 'lib/Matrix/Client.rakumod') diff --git a/lib/Matrix/Client.rakumod b/lib/Matrix/Client.rakumod new file mode 100644 index 0000000..01babe5 --- /dev/null +++ b/lib/Matrix/Client.rakumod @@ -0,0 +1,371 @@ +use HTTP::Request::Common; +use URI::Encode; +use JSON::Fast; +use Matrix::Client::Response; +use Matrix::Client::Common; +use Matrix::Client::Room; +use Matrix::Client::Requester; +use Matrix::Client::MediaStore; + +unit class Matrix::Client does Matrix::Client::Requester; + +has Str $.device-id; +has Str $!user-id; +has @!rooms; +has @!users; + +submethod TWEAK { + $Matrix::Client::Common::TXN-ID = now.Int; +} + +#| POST - /_matrix/client/r0/login +multi method login(Str $username, Str $password) { + $.login(:$username, :$password); +} + +#| POST - /_matrix/client/r0/login +multi method login(Str :$username, Str :$password) { + my $post-data = { + type => "m.login.password", + user => $username, + password => $password + }; + + if $!device-id { + $post-data = $!device-id; + } + + my $res = $.post("/login", to-json($post-data)); + my $data = from-json($res.content); + + $!access-token = $data; + $!user-id = $data; + $!device-id = $data; +} + +#| POST - /_matrix/client/r0/logout +method logout() { + $.post("/logout") +} + +#| POST - /_matrix/client/r0/register +method register($username, $password, Bool :$bind-email? = False) { + my $res = $.post("/register", + username => $username, password => $password, + bind_email => $bind-email, + auth => { + type => "m.login.dummy" + }); + my $data = from-json $res.content; + $!access-token = $data; + $!user-id = $data; +} + +# User Data + +#| GET - /_matrix/client/r0/profile/{userId} +method profile(Str :$user-id?) { + my $id = $user-id // $.whoami; + from-json($.get("/profile/" ~ $id).content); +} + +#| GET - /_matrix/client/r0/profile/{userId}/displayname +method display-name(Str :$user-id?) { + my $id = $user-id // $.whoami; + my $res = $.get("/profile/" ~ $id ~ "/displayname"); + + my $data = from-json($res.content); + + $data // "" +} + +#| PUT - /_matrix/client/r0/profile/{userId}/displayname +method change-display-name(Str:D $display-name!) { + so $.put("/profile/" ~ $.whoami ~ "/displayname", + displayname => $display-name) +} + +#| GET - /_matrix/client/r0/profile/{userId}/avatar_url +method avatar-url(Str :$user-id?) { + my $id = $user-id // $.whoami; + my $res = $.get("/profile/" ~ $id ~ "/avatar_url"); + my $data = from-json($res.content); + + $data // "" +} + +#| PUT - /_matrix/client/r0/profile/{userId}/avatar_url +multi method change-avatar(IO::Path $avatar) { + my $mxc-url = $.upload($avatar.IO); + samewith($mxc-url); +} + +#| PUT - /_matrix/client/r0/profile/{userId}/avatar_url +multi method change-avatar(Str:D $mxc-url!) { + $.put("/profile/" ~ $.whoami ~ "/avatar_url", + avatar_url => $mxc-url); +} + +#| GET - /_matrix/client/r0/account/whoami +method whoami { + unless $!user-id { + my $res = $.get('/account/whoami'); + my $data = from-json($res.content); + $!user-id = $data; + } + + $!user-id +} + +## Device management + +#| GET - /_matrix/client/r0/devices +method devices(Matrix::Client:D: --> Seq) { + my $data = from-json($.get("/devices").content); + $data.map(-> $device-data { + Matrix::Client::Response::Device.new(|$device-data) + }) +} + +#| GET - /_matrix/client/r0/devices/{deviceId} +method device(Matrix::Client:D: Str $device-id where *.chars > 0 --> Matrix::Client::Response::Device) { + my $device-data = from-json($.get("/devices/$device-id").content); + Matrix::Client::Response::Device.new(|$device-data) +} + +#| PUT - /_matrix/client/r0/devices/{deviceId} +method update-device(Matrix::Client:D: + Str $device-id where *.chars > 0, + Str $display-name) { + $.put("/devices/$device-id", :display_name($display-name)); +} + +## Presence + +#| GET - /_matrix/client/r0/presence/{userId}/status +method presence(Matrix::Client:D: $user-id? --> Matrix::Client::Response::Presence) { + my $id = $user-id // $.whoami; + my $data = from-json($.get("/presence/$id/status").content); + Matrix::Client::Response::Presence.new(|$data) +} + +#| PUT - /_matrix/client/r0/presence/{userId}/status +method set-presence(Matrix::Client:D: Str $presence, Str :$status-message = "") { + $.put("/presence/$.whoami/status", + :$presence, :status_msg($status-message)); +} + +#| PUT - /_matrix/client/r0/user/{userId}/rooms/{roomId}/tags/{tag} +multi method tags(Str $room-id, Str:D $tag, $order) { + my $id = $.whoami; + from-json($.put("/user/$id/rooms/$room-id/tags/$tag", :$order).content) +} + +#| GET - /_matrix/client/r0/user/{userId}/rooms/{roomId}/tags +multi method tags(Str $room-id) { + my $id = $.whoami; + Matrix::Client::Response::Tag.new(from-json($.get("/user/$id/rooms/$room-id/tags").content)) +} + +#| DELETE - /_matrix/client/r0/user/{userId}/rooms/{roomId}/tags/{tag} +method remove-tag(Str $room-id, Str:D $tag) { + my $id = $.whoami; + $.delete("/user/$id/rooms/$room-id/tags/$tag") +} + +# Syncronization + +#| GET - /_matrix/client/r0/sync +multi method sync(Hash :$sync-filter is copy, :$since = "") { + $.sync(sync-filter => to-json($sync-filter), since => $since) +} + +#| GET - /_matrix/client/r0/sync +multi method sync(Str:D :$sync-filter, Str :$since = "") { + my $res = $.get("/sync", + timeout => 30000, + :$sync-filter, + :$since + ); + + Matrix::Client::Response::Sync.new($res.content) +} + +#| GET - /_matrix/client/r0/sync +multi method sync(:$since = "") { + my $res = $.get("/sync", timeout => 30000, since => $since); + Matrix::Client::Response::Sync.new($res.content) +} + +# Rooms + +#| POST - /_matrix/client/r0/createRoom +method create-room( + Bool :$public = False, + *%args --> Matrix::Client::Room +) { + my %params; + + for %args.kv -> $key, $value { + %params{$key.subst('-', '_')} = $value; + } + + if 'visibility' ~~ %params { + %params = $public; + } + + my $res = from-json($.post('/createRoom', |%params).content); + + Matrix::Client::Room.new( + id => $res, + access-token => self.access-token, + home-server => self.home-server + ) +} + +#| POST - /_matrix/client/r0/join/{roomIdOrAlias} +method join-room($room-id!) { + $.post("/join/$room-id") +} + +#| POST - /_matrix/client/r0/rooms/{roomId}/ban +method ban(Str $room-id, Str $user-id, $reason = "") { + $.post( + "/rooms/$room-id/ban", + :$user-id, + :$reason + ); +} + +#| POST - /_matrix/client/r0/rooms/{roomId}/unban +method unban(Str $room-id, Str $user-id) { + $.post( + "/rooms/$room-id/unban", + :$user-id + ); +} + +#| POST - /_matrix/client/r0/rooms/{roomId}/invite +method invite(Str $room-id, Str $user-id) { + $.post( + "/rooms/$room-id/invite", + :$user-id + ) +} + +#| POST - /_matrix/client/r0/rooms/{roomId}/forget +method forget(Str $room-id) { + $.post("/rooms/$room-id/forget") +} + +#| POST - /_matrix/client/r0/rooms/{roomId}/kick +method kick(Str $room-id, Str $user-id, $reason = "") { + $.post( + "/rooms/$room-id/kick", + :$user-id, + :$reason + ); +} + +#| POST - /_matrix/client/r0/rooms/{roomId}/leave +method leave-room($room-id) { + $.post("/rooms/$room-id/leave"); +} + +#| GET - /_matrix/client/r0/joined_rooms +method joined-rooms(--> Seq) { + my $res = $.get('/joined_rooms'); + my $data = from-json($res.content); + return $data.Seq.map(-> $room-id { + Matrix::Client::Room.new( + id => $room-id, + home-server => $!home-server, + access-token => $!access-token + ) + }); +} + +#| GET - /_matrix/client/r0/publicRooms +method public-rooms() { + $.get('/publicRooms') +} + +#| PUT - /_matrix/client/r0/rooms/{roomId}/send/{eventType}/{txnId} +method send(Str $room-id, Str $body, :$type? = "m.text") { + $Matrix::Client::Common::TXN-ID++; + my $res = $.put( + "/rooms/$room-id/send/m.room.message/{$Matrix::Client::Common::TXN-ID}", + msgtype => $type, body => $body + ); + + from-json($res.content) +} + +#| PUT - /_matrix/client/r0/rooms/{roomId}/send/{eventType}/{txnId} +method send-event(Str $room-id, Str :$event-type, :$content, :$txn-id? is copy, :$timestamp?) { + unless $txn-id.defined { + $txn-id = $Matrix::Client::Common::TXN-ID++; + } + + my $path = "/rooms/$room-id/send/$event-type/$txn-id"; + my $res = $.put($path, |$content); + from-json($res.content) +} + +#| GET - /_matrix/client/r0/directory/room/{roomAlias} +method get-room-id($room-alias) { + my $res = $.get("/directory/room/$room-alias"); + + from-json($res.content) +} + +#| PUT - /_matrix/client/r0/directory/room/{roomAlias} +method add-room-alias($room-id, $room-alias) { + $.put("/directory/room/$room-alias", + room_id => $room-id); +} + +#| DELETE - /_matrix/client/r0/directory/room/{roomAlias} +method remove-room-alias($room-alias) { + $.delete("/directory/room/$room-alias"); +} + +# Media + +method media(--> Matrix::Client::MediaStore) { + return Matrix::Client::MediaStore.new( + home-server => $!home-server, + access-token => $!access-token + ) +} + +method upload(IO::Path $path, Str $filename?) is DEPRECATED('media.upload') { + self.media.upload($path, $filename) +} + +# Misc + +method run(Int :$sleep = 10, :$sync-filter?, :$start-since? --> Supply) { + my $s = Supplier.new; + my $supply = $s.Supply; + my $since = $start-since // ""; + + start { + loop { + my $sync = $.sync(:$since, :$sync-filter); + $since = $sync.next-batch; + + for $sync.invited-rooms -> $info { + $s.emit($info); + } + + for $sync.joined-rooms -> $room { + for $room.timeline.events -> $event { + $s.emit($event) + } + } + sleep $sleep; + } + } + $supply +} -- cgit v1.2.3-70-g09d2