diff options
Diffstat (limited to 'src/server/api')
31 files changed, 209 insertions, 67 deletions
diff --git a/src/server/api/endpoints/ap/show.ts b/src/server/api/endpoints/ap/show.ts index 1f390d01aa..6cbd4ef87e 100644 --- a/src/server/api/endpoints/ap/show.ts +++ b/src/server/api/endpoints/ap/show.ts @@ -24,15 +24,15 @@ export const meta = { }, }; -export default (params: any) => new Promise(async (res, rej) => { +export default async (params: any) => { const [ps, psErr] = getParams(meta, params); - if (psErr) return rej(psErr); + if (psErr) throw psErr; const object = await fetchAny(ps.uri); - if (object !== null) return res(object); + if (object !== null) return object; - return rej('object not found'); -}); + throw new Error('object not found'); +}; /*** * URIからUserかNoteを解決する diff --git a/src/server/api/endpoints/drive/files/check_existence.ts b/src/server/api/endpoints/drive/files/check_existence.ts index 73d75b7caf..a024701655 100644 --- a/src/server/api/endpoints/drive/files/check_existence.ts +++ b/src/server/api/endpoints/drive/files/check_existence.ts @@ -27,7 +27,8 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) = const file = await DriveFile.findOne({ md5: md5, - 'metadata.userId': user._id + 'metadata.userId': user._id, + 'metadata.deletedAt': { $exists: false } }); if (file === null) { diff --git a/src/server/api/endpoints/drive/files/show.ts b/src/server/api/endpoints/drive/files/show.ts index 718fb8c2d7..e35c5e3ca2 100644 --- a/src/server/api/endpoints/drive/files/show.ts +++ b/src/server/api/endpoints/drive/files/show.ts @@ -22,7 +22,8 @@ export default async (params: any, user: ILocalUser) => { const file = await DriveFile .findOne({ _id: fileId, - 'metadata.userId': user._id + 'metadata.userId': user._id, + 'metadata.deletedAt': { $exists: false } }); if (file === null) { diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts index c76d7f2e8f..152559337d 100644 --- a/src/server/api/endpoints/meta.ts +++ b/src/server/api/endpoints/meta.ts @@ -1,6 +1,3 @@ -/** - * Module dependencies - */ import * as os from 'os'; import config from '../../../config'; import Meta from '../../../models/meta'; @@ -9,9 +6,17 @@ import { ILocalUser } from '../../../models/user'; const pkg = require('../../../../package.json'); const client = require('../../../../built/client/meta.json'); -/** - * Show core info - */ +export const meta = { + desc: { + 'ja-JP': 'インスタンス情報を取得します。', + 'en-US': 'Get the information of this instance.' + }, + + requireCredential: false, + + params: {}, +}; + export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => { const meta: any = (await Meta.findOne()) || {}; @@ -28,10 +33,12 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => machine: os.hostname(), os: os.platform(), node: process.version, + cpu: { model: os.cpus()[0].model, cores: os.cpus().length }, + broadcasts: meta.broadcasts || [], disableRegistration: meta.disableRegistration, disableLocalTimeline: meta.disableLocalTimeline, @@ -40,6 +47,7 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => swPublickey: config.sw ? config.sw.public_key : null, hidedTags: (me && me.isAdmin) ? meta.hidedTags : undefined, bannerUrl: meta.bannerUrl, + features: { registration: !meta.disableRegistration, localTimeLine: !meta.disableLocalTimeline, diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts index 8362143bb2..8a6c848943 100644 --- a/src/server/api/endpoints/notes/global-timeline.ts +++ b/src/server/api/endpoints/notes/global-timeline.ts @@ -58,6 +58,8 @@ export default async (params: any, user: ILocalUser) => { }; const query = { + deletedAt: null, + // public only visibility: 'public', diff --git a/src/server/api/endpoints/notes/hybrid-timeline.ts b/src/server/api/endpoints/notes/hybrid-timeline.ts index 14b4432b33..b2ea9c60ac 100644 --- a/src/server/api/endpoints/notes/hybrid-timeline.ts +++ b/src/server/api/endpoints/notes/hybrid-timeline.ts @@ -129,6 +129,8 @@ export default async (params: any, user: ILocalUser) => { const query = { $and: [{ + deletedAt: null, + $or: [{ // フォローしている人の投稿 $or: followQuery diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts index 8ab07d8ea7..510564129c 100644 --- a/src/server/api/endpoints/notes/local-timeline.ts +++ b/src/server/api/endpoints/notes/local-timeline.ts @@ -71,6 +71,8 @@ export default async (params: any, user: ILocalUser) => { }; const query = { + deletedAt: null, + // public only visibility: 'public', diff --git a/src/server/api/endpoints/notes/mentions.ts b/src/server/api/endpoints/notes/mentions.ts index 592a94263d..27b6245eb6 100644 --- a/src/server/api/endpoints/notes/mentions.ts +++ b/src/server/api/endpoints/notes/mentions.ts @@ -45,6 +45,8 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) = // Construct query const query = { + deletedAt: null, + $or: [{ mentions: user._id }, { diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts index 44a504eb18..31a4978407 100644 --- a/src/server/api/endpoints/notes/timeline.ts +++ b/src/server/api/endpoints/notes/timeline.ts @@ -132,6 +132,8 @@ export default async (params: any, user: ILocalUser) => { const query = { $and: [{ + deletedAt: null, + // フォローしている人の投稿 $or: followQuery, diff --git a/src/server/api/endpoints/notes/user-list-timeline.ts b/src/server/api/endpoints/notes/user-list-timeline.ts index 6758b4eb73..7dddc4834e 100644 --- a/src/server/api/endpoints/notes/user-list-timeline.ts +++ b/src/server/api/endpoints/notes/user-list-timeline.ts @@ -137,6 +137,8 @@ export default async (params: any, user: ILocalUser) => { const query = { $and: [{ + deletedAt: null, + // リストに入っている人のタイムラインへの投稿 $or: listQuery, diff --git a/src/server/api/endpoints/users/notes.ts b/src/server/api/endpoints/users/notes.ts index 1bfe832c51..002ddf23e5 100644 --- a/src/server/api/endpoints/users/notes.ts +++ b/src/server/api/endpoints/users/notes.ts @@ -136,6 +136,7 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => }; const query = { + deletedAt: null, userId: user._id } as any; diff --git a/src/server/api/endpoints/users/recommendation.ts b/src/server/api/endpoints/users/recommendation.ts index e0a5cb9e36..f54326b566 100644 --- a/src/server/api/endpoints/users/recommendation.ts +++ b/src/server/api/endpoints/users/recommendation.ts @@ -3,6 +3,8 @@ import $ from 'cafy'; import User, { pack, ILocalUser } from '../../../../models/user'; import { getFriendIds } from '../../common/get-friends'; import Mute from '../../../../models/mute'; +import * as request from 'request'; +import config from '../../../../config'; export const meta = { desc: { @@ -15,44 +17,72 @@ export const meta = { }; export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => { - // Get 'limit' parameter - const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); - if (limitErr) return rej('invalid limit param'); + if (config.user_recommendation && config.user_recommendation.external) { + const userName = me.username; + const hostName = config.hostname; + const limit = params.limit; + const offset = params.offset; + const timeout = config.user_recommendation.timeout; + const engine = config.user_recommendation.engine; + const url = engine + .replace('{{host}}', hostName) + .replace('{{user}}', userName) + .replace('{{limit}}', limit) + .replace('{{offset}}', offset); - // Get 'offset' parameter - const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset); - if (offsetErr) return rej('invalid offset param'); + request( + { + url: url, + timeout: timeout, + json: true, + followRedirect: true, + followAllRedirects: true + }, + (error: any, response: any, body: any) => { + if (!error && response.statusCode == 200) { + res(body); + } else { + res([]); + } + } + ); + } else { + // Get 'limit' parameter + const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit); + if (limitErr) return rej('invalid limit param'); - // ID list of the user itself and other users who the user follows - const followingIds = await getFriendIds(me._id); + // Get 'offset' parameter + const [offset = 0, offsetErr] = $.num.optional.min(0).get(params.offset); + if (offsetErr) return rej('invalid offset param'); - // ミュートしているユーザーを取得 - const mutedUserIds = (await Mute.find({ - muterId: me._id - })).map(m => m.muteeId); + // ID list of the user itself and other users who the user follows + const followingIds = await getFriendIds(me._id); - const users = await User - .find({ - _id: { - $nin: followingIds.concat(mutedUserIds) - }, - isLocked: false, - $or: [{ + // ミュートしているユーザーを取得 + const mutedUserIds = (await Mute.find({ + muterId: me._id + })).map(m => m.muteeId); + + const users = await User + .find({ + _id: { + $nin: followingIds.concat(mutedUserIds) + }, + isLocked: { $ne: true }, lastUsedAt: { $gte: new Date(Date.now() - ms('7days')) - } - }, { + }, host: null - }] - }, { - limit: limit, - skip: offset, - sort: { - followersCount: -1 - } - }); + }, { + limit: limit, + skip: offset, + sort: { + followersCount: -1 + } + }); - // Serialize - res(await Promise.all(users.map(async user => - await pack(user, me, { detail: true })))); + // Serialize + res(await Promise.all(users.map(async user => + await pack(user, me, { detail: true })))); + } }); diff --git a/src/server/api/limitter.ts b/src/server/api/limitter.ts index 20a18a7098..abf7627ab8 100644 --- a/src/server/api/limitter.ts +++ b/src/server/api/limitter.ts @@ -8,6 +8,12 @@ import { IUser } from '../../models/user'; const log = debug('misskey:limitter'); export default (endpoint: IEndpoint, user: IUser) => new Promise((ok, reject) => { + // Redisがインストールされてない場合は常に許可 + if (limiterDB == null) { + ok(); + return; + } + const limitation = endpoint.meta.limit; const key = limitation.hasOwnProperty('key') diff --git a/src/server/api/service/twitter.ts b/src/server/api/service/twitter.ts index f71e588628..6c3cdaa138 100644 --- a/src/server/api/service/twitter.ts +++ b/src/server/api/service/twitter.ts @@ -55,7 +55,7 @@ router.get('/disconnect/twitter', async ctx => { })); }); -if (config.twitter == null) { +if (config.twitter == null || redis == null) { router.get('/connect/twitter', ctx => { ctx.body = '現在Twitterへ接続できません (このインスタンスではTwitterはサポートされていません)'; }); diff --git a/src/server/api/stream/channel.ts b/src/server/api/stream/channel.ts index e2726060dc..75914964cb 100644 --- a/src/server/api/stream/channel.ts +++ b/src/server/api/stream/channel.ts @@ -7,6 +7,8 @@ import Connection from '.'; export default abstract class Channel { protected connection: Connection; public id: string; + public abstract readonly chName: string; + public static readonly shouldShare: boolean; protected get user() { return this.connection.user; diff --git a/src/server/api/stream/channels/drive.ts b/src/server/api/stream/channels/drive.ts index 807fc93cd0..7425a620ff 100644 --- a/src/server/api/stream/channels/drive.ts +++ b/src/server/api/stream/channels/drive.ts @@ -2,6 +2,9 @@ import autobind from 'autobind-decorator'; import Channel from '../channel'; export default class extends Channel { + public readonly chName = 'drive'; + public static shouldShare = true; + @autobind public async init(params: any) { // Subscribe drive stream diff --git a/src/server/api/stream/channels/games/reversi-game.ts b/src/server/api/stream/channels/games/reversi-game.ts index 11f1fb1feb..5dc9ca0608 100644 --- a/src/server/api/stream/channels/games/reversi-game.ts +++ b/src/server/api/stream/channels/games/reversi-game.ts @@ -1,5 +1,6 @@ import autobind from 'autobind-decorator'; import * as CRC32 from 'crc-32'; +import * as mongo from 'mongodb'; import ReversiGame, { pack } from '../../../../../models/games/reversi/game'; import { publishReversiGameStream } from '../../../../../stream'; import Reversi from '../../../../../games/reversi/core'; @@ -7,11 +8,14 @@ import * as maps from '../../../../../games/reversi/maps'; import Channel from '../../channel'; export default class extends Channel { - private gameId: string; + public readonly chName = 'gamesReversiGame'; + public static shouldShare = false; + + private gameId: mongo.ObjectID; @autobind public async init(params: any) { - this.gameId = params.gameId as string; + this.gameId = new mongo.ObjectID(params.gameId as string); // Subscribe game stream this.subscriber.on(`reversiGameStream:${this.gameId}`, data => { @@ -23,10 +27,10 @@ export default class extends Channel { public onMessage(type: string, body: any) { switch (type) { case 'accept': this.accept(true); break; - case 'cancel-accept': this.accept(false); break; - case 'update-settings': this.updateSettings(body.settings); break; - case 'init-form': this.initForm(body); break; - case 'update-form': this.updateForm(body.id, body.value); break; + case 'cancelAccept': this.accept(false); break; + case 'updateSettings': this.updateSettings(body.settings); break; + case 'initForm': this.initForm(body); break; + case 'updateForm': this.updateForm(body.id, body.value); break; case 'message': this.message(body); break; case 'set': this.set(body.pos); break; case 'check': this.check(body.crc32); break; diff --git a/src/server/api/stream/channels/games/reversi.ts b/src/server/api/stream/channels/games/reversi.ts index d75025c944..51cb264d98 100644 --- a/src/server/api/stream/channels/games/reversi.ts +++ b/src/server/api/stream/channels/games/reversi.ts @@ -5,6 +5,9 @@ import { publishMainStream } from '../../../../../stream'; import Channel from '../../channel'; export default class extends Channel { + public readonly chName = 'gamesReversi'; + public static shouldShare = true; + @autobind public async init(params: any) { // Subscribe reversi stream diff --git a/src/server/api/stream/channels/global-timeline.ts b/src/server/api/stream/channels/global-timeline.ts index ab0fe5d094..e39ea269a6 100644 --- a/src/server/api/stream/channels/global-timeline.ts +++ b/src/server/api/stream/channels/global-timeline.ts @@ -5,6 +5,9 @@ import shouldMuteThisNote from '../../../../misc/should-mute-this-note'; import Channel from '../channel'; export default class extends Channel { + public readonly chName = 'globalTimeline'; + public static shouldShare = true; + private mutedUserIds: string[] = []; @autobind diff --git a/src/server/api/stream/channels/hashtag.ts b/src/server/api/stream/channels/hashtag.ts index 652b0caa5b..cf652c166c 100644 --- a/src/server/api/stream/channels/hashtag.ts +++ b/src/server/api/stream/channels/hashtag.ts @@ -5,6 +5,9 @@ import shouldMuteThisNote from '../../../../misc/should-mute-this-note'; import Channel from '../channel'; export default class extends Channel { + public readonly chName = 'hashtag'; + public static shouldShare = false; + @autobind public async init(params: any) { const mute = this.user ? await Mute.find({ muterId: this.user._id }) : null; diff --git a/src/server/api/stream/channels/home-timeline.ts b/src/server/api/stream/channels/home-timeline.ts index 4c674e75ef..3fa887f1e5 100644 --- a/src/server/api/stream/channels/home-timeline.ts +++ b/src/server/api/stream/channels/home-timeline.ts @@ -5,6 +5,9 @@ import shouldMuteThisNote from '../../../../misc/should-mute-this-note'; import Channel from '../channel'; export default class extends Channel { + public readonly chName = 'homeTimeline'; + public static shouldShare = true; + private mutedUserIds: string[] = []; @autobind diff --git a/src/server/api/stream/channels/hybrid-timeline.ts b/src/server/api/stream/channels/hybrid-timeline.ts index 0b12ab3a8f..d72545e4c8 100644 --- a/src/server/api/stream/channels/hybrid-timeline.ts +++ b/src/server/api/stream/channels/hybrid-timeline.ts @@ -5,6 +5,9 @@ import shouldMuteThisNote from '../../../../misc/should-mute-this-note'; import Channel from '../channel'; export default class extends Channel { + public readonly chName = 'hybridTimeline'; + public static shouldShare = true; + private mutedUserIds: string[] = []; @autobind diff --git a/src/server/api/stream/channels/local-timeline.ts b/src/server/api/stream/channels/local-timeline.ts index 769ec6392f..0ba0b1b195 100644 --- a/src/server/api/stream/channels/local-timeline.ts +++ b/src/server/api/stream/channels/local-timeline.ts @@ -5,6 +5,9 @@ import shouldMuteThisNote from '../../../../misc/should-mute-this-note'; import Channel from '../channel'; export default class extends Channel { + public readonly chName = 'localTimeline'; + public static shouldShare = true; + private mutedUserIds: string[] = []; @autobind diff --git a/src/server/api/stream/channels/main.ts b/src/server/api/stream/channels/main.ts index fd0984c833..7d5462c092 100644 --- a/src/server/api/stream/channels/main.ts +++ b/src/server/api/stream/channels/main.ts @@ -3,6 +3,9 @@ import Mute from '../../../../models/mute'; import Channel from '../channel'; export default class extends Channel { + public readonly chName = 'main'; + public static shouldShare = true; + @autobind public async init(params: any) { const mute = await Mute.find({ muterId: this.user._id }); diff --git a/src/server/api/stream/channels/messaging-index.ts b/src/server/api/stream/channels/messaging-index.ts index 6e87cca7f4..0211d702cf 100644 --- a/src/server/api/stream/channels/messaging-index.ts +++ b/src/server/api/stream/channels/messaging-index.ts @@ -2,6 +2,9 @@ import autobind from 'autobind-decorator'; import Channel from '../channel'; export default class extends Channel { + public readonly chName = 'messagingIndex'; + public static shouldShare = true; + @autobind public async init(params: any) { // Subscribe messaging index stream diff --git a/src/server/api/stream/channels/messaging.ts b/src/server/api/stream/channels/messaging.ts index e1a78c8678..ab04a332cf 100644 --- a/src/server/api/stream/channels/messaging.ts +++ b/src/server/api/stream/channels/messaging.ts @@ -3,6 +3,9 @@ import read from '../../common/read-messaging-message'; import Channel from '../channel'; export default class extends Channel { + public readonly chName = 'messaging'; + public static shouldShare = false; + private otherpartyId: string; @autobind diff --git a/src/server/api/stream/channels/notes-stats.ts b/src/server/api/stream/channels/notes-stats.ts index cc68d9886d..2282f8bc70 100644 --- a/src/server/api/stream/channels/notes-stats.ts +++ b/src/server/api/stream/channels/notes-stats.ts @@ -5,6 +5,9 @@ import Channel from '../channel'; const ev = new Xev(); export default class extends Channel { + public readonly chName = 'notesStats'; + public static shouldShare = true; + @autobind public async init(params: any) { ev.addListener('notesStats', this.onStats); diff --git a/src/server/api/stream/channels/server-stats.ts b/src/server/api/stream/channels/server-stats.ts index 28a566e8ae..912dcf5305 100644 --- a/src/server/api/stream/channels/server-stats.ts +++ b/src/server/api/stream/channels/server-stats.ts @@ -5,6 +5,9 @@ import Channel from '../channel'; const ev = new Xev(); export default class extends Channel { + public readonly chName = 'serverStats'; + public static shouldShare = true; + @autobind public async init(params: any) { ev.addListener('serverStats', this.onStats); diff --git a/src/server/api/stream/channels/user-list.ts b/src/server/api/stream/channels/user-list.ts index 4ace308923..b526a5f986 100644 --- a/src/server/api/stream/channels/user-list.ts +++ b/src/server/api/stream/channels/user-list.ts @@ -2,6 +2,9 @@ import autobind from 'autobind-decorator'; import Channel from '../channel'; export default class extends Channel { + public readonly chName = 'userList'; + public static shouldShare = false; + @autobind public async init(params: any) { const listId = params.listId as string; diff --git a/src/server/api/stream/index.ts b/src/server/api/stream/index.ts index ef6397fcd9..6d3675c94b 100644 --- a/src/server/api/stream/index.ts +++ b/src/server/api/stream/index.ts @@ -1,6 +1,5 @@ import autobind from 'autobind-decorator'; import * as websocket from 'websocket'; -import Xev from 'xev'; import * as debug from 'debug'; import User, { IUser } from '../../../models/user'; @@ -11,6 +10,7 @@ import readNote from '../../../services/note/read'; import Channel from './channel'; import channels from './channels'; +import { EventEmitter } from 'events'; const log = debug('misskey'); @@ -21,14 +21,14 @@ export default class Connection { public user?: IUser; public app: IApp; private wsConnection: websocket.connection; - public subscriber: Xev; + public subscriber: EventEmitter; private channels: Channel[] = []; private subscribingNotes: any = {}; public sendMessageToWsOverride: any = null; // 後方互換性のため constructor( wsConnection: websocket.connection, - subscriber: Xev, + subscriber: EventEmitter, user: IUser, app: IApp ) { @@ -58,6 +58,7 @@ export default class Connection { case 'connect': this.onChannelConnectRequested(body); break; case 'disconnect': this.onChannelDisconnectRequested(body); break; case 'channel': this.onChannelMessageRequested(body); break; + case 'ch': this.onChannelMessageRequested(body); break; // alias } } @@ -147,7 +148,7 @@ export default class Connection { private onChannelConnectRequested(payload: any) { const { channel, id, params } = payload; log(`CH CONNECT: ${id} ${channel} by @${this.user.username}`); - this.connectChannel(id, params, (channels as any)[channel]); + this.connectChannel(id, params, channel); } /** @@ -176,10 +177,18 @@ export default class Connection { * チャンネルに接続 */ @autobind - public connectChannel(id: string, params: any, channelClass: { new(id: string, connection: Connection): Channel }) { - const channel = new channelClass(id, this); - this.channels.push(channel); - channel.init(params); + public connectChannel(id: string, params: any, channel: string) { + // 共有可能チャンネルに接続しようとしていて、かつそのチャンネルに既に接続していたら無意味なので無視 + if ((channels as any)[channel].shouldShare && this.channels.some(c => c.chName === channel)) { + return; + } + + const ch: Channel = new (channels as any)[channel](id, this); + this.channels.push(ch); + ch.init(params); + this.sendMessageToWs('connected', { + id: id + }); } /** diff --git a/src/server/api/streaming.ts b/src/server/api/streaming.ts index c8c4a8a294..1a0543b364 100644 --- a/src/server/api/streaming.ts +++ b/src/server/api/streaming.ts @@ -1,11 +1,13 @@ import * as http from 'http'; import * as websocket from 'websocket'; +import * as redis from 'redis'; import Xev from 'xev'; import MainStreamConnection from './stream'; import { ParsedUrlQuery } from 'querystring'; import authenticate from './authenticate'; -import channels from './stream/channels'; +import { EventEmitter } from 'events'; +import config from '../../config'; module.exports = (server: http.Server) => { // Init websocket server @@ -16,11 +18,34 @@ module.exports = (server: http.Server) => { ws.on('request', async (request) => { const connection = request.accept(); - const ev = new Xev(); - const q = request.resourceURL.query as ParsedUrlQuery; const [user, app] = await authenticate(q.i as string); + let ev: EventEmitter; + + if (config.redis) { + // Connect to Redis + const subscriber = redis.createClient( + config.redis.port, config.redis.host); + + subscriber.subscribe('misskey'); + + ev = new EventEmitter(); + + subscriber.on('message', async (_, data) => { + const obj = JSON.parse(data); + + ev.emit(obj.channel, obj.message); + }); + + connection.once('close', () => { + subscriber.unsubscribe(); + subscriber.quit(); + }); + } else { + ev = new Xev(); + } + const main = new MainStreamConnection(connection, ev, user, app); // 後方互換性のため @@ -40,10 +65,14 @@ module.exports = (server: http.Server) => { }; main.connectChannel(Math.random().toString(), null, - request.resourceURL.pathname === '/' ? channels.homeTimeline : - request.resourceURL.pathname === '/local-timeline' ? channels.localTimeline : - request.resourceURL.pathname === '/hybrid-timeline' ? channels.hybridTimeline : - request.resourceURL.pathname === '/global-timeline' ? channels.globalTimeline : null); + request.resourceURL.pathname === '/' ? 'homeTimeline' : + request.resourceURL.pathname === '/local-timeline' ? 'localTimeline' : + request.resourceURL.pathname === '/hybrid-timeline' ? 'hybridTimeline' : + request.resourceURL.pathname === '/global-timeline' ? 'globalTimeline' : null); + + if (request.resourceURL.pathname === '/') { + main.connectChannel(Math.random().toString(), null, 'main'); + } } connection.once('close', () => { |