diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 44fff6d5f..000000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "typings"]
- path = typings
- url = https://github.com/discordjs/discord.js-typings
diff --git a/.npmignore b/.npmignore
index 86270540e..a480c140f 100644
--- a/.npmignore
+++ b/.npmignore
@@ -24,3 +24,5 @@ webpack/
webpack.config.js
.github/
test/
+tsconfig.json
+tslint.json
diff --git a/package.json b/package.json
index 5df866401..e99e1e181 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
"docs:test": "docgen --source src --custom docs/index.yml",
"lint": "eslint src",
"lint:fix": "eslint --fix src",
+ "lint:typings": "tslint index.d.ts discord.js-test.ts",
"webpack": "parallel-webpack"
},
"repository": {
@@ -52,6 +53,9 @@
"discord.js-docgen": "discordjs/docgen",
"eslint": "^4.18.0",
"parallel-webpack": "^2.2.0",
+ "tslint": "^3.15.1",
+ "tslint-config-typings": "^0.2.4",
+ "typescript": "^3.0.1",
"uglifyjs-webpack-plugin": "^1.2.0",
"webpack": "^3.11.0"
},
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 000000000..6c5e479d8
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "target": "es6",
+ "noImplicitAny": true,
+ "strictNullChecks": true,
+ "noEmit": true,
+ "forceConsistentCasingInFileNames": true
+ },
+ "files": [
+ "index.d.ts"
+ ]
+}
diff --git a/tslint.json b/tslint.json
new file mode 100644
index 000000000..71f850264
--- /dev/null
+++ b/tslint.json
@@ -0,0 +1,62 @@
+{
+ "extends": [
+ "tslint-config-typings"
+ ],
+ "rules": {
+ "class-name": true,
+ "comment-format": [
+ true,
+ "check-space"
+ ],
+ "indent": [
+ true,
+ "tabs"
+ ],
+ "no-duplicate-variable": true,
+ "no-unused-variable": [false],
+ "no-eval": true,
+ "no-internal-module": true,
+ "no-trailing-whitespace": true,
+ "no-unsafe-finally": true,
+ "no-var-keyword": true,
+ "one-line": [
+ true,
+ "check-open-brace",
+ "check-whitespace"
+ ],
+ "quotemark": [
+ true,
+ "single"
+ ],
+ "semicolon": [
+ true,
+ "always"
+ ],
+ "triple-equals": [
+ true,
+ "allow-null-check"
+ ],
+ "typedef-whitespace": [
+ true,
+ {
+ "call-signature": "nospace",
+ "index-signature": "nospace",
+ "parameter": "nospace",
+ "property-declaration": "nospace",
+ "variable-declaration": "nospace"
+ }
+ ],
+ "variable-name": [
+ true,
+ "ban-keywords"
+ ],
+ "whitespace": [
+ true,
+ "check-branch",
+ "check-decl",
+ "check-operator",
+ "check-separator",
+ "check-type"
+ ]
+ }
+}
diff --git a/typings b/typings
deleted file mode 160000
index 6103ec4af..000000000
--- a/typings
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 6103ec4aff15f0c7cf7103034db0085fd6b6911a
diff --git a/typings/discord.js-test.ts b/typings/discord.js-test.ts
new file mode 100644
index 000000000..6792dba87
--- /dev/null
+++ b/typings/discord.js-test.ts
@@ -0,0 +1,69 @@
+///
+
+import { Collector, Message, CollectorFilter, Client, CollectorHandler, MessageReaction, Collection, User, ReactionCollectorOptions, Snowflake } from 'discord.js';
+
+const client = new Client({
+ disableEveryone: false,
+ disabledEvents: ['GUILD_MEMBER_ADD']
+});
+
+client.on('message', (message) => {
+ if (message.content === 'hello') {
+ message.channel.sendMessage('o/');
+ }
+
+ const collector: ReactionCollector = new ReactionCollector(message,
+ (reaction: MessageReaction) => reaction.emoji.toString() === '👌',
+ { time: 30e3 });
+ collector.on('end', collected => console.log(collected));
+});
+
+client.login('dsfsd754.4fds4f68d4f6sd46f4s.7878easfdsgdfFDSIJIO');
+
+export class TestCollector extends Collector {
+ public filter: CollectorFilter;
+ public constructor(client: Client, filter: CollectorFilter, ) {
+ super(client, filter);
+ }
+
+ public handle(message: Message): CollectorHandler {
+ return { key: message.id, value: message };
+ }
+
+ public cleanup(): void {}
+ public postCheck(): null { return null; }
+}
+
+class ReactionCollector extends Collector {
+ public message: Message;
+ public users: Collection;
+ public total: number;
+ public options: ReactionCollectorOptions;
+ public constructor(message: Message, filter: CollectorFilter, options?: ReactionCollectorOptions) {
+ super(message.client, filter, options || {});
+ this.message = message;
+ this.users = new Collection();
+ this.total = 0;
+ this.client.on('messageReactionAdd', this.listener);
+ }
+
+ public handle(reaction: MessageReaction): CollectorHandler {
+ if (reaction.message.id !== this.message.id) { return null; }
+ return {
+ key: reaction.emoji.id || reaction.emoji.name,
+ value: reaction
+ };
+ }
+
+ public postCheck(reaction: MessageReaction, user: User): string {
+ this.users.set(user.id, user);
+ if (this.options.max && ++this.total >= this.options.max) { return 'limit'; }
+ if (this.options.maxEmojis && this.collected.size >= this.options.maxEmojis) { return 'emojiLimit'; }
+ if (this.options.maxUsers && this.users.size >= this.options.maxUsers) { return 'userLimit'; }
+ return null;
+ }
+
+ public cleanup(): void {
+ this.client.removeListener('messageReactionAdd', this.listener);
+ }
+}
diff --git a/typings/index.d.ts b/typings/index.d.ts
new file mode 100644
index 000000000..a7477c501
--- /dev/null
+++ b/typings/index.d.ts
@@ -0,0 +1,2133 @@
+// Type definitions for discord.js 11.3.0
+// Project: https://github.com/hydrabolt/discord.js
+// Definitions by:
+// acdenisSK (https://github.com/acdenisSK)
+// Zack Campbell (https://github.com/zajrik)
+// License: MIT
+
+declare module 'discord.js' {
+ import { EventEmitter } from 'events';
+ import { Stream, Readable as ReadableStream } from 'stream';
+ import { ChildProcess } from 'child_process';
+
+ export const version: string;
+
+//#region Classes
+
+ class Attachment {
+ constructor(file: BufferResolvable | Stream, name?: string);
+ private _attach(file: BufferResolvable | Stream, name: string): void;
+
+ public readonly attachment: BufferResolvable | Stream;
+ public readonly name: string;
+ public setAttachment(file: BufferResolvable | Stream, name: string): this;
+ public setFile(attachment: BufferResolvable | Stream): this;
+ public setName(name: string): this;
+ }
+
+ class AudioPlayer extends EventEmitter {
+ constructor(voiceConnection: VoiceConnection);
+ public readonly dispatcher: StreamDispatcher;
+ public opusEncoder: object;
+ public prism: object;
+ public readonly transcoder: object;
+ public voiceConnection: VoiceConnection;
+ public setBitrate(value: number | 'auto'): void;
+ }
+
+ class BaseOpus {
+ constructor(options?: { bitrate?: number, fec?: boolean, plp?: number });
+ public bitrate: number;
+ public options: object;
+ }
+
+ export class CategoryChannel extends GuildChannel {
+ public readonly children: Collection;
+ }
+
+ export class Channel {
+ constructor(client: Client, data: object);
+ public readonly client: Client;
+ public readonly createdAt: Date;
+ public readonly createdTimestamp: number;
+ public id: Snowflake;
+ public type: 'dm' | 'group' | 'text' | 'voice' | 'category';
+ public delete(): Promise;
+ }
+
+ export class Client extends EventEmitter {
+ constructor(options?: ClientOptions);
+ private _intervals: Set;
+ private _pingTimestamp: number;
+ private _timeouts: Set;
+ private actions: object;
+ private dataManager: object;
+ private manager: ClientManager;
+ private resolver: ClientDataResolver;
+ private rest: object;
+ private voice: ClientVoiceManager;
+ private ws: object;
+ private _eval(script: string): any;
+ private _pong(startTime: number): void;
+ private _setPresence(id: Snowflake, presence: object): void;
+ private _validateOptions(options?: ClientOptions): void;
+
+ public broadcasts: VoiceBroadcast[];
+ public readonly browser: boolean;
+ public channels: Collection;
+ public readonly emojis: Collection;
+ public guilds: Collection;
+ public options: ClientOptions;
+ public readonly ping: number;
+ public pings: number[];
+ public presences: Collection;
+ public readyAt: Date;
+ public readonly readyTimestamp: number;
+ public shard: ShardClientUtil;
+ public readonly status: number;
+ public token: string;
+ public readonly uptime: number;
+ public user: ClientUser;
+ public users: Collection;
+ public readonly voiceConnections: Collection;
+ public clearInterval(interval: NodeJS.Timer): void;
+ public clearTimeout(timeout: NodeJS.Timer): void;
+ public createVoiceBroadcast(): VoiceBroadcast;
+ public destroy(): Promise;
+ public fetchApplication(id?: Snowflake): Promise;
+ public fetchInvite(invite: InviteResolvable): Promise;
+ public fetchUser(id: Snowflake, cache?: boolean): Promise;
+ public fetchVoiceRegions(): Promise>;
+ public fetchWebhook(id: Snowflake, token?: string): Promise;
+ public generateInvite(permissions?: PermissionResolvable): Promise;
+ public login(token?: string): Promise;
+ public setInterval(fn: Function, delay: number, ...args: any[]): NodeJS.Timer;
+ public setTimeout(fn: Function, delay: number, ...args: any[]): NodeJS.Timer;
+ public sweepMessages(lifetime?: number): number;
+ public syncGuilds(guilds?: Guild[] | Collection): void;
+
+ public on(event: 'channelCreate', listener: (channel: Channel) => void): this;
+ public on(event: 'channelDelete', listener: (channel: Channel) => void): this;
+ public on(event: 'channelPinsUpdate', listener: (channel: Channel, time: Date) => void): this;
+ public on(event: 'channelUpdate', listener: (oldChannel: Channel, newChannel: Channel) => void): this;
+ public on(event: 'clientUserGuildSettingsUpdate', listener: (clientUserGuildSettings: ClientUserGuildSettings) => void): this;
+ public on(event: 'clientUserSettingsUpdate', listener: (clientUserSettings: ClientUserSettings) => void): this;
+ public on(event: 'debug', listener: (info: string) => void): this;
+ public on(event: 'disconnect', listener: (event: any) => void): this;
+ public on(event: 'emojiCreate', listener: (emoji: Emoji) => void): this;
+ public on(event: 'emojiDelete', listener: (emoji: Emoji) => void): this;
+ public on(event: 'emojiUpdate', listener: (oldEmoji: Emoji, newEmoji: Emoji) => void): this;
+ public on(event: 'error', listener: (error: Error) => void): this;
+ public on(event: 'guildBanAdd', listener: (guild: Guild, user: User) => void): this;
+ public on(event: 'guildBanRemove', listener: (guild: Guild, user: User) => void): this;
+ public on(event: 'guildCreate', listener: (guild: Guild) => void): this;
+ public on(event: 'guildDelete', listener: (guild: Guild) => void): this;
+ public on(event: 'guildMemberAdd', listener: (member: GuildMember) => void): this;
+ public on(event: 'guildMemberAvailable', listener: (member: GuildMember) => void): this;
+ public on(event: 'guildMemberRemove', listener: (member: GuildMember) => void): this;
+ public on(event: 'guildMembersChunk', listener: (members: GuildMember[], guild: Guild) => void): this;
+ public on(event: 'guildMemberSpeaking', listener: (member: GuildMember, speaking: boolean) => void): this;
+ public on(event: 'guildMemberUpdate', listener: (oldMember: GuildMember, newMember: GuildMember) => void): this;
+ public on(event: 'guildUnavailable', listener: (guild: Guild) => void): this;
+ public on(event: 'guildUpdate', listener: (oldGuild: Guild, newGuild: Guild) => void): this;
+ public on(event: 'message', listener: (message: Message) => void): this;
+ public on(event: 'messageDelete', listener: (message: Message) => void): this;
+ public on(event: 'messageDeleteBulk', listener: (messages: Collection) => void): this;
+ public on(event: 'messageReactionAdd', listener: (messageReaction: MessageReaction, user: User) => void): this;
+ public on(event: 'messageReactionRemove', listener: (messageReaction: MessageReaction, user: User) => void): this;
+ public on(event: 'messageReactionRemoveAll', listener: (message: Message) => void): this;
+ public on(event: 'messageUpdate', listener: (oldMessage: Message, newMessage: Message) => void): this;
+ public on(event: 'presenceUpdate', listener: (oldMember: GuildMember, newMember: GuildMember) => void): this;
+ public on(event: 'rateLimit', listener: (rateLimit: RateLimitInfo) => void): this;
+ public on(event: 'ready', listener: () => void): this;
+ public on(event: 'reconnecting', listener: () => void): this;
+ public on(event: 'resume', listener: (replayed: number) => void): this;
+ public on(event: 'roleCreate', listener: (role: Role) => void): this;
+ public on(event: 'roleDelete', listener: (role: Role) => void): this;
+ public on(event: 'roleUpdate', listener: (oldRole: Role, newRole: Role) => void): this;
+ public on(event: 'typingStart', listener: (channel: Channel, user: User) => void): this;
+ public on(event: 'typingStop', listener: (channel: Channel, user: User) => void): this;
+ public on(event: 'userNoteUpdate', listener: (user: UserResolvable, oldNote: string, newNote: string) => void): this;
+ public on(event: 'userUpdate', listener: (oldUser: User, newUser: User) => void): this;
+ public on(event: 'voiceStateUpdate', listener: (oldMember: GuildMember, newMember: GuildMember) => void): this;
+ public on(event: 'warn', listener: (info: string) => void): this;
+ public on(event: string, listener: Function): this;
+
+ public once(event: 'channelCreate', listener: (channel: Channel) => void): this;
+ public once(event: 'channelDelete', listener: (channel: Channel) => void): this;
+ public once(event: 'channelPinsUpdate', listener: (channel: Channel, time: Date) => void): this;
+ public once(event: 'channelUpdate', listener: (oldChannel: Channel, newChannel: Channel) => void): this;
+ public once(event: 'clientUserGuildSettingsUpdate', listener: (clientUserGuildSettings: ClientUserGuildSettings) => void): this;
+ public once(event: 'clientUserSettingsUpdate', listener: (clientUserSettings: ClientUserSettings) => void): this;
+ public once(event: 'debug', listener: (info: string) => void): this;
+ public once(event: 'disconnect', listener: (event: any) => void): this;
+ public once(event: 'emojiCreate', listener: (emoji: Emoji) => void): this;
+ public once(event: 'emojiDelete', listener: (emoji: Emoji) => void): this;
+ public once(event: 'emojiUpdate', listener: (oldEmoji: Emoji, newEmoji: Emoji) => void): this;
+ public once(event: 'error', listener: (error: Error) => void): this;
+ public once(event: 'guildBanAdd', listener: (guild: Guild, user: User) => void): this;
+ public once(event: 'guildBanRemove', listener: (guild: Guild, user: User) => void): this;
+ public once(event: 'guildCreate', listener: (guild: Guild) => void): this;
+ public once(event: 'guildDelete', listener: (guild: Guild) => void): this;
+ public once(event: 'guildMemberAdd', listener: (member: GuildMember) => void): this;
+ public once(event: 'guildMemberAvailable', listener: (member: GuildMember) => void): this;
+ public once(event: 'guildMemberRemove', listener: (member: GuildMember) => void): this;
+ public once(event: 'guildMembersChunk', listener: (members: GuildMember[], guild: Guild) => void): this;
+ public once(event: 'guildMemberSpeaking', listener: (member: GuildMember, speaking: boolean) => void): this;
+ public once(event: 'guildMemberUpdate', listener: (oldMember: GuildMember, newMember: GuildMember) => void): this;
+ public once(event: 'guildUnavailable', listener: (guild: Guild) => void): this;
+ public once(event: 'guildUpdate', listener: (oldGuild: Guild, newGuild: Guild) => void): this;
+ public once(event: 'message', listener: (message: Message) => void): this;
+ public once(event: 'messageDelete', listener: (message: Message) => void): this;
+ public once(event: 'messageDeleteBulk', listener: (messages: Collection) => void): this;
+ public once(event: 'messageReactionAdd', listener: (messageReaction: MessageReaction, user: User) => void): this;
+ public once(event: 'messageReactionRemove', listener: (messageReaction: MessageReaction, user: User) => void): this;
+ public once(event: 'messageReactionRemoveAll', listener: (message: Message) => void): this;
+ public once(event: 'messageUpdate', listener: (oldMessage: Message, newMessage: Message) => void): this;
+ public once(event: 'presenceUpdate', listener: (oldMember: GuildMember, newMember: GuildMember) => void): this;
+ public once(event: 'rateLimit', listener: (rateLimit: RateLimitInfo) => void): this;
+ public once(event: 'ready', listener: () => void): this;
+ public once(event: 'reconnecting', listener: () => void): this;
+ public once(event: 'resume', listener: (replayed: number) => void): this;
+ public once(event: 'roleCreate', listener: (role: Role) => void): this;
+ public once(event: 'roleDelete', listener: (role: Role) => void): this;
+ public once(event: 'roleUpdate', listener: (oldRole: Role, newRole: Role) => void): this;
+ public once(event: 'typingStart', listener: (channel: Channel, user: User) => void): this;
+ public once(event: 'typingStop', listener: (channel: Channel, user: User) => void): this;
+ public once(event: 'userNoteUpdate', listener: (user: UserResolvable, oldNote: string, newNote: string) => void): this;
+ public once(event: 'userUpdate', listener: (oldUser: User, newUser: User) => void): this;
+ public once(event: 'voiceStateUpdate', listener: (oldMember: GuildMember, newMember: GuildMember) => void): this;
+ public once(event: 'warn', listener: (info: string) => void): this;
+ public once(event: string, listener: Function): this;
+ }
+
+ class ClientDataResolver {
+ constructor(client: Client);
+ public resolveBase64(data: Base64Resolvable): string;
+ public resolveChannel(channel: ChannelResolvable): Channel;
+ public resolveChannelID(channel: ChannelResolvable): Snowflake;
+ public resolveColor(color: ColorResolvable): number;
+ public resolveEmojiIdentifier(emoji: EmojiIdentifierResolvable): string;
+ public resolveFile(resource: BufferResolvable | Stream): Promise;
+ public resolveGuild(guild: GuildResolvable): Guild;
+ public resolveGuildMember(guild: GuildResolvable, user: UserResolvable): GuildMember;
+ public resolveImage(imge: BufferResolvable | Base64Resolvable): Promise;
+ public resolveInviteCode(data: InviteResolvable): string;
+ public resolveString(data: StringResolvable): string;
+ public resolveUser(user: UserResolvable): User;
+ public resolveUserID(user: UserResolvable): Snowflake;
+
+ public static resolveColor(color: ColorResolvable): number;
+ }
+
+ class ClientManager {
+ constructor(client: Client);
+ public client: Client;
+ public heartbeatInterval: number;
+ public status: number;
+ public connectToWebSocket(token: string, resolve: Function, reject: Function): void;
+ }
+
+ export class ClientUser extends User {
+ public blocked: Collection;
+ public email: string;
+ public friends: Collection;
+ public guildSettings: Collection;
+ public mfaEnabled: boolean;
+ public mobile: boolean;
+ public notes: Collection;
+ public premium: boolean;
+ public settings: ClientUserSettings;
+ public verified: boolean;
+ public acceptInvite(invite: Invite | string): Promise
+ public addFriend(user?: UserResolvable): Promise;
+ public createGroupDM(recipients: GroupDMRecipientOptions[]): Promise;
+ public createGuild(name: string, region: string, icon?: BufferResolvable | Base64Resolvable): Promise;
+ public fetchMentions(options?: { limit?: number; roles?: boolean, everyone?: boolean; guild?: Guild | Snowflake }): Promise;
+ public removeFriend(user?: UserResolvable): Promise;
+ public setActivity(name: string | null, options?: { url?: string, type?: ActivityType | number }): Promise;
+ public setAFK(afk: boolean): Promise;
+ public setAvatar(avatar: BufferResolvable | Base64Resolvable): Promise;
+ public setEmail(email: string, password: string): Promise;
+ public setGame(game: string | null, streamingURL?: string): Promise;
+ public setPassword(newPassword: string, oldPassword: string): Promise;
+ public setPresence(data: PresenceData): Promise;
+ public setStatus(status: PresenceStatus): Promise;
+ public setUsername(username: string, password?: string): Promise;
+ }
+
+ class ClientUserChannelOverride {
+ constructor(user: User, data: object);
+ private patch(data: object): void;
+
+ public messageNotifications: GuildChannelMessageNotifications;
+ public muted: boolean;
+ }
+
+ class ClientUserGuildSettings {
+ constructor(data: object, guild: Guild);
+ private patch(data: object): void;
+
+ public channelOverrides: Collection;
+ public readonly client: Client;
+ public guildID: Snowflake;
+ public messageNotifications: GuildChannelMessageNotifications;
+ public mobilePush: boolean;
+ public muted: boolean;
+ public suppressEveryone: boolean;
+ public update(name: string, value: any): Promise