aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatias Linares <matiaslina@gmail.com>2019-08-17 19:54:09 -0300
committerMatias Linares <matiaslina@gmail.com>2019-08-17 19:54:09 -0300
commit5feee914510dd9adfa53dce89b160ee2d0218fc0 (patch)
tree0bdef8fae4f5ae7cefe6848faf1a789707c78748
parentbc6c791c72f9fe460fdb9559522ae154124e8e97 (diff)
parentec4393cb81952fffa2273e313818a57c9611c5a2 (diff)
downloadperl6-matrix-client-5feee914510dd9adfa53dce89b160ee2d0218fc0.tar.gz
Merge branch 'master' into documentation
-rw-r--r--META6.json4
-rw-r--r--README.md59
-rw-r--r--endpoints.md30
-rw-r--r--lib/Matrix/Client.pm681
-rw-r--r--lib/Matrix/Client/Requester.pm643
-rw-r--r--lib/Matrix/Client/Room.pm62
-rw-r--r--lib/Matrix/Response.pm619
7 files changed, 193 insertions, 45 deletions
diff --git a/META6.json b/META6.json
index 0788805..d31ee73 100644
--- a/META6.json
+++ b/META6.json
@@ -4,7 +4,7 @@
],
"build-depends" : [ ],
"depends" : [
- "JSON::Tiny",
+ "JSON::Fast",
"HTTP::UserAgent",
"URI::Encode",
"IO::Socket::SSL"
@@ -34,5 +34,5 @@
"Test",
"Test::META"
],
- "version" : "0.3.0"
+ "version" : "0.5.1"
}
diff --git a/README.md b/README.md
index 43c1aac..bdb8067 100644
--- a/README.md
+++ b/README.md
@@ -1,26 +1,53 @@
-# Matrix client
+# Matrix::Client
A perl 6 library for [Matrix](https://matrix.org).
-## Status
+## Synopsis
-This project is in early development. A lot of methods return a raw
-`HTTP::Response` and not something from this library.
-## Examples
+ use Matrix::Client;
-From the `examples` directory:
+ my $client = Matrix::Client.new(
+ :home-server<https://matrix.org>,
+ :device-id<matrix-client>
+ );
- use v6;
- use Matrix::Client;
+ $client.login(:username<myuser>, :password<s3cr3t>);
+
+ # Check my user
+ say $client.whoami; # @myuser:matrix.org
+
+ # Send a message to a random room that I'm in
+ my $room = $client.joined-rooms.pick;
+ say "Sending a message to {$room.name}";
+ $room.send("Hello from perl6!");
+
+## Description
+
+Matrix is an open network for secure, decentralized communication.
+
+This module provides an interface to interact with a Matrix homeserver through
+the *Client-Server API*. It's currenlty on active development but it's mostly
+stable for day to day use.
+
+Here's a not complete list of things that can be done:
+
+* Login/logout
+* Registration
+* Synchronization of events/messages
+* Send events
+* Send messages
+* Upload files to a home-server
+
+
+There are many missing endpoints (you can check a complete checklist
+[here](https://github.com/matiaslina/perl6-matrix-client/blob/master/endpoints.md)).
+
+## Documentation
- # Instantiate a new client for a given home-server
- my $client = Matrix::Client.new: :home-server<https://matrix.org>
- # Login
- $client.login: @*ARGS[0], @*ARGS[1];
+There's a couple of pages of documentation on the `docs/` directory. This
+includes API documentation, basic usage, examples, etc.
- # Show all joined rooms
- say $client.rooms(:sync);
+## Author
- # And finally logout.
- $client.logout
+Matías Linares <matias@deprecated.org> | Matrix ID: `@matias:matrix.deprecated.org`
diff --git a/endpoints.md b/endpoints.md
index 9abcf1a..2ddf2c3 100644
--- a/endpoints.md
+++ b/endpoints.md
@@ -8,13 +8,17 @@ from matrix.org. This will give you an overview about what's implemented in the
- [ ] PUT - /_matrix/client/r0/directory/list/appservice/{networkId}/{roomId}
+## Capabilities
+
+- [ ] GET - /_matrix/client/r0/capabilities
+
## Device management
- [ ] DELETE - /_matrix/client/r0/devices/{deviceId}
-- [ ] GET - /_matrix/client/r0/devices
-- [ ] GET - /_matrix/client/r0/devices/{deviceId}
+- [X] GET - /_matrix/client/r0/devices
+- [X] GET - /_matrix/client/r0/devices/{deviceId}
- [ ] POST - /_matrix/client/r0/delete_devices
-- [ ] PUT - /_matrix/client/r0/devices/{deviceId}
+- [X] PUT - /_matrix/client/r0/devices/{deviceId}
## End-to-end encryption
@@ -38,9 +42,7 @@ from matrix.org. This will give you an overview about what's implemented in the
## Presence
-- [ ] GET - /_matrix/client/r0/presence/list/{userId}
- [X] GET - /_matrix/client/r0/presence/{userId}/status
-- [ ] POST - /_matrix/client/r0/presence/list/{userId}
- [X] PUT - /_matrix/client/r0/presence/{userId}/status
## Push notifications
@@ -82,14 +84,14 @@ from matrix.org. This will give you an overview about what's implemented in the
- [X] GET - /_matrix/client/r0/joined_rooms
- [X] POST - /_matrix/client/r0/join/{roomIdOrAlias}
-- [ ] POST - /_matrix/client/r0/rooms/{roomId}/ban
-- [ ] POST - /_matrix/client/r0/rooms/{roomId}/forget
-- [ ] POST - /_matrix/client/r0/rooms/{roomId}/invite
+- [X] POST - /_matrix/client/r0/rooms/{roomId}/ban
+- [X] POST - /_matrix/client/r0/rooms/{roomId}/forget
+- [X] POST - /_matrix/client/r0/rooms/{roomId}/invite
- [ ] POST - /_matrix/client/r0/rooms/{roomId}/invite
- [ ] POST - /_matrix/client/r0/rooms/{roomId}/join
-- [ ] POST - /_matrix/client/r0/rooms/{roomId}/kick
+- [X] POST - /_matrix/client/r0/rooms/{roomId}/kick
- [X] POST - /_matrix/client/r0/rooms/{roomId}/leave
-- [ ] POST - /_matrix/client/r0/rooms/{roomId}/unban
+- [X] POST - /_matrix/client/r0/rooms/{roomId}/unban
## Room participation
@@ -103,7 +105,6 @@ from matrix.org. This will give you an overview about what's implemented in the
- [ ] GET - /_matrix/client/r0/rooms/{roomId}/members
- [X] GET - /_matrix/client/r0/rooms/{roomId}/messages
- [ ] GET - /_matrix/client/r0/rooms/{roomId}/state
-- [ ] GET - /_matrix/client/r0/rooms/{roomId}/state/{eventType}
- [ ] GET - /_matrix/client/r0/rooms/{roomId}/state/{eventType}/{stateKey}
- [ ] GET - /_matrix/client/r0/sync
- [ ] GET - /_matrix/client/r0/user/{userId}/filter/{filterId}
@@ -111,10 +112,13 @@ from matrix.org. This will give you an overview about what's implemented in the
- [ ] POST - /_matrix/client/r0/user/{userId}/filter
- [ ] PUT - /_matrix/client/r0/rooms/{roomId}/redact/{eventId}/{txnId}
- [X] PUT - /_matrix/client/r0/rooms/{roomId}/send/{eventType}/{txnId}
-- [ ] PUT - /_matrix/client/r0/rooms/{roomId}/state/{eventType}
- [X] PUT - /_matrix/client/r0/rooms/{roomId}/state/{eventType}/{stateKey}
- [ ] PUT - /_matrix/client/r0/rooms/{roomId}/typing/{userId}
+## Room ugprades
+
+- [ ] POST - /_matrix/client/r0/rooms/{roomId}/upgrade
+
## Search
- [ ] POST - /_matrix/client/r0/search
@@ -145,6 +149,8 @@ from matrix.org. This will give you an overview about what's implemented in the
- [X] GET - /_matrix/client/r0/profile/{userId}/avatar_url
- [X] GET - /_matrix/client/r0/profile/{userId}/displayname
- [ ] GET - /_matrix/client/r0/register/available
+- [ ] GET - /_matrix/client/r0/user/{userId}/account_data/{type}
+- [ ] GET - /_matrix/client/r0/user/{userId}/rooms/{roomId}/account_data/{type}
- [ ] GET - /_matrix/client/r0/user/{userId}/rooms/{roomId}/tags
- [ ] POST - /_matrix/client/r0/account/3pid
- [ ] POST - /_matrix/client/r0/account/3pid/delete
diff --git a/lib/Matrix/Client.pm6 b/lib/Matrix/Client.pm6
index 2fdbf4b..9022c65 100644
--- a/lib/Matrix/Client.pm6
+++ b/lib/Matrix/Client.pm6
@@ -1,6 +1,6 @@
use HTTP::Request::Common;
use URI::Encode;
-use JSON::Tiny;
+use JSON::Fast;
use Matrix::Response;
use Matrix::Client::Common;
use Matrix::Client::Room;
@@ -116,6 +116,31 @@ method whoami {
$!user-id
}
+## Device management
+
+#| GET - /_matrix/client/r0/devices
+method devices(Matrix::Client:D: --> Seq) {
+ my $data = from-json($.get("/devices").content);
+ $data<devices>.map(-> $device-data {
+ Matrix::Response::Device.new(|$device-data)
+ })
+}
+
+#| GET - /_matrix/client/r0/devices/{deviceId}
+method device(Matrix::Client:D: Str $device-id where *.chars > 0 --> Matrix::Response::Device) {
+ my $device-data = from-json($.get("/devices/$device-id").content);
+ Matrix::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::Response::Presence) {
my $id = $user-id // $.whoami;
@@ -202,6 +227,45 @@ 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");
@@ -236,6 +300,17 @@ method send(Str $room-id, Str $body, :$type? = "m.text") {
from-json($res.content)<event_id>
}
+#| 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)<event_id>
+}
+
#| GET - /_matrix/client/r0/directory/room/{roomAlias}
method get-room-id($room-alias) {
my $res = $.get("/directory/room/$room-alias");
@@ -270,10 +345,10 @@ method upload(IO::Path $path, Str $filename?) {
# Misc
-method run(Int :$sleep = 10, :$sync-filter? --> Supply) {
+method run(Int :$sleep = 10, :$sync-filter?, :$start-since? --> Supply) {
my $s = Supplier.new;
my $supply = $s.Supply;
- my $since = "";
+ my $since = $start-since // "";
start {
loop {
diff --git a/lib/Matrix/Client/Requester.pm6 b/lib/Matrix/Client/Requester.pm6
index 1a60014..ff543c9 100644
--- a/lib/Matrix/Client/Requester.pm6
+++ b/lib/Matrix/Client/Requester.pm6
@@ -1,7 +1,7 @@
use HTTP::UserAgent;
use HTTP::Request::Common;
use URI::Encode;
-use JSON::Tiny;
+use JSON::Fast;
use Matrix::Client::Exception;
unit role Matrix::Client::Requester;
@@ -27,13 +27,22 @@ method !access-token-arg {
}
method get(Str $path, :$media = False, *%data) {
- my $query = "?{self!access-token-arg}";
+ my $query = "?";
for %data.kv -> $k,$v {
$query ~= "&$k=$v" if $v.so;
}
my $encoded-path = $path.subst('#', '%23');
my $uri = $.base-url(:$media) ~ $encoded-path ~ uri_encode($query);
- return self!handle-error($!ua.get($uri));
+
+ my $req = HTTP::Request.new(GET => $uri);
+
+ if $!access-token.so {
+ $req.header.field(Authorization => "Bearer {$!access-token}");
+ }
+
+ return self!handle-error(
+ $!ua.request($req)
+ );
}
method base-url(Bool :$media? = False --> Str) {
@@ -46,9 +55,12 @@ method base-url(Bool :$media? = False --> Str) {
multi method post(Str $path, Str $json, :$media = False) {
my $encoded-path = $path.subst('#', '%23');
- my $url = $.base-url(:$media) ~ $encoded-path ~ "?{self!access-token-arg}";
+ my $url = $.base-url(:$media) ~ $encoded-path;
my $req = HTTP::Request.new(POST => $url,
Content-Type => 'application/json');
+ if $!access-token.so {
+ $req.header.field(Authorization => "Bearer {$!access-token}");
+ }
$req.add-content($json);
return self!handle-error($!ua.request($req));
}
@@ -60,19 +72,27 @@ multi method post(Str $path, :$media = False, *%params) {
method post-bin(Str $path, Buf $buf, :$content-type) {
my $encoded-path = $path.subst('#', '%23');
- my $req = POST($.base-url(:media)
- ~ $encoded-path
- ~ "?{self!access-token-arg}",
+ my $req = POST(
+ $.base-url(:media) ~ $encoded-path,
content => $buf,
Content-Type => $content-type
);
+
+ if $!access-token.so {
+ $req.header.field(Authorization => "Bearer {$!access-token}");
+ }
+
return self!handle-error($!ua.request($req));
}
multi method put(Str $path, Str $json) {
my $encoded-path = $path.subst('#', '%23');
- my $req = HTTP::Request.new(PUT => $.base-url() ~ $encoded-path ~ "?{self!access-token-arg}",
+ my $req = HTTP::Request.new(PUT => $.base-url() ~ $encoded-path,
Content-Type => 'application/json');
+ if $!access-token.so {
+ $req.header.field(Authorization => "Bearer {$!access-token}");
+ }
+
$req.add-content($json);
return self!handle-error($!ua.request($req))
}
@@ -84,7 +104,12 @@ multi method put(Str $path, *%params) {
method delete(Str $path) {
my $encoded-path = $path.subst('#', '%23');
my $req = HTTP::Request.new(
- DELETE => $.base-url ~ $encoded-path ~ "?{self!access-token-arg}",
+ DELETE => $.base-url ~ $encoded-path,
Content-Type => 'application/json');
+ if $!access-token.so {
+ $req.header.field(
+ Authorization => "Bearer $!access-token"
+ );
+ }
return self!handle-error($!ua.request($req))
}
diff --git a/lib/Matrix/Client/Room.pm6 b/lib/Matrix/Client/Room.pm6
index 4ec774f..ca97d2f 100644
--- a/lib/Matrix/Client/Room.pm6
+++ b/lib/Matrix/Client/Room.pm6
@@ -1,4 +1,4 @@
-use JSON::Tiny;
+use JSON::Fast;
use Matrix::Client::Common;
use Matrix::Client::Requester;
use Matrix::Response;
diff --git a/lib/Matrix/Response.pm6 b/lib/Matrix/Response.pm6
index edd4d51..268be84 100644
--- a/lib/Matrix/Response.pm6
+++ b/lib/Matrix/Response.pm6
@@ -1,4 +1,4 @@
-use JSON::Tiny;
+use JSON::Fast;
unit module Matrix::Response;
@@ -69,7 +69,7 @@ class Matrix::Response::Sync {
my Matrix::Response::Event @presence;
my Matrix::Response::RoomInfo @joined-rooms;
my Matrix::Response::InviteInfo @invited-rooms;
-
+
for $json<presence><events>.List -> $ev {
@presence.push(Matrix::Response::Event.new(|$ev));
}
@@ -122,3 +122,18 @@ class Tag {
self.bless(:@tags)
}
}
+
+
+class Matrix::Response::Device {
+ has Str $.device-id;
+ has $.display-name;
+ has $.last-seen-ip;
+ has $.last-seen-ts;
+
+ submethod BUILD(
+ Str :device_id(:$!device-id),
+ :display_name(:$!display-name)?,
+ :last_seen_ip(:$!last-seen-ip)?,
+ :last_seen_ts(:$!last-seen-ts)?
+ ) { }
+}