From 495cfa96c26a89b09a73c7dd11d85cfce6d3c7a8 Mon Sep 17 00:00:00 2001 From: C eq Q divided-by U <61620747+LxveFades@users.noreply.github.com> Date: Sat, 21 Mar 2020 09:52:40 +0100 Subject: [PATCH] fix(TypingStart): typing methods returning falsy values (#3939) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: typing methods returning falsy values * fix: eslint * fix: no provided parameters; updated jsdocs * fix(Typings): reflect typingStop * refactor: since and lastTimestamp merged into one constructable value * feat(Typings): document Channel#_typing * feat: emit TypingData on typingStart; update jsdocs * feat(Typings): move _typing to TextBasedChannel; sort props alphabetic * feat(Event): remove typingStop * feat(Typings): update typings - remove typingStop * feat(Event): remove typingStop from Constants * feat(Typing): remove TypingData class - redundant * refactor(Events): remove TYPING_STOP event * refactor(TypingData): now is an interface for _typing * fix(TypingStart): timeout variable, removed emit for TypingData * feat(Typing): timeout property on Channel#_typing, remove redundancy * fix(Typings): extra overload(s) Co-Authored-By: Sugden <28943913+NotSugden@users.noreply.github.com> * Update index.d.ts * fix(Typings): remove "private" from interface — invalid TS * feat(Typings): add PartialUser in case partials are enabled Co-Authored-By: Sugden <28943913+NotSugden@users.noreply.github.com> * feat(Typings): document 'timeout' property of TypingData Co-authored-by: Crawl Co-authored-by: Sugden <28943913+NotSugden@users.noreply.github.com> --- src/client/websocket/handlers/TYPING_START.js | 45 ++++++++++++++++--- typings/index.d.ts | 23 ++++++---- 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/client/websocket/handlers/TYPING_START.js b/src/client/websocket/handlers/TYPING_START.js index 426c96f14..86fb26b1a 100644 --- a/src/client/websocket/handlers/TYPING_START.js +++ b/src/client/websocket/handlers/TYPING_START.js @@ -5,14 +5,45 @@ const { Events } = require('../../../util/Constants'); module.exports = (client, { d: data }) => { const channel = client.channels.cache.get(data.channel_id); const user = client.users.cache.get(data.user_id); + const timestamp = new Date(data.timestamp * 1000); if (channel && user) { - /** - * Emitted whenever a user starts typing in a channel. - * @event Client#typingStart - * @param {Channel} channel The channel the user started typing in - * @param {User} user The user that started typing - */ - client.emit(Events.TYPING_START, channel, user); + if (channel.type === 'voice') { + client.emit(Events.WARN, `Discord sent a typing packet to a voice channel ${channel.id}`); + return; + } + + if (channel._typing.has(user.id)) { + const typing = channel._typing.get(user.id); + + typing.lastTimestamp = timestamp; + typing.elapsedTime = Date.now() - typing.since; + client.clearTimeout(typing.timeout); + typing.timeout = tooLate(channel, user); + } else { + const since = new Date(); + const lastTimestamp = new Date(); + channel._typing.set(user.id, { + user, + since, + lastTimestamp, + elapsedTime: Date.now() - since, + timeout: tooLate(channel, user), + }); + + /** + * Emitted whenever a user starts typing in a channel. + * @event Client#typingStart + * @param {Channel} channel The channel the user started typing in + * @param {User} user The user that started typing + */ + client.emit(Events.TYPING_START, channel, user); + } } }; + +function tooLate(channel, user) { + return channel.client.setTimeout(() => { + channel._typing.delete(user.id); + }, 10000); +} diff --git a/typings/index.d.ts b/typings/index.d.ts index 4cc9bb698..c0c61ef08 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1952,6 +1952,7 @@ declare module 'discord.js' { } interface TextBasedChannelFields extends PartialTextBasedChannelFields { + _typing: Map; lastPinTimestamp: number | null; readonly lastPinAt: Date; typing: boolean; @@ -2780,15 +2781,11 @@ declare module 'discord.js' { partial: true; fetch(): Promise; } & { - [K in keyof Omit - // tslint:disable-next-line:ban-types - ]: T[K] extends Function ? T[K] : T[K] | null; + [K in keyof Omit< + T, + 'client' | 'createdAt' | 'createdTimestamp' | 'id' | 'partial' | 'fetch' + >]: // tslint:disable-next-line:ban-types + T[K] extends Function ? T[K] : T[K] | null; }; interface PartialDMChannel extends Partialize