Merge remote-tracking branch 'Kwoth/dev' into dev

This commit is contained in:
Shikhir Arora 2017-02-17 17:14:22 -05:00
commit 8ab9b57c7d
11 changed files with 188 additions and 116 deletions

View File

@ -1,14 +1,12 @@
![img](https://ci.appveyor.com/api/projects/status/gmu6b3ltc80hr3k9?svg=true) ![img](https://ci.appveyor.com/api/projects/status/gmu6b3ltc80hr3k9?svg=true)
[![Discord](https://discordapp.com/api/guilds/117523346618318850/widget.png)](https://discord.gg/nadekobot) [![Discord](https://discordapp.com/api/guilds/117523346618318850/widget.png)](https://discord.gg/nadekobot)
[![Documentation Status](https://readthedocs.org/projects/nadekobot/badge/?version=latest)](http://nadekobot.readthedocs.io/en/latest/?badge=latest) [![Documentation Status](https://readthedocs.org/projects/nadekobot/badge/?version=latest)](http://nadekobot.readthedocs.io/en/latest/?badge=latest)
![nadeko0](https://cdn.discordapp.com/attachments/266240393639755778/281920716809699328/part1.png) [![nadeko0](https://cdn.discordapp.com/attachments/266240393639755778/281920716809699328/part1.png)](http://nadekobot.xyz)
[![nadeko1](https://cdn.discordapp.com/attachments/266240393639755778/281920134967328768/part2.png)](https://discordapp.com/oauth2/authorize?client_id=170254782546575360&scope=bot&permissions=66186303) [![nadeko1](https://cdn.discordapp.com/attachments/266240393639755778/281920134967328768/part2.png)](https://discordapp.com/oauth2/authorize?client_id=170254782546575360&scope=bot&permissions=66186303)
[![nadeko2](https://cdn.discordapp.com/attachments/266240393639755778/281920161311883264/part3.png)](http://nadekobot.readthedocs.io/en/latest/Commands%20List/) [![nadeko2](https://cdn.discordapp.com/attachments/266240393639755778/281920161311883264/part3.png)](http://nadekobot.readthedocs.io/en/latest/Commands%20List/)
##For Update, Help and Guidlines ##For Update, Help and Guidelines
`Follow me on twitter for updates. | Join my Discord server if you need help. | Read the Docs for hosting guides.`
[![twitter](https://cdn.discordapp.com/attachments/155726317222887425/252192520094613504/twiter_banner.JPG)](https://twitter.com/TheNadekoBot) [![discord](https://cdn.discordapp.com/attachments/266240393639755778/281920766490968064/discord.png)](https://discord.gg/nadekobot) [![Wiki](https://cdn.discordapp.com/attachments/266240393639755778/281920793330581506/datcord.png)](http://nadekobot.readthedocs.io/en/latest/)
| [![twitter](https://cdn.discordapp.com/attachments/155726317222887425/252192520094613504/twiter_banner.JPG)](https://twitter.com/TheNadekoBot) | [![discord](https://cdn.discordapp.com/attachments/266240393639755778/281920766490968064/discord.png)](https://discord.gg/nadekobot) | [![Wiki](https://cdn.discordapp.com/attachments/266240393639755778/281920793330581506/datcord.png)](http://nadekobot.readthedocs.io/en/latest/)
| --- | --- | --- |
| Follow me on Twitter for updates. | Join my Discord server if you need help. | Read the Docs for hosting guides. |

View File

@ -72,19 +72,37 @@ namespace NadekoBot.Modules.Administration
{ {
if (_forwardDMs && ownerChannels.Any()) if (_forwardDMs && ownerChannels.Any())
{ {
var title = var title = GetTextStatic("dm_from",
GetTextStatic("dm_from", NadekoBot.Localization.DefaultCultureInfo, NadekoBot.Localization.DefaultCultureInfo,
typeof(Administration).Name.ToLowerInvariant()) + $" [{msg.Author}]({msg.Author.Id})"; typeof(Administration).Name.ToLowerInvariant()) +
$" [{msg.Author}]({msg.Author.Id})";
var attachamentsTxt = GetTextStatic("attachments",
NadekoBot.Localization.DefaultCultureInfo,
typeof(Administration).Name.ToLowerInvariant());
var toSend = msg.Content;
if (msg.Attachments.Count > 0)
{
toSend += $"\n\n{Format.Code(attachamentsTxt)}:\n" +
string.Join("\n", msg.Attachments.Select(a => a.ProxyUrl));
}
if (_forwardDMsToAllOwners) if (_forwardDMsToAllOwners)
{ {
await Task.WhenAll(ownerChannels.Where(ch => ch.Recipient.Id != msg.Author.Id) await Task.WhenAll(ownerChannels.Where(ch => ch.Recipient.Id != msg.Author.Id)
.Select(ch => ch.SendConfirmAsync(title, msg.Content))).ConfigureAwait(false); .Select(ch => ch.SendConfirmAsync(title, toSend))).ConfigureAwait(false);
} }
else else
{ {
var firstOwnerChannel = ownerChannels.First(); var firstOwnerChannel = ownerChannels.First();
if (firstOwnerChannel.Recipient.Id != msg.Author.Id) if (firstOwnerChannel.Recipient.Id != msg.Author.Id)
try { await firstOwnerChannel.SendConfirmAsync(title, msg.Content).ConfigureAwait(false); } {
try
{
await firstOwnerChannel.SendConfirmAsync(title, toSend).ConfigureAwait(false);
}
catch catch
{ {
// ignored // ignored
@ -92,6 +110,7 @@ namespace NadekoBot.Modules.Administration
} }
} }
} }
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]

View File

@ -43,7 +43,7 @@ namespace NadekoBot.Modules.Gambling
switch (e) switch (e)
{ {
case CurrencyEvent.FlowerReaction: case CurrencyEvent.FlowerReaction:
await FlowerReactionEvent(Context).ConfigureAwait(false); await FlowerReactionEvent(Context, arg).ConfigureAwait(false);
break; break;
case CurrencyEvent.SneakyGameStatus: case CurrencyEvent.SneakyGameStatus:
await SneakyGameStatusEvent(Context, arg).ConfigureAwait(false); await SneakyGameStatusEvent(Context, arg).ConfigureAwait(false);
@ -115,23 +115,26 @@ namespace NadekoBot.Modules.Gambling
return Task.Delay(0); return Task.Delay(0);
} }
public async Task FlowerReactionEvent(CommandContext context) public async Task FlowerReactionEvent(CommandContext context, int amount)
{ {
if (amount <= 0)
amount = 100;
var title = GetText("flowerreaction_title"); var title = GetText("flowerreaction_title");
var desc = GetText("flowerreaction_desc", "🌸", Format.Bold(100.ToString()) + CurrencySign); var desc = GetText("flowerreaction_desc", "🌸", Format.Bold(amount.ToString()) + CurrencySign);
var footer = GetText("flowerreaction_footer", 24); var footer = GetText("flowerreaction_footer", 24);
var msg = await context.Channel.SendConfirmAsync(title, var msg = await context.Channel.SendConfirmAsync(title,
desc, footer: footer) desc, footer: footer)
.ConfigureAwait(false); .ConfigureAwait(false);
await new FlowerReactionEvent().Start(msg, context); await new FlowerReactionEvent().Start(msg, context, amount);
} }
} }
} }
public abstract class CurrencyEvent public abstract class CurrencyEvent
{ {
public abstract Task Start(IUserMessage msg, CommandContext channel); public abstract Task Start(IUserMessage msg, CommandContext channel, int amount);
} }
public class FlowerReactionEvent : CurrencyEvent public class FlowerReactionEvent : CurrencyEvent
@ -172,7 +175,7 @@ namespace NadekoBot.Modules.Gambling
return Task.CompletedTask; return Task.CompletedTask;
} }
public override async Task Start(IUserMessage umsg, CommandContext context) public override async Task Start(IUserMessage umsg, CommandContext context, int amount)
{ {
msg = umsg; msg = umsg;
NadekoBot.Client.MessageDeleted += MessageDeletedEventHandler; NadekoBot.Client.MessageDeleted += MessageDeletedEventHandler;
@ -193,7 +196,7 @@ namespace NadekoBot.Modules.Gambling
{ {
if (r.Emoji.Name == "🌸" && r.User.IsSpecified && ((DateTime.UtcNow - r.User.Value.CreatedAt).TotalDays > 5) && _flowerReactionAwardedUsers.Add(r.User.Value.Id)) if (r.Emoji.Name == "🌸" && r.User.IsSpecified && ((DateTime.UtcNow - r.User.Value.CreatedAt).TotalDays > 5) && _flowerReactionAwardedUsers.Add(r.User.Value.Id))
{ {
await CurrencyHandler.AddCurrencyAsync(r.User.Value, "Flower Reaction Event", 100, false) await CurrencyHandler.AddCurrencyAsync(r.User.Value, "Flower Reaction Event", amount, false)
.ConfigureAwait(false); .ConfigureAwait(false);
} }
} }

View File

@ -49,7 +49,9 @@ namespace NadekoBot.Modules.Gambling
[Priority(0)] [Priority(0)]
public async Task Cash([Remainder] IUser user = null) public async Task Cash([Remainder] IUser user = null)
{ {
user = user ?? Context.User; if(user == null)
await ConfirmLocalized("has", Format.Bold(Context.User.ToString()), $"{GetCurrency(Context.User.Id)} {CurrencySign}").ConfigureAwait(false);
else
await ReplyConfirmLocalized("has", Format.Bold(user.ToString()), $"{GetCurrency(user.Id)} {CurrencySign}").ConfigureAwait(false); await ReplyConfirmLocalized("has", Format.Bold(user.ToString()), $"{GetCurrency(user.Id)} {CurrencySign}").ConfigureAwait(false);
} }

View File

@ -77,10 +77,10 @@ namespace NadekoBot.Modules.Music.Classes
public IVoiceChannel PlaybackVoiceChannel { get; private set; } public IVoiceChannel PlaybackVoiceChannel { get; private set; }
public ITextChannel OutputTextChannel { get; set; } public ITextChannel OutputTextChannel { get; set; }
private bool destroyed { get; set; } = false; private bool destroyed { get; set; }
public bool RepeatSong { get; private set; } = false; public bool RepeatSong { get; private set; }
public bool RepeatPlaylist { get; private set; } = false; public bool RepeatPlaylist { get; private set; }
public bool Autoplay { get; set; } = false; public bool Autoplay { get; set; }
public uint MaxQueueSize { get; set; } = 0; public uint MaxQueueSize { get; set; } = 0;
private ConcurrentQueue<Action> actionQueue { get; } = new ConcurrentQueue<Action>(); private ConcurrentQueue<Action> actionQueue { get; } = new ConcurrentQueue<Action>();

View File

@ -5,12 +5,9 @@ using System;
using System.Diagnostics; using System.Diagnostics;
using System.Diagnostics.Contracts; using System.Diagnostics.Contracts;
using System.IO; using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using VideoLibrary;
using System.Net; using System.Net;
namespace NadekoBot.Modules.Music.Classes namespace NadekoBot.Modules.Music.Classes
@ -32,13 +29,13 @@ namespace NadekoBot.Modules.Music.Classes
public string QueuerName { get; set; } public string QueuerName { get; set; }
public TimeSpan TotalTime { get; set; } = TimeSpan.Zero; public TimeSpan TotalTime { get; set; } = TimeSpan.Zero;
public TimeSpan CurrentTime => TimeSpan.FromSeconds(bytesSent / frameBytes / (1000 / milliseconds)); public TimeSpan CurrentTime => TimeSpan.FromSeconds(bytesSent / (float)_frameBytes / (1000 / (float)_milliseconds));
const int milliseconds = 20; private const int _milliseconds = 20;
const int samplesPerFrame = (48000 / 1000) * milliseconds; private const int _samplesPerFrame = (48000 / 1000) * _milliseconds;
const int frameBytes = 3840; //16-bit, 2 channels private const int _frameBytes = 3840; //16-bit, 2 channels
private ulong bytesSent { get; set; } = 0; private ulong bytesSent { get; set; }
//pwetty //pwetty
@ -47,7 +44,7 @@ namespace NadekoBot.Modules.Music.Classes
public string PrettyFullTime => PrettyCurrentTime + " / " + PrettyTotalTime; public string PrettyFullTime => PrettyCurrentTime + " / " + PrettyTotalTime;
public string PrettyName => $"**[{SongInfo.Title.TrimTo(65)}]({songUrl})**"; public string PrettyName => $"**[{SongInfo.Title.TrimTo(65)}]({SongUrl})**";
public string PrettyInfo => $"{MusicPlayer.PrettyVolume} | {PrettyTotalTime} | {PrettyProvider} | {QueuerName}"; public string PrettyInfo => $"{MusicPlayer.PrettyVolume} | {PrettyTotalTime} | {PrettyProvider} | {QueuerName}";
@ -65,37 +62,34 @@ namespace NadekoBot.Modules.Music.Classes
} }
} }
private string PrettyTotalTime { public string PrettyTotalTime {
get { get
{
if (TotalTime == TimeSpan.Zero) if (TotalTime == TimeSpan.Zero)
return "(?)"; return "(?)";
else if (TotalTime == TimeSpan.MaxValue) if (TotalTime == TimeSpan.MaxValue)
return "∞"; return "∞";
else
{
var time = TotalTime.ToString(@"mm\:ss"); var time = TotalTime.ToString(@"mm\:ss");
var hrs = (int)TotalTime.TotalHours; var hrs = (int)TotalTime.TotalHours;
if (hrs > 0) if (hrs > 0)
return hrs + ":" + time; return hrs + ":" + time;
else
return time; return time;
} }
} }
}
public string Thumbnail { public string Thumbnail {
get { get {
switch (SongInfo.ProviderType) switch (SongInfo.ProviderType)
{ {
case MusicType.Radio: case MusicType.Radio:
return $"https://cdn.discordapp.com/attachments/155726317222887425/261850925063340032/1482522097_radio.png"; //test links return "https://cdn.discordapp.com/attachments/155726317222887425/261850925063340032/1482522097_radio.png"; //test links
case MusicType.Normal: case MusicType.Normal:
//todo have videoid in songinfo from the start //todo have videoid in songinfo from the start
var videoId = Regex.Match(SongInfo.Query, "<=v=[a-zA-Z0-9-]+(?=&)|(?<=[0-9])[^&\n]+|(?<=v=)[^&\n]+"); var videoId = Regex.Match(SongInfo.Query, "<=v=[a-zA-Z0-9-]+(?=&)|(?<=[0-9])[^&\n]+|(?<=v=)[^&\n]+");
return $"https://img.youtube.com/vi/{ videoId }/0.jpg"; return $"https://img.youtube.com/vi/{ videoId }/0.jpg";
case MusicType.Local: case MusicType.Local:
return $"https://cdn.discordapp.com/attachments/155726317222887425/261850914783100928/1482522077_music.png"; //test links return "https://cdn.discordapp.com/attachments/155726317222887425/261850914783100928/1482522077_music.png"; //test links
case MusicType.Soundcloud: case MusicType.Soundcloud:
return SongInfo.AlbumArt; return SongInfo.AlbumArt;
default: default:
@ -104,7 +98,7 @@ namespace NadekoBot.Modules.Music.Classes
} }
} }
private string songUrl { public string SongUrl {
get { get {
switch (SongInfo.ProviderType) switch (SongInfo.ProviderType)
{ {
@ -122,36 +116,32 @@ namespace NadekoBot.Modules.Music.Classes
} }
} }
private int skipTo = 0; public int SkipTo { get; set; }
public int SkipTo {
get { return skipTo; }
set {
skipTo = value;
bytesSent = (ulong)skipTo * 3840 * 50;
}
}
private readonly Logger _log; private readonly Logger _log;
public Song(SongInfo songInfo) public Song(SongInfo songInfo)
{ {
this.SongInfo = songInfo; SongInfo = songInfo;
this._log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
} }
public Song Clone() public Song Clone()
{ {
var s = new Song(SongInfo); var s = new Song(SongInfo)
s.MusicPlayer = MusicPlayer; {
s.QueuerName = QueuerName; MusicPlayer = MusicPlayer,
QueuerName = QueuerName
};
return s; return s;
} }
public async Task Play(IAudioClient voiceClient, CancellationToken cancelToken) public async Task Play(IAudioClient voiceClient, CancellationToken cancelToken)
{ {
bytesSent = (ulong) SkipTo * 3840 * 50;
var filename = Path.Combine(Music.MusicDataPath, DateTime.Now.UnixTimestamp().ToString()); var filename = Path.Combine(Music.MusicDataPath, DateTime.Now.UnixTimestamp().ToString());
SongBuffer inStream = new SongBuffer(MusicPlayer, filename, SongInfo, skipTo, frameBytes * 100); var inStream = new SongBuffer(MusicPlayer, filename, SongInfo, SkipTo, _frameBytes * 100);
var bufferTask = inStream.BufferSong(cancelToken).ConfigureAwait(false); var bufferTask = inStream.BufferSong(cancelToken).ConfigureAwait(false);
try try
@ -200,22 +190,22 @@ namespace NadekoBot.Modules.Music.Classes
var outStream = voiceClient.CreatePCMStream(960); var outStream = voiceClient.CreatePCMStream(960);
int nextTime = Environment.TickCount + milliseconds; int nextTime = Environment.TickCount + _milliseconds;
byte[] buffer = new byte[frameBytes]; byte[] buffer = new byte[_frameBytes];
while (!cancelToken.IsCancellationRequested && //song canceled for whatever reason while (!cancelToken.IsCancellationRequested && //song canceled for whatever reason
!(MusicPlayer.MaxPlaytimeSeconds != 0 && CurrentTime.TotalSeconds >= MusicPlayer.MaxPlaytimeSeconds)) // or exceedded max playtime !(MusicPlayer.MaxPlaytimeSeconds != 0 && CurrentTime.TotalSeconds >= MusicPlayer.MaxPlaytimeSeconds)) // or exceedded max playtime
{ {
//Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------"); //Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------");
var read = await inStream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); var read = await inStream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
//await inStream.CopyToAsync(voiceClient.OutputStream); //await inStream.CopyToAsync(voiceClient.OutputStream);
if (read < frameBytes) if (read < _frameBytes)
_log.Debug("read {0}", read); _log.Debug("read {0}", read);
unchecked unchecked
{ {
bytesSent += (ulong)read; bytesSent += (ulong)read;
} }
if (read < frameBytes) if (read < _frameBytes)
{ {
if (read == 0) if (read == 0)
{ {
@ -231,12 +221,12 @@ namespace NadekoBot.Modules.Music.Classes
_log.Warn("Slow connection has disrupted music, waiting a bit for buffer"); _log.Warn("Slow connection has disrupted music, waiting a bit for buffer");
await Task.Delay(1000, cancelToken).ConfigureAwait(false); await Task.Delay(1000, cancelToken).ConfigureAwait(false);
nextTime = Environment.TickCount + milliseconds; nextTime = Environment.TickCount + _milliseconds;
} }
else else
{ {
await Task.Delay(100, cancelToken).ConfigureAwait(false); await Task.Delay(100, cancelToken).ConfigureAwait(false);
nextTime = Environment.TickCount + milliseconds; nextTime = Environment.TickCount + _milliseconds;
} }
} }
else else
@ -245,16 +235,16 @@ namespace NadekoBot.Modules.Music.Classes
else else
attempt = 0; attempt = 0;
while (this.MusicPlayer.Paused) while (MusicPlayer.Paused)
{ {
await Task.Delay(200, cancelToken).ConfigureAwait(false); await Task.Delay(200, cancelToken).ConfigureAwait(false);
nextTime = Environment.TickCount + milliseconds; nextTime = Environment.TickCount + _milliseconds;
} }
buffer = AdjustVolume(buffer, MusicPlayer.Volume); buffer = AdjustVolume(buffer, MusicPlayer.Volume);
if (read != frameBytes) continue; if (read != _frameBytes) continue;
nextTime = unchecked(nextTime + milliseconds); nextTime = unchecked(nextTime + _milliseconds);
int delayMillis = unchecked(nextTime - Environment.TickCount); int delayMillis = unchecked(nextTime - Environment.TickCount);
if (delayMillis > 0) if (delayMillis > 0)
await Task.Delay(delayMillis, cancelToken).ConfigureAwait(false); await Task.Delay(delayMillis, cancelToken).ConfigureAwait(false);
@ -264,7 +254,6 @@ namespace NadekoBot.Modules.Music.Classes
finally finally
{ {
await bufferTask; await bufferTask;
if (inStream != null)
inStream.Dispose(); inStream.Dispose();
} }
} }
@ -279,7 +268,7 @@ namespace NadekoBot.Modules.Music.Classes
} }
//aidiakapi ftw //aidiakapi ftw
public unsafe static byte[] AdjustVolume(byte[] audioSamples, float volume) public static unsafe byte[] AdjustVolume(byte[] audioSamples, float volume)
{ {
Contract.Requires(audioSamples != null); Contract.Requires(audioSamples != null);
Contract.Requires(audioSamples.Length % 2 == 0); Contract.Requires(audioSamples.Length % 2 == 0);
@ -289,15 +278,15 @@ namespace NadekoBot.Modules.Music.Classes
if (Math.Abs(volume - 1f) < 0.0001f) return audioSamples; if (Math.Abs(volume - 1f) < 0.0001f) return audioSamples;
// 16-bit precision for the multiplication // 16-bit precision for the multiplication
int volumeFixed = (int)Math.Round(volume * 65536d); var volumeFixed = (int)Math.Round(volume * 65536d);
int count = audioSamples.Length / 2; var count = audioSamples.Length / 2;
fixed (byte* srcBytes = audioSamples) fixed (byte* srcBytes = audioSamples)
{ {
short* src = (short*)srcBytes; var src = (short*)srcBytes;
for (int i = count; i != 0; i--, src++) for (var i = count; i != 0; i--, src++)
*src = (short)(((*src) * volumeFixed) >> 16); *src = (short)(((*src) * volumeFixed) >> 16);
} }

View File

@ -6,12 +6,14 @@ using System.Net.Http;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using NLog;
using VideoLibrary; using VideoLibrary;
namespace NadekoBot.Modules.Music.Classes namespace NadekoBot.Modules.Music.Classes
{ {
public static class SongHandler public static class SongHandler
{ {
private static readonly Logger _log = LogManager.GetCurrentClassLogger();
public static async Task<Song> ResolveSong(string query, MusicType musicType = MusicType.Normal) public static async Task<Song> ResolveSong(string query, MusicType musicType = MusicType.Normal)
{ {
if (string.IsNullOrWhiteSpace(query)) if (string.IsNullOrWhiteSpace(query))
@ -106,7 +108,8 @@ namespace NadekoBot.Modules.Music.Classes
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine($"Failed resolving the link.{ex.Message}"); _log.Warn($"Failed resolving the link.{ex.Message}");
_log.Warn(ex);
return null; return null;
} }
} }
@ -137,7 +140,7 @@ namespace NadekoBot.Modules.Music.Classes
} }
catch catch
{ {
Console.WriteLine($"Failed reading .pls:\n{file}"); _log.Warn($"Failed reading .pls:\n{file}");
return null; return null;
} }
} }
@ -156,7 +159,7 @@ namespace NadekoBot.Modules.Music.Classes
} }
catch catch
{ {
Console.WriteLine($"Failed reading .m3u:\n{file}"); _log.Warn($"Failed reading .m3u:\n{file}");
return null; return null;
} }
@ -172,7 +175,7 @@ namespace NadekoBot.Modules.Music.Classes
} }
catch catch
{ {
Console.WriteLine($"Failed reading .asx:\n{file}"); _log.Warn($"Failed reading .asx:\n{file}");
return null; return null;
} }
} }
@ -192,7 +195,7 @@ namespace NadekoBot.Modules.Music.Classes
} }
catch catch
{ {
Console.WriteLine($"Failed reading .xspf:\n{file}"); _log.Warn($"Failed reading .xspf:\n{file}");
return null; return null;
} }
} }

View File

@ -14,7 +14,6 @@ using System.Net.Http;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
namespace NadekoBot.Modules.Music namespace NadekoBot.Modules.Music
@ -78,7 +77,10 @@ namespace NadekoBot.Modules.Music
} }
} }
catch { } catch
{
// ignored
}
return Task.CompletedTask; return Task.CompletedTask;
} }
@ -216,7 +218,6 @@ namespace NadekoBot.Modules.Music
.Take(itemsPerPage) .Take(itemsPerPage)
.Select(v => $"`{++number}.` {v.PrettyFullName}")); .Select(v => $"`{++number}.` {v.PrettyFullName}"));
if (currentSong != null)
desc = $"`🔊` {currentSong.PrettyFullName}\n\n" + desc; desc = $"`🔊` {currentSong.PrettyFullName}\n\n" + desc;
if (musicPlayer.RepeatSong) if (musicPlayer.RepeatSong)
@ -512,12 +513,13 @@ namespace NadekoBot.Modules.Music
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task MoveSong([Remainder] string fromto) public async Task MoveSong([Remainder] string fromto)
{ {
if (string.IsNullOrWhiteSpace(fromto))
return;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer)) if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
{
return; return;
}
fromto = fromto?.Trim(); fromto = fromto?.Trim();
var fromtoArr = fromto.Split('>'); var fromtoArr = fromto.Split('>');
@ -541,7 +543,7 @@ namespace NadekoBot.Modules.Music
var embed = new EmbedBuilder() var embed = new EmbedBuilder()
.WithTitle($"{s.SongInfo.Title.TrimTo(70)}") .WithTitle($"{s.SongInfo.Title.TrimTo(70)}")
.WithUrl($"{s.SongInfo.Query}") .WithUrl(s.SongUrl)
.WithAuthor(eab => eab.WithName("Song Moved").WithIconUrl("https://cdn.discordapp.com/attachments/155726317222887425/258605269972549642/music1.png")) .WithAuthor(eab => eab.WithName("Song Moved").WithIconUrl("https://cdn.discordapp.com/attachments/155726317222887425/258605269972549642/music1.png"))
.AddField(fb => fb.WithName("**From Position**").WithValue($"#{n1}").WithIsInline(true)) .AddField(fb => fb.WithName("**From Position**").WithValue($"#{n1}").WithIsInline(true))
.AddField(fb => fb.WithName("**To Position**").WithValue($"#{n2}").WithIsInline(true)) .AddField(fb => fb.WithName("**To Position**").WithValue($"#{n2}").WithIsInline(true))
@ -861,8 +863,7 @@ namespace NadekoBot.Modules.Music
textCh, textCh,
voiceCh, voiceCh,
relatedVideos[new NadekoRandom().Next(0, relatedVideos.Count)], relatedVideos[new NadekoRandom().Next(0, relatedVideos.Count)],
true, true).ConfigureAwait(false);
musicType).ConfigureAwait(false);
} }
} }
catch { } catch { }
@ -870,7 +871,11 @@ namespace NadekoBot.Modules.Music
mp.OnStarted += async (player, song) => mp.OnStarted += async (player, song) =>
{ {
try { await mp.UpdateSongDurationsAsync().ConfigureAwait(false); } catch { } try { await mp.UpdateSongDurationsAsync().ConfigureAwait(false); }
catch
{
// ignored
}
var sender = player as MusicPlayer; var sender = player as MusicPlayer;
if (sender == null) if (sender == null)
return; return;
@ -914,7 +919,10 @@ namespace NadekoBot.Modules.Music
await mp.OutputTextChannel.EmbedAsync(embed).ConfigureAwait(false); await mp.OutputTextChannel.EmbedAsync(embed).ConfigureAwait(false);
} }
catch { } catch
{
// ignored
}
}; };
return mp; return mp;
}); });
@ -945,10 +953,12 @@ namespace NadekoBot.Modules.Music
.WithThumbnailUrl(resolvedSong.Thumbnail) .WithThumbnailUrl(resolvedSong.Thumbnail)
.WithFooter(ef => ef.WithText(resolvedSong.PrettyProvider))) .WithFooter(ef => ef.WithText(resolvedSong.PrettyProvider)))
.ConfigureAwait(false); .ConfigureAwait(false);
if (queuedMessage != null) queuedMessage?.DeleteAfter(10);
queuedMessage.DeleteAfter(10);
} }
catch { } // if queued message sending fails, don't attempt to delete it catch
{
// ignored
} // if queued message sending fails, don't attempt to delete it
} }
} }
} }

