mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 16:38:19 +01:00
Add user outbox
This commit is contained in:
parent
ed96e11301
commit
6d77c8edc7
|
|
@ -11,7 +11,6 @@ export default async (
|
||||||
req: Request,
|
req: Request,
|
||||||
matchedRoute: MatchedRoute
|
matchedRoute: MatchedRoute
|
||||||
): Promise<Response> => {
|
): Promise<Response> => {
|
||||||
// In the format acct:name@example.com
|
|
||||||
const username = matchedRoute.params.username;
|
const username = matchedRoute.params.username;
|
||||||
|
|
||||||
const user = await User.findOneBy({ username });
|
const user = await User.findOneBy({ username });
|
||||||
|
|
@ -28,9 +27,17 @@ export default async (
|
||||||
],
|
],
|
||||||
id: `${getHost()}/@${user.username}/actor`,
|
id: `${getHost()}/@${user.username}/actor`,
|
||||||
type: "Person",
|
type: "Person",
|
||||||
preferredUsername: user.username,
|
preferredUsername: user.username, // TODO: Add user display name
|
||||||
|
name: user.username,
|
||||||
summary: user.bio,
|
summary: user.bio,
|
||||||
|
icon: [
|
||||||
|
// TODO: Add user avatar
|
||||||
|
],
|
||||||
inbox: `${getHost()}/@${user.username}/inbox`,
|
inbox: `${getHost()}/@${user.username}/inbox`,
|
||||||
|
outbox: `${getHost()}/@${user.username}/outbox`,
|
||||||
|
followers: `${getHost()}/@${user.username}/followers`,
|
||||||
|
following: `${getHost()}/@${user.username}/following`,
|
||||||
|
liked: `${getHost()}/@${user.username}/liked`,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
import { errorResponse, jsonResponse } from "@response";
|
|
||||||
import { MatchedRoute } from "bun";
|
|
||||||
import { User } from "~database/entities/User";
|
|
||||||
import { getHost } from "@config";
|
|
||||||
import { compact } from "jsonld";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ActivityPub user actor endpoinmt
|
|
||||||
*/
|
|
||||||
export default async (
|
|
||||||
req: Request,
|
|
||||||
matchedRoute: MatchedRoute
|
|
||||||
): Promise<Response> => {
|
|
||||||
// In the format acct:name@example.com
|
|
||||||
const username = matchedRoute.params.username;
|
|
||||||
|
|
||||||
const user = await User.findOneBy({ username });
|
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
return errorResponse("User not found", 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
return jsonResponse({
|
|
||||||
|
|
||||||
})
|
|
||||||
};
|
|
||||||
132
server/api/@[username]/outbox.json/index.ts
Normal file
132
server/api/@[username]/outbox.json/index.ts
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
import { errorResponse, jsonResponse } from "@response";
|
||||||
|
import { MatchedRoute } from "bun";
|
||||||
|
import { User } from "~database/entities/User";
|
||||||
|
import { getHost } from "@config";
|
||||||
|
import { NodeObject, compact } from "jsonld";
|
||||||
|
import { RawObject } from "~database/entities/RawObject";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ActivityPub user inbox endpoint
|
||||||
|
*/
|
||||||
|
export default async (
|
||||||
|
req: Request,
|
||||||
|
matchedRoute: MatchedRoute
|
||||||
|
): Promise<Response> => {
|
||||||
|
// Check if POST request
|
||||||
|
if (req.method !== "POST") {
|
||||||
|
return errorResponse("Method not allowed", 405);
|
||||||
|
}
|
||||||
|
|
||||||
|
const username = matchedRoute.params.username;
|
||||||
|
const page = Boolean(matchedRoute.query.page || "false");
|
||||||
|
const min_id = matchedRoute.query.min_id || false;
|
||||||
|
const max_id = matchedRoute.query.max_id || false;
|
||||||
|
|
||||||
|
const user = await User.findOneBy({ username });
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return errorResponse("User not found", 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the user's corresponding ActivityPub notes
|
||||||
|
const count = await RawObject.count({
|
||||||
|
where: {
|
||||||
|
data: {
|
||||||
|
attributedTo: `${getHost()}/@${user.username}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
order: {
|
||||||
|
data: {
|
||||||
|
published: "DESC",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const lastPost = (await RawObject.find({
|
||||||
|
where: {
|
||||||
|
data: {
|
||||||
|
attributedTo: `${getHost()}/@${user.username}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
order: {
|
||||||
|
data: {
|
||||||
|
published: "ASC",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
take: 1,
|
||||||
|
}))[0];
|
||||||
|
|
||||||
|
if (!page)
|
||||||
|
return jsonResponse(
|
||||||
|
await compact({
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://w3id.org/security/v1",
|
||||||
|
],
|
||||||
|
id: `${getHost()}/@${user.username}/inbox`,
|
||||||
|
type: "OrderedCollection",
|
||||||
|
totalItems: count,
|
||||||
|
first: `${getHost()}/@${user.username}/outbox?page=true`,
|
||||||
|
last: `${getHost()}/@${
|
||||||
|
user.username
|
||||||
|
}/outbox?min_id=${lastPost.id}&page=true`,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
else {
|
||||||
|
let posts: RawObject[] = []
|
||||||
|
|
||||||
|
if (min_id) {
|
||||||
|
posts = await RawObject.find({
|
||||||
|
where: {
|
||||||
|
data: {
|
||||||
|
attributedTo: `${getHost()}/@${user.username}`,
|
||||||
|
id: min_id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
order: {
|
||||||
|
data: {
|
||||||
|
published: "DESC",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
take: 11, // Take one extra to have the ID of the next post
|
||||||
|
});
|
||||||
|
} else if (max_id) {
|
||||||
|
posts = await RawObject.find({
|
||||||
|
where: {
|
||||||
|
data: {
|
||||||
|
attributedTo: `${getHost()}/@${user.username}`,
|
||||||
|
id: max_id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
order: {
|
||||||
|
data: {
|
||||||
|
published: "ASC",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
take: 10,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return jsonResponse(await compact({
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://w3id.org/security/v1",
|
||||||
|
],
|
||||||
|
id: `${getHost()}/@${user.username}/inbox`,
|
||||||
|
type: "OrderedCollectionPage",
|
||||||
|
totalItems: count,
|
||||||
|
partOf: `${getHost()}/@${user.username}/inbox`,
|
||||||
|
// Next is less recent posts chronologically, uses min_id
|
||||||
|
next: `${getHost()}/@${user.username}/outbox?min_id=${
|
||||||
|
posts[posts.length - 1].id
|
||||||
|
}&page=true`,
|
||||||
|
// Prev is more recent posts chronologically, uses max_id
|
||||||
|
prev: `${getHost()}/@${user.username}/outbox?max_id=${
|
||||||
|
posts[0].id
|
||||||
|
}&page=true`,
|
||||||
|
orderedItems: posts.slice(0, 10).map(post => post.data) as NodeObject[]
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Reference in a new issue