Skip to content

Commit

Permalink
feat(lavalink): Implemented support for lavalink v4.
Browse files Browse the repository at this point in the history
  • Loading branch information
DHCPCD9 committed Dec 28, 2023
1 parent 597d15d commit bda6e12
Show file tree
Hide file tree
Showing 10 changed files with 226 additions and 48 deletions.
34 changes: 31 additions & 3 deletions Nomia.Test/Commands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public async Task Ping(CommandContext ctx)
[Command("join")]
public async Task Join(CommandContext ctx)
{
await ctx.RespondAsync("Connecting...");
var voiceState = ctx.Member?.VoiceState;
if (voiceState == null)
{
Expand Down Expand Up @@ -109,17 +110,44 @@ public async Task Play(CommandContext ctx, [RemainingText] string query)
try
{
var player = await node.ConnectAsync(voiceChannel);
var tracks = await node.LoadTrackAsync(query);
var track = tracks.Tracks.FirstOrDefault();
var result = await node.LoadTrackAsync(query, LavalinkSearchType.Raw);

if (track is null)
if (result is LavalinkEmptyLoadType)
{
await ctx.RespondAsync("No tracks found.");
return;
}


LavalinkTrack track = null;
if (result is LavalinkTrackLoadedType loadedTrack)
{
track = loadedTrack.Data;
}

if (result is LavalinkSearchLoadedType loadedSearchResult)
{
await ctx.RespondAsync($"Found {loadedSearchResult.Tracks.Count} tracks.");
track = loadedSearchResult.Tracks.First();
}


if (result is LavalinkPlaylistLoadedType loadedPlaylist)
{
await ctx.RespondAsync($"Loaded playlist {loadedPlaylist.Data.Info.Name}");
track = loadedPlaylist.Data.Tracks.First();
}

if (track is null)
{
await ctx.RespondAsync("Looks like track has been loaded, but wasn't parsed");
return;
}

await player.PlayAsync(track);

await ctx.RespondAsync($"Playing {track.Info}");

}
catch (Exception e)
{
Expand Down
2 changes: 1 addition & 1 deletion Nomia.Test/Nomia.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
Expand Down
4 changes: 2 additions & 2 deletions Nomia.Websocket/Nomia.Websocket.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RootNamespace>Nomia.Websocket</RootNamespace>
<TargetFramework>net6</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Emzi0767.Common" Version="2.6.6" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Websocket.Client" Version="4.6.1" />
<PackageReference Include="Websocket.Client" Version="5.0.0" />
</ItemGroup>


Expand Down
3 changes: 0 additions & 3 deletions Nomia.Websocket/NomiaWebsocket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@
using System.Collections.Generic;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Emzi0767;
using Emzi0767.Utilities;
using Newtonsoft.Json.Linq;
using Nomia.Websocket.Entities;
using Nomia.Websocket.EventArgs;
using Websocket.Client;
using Websocket.Client.Models;

namespace Nomia.Websocket
{
Expand Down
156 changes: 143 additions & 13 deletions Nomia/Entities/LavalinkTrack.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;

Expand Down Expand Up @@ -27,31 +28,31 @@ public enum LavalinkLoadType
/// <summary>
/// Track loaded
/// </summary>
[EnumMember(Value = "TRACK_LOADED")]
[EnumMember(Value = "track")]
TrackLoaded,

/// <summary>
/// Playlist loaded
/// </summary>
[EnumMember(Value = "PLAYLIST_LOADED")]
[EnumMember(Value = "playlist")]
PlaylistLoaded,

/// <summary>
/// No matches found
/// </summary>
[EnumMember(Value = "NO_MATCHES")]
[EnumMember(Value = "empty")]
NoMatches,

/// <summary>
/// Load failed
/// </summary>
[EnumMember(Value = "LOAD_FAILED")]
[EnumMember(Value = "error")]
LoadFailed,

/// <summary>
/// Search result
/// </summary>
[EnumMember(Value = "SEARCH_RESULT")]
[EnumMember(Value = "search")]
SearchResult
}

Expand All @@ -60,31 +61,31 @@ public enum LavalinkTrackEndReason
/// <summary>
/// Track has finished playing
/// </summary>
[EnumMember(Value = "FINISHED")]
[EnumMember(Value = "finished")]
Finished,

/// <summary>
/// Load failed
/// </summary>
[EnumMember(Value = "LOAD_FAILED")]
[EnumMember(Value = "loadFailed")]
LoadFailed,

/// <summary>
/// Track has been stopped
/// </summary>
[EnumMember(Value = "STOPPED")]
[EnumMember(Value = "stopped")]
Stopped,

/// <summary>
/// Track has been replaced
/// </summary>
[EnumMember(Value = "REPLACED")]
[EnumMember(Value = "replaced")]
Replaced,

/// <summary>
/// Track has been cleaned up
/// </summary>
[EnumMember(Value = "CLEANUP")]
[EnumMember(Value = "cleanup")]
Cleanup
}

Expand All @@ -101,30 +102,147 @@ public class LavalinkTrack
/// </summary>
[JsonProperty("info")]
public LavalinkTrackInfo Info { get; set; }

/// <summary>
/// Additional track info provided by plugins
/// </summary>
[JsonProperty("pluginInfo")]
public object PluginInfo { get; set; }

/// <summary>
/// Additional track data provided via the <see cref="https://lavalink.dev/api/rest#update-player">Update Player</see> endpoint
/// </summary>
[JsonProperty("userData")]
public object UserData { get; set; }
}

public class LavalinkPlaylistInfo {
/// <summary>
/// Name of playlist
/// </summary>
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// 0-indexed index of selected track
/// </summary>
[JsonProperty("selectedTrack")]
public int SelectedTrack { get; set; }
}

/// <summary>
/// Lavalink exception object.
/// </summary>
public class LavalinkException
{
/// <summary>
/// The message of the exception
/// </summary>
[JsonProperty("message")]
public string Message { get; set; }
/// <summary>
/// The severity of the exception
/// </summary>
[JsonProperty("severity")]
public string Severity { get; set; }
/// <summary>
/// The cause of the exception
/// </summary>
[JsonProperty("cause")]
public string Cause { get; set; }
}

public class LavalinkLoadResult
public class LavalinkTrackLoadedResult
{
[JsonProperty("encoded")]
public String Encoded { get; }

[JsonProperty("info")]
public LavalinkTrackInfo Info { get; }
}

/// <summary>
/// Loadable response type from lavalink
/// </summary>
public class LavalinkLoadable
{
/// <summary>
/// The type of the result
/// </summary>
[JsonProperty("loadType")]
public LavalinkLoadType LoadType { get; set; }

}

/// <summary>
/// Lavalink load type that contains search response
/// </summary>
public class LavalinkSearchLoadedType : LavalinkLoadable
{
[JsonProperty("data")]
public IReadOnlyList<LavalinkTrack> Tracks { get; set; }
}


public class LavalinkPlaylistLoadedData : LavalinkLoadable
{
/// <summary>
/// Information about loaded playlist
/// </summary>
[JsonProperty("info")]
public LavalinkPlaylistInfo Info { get; set; }
/// <summary>
/// Additional information from plugins
/// </summary>
[JsonProperty("pluginInfo")]
public object PluginInfo { get; set; }
/// <summary>
/// Loaded tracks from playlist
/// </summary>
[JsonProperty("tracks")]
public IReadOnlyList<LavalinkTrack> Tracks { get; set; }
}

public class LavalinkPlaylistLoadedType : LavalinkLoadable
{
/// <summary>
/// Information about loaded playlist
/// </summary>
[JsonProperty("data")]
public LavalinkPlaylistLoadedData Data { get; set; }
}

/// <summary>
/// Contains response of successful track loading
/// </summary>
public class LavalinkTrackLoadedType : LavalinkLoadable
{
/// <summary>
/// Loaded track.
/// </summary>
[JsonProperty("data")]
public LavalinkTrack Data { get; set; }
}

/// <summary>
/// Lavalink object that contains exception of loaded track
/// </summary>
public class LavalinkLoadFailedType : LavalinkLoadable
{
/// <summary>
/// Exception that was thrown by lavalink.
/// </summary>
[JsonProperty("data")]
public LavalinkException Data { get; set; }
}

/// <summary>
/// Lavalink object with no data
/// </summary>
public class LavalinkEmptyLoadType : LavalinkLoadable
{
}

public class LavalinkLoadResult
{
/// <summary>
/// All tracks which have been loaded
/// </summary>
Expand Down Expand Up @@ -197,11 +315,23 @@ public class LavalinkTrackInfo
[JsonProperty("uri")]
public string Uri { get; set; }

/// <summary>
/// The track artwork url
/// </summary>
[JsonProperty("artworkUrl")]
public string ArtworkUrl { get; set; }

/// <summary>
/// The track <see cref="https://en.wikipedia.org/wiki/International_Standard_Recording_Code">ISRC</see>
/// </summary>
[JsonProperty("isrc")]
public string Isrc { get; set; }

/// <summary>
/// The track source name
/// </summary>
[JsonProperty("sourceName")]
public string SourceName { get; set; }

public override string ToString() => $"[{SourceName}] {Title} by {Author}";
}
7 changes: 6 additions & 1 deletion Nomia/EventArgs/Player/PlayerWebsocketClosedEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@ public class PlayerWebsocketClosedEventArgs : AsyncEventArgs
/// The close reason
/// </summary>
public string Reason { get; }
/// <summary>
/// Whether the connection was closed by Discord
/// </summary>
public bool ByRemote { get; }

public PlayerWebsocketClosedEventArgs(int code, string reason)
public PlayerWebsocketClosedEventArgs(int code, string reason, bool byRemote)
{
Code = code;
Reason = reason;
ByRemote = byRemote;
}
}
10 changes: 10 additions & 0 deletions Nomia/Exceptions/UnknownLoadTypeException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;

namespace Nomia.Exceptions;

internal class UnknownLoadTypeException : Exception
{
public UnknownLoadTypeException(string message) : base(message)
{
}
}
2 changes: 1 addition & 1 deletion Nomia/Nomia.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RootNamespace>Nomia</RootNamespace>
<TargetFramework>net6</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<LangVersion>latest</LangVersion>
</PropertyGroup>
Expand Down
Loading

0 comments on commit bda6e12

Please sign in to comment.