View File

@ -94,7 +94,7 @@ namespace NadekoBot.Modules.Searches
using (var http = new HttpClient()) using (var http = new HttpClient())
{ {
var res = JObject.Parse(await http.GetStringAsync("http://www.random.cat/meow").ConfigureAwait(false)); var res = JObject.Parse(await http.GetStringAsync("http://www.random.cat/meow").ConfigureAwait(false));
await Context.Channel.SendMessageAsync(res["file"].ToString()).ConfigureAwait(false); await Context.Channel.SendMessageAsync(Uri.EscapeUriString(res["file"].ToString())).ConfigureAwait(false);
} }
} }
@ -273,7 +273,7 @@ namespace NadekoBot.Modules.Searches
var results = elems.Select<IElement, GoogleSearchResult?>(elem => var results = elems.Select<IElement, GoogleSearchResult?>(elem =>
{ {
var aTag = (elem.Children.FirstOrDefault().Children.FirstOrDefault() as IHtmlAnchorElement); // <h3> -> <a> var aTag = (elem.Children.FirstOrDefault()?.Children.FirstOrDefault() as IHtmlAnchorElement); // <h3> -> <a>
var href = aTag?.Href; var href = aTag?.Href;
var name = aTag?.TextContent; var name = aTag?.TextContent;
if (href == null || name == null) if (href == null || name == null)
@ -292,7 +292,7 @@ namespace NadekoBot.Modules.Searches
.WithAuthor(eab => eab.WithName("Search For: " + terms.TrimTo(50)) .WithAuthor(eab => eab.WithName("Search For: " + terms.TrimTo(50))
.WithUrl(fullQueryLink) .WithUrl(fullQueryLink)
.WithIconUrl("http://i.imgur.com/G46fm8J.png")) .WithIconUrl("http://i.imgur.com/G46fm8J.png"))
.WithTitle(Context.User.Mention) .WithTitle(Context.User.ToString())
.WithFooter(efb => efb.WithText(totalResults)); .WithFooter(efb => efb.WithText(totalResults));
var desc = await Task.WhenAll(results.Select(async res => var desc = await Task.WhenAll(results.Select(async res =>

View File

@ -8,13 +8,14 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.DataStructures;
namespace NadekoBot.Modules.Utility namespace NadekoBot.Modules.Utility
{ {
public partial class Utility public partial class Utility
{ {
[Group] [Group]
public class QuoteCommands : ModuleBase public class QuoteCommands : NadekoSubmodule
{ {
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
@ -56,6 +57,17 @@ namespace NadekoBot.Modules.Utility
if (quote == null) if (quote == null)
return; return;
CREmbed crembed;
if (CREmbed.TryParse(quote.Text, out crembed))
{
try { await Context.Channel.EmbedAsync(crembed.ToEmbed(), crembed.PlainText ?? "").ConfigureAwait(false); }
catch (Exception ex)
{
_log.Warn("Sending CREmbed failed");
_log.Warn(ex);
}
return;
}
await Context.Channel.SendMessageAsync("📣 " + quote.Text.SanitizeMentions()); await Context.Channel.SendMessageAsync("📣 " + quote.Text.SanitizeMentions());
} }

View File

@ -40,7 +40,7 @@ namespace NadekoBot.Services
private readonly CommandService _commandService; private readonly CommandService _commandService;
private readonly Logger _log; private readonly Logger _log;
private List<IDMChannel> ownerChannels { get; set; } private List<IDMChannel> ownerChannels { get; set; } = new List<IDMChannel>();
public event Func<SocketUserMessage, CommandInfo, Task> CommandExecuted = delegate { return Task.CompletedTask; }; public event Func<SocketUserMessage, CommandInfo, Task> CommandExecuted = delegate { return Task.CompletedTask; };
@ -61,12 +61,25 @@ namespace NadekoBot.Services
UsersOnShortCooldown.Clear(); UsersOnShortCooldown.Clear();
}, null, GlobalCommandsCooldown, GlobalCommandsCooldown); }, null, GlobalCommandsCooldown, GlobalCommandsCooldown);
} }
public async Task StartHandling() public Task StartHandling()
{ {
var _ = Task.Run(async () =>
{
await Task.Delay(5000).ConfigureAwait(false);
ownerChannels = (await Task.WhenAll(_client.GetGuilds().SelectMany(g => g.Users) ownerChannels = (await Task.WhenAll(_client.GetGuilds().SelectMany(g => g.Users)
.Where(u => NadekoBot.Credentials.OwnerIds.Contains(u.Id)) .Where(u => NadekoBot.Credentials.OwnerIds.Contains(u.Id))
.Distinct(new IGuildUserComparer()) .Distinct(new IGuildUserComparer())
.Select(async u => { try { return await u.CreateDMChannelAsync(); } catch { return null; } }))) .Select(async u =>
{
try
{
return await u.CreateDMChannelAsync();
}
catch
{
return null;
}
})))
.Where(ch => ch != null) .Where(ch => ch != null)
.ToList(); .ToList();
@ -74,8 +87,31 @@ namespace NadekoBot.Services
_log.Warn("No owner channels created! Make sure you've specified correct OwnerId in the credentials.json file."); _log.Warn("No owner channels created! Make sure you've specified correct OwnerId in the credentials.json file.");
else else
_log.Info($"Created {ownerChannels.Count} out of {NadekoBot.Credentials.OwnerIds.Count} owner message channels."); _log.Info($"Created {ownerChannels.Count} out of {NadekoBot.Credentials.OwnerIds.Count} owner message channels.");
});
_client.MessageReceived += MessageReceivedHandler; _client.MessageReceived += MessageReceivedHandler;
_client.MessageUpdated += (oldmsg, newMsg) =>
{
var ignore = Task.Run(async () =>
{
try
{
var usrMsg = newMsg as SocketUserMessage;
var guild = (usrMsg?.Channel as ITextChannel)?.Guild;
if (guild != null && !await InviteFiltered(guild, usrMsg).ConfigureAwait(false))
await WordFiltered(guild, usrMsg).ConfigureAwait(false);
}
catch (Exception ex)
{
_log.Warn(ex);
}
return Task.CompletedTask;
});
return Task.CompletedTask;
};
return Task.CompletedTask;
} }
private async Task<bool> TryRunCleverbot(SocketUserMessage usrMsg, IGuild guild) private async Task<bool> TryRunCleverbot(SocketUserMessage usrMsg, IGuild guild)