Back to APIs list

Matrix API examples & templates

Use these vals as a playground to view and fork Matrix API examples and templates on Val Town. Run any example below or find templates that can be used as a pre-built solution.

Usage

import {githubEmojiUrl} from "https://esm.town/v/karfau/githubEmoji";
console.log(githubEmojiUrl('+1'))
//"https://github.githubassets.com/images/icons/emoji/unicode/1f44d.png?v8" 

or in a browser

<img src="https://karfau-githubEmoji.web.val.run/+1"></img>

Looks like in the preview.

curl https://karfau-githubEmoji.web.val.run/+1

(prints "https://github.githubassets.com/images/icons/emoji/unicode/1f44d.png?v8")


If the name you pass (as argument or in the request path) is not in the list, it returns octocat

The list of names can be accessed using githubEmojiNames or by calling https://karfau-githubemoji.web.val.run/names

Readme
Fork
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import { GITHUB_EMOJIS } from "https://esm.town/v/karfau/GITHUB_EMOJIS";
import { fetch } from "https://esm.town/v/std/fetch?v=4";
export const isEmoji = (key: string) => Object.hasOwn(GITHUB_EMOJIS, key);
export const githubEmojiUrl = (name: string, fallback = "octocat"): string =>
GITHUB_EMOJIS[isEmoji(name) ? name : fallback];
export const githubEmojiNames = (): string[] => Object.keys(GITHUB_EMOJIS);
export default async function githubEmoji(req: Request): Promise<Response> {
const contentType = req.headers.get("Content-Type");
const nameFromURL = new URL(req.url).pathname.split("/").filter(Boolean)[0];
if (nameFromURL === "names") {
return Response.json(githubEmojiNames());
}
const url = githubEmojiUrl(nameFromURL);
if (contentType || contentType === "application/json") {
return Response.json(url);
}
try {
return fetch(url);
} catch (error) {
console.error(req.url, nameFromURL, error);
return new Response(
"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"64\" height=\"64\" viewBox=\"218.329 117.251 67.385 67.385\" xml:space=\"preserve\"><path style=\"stroke:#e9d535;stroke-width:0;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-li
{ headers: { "Content-Type": "image/svg" }, status: 307, statusText: "Currently not available" },
);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import { fetch } from "https://esm.town/v/std/fetch";
export const sendMatrixChatRoomMessage = async (
accessToken: string,
roomId: string,
transactionId: string,
message: MessageEventContent,
serverUrl: string = "https://matrix.org",
) => {
const url = `${serverUrl}/_matrix/client/v3/rooms/${
encodeURIComponent(roomId)
}/send/m.room.message/${encodeURIComponent(transactionId)}`;
//
const config = {
method: "PUT",
headers: {
"Authorization": `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(message),
};
return await fetch(url, config);
};
//
// Types
export interface MessageEventContent {
msgtype?: string;
body?: string;
format?: string;
formatted_body?: string;
info?: MessageEventContentInfo_;
url?: string;
membership?: RoomPhase;
"m.relates_to"?: {
event_id?: string;
is_falling_back?: boolean;
rel_type?: string;
"m.in_reply_to"?: {
[event_id: string]: string;
};
};
name?: string;
alias?: string;
join_rule?: string;
topic?: string;
display_name?: string;
displayname?: string;
avatar_url?: string;
is_direct?: boolean;
third_party_signed?: string;
Runs every 15 min
Fork
1
2
3
4
import { watchReaderAndSendToMatrix } from "https://esm.town/v/vlad/watchReaderAndSendToMatrix";
export const watchReaderAndSendToMatrix_time2 = () =>
watchReaderAndSendToMatrix();
1
2
3
4
5
6
7
8
9
export function getRotationFromFFmpegDisplayMatrixString(str: string) {
let elements = str.match(/[-+]?\d+/g)?.map(Number) || [];
if (elements.length !== 9) {
// throw new Error("Exactly 9 matrix elements are required");
}
// Drop the last row
elements = elements.slice(-6);
return elements;
}
1
2
3
4
5
6
7
8
9
10
import process from "node:process";
import { fetchJSON } from "https://esm.town/v/stevekrouse/fetchJSON?v=41";
export let distance = (a, b) => {
let destinationA = encodeURIComponent(String(a).trim());
let destinationB = encodeURIComponent(String(b).trim());
return fetchJSON(
`https://maps.googleapis.com/maps/api/distancematrix/json?destinations=${destinationA}&origins=${destinationB}&units=imperial&key=${process.env.GOOGLE_MAPS_API_KEY}`
);
};
Runs every 15 min
Fork
1
2
3
4
import { watchReaderAndSendToMatrix } from "https://esm.town/v/vlad/watchReaderAndSendToMatrix";
export const watchReaderAndSendToMatrix_time3 = () =>
watchReaderAndSendToMatrix();
Fork
1
2
3
4
// https://stevekrouse-serverlessMatrixEchoBot.express.val.run/_matrix/push/v1/notify
export async function serverlessMatrixEchoBot(req, res) {
res.send(req.path);
}
Runs every 15 min
Fork
1
2
3
4
import { watchReaderAndSendToMatrix } from "https://esm.town/v/vlad/watchReaderAndSendToMatrix";
export const watchReaderAndSendToMatrix_time4 = () =>
watchReaderAndSendToMatrix();
Runs every 15 min
Fork
1
2
3
4
import { watchReaderAndSendToMatrix } from "https://esm.town/v/vlad/watchReaderAndSendToMatrix";
export const watchReaderAndSendToMatrix_time1 = () =>
watchReaderAndSendToMatrix();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { fetch } from "https://esm.town/v/std/fetch";
export const joinMatrixRoom = async (
accessToken: string,
roomId: string,
serverUrl: string = "https://matrix.org",
) => {
const url = `${serverUrl}/_matrix/client/v3/rooms/${
encodeURIComponent(roomId)
}/join`;
//
const config = {
method: "POST",
headers: {
"Authorization": `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
};
return await fetch(url, config);
};
1
2
3
4
export async function serverlessMatrixEchoBot2(req, res) {
console.log(req.path);
res.send("<h1>working!</h1>");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { sendMatrixChatRoomMessage } from "https://esm.town/v/vlad/sendMatrixChatRoomMessage";
export const sendMatrixChatRoomTextMessage = (
accessToken: string,
roomId: string,
message: string,
) => {
sendMatrixChatRoomMessage(
accessToken,
roomId,
new Date().toISOString(),
{ msgtype: "m.text", body: message },
);
};

A example Serverless Bot for Matrix chat. See https://vlad.roam.garden/How-to-create-a-serverless-Matrix-Chat-bot for a more detailed write-up on how to set one up!

To test this bot:

  • invite serverless-echo@matrix.org to your unencrypted room
  • Send a message starting with !echo and the bot will repeat content after.

Use https://matrix-serverless.netlify.app/ to configure Matrix to call the endpoint on newly received messages

Readme
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import { sendMatrixChatRoomTextMessage } from "https://esm.town/v/vlad/sendMatrixChatRoomTextMessage";
import { joinMatrixRoom } from "https://esm.town/v/vlad/joinMatrixRoom";
import process from "node:process";
export async function serverlessMatrixEchoBot(
req: express.Request,
res: express.Response,
) {
// Todo: explicitly ignore encrypted messages, or matrix will keep try sending them
// as rn this will just error out
const event = req.body.notification;
const matrixToken = process.env.matrixEchoBot;
/**
* Accept all invites sent to the bot, generally this is optional
* (e.g. I have a personal bot that I only talk to in a specific room and so I just joined that room from bot account)
* but you'd want this if you want to make a bot anyone can interact with
*/
if (event.membership === "invite") {
await joinMatrixRoom(matrixToken, event.room_id);
return res.json({ rejected: [] });
}
//
const text = event.content.body;
const roomId = event.room_id;
//
const echoText = "!echo ";
if (text.startsWith(echoText)) {
await sendMatrixChatRoomTextMessage(
matrixToken,
roomId,
text.slice(echoText.length),
);
}
//
// This is important - if you don't return this JSON -
// Matrix won't consider notification as processed and will keep sending you the same one
return res.json({ rejected: [] });
}
1
2
3
4
5
6
7
8
9
10
11
export function matrixMediaToHttpUrl(
mxcUrl: string,
homeserverDomain: string = "matrix.org",
) {
const mxcPrefix = "mxc://";
if (!mxcUrl.startsWith(mxcPrefix)) {
throw new Error("Invalid mxc URL");
}
const mxcUrlWithoutScheme = mxcUrl.slice(mxcPrefix.length);
return `https://${homeserverDomain}/_matrix/media/v3/download/${mxcUrlWithoutScheme}`;
}
1
Next