From ba680211ca2e71be2dcf3dd7bd9a265f621ab77a Mon Sep 17 00:00:00 2001 From: CGsama Date: Sat, 1 Jul 2023 23:58:36 -0400 Subject: [PATCH 001/279] Embedded all attachment, renotes and discussion history into rss feed content & improve title, and not generate feed for locked account --- packages/backend/src/server/web/feed.ts | 111 ++++++++++++++++++----- packages/backend/src/server/web/index.ts | 28 ++++-- 2 files changed, 106 insertions(+), 33 deletions(-) diff --git a/packages/backend/src/server/web/feed.ts b/packages/backend/src/server/web/feed.ts index 9cbeb28ae1..1d24345024 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 += `