diff --git a/src/remote/activitypub/renderer/announce.ts b/src/remote/activitypub/renderer/announce.ts index f6276ade0..18e23cc33 100644 --- a/src/remote/activitypub/renderer/announce.ts +++ b/src/remote/activitypub/renderer/announce.ts @@ -5,7 +5,7 @@ export default (object: any, note: INote) => { const attributedTo = `${config.url}/users/${note.userId}`; return { - id: `${config.url}/notes/${note._id}`, + id: `${config.url}/notes/${note._id}/activity`, actor: `${config.url}/users/${note.userId}`, type: 'Announce', published: note.createdAt.toISOString(), diff --git a/src/server/activitypub.ts b/src/server/activitypub.ts index f04f9e91e..3d346693d 100644 --- a/src/server/activitypub.ts +++ b/src/server/activitypub.ts @@ -10,7 +10,7 @@ import User, { isLocalUser, ILocalUser, IUser } from '../models/user'; import renderNote from '../remote/activitypub/renderer/note'; import renderKey from '../remote/activitypub/renderer/key'; import renderPerson from '../remote/activitypub/renderer/person'; -import Outbox from './activitypub/outbox'; +import Outbox, { packActivity } from './activitypub/outbox'; import Followers from './activitypub/followers'; import Following from './activitypub/following'; @@ -77,6 +77,22 @@ router.get('/notes/:note', async (ctx, next) => { setResponseType(ctx); }); +// note activity +router.get('/notes/:note/activity', async ctx => { + const note = await Note.findOne({ + _id: new mongo.ObjectID(ctx.params.note), + visibility: { $in: ['public', 'home'] } + }); + + if (note === null) { + ctx.status = 404; + return; + } + + ctx.body = pack(await packActivity(note)); + setResponseType(ctx); +}); + // outbox router.get('/users/:user/outbox', Outbox); diff --git a/src/server/activitypub/outbox.ts b/src/server/activitypub/outbox.ts index a5e762eea..9a4c88177 100644 --- a/src/server/activitypub/outbox.ts +++ b/src/server/activitypub/outbox.ts @@ -8,8 +8,10 @@ import renderOrderedCollection from '../../remote/activitypub/renderer/ordered-c import renderOrderedCollectionPage from '../../remote/activitypub/renderer/ordered-collection-page'; import { setResponseType } from '../activitypub'; -import Note from '../../models/note'; +import Note, { INote } from '../../models/note'; import renderNote from '../../remote/activitypub/renderer/note'; +import renderCreate from '../../remote/activitypub/renderer/create'; +import renderAnnounce from '../../remote/activitypub/renderer/announce'; import { countIf } from '../../prelude/array'; export default async (ctx: Router.IRouterContext) => { @@ -53,15 +55,7 @@ export default async (ctx: Router.IRouterContext) => { const query = { userId: user._id, - $and: [{ - $or: [ { visibility: 'public' }, { visibility: 'home' } ] - }, { // exclude renote, but include quote - $or: [{ - text: { $ne: null } - }, { - fileIds: { $ne: [] } - }] - }] + visibility: { $in: ['public', 'home'] } } as any; if (sinceId) { @@ -85,10 +79,10 @@ export default async (ctx: Router.IRouterContext) => { if (sinceId) notes.reverse(); - const renderedNotes = await Promise.all(notes.map(note => renderNote(note, false))); + const activities = await Promise.all(notes.map(note => packActivity(note))); const rendered = renderOrderedCollectionPage( `${partOf}?page=true${sinceId ? `&since_id=${sinceId}` : ''}${untilId ? `&until_id=${untilId}` : ''}`, - user.notesCount, renderedNotes, partOf, + user.notesCount, activities, partOf, notes.length > 0 ? `${partOf}?page=true&since_id=${notes[0]._id}` : null, notes.length > 0 ? `${partOf}?page=true&until_id=${notes[notes.length - 1]._id}` : null ); @@ -105,3 +99,16 @@ export default async (ctx: Router.IRouterContext) => { setResponseType(ctx); } }; + +/** + * Pack Create or Announce Activity + * @param note Note + */ +export async function packActivity(note: INote): Promise { + if (note.renoteId && note.text == null) { + const renote = await Note.findOne(note.renoteId); + return renderAnnounce(renote.uri ? renote.uri : `${config.url}/notes/${renote._id}`, note); + } + + return renderCreate(await renderNote(note, false), note); +}