Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(lavalink)!: Lavalink refactor to v4 API #2322

Open
wants to merge 70 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
9ad9051
feat(lavalink)!: Adding updated structs and enums for v4 of lavalink
LinuxDevon Mar 10, 2024
d309466
feat(lavalink)!: Updating model structs. Removed old OP struct not in…
LinuxDevon Mar 11, 2024
b099660
Remove commented out code in example lavalink bot
LinuxDevon Mar 11, 2024
338cfa4
fix(lavalink): Fixed the play, stop, seek, pause, volume, etc stucts …
LinuxDevon Mar 11, 2024
a7866f1
This is the first stab at figuring out the session id. I fixed the re…
LinuxDevon Mar 11, 2024
d52bf32
fix(lavalink): Removing the session implementation and renamed the se…
LinuxDevon Mar 11, 2024
ee4f523
fix(lavalink): Fixed the lavalink v4 playerupdatestat ping field.
LinuxDevon Mar 11, 2024
0534c02
feat(lavalink): Now can read the lavalink session in the connection t…
LinuxDevon Mar 11, 2024
b92b2f3
fix(lavalink): Fixed the player track model to remove user_data since…
LinuxDevon Mar 11, 2024
98e76cc
fix(lavalink): Working event op code now for trackStartEvent
LinuxDevon Mar 11, 2024
5fc8850
fix(lavalink): Adding todos to the guild ids for the outgoing events …
LinuxDevon Mar 11, 2024
cbf10ad
fix(lavalink): Adding the guild_id as no serialize for equalizer
LinuxDevon Mar 12, 2024
1a5b5dd
test(lavalink): Adding a serialize test for string comparison of the …
LinuxDevon Mar 12, 2024
e7435e1
refactor(lavalink): Cleaned up tests to have a function do the string…
LinuxDevon Mar 12, 2024
1cc0047
tests(lavalink): Adding a test for track_start_event
LinuxDevon Mar 12, 2024
c26de22
tests(lavalink): The play struct and command is tested against a good…
LinuxDevon Mar 12, 2024
e33c8ce
feat(lavalink): Working stop now. Needed to put no replace in to fals…
LinuxDevon Mar 12, 2024
ec43697
feat(lavalink): Working pause function in new v4
LinuxDevon Mar 12, 2024
4d87d91
feat(lavalink): Working seek and volume now.
LinuxDevon Mar 12, 2024
09e57fa
feat(lavalink): Stop now works in v4. Refactored the node some to cha…
LinuxDevon Mar 12, 2024
b48ec2b
test(lavalink): Adding stats tests for the stats structures
LinuxDevon Mar 12, 2024
a498dd9
refactor(lavalink): fixed the test names for the incoming to be only …
LinuxDevon Mar 12, 2024
2c5e10e
feat(lavalink): Adding in support and tests for equalizer. Added a co…
LinuxDevon Mar 12, 2024
c3f79de
refactor(lavalink): moved the modules from model.rs into their own fi…
LinuxDevon Mar 12, 2024
9b75e43
doc(lavalink): Updating the README with the changes of v4 and what di…
LinuxDevon Mar 12, 2024
f532c43
fix(lavalink): Fixed typo in WebSocketClosedEvent with a lowercase `s…
LinuxDevon Mar 12, 2024
17d4a84
fix(lavalink): Track events now decoded correctly and the WebSocketCl…
LinuxDevon Mar 14, 2024
fad0435
fix(lavalink): spelling errors
LinuxDevon Mar 14, 2024
a82950a
fix(lavalink): ran formater on the code
LinuxDevon Mar 14, 2024
7ae3b51
fix(lavalink): clippy errors are now resolved
LinuxDevon Mar 14, 2024
bab628c
fix(lavalink): fixing the tests and minimal versions
LinuxDevon Mar 14, 2024
dfd42ce
fix(lavalink): Fixing formatting and clippy warnings for lavalink tests
LinuxDevon Mar 14, 2024
38f2aaa
fix(lavalink): Fixing the no default config of http. If that wasn't e…
LinuxDevon Mar 14, 2024
3147e92
refactor(lavalink): Move the guild id and no replace with helper func…
LinuxDevon Mar 25, 2024
b08ccbd
refactor(lavalink): Use Uri builder for the outgoing events instead
LinuxDevon Mar 25, 2024
5da3c95
refactor: Format code
LinuxDevon Mar 25, 2024
b0277aa
feat(lavalink): Added OutgoingEventHasNoSession for when we try to co…
LinuxDevon Mar 25, 2024
422cb43
doc(lavalink): Adding documentation to the new helper functions for o…
LinuxDevon Mar 25, 2024
a37e113
refactor(lavalink): Adding debug tracing, spelling fix, Replacing the…
LinuxDevon Mar 25, 2024
25c60b6
refactor(lavalink): format and clippy warnings and error cleanup
LinuxDevon Mar 25, 2024
7ba6c16
fix(lavalink): Session was being taken causing broken outgoing.
LinuxDevon Mar 25, 2024
8f50b4a
feat(lavalink): Updating the todo's for the examples in the basic bot
LinuxDevon Mar 25, 2024
dd66b21
refactor(lavalink): Alphabetized the structs and enums in incoming
LinuxDevon Mar 25, 2024
4964939
refactor(lavalink): alphabetize enums and structs for http and model
LinuxDevon Mar 26, 2024
588b4d2
fix(lavalink): Remove the unnecessary rename for the serde on frame_s…
LinuxDevon Mar 26, 2024
2fa60e2
feat(lavalink): Adding a feature flag to enable http2 support for lav…
LinuxDevon Mar 27, 2024
e027013
refactor(lavalink): Adding documentation to README about flag and ren…
LinuxDevon Mar 27, 2024
89d472d
refactor(lavalink): Use the legacy build for client on hyper and stor…
LinuxDevon Mar 27, 2024
2e78099
fix: Spelling and formatting corrected
LinuxDevon Mar 27, 2024
9477c59
fix: Tests now pass based on new struct order
LinuxDevon Mar 27, 2024
22b6ae9
fix: hyper_utils missing feature flags
LinuxDevon Mar 27, 2024
7095e46
refactor(lavalink): Adding suggested changes based on feedback
LinuxDevon Apr 6, 2024
cd4906c
refactor(lavalink): Adding new error for the failed to request over h…
LinuxDevon Apr 6, 2024
ddbd6f4
fix(lavalink): Removed the optional dependencies after removing the f…
LinuxDevon Apr 6, 2024
f8d66ac
Use `self` in getters
vilgotf Jun 16, 2024
99a00b7
fmt imports
vilgotf Jun 16, 2024
885c4d8
Remove node session_id lock
vilgotf Jun 16, 2024
a999a13
Conditionally enable HTTP/2
vilgotf Jun 16, 2024
1159372
Make client-name const
vilgotf Jun 16, 2024
a4c7af6
Avoid leaking authorization
vilgotf Jun 16, 2024
2510e16
Remove overly verbose tracing events
vilgotf Jun 16, 2024
d12aed8
Improve module documentation
vilgotf Jun 16, 2024
199190d
Add no default features to deps
vilgotf Jun 17, 2024
3038739
Update some README documentation
vilgotf Jun 17, 2024
28c720f
Clippy suggestions
vilgotf Jun 17, 2024
9de5656
feat: Adding support for Identifier to the UpdatePlayerTrack struct
LinuxDevon Jul 11, 2024
61b8cd5
refactor: Updating the README for lavalink. Moved the comments to the…
LinuxDevon Jul 11, 2024
fd521d9
fix: Consistency in the capitalization of tracing statements
LinuxDevon Jul 11, 2024
571355e
fix: Setting the correct websocket address if TLS is enabled
LinuxDevon Jul 25, 2024
9d7ad7b
Revert "fix: Setting the correct websocket address if TLS is enabled"
LinuxDevon Jul 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 71 additions & 2 deletions examples/lavalink-basic-bot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ use twilight_gateway::{
Event, EventTypeFlags, Intents, MessageSender, Shard, ShardId, StreamExt as _,
};
use twilight_http::Client as HttpClient;
use twilight_lavalink::{
http::LoadResultData::{Playlist, Search, Track},
model::{Equalizer, EqualizerBand},
};
use twilight_lavalink::{
http::LoadedTracks,
model::{Destroy, Pause, Play, Seek, Stop, Volume},
Expand Down Expand Up @@ -53,6 +57,7 @@ async fn main() -> anyhow::Result<()> {
let http = HttpClient::new(token.clone());
let user_id = http.current_user().await?.model().await?.id;

// The client is [`Lavalink`](crate::client::Lavalink) that forwards the required events from Discord.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's nice that you are trying to document what is going on here, but this is not a doc comment and won't get rendered anywhere. I'd try and rephrase it as a comment rather than documentation

let lavalink = Lavalink::new(user_id, shard_count);
lavalink.add(lavalink_host, lavalink_auth).await?;

Expand Down Expand Up @@ -81,6 +86,10 @@ async fn main() -> anyhow::Result<()> {
};

state.standby.process(&event);

// We read the [Voice State and Voice Server Updates](https://discord.com/developers/docs/topics/gateway-events#voice) from discord to format the data to send to a Lavalink `VoiceUpdate` Event.
// There is a lower level [node](crate::node) that processes this for you. It isn't recommended to use this but rather the lavalink struct with the players. If you don't find functionality please open up and issue to expose what you need.
// See the command functions for where we use the players.
Comment on lines +90 to +92
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

state.lavalink.process(&event).await?;

if let Event::MessageCreate(msg) = event {
Expand All @@ -96,6 +105,7 @@ async fn main() -> anyhow::Result<()> {
Some("!seek") => spawn(seek(msg.0, Arc::clone(&state))),
Some("!stop") => spawn(stop(msg.0, Arc::clone(&state))),
Some("!volume") => spawn(volume(msg.0, Arc::clone(&state))),
Some("!equalize") => spawn(equalize(msg.0, Arc::clone(&state))),
_ => continue,
}
}
Expand Down Expand Up @@ -194,13 +204,21 @@ async fn play(msg: Message, state: State) -> anyhow::Result<()> {

let loaded = serde_json::from_slice::<LoadedTracks>(&response_bytes)?;

if let Some(track) = loaded.tracks.first() {
player.send(Play::from((guild_id, &track.track)))?;
let track = match loaded.data {
Track(track) => Some(track),
Playlist(top_track) => top_track.tracks.first().cloned(),
Search(result) => result.first().cloned(),
_ => None,
};

if let Some(track) = track {
player.send(Play::from((guild_id, &track.encoded)))?;

let content = format!(
"Playing **{:?}** by **{:?}**",
track.info.title, track.info.author
);

state
.http
.create_message(msg.channel_id)
Expand Down Expand Up @@ -274,6 +292,57 @@ async fn seek(msg: Message, state: State) -> anyhow::Result<()> {
Ok(())
}

async fn equalize(msg: Message, state: State) -> anyhow::Result<()> {
tracing::debug!(
"equalize command in channel {} by {}",
msg.channel_id,
msg.author.name
);
state
.http
.create_message(msg.channel_id)
.content("What band do you want to equalize (0-14)?")
.await?;

let author_id = msg.author.id;
let band_msg = state
.standby
.wait_for_message(msg.channel_id, move |new_msg: &MessageCreate| {
new_msg.author.id == author_id
})
.await?;
let guild_id = msg.guild_id.unwrap();
let band = band_msg.content.parse::<i64>()?;

state
.http
.create_message(msg.channel_id)
.content("What gain do you want to equalize (-0.25 to 1.0)?")
.await?;

let gain_msg = state
.standby
.wait_for_message(msg.channel_id, move |new_msg: &MessageCreate| {
new_msg.author.id == author_id
})
.await?;
let gain = gain_msg.content.parse::<f64>()?;

let player = state.lavalink.player(guild_id).await.unwrap();
player.send(Equalizer::from((
guild_id,
vec![EqualizerBand::new(band, gain)],
)))?;

state
.http
.create_message(msg.channel_id)
.content(&format!("Changed gain level to {gain} on band {band}."))
.await?;

Ok(())
}

async fn stop(msg: Message, state: State) -> anyhow::Result<()> {
tracing::debug!(
"stop command in channel {} by {}",
Expand Down
11 changes: 6 additions & 5 deletions twilight-lavalink/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@ version = "0.16.0-rc.1"
dashmap = { default-features = false, version = "5.3" }
futures-util = { default-features = false, features = ["bilock", "sink", "std", "unstable"], version = "0.3" }
http = { default-features = false, version = "1" }
hyper = { default-features = false, features = ["client", "http1"], version = "1" }
hyper-util = { default-features = false, features = ["client-legacy", "client", "http1", "tokio"], version = "0.1" }
http-body-util = "0.1"
serde = { default-features = false, features = ["derive", "std"], version = "1" }
serde_json = { default-features = false, features = ["std"], version = "1" }
tokio = { default-features = false, features = ["macros", "net", "rt", "sync", "time"], version = "1.0" }
tokio-websockets = { default-features = false, features = ["client", "fastrand", "sha1_smol", "simd"], version = "0.7" }
tracing = { default-features = false, features = ["std", "attributes"], version = "0.1" }
twilight-model = { default-features = false, path = "../twilight-model", version = "0.16.0-rc.1" }

# Optional dependencies.
percent-encoding = { default-features = false, optional = true, version = "2" }
percent-encoding = { default-features = false, version = "2" }

[dev-dependencies]
anyhow = { default-features = false, features = ["std"], version = "1" }
Expand All @@ -37,8 +38,8 @@ twilight-gateway = { default-features = false, features = ["rustls-native-roots"
twilight-http = { default-features = false, features = ["rustls-native-roots"], path = "../twilight-http", version = "0.16.0-rc.1" }

[features]
default = ["http-support", "rustls-native-roots"]
http-support = ["dep:percent-encoding"]
default = ["http2", "rustls-native-roots"]
http2 = ["hyper/http2", "hyper-util/http2"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HTTP2 as a separate feature makes little sense because it is pointless without prior knowledge, which I assume is virtually never the case. I'd add this implicitly to the TLS features.

native-tls = ["tokio-websockets/native-tls", "tokio-websockets/openssl"]
rustls-native-roots = ["tokio-websockets/ring", "tokio-websockets/rustls-native-roots"]
rustls-webpki-roots = ["tokio-websockets/ring", "tokio-websockets/rustls-webpki-roots"]
Expand Down
15 changes: 12 additions & 3 deletions twilight-lavalink/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,19 @@ handle sending voice channel updates to Lavalink by processing events via
the [client's `process` method][`Lavalink::process`], which you must call
with every Voice State Update and Voice Server Update you receive.

Currently some [Filters](crate::model::outgoing::Filters) are not yet supported.
Some endpoints such as [Lavalink Info] and [Update Session] have also not yet
been implemented. Please reach out and open an issue for any missing feature you
would like to use. The Lavalink V4 port did not add support for any new features
not previously found in V3.
Comment on lines +16 to +20
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this is supposed to go inside the changelog, not the README


## Features

### `http-support`
### `http2`

The `http-support` feature adds support for the `http` module to return
request types from the [`http`] crate. This is enabled by default.
The `http2` feature enables support for communicating with the Lavalink server
over HTTP/2. You will also need to enable http2 support in your Lavalink server
configuration as it is disabled by default.

### TLS

Expand Down Expand Up @@ -104,6 +111,8 @@ There is also an example of a basic bot located in the [root of the
`twilight` repository][github examples link].

[Lavalink]: https://github.com/freyacodes/Lavalink
[Lavalink Info]: https://lavalink.dev/api/rest.html#get-lavalink-version
[Update Session]: https://lavalink.dev/api/rest#update-session
[`http`]: https://crates.io/crates/http
[`rustls`]: https://crates.io/crates/rustls
[`rustls-native-certs`]: https://crates.io/crates/rustls-native-certs
Expand Down
12 changes: 6 additions & 6 deletions twilight-lavalink/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ pub struct Lavalink {
shard_count: u32,
user_id: Id<UserMarker>,
server_updates: DashMap<Id<GuildMarker>, VoiceServerUpdate>,
sessions: DashMap<Id<GuildMarker>, Box<str>>,
discord_sessions: DashMap<Id<GuildMarker>, Box<str>>,
}

impl Lavalink {
Expand Down Expand Up @@ -145,7 +145,7 @@ impl Lavalink {
shard_count,
user_id,
server_updates: DashMap::new(),
sessions: DashMap::new(),
discord_sessions: DashMap::new(),
}
}

Expand Down Expand Up @@ -199,10 +199,10 @@ impl Lavalink {
}

if e.channel_id.is_none() {
self.sessions.remove(&guild_id);
self.discord_sessions.remove(&guild_id);
self.server_updates.remove(&guild_id);
} else {
self.sessions
self.discord_sessions
.insert(guild_id, e.session_id.clone().into_boxed_str());
}
guild_id
Expand All @@ -218,7 +218,7 @@ impl Lavalink {

let update = {
let server = self.server_updates.get(&guild_id);
let session = self.sessions.get(&guild_id);
let session = self.discord_sessions.get(&guild_id);
match (server, session) {
(Some(server), Some(session)) => {
let server = server.value();
Expand Down Expand Up @@ -386,7 +386,7 @@ impl Lavalink {

self.server_updates
.retain(|k, _| (k.get() >> 22) % shard_count != u64::from(shard_id));
self.sessions
self.discord_sessions
.retain(|k, _| (k.get() >> 22) % shard_count != u64::from(shard_id));
}
}
Expand Down
Loading
Loading