Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add commands for Naka-Kon #18

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions MajorInteractiveBot/MajorBot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,12 @@
using MajorInteractiveBot.Modules;
using MajorInteractiveBot.TypeReaders;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

Expand Down
1 change: 1 addition & 0 deletions MajorInteractiveBot/MajorInteractiveBot.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<PackageReference Include="Discord.Addons.PassiveInteractive" Version="2.0.4" />
<PackageReference Include="Discord.Net" Version="2.1.1" />
<PackageReference Include="Humanizer.Core" Version="2.7.9" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="3.0.0" />
Expand Down
69 changes: 25 additions & 44 deletions MajorInteractiveBot/Modules/AnimalModule.cs
Original file line number Diff line number Diff line change
@@ -1,33 +1,34 @@
using Discord;
using Discord.Commands;
using MajorInteractiveBot.Attributes;
using MajorInteractiveBot.Services.ImageService;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

namespace MajorInteractiveBot.Modules
{
[Name("Animal")]
[Summary("A collection of commands for displaying animals of the specified type.")]
[Module]
public class AnimalModule : ModuleBase
public sealed class AnimalModule : ModuleBase
{
private readonly ILogger<AnimalModule> Log;
private readonly IServiceProvider _services;
private readonly ILogger Log;
private readonly ImageService _imageService;

public AnimalModule(IServiceProvider services)
public AnimalModule(ILogger<AnimalModule> logger, ImageService imageService)
{
_services = services;
Log = services.GetRequiredService<ILogger<AnimalModule>>();
Log = logger;
_imageService = imageService;
}

private const string FindBird = "https://random.birb.pw/tweet/";
private const string BirdPicture = "https://random.birb.pw/img/{0}";

private const string CatPicture = "https://api.thecatapi.com/v1/images/search";

[Command("bird")]
Expand All @@ -36,65 +37,45 @@ public AnimalModule(IServiceProvider services)
[RequireCommandChannel]
public async Task ShowBird()
{
string location = await GetAsync(FindBird);
var message = await ReplyAsync("Searching for a bird...");
var result = await _imageService.FromBodyAsync(FindBird, BirdPicture);

await ShowPicture("bird", string.Format(BirdPicture, location));
await ShowPictureAsync(message, result);
}

[Command("cat")]
[Summary("Show a random cat")]
[RequireCommandChannel]
public async Task ShowCat()
{
string location = await GetJsonAsync(CatPicture, "url");
await ShowPicture("cat", location);
}

private async Task<string> GetJsonAsync(string uri, string key)
{
string json = await GetAsync(uri);
// string location = await GetJsonAsync(CatPicture, "url");
// await ShowPicture("cat", location);

var jArray = JArray.Parse(json);
var jToken = jArray.First;
var message = await ReplyAsync("Searching for a cat...");
var result = await _imageService.FromJsonAsync(CatPicture, "url");

return jToken.Value<string>(key);
await ShowPictureAsync(message, result);
}

private async Task ShowPicture(string type, string uri)
private async Task ShowPictureAsync(IUserMessage message, ImageUrlResult result)
{
var message = await ReplyAsync($"Searching for a {type}...");
try
if (result.IsSuccess)
{
var imageEmbed = EmbedFromImage(uri);
var embed = new EmbedBuilder().WithUrl(result.Result);

await message.ModifyAsync(msg =>
{
msg.Content = "Found one!";
msg.Embed = imageEmbed.Build();
msg.Embed = embed.Build();
});
}
catch (Exception ex)
{
Log.LogCritical(ex, "Image lookup failed.");
}
}

private async Task<string> GetAsync(string uri)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;

using (HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
else
{
return await reader.ReadToEndAsync();
await message.ModifyAsync(msg =>
{
msg.Content = "Image lookup failed.";
});
}
}

private EmbedBuilder EmbedFromImage(string imageUrl)
{
return new EmbedBuilder().WithImageUrl(imageUrl);
}
}
}
105 changes: 105 additions & 0 deletions MajorInteractiveBot/Modules/FunModule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Discord;
using Discord.Commands;
using MajorInteractiveBot.Attributes;
using MajorInteractiveBot.Services.ImageService;
using MajorInteractiveBot.Utilities;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace MajorInteractiveBot.Modules
{
[Name("Fun")]
[Summary("Provides miscelaneous fun commands")]
[Module]
public sealed class FunModule : ModuleBase
{
private readonly IMemoryCache _memoryCache;
private readonly ILogger _logger;
private readonly ImageService _imageService;


private const string xkcdPath = "https://xkcd.com/info.0.json";
private const string xkcdSpecificPath = "https://xkcd.com/{0}/info.0.json";
private const string xkcdMemoryKey = "kxcdLatest";
private const int defaultXkcdMax = 2100;
public const string Empty = "";

public FunModule(IMemoryCache memoryCache, ILogger<FunModule> logger, ImageService imageService)
{
_memoryCache = memoryCache;
_logger = logger;
_imageService = imageService;
}

[Command("8ball")]
[Summary("Answers a yes or no question")]
public async Task EightBall([Remainder] string question = "")
{
// get random responses and reply with them
// ThrowHelper.ThrowNotImplementedException();

}

[Command("trapcard")]
[Summary("Turn the tables with your ultimate Yu-Gi-Oh trap card!")]
public async Task TrapCard()
{
ThrowHelper.ThrowNotImplementedException();
}

[Command("xkcd"), Summary("Posts a random xkcd article")]
public async Task PostRandomXkcd()
{
var latestComicId = await _memoryCache.GetOrCreateAsync(xkcdMemoryKey, GetLatestComicId);

var random = new Random();

await PostXkcd(random.Next(1, latestComicId));
}

[Command("xkcd"), Summary("Posts the specified xkcd article")]
public async Task PostXkcd([Summary("The zero-based Id of the article you're trying to get.")] int id)
{
string jsonUrl = string.Format(xkcdSpecificPath, id);
ImageUrlResult result = await _imageService.FromJsonAsync(jsonUrl, "img");

if (result.IsSuccess)
{
var embedBuilder = new EmbedBuilder()
.WithImageUrl(result.Result)
.WithAuthor(Context.User)
.WithCurrentTimestamp();

await ReplyAsync(embed: embedBuilder.Build());
}
else
{
await ReplyAsync("Could not find the image specified.");
}
}

/// <summary>
/// Retrieves the latest XKCD comic id
/// </summary>
private async Task<int> GetLatestComicId(ICacheEntry cache)
{
IResult<string> latestResult = await _imageService.FromJsonAsync(xkcdPath, "num");

if (!(latestResult.IsSuccess && int.TryParse(latestResult.Result, out int latest)))
{
latest = defaultXkcdMax;
}

cache.SetValue(latest);
return latest;
}
}
}
2 changes: 1 addition & 1 deletion MajorInteractiveBot/Modules/GuildModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ async Task<string> GetCommandChannels()
{
IsInline = false,
Name = "Current Command Channels",
Value = GetCommandChannels()
Value = await GetCommandChannels()
}
},
Color = Color.Green
Expand Down
13 changes: 8 additions & 5 deletions MajorInteractiveBot/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Net.Http;
using System.IO;

