diff --git a/CHANGELOG.md b/CHANGELOG.md
index e827e070..c050e7e5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ Versia Server `0.8.0` is fully backwards compatible with `0.7.0`.
- Outbound federation and inbox processing are now handled by a queue system (like most federated software).
- Added an administration UI for managing the queue.
- Upgraded Bun to `1.1.36`.
+- Implemented support for the [Instance Messaging Extension](https://versia.pub/extensions/instance-messaging)
- Allowed `
` and `` tags in Markdown.
- Added `--password` flag to the user creation CLI.
diff --git a/README.md b/README.md
index 781d21e3..dad685f2 100644
--- a/README.md
+++ b/README.md
@@ -70,6 +70,7 @@ Contributions are welcome! Please see the [CONTRIBUTING.md](CONTRIBUTING.md) fil
The following extensions are currently supported or being worked on:
- `pub.versia:custom_emojis`: Custom emojis
+- `pub.versia:instance_messaging`: Instance Messaging
- `pub.versia:polls`: Polls
- `pub.versia:share`: Share
diff --git a/api/messaging/index.ts b/api/messaging/index.ts
new file mode 100644
index 00000000..efc5f07d
--- /dev/null
+++ b/api/messaging/index.ts
@@ -0,0 +1,48 @@
+import { apiRoute, applyConfig } from "@/api";
+import { createRoute } from "@hono/zod-openapi";
+import { getLogger } from "@logtape/logtape";
+import chalk from "chalk";
+import { z } from "zod";
+
+export const meta = applyConfig({
+ auth: {
+ required: false,
+ },
+ ratelimits: {
+ duration: 60,
+ max: 500,
+ },
+ route: "/messaging",
+});
+
+const route = createRoute({
+ method: "post",
+ path: "/messaging",
+ summary: "Endpoint for the Instance Messaging Versia Extension.",
+ description: "https://versia.pub/extensions/instance-messaging.",
+ request: {
+ body: {
+ content: {
+ "text/plain": {
+ schema: z.string(),
+ },
+ },
+ },
+ },
+ responses: {
+ 200: {
+ description: "Message saved",
+ },
+ },
+});
+
+export default apiRoute((app) =>
+ app.openapi(route, async (context) => {
+ const content = await context.req.text();
+
+ getLogger(["federation", "messaging"])
+ .info`Received message via ${chalk.bold("Instance Messaging")}:\n${content}`;
+
+ return context.newResponse(null, 200);
+ }),
+);
diff --git a/api/well-known/versia.ts b/api/well-known/versia.ts
index dca0d16f..002d29d0 100644
--- a/api/well-known/versia.ts
+++ b/api/well-known/versia.ts
@@ -44,7 +44,10 @@ export default apiRoute((app) =>
{
type: "InstanceMetadata" as const,
compatibility: {
- extensions: ["pub.versia:custom_emojis"],
+ extensions: [
+ "pub.versia:custom_emojis",
+ "pub.versia:instance_messaging",
+ ],
versions: ["0.4.0"],
},
host: new URL(config.http.base_url).host,
@@ -63,6 +66,14 @@ export default apiRoute((app) =>
created_at: new Date(
firstUser?.data.createdAt ?? 0,
).toISOString(),
+ extensions: {
+ "pub.versia:instance_messaging": {
+ endpoint: new URL(
+ "/messaging",
+ config.http.base_url,
+ ).toString(),
+ },
+ },
},
200,
);
diff --git a/utils/loggers.ts b/utils/loggers.ts
index 8c583d05..471797fb 100644
--- a/utils/loggers.ts
+++ b/utils/loggers.ts
@@ -194,6 +194,11 @@ export const configureLoggers = (silent = false): Promise =>
sinks: ["console", "file"],
filters: ["configFilter"],
},
+ {
+ category: ["federation", "messaging"],
+ sinks: ["console", "file"],
+ filters: ["configFilter"],
+ },
{
category: "database",
sinks: ["console", "file"],