summaryrefslogtreecommitdiff
path: root/src/remote
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2018-04-08 06:55:26 +0900
committersyuilo <syuilotan@yahoo.co.jp>2018-04-08 06:55:26 +0900
commit6e34e77372bd74c85ebf5a6b4214c818231dbe8b (patch)
tree614e46573693bb4e0b6d097fde88a52d1cd0fa1f /src/remote
parentFix bug (diff)
downloadmisskey-6e34e77372bd74c85ebf5a6b4214c818231dbe8b.tar.gz
misskey-6e34e77372bd74c85ebf5a6b4214c818231dbe8b.tar.bz2
misskey-6e34e77372bd74c85ebf5a6b4214c818231dbe8b.zip
Implement announce
And bug fixes
Diffstat (limited to 'src/remote')
-rw-r--r--src/remote/activitypub/act/announce/index.ts39
-rw-r--r--src/remote/activitypub/act/announce/note.ts52
-rw-r--r--src/remote/activitypub/act/index.ts5
-rw-r--r--src/remote/activitypub/act/like.ts2
-rw-r--r--src/remote/activitypub/renderer/announce.ts4
-rw-r--r--src/remote/activitypub/renderer/like.ts3
-rw-r--r--src/remote/activitypub/renderer/note.ts8
-rw-r--r--src/remote/activitypub/resolve-person.ts10
-rw-r--r--src/remote/activitypub/resolver.ts7
-rw-r--r--src/remote/activitypub/type.ts15
10 files changed, 135 insertions, 10 deletions
diff --git a/src/remote/activitypub/act/announce/index.ts b/src/remote/activitypub/act/announce/index.ts
new file mode 100644
index 0000000000..c3ac06607d
--- /dev/null
+++ b/src/remote/activitypub/act/announce/index.ts
@@ -0,0 +1,39 @@
+import * as debug from 'debug';
+
+import Resolver from '../../resolver';
+import { IRemoteUser } from '../../../../models/user';
+import announceNote from './note';
+import { IAnnounce } from '../../type';
+
+const log = debug('misskey:activitypub');
+
+export default async (actor: IRemoteUser, activity: IAnnounce): Promise<void> => {
+ if ('actor' in activity && actor.uri !== activity.actor) {
+ throw new Error('invalid actor');
+ }
+
+ const uri = activity.id || activity;
+
+ log(`Announce: ${uri}`);
+
+ const resolver = new Resolver();
+
+ let object;
+
+ try {
+ object = await resolver.resolve(activity.object);
+ } catch (e) {
+ log(`Resolution failed: ${e}`);
+ throw e;
+ }
+
+ switch (object.type) {
+ case 'Note':
+ announceNote(resolver, actor, activity, object);
+ break;
+
+ default:
+ console.warn(`Unknown announce type: ${object.type}`);
+ break;
+ }
+};
diff --git a/src/remote/activitypub/act/announce/note.ts b/src/remote/activitypub/act/announce/note.ts
new file mode 100644
index 0000000000..24d159f184
--- /dev/null
+++ b/src/remote/activitypub/act/announce/note.ts
@@ -0,0 +1,52 @@
+import * as debug from 'debug';
+
+import Resolver from '../../resolver';
+import Note from '../../../../models/note';
+import post from '../../../../services/note/create';
+import { IRemoteUser, isRemoteUser } from '../../../../models/user';
+import { IAnnounce, INote } from '../../type';
+import createNote from '../create/note';
+import resolvePerson from '../../resolve-person';
+
+const log = debug('misskey:activitypub');
+
+/**
+ * アナウンスアクティビティを捌きます
+ */
+export default async function(resolver: Resolver, actor: IRemoteUser, activity: IAnnounce, note: INote): Promise<void> {
+ const uri = activity.id || activity;
+
+ if (typeof uri !== 'string') {
+ throw new Error('invalid announce');
+ }
+
+ // 既に同じURIを持つものが登録されていないかチェック
+ const exist = await Note.findOne({ uri });
+ if (exist) {
+ return;
+ }
+
+ // アナウンス元の投稿の投稿者をフェッチ
+ const announcee = await resolvePerson(note.attributedTo);
+
+ const renote = isRemoteUser(announcee)
+ ? await createNote(resolver, announcee, note, true)
+ : await Note.findOne({ _id: note.id.split('/').pop() });
+
+ log(`Creating the (Re)Note: ${uri}`);
+
+ //#region Visibility
+ let visibility = 'public';
+ if (!activity.to.includes('https://www.w3.org/ns/activitystreams#Public')) visibility = 'unlisted';
+ if (activity.cc.length == 0) visibility = 'private';
+ // TODO
+ if (visibility != 'public') throw new Error('unspported visibility');
+ //#endergion
+
+ await post(actor, {
+ createdAt: new Date(activity.published),
+ renote,
+ visibility,
+ uri
+ });
+}
diff --git a/src/remote/activitypub/act/index.ts b/src/remote/activitypub/act/index.ts
index 45d7bd16a9..15ea9494ae 100644
--- a/src/remote/activitypub/act/index.ts
+++ b/src/remote/activitypub/act/index.ts
@@ -5,6 +5,7 @@ import performDeleteActivity from './delete';
import follow from './follow';
import undo from './undo';
import like from './like';
+import announce from './announce';
const self = async (actor: IRemoteUser, activity: Object): Promise<void> => {
switch (activity.type) {
@@ -24,6 +25,10 @@ const self = async (actor: IRemoteUser, activity: Object): Promise<void> => {
// noop
break;
+ case 'Announce':
+ await announce(actor, activity);
+ break;
+
case 'Like':
await like(actor, activity);
break;
diff --git a/src/remote/activitypub/act/like.ts b/src/remote/activitypub/act/like.ts
index a3243948ba..4941608588 100644
--- a/src/remote/activitypub/act/like.ts
+++ b/src/remote/activitypub/act/like.ts
@@ -7,7 +7,7 @@ export default async (actor: IRemoteUser, activity: ILike) => {
const id = typeof activity.object == 'string' ? activity.object : activity.object.id;
// Transform:
- // https://misskey.ex/@syuilo/xxxx to
+ // https://misskey.ex/notes/xxxx to
// xxxx
const noteId = id.split('/').pop();
diff --git a/src/remote/activitypub/renderer/announce.ts b/src/remote/activitypub/renderer/announce.ts
new file mode 100644
index 0000000000..8e4b3d26a6
--- /dev/null
+++ b/src/remote/activitypub/renderer/announce.ts
@@ -0,0 +1,4 @@
+export default object => ({
+ type: 'Announce',
+ object
+});
diff --git a/src/remote/activitypub/renderer/like.ts b/src/remote/activitypub/renderer/like.ts
index fe36c7094d..744896cc41 100644
--- a/src/remote/activitypub/renderer/like.ts
+++ b/src/remote/activitypub/renderer/like.ts
@@ -1,6 +1,7 @@
import config from '../../../config';
+import { ILocalUser } from '../../../models/user';
-export default (user, note) => {
+export default (user: ILocalUser, note) => {
return {
type: 'Like',
actor: `${config.url}/@${user.username}`,
diff --git a/src/remote/activitypub/renderer/note.ts b/src/remote/activitypub/renderer/note.ts
index 244aecf6a3..48799af084 100644
--- a/src/remote/activitypub/renderer/note.ts
+++ b/src/remote/activitypub/renderer/note.ts
@@ -3,9 +3,9 @@ import renderHashtag from './hashtag';
import config from '../../../config';
import DriveFile from '../../../models/drive-file';
import Note, { INote } from '../../../models/note';
-import User, { IUser } from '../../../models/user';
+import User from '../../../models/user';
-export default async (user: IUser, note: INote) => {
+export default async (note: INote) => {
const promisedFiles = note.mediaIds
? DriveFile.find({ _id: { $in: note.mediaIds } })
: Promise.resolve([]);
@@ -30,6 +30,10 @@ export default async (user: IUser, note: INote) => {
inReplyTo = null;
}
+ const user = await User.findOne({
+ _id: note.userId
+ });
+
const attributedTo = `${config.url}/@${user.username}`;
return {
diff --git a/src/remote/activitypub/resolve-person.ts b/src/remote/activitypub/resolve-person.ts
index ddb8d68715..7d7989a01f 100644
--- a/src/remote/activitypub/resolve-person.ts
+++ b/src/remote/activitypub/resolve-person.ts
@@ -2,18 +2,18 @@ import { JSDOM } from 'jsdom';
import { toUnicode } from 'punycode';
import parseAcct from '../../acct/parse';
import config from '../../config';
-import User, { validateUsername, isValidName, isValidDescription } from '../../models/user';
+import User, { validateUsername, isValidName, isValidDescription, IUser } from '../../models/user';
import webFinger from '../webfinger';
import Resolver from './resolver';
import uploadFromUrl from '../../services/drive/upload-from-url';
-import { isCollectionOrOrderedCollection } from './type';
+import { isCollectionOrOrderedCollection, IObject } from './type';
-export default async (value, verifier?: string) => {
- const id = value.id || value;
+export default async (value: string | IObject, verifier?: string): Promise<IUser> => {
+ const id = typeof value == 'string' ? value : value.id;
const localPrefix = config.url + '/@';
if (id.startsWith(localPrefix)) {
- return User.findOne(parseAcct(id.slice(localPrefix)));
+ return await User.findOne(parseAcct(id.substr(localPrefix.length)));
}
const resolver = new Resolver();
diff --git a/src/remote/activitypub/resolver.ts b/src/remote/activitypub/resolver.ts
index 4a97e2ef66..1466139c48 100644
--- a/src/remote/activitypub/resolver.ts
+++ b/src/remote/activitypub/resolver.ts
@@ -1,6 +1,7 @@
import * as request from 'request-promise-native';
import * as debug from 'debug';
import { IObject } from './type';
+//import config from '../../config';
const log = debug('misskey:activitypub:resolver');
@@ -47,6 +48,11 @@ export default class Resolver {
this.history.add(value);
+ //#region resolve local objects
+ // TODO
+ //if (value.startsWith(`${config.url}/@`)) {
+ //#endregion
+
const object = await request({
url: value,
headers: {
@@ -60,6 +66,7 @@ export default class Resolver {
!object['@context'].includes('https://www.w3.org/ns/activitystreams') :
object['@context'] !== 'https://www.w3.org/ns/activitystreams'
)) {
+ log(`invalid response: ${JSON.stringify(object, null, 2)}`);
throw new Error('invalid response');
}
diff --git a/src/remote/activitypub/type.ts b/src/remote/activitypub/type.ts
index 450d5906d8..2335517645 100644
--- a/src/remote/activitypub/type.ts
+++ b/src/remote/activitypub/type.ts
@@ -5,6 +5,10 @@ export interface IObject {
type: string;
id?: string;
summary?: string;
+ published?: string;
+ cc?: string[];
+ to?: string[];
+ attributedTo: string;
}
export interface IActivity extends IObject {
@@ -26,6 +30,10 @@ export interface IOrderedCollection extends IObject {
orderedItems: IObject | string | IObject[] | string[];
}
+export interface INote extends IObject {
+ type: 'Note';
+}
+
export const isCollection = (object: IObject): object is ICollection =>
object.type === 'Collection';
@@ -59,6 +67,10 @@ export interface ILike extends IActivity {
type: 'Like';
}
+export interface IAnnounce extends IActivity {
+ type: 'Announce';
+}
+
export type Object =
ICollection |
IOrderedCollection |
@@ -67,4 +79,5 @@ export type Object =
IUndo |
IFollow |
IAccept |
- ILike;
+ ILike |
+ IAnnounce;