setup linter
This commit is contained in:
parent
821e3d1053
commit
b485ed8a9f
16 changed files with 94 additions and 53 deletions
7
.eslintignore
Normal file
7
.eslintignore
Normal file
|
@ -0,0 +1,7 @@
|
|||
example/
|
||||
node_modules/
|
||||
lib/
|
||||
.github/
|
||||
docs/
|
||||
|
||||
*.d.ts
|
20
.eslintrc.json
Normal file
20
.eslintrc.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"@typescript-eslint/no-unused-vars": "error",
|
||||
"@typescript-eslint/no-explicit-any": "error",
|
||||
"@typescript-eslint/ban-ts-comment": "error"
|
||||
}
|
||||
}
|
|
@ -172,7 +172,7 @@ client.on("interaction", async (interaction) => {
|
|||
requestedBy: interaction.user,
|
||||
searchEngine: interaction.commandName === "soundcloud" ? QueryType.SOUNDCLOUD_SEARCH : QueryType.AUTO
|
||||
})
|
||||
.catch(() => {});
|
||||
.catch(Util.noop);
|
||||
if (!searchResult || !searchResult.tracks.length) return void interaction.followUp({ content: "No results were found!" });
|
||||
|
||||
const queue = await player.createQueue(interaction.guild, {
|
||||
|
|
13
package.json
13
package.json
|
@ -10,10 +10,12 @@
|
|||
"scripts": {
|
||||
"dev": "cd example/test && ts-node index.ts",
|
||||
"build": "rimraf lib && tsc",
|
||||
"build:check": "tsc --noEmit --incremental false",
|
||||
"format": "prettier --write \"src/**/*.ts\" \"example/**/*.ts\"",
|
||||
"lint": "tslint -p tsconfig.json",
|
||||
"docs": "docgen --jsdoc jsdoc.json --source src/*.ts src/**/*.ts --custom docs/index.yml --output docs/docs.json",
|
||||
"docs:test": "docgen --jsdoc jsdoc.json --source src/*.ts src/**/*.ts --custom docs/index.yml"
|
||||
"docs:test": "docgen --jsdoc jsdoc.json --source src/*.ts src/**/*.ts --custom docs/index.yml",
|
||||
"lint": "eslint src --ext .ts",
|
||||
"lint:fix": "eslint src --ext .ts --fix"
|
||||
},
|
||||
"funding": "https://github.com/Androz2091/discord-player?sponsor=1",
|
||||
"contributors": [
|
||||
|
@ -68,15 +70,16 @@
|
|||
"@discordjs/opus": "^0.5.3",
|
||||
"@types/node": "^15.12.2",
|
||||
"@types/ws": "^7.4.4",
|
||||
"@typescript-eslint/eslint-plugin": "^4.28.0",
|
||||
"@typescript-eslint/parser": "^4.28.0",
|
||||
"discord-api-types": "^0.18.1",
|
||||
"discord.js": "^13.0.0-dev.c850ae10270076c4b2e10b130dd8f88eed4ed201",
|
||||
"discord.js-docgen": "discordjs/docgen#ts-patch",
|
||||
"eslint": "^7.29.0",
|
||||
"jsdoc-babel": "^0.5.0",
|
||||
"prettier": "^2.3.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-node": "^10.0.0",
|
||||
"tslint": "^6.1.3",
|
||||
"tslint-config-prettier": "^1.18.0",
|
||||
"typescript": "^4.3.2"
|
||||
"typescript": "^4.3.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import { QueryResolver } from "./utils/QueryResolver";
|
|||
import YouTube from "youtube-sr";
|
||||
import { Util } from "./utils/Util";
|
||||
import Spotify from "spotify-url-info";
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
import { Client as SoundCloud } from "soundcloud-scraper";
|
||||
import { Playlist } from "./Structures/Playlist";
|
||||
|
@ -49,7 +50,7 @@ class Player extends EventEmitter<PlayerEvents> {
|
|||
this.client.on("voiceStateUpdate", this._handleVoiceState.bind(this));
|
||||
|
||||
if (this.options?.autoRegisterExtractor) {
|
||||
let nv: any;
|
||||
let nv: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
|
||||
if ((nv = Util.require("@discord-player/extractor"))) {
|
||||
["Attachment", "Facebook", "Reverbnation", "Vimeo"].forEach((ext) => void this.use(ext, nv[ext]));
|
||||
|
@ -139,7 +140,7 @@ class Player extends EventEmitter<PlayerEvents> {
|
|||
|
||||
try {
|
||||
prev.destroy();
|
||||
} catch {}
|
||||
} catch {} // eslint-disable-line no-empty
|
||||
this.queues.delete(guild.id);
|
||||
|
||||
return prev;
|
||||
|
@ -162,6 +163,7 @@ class Player extends EventEmitter<PlayerEvents> {
|
|||
options.requestedBy = this.client.users.resolve(options.requestedBy);
|
||||
if (!("searchEngine" in options)) options.searchEngine = QueryType.AUTO;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
for (const [_, extractor] of this.extractors) {
|
||||
if (!extractor.validate(query)) continue;
|
||||
const data = await extractor.handle(query);
|
||||
|
@ -194,11 +196,11 @@ class Player extends EventEmitter<PlayerEvents> {
|
|||
case QueryType.YOUTUBE_SEARCH: {
|
||||
const videos = await YouTube.search(query, {
|
||||
type: "video"
|
||||
}).catch(() => {});
|
||||
}).catch(Util.noop); // eslint-disable-line @typescript-eslint/no-empty-function
|
||||
if (!videos) return { playlist: null, tracks: [] };
|
||||
|
||||
const tracks = videos.map((m) => {
|
||||
(m as any).source = "youtube";
|
||||
(m as any).source = "youtube"; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
return new Track(this, {
|
||||
title: m.title,
|
||||
description: m.description,
|
||||
|
@ -216,12 +218,13 @@ class Player extends EventEmitter<PlayerEvents> {
|
|||
}
|
||||
case QueryType.SOUNDCLOUD_TRACK:
|
||||
case QueryType.SOUNDCLOUD_SEARCH: {
|
||||
const result: any[] = QueryResolver.resolve(query) === QueryType.SOUNDCLOUD_TRACK ? [{ url: query }] : await soundcloud.search(query, "track").catch(() => {});
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-empty-function
|
||||
const result: any[] = QueryResolver.resolve(query) === QueryType.SOUNDCLOUD_TRACK ? [{ url: query }] : await soundcloud.search(query, "track").catch(Util.noop);
|
||||
if (!result || !result.length) return { playlist: null, tracks: [] };
|
||||
const res: Track[] = [];
|
||||
|
||||
for (const r of result) {
|
||||
const trackInfo = await soundcloud.getSongInfo(r.url).catch(() => {});
|
||||
const trackInfo = await soundcloud.getSongInfo(r.url).catch(Util.noop); // eslint-disable-line @typescript-eslint/no-empty-function
|
||||
if (!trackInfo) continue;
|
||||
|
||||
const track = new Track(this, {
|
||||
|
@ -243,7 +246,7 @@ class Player extends EventEmitter<PlayerEvents> {
|
|||
return { playlist: null, tracks: res };
|
||||
}
|
||||
case QueryType.SPOTIFY_SONG: {
|
||||
const spotifyData = await Spotify.getData(query).catch(() => {});
|
||||
const spotifyData = await Spotify.getData(query).catch(Util.noop); // eslint-disable-line @typescript-eslint/no-empty-function
|
||||
if (!spotifyData) return { playlist: null, tracks: [] };
|
||||
const spotifyTrack = new Track(this, {
|
||||
title: spotifyData.name,
|
||||
|
@ -264,7 +267,7 @@ class Player extends EventEmitter<PlayerEvents> {
|
|||
}
|
||||
case QueryType.SPOTIFY_PLAYLIST:
|
||||
case QueryType.SPOTIFY_ALBUM: {
|
||||
const spotifyPlaylist = await Spotify.getData(query).catch(() => {});
|
||||
const spotifyPlaylist = await Spotify.getData(query).catch(Util.noop); // eslint-disable-line @typescript-eslint/no-empty-function
|
||||
if (!spotifyPlaylist) return { playlist: null, tracks: [] };
|
||||
|
||||
const playlist = new Playlist(this, {
|
||||
|
@ -290,6 +293,7 @@ class Player extends EventEmitter<PlayerEvents> {
|
|||
});
|
||||
|
||||
if (spotifyPlaylist.type !== "playlist") {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
playlist.tracks = spotifyPlaylist.tracks.items.map((m: any) => {
|
||||
const data = new Track(this, {
|
||||
title: m.name ?? "",
|
||||
|
@ -307,6 +311,7 @@ class Player extends EventEmitter<PlayerEvents> {
|
|||
return data;
|
||||
}) as Track[];
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
playlist.tracks = spotifyPlaylist.tracks.items.map((m: any) => {
|
||||
const data = new Track(this, {
|
||||
title: m.track.name ?? "",
|
||||
|
@ -328,7 +333,7 @@ class Player extends EventEmitter<PlayerEvents> {
|
|||
return { playlist: playlist, tracks: playlist.tracks };
|
||||
}
|
||||
case QueryType.SOUNDCLOUD_PLAYLIST: {
|
||||
const data = await SoundCloud.getPlaylist(query).catch(() => {});
|
||||
const data = await SoundCloud.getPlaylist(query).catch(Util.noop); // eslint-disable-line @typescript-eslint/no-empty-function
|
||||
if (!data) return { playlist: null, tracks: [] };
|
||||
|
||||
const res = new Playlist(this, {
|
||||
|
@ -367,11 +372,11 @@ class Player extends EventEmitter<PlayerEvents> {
|
|||
return { playlist: res, tracks: res.tracks };
|
||||
}
|
||||
case QueryType.YOUTUBE_PLAYLIST: {
|
||||
const ytpl = await YouTube.getPlaylist(query).catch(() => {});
|
||||
const ytpl = await YouTube.getPlaylist(query).catch(Util.noop); // eslint-disable-line @typescript-eslint/no-empty-function
|
||||
if (!ytpl) return { playlist: null, tracks: [] };
|
||||
|
||||
// @todo: better way of handling large playlists
|
||||
await ytpl.fetch().catch(() => {});
|
||||
await ytpl.fetch().catch(Util.noop); // eslint-disable-line @typescript-eslint/no-empty-function
|
||||
|
||||
const playlist: Playlist = new Playlist(this, {
|
||||
title: ytpl.title,
|
||||
|
@ -420,6 +425,7 @@ class Player extends EventEmitter<PlayerEvents> {
|
|||
* @param {boolean} [force=false] Overwrite existing extractor with this name (if available)
|
||||
* @returns {ExtractorModel}
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
use(extractorName: string, extractor: ExtractorModel | any, force = false): ExtractorModel {
|
||||
if (!extractorName) throw new Error("Cannot use unknown extractor!");
|
||||
if (this.extractors.has(extractorName) && !force) return this.extractors.get(extractorName);
|
||||
|
|
|
@ -2,13 +2,14 @@ import { ExtractorModelData } from "../types/types";
|
|||
|
||||
class ExtractorModel {
|
||||
name: string;
|
||||
private _raw: any;
|
||||
private _raw: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
|
||||
/**
|
||||
* Model for raw Discord Player extractors
|
||||
* @param {string} extractorName Name of the extractor
|
||||
* @param {object} data Extractor object
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
constructor(extractorName: string, data: any) {
|
||||
/**
|
||||
* The extractor name
|
||||
|
@ -37,6 +38,7 @@ class ExtractorModel {
|
|||
return {
|
||||
playlist: data.playlist ?? null,
|
||||
data:
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
data.info?.map((m: any) => ({
|
||||
title: m.title,
|
||||
duration: m.duration,
|
||||
|
|
|
@ -16,7 +16,7 @@ class Playlist {
|
|||
};
|
||||
public id: string;
|
||||
public url: string;
|
||||
public readonly rawPlaylist?: any;
|
||||
public readonly rawPlaylist?: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
|
||||
/**
|
||||
* Playlist constructor
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Collection, Guild, StageChannel, VoiceChannel } from "discord.js";
|
|||
import { Player } from "../Player";
|
||||
import { StreamDispatcher } from "../VoiceInterface/BasicStreamDispatcher";
|
||||
import Track from "./Track";
|
||||
import { FiltersName, PlayerOptions, PlayOptions, QueueFilters, QueueRepeatMode } from "../types/types";
|
||||
import { PlayerOptions, PlayOptions, QueueFilters, QueueRepeatMode } from "../types/types";
|
||||
import ytdl from "discord-ytdl-core";
|
||||
import { AudioResource, StreamType } from "@discordjs/voice";
|
||||
import { Util } from "../utils/Util";
|
||||
|
@ -19,9 +19,9 @@ class Queue<T = unknown> {
|
|||
public playing = false;
|
||||
public metadata?: T = null;
|
||||
public repeatMode: QueueRepeatMode = 0;
|
||||
private _streamTime: number = 0;
|
||||
private _streamTime = 0;
|
||||
public _cooldownsTimeout = new Collection<string, NodeJS.Timeout>();
|
||||
private _activeFilters: any[] = [];
|
||||
private _activeFilters: any[] = []; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
private _filtersUpdate = false;
|
||||
public destroyed = false;
|
||||
|
||||
|
@ -134,7 +134,7 @@ class Queue<T = unknown> {
|
|||
});
|
||||
this.connection = connection;
|
||||
|
||||
if (channel.type === "stage") await channel.guild.me.voice.setRequestToSpeak(true).catch(() => {});
|
||||
if (channel.type === "stage") await channel.guild.me.voice.setRequestToSpeak(true).catch(Util.noop); // eslint-disable-line @typescript-eslint/no-empty-function
|
||||
|
||||
this.connection.on("error", (err) => this.player.emit("connectionError", this, err));
|
||||
this.connection.on("debug", (msg) => this.player.emit("debug", this, msg));
|
||||
|
@ -332,7 +332,7 @@ class Queue<T = unknown> {
|
|||
});
|
||||
}
|
||||
|
||||
const _filters: any[] = [];
|
||||
const _filters: any[] = []; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
|
||||
for (const filter in filters) {
|
||||
if (filters[filter as keyof QueueFilters] === true) _filters.push(filter);
|
||||
|
@ -466,7 +466,7 @@ class Queue<T = unknown> {
|
|||
const info = await ytdl
|
||||
.getInfo(track.url)
|
||||
.then((x) => x.related_videos[0])
|
||||
.catch(() => {});
|
||||
.catch(Util.noop); // eslint-disable-line @typescript-eslint/no-empty-function
|
||||
if (!info) {
|
||||
if (this.options.leaveOnEnd) this.destroy();
|
||||
return void this.player.emit("queueEnd", this);
|
||||
|
|
|
@ -18,10 +18,10 @@ import Track from "../Structures/Track";
|
|||
import { Util } from "../utils/Util";
|
||||
|
||||
export interface VoiceEvents {
|
||||
error: (error: AudioPlayerError) => any;
|
||||
debug: (message: string) => any;
|
||||
start: () => any;
|
||||
finish: () => any;
|
||||
error: (error: AudioPlayerError) => any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
debug: (message: string) => any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
start: () => any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
finish: () => any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
}
|
||||
|
||||
class StreamDispatcher extends EventEmitter<VoiceEvents> {
|
||||
|
@ -29,7 +29,7 @@ class StreamDispatcher extends EventEmitter<VoiceEvents> {
|
|||
public readonly audioPlayer: AudioPlayer;
|
||||
public readonly channel: VoiceChannel | StageChannel;
|
||||
public audioResource?: AudioResource<Track>;
|
||||
private readyLock: boolean = false;
|
||||
private readyLock = false;
|
||||
|
||||
/**
|
||||
* Creates new connection object
|
||||
|
@ -108,6 +108,7 @@ class StreamDispatcher extends EventEmitter<VoiceEvents> {
|
|||
* @param {object} [ops={}] Options
|
||||
* @returns {AudioResource}
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
createStream(src: Readable | Duplex | string, ops?: { type?: StreamType; data?: any }) {
|
||||
this.audioResource = createAudioResource(src, {
|
||||
inputType: ops?.type ?? StreamType.Arbitrary,
|
||||
|
@ -134,7 +135,7 @@ class StreamDispatcher extends EventEmitter<VoiceEvents> {
|
|||
try {
|
||||
this.audioPlayer.stop(true);
|
||||
this.voiceConnection.destroy();
|
||||
} catch {}
|
||||
} catch {} // eslint-disable-line no-empty
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -52,7 +52,7 @@ class VoiceUtils {
|
|||
let conn = joinVoiceChannel({
|
||||
guildId: channel.guild.id,
|
||||
channelId: channel.id,
|
||||
adapterCreator: (channel.guild as any).voiceAdapterCreator,
|
||||
adapterCreator: (channel.guild as any).voiceAdapterCreator, // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
selfDeaf: Boolean(options.deaf)
|
||||
});
|
||||
|
||||
|
|
|
@ -84,9 +84,9 @@ export interface RawTrackData {
|
|||
requestedBy: User;
|
||||
playlist?: Playlist;
|
||||
source?: TrackSource;
|
||||
engine?: any;
|
||||
engine?: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
live?: boolean;
|
||||
raw?: any;
|
||||
raw?: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -182,7 +182,7 @@ export interface ExtractorModelData {
|
|||
};
|
||||
id: string;
|
||||
url: string;
|
||||
rawPlaylist?: any;
|
||||
rawPlaylist?: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
};
|
||||
data: {
|
||||
title: string;
|
||||
|
@ -304,6 +304,7 @@ export enum QueryType {
|
|||
* @param {Track} track The track
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
export interface PlayerEvents {
|
||||
botDisconnect: (queue: Queue) => any;
|
||||
channelEmpty: (queue: Queue) => any;
|
||||
|
@ -317,6 +318,8 @@ export interface PlayerEvents {
|
|||
trackStart: (queue: Queue, track: Track) => any;
|
||||
}
|
||||
|
||||
/* eslint-enable @typescript-eslint/no-explicit-any */
|
||||
|
||||
/**
|
||||
* @typedef {object} PlayOptions
|
||||
* @property {boolean} [filtersUpdate=false] If this play was triggered for filters update
|
||||
|
@ -384,7 +387,7 @@ export interface PlaylistInitData {
|
|||
};
|
||||
id: string;
|
||||
url: string;
|
||||
rawPlaylist?: any;
|
||||
rawPlaylist?: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -90,7 +90,7 @@ const FilterList = {
|
|||
},
|
||||
|
||||
toString() {
|
||||
return this.names.map((m) => (this as any)[m]).join(",");
|
||||
return this.names.map((m) => (this as any)[m]).join(","); // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
},
|
||||
|
||||
create(filter?: FiltersName[]): string {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { validateID, validateURL } from "ytdl-core";
|
||||
import { YouTube } from "youtube-sr";
|
||||
import { QueryType } from "../types/types";
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
import { validateURL as SoundcloudValidateURL } from "soundcloud-scraper";
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ class Util {
|
|||
* @param {object} durObj The duration object
|
||||
* @returns {string}
|
||||
*/
|
||||
static durationString(durObj: object) {
|
||||
static durationString(durObj: Record<string, number>) {
|
||||
return Object.values(durObj)
|
||||
.map((m) => (isNaN(m) ? 0 : m))
|
||||
.join(":");
|
||||
|
@ -58,6 +58,7 @@ class Util {
|
|||
* @param {any[]} arr The array
|
||||
* @returns {any}
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
static last<T = any>(arr: T[]): T {
|
||||
if (!Array.isArray(arr)) return;
|
||||
return arr[arr.length - 1];
|
||||
|
@ -93,6 +94,10 @@ class Util {
|
|||
static wait(time: number) {
|
||||
return new Promise((r) => setTimeout(r, time).unref());
|
||||
}
|
||||
|
||||
static get noop() {
|
||||
return () => {}; // eslint-disable-line @typescript-eslint/no-empty-function
|
||||
}
|
||||
}
|
||||
|
||||
export { Util };
|
||||
|
|
8
tsconfig.eslint.json
Normal file
8
tsconfig.eslint.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
"**/*.js"
|
||||
],
|
||||
"exclude": []
|
||||
}
|
15
tslint.json
15
tslint.json
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"defaultSeverity": "error",
|
||||
"extends": ["tslint:recommended", "tslint-config-prettier"],
|
||||
"jsRules": {
|
||||
"no-unused-expression": true
|
||||
},
|
||||
"rules": {
|
||||
"object-literal-sort-keys": false,
|
||||
"interface-name": false,
|
||||
"no-empty": false,
|
||||
"no-console": false,
|
||||
"radix": false
|
||||
},
|
||||
"rulesDirectory": []
|
||||
}
|
Loading…
Reference in a new issue