From e44d7d0eaccddf86ee8726f414780c7ba5db340f Mon Sep 17 00:00:00 2001 From: topi314 Date: Mon, 4 Dec 2023 11:13:35 +0100 Subject: [PATCH 01/33] fix not rendered markdown in docs tags --- docs/api/rest.md | 42 ++++++++++++++++++------------------- docs/api/websocket.md | 22 +++++++++---------- docs/configuration/index.md | 4 ++-- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/docs/api/rest.md b/docs/api/rest.md index 72d3f9722..f8c1205ce 100644 --- a/docs/api/rest.md +++ b/docs/api/rest.md @@ -30,7 +30,7 @@ When Lavalink encounters an error, it will respond with a JSON object containing | message | string | The error message | | path | string | The request path | -
+
Example Payload ```json @@ -128,7 +128,7 @@ Response: [Track](#track) object with the loaded track. -
+
Example Payload ```yaml @@ -153,7 +153,7 @@ Response: | pluginInfo | Object | Addition playlist info provided by plugins | | tracks | array of [Track](#track) objects | The tracks of the playlist | -
+
Example Payload ```yaml @@ -173,7 +173,7 @@ Response: Array of [Track](#track) objects from the search result. -
+
Example Payload ```yaml @@ -197,7 +197,7 @@ Array of [Track](#track) objects from the search result. Empty object. -
+
Example Payload ```yaml @@ -213,7 +213,7 @@ Empty object. [Exception](websocket.md#exception-object) object with the error. -
+
Example Payload ```yaml @@ -243,7 +243,7 @@ Response: [Track](#track) object -
+
Example Payload ```yaml @@ -281,7 +281,7 @@ Request: Array of track data strings -
+
Example Payload ```yaml @@ -297,7 +297,7 @@ Response: Array of [Track](#track) objects -
+
Example Payload ```yaml @@ -381,7 +381,7 @@ There are 15 bands (0-14) that can be changed. "gain" is the multiplier for the given band. The default value is 0. Valid values range from -0.25 to 1.0, where -0.25 means the given band is completely muted, and 0.25 means it is doubled. Modifying the gain could also change the volume of the output. -
+
Band Frequencies | Band | Frequency | @@ -498,7 +498,7 @@ Any smoothing values equal to or less than 1.0 will disable the filter. Plugins can add their own filters. The key is the name of the plugin, and the value is the configuration for that plugin. The configuration is plugin specific. See [Plugins](plugins.md) for more plugin information. -
+
Example Payload ```json @@ -571,7 +571,7 @@ Returns a list of players in this specific session. GET /v4/sessions/{sessionId}/players ``` -
+
Example Payload ```yaml @@ -631,7 +631,7 @@ Response: [Player](#Player) object -
+
Example Payload ```yaml @@ -724,7 +724,7 @@ Request: When `identifier` is used, Lavalink will try to resolve the identifier as a single track. An HTTP `400` error is returned when resolving a playlist, search result, or no tracks. -
+
Example Payload ```yaml @@ -753,7 +753,7 @@ Response: [Player](#Player) object -
+
Example Payload ```yaml @@ -827,7 +827,7 @@ Request: | resuming? | bool | Whether resuming is enabled for this session or not | | timeout? | int | The timeout in seconds (default is 60s) | -
+
Example Payload ```json @@ -846,7 +846,7 @@ Response: | resuming | bool | Whether resuming is enabled for this session or not | | timeout | int | The timeout in seconds (default is 60s) | -
+
Example Payload ```json @@ -911,7 +911,7 @@ Parsed [Semantic Versioning 2.0.0](https://semver.org/) | name | string | The name of the plugin | | version | string | The version of the plugin | -
+
Example Payload ```json @@ -988,7 +988,7 @@ Response: `frameStats` is always missing for this endpoint. [Stats](websocket.md#stats-object) object -
+
Example Payload ```json @@ -1079,7 +1079,7 @@ Response: | class | ?[Route Planner Type](#route-planner-types) | The name of the RoutePlanner implementation being used by this server | | details | ?[Details](#details-object) object | The status details of the RoutePlanner | -
+
Example Payload ```json @@ -1119,7 +1119,7 @@ Request: |---------|--------|-----------------------------------------------------------------------------| | address | string | The address to unmark as failed. This address must be in the same ip block. | -
+
Example Payload ```json diff --git a/docs/api/websocket.md b/docs/api/websocket.md index 487c5aa36..fe3f18516 100644 --- a/docs/api/websocket.md +++ b/docs/api/websocket.md @@ -19,7 +19,7 @@ When opening a websocket connection, you must supply 3 required headers: **\*For more information on resuming see [Resuming](index.md#resuming)** -
+
Example Headers ``` @@ -37,7 +37,7 @@ Websocket messages all follow the following standard format: | op | [OP Type](#op-types) | The op type | | ... | ... | Extra fields depending on the op type | -
+
Example Payload ```yaml @@ -67,7 +67,7 @@ Dispatched by Lavalink upon successful connection and authorization. Contains fi | resumed | bool | Whether this session was resumed | | sessionId | string | The Lavalink session id of this connection. Not to be confused with a Discord voice session id | -
+
Example Payload ```json @@ -100,7 +100,7 @@ Dispatched every x seconds (configurable in `application.yml`) with the current | connected | bool | Whether Lavalink is connected to the voice gateway | | ping | int | The ping of the node to the Discord voice server in milliseconds (`-1` if not connected) | -
+
Example Payload ```json @@ -162,7 +162,7 @@ A collection of statistics sent every minute. \* The expected amount of frames is 3000 (1 every 20 ms) per player. If the `deficit` is negative, too many frames were sent, and if it's positive, not enough frames got sent. -
+
Example Payload ```json @@ -204,7 +204,7 @@ Server dispatched an event. See the [Event Types](#event-types) section for more | guildId | string | The guild id | | ... | ... | Extra fields depending on the event | -
+
Example Payload ```yaml @@ -236,7 +236,7 @@ Dispatched when a track starts playing. |-------|-------------------------------|--------------------------------| | track | [Track](rest.md#track) object | The track that started playing | -
+
Example Payload ```json @@ -287,7 +287,7 @@ Dispatched when a track ends. | `replaced` | The track was replaced | false | | `cleanup` | The track was cleaned up | false | -
+
Example Payload ```json @@ -345,7 +345,7 @@ Dispatched when a track throws an exception. | `suspicious` | The cause might not be exactly known, but is possibly caused by outside factors. For example when an outside service responds in a format that we do not expect | | `fault` | The probable cause is an issue with the library or there is no way to tell what the cause might be. This is the default level and other levels are used in cases where the thrower has more in-depth knowledge about the error | -
+
Example Payload ```json @@ -391,7 +391,7 @@ Dispatched when a track gets stuck while playing. | track | [Track](rest.md#track) object | The track that got stuck | | thresholdMs | int | The threshold in milliseconds that was exceeded | -
+
Example Payload ```json @@ -437,7 +437,7 @@ See the [Discord Docs](https://discord.com/developers/docs/topics/opcodes-and-st | reason | string | The close reason | | byRemote | bool | Whether the connection was closed by Discord | -
+
Example Payload ```json diff --git a/docs/configuration/index.md b/docs/configuration/index.md index 91745d799..011613c41 100644 --- a/docs/configuration/index.md +++ b/docs/configuration/index.md @@ -8,7 +8,7 @@ The server configuration is done in `application.yml`. You can find an example b ## Example application.yml -
+
application.yml ```yaml title="application.yml" @@ -22,7 +22,7 @@ For arrays, the index is appended to the key, starting at 0. For example, `LAVAL ## Example environment variables -
+
environment variables ```env title="enviroment variables" From 031a9fb194e776f0e11847c09add657c27143914 Mon Sep 17 00:00:00 2001 From: devoxin <15076404+devoxin@users.noreply.github.com> Date: Fri, 8 Dec 2023 20:33:14 +0000 Subject: [PATCH 02/33] Add lavalink.py to clients --- docs/clients.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/clients.md b/docs/clients.md index 5abff48ce..62bcaca70 100644 --- a/docs/clients.md +++ b/docs/clients.md @@ -9,6 +9,7 @@ description: A list of Lavalink client libraries. | [Lavalink-Client](https://github.com/lavalink-devs/Lavalink-Client) | Java/Kotlin/JVM | JDA/Discord4J/**Any** | Uses reactor | | [Lavalink.kt](https://github.com/DRSchlaubi/Lavalink.kt) | Kotlin | Kord/JDA/**Any** | Kotlin Coroutines | | [DisGoLink](https://github.com/disgoorg/disgolink) | Go | **Any** | | +| [lavalink.py](https://github.com/devoxin/lavalink.py) | Python | **Any** | | | [Mafic](https://github.com/ooliver1/mafic) | Python | discord.py **V2**/nextcord/disnake/py-cord | | | [Wavelink](https://github.com/PythonistaGuild/Wavelink) | Python | discord.py **V2** | | | [Moonlink.js](https://github.com/1Lucas1apk/moonlink.js) | Node.js | **Any** | | From 9ff9f07d48672f10526368a7c9175e7028fab583 Mon Sep 17 00:00:00 2001 From: topi314 Date: Sat, 9 Dec 2023 12:37:37 +0100 Subject: [PATCH 03/33] update significant changes & fix plugin filters link --- docs/api/rest.md | 26 +++++++++++++------------- docs/changelog/index.md | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/api/rest.md b/docs/api/rest.md index f8c1205ce..c3b5f19ff 100644 --- a/docs/api/rest.md +++ b/docs/api/rest.md @@ -361,19 +361,19 @@ with the Voice Server Update. Please refer to https://discord.com/developers/doc Filters are used in above requests and look like this -| Field | Type | Description | -|----------------|------------------------------------------------|----------------------------------------------------------------------------------------------| -| volume? | float | Adjusts the player volume from 0.0 to 5.0, where 1.0 is 100%. Values >1.0 may cause clipping | -| equalizer? | array of [Equalizer](#equalizer) objects | Adjusts 15 different bands | -| karaoke? | [Karaoke](#karaoke) object | Eliminates part of a band, usually targeting vocals | -| timescale? | [Timescale](#timescale) object | Changes the speed, pitch, and rate | -| tremolo? | [Tremolo](#tremolo) object | Creates a shuddering effect, where the volume quickly oscillates | -| vibrato? | [Vibrato](#vibrato) object | Creates a shuddering effect, where the pitch quickly oscillates | -| rotation? | [Rotation](#rotation) object | Rotates the audio around the stereo channels/user headphones (aka Audio Panning) | -| distortion? | [Distortion](#distortion) object | Distorts the audio | -| channelMix? | [Channel Mix](#channel-mix) object | Mixes both channels (left and right) | -| lowPass? | [Low Pass](#low-pass) object | Filters higher frequencies | -| pluginFilters? | map of [Plugin Filter](#plugin-filter) objects | Filter plugin configurations | +| Field | Type | Description | +|----------------|--------------------------------------------------|----------------------------------------------------------------------------------------------| +| volume? | float | Adjusts the player volume from 0.0 to 5.0, where 1.0 is 100%. Values >1.0 may cause clipping | +| equalizer? | array of [Equalizer](#equalizer) objects | Adjusts 15 different bands | +| karaoke? | [Karaoke](#karaoke) object | Eliminates part of a band, usually targeting vocals | +| timescale? | [Timescale](#timescale) object | Changes the speed, pitch, and rate | +| tremolo? | [Tremolo](#tremolo) object | Creates a shuddering effect, where the volume quickly oscillates | +| vibrato? | [Vibrato](#vibrato) object | Creates a shuddering effect, where the pitch quickly oscillates | +| rotation? | [Rotation](#rotation) object | Rotates the audio around the stereo channels/user headphones (aka Audio Panning) | +| distortion? | [Distortion](#distortion) object | Distorts the audio | +| channelMix? | [Channel Mix](#channel-mix) object | Mixes both channels (left and right) | +| lowPass? | [Low Pass](#low-pass) object | Filters higher frequencies | +| pluginFilters? | map of [Plugin Filters](#plugin-filters) objects | Filter plugin configurations | ##### Equalizer diff --git a/docs/changelog/index.md b/docs/changelog/index.md index 572a99faf..5c43ab435 100644 --- a/docs/changelog/index.md +++ b/docs/changelog/index.md @@ -26,7 +26,7 @@ The most noteworthy of these, as well as any features and breaking changes, are All websocket ops are removed as of `v4.0.0` and replaced with the following endpoints and json fields: -* `play` -> [Update Player Endpoint](#update-player) `encodedTrack` or `identifier` field +* `play` -> [Update Player Endpoint](#update-player) `track`->`encoded` or `track`->`identifier` field * `stop` -> [Update Player Endpoint](#update-player) `encodedTrack` field with `null` * `pause` -> [Update Player Endpoint](#update-player) `pause` field * `seek` -> [Update Player Endpoint](#update-player) `position` field From f790a2e1206fd046222fbe40b199de106d408c8b Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sun, 17 Dec 2023 14:36:15 +0100 Subject: [PATCH 04/33] Add lyrics.kt (#996) * Add lyrics.kt * Make somone happy --- docs/plugins.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/plugins.md b/docs/plugins.md index 4ea709419..417ab5f86 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -20,5 +20,6 @@ for instructions. | [DuncteBot plugin](https://github.com/DuncteBot/skybot-lavalink-plugin) | Additional source managers that are not widely used | | [Extra Filter plugin](https://github.com/rohank05/lavalink-filter-plugin) | Additional audio filters for lavalink | | [XM plugin](https://github.com/esmBot/lava-xm-plugin) | Support for various [music tracker module](https://en.wikipedia.org/wiki/Module_file) formats | +| [Lyrics.kt plugin](https://github.com/DRSchlaubi/lyrics.kt) | Plugin that fetches timestamped lyrics from YouTube | If you want to make your own plugin see [here](api/plugins.md) \ No newline at end of file From 29f5c957cbf60bfcaa752fec7246295a563e968f Mon Sep 17 00:00:00 2001 From: topi314 Date: Mon, 18 Dec 2023 00:29:49 +0100 Subject: [PATCH 05/33] fix readme & move routeplanner docs --- README.md | 2 +- ROUTEPLANNERS.md => docs/configuration/routeplanner.md | 4 +++- docs/mkdocs.yml | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) rename ROUTEPLANNERS.md => docs/configuration/routeplanner.md (97%) diff --git a/README.md b/README.md index 5382fb723..b5f0b6ea3 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ A [basic example bot](Testbot) is available. * Basic authentication * Prometheus metrics * Docker images -* [Plugin support](PLUGINS.md) +* [Plugin support](https://lavalink.dev/plugins.html) ## Requirements diff --git a/ROUTEPLANNERS.md b/docs/configuration/routeplanner.md similarity index 97% rename from ROUTEPLANNERS.md rename to docs/configuration/routeplanner.md index 2acf184f9..f2721003f 100644 --- a/ROUTEPLANNERS.md +++ b/docs/configuration/routeplanner.md @@ -1,4 +1,6 @@ -# RoutePlanner Strategies +--- +description: Lavalink RoutePlanner Strategies +--- ## Terminology diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 7214bf763..1434f86d2 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -24,6 +24,7 @@ nav: - Binary: configuration/binary.md - Systemd: configuration/systemd.md - Docker: configuration/docker.md + - RoutePlanner: configuration/routeplanner.md - Clients: clients.md - Plugins: plugins.md - API: From 6de2a86fbd0910a42e4c69da81560330a58af2d2 Mon Sep 17 00:00:00 2001 From: Abitofevrything <54505189+abitofevrything@users.noreply.github.com> Date: Wed, 27 Dec 2023 14:42:49 +0100 Subject: [PATCH 06/33] Add nyxx_lavalink to clients (#998) * Add nyxx_lavalink to clients * Merge Dart clients into one entry --- docs/clients.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/clients.md b/docs/clients.md index 62bcaca70..eb5688e53 100644 --- a/docs/clients.md +++ b/docs/clients.md @@ -23,6 +23,7 @@ description: A list of Lavalink client libraries. | [Lavalink4NET](https://github.com/angelobreuer/Lavalink4NET) | .NET | Discord.Net/DSharpPlus/Remora | v4+ | | [Coglink](https://github.com/PerformanC/Coglink) | C | Concord | | | [lavalink-rs](https://gitlab.com/vicky5124/lavalink-rs) | Rust, Python | **Any** | `tokio`-based, `asyncio`-based | +| [lavalink](https://github.com/nyxx-discord/nyxx_lavalink) | Dart | nyxx/**Any** | |
v3.7 supporting Client Libraries From aa605c0bd2c41582826720f637b71565a439bdf4 Mon Sep 17 00:00:00 2001 From: Egor Dvachevsky Date: Thu, 28 Dec 2023 16:42:02 +0100 Subject: [PATCH 07/33] Move nomia to clients that support lavalink version 4.x.x (#999) --- docs/clients.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/clients.md b/docs/clients.md index eb5688e53..aed80496b 100644 --- a/docs/clients.md +++ b/docs/clients.md @@ -21,6 +21,7 @@ description: A list of Lavalink client libraries. | [Riffy](https://github.com/riffy-team/riffy) | Node.js | **Any** | | | [DisCatSharp](https://github.com/Aiko-IT-Systems/DisCatSharp) | .NET | DisCatSharp | v10.4.2+ | | [Lavalink4NET](https://github.com/angelobreuer/Lavalink4NET) | .NET | Discord.Net/DSharpPlus/Remora | v4+ | +| [Nomia](https://github.com/DHCPCD9/Nomia) | .NET | DSharpPlus | | | [Coglink](https://github.com/PerformanC/Coglink) | C | Concord | | | [lavalink-rs](https://gitlab.com/vicky5124/lavalink-rs) | Rust, Python | **Any** | `tokio`-based, `asyncio`-based | | [lavalink](https://github.com/nyxx-discord/nyxx_lavalink) | Dart | nyxx/**Any** | | @@ -40,7 +41,6 @@ description: A list of Lavalink client libraries. | [Shoukaku](https://github.com/Deivu/Shoukaku) | Node.js | **Any** | | | [Cosmicord.js](https://github.com/SudhanPlayz/Cosmicord.js) | Node.js | **Any** | | | [DisCatSharp](https://github.com/Aiko-IT-Systems/DisCatSharp) | .NET | DisCatSharp | Only prior v10.4.1 | -| [Nomia](https://github.com/DHCPCD9/Nomia) | .NET | DSharpPlus | | | [Lavalink4NET](https://github.com/angelobreuer/Lavalink4NET) | .NET | Discord.Net/DSharpPlus | < v4 | | [DisGoLink](https://github.com/disgoorg/disgolink) | Go | **Any** | | From 93d8f6c92fc68e930f7d8381f083e000f266a5c6 Mon Sep 17 00:00:00 2001 From: topi314 Date: Sat, 30 Dec 2023 11:54:55 +0100 Subject: [PATCH 08/33] add warning when trying to connect to the old websocket endpoints --- .../java/lavalink/server/config/WebsocketConfig.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/LavalinkServer/src/main/java/lavalink/server/config/WebsocketConfig.kt b/LavalinkServer/src/main/java/lavalink/server/config/WebsocketConfig.kt index fbf73b34e..16c57eb61 100644 --- a/LavalinkServer/src/main/java/lavalink/server/config/WebsocketConfig.kt +++ b/LavalinkServer/src/main/java/lavalink/server/config/WebsocketConfig.kt @@ -2,18 +2,32 @@ package lavalink.server.config import lavalink.server.io.HandshakeInterceptorImpl import lavalink.server.io.SocketServer +import org.slf4j.LoggerFactory import org.springframework.context.annotation.Configuration +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RestController import org.springframework.web.socket.config.annotation.EnableWebSocket import org.springframework.web.socket.config.annotation.WebSocketConfigurer import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry @Configuration @EnableWebSocket +@RestController class WebsocketConfig( private val server: SocketServer, private val handshakeInterceptor: HandshakeInterceptorImpl, ) : WebSocketConfigurer { + + companion object { + private val log = LoggerFactory.getLogger(WebsocketConfig::class.java) + } + override fun registerWebSocketHandlers(registry: WebSocketHandlerRegistry) { registry.addHandler(server, "/v4/websocket").addInterceptors(handshakeInterceptor) } + + @GetMapping("/", "/v3/websocket") + fun oldWebsocket() { + log.warn("This is the old Lavalink websocket endpoint. Please use /v4/websocket instead. If you are using a client library, please update it to a Lavalink v4 compatible version or use Lavalink v3 instead.") + } } From 4acd10f0ec70c54330d34adbf530456f2f2ff703 Mon Sep 17 00:00:00 2001 From: topi314 Date: Sat, 30 Dec 2023 11:57:20 +0100 Subject: [PATCH 09/33] this info log isn't needed anymore since java 17 apparently --- LavalinkServer/src/main/java/lavalink/server/Launcher.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/LavalinkServer/src/main/java/lavalink/server/Launcher.kt b/LavalinkServer/src/main/java/lavalink/server/Launcher.kt index 6ae103fe7..8252b9a47 100644 --- a/LavalinkServer/src/main/java/lavalink/server/Launcher.kt +++ b/LavalinkServer/src/main/java/lavalink/server/Launcher.kt @@ -123,7 +123,6 @@ object Launcher { } val parent = launchPluginBootstrap() - log.info("You can safely ignore the big red warning about illegal reflection. See https://github.com/lavalink-devs/Lavalink/issues/295") launchMain(parent, args) } From 3820e5397a2014ef99f62c0763e201c29b64705b Mon Sep 17 00:00:00 2001 From: topi314 Date: Thu, 4 Jan 2024 00:04:38 +0100 Subject: [PATCH 10/33] fix not being able to seek when player is paused --- .../src/main/java/lavalink/server/player/PlayerRestHandler.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LavalinkServer/src/main/java/lavalink/server/player/PlayerRestHandler.kt b/LavalinkServer/src/main/java/lavalink/server/player/PlayerRestHandler.kt index 6a837dbf5..4f4831078 100644 --- a/LavalinkServer/src/main/java/lavalink/server/player/PlayerRestHandler.kt +++ b/LavalinkServer/src/main/java/lavalink/server/player/PlayerRestHandler.kt @@ -150,7 +150,7 @@ class PlayerRestHandler( // we handle position differently for playing new tracks playerUpdate.position.takeIfPresent { encodedTrack is Omissible.Omitted && identifier is Omissible.Omitted } ?.let { - if (player.isPlaying) { + if (player.track != null) { player.seekTo(it) SocketServer.sendPlayerUpdate(context, player) } From 75559ad3169e698a4cbec4a8d766789c62d83395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?To=CF=80?= Date: Thu, 4 Jan 2024 00:11:52 +0100 Subject: [PATCH 11/33] Fix/user data missing field exception (#997) --- .../kotlin/dev/arbjerg/lavalink/protocol/v4/loadResult.kt | 2 +- .../kotlin/dev/arbjerg/lavalink/protocol/v4/player.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/loadResult.kt b/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/loadResult.kt index f1b902d1f..c5c348c3c 100644 --- a/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/loadResult.kt +++ b/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/loadResult.kt @@ -133,7 +133,7 @@ data class PlaylistInfo( @Serializable data class Playlist( val info: PlaylistInfo, - val pluginInfo: JsonObject, + val pluginInfo: JsonObject = JsonObject(emptyMap()), val tracks: List ) : LoadResult.Data { diff --git a/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/player.kt b/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/player.kt index b9ddf2733..19c7a7917 100644 --- a/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/player.kt +++ b/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/player.kt @@ -31,8 +31,8 @@ data class Player( data class Track( val encoded: String, val info: TrackInfo, - val pluginInfo: JsonObject, - val userData: JsonObject + val pluginInfo: JsonObject = JsonObject(emptyMap()), + val userData: JsonObject = JsonObject(emptyMap()) ) : LoadResult.Data { /** From c2431ce1b1aab088aff29033b2e44bb840fd5cd1 Mon Sep 17 00:00:00 2001 From: Duncan Sterken Date: Thu, 4 Jan 2024 10:34:48 +0100 Subject: [PATCH 12/33] Add JTL plugin (#1001) Features include: ip-rotation and LavaLyrics support --- docs/plugins.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/plugins.md b/docs/plugins.md index 417ab5f86..e285e3ec0 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -21,5 +21,6 @@ for instructions. | [Extra Filter plugin](https://github.com/rohank05/lavalink-filter-plugin) | Additional audio filters for lavalink | | [XM plugin](https://github.com/esmBot/lava-xm-plugin) | Support for various [music tracker module](https://en.wikipedia.org/wiki/Module_file) formats | | [Lyrics.kt plugin](https://github.com/DRSchlaubi/lyrics.kt) | Plugin that fetches timestamped lyrics from YouTube | +| [Java Timed Lyrics](https://github.com/DuncteBot/java-timed-lyrics) | Timestamped lyrics from YouTube with Genius fallback, supports IP-rotation | -If you want to make your own plugin see [here](api/plugins.md) \ No newline at end of file +If you want to make your own plugin see [here](api/plugins.md) From 2cbe1bbfa645e54b5f3f07dcb9fea5810abe912b Mon Sep 17 00:00:00 2001 From: Freya Arbjerg Date: Thu, 11 Jan 2024 10:27:49 +0100 Subject: [PATCH 13/33] Update Lavaplayer to version 2.1.0 --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index cf4dad5bb..861cb22c7 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -36,7 +36,7 @@ fun VersionCatalogBuilder.spring() { } fun VersionCatalogBuilder.voice() { - version("lavaplayer", "2.0.4") + version("lavaplayer", "2.1.0") library("lavaplayer", "dev.arbjerg", "lavaplayer").versionRef("lavaplayer") library("lavaplayer-ip-rotator", "dev.arbjerg", "lavaplayer-ext-youtube-rotator").versionRef("lavaplayer") From 6560834b31d70ee1c89907d925df7bc2b0613480 Mon Sep 17 00:00:00 2001 From: topi314 Date: Thu, 25 Jan 2024 12:28:27 +0100 Subject: [PATCH 14/33] fix publishing snapshots into releases & other way around --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 98e606842..cd938efea 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -54,7 +54,7 @@ subprojects { val snapshots = "https://maven.lavalink.dev/snapshots" val releases = "https://maven.lavalink.dev/releases" - maven(if ((version as String).endsWith("-SNAPSHOT")) releases else snapshots) { + maven(if ((version as String).endsWith("-SNAPSHOT")) snapshots else releases) { credentials { password = findProperty("MAVEN_PASSWORD") as String? username = findProperty("MAVEN_USERNAME") as String? From c4351be3ba24a0d3e7ae542e057db8ae21186d26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?To=CF=80?= Date: Mon, 5 Feb 2024 13:05:36 +0100 Subject: [PATCH 15/33] fix plugin manager not deleting old plugin version (#991) * read plugin version & name from manifest instead of file name in plugin manager * close JarFile correctly --- .../server/bootstrap/PluginManager.kt | 100 ++++++++++-------- 1 file changed, 55 insertions(+), 45 deletions(-) diff --git a/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt b/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt index 6f168a1b6..d34d61628 100644 --- a/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt +++ b/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt @@ -10,15 +10,16 @@ import java.io.InputStream import java.net.URL import java.net.URLClassLoader import java.nio.channels.Channels -import java.nio.file.Files import java.util.* import java.util.jar.JarFile -import java.util.regex.Pattern - @SpringBootApplication class PluginManager(val config: PluginsConfig) { + companion object { + private val log: Logger = LoggerFactory.getLogger(PluginManager::class.java) + } + final val pluginManifests: MutableList = mutableListOf() var classLoader: ClassLoader = PluginManager::class.java.classLoader @@ -35,14 +36,13 @@ class PluginManager(val config: PluginsConfig) { val directory = File(config.pluginsDir) directory.mkdir() - data class PluginJar(val name: String, val version: String, val file: File) + data class PluginJar(val manifest: PluginManifest, val file: File) - val pattern = Pattern.compile("(.+)-(.+)\\.jar$") - val pluginJars = directory.listFiles()!!.mapNotNull { f -> - val matcher = pattern.matcher(f.name) - if (!matcher.find()) return@mapNotNull null - PluginJar(matcher.group(1), matcher.group(2), f) - } + val pluginJars = directory.listFiles()!!.filter { it.extension == "jar" }.map { + JarFile(it).use {jar -> + loadPluginManifests(jar).map { manifest -> PluginJar(manifest, it) } + } + }.flatten() data class Declaration(val group: String, val name: String, val version: String, val repository: String) @@ -55,21 +55,22 @@ class PluginManager(val config: PluginsConfig) { ?: if (declaration.snapshot) config.defaultPluginSnapshotRepository else config.defaultPluginRepository repository = if (repository.endsWith("/")) repository else "$repository/" Declaration(fragments[0], fragments[1], fragments[2], repository) - } + }.distinctBy { "${it.group}:${it.name}" } declarations.forEach declarationLoop@{ declaration -> - pluginJars.forEach { jar -> - if (declaration.name == jar.name) { - if (declaration.version == jar.version) { - // We already have this jar so don't redownload it - return@declarationLoop - } - - // Delete jar of different versions - if (!jar.file.delete()) throw RuntimeException("Failed to delete ${jar.file.path}") - log.info("Deleted ${jar.file.path}") + var hasVersion = false + pluginJars.forEach pluginLoop@{ jar -> + if (declaration.version == jar.manifest.version && !hasVersion) { + hasVersion = true + // We already have this jar so don't redownload it + return@pluginLoop } + + // Delete jar of different versions + if (!jar.file.delete()) throw RuntimeException("Failed to delete ${jar.file.path}") + log.info("Deleted ${jar.file.path}") } + if (hasVersion) return@declarationLoop val url = declaration.run { "$repository${group.replace(".", "/")}/$name/$version/$name-$version.jar" } val file = File(directory, declaration.run { "$name-$version.jar" }) @@ -87,7 +88,11 @@ class PluginManager(val config: PluginsConfig) { private fun readClasspathManifests(): List { return PathMatchingResourcePatternResolver() .getResources("classpath*:lavalink-plugins/*.properties") - .map { r -> parsePluginManifest(r.inputStream) } + .map map@{ r -> + val manifest = parsePluginManifest(r.inputStream) + log.info("Found plugin '${manifest.name}' version ${manifest.version}") + return@map manifest + } } private fun loadJars(): List { @@ -95,8 +100,7 @@ class PluginManager(val config: PluginsConfig) { if (!directory.isDirectory) return emptyList() val jarsToLoad = mutableListOf() - Files.list(File(config.pluginsDir).toPath()).forEach { path -> - val file = path.toFile() + directory.listFiles()?.forEach { file -> if (!file.isFile) return@forEach if (file.extension != "jar") return@forEach jarsToLoad.add(file) @@ -111,7 +115,6 @@ class PluginManager(val config: PluginsConfig) { classLoader = cl val manifests = mutableListOf() - jarsToLoad.forEach { file -> try { manifests.addAll(loadJar(file, cl)) @@ -124,31 +127,43 @@ class PluginManager(val config: PluginsConfig) { return manifests } - private fun loadJar(file: File, cl: URLClassLoader): MutableList { + private fun loadJar(file: File, cl: URLClassLoader): List { var classCount = 0 val jar = JarFile(file) + var manifests: List + + jar.use { + manifests = loadPluginManifests(jar) + if (manifests.isEmpty()) { + throw RuntimeException("No plugin manifest found in ${file.path}") + } + val allowedPaths = manifests.map { it.path.replace(".", "/") } + + jar.entries().asIterator().forEach { entry -> + if (entry.isDirectory) return@forEach + if (!entry.name.endsWith(".class")) return@forEach + if (!allowedPaths.any { entry.name.startsWith(it) }) return@forEach + cl.loadClass(entry.name.dropLast(6).replace("/", ".")) + classCount++ + } + } + + log.info("Loaded ${file.name} ($classCount classes)") + return manifests + } + + private fun loadPluginManifests(jar: JarFile): List { val manifests = mutableListOf() jar.entries().asIterator().forEach { entry -> if (entry.isDirectory) return@forEach if (!entry.name.startsWith("lavalink-plugins/")) return@forEach if (!entry.name.endsWith(".properties")) return@forEach - manifests.add(parsePluginManifest(jar.getInputStream(entry))) - } - if (manifests.isEmpty()) { - throw RuntimeException("No plugin manifest found in ${file.path}") + val manifest = parsePluginManifest(jar.getInputStream(entry)) + log.info("Found plugin '${manifest.name}' version ${manifest.version}") + manifests.add(manifest) } - val allowedPaths = manifests.map { it.path.replace(".", "/") } - - jar.entries().asIterator().forEach { entry -> - if (entry.isDirectory) return@forEach - if (!entry.name.endsWith(".class")) return@forEach - if (!allowedPaths.any { entry.name.startsWith(it) }) return@forEach - cl.loadClass(entry.name.dropLast(6).replace("/", ".")) - classCount++ - } - log.info("Loaded ${file.name} ($classCount classes)") return manifests } @@ -160,11 +175,6 @@ class PluginManager(val config: PluginsConfig) { val name = props.getProperty("name") ?: throw RuntimeException("Manifest is missing 'name'") val path = props.getProperty("path") ?: throw RuntimeException("Manifest is missing 'path'") val version = props.getProperty("version") ?: throw RuntimeException("Manifest is missing 'version'") - log.info("Found plugin '$name' version $version") return PluginManifest(name, path, version) } - - companion object { - private val log: Logger = LoggerFactory.getLogger(PluginManager::class.java) - } } \ No newline at end of file From a5278864694d95276eb68b4ca861a24a5a1694d4 Mon Sep 17 00:00:00 2001 From: Freya Arbjerg Date: Mon, 5 Feb 2024 13:23:17 +0100 Subject: [PATCH 16/33] Release 4.0.1 --- CHANGELOG.md | 8 ++++++++ docs/changelog/v4.md | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff0ec9644..769a345d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,14 @@ Each release usually includes various fixes and improvements. The most noteworthy of these, as well as any features and breaking changes, are listed here. +## 4.0.1 +* Updated Lavaplayer to 2.10 +* Updated OSHI to 6.4.8 +* Fix/user data missing field exception in protocol +* Fix plugin manager not deleting old plugin version +* Fix not being able to seek when player is paused +* Removed illegal reflection notice + ## 4.0.0 * Lavalink now requires Java 17 or higher to run * **Removal of all websocket messages sent by the client. Everything is now done via [REST](../api/rest.md)** diff --git a/docs/changelog/v4.md b/docs/changelog/v4.md index e7db702f5..ad762f496 100644 --- a/docs/changelog/v4.md +++ b/docs/changelog/v4.md @@ -1,3 +1,11 @@ +## 4.0.1 +* Updated Lavaplayer to 2.10 +* Updated OSHI to 6.4.8 +* Fix/user data missing field exception in protocol +* Fix plugin manager not deleting old plugin version +* Fix not being able to seek when player is paused +* Removed illegal reflection notice + ## v4.0.0 * Lavalink now requires Java 17 or higher to run * **Removal of all websocket messages sent by the client. Everything is now done via [REST](../api/rest.md)** From c59e0877401483e6f2d71af321175e6190d5e221 Mon Sep 17 00:00:00 2001 From: topi314 Date: Mon, 5 Feb 2024 23:29:59 +0100 Subject: [PATCH 17/33] fix issue where all plugins get deleted when already present --- .../server/bootstrap/PluginManager.kt | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt b/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt index d34d61628..8d83cad3f 100644 --- a/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt +++ b/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt @@ -39,8 +39,11 @@ class PluginManager(val config: PluginsConfig) { data class PluginJar(val manifest: PluginManifest, val file: File) val pluginJars = directory.listFiles()!!.filter { it.extension == "jar" }.map { - JarFile(it).use {jar -> - loadPluginManifests(jar).map { manifest -> PluginJar(manifest, it) } + JarFile(it).use { jar -> + loadPluginManifests(jar).map { manifest -> + log.info("Found plugin '${manifest.name}' version ${manifest.version}") + PluginJar(manifest, it) + } } }.flatten() @@ -59,17 +62,18 @@ class PluginManager(val config: PluginsConfig) { declarations.forEach declarationLoop@{ declaration -> var hasVersion = false - pluginJars.forEach pluginLoop@{ jar -> - if (declaration.version == jar.manifest.version && !hasVersion) { - hasVersion = true - // We already have this jar so don't redownload it - return@pluginLoop + pluginJars.filter { jar -> declaration.name == jar.manifest.name } + .forEach pluginLoop@{ jar -> + if (declaration.version == jar.manifest.version && !hasVersion) { + hasVersion = true + // We already have this jar so don't redownload it + return@pluginLoop + } + + // Delete jar of different versions + if (!jar.file.delete()) throw RuntimeException("Failed to delete ${jar.file.path}") + log.info("Deleted ${jar.file.path}") } - - // Delete jar of different versions - if (!jar.file.delete()) throw RuntimeException("Failed to delete ${jar.file.path}") - log.info("Deleted ${jar.file.path}") - } if (hasVersion) return@declarationLoop val url = declaration.run { "$repository${group.replace(".", "/")}/$name/$version/$name-$version.jar" } @@ -130,7 +134,7 @@ class PluginManager(val config: PluginsConfig) { private fun loadJar(file: File, cl: URLClassLoader): List { var classCount = 0 val jar = JarFile(file) - var manifests: List + var manifests: List jar.use { manifests = loadPluginManifests(jar) @@ -160,9 +164,7 @@ class PluginManager(val config: PluginsConfig) { if (!entry.name.startsWith("lavalink-plugins/")) return@forEach if (!entry.name.endsWith(".properties")) return@forEach - val manifest = parsePluginManifest(jar.getInputStream(entry)) - log.info("Found plugin '${manifest.name}' version ${manifest.version}") - manifests.add(manifest) + manifests.add(parsePluginManifest(jar.getInputStream(entry))) } return manifests } From 59b7ac8207363b24b735468d778c6c594dd8e293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?To=CF=80?= Date: Tue, 6 Feb 2024 11:36:31 +0100 Subject: [PATCH 18/33] always include plugin info & user data when serializing (#1008) --- .../kotlin/dev/arbjerg/lavalink/protocol/v4/loadResult.kt | 6 ++---- .../kotlin/dev/arbjerg/lavalink/protocol/v4/player.kt | 7 ++++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/loadResult.kt b/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/loadResult.kt index c5c348c3c..db289f9c3 100644 --- a/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/loadResult.kt +++ b/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/loadResult.kt @@ -3,10 +3,7 @@ package dev.arbjerg.lavalink.protocol.v4 import dev.arbjerg.lavalink.protocol.v4.serialization.asPolymorphicDeserializer -import kotlinx.serialization.DeserializationStrategy -import kotlinx.serialization.KSerializer -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable +import kotlinx.serialization.* import kotlinx.serialization.builtins.ListSerializer import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder @@ -133,6 +130,7 @@ data class PlaylistInfo( @Serializable data class Playlist( val info: PlaylistInfo, + @EncodeDefault val pluginInfo: JsonObject = JsonObject(emptyMap()), val tracks: List ) : LoadResult.Data { diff --git a/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/player.kt b/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/player.kt index 19c7a7917..c4e2b0c36 100644 --- a/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/player.kt +++ b/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/player.kt @@ -1,9 +1,8 @@ package dev.arbjerg.lavalink.protocol.v4 -import kotlinx.serialization.DeserializationStrategy -import kotlinx.serialization.Serializable +import kotlinx.serialization.* +import kotlinx.serialization.json.JsonNames import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.serializer import kotlin.jvm.JvmInline inline fun JsonObject.deserialize(): T = @@ -31,7 +30,9 @@ data class Player( data class Track( val encoded: String, val info: TrackInfo, + @EncodeDefault val pluginInfo: JsonObject = JsonObject(emptyMap()), + @EncodeDefault val userData: JsonObject = JsonObject(emptyMap()) ) : LoadResult.Data { From b9eae8a7cc25d70c71da428cec7bcc1d368220ea Mon Sep 17 00:00:00 2001 From: devoxin <15076404+devoxin@users.noreply.github.com> Date: Tue, 6 Feb 2024 15:48:45 +0000 Subject: [PATCH 19/33] Cleanup plugin loading code (#1009) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * cleanup code * apply feedback * don't iterate jars twice * Update LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt Co-authored-by: Toπ * remove stray `")` --------- Co-authored-by: Toπ --- .gitignore | 3 +- .../src/main/java/lavalink/server/Launcher.kt | 2 +- .../server/bootstrap/PluginManager.kt | 142 ++++++++---------- 3 files changed, 65 insertions(+), 82 deletions(-) diff --git a/.gitignore b/.gitignore index d9ac554cd..703911c04 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,5 @@ gradle.properties application.yml LavalinkServer/plugins .cache/ -site/ \ No newline at end of file +site/ +.DS_Store \ No newline at end of file diff --git a/LavalinkServer/src/main/java/lavalink/server/Launcher.kt b/LavalinkServer/src/main/java/lavalink/server/Launcher.kt index 8252b9a47..28186c783 100644 --- a/LavalinkServer/src/main/java/lavalink/server/Launcher.kt +++ b/LavalinkServer/src/main/java/lavalink/server/Launcher.kt @@ -143,7 +143,7 @@ object Launcher { .properties(properties) .web(WebApplicationType.SERVLET) .bannerMode(Banner.Mode.OFF) - .resourceLoader(DefaultResourceLoader(pluginManager.classLoader)) + .resourceLoader(DefaultResourceLoader(pluginManager::class.java.classLoader)) .listeners( ApplicationListener { event: Any -> when (event) { diff --git a/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt b/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt index 8d83cad3f..e422785a6 100644 --- a/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt +++ b/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt @@ -15,13 +15,11 @@ import java.util.jar.JarFile @SpringBootApplication class PluginManager(val config: PluginsConfig) { - companion object { private val log: Logger = LoggerFactory.getLogger(PluginManager::class.java) } final val pluginManifests: MutableList = mutableListOf() - var classLoader: ClassLoader = PluginManager::class.java.classLoader init { manageDownloads() @@ -33,57 +31,59 @@ class PluginManager(val config: PluginsConfig) { private fun manageDownloads() { if (config.plugins.isEmpty()) return + val directory = File(config.pluginsDir) directory.mkdir() - data class PluginJar(val manifest: PluginManifest, val file: File) - - val pluginJars = directory.listFiles()!!.filter { it.extension == "jar" }.map { - JarFile(it).use { jar -> - loadPluginManifests(jar).map { manifest -> - log.info("Found plugin '${manifest.name}' version ${manifest.version}") - PluginJar(manifest, it) + val pluginJars = directory.listFiles()?.filter { it.extension == "jar" } + ?.flatMap { file -> + JarFile(file).use { jar -> + loadPluginManifests(jar).map { manifest -> PluginJar(manifest, file) } } } - }.flatten() - - data class Declaration(val group: String, val name: String, val version: String, val repository: String) + ?.onEach { log.info("Found plugin '${it.manifest.name}' version ${it.manifest.version}") } + ?: return val declarations = config.plugins.map { declaration -> if (declaration.dependency == null) throw RuntimeException("Illegal dependency declaration: null") val fragments = declaration.dependency!!.split(":") if (fragments.size != 3) throw RuntimeException("Invalid dependency \"${declaration.dependency}\"") - var repository = declaration.repository - ?: if (declaration.snapshot) config.defaultPluginSnapshotRepository else config.defaultPluginRepository - repository = if (repository.endsWith("/")) repository else "$repository/" - Declaration(fragments[0], fragments[1], fragments[2], repository) + val repository = declaration.repository + ?: config.defaultPluginSnapshotRepository.takeIf { declaration.snapshot } + ?: config.defaultPluginRepository + + Declaration(fragments[0], fragments[1], fragments[2], "${repository.removeSuffix("/")}/") }.distinctBy { "${it.group}:${it.name}" } - declarations.forEach declarationLoop@{ declaration -> - var hasVersion = false - pluginJars.filter { jar -> declaration.name == jar.manifest.name } - .forEach pluginLoop@{ jar -> - if (declaration.version == jar.manifest.version && !hasVersion) { - hasVersion = true - // We already have this jar so don't redownload it - return@pluginLoop - } - - // Delete jar of different versions - if (!jar.file.delete()) throw RuntimeException("Failed to delete ${jar.file.path}") - log.info("Deleted ${jar.file.path}") + for (declaration in declarations) { + val jars = pluginJars.filter { it.manifest.name == declaration.name } + var hasCurrentVersion = false + + for (jar in jars) { + if (jar.manifest.version == declaration.version) { + hasCurrentVersion = true + // Don't clean up the jar if it's a current version. + continue } - if (hasVersion) return@declarationLoop - val url = declaration.run { "$repository${group.replace(".", "/")}/$name/$version/$name-$version.jar" } - val file = File(directory, declaration.run { "$name-$version.jar" }) - downloadJar(file, url) + // Delete versions of the plugin that aren't the same as declared version. + if (!jar.file.delete()) throw RuntimeException("Failed to delete ${jar.file.path}") + log.info("Deleted ${jar.file.path} (new version: ${declaration.version})") + + } + + if (!hasCurrentVersion) { + val url = declaration.url + val file = File(directory, declaration.canonicalJarName) + downloadJar(file, url) + } } } private fun downloadJar(output: File, url: String) { log.info("Downloading $url") + Channels.newChannel(URL(url).openStream()).use { FileOutputStream(output).channel.transferFrom(it, 0, Long.MAX_VALUE) } @@ -92,61 +92,43 @@ class PluginManager(val config: PluginsConfig) { private fun readClasspathManifests(): List { return PathMatchingResourcePatternResolver() .getResources("classpath*:lavalink-plugins/*.properties") - .map map@{ r -> - val manifest = parsePluginManifest(r.inputStream) - log.info("Found plugin '${manifest.name}' version ${manifest.version}") - return@map manifest - } + .map { parsePluginManifest(it.inputStream) } + .onEach { log.info("Found plugin '${it.name}' version ${it.version}") } } private fun loadJars(): List { - val directory = File(config.pluginsDir) - if (!directory.isDirectory) return emptyList() - val jarsToLoad = mutableListOf() - - directory.listFiles()?.forEach { file -> - if (!file.isFile) return@forEach - if (file.extension != "jar") return@forEach - jarsToLoad.add(file) - } + val directory = File(config.pluginsDir).takeIf { it.isDirectory } + ?: return emptyList() - if (jarsToLoad.isEmpty()) return emptyList() + val jarsToLoad = directory.listFiles()?.filter { it.isFile && it.extension == "jar" } + ?.takeIf { it.isNotEmpty() } + ?: return emptyList() - val cl = URLClassLoader.newInstance( + val classLoader = URLClassLoader.newInstance( jarsToLoad.map { URL("jar:file:${it.absolutePath}!/") }.toTypedArray(), javaClass.classLoader ) - classLoader = cl - - val manifests = mutableListOf() - jarsToLoad.forEach { file -> - try { - manifests.addAll(loadJar(file, cl)) - } catch (e: Exception) { - throw RuntimeException("Error loading $file", e) - } - } - - return manifests + return jarsToLoad.flatMap { loadJar(it, classLoader) } } private fun loadJar(file: File, cl: URLClassLoader): List { - var classCount = 0 val jar = JarFile(file) - var manifests: List + val manifests = loadPluginManifests(jar) + var classCount = 0 jar.use { - manifests = loadPluginManifests(jar) if (manifests.isEmpty()) { throw RuntimeException("No plugin manifest found in ${file.path}") } - val allowedPaths = manifests.map { it.path.replace(".", "/") } - jar.entries().asIterator().forEach { entry -> - if (entry.isDirectory) return@forEach - if (!entry.name.endsWith(".class")) return@forEach - if (!allowedPaths.any { entry.name.startsWith(it) }) return@forEach + val allowedPaths = manifests.map { manifest -> manifest.path.replace(".", "/") } + + for (entry in it.entries()) { + if (entry.isDirectory || + !entry.name.endsWith(".class") || + allowedPaths.none(entry.name::startsWith)) continue + cl.loadClass(entry.name.dropLast(6).replace("/", ".")) classCount++ } @@ -157,16 +139,10 @@ class PluginManager(val config: PluginsConfig) { } private fun loadPluginManifests(jar: JarFile): List { - val manifests = mutableListOf() - - jar.entries().asIterator().forEach { entry -> - if (entry.isDirectory) return@forEach - if (!entry.name.startsWith("lavalink-plugins/")) return@forEach - if (!entry.name.endsWith(".properties")) return@forEach - - manifests.add(parsePluginManifest(jar.getInputStream(entry))) - } - return manifests + return jar.entries().asSequence() + .filter { !it.isDirectory && it.name.startsWith("lavalink-plugins/") && it.name.endsWith(".properties") } + .map { parsePluginManifest(jar.getInputStream(it)) } + .toList() } private fun parsePluginManifest(stream: InputStream): PluginManifest { @@ -179,4 +155,10 @@ class PluginManager(val config: PluginsConfig) { val version = props.getProperty("version") ?: throw RuntimeException("Manifest is missing 'version'") return PluginManifest(name, path, version) } -} \ No newline at end of file + + private data class PluginJar(val manifest: PluginManifest, val file: File) + private data class Declaration(val group: String, val name: String, val version: String, val repository: String) { + val canonicalJarName = "$name-$version.jar" + val url = "$repository${group.replace(".", "/")}/$name/$version/$name-$version.jar" + } +} From 070990f9db86a5196c4b5a1e4449da66c6618d82 Mon Sep 17 00:00:00 2001 From: topi314 Date: Tue, 6 Feb 2024 21:07:14 +0100 Subject: [PATCH 20/33] update oshi to 6.4.11 --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 861cb22c7..4b30af382 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -76,7 +76,7 @@ fun VersionCatalogBuilder.common() { library("logback", "ch.qos.logback", "logback-classic").version("1.4.7") library("sentry-logback", "io.sentry", "sentry-logback").version("6.22.0") - library("oshi", "com.github.oshi", "oshi-core").version("6.4.8") + library("oshi", "com.github.oshi", "oshi-core").version("6.4.11") } fun VersionCatalogBuilder.other() { From c81107a53f6476e6a5bc9de94200e7954ab2c453 Mon Sep 17 00:00:00 2001 From: topi314 Date: Tue, 6 Feb 2024 21:15:15 +0100 Subject: [PATCH 21/33] update changelog --- CHANGELOG.md | 17 +++++++++++------ docs/changelog/v4.md | 11 ++++++++--- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 769a345d7..d2de06457 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,14 @@ Each release usually includes various fixes and improvements. The most noteworthy of these, as well as any features and breaking changes, are listed here. +## v4.0.2 +* Fixed issue where all plugins get deleted when already present (introduced in [`v4.0.1`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.1)) +* Always include plugin info & user data when serializing (introduced in [`v4.0.1`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.1)) +* Updated oshi to `6.4.11` + ## 4.0.1 -* Updated Lavaplayer to 2.10 -* Updated OSHI to 6.4.8 +* Updated Lavaplayer to `2.1.0` +* Updated oshi to `6.4.8` * Fix/user data missing field exception in protocol * Fix plugin manager not deleting old plugin version * Fix not being able to seek when player is paused @@ -13,7 +18,7 @@ The most noteworthy of these, as well as any features and breaking changes, are ## 4.0.0 * Lavalink now requires Java 17 or higher to run -* **Removal of all websocket messages sent by the client. Everything is now done via [REST](../api/rest.md)** +* **Removal of all websocket messages sent by the client. Everything is now done via [REST](https://lavalink.dev/api/rest.html)** * Remove default 4GB max heap allocation from docker image * Removal of all `/v3` endpoints except `/version`. All other endpoints are now under `/v4` * Reworked track loading result. For more info see [here](https://lavalink.dev/api/rest.md#track-loading-result) @@ -59,17 +64,17 @@ The most noteworthy of these, as well as any features and breaking changes, are ## 4.0.0-beta.1 * New Lavalink now requires Java 17 or higher to run -* **Removal of all websocket messages sent by the client. Everything is now done via [REST](IMPLEMENTATION.md#rest-api)** +* **Removal of all websocket messages sent by the client. Everything is now done via [REST](https://lavalink.dev/api/rest.html)** * Update to [Lavaplayer custom branch](https://github.com/Walkyst/lavaplayer-fork/tree/custom), which includes native support for artwork urls and ISRCs in the track info * Addition of full `Track` objects in following events: `TrackStartEvent`, `TrackEndEvent`, `TrackExceptionEvent`, `TrackStuckEvent` * Resuming a session now requires the `Session-Id` header instead of `Resume-Key` header -* Reworked track loading result. For more info see [here](IMPLEMENTATION.md#track-loading-result) +* Reworked track loading result. For more info see [here](https://lavalink.dev/api/rest.html#track-loading-result) * Update to the [Protocol Module](protocol) to support Kotlin/JS * Removal of all `/v3` endpoints except `/version`. All other endpoints are now under `/v4` > **Warning** > This is a beta release, and as such, may contain bugs. Please report any bugs you find to the [issue tracker](https://github.com/lavalink-devs/Lavalink/issues/new/choose). -> For more info on the changes in this release, see [here](IMPLEMENTATION.md#significant-changes-v370---v400) +> For more info on the changes in this release, see [here](https://lavalink.dev/changelog/index.html#significant-changes) > If you have any question regarding the changes in this release, please ask in the [support server](https://discord.gg/ZW4s47Ppw4) or [GitHub discussions](https://github.com/lavalink-devs/Lavalink/discussions/categories/q-a) Contributors: diff --git a/docs/changelog/v4.md b/docs/changelog/v4.md index ad762f496..b18886c65 100644 --- a/docs/changelog/v4.md +++ b/docs/changelog/v4.md @@ -1,6 +1,11 @@ -## 4.0.1 -* Updated Lavaplayer to 2.10 -* Updated OSHI to 6.4.8 +## v4.0.2 +* Fixed issue where all plugins get deleted when already present (introduced in [`v4.0.1`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.1)) +* Always include plugin info & user data when serializing (introduced in [`v4.0.1`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.1)) +* Updated oshi to `6.4.11` + +## v4.0.1 +* Updated Lavaplayer to `2.1.0` +* Updated oshi to `6.4.8` * Fix/user data missing field exception in protocol * Fix plugin manager not deleting old plugin version * Fix not being able to seek when player is paused From a4a9b4d5796aef377f23885478302fb77e863f92 Mon Sep 17 00:00:00 2001 From: devoxin Date: Tue, 6 Feb 2024 21:28:33 +0000 Subject: [PATCH 22/33] fix: actually registering plugins --- LavalinkServer/src/main/java/lavalink/server/Launcher.kt | 2 +- .../main/java/lavalink/server/bootstrap/PluginManager.kt | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/LavalinkServer/src/main/java/lavalink/server/Launcher.kt b/LavalinkServer/src/main/java/lavalink/server/Launcher.kt index 28186c783..8252b9a47 100644 --- a/LavalinkServer/src/main/java/lavalink/server/Launcher.kt +++ b/LavalinkServer/src/main/java/lavalink/server/Launcher.kt @@ -143,7 +143,7 @@ object Launcher { .properties(properties) .web(WebApplicationType.SERVLET) .bannerMode(Banner.Mode.OFF) - .resourceLoader(DefaultResourceLoader(pluginManager::class.java.classLoader)) + .resourceLoader(DefaultResourceLoader(pluginManager.classLoader)) .listeners( ApplicationListener { event: Any -> when (event) { diff --git a/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt b/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt index e422785a6..3c0ab07a8 100644 --- a/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt +++ b/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt @@ -21,8 +21,11 @@ class PluginManager(val config: PluginsConfig) { final val pluginManifests: MutableList = mutableListOf() + var classLoader = javaClass.classLoader + init { manageDownloads() + pluginManifests.apply { addAll(readClasspathManifests()) addAll(loadJars()) @@ -104,12 +107,12 @@ class PluginManager(val config: PluginsConfig) { ?.takeIf { it.isNotEmpty() } ?: return emptyList() - val classLoader = URLClassLoader.newInstance( + classLoader = URLClassLoader.newInstance( jarsToLoad.map { URL("jar:file:${it.absolutePath}!/") }.toTypedArray(), javaClass.classLoader ) - return jarsToLoad.flatMap { loadJar(it, classLoader) } + return jarsToLoad.flatMap { loadJar(it, classLoader as URLClassLoader) } } private fun loadJar(file: File, cl: URLClassLoader): List { From e33432503b5a7002b336343eec309a6d0ff244a4 Mon Sep 17 00:00:00 2001 From: devoxin Date: Tue, 6 Feb 2024 21:57:33 +0000 Subject: [PATCH 23/33] Match plugins by file name if not by manifest name. --- .../server/bootstrap/PluginManager.kt | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt b/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt index 3c0ab07a8..c3ed4cb73 100644 --- a/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt +++ b/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt @@ -60,7 +60,9 @@ class PluginManager(val config: PluginsConfig) { }.distinctBy { "${it.group}:${it.name}" } for (declaration in declarations) { - val jars = pluginJars.filter { it.manifest.name == declaration.name } + val jars = pluginJars.filter { it.manifest.name == declaration.name }.takeIf { it.isNotEmpty() } + ?: pluginJars.filter { matchName(it, declaration.name) } + var hasCurrentVersion = false for (jar in jars) { @@ -112,10 +114,10 @@ class PluginManager(val config: PluginsConfig) { javaClass.classLoader ) - return jarsToLoad.flatMap { loadJar(it, classLoader as URLClassLoader) } + return jarsToLoad.flatMap { loadJar(it, classLoader) } } - private fun loadJar(file: File, cl: URLClassLoader): List { + private fun loadJar(file: File, cl: ClassLoader): List { val jar = JarFile(file) val manifests = loadPluginManifests(jar) var classCount = 0 @@ -159,6 +161,18 @@ class PluginManager(val config: PluginsConfig) { return PluginManifest(name, path, version) } + private fun matchName(jar: PluginJar, name: String): Boolean { + // removeSuffix removes names ending with "-v", such as -v1.0.0 + // and then the subsequent removeSuffix call removes trailing "-", which + // usually precedes a version number, such as my-plugin-1.0.0. + // We strip these to produce the name of the jar's file. + val jarName = jar.file.nameWithoutExtension.takeWhile { !it.isDigit() } + .removeSuffix("-v") + .removeSuffix("-") + + return name == jarName + } + private data class PluginJar(val manifest: PluginManifest, val file: File) private data class Declaration(val group: String, val name: String, val version: String, val repository: String) { val canonicalJarName = "$name-$version.jar" From c152d0cb0f38875ee1ad3c48194befc86f1c1cbd Mon Sep 17 00:00:00 2001 From: topi314 Date: Tue, 6 Feb 2024 23:12:53 +0100 Subject: [PATCH 24/33] remove not working plugins --- docs/plugins.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/plugins.md b/docs/plugins.md index e285e3ec0..07ff750fd 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -18,7 +18,6 @@ for instructions. | [LavaSrc plugin](https://github.com/topi314/LavaSrc) | Spotify, Apple Music & Deezer(native play) support | | [LavaSearch plugin](https://github.com/topi314/LavaSearch) | Advanced search functionality including playlists, albums, artists, tracks & terms | | [DuncteBot plugin](https://github.com/DuncteBot/skybot-lavalink-plugin) | Additional source managers that are not widely used | -| [Extra Filter plugin](https://github.com/rohank05/lavalink-filter-plugin) | Additional audio filters for lavalink | | [XM plugin](https://github.com/esmBot/lava-xm-plugin) | Support for various [music tracker module](https://en.wikipedia.org/wiki/Module_file) formats | | [Lyrics.kt plugin](https://github.com/DRSchlaubi/lyrics.kt) | Plugin that fetches timestamped lyrics from YouTube | | [Java Timed Lyrics](https://github.com/DuncteBot/java-timed-lyrics) | Timestamped lyrics from YouTube with Genius fallback, supports IP-rotation | From 8c131569c4bfe512575c2abc4890ae48d8c62561 Mon Sep 17 00:00:00 2001 From: devoxin Date: Tue, 6 Feb 2024 22:16:10 +0000 Subject: [PATCH 25/33] add LavaDSPX to plugins --- docs/plugins.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/plugins.md b/docs/plugins.md index 07ff750fd..a2aa13aaf 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -21,5 +21,6 @@ for instructions. | [XM plugin](https://github.com/esmBot/lava-xm-plugin) | Support for various [music tracker module](https://en.wikipedia.org/wiki/Module_file) formats | | [Lyrics.kt plugin](https://github.com/DRSchlaubi/lyrics.kt) | Plugin that fetches timestamped lyrics from YouTube | | [Java Timed Lyrics](https://github.com/DuncteBot/java-timed-lyrics) | Timestamped lyrics from YouTube with Genius fallback, supports IP-rotation | +| [LavaDSPX Audio Filters](https://github.com/Devoxin/LavaDSPX-Plugin) | Additional audio filters for Lavalink | If you want to make your own plugin see [here](api/plugins.md) From 502a4b0bc137c709bde58c9e8a4ec93358bbae47 Mon Sep 17 00:00:00 2001 From: topi314 Date: Tue, 6 Feb 2024 23:27:34 +0100 Subject: [PATCH 26/33] update changelog --- CHANGELOG.md | 5 +++++ docs/changelog/v4.md | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2de06457..8f6277446 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ Each release usually includes various fixes and improvements. The most noteworthy of these, as well as any features and breaking changes, are listed here. +## v4.0.3 +* Fixed plugins not registering (introduced in [`4.0.2`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.2)) +* Fixed some issues where plugins would be redownloaded everytime lavalink started (introduced in [`4.0.1`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.1)) + + ## v4.0.2 * Fixed issue where all plugins get deleted when already present (introduced in [`v4.0.1`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.1)) * Always include plugin info & user data when serializing (introduced in [`v4.0.1`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.1)) diff --git a/docs/changelog/v4.md b/docs/changelog/v4.md index b18886c65..451886fc7 100644 --- a/docs/changelog/v4.md +++ b/docs/changelog/v4.md @@ -1,3 +1,7 @@ +## v4.0.3 +* Fixed plugins not registering (introduced in [`4.0.2`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.2)) +* Fixed some issues where plugins would be redownloaded everytime lavalink started (introduced in [`4.0.1`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.1)) + ## v4.0.2 * Fixed issue where all plugins get deleted when already present (introduced in [`v4.0.1`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.1)) * Always include plugin info & user data when serializing (introduced in [`v4.0.1`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.1)) From ae3deb1ad61ea31f040ddaa4a283a38c298f326f Mon Sep 17 00:00:00 2001 From: Clxud <71564480+cloudwithax@users.noreply.github.com> Date: Wed, 14 Feb 2024 17:51:16 -0500 Subject: [PATCH 27/33] Update clients to include Pomice for v4 support (#1011) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update clients to include Pomice for v4 support Pomice has been updated to add support for v4 officially * Update docs/clients.md Co-authored-by: Toπ --------- Co-authored-by: Toπ --- docs/clients.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/clients.md b/docs/clients.md index aed80496b..b07d85257 100644 --- a/docs/clients.md +++ b/docs/clients.md @@ -12,6 +12,7 @@ description: A list of Lavalink client libraries. | [lavalink.py](https://github.com/devoxin/lavalink.py) | Python | **Any** | | | [Mafic](https://github.com/ooliver1/mafic) | Python | discord.py **V2**/nextcord/disnake/py-cord | | | [Wavelink](https://github.com/PythonistaGuild/Wavelink) | Python | discord.py **V2** | | +| [Pomice](https://github.com/cloudwithax/pomice) | Python | discord.py **V2** | | | [Moonlink.js](https://github.com/1Lucas1apk/moonlink.js) | Node.js | **Any** | | | [Magmastream](https://github.com/Blackfort-Hosting/magmastream) | Node.js | **Any** | | | [Lavacord](https://github.com/lavacord/Lavacord) | Node.js | **Any** | | From c70ee6a5084a2cd64b140fd953351d953cc776a8 Mon Sep 17 00:00:00 2001 From: Platy Date: Sat, 2 Mar 2024 23:34:41 +1100 Subject: [PATCH 28/33] Adding ongaku to the client.md list. (#1017) * Added Ongaku client --- docs/clients.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/clients.md b/docs/clients.md index b07d85257..2d025560e 100644 --- a/docs/clients.md +++ b/docs/clients.md @@ -13,6 +13,7 @@ description: A list of Lavalink client libraries. | [Mafic](https://github.com/ooliver1/mafic) | Python | discord.py **V2**/nextcord/disnake/py-cord | | | [Wavelink](https://github.com/PythonistaGuild/Wavelink) | Python | discord.py **V2** | | | [Pomice](https://github.com/cloudwithax/pomice) | Python | discord.py **V2** | | +| [hikari-ongaku](https://github.com/MPlatypus/hikari-ongaku) | Python | Hikari | `asyncio`-based | | [Moonlink.js](https://github.com/1Lucas1apk/moonlink.js) | Node.js | **Any** | | | [Magmastream](https://github.com/Blackfort-Hosting/magmastream) | Node.js | **Any** | | | [Lavacord](https://github.com/lavacord/Lavacord) | Node.js | **Any** | | From 31f848ed2b41d77138a01643baf23a6b7dfb26c2 Mon Sep 17 00:00:00 2001 From: Angelo Breuer <46497296+angelobreuer@users.noreply.github.com> Date: Sun, 3 Mar 2024 01:01:27 +0100 Subject: [PATCH 29/33] Update supported clients for Lavalink4NET (#1018) --- docs/clients.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/clients.md b/docs/clients.md index 2d025560e..d7968edf1 100644 --- a/docs/clients.md +++ b/docs/clients.md @@ -22,7 +22,7 @@ description: A list of Lavalink client libraries. | [FastLink](https://github.com/PerformanC/FastLink) | Node.js | **Any** | | | [Riffy](https://github.com/riffy-team/riffy) | Node.js | **Any** | | | [DisCatSharp](https://github.com/Aiko-IT-Systems/DisCatSharp) | .NET | DisCatSharp | v10.4.2+ | -| [Lavalink4NET](https://github.com/angelobreuer/Lavalink4NET) | .NET | Discord.Net/DSharpPlus/Remora | v4+ | +| [Lavalink4NET](https://github.com/angelobreuer/Lavalink4NET) | .NET | Discord.Net/DSharpPlus/Remora/NetCord | v4+ | | [Nomia](https://github.com/DHCPCD9/Nomia) | .NET | DSharpPlus | | | [Coglink](https://github.com/PerformanC/Coglink) | C | Concord | | | [lavalink-rs](https://gitlab.com/vicky5124/lavalink-rs) | Rust, Python | **Any** | `tokio`-based, `asyncio`-based | From f77c8f5c3eb52bd9452be5b5b4002e767854e25b Mon Sep 17 00:00:00 2001 From: topi314 Date: Wed, 6 Mar 2024 13:35:11 +0100 Subject: [PATCH 30/33] fix dead links in docs --- docs/api/index.md | 4 ++-- docs/api/rest.md | 8 +++---- docs/changelog/index.md | 50 ++++++++++++++++++++--------------------- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/docs/api/index.md b/docs/api/index.md index 49a142ca3..efb4a5caf 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -22,7 +22,7 @@ What happens after your client disconnects is dependent on whether the session h * If resuming is disabled all voice connections are closed immediately. * If resuming is enabled all music will continue playing. You will then be able to resume your session, allowing you to control the players again. -To enable resuming, you must call the [Update Session](#update-session) endpoint with the `resuming` and `timeout`. +To enable resuming, you must call the [Update Session](../api/rest.md#update-session) endpoint with the `resuming` and `timeout`. To resume a session, specify the session id in your WebSocket handshake request headers: @@ -36,7 +36,7 @@ You can tell if your session was resumed by looking at the handshake response he Session-Resumed: true ``` -In case your websocket library doesn't support reading headers you can listen for the [ready op](#ready-op) and check the `resumed` field. +In case your websocket library doesn't support reading headers you can listen for the [ready op](../api/websocket.md#ready-op) and check the `resumed` field. When a session is paused, any events that would normally have been sent are queued up. When the session is resumed, this queue is then emptied and the events are replayed. diff --git a/docs/api/rest.md b/docs/api/rest.md index c3b5f19ff..5810423c8 100644 --- a/docs/api/rest.md +++ b/docs/api/rest.md @@ -53,10 +53,10 @@ When Lavalink encounters an error, it will respond with a JSON object containing #### Track -| Field | Type | Description | -|------------|----------------------------------|-------------------------------------------------------------------------------| -| encoded | string | The base64 encoded track data | -| info | [Track Info](#track-info) object | Info about the track | +| Field | Type | Description | +|------------|----------------------------------|---------------------------------------------------------------------------------| +| encoded | string | The base64 encoded track data | +| info | [Track Info](#track-info) object | Info about the track | | pluginInfo | object | Additional track info provided by plugins | | userData | object | Additional track data provided via the [Update Player](#update-player) endpoint | diff --git a/docs/changelog/index.md b/docs/changelog/index.md index 5c43ab435..ece60ffc8 100644 --- a/docs/changelog/index.md +++ b/docs/changelog/index.md @@ -17,24 +17,24 @@ The most noteworthy of these, as well as any features and breaking changes, are * `v4` uses the `sessionId` instead of the `resumeKey` for resuming. * `v4` now returns the tracks `artworkUrl` and `isrc` if the source supports it. * removal of deprecated json fields like `track`. -* addition of `artworkUrl` and `isrc` fields to the [Track Info](#track-info) object. -* addition of the full [Track](#track) object in [TrackStartEvent](#trackstartevent), [TrackEndEvent](#trackendevent), [TrackExceptionEvent](#trackexceptionevent) and [TrackStuckEvent](#trackstuckevent). -* updated capitalization of [Track End Reason](#track-end-reason) and [Severity](#severity) -* reworked [Load Result](#track-loading-result) object +* addition of `artworkUrl` and `isrc` fields to the [Track Info](../api/rest.md#track-info) object. +* addition of the full [Track](../api/rest.md#track) object in [TrackStartEvent](../api/websocket.md#trackstartevent), [TrackEndEvent](../api/websocket.md#trackendevent), [TrackExceptionEvent](../api/websocket.md#trackexceptionevent) and [TrackStuckEvent](../api/websocket.md#trackstuckevent). +* updated capitalization of [Track End Reason](../api/websocket.md#track-end-reason) and [Severity](../api/websocket.md#severity) +* reworked [Load Result](../api/rest.md#track-loading-result) object * allow setting user data on tracks in the REST API. For more info see [here](https://lavalink.dev/api/rest.html#update-player-track) All websocket ops are removed as of `v4.0.0` and replaced with the following endpoints and json fields: -* `play` -> [Update Player Endpoint](#update-player) `track`->`encoded` or `track`->`identifier` field -* `stop` -> [Update Player Endpoint](#update-player) `encodedTrack` field with `null` -* `pause` -> [Update Player Endpoint](#update-player) `pause` field -* `seek` -> [Update Player Endpoint](#update-player) `position` field -* `volume` -> [Update Player Endpoint](#update-player) `volume` field -* `filters` -> [Update Player Endpoint](#update-player) `filters` field -* `destroy` -> [Destroy Player Endpoint](#destroy-player) -* `voiceUpdate` -> [Update Player Endpoint](#update-player) `voice` field -* `configureResuming` -> [Update Session Endpoint](#update-session) +* `play` -> [Update Player Endpoint](../api/rest.md#update-player) `track`->`encoded` or `track`->`identifier` field +* `stop` -> [Update Player Endpoint](../api/rest.md#update-player) `encodedTrack` field with `null` +* `pause` -> [Update Player Endpoint](../api/rest.md#update-player) `pause` field +* `seek` -> [Update Player Endpoint](../api/rest.md#update-player) `position` field +* `volume` -> [Update Player Endpoint](../api/rest.md#update-player) `volume` field +* `filters` -> [Update Player Endpoint](../api/rest.md#update-player) `filters` field +* `destroy` -> [Destroy Player Endpoint](../api/rest.md#destroy-player) +* `voiceUpdate` -> [Update Player Endpoint](../api/rest.md#update-player) `voice` field +* `configureResuming` -> [Update Session Endpoint](../api/rest.md#update-session)
@@ -46,8 +46,8 @@ All websocket ops are removed as of `v4.0.0` and replaced with the following end * WebSocket handshakes should be done with `/v3/websocket`. Handshakes on `/` are now deprecated. * Deprecation of all client-to-server messages (play, stop, pause, seek, volume, filters, destroy, voiceUpdate & configureResuming). * Addition of REST endpoints intended to replace client requests. -* Addition of new WebSocket dispatch [Ready OP](#ready-op) to get `sessionId` and `resume` status. -* Addition of new [Session](#update-session)/[Player](#get-player) REST API. +* Addition of new WebSocket dispatch [Ready OP](../api/websocket.md#ready-op) to get `sessionId` and `resume` status. +* Addition of new [Session](../api/rest.md#update-session)/[Player](../api/rest.md#get-player) REST API. * Addition of `/v3/info`, replaces `/plugins`. * Deprecation of `Track.track` in existing endpoints. Use `Track.encoded` instead. * Deprecation of `TrackXEvent.track` in WebSocket dispatches. Use `TrackXEvent.encodedTrack` instead. @@ -55,15 +55,15 @@ All websocket ops are removed as of `v4.0.0` and replaced with the following end All websocket ops are deprecated as of `v3.7.0` and replaced with the following endpoints and json fields: -* `play` -> [Update Player Endpoint](#update-player) `track` or `identifier` field -* `stop` -> [Update Player Endpoint](#update-player) `track` field with `null` -* `pause` -> [Update Player Endpoint](#update-player) `pause` field -* `seek` -> [Update Player Endpoint](#update-player) `position` field -* `volume` -> [Update Player Endpoint](#update-player) `volume` field -* `filters` -> [Update Player Endpoint](#update-player) `filters` field -* `destroy` -> [Destroy Player Endpoint](#destroy-player) -* `voiceUpdate` -> [Update Player Endpoint](#update-player) `voice` field -* `configureResuming` -> [Update Session Endpoint](#update-session) +* `play` -> [Update Player Endpoint](../api/rest.md#update-player) `track` or `identifier` field +* `stop` -> [Update Player Endpoint](../api/rest.md#update-player) `track` field with `null` +* `pause` -> [Update Player Endpoint](../api/rest.md#update-player) `pause` field +* `seek` -> [Update Player Endpoint](../api/rest.md#update-player) `position` field +* `volume` -> [Update Player Endpoint](../api/rest.md#update-player) `volume` field +* `filters` -> [Update Player Endpoint](../api/rest.md#update-player) `filters` field +* `destroy` -> [Destroy Player Endpoint](../api/rest.md#destroy-player) +* `voiceUpdate` -> [Update Player Endpoint](../api/rest.md#update-player) `voice` field +* `configureResuming` -> [Update Session Endpoint](../api/rest.md#update-session)
@@ -72,7 +72,7 @@ All websocket ops are deprecated as of `v3.7.0` and replaced with the following * Added filters * The `error` string on the `TrackExceptionEvent` has been deprecated and replaced by - the [Exception](#exception-object) object following the same structure as the `LOAD_FAILED` error on [`/loadtracks`](#track-loading). + the [Exception](../api/websocket.md#exception-object) object following the same structure as the `LOAD_FAILED` error on [`/loadtracks`](../api/rest.md#track-loading). * Added the `connected` boolean to player updates. * Added source name to REST api track objects * Clients are now requested to make their name known during handshake From 899e37088c1d275e3786bad3878e28bcc95805fb Mon Sep 17 00:00:00 2001 From: topi314 Date: Sun, 10 Mar 2024 18:06:28 +0100 Subject: [PATCH 31/33] update lavaplayer to v2.1.1 --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 4b30af382..1e6dff63c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -36,7 +36,7 @@ fun VersionCatalogBuilder.spring() { } fun VersionCatalogBuilder.voice() { - version("lavaplayer", "2.1.0") + version("lavaplayer", "2.1.1") library("lavaplayer", "dev.arbjerg", "lavaplayer").versionRef("lavaplayer") library("lavaplayer-ip-rotator", "dev.arbjerg", "lavaplayer-ext-youtube-rotator").versionRef("lavaplayer") From 8888cefc053195414c549272ded9670ce6a1cb2a Mon Sep 17 00:00:00 2001 From: topi314 Date: Sun, 10 Mar 2024 18:14:26 +0100 Subject: [PATCH 32/33] update changelogs update v3 changelog fix changelog update changelog --- CHANGELOG.md | 7 +++++++ docs/changelog/v3.md | 5 +++++ docs/changelog/v4.md | 7 +++++++ 3 files changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2de06457..bda14c865 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,13 @@ Each release usually includes various fixes and improvements. The most noteworthy of these, as well as any features and breaking changes, are listed here. +## v4.0.4 +* Update Lavaplayer to `2.1.1` + +## v4.0.3 +* Fixed plugins not registering (introduced in [`4.0.2`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.2)) +* Fixed some issues where plugins would be redownloaded everytime lavalink started (introduced in [`4.0.1`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.1)) + ## v4.0.2 * Fixed issue where all plugins get deleted when already present (introduced in [`v4.0.1`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.1)) * Always include plugin info & user data when serializing (introduced in [`v4.0.1`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.1)) diff --git a/docs/changelog/v3.md b/docs/changelog/v3.md index 33e635fa5..1db493ed3 100644 --- a/docs/changelog/v3.md +++ b/docs/changelog/v3.md @@ -1,3 +1,8 @@ +## v3.7.11 +* Fixed not being able to seek when player is paused +* Update Oshi to `6.4.3` +* Update Lavaplayer to `1.5.3` + ## v3.7.10 * Update lavaplayer to [`1.5.2`](https://github.com/lavalink-devs/lavaplayer/releases/tag/1.5.2) - Fixed NPE on missing author in playlist tracks in YouTube diff --git a/docs/changelog/v4.md b/docs/changelog/v4.md index b18886c65..0834ebafc 100644 --- a/docs/changelog/v4.md +++ b/docs/changelog/v4.md @@ -1,3 +1,10 @@ +## v4.0.4 +* Update Lavaplayer to `2.1.1` + +## v4.0.3 +* Fixed plugins not registering (introduced in [`4.0.2`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.2)) +* Fixed some issues where plugins would be redownloaded everytime lavalink started (introduced in [`4.0.1`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.1)) + ## v4.0.2 * Fixed issue where all plugins get deleted when already present (introduced in [`v4.0.1`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.1)) * Always include plugin info & user data when serializing (introduced in [`v4.0.1`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.1)) From bb5e1264b8a0bda6dda7d39aff8937dfaef8d834 Mon Sep 17 00:00:00 2001 From: topi314 Date: Sun, 10 Mar 2024 18:29:08 +0100 Subject: [PATCH 33/33] update changelog --- docs/changelog/v3.md | 8 ++++---- docs/changelog/v4.md | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/changelog/v3.md b/docs/changelog/v3.md index 1db493ed3..9c1c3c351 100644 --- a/docs/changelog/v3.md +++ b/docs/changelog/v3.md @@ -1,13 +1,13 @@ ## v3.7.11 * Fixed not being able to seek when player is paused -* Update Oshi to `6.4.3` -* Update Lavaplayer to `1.5.3` +* Updated Oshi to `6.4.3` +* Updated Lavaplayer to `1.5.3` ## v3.7.10 -* Update lavaplayer to [`1.5.2`](https://github.com/lavalink-devs/lavaplayer/releases/tag/1.5.2) - Fixed NPE on missing author in playlist tracks in YouTube +* Updated lavaplayer to [`1.5.2`](https://github.com/lavalink-devs/lavaplayer/releases/tag/1.5.2) - Fixed NPE on missing author in playlist tracks in YouTube ## v3.7.9 -* Update lavaplayer to [`1.5.1`](https://github.com/lavalink-devs/lavaplayer/releases/tag/1.5.1) - Fixed YouTube access token errors +* Updated lavaplayer to [`1.5.1`](https://github.com/lavalink-devs/lavaplayer/releases/tag/1.5.1) - Fixed YouTube access token errors * Fixed websocket crash when seeking and nothing is playing * Fixed error when seeking and player is not playing anything diff --git a/docs/changelog/v4.md b/docs/changelog/v4.md index 0834ebafc..d9b9a2d82 100644 --- a/docs/changelog/v4.md +++ b/docs/changelog/v4.md @@ -1,5 +1,5 @@ ## v4.0.4 -* Update Lavaplayer to `2.1.1` +* Updated Lavaplayer to `2.1.1` ## v4.0.3 * Fixed plugins not registering (introduced in [`4.0.2`](https://github.com/lavalink-devs/Lavalink/releases/tag/4.0.2))