summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2018-04-07 17:05:14 +0900
committersyuilo <syuilotan@yahoo.co.jp>2018-04-07 17:05:14 +0900
commitc5f23bce7864bc1cffb82b54f62e019c4c04137d (patch)
tree8ec7313f4ec333bcb4ca3e19a5106c602740870c /src
parentRefactor (diff)
downloadsharkey-c5f23bce7864bc1cffb82b54f62e019c4c04137d.tar.gz
sharkey-c5f23bce7864bc1cffb82b54f62e019c4c04137d.tar.bz2
sharkey-c5f23bce7864bc1cffb82b54f62e019c4c04137d.zip
Implement like
Diffstat (limited to 'src')
-rw-r--r--src/remote/activitypub/act/index.ts11
-rw-r--r--src/remote/activitypub/act/like.ts55
-rw-r--r--src/remote/activitypub/renderer/like.ts9
-rw-r--r--src/remote/activitypub/renderer/note.ts4
-rw-r--r--src/remote/activitypub/type.ts7
-rw-r--r--src/server/api/endpoints/posts/reactions/create.ts88
-rw-r--r--src/services/post/reaction/create.ts94
7 files changed, 131 insertions, 137 deletions
diff --git a/src/remote/activitypub/act/index.ts b/src/remote/activitypub/act/index.ts
index 5fcdb61748..45d7bd16a9 100644
--- a/src/remote/activitypub/act/index.ts
+++ b/src/remote/activitypub/act/index.ts
@@ -1,9 +1,10 @@
+import { Object } from '../type';
+import { IRemoteUser } from '../../../models/user';
import create from './create';
import performDeleteActivity from './delete';
import follow from './follow';
import undo from './undo';
-import { Object } from '../type';
-import { IRemoteUser } from '../../../models/user';
+import like from './like';
const self = async (actor: IRemoteUser, activity: Object): Promise<void> => {
switch (activity.type) {
@@ -23,6 +24,10 @@ const self = async (actor: IRemoteUser, activity: Object): Promise<void> => {
// noop
break;
+ case 'Like':
+ await like(actor, activity);
+ break;
+
case 'Undo':
await undo(actor, activity);
break;
@@ -33,7 +38,7 @@ const self = async (actor: IRemoteUser, activity: Object): Promise<void> => {
break;
default:
- console.warn(`unknown activity type: ${activity.type}`);
+ console.warn(`unknown activity type: ${(activity as any).type}`);
return null;
}
};
diff --git a/src/remote/activitypub/act/like.ts b/src/remote/activitypub/act/like.ts
index ea53242017..2f5e3f807d 100644
--- a/src/remote/activitypub/act/like.ts
+++ b/src/remote/activitypub/act/like.ts
@@ -1,10 +1,10 @@
-import { MongoError } from 'mongodb';
-import Reaction, { IPostReaction } from '../../../models/post-reaction';
import Post from '../../../models/post';
-import queue from '../../../queue';
+import { IRemoteUser } from '../../../models/user';
+import { ILike } from '../type';
+import create from '../../../services/post/reaction/create';
-export default async (resolver, actor, activity, distribute) => {
- const id = activity.object.id || activity.object;
+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
@@ -16,48 +16,5 @@ export default async (resolver, actor, activity, distribute) => {
throw new Error();
}
- if (!distribute) {
- const { _id } = await Reaction.findOne({
- userId: actor._id,
- postId: post._id
- });
-
- return {
- resolver,
- object: { $ref: 'postPeactions', $id: _id }
- };
- }
-
- const promisedReaction = Reaction.insert({
- createdAt: new Date(),
- userId: actor._id,
- postId: post._id,
- reaction: 'pudding'
- }).then(reaction => new Promise<IPostReaction>((resolve, reject) => {
- queue.create('http', {
- type: 'reaction',
- reactionId: reaction._id
- }).save(error => {
- if (error) {
- reject(error);
- } else {
- resolve(reaction);
- }
- });
- }), async error => {
- // duplicate key error
- if (error instanceof MongoError && error.code === 11000) {
- return Reaction.findOne({
- userId: actor._id,
- postId: post._id
- });
- }
-
- throw error;
- });
-
- return promisedReaction.then(({ _id }) => ({
- resolver,
- object: { $ref: 'postPeactions', $id: _id }
- }));
+ await create(actor, post, 'pudding');
};
diff --git a/src/remote/activitypub/renderer/like.ts b/src/remote/activitypub/renderer/like.ts
new file mode 100644
index 0000000000..903b10789e
--- /dev/null
+++ b/src/remote/activitypub/renderer/like.ts
@@ -0,0 +1,9 @@
+import config from '../../../config';
+
+export default (user, post) => {
+ return {
+ type: 'Like',
+ actor: `${config.url}/@${user.username}`,
+ object: post.uri ? post.uri : `${config.url}/posts/${post._id}`
+ };
+};
diff --git a/src/remote/activitypub/renderer/note.ts b/src/remote/activitypub/renderer/note.ts
index b971a53951..bbab63db36 100644
--- a/src/remote/activitypub/renderer/note.ts
+++ b/src/remote/activitypub/renderer/note.ts
@@ -23,7 +23,7 @@ export default async (user: IUser, post: IPost) => {
});
if (inReplyToUser !== null) {
- inReplyTo = inReplyToPost.uri || `${config.url}/@${inReplyToUser.username}/${inReplyToPost._id}`;
+ inReplyTo = inReplyToPost.uri || `${config.url}/posts/${inReplyToPost._id}`;
}
}
} else {
@@ -33,7 +33,7 @@ export default async (user: IUser, post: IPost) => {
const attributedTo = `${config.url}/@${user.username}`;
return {
- id: `${attributedTo}/${post._id}`,
+ id: `${config.url}/posts/${post._id}`,
type: 'Note',
attributedTo,
content: post.textHtml,
diff --git a/src/remote/activitypub/type.ts b/src/remote/activitypub/type.ts
index c07b806be8..450d5906d8 100644
--- a/src/remote/activitypub/type.ts
+++ b/src/remote/activitypub/type.ts
@@ -55,6 +55,10 @@ export interface IAccept extends IActivity {
type: 'Accept';
}
+export interface ILike extends IActivity {
+ type: 'Like';
+}
+
export type Object =
ICollection |
IOrderedCollection |
@@ -62,4 +66,5 @@ export type Object =
IDelete |
IUndo |
IFollow |
- IAccept;
+ IAccept |
+ ILike;
diff --git a/src/server/api/endpoints/posts/reactions/create.ts b/src/server/api/endpoints/posts/reactions/create.ts
index f1b0c7dd29..71fa6a2955 100644
--- a/src/server/api/endpoints/posts/reactions/create.ts
+++ b/src/server/api/endpoints/posts/reactions/create.ts
@@ -3,20 +3,11 @@
*/
import $ from 'cafy';
import Reaction from '../../../../../models/post-reaction';
-import Post, { pack as packPost } from '../../../../../models/post';
-import { pack as packUser } from '../../../../../models/user';
-import Watching from '../../../../../models/post-watching';
-import watch from '../../../../../post/watch';
-import { publishPostStream } from '../../../../../publishers/stream';
-import notify from '../../../../../publishers/notify';
-import pushSw from '../../../../../publishers/push-sw';
+import Post from '../../../../../models/post';
+import create from '../../../../../services/post/reaction/create';
/**
* React to a post
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
*/
module.exports = (params, user) => new Promise(async (res, rej) => {
// Get 'postId' parameter
@@ -46,78 +37,11 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
return rej('post not found');
}
- // Myself
- if (post.userId.equals(user._id)) {
- return rej('cannot react to my post');
+ try {
+ await create(user, post, reaction);
+ } catch (e) {
+ rej(e);
}
- // if already reacted
- const exist = await Reaction.findOne({
- postId: post._id,
- userId: user._id,
- deletedAt: { $exists: false }
- });
-
- if (exist !== null) {
- return rej('already reacted');
- }
-
- // Create reaction
- await Reaction.insert({
- createdAt: new Date(),
- postId: post._id,
- userId: user._id,
- reaction: reaction
- });
-
- // Send response
res();
-
- const inc = {};
- inc[`reactionCounts.${reaction}`] = 1;
-
- // Increment reactions count
- await Post.update({ _id: post._id }, {
- $inc: inc
- });
-
- publishPostStream(post._id, 'reacted');
-
- // Notify
- notify(post.userId, user._id, 'reaction', {
- postId: post._id,
- reaction: reaction
- });
-
- pushSw(post.userId, 'reaction', {
- user: await packUser(user, post.userId),
- post: await packPost(post, post.userId),
- reaction: reaction
- });
-
- // Fetch watchers
- Watching
- .find({
- postId: post._id,
- userId: { $ne: user._id },
- // 削除されたドキュメントは除く
- deletedAt: { $exists: false }
- }, {
- fields: {
- userId: true
- }
- })
- .then(watchers => {
- watchers.forEach(watcher => {
- notify(watcher.userId, user._id, 'reaction', {
- postId: post._id,
- reaction: reaction
- });
- });
- });
-
- // この投稿をWatchする
- if (user.account.settings.autoWatch !== false) {
- watch(user._id, post);
- }
});
diff --git a/src/services/post/reaction/create.ts b/src/services/post/reaction/create.ts
index e69de29bb2..c26efcfc75 100644
--- a/src/services/post/reaction/create.ts
+++ b/src/services/post/reaction/create.ts
@@ -0,0 +1,94 @@
+import { IUser, pack as packUser, isLocalUser, isRemoteUser } from '../../../models/user';
+import Post, { IPost, pack as packPost } from '../../../models/post';
+import PostReaction from '../../../models/post-reaction';
+import { publishPostStream } from '../../../publishers/stream';
+import notify from '../../../publishers/notify';
+import pushSw from '../../../publishers/push-sw';
+import PostWatching from '../../../models/post-watching';
+import watch from '../watch';
+import renderLike from '../../../remote/activitypub/renderer/like';
+import { deliver } from '../../../queue';
+import context from '../../../remote/activitypub/renderer/context';
+
+export default async (user: IUser, post: IPost, reaction: string) => new Promise(async (res, rej) => {
+ // Myself
+ if (post.userId.equals(user._id)) {
+ return rej('cannot react to my post');
+ }
+
+ // if already reacted
+ const exist = await PostReaction.findOne({
+ postId: post._id,
+ userId: user._id
+ });
+
+ if (exist !== null) {
+ return rej('already reacted');
+ }
+
+ // Create reaction
+ await PostReaction.insert({
+ createdAt: new Date(),
+ postId: post._id,
+ userId: user._id,
+ reaction
+ });
+
+ res();
+
+ const inc = {};
+ inc[`reactionCounts.${reaction}`] = 1;
+
+ // Increment reactions count
+ await Post.update({ _id: post._id }, {
+ $inc: inc
+ });
+
+ publishPostStream(post._id, 'reacted');
+
+ // Notify
+ notify(post.userId, user._id, 'reaction', {
+ postId: post._id,
+ reaction: reaction
+ });
+
+ pushSw(post.userId, 'reaction', {
+ user: await packUser(user, post.userId),
+ post: await packPost(post, post.userId),
+ reaction: reaction
+ });
+
+ // Fetch watchers
+ PostWatching
+ .find({
+ postId: post._id,
+ userId: { $ne: user._id }
+ }, {
+ fields: {
+ userId: true
+ }
+ })
+ .then(watchers => {
+ watchers.forEach(watcher => {
+ notify(watcher.userId, user._id, 'reaction', {
+ postId: post._id,
+ reaction: reaction
+ });
+ });
+ });
+
+ // ユーザーがローカルユーザーかつ自動ウォッチ設定がオンならばこの投稿をWatchする
+ if (isLocalUser(user) && user.account.settings.autoWatch !== false) {
+ watch(user._id, post);
+ }
+
+ //#region 配信
+ const content = renderLike(user, post);
+ content['@context'] = context;
+
+ // リアクターがローカルユーザーかつリアクション対象がリモートユーザーの投稿なら配送
+ if (isLocalUser(user) && isRemoteUser(post._user)) {
+ deliver(user, content, post._user.account.inbox).save();
+ }
+ //#endregion
+});