Replace nancy with kestrel

This commit is contained in:
runebaas 2018-05-14 02:33:49 +02:00
parent 3004b19209
commit 8c107de92e
No known key found for this signature in database
GPG key ID: 2677AF508D0300D6
13 changed files with 222 additions and 117 deletions

View file

@ -24,6 +24,7 @@
</PackageReference> </PackageReference>
<PackageReference Include="Google.Apis.YouTube.v3" Version="1.33.1.1217" /> <PackageReference Include="Google.Apis.YouTube.v3" Version="1.33.1.1217" />
<PackageReference Include="HtmlAgilityPack" Version="1.8.1" /> <PackageReference Include="HtmlAgilityPack" Version="1.8.1" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.2" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.2" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.0.2" /> <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.0.2" />
@ -34,8 +35,6 @@
<PackageReference Include="Microsoft.Extensions.Options" Version="2.0.2" /> <PackageReference Include="Microsoft.Extensions.Options" Version="2.0.2" />
<PackageReference Include="MtgApiManager.Lib" Version="1.1.0" /> <PackageReference Include="MtgApiManager.Lib" Version="1.1.0" />
<PackageReference Include="MyAnimeListSharp" Version="1.3.4" /> <PackageReference Include="MyAnimeListSharp" Version="1.3.4" />
<PackageReference Include="Nancy" Version="2.0.0-clinteastwood" />
<PackageReference Include="Nancy.Hosting.Self" Version="2.0.0-clinteastwood" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="NLog" Version="4.5.3" /> <PackageReference Include="NLog" Version="4.5.3" />
<PackageReference Include="NLog.Config" Version="4.5.3" /> <PackageReference Include="NLog.Config" Version="4.5.3" />
@ -43,9 +42,6 @@
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.Design" Version="1.1.1" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.Design" Version="1.1.1" />
<PackageReference Include="PokeApi.NET" Version="1.1.0" /> <PackageReference Include="PokeApi.NET" Version="1.1.0" />
<PackageReference Include="SharpRaven" Version="2.3.2" /> <PackageReference Include="SharpRaven" Version="2.3.2" />
<PackageReference Include="StackExchange.Redis">
<Version>1.2.6</Version>
</PackageReference>
<PackageReference Include="SumoLogic.Logging.NLog" Version="1.0.0.7" /> <PackageReference Include="SumoLogic.Logging.NLog" Version="1.0.0.7" />
<PackageReference Include="System.Net.Http" Version="4.3.3" /> <PackageReference Include="System.Net.Http" Version="4.3.3" />
<PackageReference Include="System.Runtime.Serialization.Formatters" Version="4.3.0" /> <PackageReference Include="System.Runtime.Serialization.Formatters" Version="4.3.0" />

View file

@ -19,9 +19,7 @@ using Geekbot.net.Lib.Logger;
using Geekbot.net.Lib.Media; using Geekbot.net.Lib.Media;
using Geekbot.net.Lib.ReactionListener; using Geekbot.net.Lib.ReactionListener;
using Geekbot.net.Lib.UserRepository; using Geekbot.net.Lib.UserRepository;
using Geekbot.net.WebApi;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Nancy.Hosting.Self;
using StackExchange.Redis; using StackExchange.Redis;
using WikipediaApi; using WikipediaApi;
@ -203,8 +201,7 @@ namespace Geekbot.net
{ {
_logger.Information(LogSource.Api, "Starting Webserver"); _logger.Information(LogSource.Api, "Starting Webserver");
var webApiUrl = new Uri($"http://{_runParameters.ApiHost}:{_runParameters.ApiPort}"); var webApiUrl = new Uri($"http://{_runParameters.ApiHost}:{_runParameters.ApiPort}");
var webConfig = new WebConfig(_logger, _commands); WebApi.WebApiStartup.StartWebApi(_logger, _runParameters, _commands);
new NancyHost(webConfig, webApiUrl).Start();
_logger.Information(LogSource.Api, $"Webserver now running on {webApiUrl}"); _logger.Information(LogSource.Api, $"Webserver now running on {webApiUrl}");
} }
} }

View file

