Merge branch 'refactoring' into 'master'

Refactoring

See merge request open/Geekbot.net!12
This commit is contained in:
Daan 2018-05-04 21:37:57 +00:00
commit 26a0c89cf7
18 changed files with 245 additions and 29 deletions

View file

@ -47,7 +47,7 @@ namespace Geekbot.net.Commands.Admin
catch (Exception e)
{
_errorHandler.HandleCommandException(e, Context,
$"I don't have enough permissions to give {user.Username} that role");
$"I don't have enough permissions do that");
}
}

View file

@ -0,0 +1,101 @@
using System;
using System.Threading.Tasks;
using Discord;
using Discord.Commands;
using Geekbot.net.Lib.Audio;
using Geekbot.net.Lib.ErrorHandling;
namespace Geekbot.net.Commands.Audio
{
public class Voice : ModuleBase
{
private readonly IAudioUtils _audioUtils;
private readonly IErrorHandler _errorHandler;
public Voice(IErrorHandler errorHandler, IAudioUtils audioUtils)
{
_errorHandler = errorHandler;
_audioUtils = audioUtils;
}
// [Command("join")]
public async Task JoinChannel()
{
try
{
// Get the audio channel
var channel = (Context.User as IGuildUser)?.VoiceChannel;
if (channel == null)
{
await Context.Channel.SendMessageAsync("You must be in a voice channel.");
return;
}
var audioClient = await channel.ConnectAsync();
_audioUtils.StoreAudioClient(Context.Guild.Id, audioClient);
await ReplyAsync($"Connected to {channel.Name}");
}
catch (Exception e)
{
_errorHandler.HandleCommandException(e, Context);
}
}
// [Command("disconnect")]
public async Task DisconnectChannel()
{
try
{
var audioClient = _audioUtils.GetAudioClient(Context.Guild.Id);
if (audioClient == null)
{
await Context.Channel.SendMessageAsync("I'm not in a voice channel at the moment");
return;
}
await audioClient.StopAsync();
await ReplyAsync("Disconnected from channel!");
_audioUtils.Cleanup(Context.Guild.Id);
}
catch (Exception e)
{
_errorHandler.HandleCommandException(e, Context);
_audioUtils.Cleanup(Context.Guild.Id);
}
}
// [Command("ytplay")]
public async Task ytplay(string url)
{
try
{
if (!url.Contains("youtube"))
{
await ReplyAsync("I can only play youtube videos");
return;
}
var audioClient = _audioUtils.GetAudioClient(Context.Guild.Id);
if (audioClient == null)
{
await ReplyAsync("I'm not in a voice channel at the moment");
return;
}
var message = await Context.Channel.SendMessageAsync("Just a second, i'm still a bit slow at this");
var ffmpeg = _audioUtils.CreateStreamFromYoutube(url, Context.Guild.Id);
var output = ffmpeg.StandardOutput.BaseStream;
await message.ModifyAsync(msg => msg.Content = "**Playing!** Please note that this feature is experimental");
var discord = audioClient.CreatePCMStream(Discord.Audio.AudioApplication.Mixed);
await output.CopyToAsync(discord);
await discord.FlushAsync();
_audioUtils.Cleanup(Context.Guild.Id);
}
catch (Exception e)
{
_errorHandler.HandleCommandException(e, Context);
_audioUtils.Cleanup(Context.Guild.Id);
}
}
}
}

View file

