|
|
|
@ -53,7 +53,7 @@ const redisUrlToClient = async (defaultConfig, redisUrl) => {
|
|
|
|
|
/**
|
|
|
|
|
* @param {string} json
|
|
|
|
|
* @param {any} req
|
|
|
|
|
* @return {Object.<string, any>|null}
|
|
|
|
|
* @returns {Object.<string, any>|null}
|
|
|
|
|
*/
|
|
|
|
|
const parseJSON = (json, req) => {
|
|
|
|
|
try {
|
|
|
|
@ -70,7 +70,7 @@ const parseJSON = (json, req) => {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {Object.<string, any>} env the `process.env` value to read configuration from
|
|
|
|
|
* @return {Object.<string, any>} the configuration for the PostgreSQL connection
|
|
|
|
|
* @returns {Object.<string, any>} the configuration for the PostgreSQL connection
|
|
|
|
|
*/
|
|
|
|
|
const pgConfigFromEnv = (env) => {
|
|
|
|
|
const pgConfigs = {
|
|
|
|
@ -124,7 +124,7 @@ const pgConfigFromEnv = (env) => {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {Object.<string, any>} env the `process.env` value to read configuration from
|
|
|
|
|
* @return {Object.<string, any>} configuration for the Redis connection
|
|
|
|
|
* @returns {Object.<string, any>} configuration for the Redis connection
|
|
|
|
|
*/
|
|
|
|
|
const redisConfigFromEnv = (env) => {
|
|
|
|
|
const redisNamespace = env.REDIS_NAMESPACE || null;
|
|
|
|
@ -171,7 +171,7 @@ const startServer = async () => {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {string[]} channels
|
|
|
|
|
* @return {function(): void}
|
|
|
|
|
* @returns {function(): void}
|
|
|
|
|
*/
|
|
|
|
|
const subscriptionHeartbeat = channels => {
|
|
|
|
|
const interval = 6 * 60;
|
|
|
|
@ -224,6 +224,7 @@ const startServer = async () => {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {string} channel
|
|
|
|
|
* @param {function(string): void} callback
|
|
|
|
|
*/
|
|
|
|
|
const unsubscribe = (channel, callback) => {
|
|
|
|
|
log.silly(`Removing listener for ${channel}`);
|
|
|
|
@ -255,7 +256,7 @@ const startServer = async () => {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {any} value
|
|
|
|
|
* @return {boolean}
|
|
|
|
|
* @returns {boolean}
|
|
|
|
|
*/
|
|
|
|
|
const isTruthy = value =>
|
|
|
|
|
value && !FALSE_VALUES.includes(value);
|
|
|
|
@ -263,7 +264,7 @@ const startServer = async () => {
|
|
|
|
|
/**
|
|
|
|
|
* @param {any} req
|
|
|
|
|
* @param {any} res
|
|
|
|
|
* @param {function(Error=): void}
|
|
|
|
|
* @param {function(Error=): void} next
|
|
|
|
|
*/
|
|
|
|
|
const allowCrossDomain = (req, res, next) => {
|
|
|
|
|
res.header('Access-Control-Allow-Origin', '*');
|
|
|
|
@ -276,7 +277,7 @@ const startServer = async () => {
|
|
|
|
|
/**
|
|
|
|
|
* @param {any} req
|
|
|
|
|
* @param {any} res
|
|
|
|
|
* @param {function(Error=): void}
|
|
|
|
|
* @param {function(Error=): void} next
|
|
|
|
|
*/
|
|
|
|
|
const setRequestId = (req, res, next) => {
|
|
|
|
|
req.requestId = uuid.v4();
|
|
|
|
@ -288,7 +289,7 @@ const startServer = async () => {
|
|
|
|
|
/**
|
|
|
|
|
* @param {any} req
|
|
|
|
|
* @param {any} res
|
|
|
|
|
* @param {function(Error=): void}
|
|
|
|
|
* @param {function(Error=): void} next
|
|
|
|
|
*/
|
|
|
|
|
const setRemoteAddress = (req, res, next) => {
|
|
|
|
|
req.remoteAddress = req.connection.remoteAddress;
|
|
|
|
@ -299,7 +300,7 @@ const startServer = async () => {
|
|
|
|
|
/**
|
|
|
|
|
* @param {any} req
|
|
|
|
|
* @param {string[]} necessaryScopes
|
|
|
|
|
* @return {boolean}
|
|
|
|
|
* @returns {boolean}
|
|
|
|
|
*/
|
|
|
|
|
const isInScope = (req, necessaryScopes) =>
|
|
|
|
|
req.scopes.some(scope => necessaryScopes.includes(scope));
|
|
|
|
@ -307,7 +308,7 @@ const startServer = async () => {
|
|
|
|
|
/**
|
|
|
|
|
* @param {string} token
|
|
|
|
|
* @param {any} req
|
|
|
|
|
* @return {Promise.<void>}
|
|
|
|
|
* @returns {Promise.<void>}
|
|
|
|
|
*/
|
|
|
|
|
const accountFromToken = (token, req) => new Promise((resolve, reject) => {
|
|
|
|
|
pgPool.connect((err, client, done) => {
|
|
|
|
@ -345,8 +346,7 @@ const startServer = async () => {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {any} req
|
|
|
|
|
* @param {boolean=} required
|
|
|
|
|
* @return {Promise.<void>}
|
|
|
|
|
* @returns {Promise.<void>}
|
|
|
|
|
*/
|
|
|
|
|
const accountFromRequest = (req) => new Promise((resolve, reject) => {
|
|
|
|
|
const authorization = req.headers.authorization;
|
|
|
|
@ -368,7 +368,7 @@ const startServer = async () => {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {any} req
|
|
|
|
|
* @return {string}
|
|
|
|
|
* @returns {string}
|
|
|
|
|
*/
|
|
|
|
|
const channelNameFromPath = req => {
|
|
|
|
|
const { path, query } = req;
|
|
|
|
@ -412,7 +412,7 @@ const startServer = async () => {
|
|
|
|
|
/**
|
|
|
|
|
* @param {any} req
|
|
|
|
|
* @param {string} channelName
|
|
|
|
|
* @return {Promise.<void>}
|
|
|
|
|
* @returns {Promise.<void>}
|
|
|
|
|
*/
|
|
|
|
|
const checkScopes = (req, channelName) => new Promise((resolve, reject) => {
|
|
|
|
|
log.silly(req.requestId, `Checking OAuth scopes for ${channelName}`);
|
|
|
|
@ -477,7 +477,7 @@ const startServer = async () => {
|
|
|
|
|
/**
|
|
|
|
|
* @param {any} req
|
|
|
|
|
* @param {SystemMessageHandlers} eventHandlers
|
|
|
|
|
* @return {function(string): void}
|
|
|
|
|
* @returns {function(string): void}
|
|
|
|
|
*/
|
|
|
|
|
const createSystemMessageListener = (req, eventHandlers) => {
|
|
|
|
|
return message => {
|
|
|
|
@ -565,14 +565,14 @@ const startServer = async () => {
|
|
|
|
|
/**
|
|
|
|
|
* @param {array} arr
|
|
|
|
|
* @param {number=} shift
|
|
|
|
|
* @return {string}
|
|
|
|
|
* @returns {string}
|
|
|
|
|
*/
|
|
|
|
|
const placeholders = (arr, shift = 0) => arr.map((_, i) => `$${i + 1 + shift}`).join(', ');
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {string} listId
|
|
|
|
|
* @param {any} req
|
|
|
|
|
* @return {Promise.<void>}
|
|
|
|
|
* @returns {Promise.<void>}
|
|
|
|
|
*/
|
|
|
|
|
const authorizeListAccess = (listId, req) => new Promise((resolve, reject) => {
|
|
|
|
|
const { accountId } = req;
|
|
|
|
@ -602,7 +602,7 @@ const startServer = async () => {
|
|
|
|
|
* @param {function(string, string): void} output
|
|
|
|
|
* @param {function(string[], function(string): void): void} attachCloseHandler
|
|
|
|
|
* @param {boolean=} needsFiltering
|
|
|
|
|
* @return {function(string): void}
|
|
|
|
|
* @returns {function(string): void}
|
|
|
|
|
*/
|
|
|
|
|
const streamFrom = (ids, req, output, attachCloseHandler, needsFiltering = false) => {
|
|
|
|
|
const accountId = req.accountId || req.remoteAddress;
|
|
|
|
@ -765,7 +765,7 @@ const startServer = async () => {
|
|
|
|
|
/**
|
|
|
|
|
* @param {any} req
|
|
|
|
|
* @param {any} res
|
|
|
|
|
* @return {function(string, string): void}
|
|
|
|
|
* @returns {function(string, string): void}
|
|
|
|
|
*/
|
|
|
|
|
const streamToHttp = (req, res) => {
|
|
|
|
|
const accountId = req.accountId || req.remoteAddress;
|
|
|
|
@ -792,7 +792,7 @@ const startServer = async () => {
|
|
|
|
|
/**
|
|
|
|
|
* @param {any} req
|
|
|
|
|
* @param {function(): void} [closeHandler]
|
|
|
|
|
* @return {function(string[]): void}
|
|
|
|
|
* @returns {function(string[]): void}
|
|
|
|
|
*/
|
|
|
|
|
const streamHttpEnd = (req, closeHandler = undefined) => (ids) => {
|
|
|
|
|
req.on('close', () => {
|
|
|
|
@ -810,7 +810,7 @@ const startServer = async () => {
|
|
|
|
|
* @param {any} req
|
|
|
|
|
* @param {any} ws
|
|
|
|
|
* @param {string[]} streamName
|
|
|
|
|
* @return {function(string, string): void}
|
|
|
|
|
* @returns {function(string, string): void}
|
|
|
|
|
*/
|
|
|
|
|
const streamToWs = (req, ws, streamName) => (event, payload) => {
|
|
|
|
|
if (ws.readyState !== ws.OPEN) {
|
|
|
|
@ -885,7 +885,7 @@ const startServer = async () => {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {any} req
|
|
|
|
|
* @return {string[]}
|
|
|
|
|
* @returns {string[]}
|
|
|
|
|
*/
|
|
|
|
|
const channelsForUserStream = req => {
|
|
|
|
|
const arr = [`timeline:${req.accountId}`];
|
|
|
|
@ -910,7 +910,7 @@ const startServer = async () => {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {string} str
|
|
|
|
|
* @return {string}
|
|
|
|
|
* @returns {string}
|
|
|
|
|
*/
|
|
|
|
|
const foldToASCII = str => {
|
|
|
|
|
const regex = new RegExp(NON_ASCII_CHARS.split('').join('|'), 'g');
|
|
|
|
@ -923,7 +923,7 @@ const startServer = async () => {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {string} str
|
|
|
|
|
* @return {string}
|
|
|
|
|
* @returns {string}
|
|
|
|
|
*/
|
|
|
|
|
const normalizeHashtag = str => {
|
|
|
|
|
return foldToASCII(str.normalize('NFKC').toLowerCase()).replace(/[^\p{L}\p{N}_\u00b7\u200c]/gu, '');
|
|
|
|
@ -933,7 +933,7 @@ const startServer = async () => {
|
|
|
|
|
* @param {any} req
|
|
|
|
|
* @param {string} name
|
|
|
|
|
* @param {StreamParams} params
|
|
|
|
|
* @return {Promise.<{ channelIds: string[], options: { needsFiltering: boolean } }>}
|
|
|
|
|
* @returns {Promise.<{ channelIds: string[], options: { needsFiltering: boolean } }>}
|
|
|
|
|
*/
|
|
|
|
|
const channelNameToIds = (req, name, params) => new Promise((resolve, reject) => {
|
|
|
|
|
switch (name) {
|
|
|
|
@ -1041,7 +1041,7 @@ const startServer = async () => {
|
|
|
|
|
/**
|
|
|
|
|
* @param {string} channelName
|
|
|
|
|
* @param {StreamParams} params
|
|
|
|
|
* @return {string[]}
|
|
|
|
|
* @returns {string[]}
|
|
|
|
|
*/
|
|
|
|
|
const streamNameFromChannelName = (channelName, params) => {
|
|
|
|
|
if (channelName === 'list') {
|
|
|
|
@ -1149,7 +1149,7 @@ const startServer = async () => {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {string|string[]} arrayOrString
|
|
|
|
|
* @return {string}
|
|
|
|
|
* @returns {string}
|
|
|
|
|
*/
|
|
|
|
|
const firstParam = arrayOrString => {
|
|
|
|
|
if (Array.isArray(arrayOrString)) {
|
|
|
|
|