Compare commits

...

6 Commits

Author SHA1 Message Date
1ccc31d3d2 Update readme.md 2024-10-25 21:50:41 +02:00
7c4d8c246d Update README.md 2024-10-25 21:49:24 +02:00
43f0191752 Update readme.md 2024-10-25 21:47:54 +02:00
872b6d3138 Create README.md 2024-10-25 21:44:08 +02:00
f292124228 Update documentation 2024-10-25 21:38:47 +02:00
4cbee9a625 Fix bug with playback & add statuses (#8)
Co-authored-by: Myx <info@azaaxin.com>
2024-10-25 21:06:26 +02:00
8 changed files with 229 additions and 25 deletions

View File

@@ -31,21 +31,23 @@ public class MessageReceivedHandler : INotificationHandler<MessageReceivedNotifi
var servers = _client.Guilds.Select(guild => guild.Name);
var channels = _client.Guilds
.SelectMany(guild => guild.VoiceChannels)
.Where(channel => channel.Users.Any(user => user.IsBot));
.Where(channel => channel.ConnectedUsers.Any(guildUser => guildUser.Id == _client.CurrentUser.Id) &&
channel.Users.Count != 1);
var table = new StringBuilder();
var serverColumnWidth = 25; // Width for server column
var channelColumnWidth = 25; // Width for channel column
table.AppendLine($"{"Servers".PadRight(serverColumnWidth - 1)}|{"Channels".PadRight(channelColumnWidth - 1)}");
table.AppendLine($"{new string('-', serverColumnWidth - 1)}|{new string('-', channelColumnWidth - 1)}");
foreach (var (server, channel) in servers.Zip(channels))
{
table.AppendLine($"{server.PadRight(serverColumnWidth - 1)}|{channel.Name.PadRight(channelColumnWidth - 1)}");
}
var statsList = new StringBuilder();
statsList.AppendLine("➡️ Servers");
foreach (var server in servers)
statsList.AppendLine($"* {server}");
statsList.AppendLine("➡️ Now playing channels: ");
foreach (var channel in channels)
statsList.AppendLine($"* {channel.Name} in {channel.Guild.Name}");
var embed = new EmbedBuilder()
.WithTitle("Lunaris Statistics")
.WithDescription(table.ToString())
.WithDescription(statsList.ToString())
.Build();
await notification.Message.Channel.SendMessageAsync(embed: embed);

View File

@@ -105,7 +105,7 @@ public class PlayHandler : IRequestHandler<PlayCommand>
var trackLoadOptions = new TrackLoadOptions
{
SearchMode = TrackSearchMode.YouTube,
SearchMode = TrackSearchMode.YouTubeMusic,
};
var trackCollection = await _audioService.Tracks.LoadTracksAsync(searchQuery, trackLoadOptions, cancellationToken: cancellationToken);
@@ -145,7 +145,7 @@ public class PlayHandler : IRequestHandler<PlayCommand>
else
{
// It's just a single track or a search result.
var track = trackCollection.Tracks.FirstOrDefault();
var track = trackCollection.Track;
if (track != null)
{

View File

@@ -8,6 +8,26 @@ flowchart TD
PlayTrack --> NowPlayingEmbed
```
```mermaid
sequenceDiagram
participant User as User
participant DiscordSocketClient as DiscordSocketClient
participant MessageReceivedHandler as MessageReceivedHandler
participant MessageReceivedNotification as MessageReceivedNotification
participant EmbedBuilder as EmbedBuilder
participant Channel as Channel
User->>DiscordSocketClient: Send message "!LunarisStats"
DiscordSocketClient->>MessageReceivedHandler: MessageReceivedNotification
MessageReceivedHandler->>MessageReceivedNotification: Handle(notification, cancellationToken)
MessageReceivedNotification->>MessageReceivedHandler: BotMentioned(notification, cancellationToken)
MessageReceivedHandler->>DiscordSocketClient: Get guilds and voice channels
DiscordSocketClient-->>MessageReceivedHandler: List of guilds and voice channels
MessageReceivedHandler->>EmbedBuilder: Create embed with statistics
EmbedBuilder-->>MessageReceivedHandler: Embed
MessageReceivedHandler->>Channel: Send embed message
```
## Steps in the code
| Name | Description |
@@ -32,4 +52,4 @@ There is also OnTrackEnd, when it get called an attempt is made to play the next
| `player` | `LavaPlayer` | An instance of the `LavaPlayer` class, representing a music player connected to a specific voice channel. Used to play, pause, skip, and queue tracks. |
| `guildMessageIds` | `Dictionary<ulong, List<ulong>>` | A dictionary that maps guild IDs to lists of message IDs. Used to keep track of messages sent by the bot in each guild, allowing the bot to delete its old messages when it sends new ones. |
| `songName` | `string` | A string that represents the name or URL of a song to play. Used to search for and queue tracks. |
| `searchResponse` | `SearchResponse` | An instance of the `SearchResponse` class, representing the result of a search for tracks. Used to get the tracks that were found and queue them in the player. |
| `searchResponse` | `SearchResponse` | An instance of the `SearchResponse` class, representing the result of a search for tracks. Used to get the tracks that were found and queue them in the player. |

View File

@@ -0,0 +1,139 @@
### README.md
# Handlers
Handlers for the Lunaris2 bot, which is built using C#, Discord.Net, and Lavalink4NET. Below is a detailed description of each handler and their responsibilities.
## Handlers
### ClearQueueHandler
Handles the command to clear the music queue.
```csharp
public class ClearQueueHandler : IRequestHandler<ClearQueueCommand>
```
### DisconnectHandler
Handles the command to disconnect the bot from the voice channel.
```csharp
public class DisconnectHandler : IRequestHandler<DisconnectCommand>
```
### PauseHandler
Handles the command to pause the currently playing track.
```csharp
public class PauseHandler : IRequestHandler<PauseCommand>
```
### PlayHandler
Handles the command to play a track or playlist.
```csharp
public class PlayHandler : IRequestHandler<PlayCommand>
```
### ResumeHandler
Handles the command to resume the currently paused track.
```csharp
public class ResumeHandler : IRequestHandler<ResumeCommand>
```
### SkipHandler
Handles the command to skip the currently playing track.
```csharp
public class SkipHandler : IRequestHandler<SkipCommand>
```
### MessageReceivedHandler
Handles incoming messages and processes commands or statistics requests.
```csharp
public class MessageReceivedHandler : INotificationHandler<MessageReceivedNotification>
```
## Mermaid Diagrams
### Class Diagram
```mermaid
sequenceDiagram
participant User as User
participant DiscordSocketClient as DiscordSocketClient
participant MessageReceivedHandler as MessageReceivedHandler
participant MessageReceivedNotification as MessageReceivedNotification
participant EmbedBuilder as EmbedBuilder
participant Channel as Channel
User->>DiscordSocketClient: Send message "!LunarisStats"
DiscordSocketClient->>MessageReceivedHandler: MessageReceivedNotification
MessageReceivedHandler->>MessageReceivedNotification: Handle(notification, cancellationToken)
MessageReceivedNotification->>MessageReceivedHandler: BotMentioned(notification, cancellationToken)
MessageReceivedHandler->>DiscordSocketClient: Get guilds and voice channels
DiscordSocketClient-->>MessageReceivedHandler: List of guilds and voice channels
MessageReceivedHandler->>EmbedBuilder: Create embed with statistics
EmbedBuilder-->>MessageReceivedHandler: Embed
MessageReceivedHandler->>Channel: Send embed message
```
### Sequence Diagram for PlayHandler
```mermaid
sequenceDiagram
participant User
participant Bot
participant DiscordSocketClient
participant IAudioService
participant SocketSlashCommand
participant LavalinkPlayer
User->>Bot: /play [song]
Bot->>DiscordSocketClient: Get user voice channel
DiscordSocketClient-->>Bot: Voice channel info
Bot->>IAudioService: Get or create player
IAudioService-->>Bot: Player instance
Bot->>SocketSlashCommand: Get search query
SocketSlashCommand-->>Bot: Search query
Bot->>IAudioService: Load tracks
IAudioService-->>Bot: Track collection
Bot->>LavalinkPlayer: Play track
LavalinkPlayer-->>Bot: Track started
Bot->>User: Now playing embed
```
### Sequence Diagram for MessageReceivedHandler
```mermaid
sequenceDiagram
participant User
participant Bot
participant DiscordSocketClient
participant ISender
participant MessageReceivedNotification
User->>Bot: Send message
Bot->>MessageReceivedNotification: Create notification
Bot->>DiscordSocketClient: Check if bot is mentioned
DiscordSocketClient-->>Bot: Mention info
alt Bot is mentioned
Bot->>ISender: Send ChatCommand
end
Bot->>DiscordSocketClient: Check for statistics command
alt Statistics command found
Bot->>DiscordSocketClient: Get server and channel info
DiscordSocketClient-->>Bot: Server and channel info
Bot->>User: Send statistics embed
end
```
This README provides an overview of the handlers and their responsibilities, along with class and sequence diagrams to illustrate the interactions and relationships between the components.

View File

@@ -6,6 +6,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UserSecretsId>ec2f340f-a44c-4869-ab79-a12ba9459d80</UserSecretsId>
<AssemblyVersion>0.0.1337</AssemblyVersion>
</PropertyGroup>
<!-- Lavalink4net 4.0.25 seems to break the Message Module-->

View File

@@ -2,11 +2,15 @@
```mermaid
flowchart TD
Program[Program] -->|Register| EventListener
Program --> Intervals[VoiceChannelMonitorService]
Intervals --> SetStatus[SetStatus, Updates status with amount of playing bots]
Intervals --> LeaveChannel[LeaveOnAlone, Leaves channel when alone for a time]
EventListener[DiscordEventListener] --> A[MessageReceivedHandler]
EventListener[DiscordEventListener] --> A2[SlashCommandReceivedHandler]
A --> |Message| f{If bot is mentioned}
A --> |Message '!LunarisStats'| p[Responds with Server and Channel Statistics.]
f --> |ChatCommand| v[ChatHandler]
A2[SlashCommandReceivedHandler] -->|Message| C{Send to correct command by
@@ -14,8 +18,11 @@ flowchart TD
C -->|JoinCommand| D[JoinHandler]
C -->|PlayCommand| E[PlayHandler]
C -->|HelloCommand| F[HelloHandler]
C -->|GoodbyeCommand| G[GoodbyeHandler]
C -->|PauseCommand| F[PauseHandler]
C -->|DisconnectCommand| H[DisconnectHandler]
C -->|ResumeCommand| J[ResumeHandler]
C -->|SkipCommand| K[SkipHandler]
C -->|ClearQueueCommand| L[ClearQueueHandler]
```
Program registers an event listener ```DiscordEventListener``` which publish a message :
@@ -30,20 +37,33 @@ await Mediator.Publish(new MessageReceivedNotification(arg), _cancellationToken)
## Handler integrations
```mermaid
flowchart TD
flowchart LR
D[JoinHandler] --> Disc[Discord Api]
E[PlayHandler] --> Disc[Discord Api]
F[HelloHandler] --> Disc[Discord Api]
G[GoodbyeHandler] --> Disc[Discord Api]
F[SkipHandler] --> Disc[Discord Api]
G[PauseHandler] --> Disc[Discord Api]
v[ChatHandler] --> Disc[Discord Api]
ClearQueueHandler --> Disc
ClearQueuehandler --> Lava
DisconnectHandler --> Disc
Resumehandler --> Disc
v --> o[Ollama Server]
o --> v
E --> Lava[Lavalink]
F --> Lava
G --> Lava
```
|Name| Description |
|--|--|
| JoinHandler| Handles the logic for **just** joining a voice channel. |
| PlayHandler| Handles the logic for joining and playing music in a voice channel. |
| HelloHandler| Responds with Hello. (Dummy handler, will be removed)|
| GoodbyeHandler| Responds with Goodbye. (Dummy handler, will be removed)|
| PauseHandler | Handles the logic for pausing currently playing track. |
| DisconnectHandler | Handles the logic for disconnecting from voicechannels. |
| ClearQueueHandler | Handles the logic for clearing the queued songs, except the currently playing one. |
| SkipHandler | Handles the logic for skipping tracks that are queued. If 0 trackS is in queue, it stops the current one.|
| Resumehandler | Resumes paused tracks. |
| ChatHandler| Handles the logic for LLM chat with user. |

View File

@@ -1,3 +1,4 @@
using Discord;
using Discord.WebSocket;
namespace Lunaris2.Service
@@ -25,6 +26,30 @@ namespace Lunaris2.Service
}
private async Task CheckVoiceChannels()
{
SetStatus();
await LeaveOnAlone();
}
private void SetStatus()
{
var channels = _client.Guilds
.SelectMany(guild => guild.VoiceChannels)
.Count(channel =>
channel.ConnectedUsers
.Any(guildUser => guildUser.Id == _client.CurrentUser.Id) &&
channel.Users.Count > 1
);
if (channels == 0)
_client.SetGameAsync(System.Reflection.Assembly.GetEntryAssembly()?.GetName().Version?.ToString(), type: ActivityType.CustomStatus);
else if(channels == 1)
_client.SetGameAsync("in 1 server", type: ActivityType.Playing);
else if(channels > 1)
_client.SetGameAsync($" in {channels} servers", type: ActivityType.Playing);
}
private async Task LeaveOnAlone()
{
foreach (var guild in _client.Guilds)
{

View File

@@ -49,12 +49,9 @@ plugins:
# Clients are queried in the order they are given (so the first client is queried first and so on...)
clients:
- MUSIC
- ANDROID_TESTSUITE
- WEB
- TVHTML5EMBEDDED
# name: # Name of the plugin
# some_key: some_value # Some key-value pair for the plugin
# another_key: another_value
- ANDROID_TESTSUITE
lavalink:
plugins:
- dependency: com.github.devoxin:lavadspx-plugin:0.0.5 # replace {VERSION} with the latest version from the "Releases" tab.