@ -6,8 +6,8 @@ using Discord;
using Discord.Commands;
using Geekbot.net.Lib;
using Geekbot.net.Lib.ErrorHandling;
using Newtonsoft.Json;
using StackExchange.Redis;
using Utf8Json;
namespace Geekbot.net.Commands.Integrations.Google
{
@ -40,7 +40,7 @@ namespace Geekbot.net.Commands.Integrations.Google
var url = new Uri($"https://kgsearch.googleapis.com/v1/entities:search?languages=en&limit=1&query={searchText}&key={apiKey}");
var responseString = client.DownloadString(url);
var response = JsonSerializer.Deserialize<GoogleKgApiResponseDto>(responseString);
var response = JsonConvert.DeserializeObject<GoogleKgApiResponseDto>(responseString);
if (!response.ItemListElement.Any())
{
@ -48,13 +48,13 @@ namespace Geekbot.net.Commands.Integrations.Google
return;
}
var data = response.ItemListElement.First().ResultDto;
var data = response.ItemListElement.First().Result;
var eb = new EmbedBuilder();
eb.Title = data.Name;
if(!string.IsNullOrEmpty(data.Description)) eb.WithDescription(data.Description);
if(!string.IsNullOrEmpty(data.DetailedDtoDescription?.Url)) eb.WithUrl(data.DetailedDtoDescription.Url);
if(!string.IsNullOrEmpty(data.DetailedDtoDescription?.ArticleBody)) eb.AddField("Details", data.DetailedDtoDescription.ArticleBody);
if(!string.IsNullOrEmpty(data.ImageDto?.ContentUrl)) eb.WithThumbnailUrl(data.ImageDto.ContentUrl);
if(!string.IsNullOrEmpty(data.Image?.ContentUrl)) eb.WithThumbnailUrl(data.Image.ContentUrl);
await ReplyAsync("", false, eb.Build());
}

View file

@ -2,7 +2,7 @@
{
public class GoogleKgApiElementDto
{
public GoogleKgApiResultDto ResultDto { get; set; }
public GoogleKgApiResultDto Result { get; set; }
public double ResultScore { get; set; }
}
}

View file

@ -4,7 +4,7 @@
{
public string Name { get; set; }
public string Description { get; set; }
public GoogleKgApiImageDto ImageDto { get; set; }
public GoogleKgApiImageDto Image { get; set; }
public GoogleKgApiDetailedDto DetailedDtoDescription { get; set; }
}
}

View file

