matrix_csharp 1.0.1
dotnet add package matrix_csharp --version 1.0.1
NuGet\Install-Package matrix_csharp -Version 1.0.1
<PackageReference Include="matrix_csharp" Version="1.0.1" />
<PackageVersion Include="matrix_csharp" Version="1.0.1" />
<PackageReference Include="matrix_csharp" />
paket add matrix_csharp --version 1.0.1
#r "nuget: matrix_csharp, 1.0.1"
#:package matrix_csharp@1.0.1
#addin nuget:?package=matrix_csharp&version=1.0.1
#tool nuget:?package=matrix_csharp&version=1.0.1
matrix-dotnet
matrix-dotnet is a ✨modern✨ C# library for the matrix protocol focused on
code brevity. It features a two-layered approach with a Refit-based raw API
interface and a fully featured client class. Modern language features (like the
goto keyword) are used to make the code readable and succinct. Also we indent
with tabs.
Installation
NuGet
There is a NuGet package you can install by with dotnet:
dotnet add package matrix_csharp
Submodule
You can also add this library as a git submodule:
git submodule add https://gitlab.com/Greenscreener/matrix-dotnet
and then add a reference to your csproj file:
dotnet add reference ../matrix-dotnet/matrix-dotnet.csproj
Preface
It is highly recommended to consult relevant parts of the Matrix Specification when working with this library as many design decisions follow the specification's rationale.
Usage
You start by initializing the MatrixClient:
using matrix_dotnet.Client;
var client = new MatrixClient("https://example.com");
await client.PasswordLogin(Secrets.username, Secrets.password, initialDeviceDisplayName: "FreeReal development");
After that, the client will receive an access token and an optional refresh token. The client does not keep your password. Each time the short-lived access token expires, it will be automatically refreshed using the long-lived refresh token. The login API is rate limited, so you might want to store the access and refresh tokens somewhere externally, if you need to run your program many times.
using (FileStream stream = File.Create("client.json")) {
await JsonSerializer.SerializeAsync(stream, client.ToLoginData());
}
And afterwards:
matrix_dotnet.Client.LoginData? loginData = null;
using (FileStream stream = File.OpenRead("client.json")) {
loginData = await JsonSerializer.DeserializeAsync<matrix_dotnet.Client.LoginData>(stream);
};
MatrixClient? client = new MatrixClient(loginData.Value);
Using this technique, you will also be able to keep the same device_id. If you don't, you will add a new device to the users logged-in devices each time you login. Logging in with a password each time is discouraged.
Receiving messages
First, you should start by calling the Sync method:
await client.Sync();
This calls the server's /sync endpoint to establish basic information about
all rooms. To get messages for a room, you can just fetch them directly from its
Timeline:
var roomTimeline = client.JoinedRooms[new RoomID("<room_id>")].timeline;
await foreach (var timelineEvent in roomTimeline.First.EnumerateForward()) {
EventWithState ev = timelineEvent.Value;
if (ev.Event.content is Message message)
Console.WriteLine($"{ev.GetSender()?.displayname ?? ev.Event.sender}: {message.body}");
}
The Timeline is a linked list (you'll see why in a bit). The values are Events with state. In matrix, rooms have state that can change as the room evolves. This state for instance contains user's display names, which can change dynamically. The client automatically resolves this state and attaches the correct state dictionary to each event, so if a user in the example above changes their displayname mid-conversation, the shown displayname will change accordingly.
Now, the Timeline is incomplete, in the beginning, it only contains events
received from the Sync call (usually around 10). The Timeline.First property
doesn't give you the first ever event in the room, but the first currently
cached one. To get earlier events, you want to use await Timeline.First.Previous(). This is an asynchronous method and will
automatically fetch more events when needed, so it can be used to iterate
through the entire history of the room. This is also true for .Next() and
.EnumerateFroward() and .EnumerateBackward(). If this is not desired,
.NextOffline() and other -Offline() methods are available. In most cases
however, you don't want to use them as syncing might cause holes in the
timeline, which the async methods automatically fill in.
To get new messages, you should call the Sync method again. If you supply the
optional timeout argument, the server will wait for the specified time before
responding. If however a new event arrives, it will respond immediately with the
new event.
The following code can be used to display new messages as they arrive:
while (true) {
if ((await lastSeen?.Next()) is not null) {
await foreach (var timelineEvent in (await lastSeen.Next()).EnumerateForward()) {
EventWithState ev = timelineEvent.Value;
if (ev.Event.content is Message message)
Console.WriteLine($"{ev.GetSender()?.displayname ?? ev.Event.sender}: {message.body}");
lastSeen = timelineEvent;
}
}
await client.Sync(30000); // Wait for at most 30 seconds or return immediately if new events are received.
}
It is highly recommended to read the Syncing section of the Matrix Specification as it clearly explains most of what was mentioned above.
Sending messages
Sending messages is much simpler, you can just use the following method:
var id = await client.SendTextMessage(client.JoinedRooms.Keys.First(), "Hello World!");
See in-code documentation for usage of other MatrixClient methods.
Advanced usage
You can call API endpoints directly using the MatrixClient.ApiClient property.
This gives you access to the Refit-generated API client.
Contributing
The library is very incomplete so far, and somewhat on purpose. A lot of
functionality can be added just by adding more event types. If you need anything
not-yet supported, feel free to add it to the Api/EventContent.cs file. I'll
be glad to help with any contributions so even unfinished pull requests are very
welcome.
Known issues, missing features
- event relationships and all related APIs are not implemented
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Microsoft.Extensions.Http (>= 8.0.0)
- Microsoft.Extensions.Logging.Console (>= 8.0.0)
- Refit (>= 7.1.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.