4251da0a86
#worth 8 hours
182 lines
7.9 KiB
C#
182 lines
7.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Discord.Modules;
|
|
using Discord.Commands;
|
|
using System.IO;
|
|
using Discord;
|
|
using Discord.Audio;
|
|
using YoutubeExtractor;
|
|
using System.Threading;
|
|
using System.Diagnostics;
|
|
using NadekoBot.Extensions;
|
|
using System.Net;
|
|
using System.Globalization;
|
|
using System.Collections.Concurrent;
|
|
using NadekoBot.Classes.Music;
|
|
|
|
namespace NadekoBot.Modules {
|
|
class Music : DiscordModule {
|
|
|
|
public static ConcurrentDictionary<Server, MusicControls> musicPlayers = new ConcurrentDictionary<Server, MusicControls>();
|
|
|
|
internal static void CleanMusicPlayers() {
|
|
foreach (var mp in musicPlayers
|
|
.Where(kvp => kvp.Value.CurrentSong == null
|
|
&& kvp.Value.SongQueue.Count == 0)) {
|
|
var val = mp.Value;
|
|
musicPlayers.TryRemove(mp.Key, out val);
|
|
}
|
|
}
|
|
|
|
internal static string GetMusicStats() {
|
|
var servers = 0;
|
|
var queued = 0;
|
|
musicPlayers.ForEach(kvp => {
|
|
var mp = kvp.Value;
|
|
if (mp.SongQueue.Count > 0 || mp.CurrentSong != null)
|
|
queued += mp.SongQueue.Count + 1;
|
|
servers++;
|
|
});
|
|
|
|
return $"Playing {queued} songs across {servers} servers.";
|
|
}
|
|
|
|
public Music() : base() {
|
|
System.Timers.Timer cleaner = new System.Timers.Timer();
|
|
cleaner.Elapsed += (s, e) => CleanMusicPlayers();
|
|
cleaner.Interval = 10000;
|
|
cleaner.Start();
|
|
}
|
|
|
|
public override void Install(ModuleManager manager) {
|
|
var client = NadekoBot.client;
|
|
|
|
manager.CreateCommands("!m", cgb => {
|
|
//queue all more complex commands
|
|
commands.ForEach(cmd => cmd.Init(cgb));
|
|
|
|
cgb.CreateCommand("n")
|
|
.Alias("next")
|
|
.Description("Goes to the next song in the queue.")
|
|
.Do(e => {
|
|
if (musicPlayers.ContainsKey(e.Server) == false || (musicPlayers[e.Server]?.CurrentSong) == null) return;
|
|
musicPlayers[e.Server].CurrentSong.Cancel();
|
|
});
|
|
|
|
cgb.CreateCommand("s")
|
|
.Alias("stop")
|
|
.Description("Completely stops the music and unbinds the bot from the channel and cleanes up files.")
|
|
.Do(e => {
|
|
if (musicPlayers.ContainsKey(e.Server) == false) return;
|
|
var player = musicPlayers[e.Server];
|
|
player.SongQueue.Clear();
|
|
if (player.CurrentSong != null) {
|
|
player.CurrentSong.Cancel();
|
|
player.CurrentSong = null;
|
|
}
|
|
});
|
|
|
|
cgb.CreateCommand("p")
|
|
.Alias("pause")
|
|
.Description("Pauses the song")
|
|
.Do(async e => {
|
|
if (musicPlayers.ContainsKey(e.Server) == false) return;
|
|
await e.Send("This feature is coming VERY soon.");
|
|
/*
|
|
if (musicPlayers[e.Server].Pause())
|
|
if (musicPlayers[e.Server].IsPaused)
|
|
await e.Send("Music player Paused");
|
|
else
|
|
await e.Send("Music player unpaused.");
|
|
*/
|
|
});
|
|
|
|
cgb.CreateCommand("q")
|
|
.Alias("yq")
|
|
.Description("Queue a song using keywords or link. **You must be in a voice channel**.\n**Usage**: `!m q Dream Of Venice`")
|
|
.Parameter("query", ParameterType.Unparsed)
|
|
.Do(async e => {
|
|
if (musicPlayers.ContainsKey(e.Server) == false)
|
|
if (musicPlayers.Count > 25) {
|
|
await e.Send($"{e.User.Mention}, playlist supports up to 25 songs. If you think this is not enough, contact the owner.:warning:");
|
|
return;
|
|
}
|
|
else
|
|
musicPlayers.TryAdd(e.Server, new MusicControls());
|
|
|
|
var player = musicPlayers[e.Server];
|
|
try {
|
|
var sr = new StreamRequest(e, e.GetArg("query"));
|
|
Message msg = null;
|
|
sr.OnQueued += async() => {
|
|
msg = await e.Send($":musical_note:**Queued** {sr.Title}");
|
|
};
|
|
sr.OnCompleted += async () => {
|
|
await e.Send($":musical_note:**Finished playing** {sr.Title}");
|
|
};
|
|
sr.OnStarted += async () => {
|
|
if (msg == null)
|
|
await e.Send($":musical_note:**Started playing** {sr.Title}");
|
|
else
|
|
await msg.Edit($":musical_note:**Started playing** {sr.Title}");
|
|
};
|
|
sr.OnBuffering += async () => {
|
|
if (msg != null)
|
|
msg = await e.Send($":musical_note:**Buffering the song**...{sr.Title}");
|
|
};
|
|
player.SongQueue.Add(sr);
|
|
} catch (Exception ex) {
|
|
Console.WriteLine();
|
|
await e.Send("Error. :anger:");
|
|
return;
|
|
}
|
|
});
|
|
|
|
cgb.CreateCommand("lq")
|
|
.Alias("ls").Alias("lp")
|
|
.Description("Lists up to 10 currently queued songs.")
|
|
.Do(async e => {
|
|
if (musicPlayers.ContainsKey(e.Server) == false) await e.Send(":musical_note: No active music player.");
|
|
var player = musicPlayers[e.Server];
|
|
|
|
await e.Send(":musical_note: " + player.SongQueue.Count + " videos currently queued.");
|
|
await e.Send(string.Join("\n", player.SongQueue.Select(v => v.Title).Take(10)));
|
|
});
|
|
|
|
cgb.CreateCommand("np")
|
|
.Alias("playing")
|
|
.Description("Shows the song currently playing.")
|
|
.Do(async e => {
|
|
if (musicPlayers.ContainsKey(e.Server) == false) return;
|
|
var player = musicPlayers[e.Server];
|
|
await e.Send($"Now Playing **{player.CurrentSong.Title}**");
|
|
});
|
|
|
|
cgb.CreateCommand("clrbfr")
|
|
.Alias("clearbuffers")
|
|
.Description("Clears the music buffer across all servers. **Owner only.**")
|
|
.Do(e => {
|
|
if (NadekoBot.OwnerID != e.User.Id) return;
|
|
Directory.Delete("StreamBuffers", true);
|
|
});
|
|
|
|
cgb.CreateCommand("sh")
|
|
.Description("Shuffles the current playlist.")
|
|
.Do(async e => {
|
|
if (musicPlayers.ContainsKey(e.Server) == false) return;
|
|
var player = musicPlayers[e.Server];
|
|
if (player.SongQueue.Count < 2) {
|
|
await e.Send("Not enough songs in order to perform the shuffle.");
|
|
return;
|
|
}
|
|
|
|
player.SongQueue.Shuffle();
|
|
await e.Send(":musical_note: Songs shuffled!");
|
|
});
|
|
});
|
|
}
|
|
}
|
|
}
|