diff --git a/packages/backend/src/server/web/feed.ts b/packages/backend/src/server/web/feed.ts
index 9cbeb28ae..1d2434502 100644
--- a/packages/backend/src/server/web/feed.ts
+++ b/packages/backend/src/server/web/feed.ts
@@ -4,34 +4,40 @@ import config from "@/config/index.js";
import type { User } from "@/models/entities/user.js";
import { Notes, DriveFiles, UserProfiles, Users } from "@/models/index.js";
-export default async function (user: User) {
+export default async function (user: User, threadDepth = 5, history = 20, noteintitle = false, renotes = true, replies = true) {
const author = {
link: `${config.url}/@${user.username}`,
- name: user.name || user.username,
+ email: `${user.username}@${config.host}`,
+ name: user.name || user.username
};
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
+ const searchCriteria = {
+ userId: user.id,
+ visibility: In(['public', 'home']),
+ };
+
+ if (!renotes) {
+ searchCriteria.renoteId = IsNull();
+ }
+
+ if (!replies) {
+ searchCriteria.replyId = IsNull();
+ }
+
const notes = await Notes.find({
- where: {
- userId: user.id,
- renoteId: IsNull(),
- visibility: In(["public", "home"]),
- },
+ where: searchCriteria,
order: { createdAt: -1 },
- take: 20,
+ take: history,
});
const feed = new Feed({
id: author.link,
title: `${author.name} (@${user.username}@${config.host})`,
updated: notes[0].createdAt,
- generator: "Calckey",
- description: `${user.notesCount} Notes, ${
- profile.ffVisibility === "public" ? user.followingCount : "?"
- } Following, ${
- profile.ffVisibility === "public" ? user.followersCount : "?"
- } Followers${profile.description ? ` · ${profile.description}` : ""}`,
+ generator: 'Calckey',
+ description: `${user.notesCount} Notes, ${profile.ffVisibility === 'public' ? user.followingCount : '?'} Following, ${profile.ffVisibility === 'public' ? user.followersCount : '?'} Followers${profile.description ? ` · ${profile.description}` : ''}`,
link: author.link,
image: await Users.getAvatarUrl(user),
feedLinks: {
@@ -43,23 +49,78 @@ export default async function (user: User) {
});
for (const note of notes) {
- const files =
- note.fileIds.length > 0
- ? await DriveFiles.findBy({
- id: In(note.fileIds),
- })
- : [];
- const file = files.find((file) => file.type.startsWith("image/"));
+ let contentStr = await noteToString(note, true);
+ let next = note.renoteId ? note.renoteId : note.replyId;
+ let depth = threadDepth;
+ while (depth > 0 && next) {
+ const finding = await findById(next);
+ contentStr += finding.text;
+ next = finding.next;
+ depth -= 1;
+ }
+
+ let title = `${author.name} `;
+ if (note.renoteId) {
+ title += 'renotes';
+ } else if (note.replyId) {
+ title += 'replies';
+ } else {
+ title += 'says';
+ }
+ if (noteintitle) {
+ const content = note.cw ?? note.text;
+ if (content) {
+ title += `: ${content}`;
+ } else {
+ title += 'something';
+ }
+ }
feed.addItem({
- title: `New note by ${author.name}`,
+ title: title.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, '').substring(0,100),
link: `${config.url}/notes/${note.id}`,
date: note.createdAt,
- description: note.cw || undefined,
- content: note.text || undefined,
- image: file ? DriveFiles.getPublicUrl(file) || undefined : undefined,
+ description: note.cw ? note.cw.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, '') : undefined,
+ content: contentStr.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, '')
});
}
+ async function noteToString (note, isTheNote = false) {
+ const author = isTheNote ? null : await Users.findOneBy({ id: note.userId });
+ let outstr = author ? `${author.name}(@${author.username}@${author.host ? author.host : config.host}) ${(note.renoteId ? 'renotes' : (note.replyId ? 'replies' : 'says'))}:
` : '';
+ const files = note.fileIds.length > 0 ? await DriveFiles.findBy({
+ id: In(note.fileIds),
+ }) : [];
+ let fileEle = '';
+ for (const file of files) {
+ if (file.type.startsWith('image/')) {
+ fileEle += `
`;
+ } else if (file.type.startsWith('audio/')) {
+ fileEle += `