1
0
mirror of https://github.com/spacebarchat/server.git synced 2024-11-22 02:12:40 +01:00
This commit is contained in:
Madeline 2023-08-15 00:04:57 +10:00
parent cb2c2f244f
commit ff7f520ca3
No known key found for this signature in database
GPG Key ID: 1958E017C36F2E47
4 changed files with 119 additions and 3 deletions

34
scripts/ap/get.js Normal file
View File

@ -0,0 +1,34 @@
const nodeFetch = require("node-fetch");
const fetch = (url, opts) =>
nodeFetch(url, {
...opts,
headers: {
Accept: "application/activity+json",
...(opts?.headers || {}),
},
}).then((x) => x.json());
const webfinger = async (domain, user) => {
const query = `https://${domain}/.well-known/webfinger?resource=@${user}@${domain}`;
const json = await fetch(query);
return json.links.find((x) => x.rel == "self").href;
};
(async () => {
const userLocation = await webfinger(
"chat.understars.dev",
"1140599542186631381",
);
console.log(userLocation);
const user = await fetch(userLocation);
const outbox = await fetch(user.outbox);
const firstPage = await fetch(outbox.first);
const mostRecent = firstPage.orderedItems[0];
console.log(mostRecent);
})();

View File

@ -1,9 +1,22 @@
import { route } from "@spacebar/api";
import { Message, emitEvent } from "@spacebar/util";
import { Router } from "express";
import { HTTPError } from "lambert-server";
const router = Router();
export default router;
router.post("/", route({}), async (req, res) => {
console.log(req.body);
const body = req.body;
if (body.type != "Create") throw new HTTPError("not implemented");
const message = await Message.fromAP(body);
await message.save();
await emitEvent({
event: "MESSAGE_CREATE",
channel_id: message.channel_id,
data: message.toJSON(),
});
});

View File

@ -16,7 +16,13 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import type { APAnnounce, APNote } from "activitypub-types";
import type {
APAnnounce,
APNote,
APPerson,
AnyAPObject,
} from "activitypub-types";
import fetch from "node-fetch";
import {
Column,
CreateDateColumn,
@ -29,7 +35,7 @@ import {
OneToMany,
RelationId,
} from "typeorm";
import { Config } from "..";
import { Config, Snowflake } from "..";
import { InteractionType } from "../interfaces/Interaction";
import { Application } from "./Application";
import { Attachment } from "./Attachment";
@ -269,6 +275,54 @@ export class Message extends BaseClass {
content: this.content,
};
}
static async fromAP(data: APNote): Promise<Message> {
if (!data.attributedTo)
throw new Error("sb Message must have author (attributedTo)");
let attrib = Array.isArray(data.attributedTo)
? data.attributedTo[0]
: data.attributedTo;
if (typeof attrib == "string") {
// fetch it
attrib = (await fetch(attrib).then((x) => x.json())) as AnyAPObject;
}
if (attrib.type != "Person")
throw new Error("only Person can be author of sb Message"); //hm
let to = data.to;
if (Array.isArray(to))
to = to.filter((x) => {
if (typeof x == "string") return x.includes("channel");
return false;
});
if (!to) throw new Error("not deliverable");
const channel_id = (to as string).split("/").reverse()[0];
const channel = await Channel.findOneOrFail({
where: { id: channel_id },
relations: { guild: true },
});
return Message.create({
id: Snowflake.generate(),
author: await User.fromAP(attrib as APPerson),
content: data.content, // convert html to markdown
timestamp: data.published,
channel_id,
sticker_items: [],
guild_id: channel.guild_id,
attachments: [],
embeds: [],
reactions: [],
type: 0,
});
}
}
export interface MessageComponent {

View File

@ -37,6 +37,7 @@ import { Session } from "./Session";
import { UserSettings } from "./UserSettings";
import crypto from "crypto";
import fetch from "node-fetch";
import { promisify } from "util";
const generateKeyPair = promisify(crypto.generateKeyPair);
@ -322,6 +323,20 @@ export class User extends BaseClass {
};
}
static async fromAP(data: APPerson | string): Promise<User> {
if (typeof data == "string") {
data = (await fetch(data, {
headers: { Accept: "application/activity+json" },
}).then((x) => x.json())) as APPerson;
}
return User.create({
id: Snowflake.generate(), // hm
username: data.preferredUsername,
bio: data.summary, // TODO: convert to markdown
});
}
static async getPublicUser(user_id: string, opts?: FindOneOptions<User>) {
return await User.findOneOrFail({
where: { id: user_id },