From b2bfe4f517efaee1ca464500f668af5edb6f3dc3 Mon Sep 17 00:00:00 2001 From: hwangsihu Date: Mon, 16 Sep 2024 09:08:15 +0900 Subject: [PATCH 01/10] Update --- .env.example | 36 +++---- Lavalink/example.application.yml | 47 +++++--- biome.json | 66 ++++++------ locales/ChineseCN.json | 1 - locales/ChineseTW.json | 1 - locales/EnglishUS.json | 7 +- locales/French.json | 1 - locales/German.json | 1 - locales/Hindi.json | 1 - locales/Indonesian.json | 1 - locales/Japanese.json | 1 - locales/Korean.json | 35 +++--- locales/Norwegian.json | 1 - locales/Polish.json | 1 - locales/PortuguesePT.json | 1 - locales/Russian.json | 1 - locales/SpanishES.json | 1 - locales/Vietnamese.json | 1 - run.bat | 19 +--- src/LavaClient.ts | 2 +- src/commands/config/Setup.ts | 7 +- src/commands/dev/GuildList.ts | 2 +- src/events/client/Ready.ts | 2 +- src/events/client/SetupButtons.ts | 172 +++++++++++++++--------------- src/events/player/QueueEnd.ts | 1 - src/events/player/TrackStart.ts | 6 +- src/index.ts | 2 +- src/plugin/plugins/keepAlive.ts | 2 +- src/utils/Utils.ts | 4 +- tsconfig.json | 6 +- 30 files changed, 204 insertions(+), 225 deletions(-) diff --git a/.env.example b/.env.example index ac3eab50f..8e9ab5b7a 100644 --- a/.env.example +++ b/.env.example @@ -1,18 +1,18 @@ -TOKEN= "" # Your bot token. -CLIENT_ID= "" # Your bot's client ID (If this value is left blank, bots cannot be invited using /invite or /about commands.). -DEFAULT_LANGUAGE= "EnglishUS" # Default language for bot -PREFIX= "!" # Your prefix. -OWNER_IDS= ["",""] # Your discord id (You can add multiple ids.). -GUILD_ID= "" # Your server ID (If you want to use the bot for a single server). -TOPGG= "" # Your Top.gg API key. Obtain this from https://top.gg -KEEP_ALIVE= "false" # true for keep alive in https://replit.com -LOG_CHANNEL_ID= "" # If you enter this, you will be able to receive the status of Lavalink nodes and guild join/leave logs through the corresponding channel. -LOG_COMMANDS_ID= "" # The channel ID where command usage logs will be sent. -BOT_STATUS= "online" # Your bot status (online, dnd, idle, invisible or offline). -BOT_ACTIVITY_TYPE= 0 # Activity type is a number from 0 to 5. See more here: https://discord.com/developers/docs/topics/gateway-events#activity-object-activity-types -BOT_ACTIVITY=" Lavamusic" # Your bot activity. -DATABASE_URL= "" # Your database url (If you want to use sqlite, then you can leave it blank.). -AUTO_NODE=" false" # true for auto node. It is given from lavainfo-api (https://lavainfo-api.deno.dev). -SEARCH_ENGINE= "YouTubeMusic" # Search engine to be used when playing the song. You can use: YouTube, YouTubeMusic, SoundCloud, Spotify, Apple, Deezer, Yandex and JioSaavn -GENIUS_API= "" # Sign up and get your own api at (https://genius.com/) to fetch your lyrics (CLIENT TOKEN) -NODES=[{"id":"main","host":"localhost","port":2333,"authorization":"youshallnotpass"}] +TOKEN="" # Your bot token. +CLIENT_ID="" # Your bot's client ID (If this value is left blank, bots cannot be invited using /invite or /about commands.). +DEFAULT_LANGUAGE="EnglishUS" # Default language for bot +PREFIX="!" # Your prefix. +OWNER_IDS=["",""] # Your discord id (You can add multiple ids.). +GUILD_ID="" # Your server ID (If you want to use the bot for a single server). +TOPGG="" # Your Top.gg API key. Obtain this from https://top.gg +KEEP_ALIVE="false" # true for keep alive in https://replit.com +LOG_CHANNEL_ID="" # If you enter this, you will be able to receive the status of Lavalink nodes and guild join/leave logs through the corresponding channel. +LOG_COMMANDS_ID="" # The channel ID where command usage logs will be sent. +BOT_STATUS="online" # Your bot status (online, dnd, idle, invisible or offline). +BOT_ACTIVITY_TYPE=0 # Activity type is a number from 0 to 5. See more here: https://discord.com/developers/docs/topics/gateway-events#activity-object-activity-types +BOT_ACTIVITY=="Lavamusic" # Your bot activity. +DATABASE_URL="" # Your database url (If you want to use sqlite, then you can leave it blank.). +AUTO_NODE=="false" # true for auto node. It is given from lavainfo-api (https://lavainfo-api.deno.dev). +SEARCH_ENGINE="YouTubeMusic" # Search engine to be used when playing the song. You can use: YouTube, YouTubeMusic, SoundCloud, Spotify, Apple, Deezer, Yandex and JioSaavn +GENIUS_API="" # Sign up and get your own api at (https://genius.com/) to fetch your lyrics (CLIENT TOKEN) +NODES=[{"id":"Local Node","host":"localhost","port":2333,"authorization":"youshallnotpass"}] diff --git a/Lavalink/example.application.yml b/Lavalink/example.application.yml index d2ae0f771..244512cd4 100644 --- a/Lavalink/example.application.yml +++ b/Lavalink/example.application.yml @@ -18,8 +18,15 @@ plugins: mixcloud: true # mixcloud.com soundgasm: true # soundgasm.net pixeldrain: true # pixeldrain.com - jiosaavn: + jiosaavn: apiURL: "https://saavn.dev/api" # The API URL for JioSaavn + lavalyrics: + # sources is used to sort the different lyrics sources by priority (from highest to lowest) + sources: + - spotify + - youtube + - deezer + - yandexMusic lavasrc: providers: # Custom providers for track loading. This is the default # - "dzisrc:%ISRC%" # Deezer ISRC provider @@ -34,18 +41,21 @@ plugins: yandexmusic: false # Enable Yandex Music source flowerytts: false # Enable Flowery TTS source youtube: true # Enable YouTube search source (https://github.com/topi314/LavaSearch) + vkmusic: false # Enable Vk Music source lyrics-sources: - spotify: false # Enable Spotify lyrics source - deezer: false # Enable Deezer lyrics source - youtube: false # Enable YouTube lyrics source - yandexmusic: false # Enable Yandex Music lyrics source + spotify: true # Enable Spotify lyrics source + deezer: true # Enable Deezer lyrics source + youtube: true # Enable YouTube lyrics source + yandexmusic: true # Enable Yandex Music lyrics source + vkmusic: true # Enable Vk Music lyrics source spotify: clientId: "your client id" clientSecret: "your client secret" - spDc: "your sp dc cookie" # the sp dc cookie used for accessing the spotify lyrics api + # spDc: "your sp dc cookie" # the sp dc cookie used for accessing the spotify lyrics api countryCode: "US" # the country code you want to use for filtering the artists top tracks. See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 playlistLoadLimit: 6 # The number of pages at 100 tracks each albumLoadLimit: 6 # The number of pages at 50 tracks each + resolveArtistsInSearch: true # Whether to resolve artists in track search results (can be slow) localFiles: false # Enable local files support with Spotify playlists. Please note `uri` & `isrc` will be `null` & `identifier` will be `"local"` applemusic: countryCode: "US" # the country code you want to use for filtering the artists top tracks and language. See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 @@ -61,6 +71,8 @@ plugins: albumLoadLimit: 6 # The number of pages at 300 tracks each deezer: masterDecryptionKey: "your master decryption key" # the master key used for decrypting the deezer tracks. (yes this is not here you need to get it from somewhere else) + # arl: "your deezer arl" # the arl cookie used for accessing the deezer api this is optional but required for formats above MP3_128 + formats: [ "FLAC", "MP3_320", "MP3_256", "MP3_128", "MP3_64", "AAC_64" ] # the formats you want to use for the deezer tracks. "FLAC", "MP3_320", "MP3_256" & "AAC_64" are only available for premium users and require a valid arl yandexmusic: accessToken: "your access token" # the token used for accessing the yandex music api. See https://github.com/TopiSenpai/LavaSrc#yandex-music playlistLoadLimit: 1 # The number of pages at 100 tracks each @@ -74,6 +86,11 @@ plugins: audioFormat: "mp3" # supported formats are: mp3, ogg_opus, ogg_vorbis, aac, wav, and flac. Default format is mp3 youtube: countryCode: "US" # the country code you want to use for searching lyrics via ISRC. See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 + vkmusic: + userToken: "your user token" # This token is needed for authorization in the api. Guide: https://github.com/topi314/LavaSrc#vk-music + playlistLoadLimit: 1 # The number of pages at 50 tracks each + artistLoadLimit: 1 # The number of pages at 10 tracks each + recommendationsLoadLimit: 10 # Number of tracks youtube: enabled: true # Whether this source can be used. allowSearch: true # Whether "ytsearch:" and "ytmsearch:" can be used. @@ -85,11 +102,7 @@ plugins: - MUSIC - WEB - ANDROID_TESTSUITE - - ANDROID_MUSIC - TVHTML5EMBEDDED - - ANDROID_LITE - - MEDIA_CONNECT - - IOS # This secure your lavalink is working and playing music if you used this two things below. #oauth: # enabled: true # IF YOU RUN YOUR LAVALINK CHECK YOUR CONSOLE AND CLICK THE GOOGLE.COM/DEVICES LINK AND THERE IS A CODE THAT YOU NEED TO PUT IN TO THE GOOGLE AND USE A BURNER ACCOUNT OR ALT ACCOUNT THERE IS A POSSIBLE CHANGE YOU CAN GET BANNED FROM GOOGLE OR YOUTUBE SO JUST USE A BURNER ACCOUNT IN CASE. @@ -101,15 +114,17 @@ lavalink: - dependency: "com.github.appujet:jiosaavn-plugin:0.1.7" repository: "https://jitpack.io" - dependency: "com.dunctebot:skybot-lavalink-plugin:1.7.0" - snapshot: false # set to true if you want to use snapshot builds. + snapshot: false # set to true if you want to use snapshot builds + - dependency: "com.github.topi314.lavalyrics:lavalyrics-plugin:1.0.0" + snapshot: false # set to true if you want to use snapshot builds (see below) - dependency: "com.github.topi314.lavasearch:lavasearch-plugin:1.0.0" - snapshot: false # set to true if you want to use snapshot builds. + snapshot: false # set to true if you want to use snapshot builds - dependency: "com.github.topi314.lavasrc:lavasrc-plugin:4.2.0" - snapshot: false # set to true if you want to use snapshot builds. + snapshot: false # set to true if you want to use snapshot builds - dependency: "com.github.topi314.sponsorblock:sponsorblock-plugin:3.0.1" - snapshot: false # set to true if you want to use snapshot builds. - - dependency: "dev.lavalink.youtube:youtube-plugin:1.7.2" - snapshot: false # set to true if you want to use snapshot builds. + snapshot: false # set to true if you want to use snapshot builds + - dependency: "dev.lavalink.youtube:youtube-plugin:1.8.0" + snapshot: false # set to true if you want to use snapshot builds pluginsDir: './plugins' server: password: "youshallnotpass" diff --git a/biome.json b/biome.json index 52c0883ac..b85551a9e 100644 --- a/biome.json +++ b/biome.json @@ -7,16 +7,25 @@ "enabled": true, "rules": { "all": true, - "suspicious": { - "noConfusingVoidType": "off", - "noConsole": "off", - "noConsoleLog": "off", - "noEmptyBlockStatements": "off", - "noEvolvingTypes": "off", - "noExplicitAny": "off", - "noGlobalIsFinite": "off", - "noGlobalIsNan": "off", - "useAwait": "off" + "complexity": { + "noBannedTypes": "off", + "noExcessiveCognitiveComplexity": "off", + "noForEach": "off", + "noStaticOnlyClass": "off" + }, + "correctness": { + "noNodejsModules": "off", + "noUnusedFunctionParameters": "off", + "noUnusedVariables": "off", + "noVoidTypeReturn": "off", + "useImportExtensions": "off" + }, + "performance": { + "noBarrelFile": "off", + "useTopLevelRegex": "off" + }, + "security": { + "noGlobalEval": "off" }, "style": { "noDefaultExport": "off", @@ -27,34 +36,21 @@ "useBlockStatements": "off", "useDefaultSwitchClause": "off", "useFilenamingConvention": "off", + "useImportType": "warn", "useNamingConvention": "off", "useNumberNamespace": "off", - "useSingleCaseStatement": "off", - "useImportType": "warn" + "useSingleCaseStatement": "off" }, - "complexity": { - "noBannedTypes": "off", - "noForEach": "off", - "useOptionalChain": "off", - "noStaticOnlyClass": "off", - "noExcessiveCognitiveComplexity": { - "level": "warn", - "options": { - "maxAllowedComplexity": 255 - } - } - }, - "security": { - "noGlobalEval": "off" - }, - "correctness": { - "noNodejsModules": "off", - "noVoidTypeReturn": "off", - "useImportExtensions": "off" - }, - "performance": { - "noBarrelFile": "off", - "useTopLevelRegex": "off" + "suspicious": { + "noConfusingVoidType": "off", + "noConsole": "off", + "noConsoleLog": "off", + "noEmptyBlockStatements": "off", + "noEvolvingTypes": "off", + "noExplicitAny": "off", + "noGlobalIsFinite": "off", + "noGlobalIsNan": "off", + "useAwait": "off" } } }, diff --git a/locales/ChineseCN.json b/locales/ChineseCN.json index bf16f1eff..2dc1bb82f 100644 --- a/locales/ChineseCN.json +++ b/locales/ChineseCN.json @@ -619,7 +619,6 @@ "no_previous_track": "没有上一首曲目。", "playing_previous": "正在播放上一首曲目。", "previous_footer": "由 {displayName} 播放上一首曲目", - "rewind_limit": "您不能将音乐倒回到超过歌曲长度的位置。", "rewinded": "已倒回音乐。", "rewind_footer": "由 {displayName} 倒回", "forward_limit": "您不能将音乐快进到超过歌曲长度的位置。", diff --git a/locales/ChineseTW.json b/locales/ChineseTW.json index affb23d34..03ce7471d 100644 --- a/locales/ChineseTW.json +++ b/locales/ChineseTW.json @@ -619,7 +619,6 @@ "no_previous_track": "沒有上一首曲目。", "playing_previous": "正在播放上一首曲目。", "previous_footer": "由 {displayName} 播放上一首曲目", - "rewind_limit": "您不能將音樂倒帶到超過歌曲長度的位置。", "rewinded": "已倒帶音樂。", "rewind_footer": "由 {displayName} 資訊", "forward_limit": "您不能將音樂快轉到超過歌曲長度的位置。", diff --git a/locales/EnglishUS.json b/locales/EnglishUS.json index bc479f6d4..f7b96855f 100644 --- a/locales/EnglishUS.json +++ b/locales/EnglishUS.json @@ -33,7 +33,7 @@ "options": { "command": "The command you want to get info on" }, - "content": "Hey there! I'm {bot}, a music bot made with [Lavamusic](https://github.com/appujet/lavamusic) and Discord. You can use `{prefix}help ` to get more info on a command.", + "content": "Hey there! I'm {bot}, a music bot made with [Lavamusic](https://github.com/appujet/lavamusic) and Discord.js. You can use `{prefix}help ` to get more info on a command.", "title": "Help Menu", "not_found": "This `{cmdName}` command does not exist.", "help_cmd": "**Description:** {description}\n**Usage:** {usage}\n**Examples:** {examples}\n**Aliases:** {aliases}\n**Category:** {category}\n**Cooldown:** {cooldown} seconds\n**Permissions:** {premUser}\n**Bot Permissions:** {premBot}\n**Developer Only:** {dev}\n**Slash Command:** {slash}\n**Args:** {args}\n**Player:** {player}\n**DJ:** {dj}\n**DJ Permissions:** {djPerm}\n**Voice:** {voice}", @@ -41,7 +41,7 @@ }, "botinfo": { "description": "Information about the bot", - "content": "Bot Information:\n- **Operating System**: {osInfo}\n- **Uptime**: {osUptime}\n- **Hostname**: {osHostname}\n- **CPU Architecture**: {cpuInfo}\n- **CPU Usage**: {cpuUsed}%\n- **Memory Usage**: {memUsed}MB / {memTotal}GB\n- **Node Version**: {nodeVersion}\n- **Discord Version**: {discordJsVersion}\n- **Connected to** {guilds} guilds, {channels} channels, and {users} users\n- **Total Commands**: {commands}" + "content": "Bot Information:\n- **Operating System**: {osInfo}\n- **Uptime**: {osUptime}\n- **Hostname**: {osHostname}\n- **CPU Architecture**: {cpuInfo}\n- **CPU Usage**: {cpuUsed}%\n- **Memory Usage**: {memUsed}MB / {memTotal}GB\n- **Node Version**: {nodeVersion}\n- **Discord.js Version**: {discordJsVersion}\n- **Connected to** {guilds} guilds, {channels} channels, and {users} users\n- **Total Commands**: {commands}" }, "about": { "description": "Shows information about the bot", @@ -110,7 +110,7 @@ "errors": { "channel_exists": "The song request channel already exists.", "channel_not_exists": "The song request channel doesn't exist.", - "channel_delete_fail": "The song request channel has been deleted. If the channel is not deleted normally, please delete it yourself." + "channel_delete_fail": "The setup channel has been deleted from the database. Please delete the channel yourself." }, "messages": { "channel_created": "The song request channel has been created in <#{channelId}>.", @@ -631,7 +631,6 @@ "no_previous_track": "There is no previous track.", "playing_previous": "Playing the previous track.", "previous_footer": "Playing the previous track by {displayName}", - "rewind_limit": "You cannot rewind the music more than the length of the song.", "rewinded": "Rewinded the music.", "rewind_footer": "Rewinded by {displayName}", "forward_limit": "You cannot forward the music more than the length of the song.", diff --git a/locales/French.json b/locales/French.json index b0ca2a7bb..60a8a58e2 100644 --- a/locales/French.json +++ b/locales/French.json @@ -619,7 +619,6 @@ "no_previous_track": "Il n'y a pas de piste précédente.", "playing_previous": "Lecture de la piste précédente.", "previous_footer": "Lecture de la piste précédente par {displayName}", - "rewind_limit": "Vous ne pouvez pas rembobiner la musique plus que la longueur de la chanson.", "rewinded": "Rembobinage de la musique.", "rewind_footer": "Rembobiné par {displayName}", "forward_limit": "Vous ne pouvez pas avancer la musique plus que la longueur de la chanson.", diff --git a/locales/German.json b/locales/German.json index 53b894886..22540ea90 100644 --- a/locales/German.json +++ b/locales/German.json @@ -619,7 +619,6 @@ "no_previous_track": "Es gibt keinen vorherigen Track.", "playing_previous": "Spiele den vorherigen Track ab.", "previous_footer": "Spiele den vorherigen Track ab von {displayName}", - "rewind_limit": "Du kannst die Musik nicht mehr als die Länge des Songs zurückspulen.", "rewinded": "Musik zurückgespult.", "rewind_footer": "Zurückgespult von {displayName}", "forward_limit": "Du kannst die Musik nicht mehr als die Länge des Songs vorspulen.", diff --git a/locales/Hindi.json b/locales/Hindi.json index e71d90a66..515cc00f9 100644 --- a/locales/Hindi.json +++ b/locales/Hindi.json @@ -619,7 +619,6 @@ "no_previous_track": "Koi pichhla track nahin hai.", "playing_previous": "Pichhla track play कर रहा हूँ.", "previous_footer": "{displayName} dwara pichhla track play kiya जा रहा है", - "rewind_limit": "Aap music ko song ki lambai se zyada rewind nahin kar sakte.", "rewinded": "Music ko rewind कर diya गया है.", "rewind_footer": "{displayName} dwara rewind kiya गया", "forward_limit": "Aap music ko song ki lambai se zyada forward nahin kar sakte.", diff --git a/locales/Indonesian.json b/locales/Indonesian.json index 9ff592c91..c777fa29d 100644 --- a/locales/Indonesian.json +++ b/locales/Indonesian.json @@ -619,7 +619,6 @@ "no_previous_track": "Tidak ada lagu sebelumnya.", "playing_previous": "Memutar lagu sebelumnya.", "previous_footer": "Memutar lagu sebelumnya oleh {displayName}", - "rewind_limit": "Anda tidak dapat memutar mundur lagu lebih dari panjang lagu.", "rewinded": "Memutar mundur lagu.", "rewind_footer": "Diputar mundur oleh {displayName}", "forward_limit": "Anda tidak dapat memajukan lagu lebih dari panjang lagu.", diff --git a/locales/Japanese.json b/locales/Japanese.json index 3e397571e..878e9f547 100644 --- a/locales/Japanese.json +++ b/locales/Japanese.json @@ -619,7 +619,6 @@ "no_previous_track": "前のトラックがありません。", "playing_previous": "前のトラックを再生中です。", "previous_footer": "{displayName} によって前のトラックを再生中です", - "rewind_limit": "曲の長さ以上に巻き戻すことはできません。", "rewinded": "音楽を巻き戻しました。", "rewind_footer": "{displayName} によって巻き戻されました", "forward_limit": "曲の長さ以上に早送りすることはできません。", diff --git a/locales/Korean.json b/locales/Korean.json index c448eb89c..647b2c4c4 100644 --- a/locales/Korean.json +++ b/locales/Korean.json @@ -33,7 +33,7 @@ "options": { "command": "특정 명령어의 정보를 얻고 싶다면 여기에 입력해주세요" }, - "content": "안녕하세요! 저는 [Lavamusic](https://github.com/appujet/lavamusic)과 Discord로 만들어진 음악 봇이에요. `{prefix}help <명령어>`를 사용하여 그 명령어의 자세한 정보를 얻을 수 있어요.", + "content": "안녕하세요! 저는 [Lavamusic](https://github.com/appujet/lavamusic)와 Discord.js로 만들어진 음악 봇, {bot}이에요. 명령어에 대한 자세한 정보를 얻고 싶다면 `{prefix}help <명령어>`를 사용해보세요.", "title": "도움말 메뉴", "not_found": "`{cmdName}` 명령어는 존재하지 않아요.", "help_cmd": "**설명:** {description}\n**사용 방법:** {usage}\n**예시:** {examples}\n**줄인 명령어:** {aliases}\n**카테고리:** {category}\n**쿨다운:** {cooldown}초\n**필요한 권한:** {premUser}\n**봇에게 필요한 권한:** {premBot}\n**개발자 전용:** {dev}\n**빗금 명령어 사용 가능:** {slash}\n**인수 필요:** {args}\n**노래 재생 중에만 사용 가능:** {player}\n**DJ만 사용 가능:** {dj}\n**DJ에게 필요한 권한:** {djPerm}\n**음성 채널 접속 중에만 사용 가능:** {voice}", @@ -41,7 +41,7 @@ }, "botinfo": { "description": "봇에 대한 정보를 표시해요", - "content": "봇 정보:\n- **운영 체제**: {osInfo}\n- **업타임**: {osUptime}\n- **호스트 이름**: {osHostname}\n- **CPU 아키텍처**: {cpuInfo}\n- **CPU 사용량**: {cpuUsed}%\n- **메모리 사용량**: {memUsed}MB / {memTotal}GB\n- **Node 버전**: {nodeVersion}\n- **Discord 버전**: {discordJsVersion}\n- 서버 {guilds}개, 채널 {channels}개, 유저 {users}명\n- **명령어 수**: {commands}개" + "content": "봇 정보:\n- **운영 체제**: {osInfo}\n- **업타임**: {osUptime}\n- **호스트 이름**: {osHostname}\n- **CPU 아키텍처**: {cpuInfo}\n- **CPU 사용량**: {cpuUsed}%\n- **메모리 사용량**: {memUsed}MB / {memTotal}GB\n- **Node 버전**: {nodeVersion}\n- **Discord.js 버전**: {discordJsVersion}\n- 서버 {guilds}개, 채널 {channels}개, 유저 {users}명\n- **명령어 수**: {commands}개" }, "about": { "description": "봇에 대한 정보를 확인해요", @@ -132,12 +132,14 @@ }, "bassboost": { "description": "베이스부스트 필터를 토글해요", - "messages": { - "filter_enabled": "`✅` | 베이스부스트 필터가 `활성화되었어요`. \n**조심하세요, 너무 크게 들으면 귀가 나갈 수도 있어요!**", - "filter_disabled": "`✅` | 베이스부스트 필터가 `비활성화되었어요`." - }, "options": { - "level": "The bassboost level you want to set" + "level": "설정할 베이스부스트 레벨" + }, + "messages": { + "high": "`✅` | High 베이스부스트 필터가 `활성화되었어요`.", + "low": "`✅` | Low 베이스부스트 필터가 `활성화되었어요`.", + "medium": "`✅` | Medium 베이스부스트 필터가 `활성화되었어요`.", + "off": "`✅` | 베이스부스트 필터가 `비활성화되었어요`." } }, "distorsion": { @@ -267,9 +269,9 @@ "looping_off": "**반복이 꺼졌어요.**" }, "lyrics": { - "description": "현재 재생중인 노래의 가사를 가져와요", - "lyrics_track": "### [{trackTitle}]({trackUrl})의 노래 가사\n**`{lyrics}`**", - "searching": "`🔍` **{trackTitle}**의 가사 검색 중...", + "description": "현재 재생중인 노래의 가사를 확인해요", + "lyrics_track": "### [{trackTitle}]({trackUrl}) 노래 가사\n**`{lyrics}`**", + "searching": "`🔍` **{trackTitle}** 노래 가사 검색 중...", "errors": { "no_results": "가사를 찾지 못했어요.", "lyrics_error": "가사를 검색하는 도중 오류가 발생했어요." @@ -598,15 +600,15 @@ "cooldown": "`{command}` 명령어를 사용하려면 {time}초동안 기다려야 해요.", "no_mention_everyone": "이 명령어는 everyone나 here 멘션으로 사용할 수 없어요. 빗금 명령어로 사용해주세요.", "error": "오류: `{error}`", - "no_voice_channel_queue": "대기열에 노래를 추가하려면 음성 채널에 접속해주세요.", + "no_voice_channel_queue": "대기열에 노래를 추가하려면 음성 채널에 있어야 해요.", "no_permission_connect_speak": "<#{channel}>에서 연결/말하기 권한이 없어요.", "different_voice_channel_queue": "노래를 대기열에 추가하려면 <#{channel}> 채널에 있어야 해요.", "vote_button": "투표하기", "vote_message": "잠깐! 이 명령어를 사용하려면 top.gg에서 투표해야 해요." }, "setupButton": { - "no_voice_channel_button": "이 버튼을 사용하려면 음성 채널에 접속해주세요.", - "different_voice_channel_button": "이 버튼을 사용하려면 {channel} 채널에 접속해주세요.", + "no_voice_channel_button": "이 버튼을 사용하려면 음성 채널에 있어야 해요.", + "different_voice_channel_button": "이 버튼을 사용하려면 {channel} 채널에 있어야 해요.", "now_playing": "재생 중", "live": "라이브", "requested_by": "요청자: <@{requester}>", @@ -623,16 +625,15 @@ "stopped": "노래를 정지했어요.", "stopped_footer": "{displayName}님에 의해 정지됨", "nothing_playing": "재생 중인 노래 없음", - "loop_set": "{loop} 반복으로 설정했어요.", - "loop_footer": "{displayName}님에 의해 {loop} 반복으로 설정됨", + "loop_set": "반복 모드가 {loop}로 변경되었어요.", + "loop_footer": "{displayName}님에 의해 반복 모드가 {loop}로 설정됨", "shuffled": "노래를 섞었어요.", "no_previous_track": "이전 노래가 없어요.", "playing_previous": "이전 노래를 재생할게요.", "previous_footer": "{displayName}님에 의해 이전 노래 재생 중", - "rewind_limit": "현재 노래 길이보다 더 되감기할 수 없어요.", "rewinded": "노래를 되감기했어요.", "rewind_footer": "{displayName}님에 의해 노래 되감기됨", - "forward_limit": "현재 노래 길이보다 더 빨리감기할 수 없어요.", + "forward_limit": "더 이상 빨리감기할 수 없어요.", "forwarded": "노래를 빨리감기했어요.", "forward_footer": "{displayName}님에 의해 빨리감기됨", "button_not_available": "이 버튼은 사용할 수 없어요.", diff --git a/locales/Norwegian.json b/locales/Norwegian.json index 163d69550..83bf4d283 100644 --- a/locales/Norwegian.json +++ b/locales/Norwegian.json @@ -619,7 +619,6 @@ "no_previous_track": "Det er ingen forrige spor.", "playing_previous": "Spiller av forrige spor.", "previous_footer": "Spiller av forrige spor av {displayName}", - "rewind_limit": "Du kan ikke spole musikken tilbake mer enn lengden på sangen.", "rewinded": "Spolet musikken tilbake.", "rewind_footer": "Spolet tilbake av {displayName}", "forward_limit": "Du kan ikke spole musikken fremover mer enn lengden på sangen.", diff --git a/locales/Polish.json b/locales/Polish.json index 1c9646971..8aab02e92 100644 --- a/locales/Polish.json +++ b/locales/Polish.json @@ -619,7 +619,6 @@ "no_previous_track": "Nie ma żadnego poprzedniego utworu.", "playing_previous": "Odtwarzanie poprzedniego utworu", "previous_footer": "Utwór ostatnio odtwarzany przez {displayName}", - "rewind_limit": "Nie można cofnąć muzyki o więcej niż długość utworu.", "rewinded": "Cofnięto muzykę.", "rewind_footer": "Cofnięty przez {displayName}", "forward_limit": "Nie można przesunąć muzyki do przodu o więcej niż długość utworu.", diff --git a/locales/PortuguesePT.json b/locales/PortuguesePT.json index 55515ed2f..cb696ad46 100644 --- a/locales/PortuguesePT.json +++ b/locales/PortuguesePT.json @@ -613,7 +613,6 @@ "no_previous_track": "Não há nenhuma faixa anterior.", "playing_previous": "A tocar a faixa anterior.", "previous_footer": "A tocar a faixa anterior por {displayName}", - "rewind_limit": "Não pode retroceder a música mais do que o comprimento da música.", "rewinded": "A música foi retrocedida.", "rewind_footer": "Retrocedido por {displayName}", "forward_limit": "Não pode avançar a música mais do que o comprimento da música.", diff --git a/locales/Russian.json b/locales/Russian.json index a1d640041..2ec89a062 100644 --- a/locales/Russian.json +++ b/locales/Russian.json @@ -619,7 +619,6 @@ "no_previous_track": "Нет предыдущей дорожки.", "playing_previous": "Проигрывается предыдущая дорожка.", "previous_footer": "Проигрывается предыдущая дорожка {displayName}", - "rewind_limit": "Вы не можете перемотать музыку больше, чем длина песни.", "rewinded": "Музыка перемотана назад.", "rewind_footer": "Перемотано назад {displayName}", "forward_limit": "Вы не можете перемотать музыку вперед больше, чем длина песни.", diff --git a/locales/SpanishES.json b/locales/SpanishES.json index 567356249..895f00fb8 100644 --- a/locales/SpanishES.json +++ b/locales/SpanishES.json @@ -619,7 +619,6 @@ "no_previous_track": "No hay ninguna pista anterior.", "playing_previous": "Reproduciendo la pista anterior.", "previous_footer": "Reproduciendo la pista anterior por {displayName}", - "rewind_limit": "No puedes rebobinar la música más de la duración de la canción.", "rewinded": "Se ha rebobinado la música.", "rewind_footer": "Rebobinado por {displayName}", "forward_limit": "No puedes avanzar la música más de la duración de la canción.", diff --git a/locales/Vietnamese.json b/locales/Vietnamese.json index 1db3602ca..dbc0884b7 100644 --- a/locales/Vietnamese.json +++ b/locales/Vietnamese.json @@ -619,7 +619,6 @@ "no_previous_track": "Không có bài hát trước.", "playing_previous": "Đang phát bài hát trước.", "previous_footer": "Đang phát bài hát trước bởi {displayName}", - "rewind_limit": "Bạn không thể quay lại nhạc nhiều hơn độ dài của bài hát.", "rewinded": "Đã quay lại nhạc.", "rewind_footer": "Quay lại bởi {displayName}", "forward_limit": "Bạn không thể tiến tới nhạc nhiều hơn độ dài của bài hát.", diff --git a/run.bat b/run.bat index 5b7f8f7b8..a2fe91338 100644 --- a/run.bat +++ b/run.bat @@ -1,19 +1,2 @@ @echo off -setlocal enabledelayedexpansion - -:: Check if pnpm is installed - -where pnpm >nul 2>nul -if %errorlevel% equ 0 ( - set package_manager=pnpm -) else ( - set package_manager=npm -) - -:: Check if node_modules exists -if not exist node_modules ( - %package_manager% install -) - -:: start the project -%package_manager% run start \ No newline at end of file +npm run start diff --git a/src/LavaClient.ts b/src/LavaClient.ts index b173f4665..4428a2117 100644 --- a/src/LavaClient.ts +++ b/src/LavaClient.ts @@ -1,6 +1,6 @@ import { type ClientOptions, GatewayIntentBits } from "discord.js"; -import Lavamusic from "./structures/Lavamusic"; import { env } from "./env"; +import Lavamusic from "./structures/Lavamusic"; const { GuildMembers, MessageContent, GuildVoiceStates, GuildMessages, Guilds, GuildMessageTyping } = GatewayIntentBits; diff --git a/src/commands/config/Setup.ts b/src/commands/config/Setup.ts index c17ca182f..d93337ba6 100644 --- a/src/commands/config/Setup.ts +++ b/src/commands/config/Setup.ts @@ -92,10 +92,9 @@ export default class Setup extends Command { }); const player = this.client.manager.getPlayer(ctx.guild!.id); const image = this.client.config.links.img; - const desc = - player && player.queue.current - ? `[${player.queue.current.info.title}](${player.queue.current.info.uri})` - : ctx.locale("player.setupStart.nothing_playing"); + const desc = player?.queue.current + ? `[${player.queue.current.info.title}](${player.queue.current.info.uri})` + : ctx.locale("player.setupStart.nothing_playing"); embed.setDescription(desc).setImage(image); await textChannel .send({ diff --git a/src/commands/dev/GuildList.ts b/src/commands/dev/GuildList.ts index cb92967b7..4dfb2e58f 100644 --- a/src/commands/dev/GuildList.ts +++ b/src/commands/dev/GuildList.ts @@ -33,7 +33,7 @@ export default class GuildList extends Command { const guilds = await client.shard.broadcastEval((c) => c.guilds.cache.map((guild) => ({ name: guild.name, id: guild.id }))); const allGuilds = guilds.reduce((acc, val) => acc.concat(val), []); - const guildList = allGuilds.map((guild) => `- **${guild.name}** - (${guild.id})`); + const guildList = allGuilds.map((guild) => `- **${guild.name}** - ${guild.id}`); const chunks = client.utils.chunk(guildList, 10) || [[]]; const pages = chunks.map((chunk, index) => { return this.client diff --git a/src/events/client/Ready.ts b/src/events/client/Ready.ts index 9e42ab8dd..178e2f510 100644 --- a/src/events/client/Ready.ts +++ b/src/events/client/Ready.ts @@ -1,6 +1,6 @@ import { AutoPoster } from "topgg-autoposter"; -import { Event, type Lavamusic } from "../../structures/index.js"; import { env } from "../../env.js"; +import { Event, type Lavamusic } from "../../structures/index.js"; export default class Ready extends Event { constructor(client: Lavamusic, file: string) { diff --git a/src/events/client/SetupButtons.ts b/src/events/client/SetupButtons.ts index 3b7d6429e..f1766d280 100644 --- a/src/events/client/SetupButtons.ts +++ b/src/events/client/SetupButtons.ts @@ -42,9 +42,7 @@ export default class SetupButtons extends Event { message = await interaction.channel.messages.fetch(data.messageId, { cache: true, }); - } catch (_e) { - /* empty */ - } + } catch (_e) {} const iconUrl = this.client.config.icons[sourceName] || this.client.user.displayAvatarURL({ extension: "png" }); const embed = this.client @@ -81,15 +79,52 @@ export default class SetupButtons extends Event { }); }; switch (interaction.customId) { - case "LOW_VOL_BUT": - await handleVolumeChange(-10); + case "PREV_BUT": + if (!player.queue.previous) { + return await buttonReply(interaction, T(locale, "event.setupButton.no_previous_track"), this.client.color.main); + } + player.play({ + track: player.queue.previous[0], + }); + await buttonReply(interaction, T(locale, "event.setupButton.playing_previous"), this.client.color.main); + await message.edit({ + embeds: [ + embed.setFooter({ + text: T(locale, "event.setupButton.previous_footer", { + displayName: interaction.member.displayName, + }), + iconURL: interaction.member.displayAvatarURL({}), + }), + ], + }); break; - case "HIGH_VOL_BUT": - await handleVolumeChange(10); + case "REWIND_BUT": { + const time = player.position - 10000; + if (time < 0) { + player.seek(0); + } else { + player.seek(time); + } + await buttonReply(interaction, T(locale, "event.setupButton.rewinded"), this.client.color.main); + await message.edit({ + embeds: [ + embed.setFooter({ + text: T(locale, "event.setupButton.rewind_footer", { + displayName: interaction.member.displayName, + }), + iconURL: interaction.member.displayAvatarURL({}), + }), + ], + }); break; + } case "PAUSE_BUT": { const name = player.paused ? T(locale, "event.setupButton.resumed") : T(locale, "event.setupButton.paused"); - player.pause(); + if (player.paused) { + player.resume(); + } else { + player.pause(); + } await buttonReply(interaction, T(locale, "event.setupButton.pause_resume", { name }), this.client.color.main); await message.edit({ embeds: [ @@ -105,6 +140,25 @@ export default class SetupButtons extends Event { }); break; } + case "FORWARD_BUT": { + const time = player.position + 10000; + if (time > player.queue.current.info.duration) { + return await buttonReply(interaction, T(locale, "event.setupButton.forward_limit"), this.client.color.main); + } + player.seek(time); + await buttonReply(interaction, T(locale, "event.setupButton.forwarded"), this.client.color.main); + await message.edit({ + embeds: [ + embed.setFooter({ + text: T(locale, "event.setupButton.forward_footer", { + displayName: interaction.member.displayName, + }), + iconURL: interaction.member.displayAvatarURL({}), + }), + ], + }); + break; + } case "SKIP_BUT": if (player.queue.tracks.length === 0) { return await buttonReply(interaction, T(locale, "event.setupButton.no_music_to_skip"), this.client.color.main); @@ -122,28 +176,8 @@ export default class SetupButtons extends Event { ], }); break; - case "STOP_BUT": - player.stopPlaying(true, false); - await buttonReply(interaction, T(locale, "event.setupButton.stopped"), this.client.color.main); - await message.edit({ - embeds: [ - embed - .setFooter({ - text: T(locale, "event.setupButton.stopped_footer", { - displayName: interaction.member.displayName, - }), - iconURL: interaction.member.displayAvatarURL({}), - }) - .setDescription(T(locale, "event.setupButton.nothing_playing")) - .setImage(this.client.config.links.img) - .setAuthor({ - name: this.client.user.username, - iconURL: this.client.user.displayAvatarURL({ - extension: "png", - }), - }), - ], - }); + case "LOW_VOL_BUT": + await handleVolumeChange(-10); break; case "LOOP_BUT": { const loopOptions: Array<"off" | "queue" | "track"> = ["off", "queue", "track"]; @@ -169,69 +203,35 @@ export default class SetupButtons extends Event { }); break; } - case "SHUFFLE_BUT": - player.queue.shuffle(); - await buttonReply(interaction, T(locale, "event.setupButton.shuffled"), this.client.color.main); - break; - case "PREV_BUT": - if (!player.queue.previous) { - return await buttonReply(interaction, T(locale, "event.setupButton.no_previous_track"), this.client.color.main); - } - player.play({ - track: player.queue.previous[0], - }); - await buttonReply(interaction, T(locale, "event.setupButton.playing_previous"), this.client.color.main); - await message.edit({ - embeds: [ - embed.setFooter({ - text: T(locale, "event.setupButton.previous_footer", { - displayName: interaction.member.displayName, - }), - iconURL: interaction.member.displayAvatarURL({}), - }), - ], - }); - break; - case "REWIND_BUT": { - const time = player.position - 10000; - if (time < 0) { - return await buttonReply(interaction, T(locale, "event.setupButton.rewind_limit"), this.client.color.main); - } - player.seek(time); - await buttonReply(interaction, T(locale, "event.setupButton.rewinded"), this.client.color.main); + case "STOP_BUT": + player.stopPlaying(true, false); + await buttonReply(interaction, T(locale, "event.setupButton.stopped"), this.client.color.main); await message.edit({ embeds: [ - embed.setFooter({ - text: T(locale, "event.setupButton.rewind_footer", { - displayName: interaction.member.displayName, + embed + .setFooter({ + text: T(locale, "event.setupButton.stopped_footer", { + displayName: interaction.member.displayName, + }), + iconURL: interaction.member.displayAvatarURL({}), + }) + .setDescription(T(locale, "event.setupButton.nothing_playing")) + .setImage(this.client.config.links.img) + .setAuthor({ + name: this.client.user.username, + iconURL: this.client.user.displayAvatarURL({ + extension: "png", + }), }), - iconURL: interaction.member.displayAvatarURL({}), - }), ], }); break; - } - case "FORWARD_BUT": { - const time = player.position + 10000; - if (time > player.queue.current.info.duration) { - return await buttonReply(interaction, T(locale, "event.setupButton.forward_limit"), this.client.color.main); - } - player.seek(time); - await buttonReply(interaction, T(locale, "event.setupButton.forwarded"), this.client.color.main); - await message.edit({ - embeds: [ - embed.setFooter({ - text: T(locale, "event.setupButton.forward_footer", { - displayName: interaction.member.displayName, - }), - iconURL: interaction.member.displayAvatarURL({}), - }), - ], - }); + case "SHUFFLE_BUT": + player.queue.shuffle(); + await buttonReply(interaction, T(locale, "event.setupButton.shuffled"), this.client.color.main); break; - } - default: - await buttonReply(interaction, T(locale, "event.setupButton.button_not_available"), this.client.color.main); + case "HIGH_VOL_BUT": + await handleVolumeChange(10); break; } } diff --git a/src/events/player/QueueEnd.ts b/src/events/player/QueueEnd.ts index c25e808f2..24e26dbba 100644 --- a/src/events/player/QueueEnd.ts +++ b/src/events/player/QueueEnd.ts @@ -2,7 +2,6 @@ import type { TextChannel } from "discord.js"; import type { Player, Track, TrackStartEvent } from "lavalink-client"; import { Event, type Lavamusic } from "../../structures/index"; -// queueEnd export default class QueueEnd extends Event { constructor(client: Lavamusic, file: string) { super(client, file, { diff --git a/src/events/player/TrackStart.ts b/src/events/player/TrackStart.ts index 77550d8ee..2542e41b6 100644 --- a/src/events/player/TrackStart.ts +++ b/src/events/player/TrackStart.ts @@ -1,6 +1,3 @@ -import type { Player, Track, TrackStartEvent } from "lavalink-client"; -import { Event, type Lavamusic } from "../../structures/index"; -import { T } from "../../structures/I18n"; import { ActionRowBuilder, ButtonBuilder, @@ -15,6 +12,9 @@ import { type TextChannel, type UserSelectMenuInteraction, } from "discord.js"; +import type { Player, Track, TrackStartEvent } from "lavalink-client"; +import { T } from "../../structures/I18n"; +import { Event, type Lavamusic } from "../../structures/index"; import type { Requester } from "../../types"; import { trackStart } from "../../utils/SetupSystem"; diff --git a/src/index.ts b/src/index.ts index 6b3e189fd..737885c4f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ import * as fs from "node:fs"; +import { shardStart } from "./shard"; import Logger from "./structures/Logger"; import { ThemeSelector } from "./utils/ThemeSelector"; -import { shardStart } from "./shard"; const logger = new Logger(); diff --git a/src/plugin/plugins/keepAlive.ts b/src/plugin/plugins/keepAlive.ts index 4087c0ef2..982d00df1 100644 --- a/src/plugin/plugins/keepAlive.ts +++ b/src/plugin/plugins/keepAlive.ts @@ -1,7 +1,7 @@ import http from "node:http"; +import { env } from "../../env"; import type { Lavamusic } from "../../structures/index"; import type { BotPlugin } from "../index"; -import { env } from "../../env"; const keepAlive: BotPlugin = { name: "KeepAlive Plugin", diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index b11a3d0b8..c9095d9f2 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -19,8 +19,8 @@ export class Utils { user.setPresence({ activities: [ { - name: player && player.queue?.current ? `🎶 | ${player.queue?.current.info.title}` : client.env.BOT_ACTIVITY, - type: player && player?.queue?.current ? ActivityType.Listening : client.env.BOT_ACTIVITY_TYPE, + name: player?.queue?.current ? `🎶 | ${player.queue?.current.info.title}` : client.env.BOT_ACTIVITY, + type: player?.queue?.current ? ActivityType.Listening : client.env.BOT_ACTIVITY_TYPE, }, ], status: client.env.BOT_STATUS as any, diff --git a/tsconfig.json b/tsconfig.json index eb9ee500e..42b245339 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,11 +1,11 @@ { "$schema": "https://json.schemastore.org/tsconfig", "compilerOptions": { - "lib": ["ESNext", "DOM"], + "lib": ["dom", "esnext"], "rootDir": "./src", "outDir": "./dist", - "target": "ESNext", - "module": "CommonJS", + "target": "esnext", + "module": "commonjs", "declaration": true, "sourceMap": true, "newLine": "crlf", From 6cadd8278580bb44161ea24f4825b8e4bf979dd8 Mon Sep 17 00:00:00 2001 From: hwangsihu Date: Wed, 18 Sep 2024 17:53:14 +0900 Subject: [PATCH 02/10] Remove LavaLyrics Plugin --- Lavalink/example.application.yml | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/Lavalink/example.application.yml b/Lavalink/example.application.yml index 244512cd4..790624a2e 100644 --- a/Lavalink/example.application.yml +++ b/Lavalink/example.application.yml @@ -20,13 +20,6 @@ plugins: pixeldrain: true # pixeldrain.com jiosaavn: apiURL: "https://saavn.dev/api" # The API URL for JioSaavn - lavalyrics: - # sources is used to sort the different lyrics sources by priority (from highest to lowest) - sources: - - spotify - - youtube - - deezer - - yandexMusic lavasrc: providers: # Custom providers for track loading. This is the default # - "dzisrc:%ISRC%" # Deezer ISRC provider @@ -43,11 +36,11 @@ plugins: youtube: true # Enable YouTube search source (https://github.com/topi314/LavaSearch) vkmusic: false # Enable Vk Music source lyrics-sources: - spotify: true # Enable Spotify lyrics source - deezer: true # Enable Deezer lyrics source - youtube: true # Enable YouTube lyrics source - yandexmusic: true # Enable Yandex Music lyrics source - vkmusic: true # Enable Vk Music lyrics source + spotify: false # Enable Spotify lyrics source + deezer: false # Enable Deezer lyrics source + youtube: false # Enable YouTube lyrics source + yandexmusic: false # Enable Yandex Music lyrics source + vkmusic: false # Enable Vk Music lyrics source spotify: clientId: "your client id" clientSecret: "your client secret" @@ -115,8 +108,6 @@ lavalink: repository: "https://jitpack.io" - dependency: "com.dunctebot:skybot-lavalink-plugin:1.7.0" snapshot: false # set to true if you want to use snapshot builds - - dependency: "com.github.topi314.lavalyrics:lavalyrics-plugin:1.0.0" - snapshot: false # set to true if you want to use snapshot builds (see below) - dependency: "com.github.topi314.lavasearch:lavasearch-plugin:1.0.0" snapshot: false # set to true if you want to use snapshot builds - dependency: "com.github.topi314.lavasrc:lavasrc-plugin:4.2.0" From eef2786ec3be650960c8588d614920a9c97f81d5 Mon Sep 17 00:00:00 2001 From: hwangsihu Date: Wed, 18 Sep 2024 18:41:32 +0900 Subject: [PATCH 03/10] Update prisma --- prisma/example.mongodb.schema.prisma | 108 ++++++++---------------- prisma/example.postgresql.schema.prisma | 76 ++++------------- 2 files changed, 50 insertions(+), 134 deletions(-) diff --git a/prisma/example.mongodb.schema.prisma b/prisma/example.mongodb.schema.prisma index bc9a024ae..f8e3a20dc 100644 --- a/prisma/example.mongodb.schema.prisma +++ b/prisma/example.mongodb.schema.prisma @@ -14,96 +14,54 @@ datasource db { url = env("DATABASE_URL") } +model Bot { + botId String @unique + totalPlaySong Int +} + model Guild { - guildId String @id @map("_id") - prefix String - language String? - stay Stay? - dj Dj? - roles Role[] - setup Setup? + guildId String @id + prefix String + language String? @default("EnglishUS") + stay Stay? + dj Dj? + roles Role[] + setup Setup? } model Stay { - guildId String @id @map("_id") - textId String - voiceId String - Guild Guild @relation(fields: [guildId], references: [guildId]) + guildId String @id + textId String + voiceId String + Guild Guild @relation(fields: [guildId], references: [guildId]) } model Dj { - guildId String @id @map("_id") - mode Boolean - Guild Guild @relation(fields: [guildId], references: [guildId]) + guildId String @id + mode Boolean + Guild Guild @relation(fields: [guildId], references: [guildId]) } model Role { - guildId String @id @map("_id") - roleId String - Guild Guild @relation(fields: [guildId], references: [guildId]) + guildId String + roleId String + Guild Guild @relation(fields: [guildId], references: [guildId]) - @@unique([guildId, roleId]) + @@unique([guildId, roleId]) } model Playlist { - id String @id @default(cuid()) @map("_id") - userId String - name String - songs Song[] - - @@unique([userId, name]) -} - -model Song { - id String @id @map("_id") @default(cuid()) - track String - playlistId String - playlist Playlist @relation(fields: [playlistId], references: [id]) + id String @id @default(uuid()) + userId String + name String + tracks String? // Store the array of encoded tracks as a JSON string - @@unique([track, playlistId]) + @@unique([userId, name]) } model Setup { - guildId String @id @map("_id") - textId String - messageId String - Guild Guild @relation(fields: [guildId], references: [guildId]) -} - -model Premium { - userId String @id @map("_id") - guildId String -} - -enum Languages { - EnglishUS - EnglishGB - German - Bulgarian - ChineseCN - ChineseTW - Croatian - Czech - Danish - Dutch - Finnish - French - Greek - Hindi - Hungarian - Italian - Japanese - Korean - Lithuanian - Norwegian - Polish - PortugueseBR - Romanian - Russian - SpanishES - Swedish - Thai - Turkish - Ukrainian - Vietnamese -} + guildId String @id + textId String + messageId String + Guild Guild @relation(fields: [guildId], references: [guildId]) +} \ No newline at end of file diff --git a/prisma/example.postgresql.schema.prisma b/prisma/example.postgresql.schema.prisma index 3d131913d..a2f5f8307 100644 --- a/prisma/example.postgresql.schema.prisma +++ b/prisma/example.postgresql.schema.prisma @@ -14,14 +14,19 @@ datasource db { url = env("DATABASE_URL") } +model Bot { + botId String @unique + totalPlaySong Int +} + model Guild { - guildId String @id - prefix String - language String? - stay Stay? - dj Dj? - roles Role[] - setup Setup? + guildId String @id + prefix String + language String? @default("EnglishUS") + stay Stay? + dj Dj? + roles Role[] + setup Setup? } model Stay { @@ -46,64 +51,17 @@ model Role { } model Playlist { - id String @id @default(uuid()) - userId String - name String - songs Song[] + id String @id @default(uuid()) + userId String + name String + tracks String? // Store the array of encoded tracks as a JSON string @@unique([userId, name]) } -model Song { - id String @id @default(uuid()) - track String - playlistId String - playlist Playlist @relation(fields: [playlistId], references: [id]) - - @@unique([track, playlistId]) -} - model Setup { guildId String @id textId String messageId String Guild Guild @relation(fields: [guildId], references: [guildId]) -} - -model Premium { - userId String @id - guildId String -} - -enum Languages { - EnglishUS - EnglishGB - German - Bulgarian - ChineseCN - ChineseTW - Croatian - Czech - Danish - Dutch - Finnish - French - Greek - Hindi - Hungarian - Italian - Japanese - Korean - Lithuanian - Norwegian - Polish - PortugueseBR - Romanian - Russian - SpanishES - Swedish - Thai - Turkish - Ukrainian - Vietnamese -} +} \ No newline at end of file From b6f1bb7d51fa352ddbe22acb701cbb731f4ae2c8 Mon Sep 17 00:00:00 2001 From: hwangsihu Date: Wed, 18 Sep 2024 23:25:29 +0900 Subject: [PATCH 04/10] Lavalink update --- Lavalink/example.application.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Lavalink/example.application.yml b/Lavalink/example.application.yml index 790624a2e..6ca3ad5d6 100644 --- a/Lavalink/example.application.yml +++ b/Lavalink/example.application.yml @@ -34,13 +34,11 @@ plugins: yandexmusic: false # Enable Yandex Music source flowerytts: false # Enable Flowery TTS source youtube: true # Enable YouTube search source (https://github.com/topi314/LavaSearch) - vkmusic: false # Enable Vk Music source lyrics-sources: spotify: false # Enable Spotify lyrics source deezer: false # Enable Deezer lyrics source youtube: false # Enable YouTube lyrics source yandexmusic: false # Enable Yandex Music lyrics source - vkmusic: false # Enable Vk Music lyrics source spotify: clientId: "your client id" clientSecret: "your client secret" @@ -79,11 +77,6 @@ plugins: audioFormat: "mp3" # supported formats are: mp3, ogg_opus, ogg_vorbis, aac, wav, and flac. Default format is mp3 youtube: countryCode: "US" # the country code you want to use for searching lyrics via ISRC. See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 - vkmusic: - userToken: "your user token" # This token is needed for authorization in the api. Guide: https://github.com/topi314/LavaSrc#vk-music - playlistLoadLimit: 1 # The number of pages at 50 tracks each - artistLoadLimit: 1 # The number of pages at 10 tracks each - recommendationsLoadLimit: 10 # Number of tracks youtube: enabled: true # Whether this source can be used. allowSearch: true # Whether "ytsearch:" and "ytmsearch:" can be used. From 64a5c06e252e16ffa1831dfed9ee679d894d70d7 Mon Sep 17 00:00:00 2001 From: hwangsihu Date: Wed, 18 Sep 2024 23:28:03 +0900 Subject: [PATCH 05/10] Developer Bypass is back --- src/events/client/MessageCreate.ts | 267 +++++++++++++++-------------- 1 file changed, 134 insertions(+), 133 deletions(-) diff --git a/src/events/client/MessageCreate.ts b/src/events/client/MessageCreate.ts index faa336011..7e28fc4b1 100644 --- a/src/events/client/MessageCreate.ts +++ b/src/events/client/MessageCreate.ts @@ -55,6 +55,8 @@ export default class MessageCreate extends Event { ctx.guildLocale = locale; const clientMember = message.guild.members.resolve(this.client.user); + const isDev = this.client.env.OWNER_IDS?.includes(message.author.id); + if (!(message.inGuild() && message.channel.permissionsFor(clientMember)?.has(PermissionFlagsBits.ViewChannel))) return; if ( @@ -86,172 +88,171 @@ export default class MessageCreate extends Event { } if (command.permissions?.user) { - if (!(message.member as GuildMember).permissions.has(command.permissions.user)) { + if (!(isDev || (message.member as GuildMember).permissions.has(command.permissions.user))) { return await message.reply({ content: T(locale, "event.message.no_user_permission"), }); } + } - if (command.permissions?.dev && this.client.env.OWNER_IDS) { - const isDev = this.client.env.OWNER_IDS.includes(message.author.id); - if (!isDev) return; - } + if (command.permissions?.dev && this.client.env.OWNER_IDS) { + if (!isDev) return; } + } - if (command.vote && this.client.env.TOPGG) { - const voted = await this.client.topGG.hasVoted(message.author.id); - if (!voted) { - const voteBtn = new ActionRowBuilder().addComponents( - new ButtonBuilder() - .setLabel(T(locale, "event.message.vote_button")) - .setURL(`https://top.gg/bot/${this.client.user.id}/vote`) - .setStyle(ButtonStyle.Link), - ); + if (command.vote && this.client.env.TOPGG) { + const voted = await this.client.topGG.hasVoted(message.author.id); + if (!(isDev || voted)) { + const voteBtn = new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setLabel(T(locale, "event.message.vote_button")) + .setURL(`https://top.gg/bot/${this.client.user.id}/vote`) + .setStyle(ButtonStyle.Link), + ); + + return await message.reply({ + content: T(locale, "event.message.vote_message"), + components: [voteBtn], + }); + } + } + if (command.player) { + if (command.player.voice) { + if (!(message.member as GuildMember).voice.channel) { return await message.reply({ - content: T(locale, "event.message.vote_message"), - components: [voteBtn], + content: T(locale, "event.message.no_voice_channel", { command: command.name }), }); } - } - if (command.player) { - if (command.player.voice) { - if (!(message.member as GuildMember).voice.channel) { - return await message.reply({ - content: T(locale, "event.message.no_voice_channel", { command: command.name }), - }); - } + if (!clientMember.permissions.has(PermissionFlagsBits.Connect)) { + return await message.reply({ + content: T(locale, "event.message.no_connect_permission", { command: command.name }), + }); + } - if (!clientMember.permissions.has(PermissionFlagsBits.Connect)) { - return await message.reply({ - content: T(locale, "event.message.no_connect_permission", { command: command.name }), - }); - } + if (!clientMember.permissions.has(PermissionFlagsBits.Speak)) { + return await message.reply({ + content: T(locale, "event.message.no_speak_permission", { command: command.name }), + }); + } - if (!clientMember.permissions.has(PermissionFlagsBits.Speak)) { - return await message.reply({ - content: T(locale, "event.message.no_speak_permission", { command: command.name }), - }); - } + if ( + (message.member as GuildMember).voice.channel.type === ChannelType.GuildStageVoice && + !clientMember.permissions.has(PermissionFlagsBits.RequestToSpeak) + ) { + return await message.reply({ + content: T(locale, "event.message.no_request_to_speak", { command: command.name }), + }); + } - if ( - (message.member as GuildMember).voice.channel.type === ChannelType.GuildStageVoice && - !clientMember.permissions.has(PermissionFlagsBits.RequestToSpeak) - ) { - return await message.reply({ - content: T(locale, "event.message.no_request_to_speak", { command: command.name }), - }); - } + if (clientMember.voice.channel && clientMember.voice.channelId !== (message.member as GuildMember).voice.channelId) { + return await message.reply({ + content: T(locale, "event.message.different_voice_channel", { + channel: `<#${clientMember.voice.channelId}>`, + command: command.name, + }), + }); + } + } - if (clientMember.voice.channel && clientMember.voice.channelId !== (message.member as GuildMember).voice.channelId) { - return await message.reply({ - content: T(locale, "event.message.different_voice_channel", { - channel: `<#${clientMember.voice.channelId}>`, - command: command.name, - }), - }); - } + if (command.player.active) { + const queue = this.client.manager.getPlayer(message.guildId); + if (!queue?.queue.current) { + return await message.reply({ + content: T(locale, "event.message.no_music_playing"), + }); } + } - if (command.player.active) { - const queue = this.client.manager.getPlayer(message.guildId); - if (!queue?.queue.current) { + if (command.player.dj) { + const dj = await this.client.db.getDj(message.guildId); + if (dj?.mode) { + const djRole = await this.client.db.getRoles(message.guildId); + if (!djRole) { return await message.reply({ - content: T(locale, "event.message.no_music_playing"), + content: T(locale, "event.message.no_dj_role"), }); } - } - if (command.player.dj) { - const dj = await this.client.db.getDj(message.guildId); - if (dj?.mode) { - const djRole = await this.client.db.getRoles(message.guildId); - if (!djRole) { - return await message.reply({ - content: T(locale, "event.message.no_dj_role"), - }); - } - - const hasDJRole = (message.member as GuildMember).roles.cache.some((role) => - djRole.map((r) => r.roleId).includes(role.id), - ); - if (!(hasDJRole && !(message.member as GuildMember).permissions.has(PermissionFlagsBits.ManageGuild))) { - return await message.reply({ - content: T(locale, "event.message.no_dj_permission"), - }); - } + const hasDJRole = (message.member as GuildMember).roles.cache.some((role) => + djRole.map((r) => r.roleId).includes(role.id), + ); + if (!(isDev || (hasDJRole && !(message.member as GuildMember).permissions.has(PermissionFlagsBits.ManageGuild)))) { + return await message.reply({ + content: T(locale, "event.message.no_dj_permission"), + }); } } } + } - if (command.args && args.length === 0) { - const embed = this.client - .embed() - .setColor(this.client.color.red) - .setTitle(T(locale, "event.message.missing_arguments")) - .setDescription( - T(locale, "event.message.missing_arguments_description", { - command: command.name, - examples: command.description.examples ? command.description.examples.join("\n") : "None", - }), - ) - .setFooter({ text: T(locale, "event.message.syntax_footer") }); - await message.reply({ embeds: [embed] }); - return; - } - - if (!this.client.cooldown.has(cmd)) { - this.client.cooldown.set(cmd, new Collection()); - } - const now = Date.now(); - const timestamps = this.client.cooldown.get(cmd)!; - const cooldownAmount = (command.cooldown || 5) * 1000; + if (command.args && args.length === 0) { + const embed = this.client + .embed() + .setColor(this.client.color.red) + .setTitle(T(locale, "event.message.missing_arguments")) + .setDescription( + T(locale, "event.message.missing_arguments_description", { + command: command.name, + examples: command.description.examples ? command.description.examples.join("\n") : "None", + }), + ) + .setFooter({ text: T(locale, "event.message.syntax_footer") }); + await message.reply({ embeds: [embed] }); + return; + } - if (timestamps.has(message.author.id)) { - const expirationTime = timestamps.get(message.author.id)! + cooldownAmount; - const timeLeft = (expirationTime - now) / 1000; - if (now < expirationTime && timeLeft > 0.9) { - return await message.reply({ - content: T(locale, "event.message.cooldown", { time: timeLeft.toFixed(1), command: cmd }), - }); - } - timestamps.set(message.author.id, now); - setTimeout(() => timestamps.delete(message.author.id), cooldownAmount); - } else { - timestamps.set(message.author.id, now); - setTimeout(() => timestamps.delete(message.author.id), cooldownAmount); - } + if (!this.client.cooldown.has(cmd)) { + this.client.cooldown.set(cmd, new Collection()); + } + const now = Date.now(); + const timestamps = this.client.cooldown.get(cmd)!; + const cooldownAmount = (command.cooldown || 5) * 1000; - if (args.includes("@everyone") || args.includes("@here")) { + if (timestamps.has(message.author.id)) { + const expirationTime = timestamps.get(message.author.id)! + cooldownAmount; + const timeLeft = (expirationTime - now) / 1000; + if (now < expirationTime && timeLeft > 0.9) { return await message.reply({ - content: T(locale, "event.message.no_mention_everyone"), + content: T(locale, "event.message.cooldown", { time: timeLeft.toFixed(1), command: cmd }), }); } + timestamps.set(message.author.id, now); + setTimeout(() => timestamps.delete(message.author.id), cooldownAmount); + } else { + timestamps.set(message.author.id, now); + setTimeout(() => timestamps.delete(message.author.id), cooldownAmount); + } - try { - return command.run(this.client, ctx, ctx.args); - } catch (error) { - this.client.logger.error(error); - await message.reply({ - content: T(locale, "event.message.error", { error: error.message || "Unknown error" }), - }); - } finally { - const logs = this.client.channels.cache.get(this.client.env.LOG_COMMANDS_ID); - if (logs) { - const embed = new EmbedBuilder() - .setAuthor({ - name: "Prefix - Command Logs", - iconURL: this.client.user?.avatarURL({ size: 2048 }), - }) - .setColor(this.client.config.color.green) - .setDescription( - `**\`${command.name}\`** | Used By **${message.author.tag} \`${message.author.id}\`** From **${message.guild.name} \`${message.guild.id}\`**`, - ) - .setTimestamp(); + if (args.includes("@everyone") || args.includes("@here")) { + return await message.reply({ + content: T(locale, "event.message.no_mention_everyone"), + }); + } - await (logs as TextChannel).send({ embeds: [embed] }); - } + try { + return command.run(this.client, ctx, ctx.args); + } catch (error) { + this.client.logger.error(error); + await message.reply({ + content: T(locale, "event.message.error", { error: error.message || "Unknown error" }), + }); + } finally { + const logs = this.client.channels.cache.get(this.client.env.LOG_COMMANDS_ID); + if (logs) { + const embed = new EmbedBuilder() + .setAuthor({ + name: "Prefix - Command Logs", + iconURL: this.client.user?.avatarURL({ size: 2048 }), + }) + .setColor(this.client.config.color.green) + .setDescription( + `**\`${command.name}\`** | Used By **${message.author.tag} \`${message.author.id}\`** From **${message.guild.name} \`${message.guild.id}\`**`, + ) + .setTimestamp(); + + await (logs as TextChannel).send({ embeds: [embed] }); } } } From dea0f4f18667fb6a74defb887098719fd708e727 Mon Sep 17 00:00:00 2001 From: hwangsihu <129564966+hwangsihu@users.noreply.github.com> Date: Thu, 19 Sep 2024 00:21:11 +0900 Subject: [PATCH 06/10] example.application.yml --- Lavalink/example.application.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lavalink/example.application.yml b/Lavalink/example.application.yml index 6ca3ad5d6..8a4317dd2 100644 --- a/Lavalink/example.application.yml +++ b/Lavalink/example.application.yml @@ -88,7 +88,11 @@ plugins: - MUSIC - WEB - ANDROID_TESTSUITE + - ANDROID_MUSIC - TVHTML5EMBEDDED + - ANDROID_LITE + - MEDIA_CONNECT + - IOS # This secure your lavalink is working and playing music if you used this two things below. #oauth: # enabled: true # IF YOU RUN YOUR LAVALINK CHECK YOUR CONSOLE AND CLICK THE GOOGLE.COM/DEVICES LINK AND THERE IS A CODE THAT YOU NEED TO PUT IN TO THE GOOGLE AND USE A BURNER ACCOUNT OR ALT ACCOUNT THERE IS A POSSIBLE CHANGE YOU CAN GET BANNED FROM GOOGLE OR YOUTUBE SO JUST USE A BURNER ACCOUNT IN CASE. From d343846180cf0cf9c0d264829666f6743e0ad5ab Mon Sep 17 00:00:00 2001 From: hwangsihu <129564966+hwangsihu@users.noreply.github.com> Date: Thu, 19 Sep 2024 00:24:06 +0900 Subject: [PATCH 07/10] example.application.yml --- Lavalink/example.application.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lavalink/example.application.yml b/Lavalink/example.application.yml index 8a4317dd2..8f4383fd3 100644 --- a/Lavalink/example.application.yml +++ b/Lavalink/example.application.yml @@ -42,7 +42,7 @@ plugins: spotify: clientId: "your client id" clientSecret: "your client secret" - # spDc: "your sp dc cookie" # the sp dc cookie used for accessing the spotify lyrics api + spDc: "your sp dc cookie" # the sp dc cookie used for accessing the spotify lyrics api countryCode: "US" # the country code you want to use for filtering the artists top tracks. See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 playlistLoadLimit: 6 # The number of pages at 100 tracks each albumLoadLimit: 6 # The number of pages at 50 tracks each From 2aa65b7f957b4a904d363b2cc1a2d3d645b72aab Mon Sep 17 00:00:00 2001 From: LucasB25 <50886682+LucasB25@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:42:27 +0200 Subject: [PATCH 08/10] remove --- Lavalink/example.application.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Lavalink/example.application.yml b/Lavalink/example.application.yml index 8f4383fd3..9e39a288b 100644 --- a/Lavalink/example.application.yml +++ b/Lavalink/example.application.yml @@ -18,7 +18,7 @@ plugins: mixcloud: true # mixcloud.com soundgasm: true # soundgasm.net pixeldrain: true # pixeldrain.com - jiosaavn: + jiosaavn: apiURL: "https://saavn.dev/api" # The API URL for JioSaavn lavasrc: providers: # Custom providers for track loading. This is the default @@ -42,7 +42,7 @@ plugins: spotify: clientId: "your client id" clientSecret: "your client secret" - spDc: "your sp dc cookie" # the sp dc cookie used for accessing the spotify lyrics api + # spDc: "your sp dc cookie" # the sp dc cookie used for accessing the spotify lyrics api countryCode: "US" # the country code you want to use for filtering the artists top tracks. See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 playlistLoadLimit: 6 # The number of pages at 100 tracks each albumLoadLimit: 6 # The number of pages at 50 tracks each @@ -62,8 +62,6 @@ plugins: albumLoadLimit: 6 # The number of pages at 300 tracks each deezer: masterDecryptionKey: "your master decryption key" # the master key used for decrypting the deezer tracks. (yes this is not here you need to get it from somewhere else) - # arl: "your deezer arl" # the arl cookie used for accessing the deezer api this is optional but required for formats above MP3_128 - formats: [ "FLAC", "MP3_320", "MP3_256", "MP3_128", "MP3_64", "AAC_64" ] # the formats you want to use for the deezer tracks. "FLAC", "MP3_320", "MP3_256" & "AAC_64" are only available for premium users and require a valid arl yandexmusic: accessToken: "your access token" # the token used for accessing the yandex music api. See https://github.com/TopiSenpai/LavaSrc#yandex-music playlistLoadLimit: 1 # The number of pages at 100 tracks each From fcda1e2e0bd53e0433ed53eb68ee8fa867759793 Mon Sep 17 00:00:00 2001 From: hwangsihu Date: Thu, 19 Sep 2024 23:40:06 +0900 Subject: [PATCH 09/10] Biome update --- biome.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/biome.json b/biome.json index b85551a9e..a1652fdb5 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/1.9.1/schema.json", + "$schema": "https://biomejs.dev/schemas/1.9.2/schema.json", "organizeImports": { "enabled": true }, diff --git a/package.json b/package.json index dc0aefb5d..f63351dee 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ }, "homepage": "https://github.com/appujet/lavamusic#readme", "devDependencies": { - "@biomejs/biome": "^1.9.1", + "@biomejs/biome": "^1.9.2", "@types/i18n": "^0.13.12", "@types/node": "^22.5.5", "@types/signale": "^1.4.7", From f14b08d58241a457d493eda1f4c784a6429252e3 Mon Sep 17 00:00:00 2001 From: LucasB25 <50886682+LucasB25@users.noreply.github.com> Date: Fri, 20 Sep 2024 18:31:46 +0200 Subject: [PATCH 10/10] Update example.application.yml Signed-off-by: LucasB25 <50886682+LucasB25@users.noreply.github.com> --- Lavalink/example.application.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/Lavalink/example.application.yml b/Lavalink/example.application.yml index 9e39a288b..7b309cbcd 100644 --- a/Lavalink/example.application.yml +++ b/Lavalink/example.application.yml @@ -46,7 +46,6 @@ plugins: countryCode: "US" # the country code you want to use for filtering the artists top tracks. See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 playlistLoadLimit: 6 # The number of pages at 100 tracks each albumLoadLimit: 6 # The number of pages at 50 tracks each - resolveArtistsInSearch: true # Whether to resolve artists in track search results (can be slow) localFiles: false # Enable local files support with Spotify playlists. Please note `uri` & `isrc` will be `null` & `identifier` will be `"local"` applemusic: countryCode: "US" # the country code you want to use for filtering the artists top tracks and language. See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2