@ -12,7 +12,7 @@ using Geekbot.net.Lib.Logger;
using Geekbot.net.Lib.UserRepository;
using StackExchange.Redis;
namespace Geekbot.net.Commands.User.Rank
namespace Geekbot.net.Commands.User.Ranking
{
public class Rank : ModuleBase
{
@ -37,8 +37,7 @@ namespace Geekbot.net.Commands.User.Rank
[Command("rank", RunMode = RunMode.Async)]
[Remarks(CommandCategories.Statistics)]
[Summary("get user top 10 in messages or karma")]
public async Task RankCmd([Summary("type")] string typeUnformated = "messages",
[Summary("amount")] int amount = 10)
public async Task RankCmd([Summary("type")] string typeUnformated = "messages", [Summary("amount")] int amount = 10)
{
try
{

View file

@ -1,4 +1,4 @@
namespace Geekbot.net.Commands.User.Rank
namespace Geekbot.net.Commands.User.Ranking
{
internal class RankUserPolyfillDto
{

View file

@ -52,7 +52,7 @@ namespace Geekbot.net.Commands.Utils.Changelog
});
var sb = new StringBuilder();
foreach (var commit in commits.Take(10))
sb.AppendLine($"- {commit.Commit.Message} ({commit.Commit.AuthorDto.Date:yyyy-MM-dd})");
sb.AppendLine($"- {commit.Commit.Message} ({commit.Commit.Author.Date:yyyy-MM-dd})");
eb.Description = sb.ToString();
eb.WithFooter(new EmbedFooterBuilder
{

View file

@ -2,8 +2,10 @@
namespace Geekbot.net.Commands.Utils.Changelog
{
internal class CommitAuthorDto
public class CommitAuthorDto
{
public string Name { get; set; }
public string Email { get; set; }
public DateTimeOffset Date { get; set; }
}
}

View file

@ -1,6 +1,6 @@
namespace Geekbot.net.Commands.Utils.Changelog
{
internal class CommitDto
public class CommitDto
{
public CommitInfoDto Commit { get; set; }
}

View file

@ -1,8 +1,8 @@
namespace Geekbot.net.Commands.Utils.Changelog
{
internal class CommitInfoDto
public class CommitInfoDto
{
public CommitAuthorDto AuthorDto { get; set; }
public CommitAuthorDto Author { get; set; }
public string Message { get; set; }
}
}

View file

@ -3,7 +3,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
<ApplicationIcon>derp.ico</ApplicationIcon>
<Version>3.6.0</Version>
<Version>3.7.0</Version>
<Company>Pizza and Coffee Studios</Company>
<Authors>Pizza and Coffee Studios</Authors>
<Description>A Discord bot</Description>

View file

@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using Discord.Audio;
namespace Geekbot.net.Lib.Audio
{
public class AudioUtils : IAudioUtils
{
private string _tempFolderPath;
private Dictionary<ulong, IAudioClient> _audioClients;
public AudioUtils()
{
_audioClients = new Dictionary<ulong, IAudioClient>();
_tempFolderPath = Path.GetFullPath("./tmp/");
if (Directory.Exists(_tempFolderPath))
{
Directory.Delete(_tempFolderPath, true);
}
Directory.CreateDirectory(_tempFolderPath);
}
public IAudioClient GetAudioClient(ulong guildId)
{
return _audioClients[guildId];
}
public void StoreAudioClient(ulong guildId, IAudioClient client)
{
_audioClients[guildId] = client;
}
public Process CreateStreamFromFile(string path)
{
var ffmpeg = new ProcessStartInfo
{
FileName = "ffmpeg",
Arguments = $"-i {path} -ac 2 -f s16le -ar 48000 pipe:1",
UseShellExecute = false,
RedirectStandardOutput = true,
};
return Process.Start(ffmpeg);
}
public Process CreateStreamFromYoutube(string url, ulong guildId)
{
var ytdlMediaUrl = GetYoutubeMediaUrl(url);
DownloadMediaUrl(ytdlMediaUrl, guildId);
return CreateStreamFromFile($"{_tempFolderPath}{guildId}");
}
public void Cleanup(ulong guildId)
{
File.Delete($"{_tempFolderPath}{guildId}");
}
private string GetYoutubeMediaUrl(string url)
{
var ytdl = new ProcessStartInfo()
{
FileName = "youtube-dl",
Arguments = $"-f bestaudio -g {url}",
UseShellExecute = false,
RedirectStandardOutput = true
};
var output = Process.Start(ytdl).StandardOutput.ReadToEnd();
if (string.IsNullOrWhiteSpace(output))
{
throw new Exception("Could not get Youtube Media URL");
}
return output;
}
private void DownloadMediaUrl(string url, ulong guildId)
{
using (var web = new WebClient())
{
web.DownloadFile(url, $"{_tempFolderPath}{guildId}");
}
// var ffmpeg = new ProcessStartInfo
// {
// FileName = "ffmpeg",
// Arguments = $"-i \"{_tempFolderPath}{guildId}\" -c:a mp3 -b:a 256k {_tempFolderPath}{guildId}.mp3",
// UseShellExecute = false,
// RedirectStandardOutput = true,
// };
// Process.Start(ffmpeg).WaitForExit();
// File.Delete($"{_tempFolderPath}{guildId}");
return;
}
}
}

View file

@ -0,0 +1,15 @@
using System.Diagnostics;
using Discord.Audio;
namespace Geekbot.net.Lib.Audio
{
public interface IAudioUtils
{
IAudioClient GetAudioClient(ulong guildId);
void StoreAudioClient(ulong guildId, IAudioClient client);
Process CreateStreamFromFile(string path);
Process CreateStreamFromYoutube(string url, ulong guildId);
void Cleanup(ulong guildId);
}
}

View file

@ -3,7 +3,7 @@
public class Constants
{
public const string Name = "Geekbot";
public const double BotVersion = 3.6;
public const double BotVersion = 3.7;
public const double ApiVersion = 1;
}
}

View file

@ -23,7 +23,7 @@ namespace Geekbot.net.Lib.Logger
public void Trace(string source, string message, object extra = null)
{
_logger.Trace(CreateLogString("Debug", source, message, null, extra));
_logger.Trace(CreateLogString("Trace", source, message, null, extra));
}
public void Debug(string source, string message, object extra = null)
@ -43,7 +43,7 @@ namespace Geekbot.net.Lib.Logger
public void Error(string source, string message, Exception stackTrace, object extra = null)
{
_logger.Error(stackTrace, CreateLogString("Error", source, message, stackTrace, extra));
_logger.Error(CreateLogString("Error", source, message, stackTrace, extra));
}
private string CreateLogString(string type, string source, string message, Exception stackTrace = null, object extra = null)
@ -65,7 +65,7 @@ namespace Geekbot.net.Lib.Logger
if (source != "Message") return $"[{source}] - {message}";
var m = (MessageDto) extra;
return $"[{source}] - [{m.Guild.Name} - {m.Channel.Name}] {m.User.Name}: {m.Message.Content}";
return $"[{source}] - [{m?.Guild.Name} - {m?.Channel.Name}] {m?.User.Name}: {m?.Message.Content}";
}
}
}

View file

@ -17,13 +17,13 @@ namespace Geekbot.net.Lib.Logger
{
Console.WriteLine("Logging Geekbot Logs to Sumologic");
config.LoggingRules.Add(
new LoggingRule("*", LogLevel.Info, LogLevel.Fatal,
new LoggingRule("*", LogLevel.Debug, LogLevel.Fatal,
new BufferedSumoLogicTarget()
{
Url = Environment.GetEnvironmentVariable("GEEKBOT_SUMO"),
SourceName = "GeekbotLogger",
Layout = "${message}",
UseConsoleLog = false,
UseConsoleLog = true,
MaxQueueSizeBytes = 500000,
FlushingAccuracy = 250,
MaxFlushInterval = 10000,
@ -38,11 +38,11 @@ namespace Geekbot.net.Lib.Logger
{
var minLevel = runParameters.Verbose ? LogLevel.Trace : LogLevel.Info;
config.LoggingRules.Add(
new LoggingRule("*", minLevel, LogLevel.Fatal,
new LoggingRule("*", LogLevel.Info, LogLevel.Fatal,
new ColoredConsoleTarget
{
Name = "Console",
Encoding = Encoding.Unicode,
Encoding = Encoding.UTF8,
Layout = "[${longdate} ${level:format=FirstCharacter}] ${message} ${exception:format=toString}"
})
);
@ -53,7 +53,7 @@ namespace Geekbot.net.Lib.Logger
{
Name = "File",
Layout = "[${longdate} ${level}] ${message}",
Encoding = Encoding.Unicode,
Encoding = Encoding.UTF8,
LineEnding = LineEndingMode.Default,
MaxArchiveFiles = 30,
ArchiveNumbering = ArchiveNumberingMode.Date,

View file

@ -8,6 +8,7 @@ using Discord;
using Discord.Commands;
using Discord.WebSocket;
using Geekbot.net.Lib;
using Geekbot.net.Lib.Audio;
using Geekbot.net.Lib.Clients;
using Geekbot.net.Lib.Converters;
using Geekbot.net.Lib.ErrorHandling;
@ -113,10 +114,11 @@ namespace Geekbot.net
var emojiConverter = new EmojiConverter();
var mtgManaConverter = new MtgManaConverter();
var wikipediaClient = new WikipediaClient();
var audioUtils = new AudioUtils();
_services.AddSingleton(_redis);
_services.AddSingleton(logger);
_services.AddSingleton(_userRepository);
_services.AddSingleton<IDatabase>(_redis);
_services.AddSingleton<IUserRepository>(_userRepository);
_services.AddSingleton<IGeekbotLogger>(logger);
_services.AddSingleton<ILevelCalc>(levelCalc);
_services.AddSingleton<IEmojiConverter>(emojiConverter);
_services.AddSingleton<IFortunesProvider>(fortunes);
@ -124,6 +126,7 @@ namespace Geekbot.net
_services.AddSingleton<IMalClient>(malClient);
_services.AddSingleton<IMtgManaConverter>(mtgManaConverter);
_services.AddSingleton<IWikipediaClient>(wikipediaClient);
_services.AddSingleton<IAudioUtils>(audioUtils);
logger.Information("Geekbot", "Connecting to Discord");