@ -1,7 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Geekbot.net.WebApi.Help namespace Geekbot.net.WebApi.Controllers.Commands
{ {
public class CommandDto public class CommandDto
{ {

View file

@ -1,4 +1,4 @@
namespace Geekbot.net.WebApi.Help namespace Geekbot.net.WebApi.Controllers.Commands
{ {
public class CommandParamDto public class CommandParamDto
{ {

View file

@ -0,0 +1,41 @@
using System.Linq;
using Discord.Commands;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
namespace Geekbot.net.WebApi.Controllers.Commands
{
[EnableCors("AllowSpecificOrigin")]
public class HelpController : Controller
{
private readonly CommandService _commands;
public HelpController(CommandService commands)
{
_commands = commands;
}
[Route("/v1/commands")]
public IActionResult GetCommands()
{
var commandList = (from cmd in _commands.Commands
let cmdParamsObj = cmd.Parameters.Select(cmdParam => new CommandParamDto
{
Summary = cmdParam.Summary,
Default = cmdParam.DefaultValue?.ToString() ?? null,
Type = cmdParam.Type?.ToString()
})
.ToList()
let param = string.Join(", !", cmd.Aliases)
select new CommandDto
{
Name = cmd.Name,
Summary = cmd.Summary,
IsAdminCommand = (param.Contains("admin")),
Aliases = cmd.Aliases.ToArray(),
Params = cmdParamsObj
}).ToList();
return Ok(commandList);
}
}
}

View file

@ -1,4 +1,4 @@
namespace Geekbot.net.WebApi.Status namespace Geekbot.net.WebApi.Controllers.Status
{ {
public class ApiStatusDto public class ApiStatusDto
{ {

View file

@ -0,0 +1,22 @@
using Geekbot.net.Lib;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
namespace Geekbot.net.WebApi.Controllers.Status
{
[EnableCors("AllowSpecificOrigin")]
public class StatusController : Controller
{
[Route("/")]
public IActionResult GetCommands()
{
var responseBody = new ApiStatusDto
{
GeekbotVersion = Constants.BotVersion(),
ApiVersion = Constants.ApiVersion.ToString(),
Status = "Online"
};
return Ok(responseBody);
}
}
}

View file

@ -1,44 +0,0 @@
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Discord.Commands;
using Nancy;
namespace Geekbot.net.WebApi.Help
{
public sealed class HelpController : NancyModule
{
public HelpController(CommandService commands)
{
Get("/v1/commands", args =>
{
var commandList = (from cmd in commands.Commands
let cmdParamsObj = cmd.Parameters.Select(cmdParam => new CommandParamDto
{
Summary = cmdParam.Summary,
Default = cmdParam.DefaultValue?.ToString() ?? null,
Type = cmdParam.Type?.ToString()
})
.ToList()
let param = string.Join(", !", cmd.Aliases)
select new CommandDto
{
Name = cmd.Name,
Summary = cmd.Summary,
IsAdminCommand = (param.Contains("admin")),
Aliases = cmd.Aliases.ToArray(),
Params = cmdParamsObj
}).ToList();
return Response.AsJson(commandList);
});
}
private async Task<CommandService> GetCommands()
{
var commands = new CommandService();
await commands.AddModulesAsync(Assembly.GetEntryAssembly());
return commands;
}
}
}

View file

@ -0,0 +1,29 @@
using System;
using System.Collections.Concurrent;
using Geekbot.net.Lib.Logger;
using Microsoft.Extensions.Logging;
namespace Geekbot.net.WebApi.Logging
{
public class AspLogProvider : ILoggerProvider
{
private readonly IGeekbotLogger _geekbotLogger;
private readonly ConcurrentDictionary<string, AspLogger> _loggers = new ConcurrentDictionary<string, AspLogger>();
public AspLogProvider(IGeekbotLogger geekbotLogger)
{
_geekbotLogger = geekbotLogger;
}
public void Dispose()
{
_loggers.Clear();
}
public ILogger CreateLogger(string categoryName)
{
return _loggers.GetOrAdd(categoryName, name => new AspLogger(categoryName, _geekbotLogger));
}
}
}

View file

@ -0,0 +1,75 @@
using System;
using Geekbot.net.Lib.Logger;
using Microsoft.Extensions.Logging;
namespace Geekbot.net.WebApi.Logging
{
public class AspLogger : ILogger
{
private readonly string _categoryName;
private readonly IGeekbotLogger _geekbotLogger;
public AspLogger(string categoryName, IGeekbotLogger geekbotLogger)
{
geekbotLogger.Trace(LogSource.Api, $"Adding {categoryName}");
_categoryName = categoryName;
_geekbotLogger = geekbotLogger;
}
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
switch (logLevel)
{
case LogLevel.Trace:
_geekbotLogger.Trace(LogSource.Api, $"{eventId.Id} - {_categoryName} - {state}");
break;
case LogLevel.Debug:
_geekbotLogger.Debug(LogSource.Api, $"{eventId.Id} - {_categoryName} - {state}");
break;
case LogLevel.Information:
_geekbotLogger.Information(LogSource.Api, $"{eventId.Id} - {_categoryName} - {state}");
break;
case LogLevel.Warning:
_geekbotLogger.Warning(LogSource.Api, $"{eventId.Id} - {_categoryName} - {state}", exception);
break;
case LogLevel.Error:
case LogLevel.Critical:
_geekbotLogger.Error(LogSource.Api, $"{eventId.Id} - {_categoryName} - {state}", exception);
break;
default:
throw new ArgumentOutOfRangeException(nameof(logLevel));
}
}
public bool IsEnabled(LogLevel logLevel)
{
return !_geekbotLogger.LogAsJson() && _geekbotLogger.GetNLogger().IsEnabled(ToGeekbotLogLevel(logLevel));
}
public IDisposable BeginScope<TState>(TState state)
{
return null;
}
private static NLog.LogLevel ToGeekbotLogLevel(LogLevel level)
{
switch (level)
{
case LogLevel.Trace:
return NLog.LogLevel.Trace;
case LogLevel.Debug:
return NLog.LogLevel.Debug;
case LogLevel.Information:
return NLog.LogLevel.Info;
case LogLevel.Warning:
return NLog.LogLevel.Warn;
case LogLevel.Error:
return NLog.LogLevel.Error;
case LogLevel.Critical:
return NLog.LogLevel.Fatal;
default:
throw new ArgumentOutOfRangeException(nameof(level));
}
}
}
}

View file

@ -1,22 +0,0 @@
using Geekbot.net.Lib;
using Nancy;
namespace Geekbot.net.WebApi.Status
{
public sealed class StatusController : NancyModule
{
public StatusController()
{
Get("/", args =>
{
var responseBody = new ApiStatusDto
{
GeekbotVersion = Constants.BotVersion(),
ApiVersion = Constants.ApiVersion.ToString(),
Status = "Online"
};
return Response.AsJson(responseBody);
});
}
}
}

View file

@ -0,0 +1,50 @@
using System;
using System.Net;
using System.Reflection;
using Discord.Commands;
using Geekbot.net.Lib;
using Geekbot.net.Lib.Logger;
using Geekbot.net.WebApi.Logging;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Geekbot.net.WebApi
{
public class WebApiStartup
{
public static void StartWebApi(IGeekbotLogger logger, RunParameters runParameters, CommandService commandService)
{
WebHost.CreateDefaultBuilder()
.UseKestrel(options =>
{
options.Listen(IPAddress.Any, int.Parse(runParameters.ApiPort));
})
.ConfigureServices(services =>
{
services.AddMvc();
services.AddSingleton<CommandService>(commandService);
services.AddCors(options =>
{
options.AddPolicy("AllowSpecificOrigin",
builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
});
})
.Configure(app =>
{
app.UseMvc();
app.UseCors(builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().Build());
})
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.SetMinimumLevel(LogLevel.Debug);
logging.AddProvider(new AspLogProvider(logger));
})
.UseSetting(WebHostDefaults.ApplicationKey, typeof(Program).GetTypeInfo().Assembly.FullName)
.Build().Run();
}
}
}

View file

@ -1,39 +0,0 @@
using System.Diagnostics;
using Discord.Commands;
using Geekbot.net.Lib.Logger;
using Nancy;
using Nancy.Bootstrapper;
using Nancy.TinyIoc;
namespace Geekbot.net.WebApi
{
public class WebConfig : DefaultNancyBootstrapper
{
private readonly GeekbotLogger _logger;
private readonly CommandService _commands;
public WebConfig(GeekbotLogger logger, CommandService commands)
{
_logger = logger;
_commands = commands;
}
protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)
{
// Register Dependencies
container.Register<IGeekbotLogger>(_logger);
container.Register<CommandService>(_commands);
// Enable CORS
pipelines.AfterRequest.AddItemToEndOfPipeline(ctx =>
{
_logger.Information(LogSource.Api, ctx.Request.Path.ToString());
ctx.Response.WithHeader("Access-Control-Allow-Origin", "*")
.WithHeader("Access-Control-Allow-Methods", "GET")
.WithHeader("Access-Control-Allow-Headers", "Accept, Origin, Content-type")
.WithHeader("Last-Modified", Process.GetCurrentProcess().StartTime.ToString());
});
}
}
}