summaryrefslogtreecommitdiff
path: root/src/server/web
diff options
context:
space:
mode:
authorAcid Chicken (硫酸鶏) <root@acid-chicken.com>2018-12-21 11:54:39 +0900
committerGitHub <noreply@github.com>2018-12-21 11:54:39 +0900
commit1395cf89cee2916cf5e2a1af52357707222b6afd (patch)
tree556a7d3b384541bf27d8347f09661eb443046aac /src/server/web
parentFix comment (diff)
downloadmisskey-1395cf89cee2916cf5e2a1af52357707222b6afd.tar.gz
misskey-1395cf89cee2916cf5e2a1af52357707222b6afd.tar.bz2
misskey-1395cf89cee2916cf5e2a1af52357707222b6afd.zip
Feed (#3698)
* wip * Implement feed * Update feed.ts * Update index.ts * Update feed.ts
Diffstat (limited to 'src/server/web')
-rw-r--r--src/server/web/feed.ts54
-rw-r--r--src/server/web/index.ts47
2 files changed, 101 insertions, 0 deletions
diff --git a/src/server/web/feed.ts b/src/server/web/feed.ts
new file mode 100644
index 0000000000..09ac10c576
--- /dev/null
+++ b/src/server/web/feed.ts
@@ -0,0 +1,54 @@
+import { Feed } from 'feed';
+import config from '../../config';
+import Note from '../../models/note';
+import { IUser } from '../../models/user';
+import { getOriginalUrl } from '../../misc/get-drive-file-url';
+
+export default async function(user: IUser) {
+ const author: Author = {
+ link: `${config.url}/@${user.username}`,
+ name: user.name || user.username
+ };
+
+ const notes = await Note.find({
+ userId: user._id,
+ renoteId: null,
+ $or: [
+ { visibility: 'public' },
+ { visibility: 'home' }
+ ]
+ }, {
+ sort: { createdAt: -1 },
+ limit: 20
+ });
+
+ const feed = new Feed({
+ id: author.link,
+ title: `${author.name} (@${user.username}@${config.host})`,
+ updated: notes[0].createdAt,
+ generator: 'Misskey',
+ description: `${user.notesCount} Notes, ${user.followingCount} Following, ${user.followersCount} Followers${user.description ? ` · ${user.description}` : ''}`,
+ link: author.link,
+ image: user.avatarUrl,
+ feedLinks: {
+ json: `${author.link}.json`,
+ atom: `${author.link}.atom`,
+ },
+ author
+ } as FeedOptions);
+
+ for (const note of notes) {
+ const file = note._files && note._files.find(file => file.contentType.startsWith('image/'));
+
+ feed.addItem({
+ title: `New note by ${author.name}`,
+ link: `${config.url}/notes/${note._id}`,
+ date: note.createdAt,
+ description: note.cw,
+ content: note.text,
+ image: file && getOriginalUrl(file)
+ });
+ }
+
+ return feed;
+}
diff --git a/src/server/web/index.ts b/src/server/web/index.ts
index 5a5029c7fb..f2a40c01f7 100644
--- a/src/server/web/index.ts
+++ b/src/server/web/index.ts
@@ -10,6 +10,7 @@ import * as favicon from 'koa-favicon';
import * as views from 'koa-views';
import docs from './docs';
+import packFeed from './feed';
import User from '../../models/user';
import parseAcct from '../../misc/acct/parse';
import config from '../../config';
@@ -82,6 +83,52 @@ router.use('/docs', docs.routes());
// URL preview endpoint
router.get('/url', require('./url-preview'));
+const getFeed = async (acct: string) => {
+ const { username, host } = parseAcct(acct);
+ const user = await User.findOne({
+ usernameLower: username.toLowerCase(),
+ host
+ });
+
+ return user && await packFeed(user);
+};
+
+// Atom
+router.get('/@:user.atom', async ctx => {
+ const feed = await getFeed(ctx.params.user);
+
+ if (feed) {
+ ctx.set('Content-Type', 'application/atom+xml; charset=utf-8');
+ ctx.body = feed.atom1();
+ } else {
+ ctx.status = 404;
+ }
+});
+
+// RSS
+router.get('/@:user.rss', async ctx => {
+ const feed = await getFeed(ctx.params.user);
+
+ if (feed) {
+ ctx.set('Content-Type', 'application/rss+xml; charset=utf-8');
+ ctx.body = feed.rss2();
+ } else {
+ ctx.status = 404;
+ }
+});
+
+// JSON
+router.get('/@:user.json', async ctx => {
+ const feed = await getFeed(ctx.params.user);
+
+ if (feed) {
+ ctx.set('Content-Type', 'application/json; charset=utf-8');
+ ctx.body = feed.json1();
+ } else {
+ ctx.status = 404;
+ }
+});
+
//#region for crawlers
// User
router.get('/@:user', async (ctx, next) => {