UNPKG

social-butterfly

Version:

Incorporate federated social network protocols easily. Used with Hello, world federated blog.

145 lines (109 loc) 4.78 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _activitystreams = require("./activitystreams"); var _cheerio = _interopRequireDefault(require("cheerio")); var _draftJs = require("draft-js"); var _email = require("./email"); var _url_factory = require("./util/url_factory"); var _nodeFetch = _interopRequireDefault(require("node-fetch")); var _crawler = require("./util/crawler"); var _webmention = require("./webmention"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var _default = options => async function syndicate(req, contentOwner, localContent, opt_remoteContent, opt_isComment) { if (localContent.hidden) { return; } await webSubPush(req, options, localContent); await parseMentions(req, options, contentOwner, localContent, opt_remoteContent); if (opt_isComment) { const localContentUser = await options.getLocalUser(localContent.url, req); (0, _email.comment)(req, opt_remoteContent.username, opt_remoteContent.comment_user, localContentUser.email, localContent.url, opt_remoteContent); } }; exports.default = _default; function findMentionsInDraftJS(draftJsContent) { const contentState = (0, _draftJs.convertFromRaw)(JSON.parse(draftJsContent)); return Object.keys(contentState.entityMap).map(key => contentState.getEntity(contentState.entityMap[key])).filter(entity => entity.type === 'mention' || entity.type === 'rsvp').map(entity => entity.data.mention.link); } async function parseMentions(req, options, contentOwner, content, opt_remoteContent) { const remoteUsers = []; const mentionedRemoteUsers = []; async function addToUsersList(userRemote, threadUrl, shouldAddToMentions) { if (!userRemote && threadUrl) { const webpage = await (0, _crawler.fetchText)(threadUrl); const $ = _cheerio.default.load(webpage); let webmention_url = $('link[rel="webmention"]').attr('href'); webmention_url = (0, _url_factory.ensureAbsoluteUrl)(threadUrl, webmention_url); // TODO(mime): pretty funky smell. refactor. if (webmention_url) { userRemote = { webmention_url }; } } if (!userRemote || remoteUsers.find(el => el.profile_url === userRemote.profile_url)) { return; } if (userRemote.salmon_url || userRemote.activitypub_inbox_url || userRemote.webmention_url) { remoteUsers.push(userRemote); shouldAddToMentions && mentionedRemoteUsers.push(userRemote); } } // Add user from original thread as mentioned user. if (content.thread) { const threadContent = await options.getRemoteContent(content.username, content.thread); let threadUserRemote; if (threadContent) { threadUserRemote = await options.getRemoteUser(content.username, threadContent.from_user); } await addToUsersList(threadUserRemote, content.thread, true); } // Find mentions in the text. // TODO(mime): support @blah@blah.com const mentions = content.content && findMentionsInDraftJS(content.content) || []; for (const mention of mentions) { const userRemote = await options.getRemoteUser(content.username, mention); await addToUsersList(userRemote, undefined /* threadUrl */ , true); } // Find all users from the comments. if (content.comments_count) { const comments = await options.getRemoteCommentsOnLocalContent(content.url); for (const comment of comments) { const userRemote = await options.getRemoteUser(content.username, comment.from_user); await addToUsersList(userRemote, undefined /* threadUrl */ , false); } } if (opt_remoteContent) { // Find mentions in the comment text. // TODO(mime): support @blah@blah.com const mentions = opt_remoteContent.content && findMentionsInDraftJS(opt_remoteContent.content) || []; for (const mention of mentions) { const userRemote = await options.getRemoteUser(content.username, mention); await addToUsersList(userRemote, undefined /* threadUrl */ , true); } } for (const userRemote of remoteUsers) { if (userRemote.activitypub_inbox_url || userRemote.salmon_url) { (0, _activitystreams.reply)(req, contentOwner, content, userRemote, mentionedRemoteUsers); } else if (userRemote.webmention_url) { (0, _webmention.reply)(req, contentOwner, content, userRemote, mentionedRemoteUsers); } } } async function webSubPush(req, options, content) { try { await (0, _nodeFetch.default)(options.constants.webSubHub, { method: 'POST', body: new URLSearchParams({ 'hub.url': content.url, 'hub.mode': 'publish' }) }); } catch (ex) {// Not a big deal if this fails. } }