namespace MajorInteractiveBot
{
Expand All @@ -29,8 +31,8 @@ public static async Task<int> Main()
.ConfigureAppConfiguration((ctx, builder) =>
{
builder.AddEnvironmentVariables("MAJOR_");
builder.AddJsonFile("appsettings.json");
builder.AddJsonFile($"appsettings.{ctx.HostingEnvironment.EnvironmentName}.json", true);
builder.AddJsonFile("appsettings.json", true);
builder.AddJsonFile($"appsettings.{ctx.HostingEnvironment.EnvironmentName}.json", true);

Debug.WriteLine(ctx.HostingEnvironment.EnvironmentName);

Expand All @@ -43,9 +45,8 @@ public static async Task<int> Main()
{
var logMinimum = new Serilog.Core.LoggingLevelSwitch(ctx.HostingEnvironment.IsDevelopment() ? LogEventLevel.Debug : LogEventLevel.Information);
var seriLogger = new LoggerConfiguration()
.MinimumLevel.ControlledBy(logMinimum)
.WriteTo.Console()
.WriteTo.RollingFile(@"logs\{date}", restrictedToMinimumLevel: LogEventLevel.Debug)
.WriteTo.Console(levelSwitch: logMinimum)
.WriteTo.RollingFile(Path.Combine("logs", "{Date}"), restrictedToMinimumLevel: LogEventLevel.Debug)
.CreateLogger();

builder.AddSerilog(seriLogger);
Expand All @@ -59,11 +60,13 @@ public static async Task<int> Main()
// options.UseSqlite(context.Configuration.GetValue<string>(nameof(MajorConfig.DbConnection)));
options.UseNpgsql(context.Configuration.GetConnectionString("MajorDb"));
})
.AddMemoryCache()
.AddSingleton<DiscordSocketClient>()
.AddSingleton<CommandService>()
.AddSingleton<CommandHandler>()
.AddSingleton<InteractiveService>()
.AddSingleton<ICommandHelpService, CommandHelpService>()
.AddSingleton<HttpClient>()

.AddHostedService<MajorBot>();
});
Expand Down
Loading