diff options
| author | Akihiko Odaki <nekomanma@pixiv.co.jp> | 2018-04-01 19:43:26 +0900 |
|---|---|---|
| committer | Akihiko Odaki <nekomanma@pixiv.co.jp> | 2018-04-01 23:30:57 +0900 |
| commit | dc529711ced031155f53fa321159ec2830ef8b05 (patch) | |
| tree | 7a677cd11deab9a3026e7fc30f57556398901083 /src/processor/http | |
| parent | Implement account public key endpoint (diff) | |
| download | sharkey-dc529711ced031155f53fa321159ec2830ef8b05.tar.gz sharkey-dc529711ced031155f53fa321159ec2830ef8b05.tar.bz2 sharkey-dc529711ced031155f53fa321159ec2830ef8b05.zip | |
Implement remote follow
Diffstat (limited to 'src/processor/http')
| -rw-r--r-- | src/processor/http/follow.ts | 89 | ||||
| -rw-r--r-- | src/processor/http/index.ts | 2 |
2 files changed, 91 insertions, 0 deletions
diff --git a/src/processor/http/follow.ts b/src/processor/http/follow.ts new file mode 100644 index 0000000000..adaa2f3f65 --- /dev/null +++ b/src/processor/http/follow.ts @@ -0,0 +1,89 @@ +import { request } from 'https'; +import { sign } from 'http-signature'; +import { URL } from 'url'; +import User, { ILocalAccount, IRemoteAccount, pack as packUser } from '../../models/user'; +import Following from '../../models/following'; +import event from '../../common/event'; +import notify from '../../common/notify'; +import context from '../../common/remote/activitypub/renderer/context'; +import render from '../../common/remote/activitypub/renderer/follow'; +import config from '../../conf'; + +export default ({ data }, done) => Following.findOne({ _id: data.following }).then(({ followerId, followeeId }) => { + const promisedFollower = User.findOne({ _id: followerId }); + const promisedFollowee = User.findOne({ _id: followeeId }); + + return Promise.all([ + // Increment following count + User.update(followerId, { + $inc: { + followingCount: 1 + } + }), + + // Increment followers count + User.update({ _id: followeeId }, { + $inc: { + followersCount: 1 + } + }), + + // Notify + promisedFollowee.then(followee => followee.host === null ? + notify(followeeId, followerId, 'follow') : null), + + // Publish follow event + Promise.all([promisedFollower, promisedFollowee]).then(([follower, followee]) => { + const followerEvent = packUser(followee, follower) + .then(packed => event(follower._id, 'follow', packed)); + let followeeEvent; + + if (followee.host === null) { + followeeEvent = packUser(follower, followee) + .then(packed => event(followee._id, 'followed', packed)); + } else { + followeeEvent = new Promise((resolve, reject) => { + const { + protocol, + hostname, + port, + pathname, + search + } = new URL(followee.account as IRemoteAccount).inbox); + + const req = request({ + protocol, + hostname, + port, + method: 'POST', + path: pathname + search, + }, res => { + res.on('close', () => { + if (res.statusCode >= 200 && res.statusCode < 300) { + resolve(); + } else { + reject(res); + } + }); + + res.on('data', () => {}); + res.on('error', reject); + }); + + sign(req, { + authorizationHeaderName: 'Signature', + key: (follower.account as ILocalAccount).keypair, + keyId: `acct:${follower.username}@${config.host}` + }); + + const rendered = render(follower, followee); + rendered['@context'] = context; + + req.end(JSON.stringify(rendered)); + }); + } + + return Promise.all([followerEvent, followeeEvent]); + }) + ]); +}).then(done, done); diff --git a/src/processor/http/index.ts b/src/processor/http/index.ts index da942ad2a1..a001cf11f7 100644 --- a/src/processor/http/index.ts +++ b/src/processor/http/index.ts @@ -1,7 +1,9 @@ +import follow from './follow'; import performActivityPub from './perform-activitypub'; import reportGitHubFailure from './report-github-failure'; const handlers = { + follow, performActivityPub, reportGitHubFailure, }; |