NadekoBot/src/NadekoBot/NadekoBot.cs

295 lines
12 KiB
C#
Raw Normal View History

2016-08-15 14:57:40 +00:00
using Discord;
using Discord.Commands;
2016-08-13 18:45:08 +00:00
using Discord.WebSocket;
2016-08-15 14:57:40 +00:00
using NadekoBot.Services;
using NadekoBot.Services.Impl;
2016-08-18 21:00:54 +00:00
using NLog;
using NLog.Config;
using NLog.Targets;
2016-08-13 18:45:08 +00:00
using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using NadekoBot.Modules.Permissions;
using NadekoBot.TypeReaders;
2017-02-14 14:53:51 +00:00
using System.Collections.Immutable;
using System.Diagnostics;
2016-10-26 14:30:49 +00:00
using NadekoBot.Services.Database.Models;
2017-04-15 00:54:19 +00:00
using System.Threading;
2017-05-22 23:59:31 +00:00
using NadekoBot.Services.Searches;
2017-05-24 04:43:00 +00:00
using NadekoBot.Services.ClashOfClans;
using NadekoBot.Services.Music;
2017-05-25 02:24:43 +00:00
using NadekoBot.Services.CustomReactions;
2017-05-27 08:19:27 +00:00
using NadekoBot.Services.Games;
using NadekoBot.Services.Administration;
using NadekoBot.Services.Permissions;
using NadekoBot.Services.Utility;
using NadekoBot.Services.Help;
2016-08-13 18:45:08 +00:00
namespace NadekoBot
{
public class NadekoBot
{
2016-08-18 21:00:54 +00:00
private Logger _log;
2017-05-22 23:59:31 +00:00
/* I don't know how to make this not be static
* and keep the convenience of .WithOkColor
* and .WithErrorColor extensions methods.
* I don't want to pass botconfig every time I
* want to send a confirm or error message, so
* I'll keep this for now */
public static Color OkColor { get; private set; }
public static Color ErrorColor { get; private set; }
2017-05-22 23:59:31 +00:00
//todo placeholder, will be guild-based
public static string Prefix { get; } = ".";
2017-05-22 23:59:31 +00:00
public ImmutableArray<GuildConfig> AllGuildConfigs { get; }
public BotConfig BotConfig { get; }
public DbService Db { get; }
public CommandService CommandService { get; }
2016-09-15 15:31:02 +00:00
2017-05-22 23:59:31 +00:00
public DiscordShardedClient Client { get; }
public bool Ready { get; private set; }
2016-10-26 14:30:49 +00:00
public INServiceProvider Services { get; private set; }
public BotCredentials Credentials { get; }
2017-05-10 14:08:31 +00:00
2017-05-22 23:59:31 +00:00
public NadekoBot()
2016-10-26 14:30:49 +00:00
{
2016-11-15 09:54:56 +00:00
SetupLogger();
2017-05-22 23:59:31 +00:00
_log = LogManager.GetCurrentClassLogger();
2016-11-15 09:54:56 +00:00
Credentials = new BotCredentials();
Db = new DbService(Credentials);
using (var uow = Db.UnitOfWork)
2016-10-26 14:30:49 +00:00
{
2017-02-14 14:53:51 +00:00
AllGuildConfigs = uow.GuildConfigs.GetAllGuildConfigs().ToImmutableArray();
2017-01-12 00:21:32 +00:00
BotConfig = uow.BotConfig.GetOrCreate();
OkColor = new Color(Convert.ToUInt32(BotConfig.OkColor, 16));
ErrorColor = new Color(Convert.ToUInt32(BotConfig.ErrorColor, 16));
2016-10-26 14:30:49 +00:00
}
2017-05-22 23:59:31 +00:00
2017-01-15 01:08:14 +00:00
Client = new DiscordShardedClient(new DiscordSocketConfig
2016-08-13 18:45:08 +00:00
{
2016-09-06 21:34:00 +00:00
MessageCacheSize = 10,
2016-08-15 14:57:40 +00:00
LogLevel = LogSeverity.Warning,
TotalShards = Credentials.TotalShards,
2017-02-01 16:50:14 +00:00
ConnectionTimeout = int.MaxValue,
2017-05-22 23:59:31 +00:00
AlwaysDownloadUsers = true,
2016-08-13 18:45:08 +00:00
});
CommandService = new CommandService(new CommandServiceConfig()
2017-05-22 23:59:31 +00:00
{
2017-01-28 23:38:09 +00:00
CaseSensitiveCommands = false,
2017-05-22 23:59:31 +00:00
DefaultRunMode = RunMode.Sync,
2016-12-31 16:34:21 +00:00
});
2016-08-18 21:00:54 +00:00
#if GLOBAL_NADEKO
Client.Log += Client_Log;
#endif
}
2016-08-13 18:45:08 +00:00
private void AddServices()
{
var googleApiService = new GoogleApiService(Credentials);
var soundcloudApiService = new SoundCloudApiService(Credentials);
var localization = new Localization(BotConfig.Locale, AllGuildConfigs.ToDictionary(x => x.GuildId, x => x.Locale), Db);
var strings = new NadekoStrings(localization);
var commandHandler = new CommandHandler(Client, CommandService, Credentials, this);
var stats = new StatsService(Client, commandHandler, Credentials);
2017-05-22 23:59:31 +00:00
var images = new ImagesService();
var currencyHandler = new CurrencyService(BotConfig, Db);
2017-05-24 04:43:00 +00:00
2017-05-22 23:59:31 +00:00
//module services
//todo 90 - autodiscover, DI, and add instead of manual like this
#region utility
2017-05-29 23:53:16 +00:00
var crossServerTextService = new CrossServerTextService(AllGuildConfigs, Client);
var remindService = new RemindService(Client, BotConfig, Db);
var repeaterService = new MessageRepeaterService(Client, AllGuildConfigs);
var converterService = new ConverterService(Db);
2017-05-29 23:53:16 +00:00
var commandMapService = new CommandMapService(AllGuildConfigs);
#endregion
#region Searches
var searchesService = new SearchesService(Client, googleApiService, Db);
var streamNotificationService = new StreamNotificationService(Db, Client, strings);
#endregion
var clashService = new ClashOfClansService(Client, Db, localization, strings);
var musicService = new MusicService(googleApiService, strings, localization, Db, soundcloudApiService, Credentials, AllGuildConfigs);
var crService = new CustomReactionsService(Db, Client);
var helpService = new HelpService(BotConfig);
#region Games
2017-05-27 08:19:27 +00:00
var gamesService = new GamesService(Client, BotConfig, AllGuildConfigs, strings, images);
var chatterBotService = new ChatterBotService(Client, AllGuildConfigs);
var pollService = new PollService(Client, strings);
#endregion
#region administration
2017-05-27 08:19:27 +00:00
var administrationService = new AdministrationService(AllGuildConfigs, commandHandler);
var greetSettingsService = new GreetSettingsService(Client, AllGuildConfigs, Db);
var selfService = new SelfService(Client, this, commandHandler, Db, BotConfig, localization, strings, Credentials);
var vcRoleService = new VcRoleService(Client, AllGuildConfigs, Db);
var vPlusTService = new VplusTService(Client, AllGuildConfigs, strings, Db);
var muteService = new MuteService(Client, AllGuildConfigs, Db);
var ratelimitService = new SlowmodeService(AllGuildConfigs);
var protectionService = new ProtectionService(Client, AllGuildConfigs, muteService);
var playingRotateService = new PlayingRotateService(Client, BotConfig, musicService);
var gameVcService = new GameVoiceChannelService(Client, Db, AllGuildConfigs);
var autoAssignRoleService = new AutoAssignRoleService(Client, AllGuildConfigs);
var permissionsService = new PermissionsService(Db, BotConfig);
var blacklistService = new BlacklistService(BotConfig);
var cmdcdsService = new CmdCdService(AllGuildConfigs);
2017-05-29 23:53:16 +00:00
var filterService = new FilterService(Client, AllGuildConfigs);
var globalPermsService = new GlobalPermissionService(BotConfig);
#endregion
2017-05-27 08:19:27 +00:00
2017-05-22 23:59:31 +00:00
//initialize Services
Services = new NServiceProvider.ServiceProviderBuilder()
2017-05-22 23:59:31 +00:00
.Add<ILocalization>(localization)
.Add<IStatsService>(stats)
.Add<IImagesService>(images)
.Add<IGoogleApiService>(googleApiService)
2017-05-22 23:59:31 +00:00
.Add<IStatsService>(stats)
.Add<IBotCredentials>(Credentials)
.Add<CommandService>(CommandService)
2017-05-22 23:59:31 +00:00
.Add<NadekoStrings>(strings)
.Add<DiscordShardedClient>(Client)
2017-05-24 04:43:00 +00:00
.Add<BotConfig>(BotConfig)
.Add<CurrencyService>(currencyHandler)
2017-05-22 23:59:31 +00:00
.Add<CommandHandler>(commandHandler)
.Add<DbService>(Db)
2017-05-22 23:59:31 +00:00
//modules
2017-05-29 23:53:16 +00:00
.Add(crossServerTextService)
.Add(commandMapService)
.Add(remindService)
.Add(repeaterService)
.Add(converterService)
2017-05-22 23:59:31 +00:00
.Add<SearchesService>(searchesService)
.Add(streamNotificationService)
2017-05-24 04:43:00 +00:00
.Add<ClashOfClansService>(clashService)
2017-05-25 02:24:43 +00:00
.Add<MusicService>(musicService)
.Add<GreetSettingsService>(greetSettingsService)
.Add<CustomReactionsService>(crService)
.Add<HelpService>(helpService)
2017-05-27 08:19:27 +00:00
.Add<GamesService>(gamesService)
.Add(chatterBotService)
.Add(pollService)
.Add<AdministrationService>(administrationService)
.Add(selfService)
.Add(vcRoleService)
.Add(vPlusTService)
.Add(muteService)
.Add(ratelimitService)
.Add(playingRotateService)
.Add(gameVcService)
.Add(autoAssignRoleService)
.Add(protectionService)
.Add<PermissionsService>(permissionsService)
.Add(blacklistService)
.Add(cmdcdsService)
.Add(filterService)
.Add(globalPermsService)
2017-05-22 23:59:31 +00:00
.Build();
commandHandler.AddServices(Services);
//setup typereaders
CommandService.AddTypeReader<PermissionAction>(new PermissionActionTypeReader());
CommandService.AddTypeReader<CommandInfo>(new CommandTypeReader(CommandService));
CommandService.AddTypeReader<CommandOrCrInfo>(new CommandOrCrTypeReader(crService, CommandService));
CommandService.AddTypeReader<ModuleInfo>(new ModuleTypeReader(CommandService));
CommandService.AddTypeReader<ModuleOrCrInfo>(new ModuleOrCrTypeReader(CommandService));
CommandService.AddTypeReader<IGuild>(new GuildTypeReader(Client));
2017-05-22 23:59:31 +00:00
}
private async Task LoginAsync(string token)
2017-05-22 23:59:31 +00:00
{
2016-08-15 14:57:40 +00:00
//connect
await Client.LoginAsync(TokenType.Bot, token).ConfigureAwait(false);
2017-04-15 00:54:19 +00:00
await Client.StartAsync().ConfigureAwait(false);
2017-04-15 00:54:19 +00:00
// wait for all shards to be ready
int readyCount = 0;
foreach (var s in Client.Shards)
s.Ready += () => Task.FromResult(Interlocked.Increment(ref readyCount));
while (readyCount < Client.Shards.Count)
await Task.Delay(100).ConfigureAwait(false);
}
public async Task RunAsync(params string[] args)
{
_log.Info("Starting NadekoBot v" + StatsService.BotVersion);
var sw = Stopwatch.StartNew();
await LoginAsync(Credentials.Token).ConfigureAwait(false);
AddServices();
2016-08-18 21:00:54 +00:00
sw.Stop();
_log.Info("Connected in " + sw.Elapsed.TotalSeconds.ToString("F2"));
2016-08-18 21:00:54 +00:00
var stats = Services.GetService<IStatsService>();
stats.Initialize();
var commandHandler = Services.GetService<CommandHandler>();
var CommandService = Services.GetService<CommandService>();
// start handling messages received in commandhandler
2017-05-22 23:59:31 +00:00
await commandHandler.StartHandling().ConfigureAwait(false);
var _ = await CommandService.AddModulesAsync(this.GetType().GetTypeInfo().Assembly);
#if GLOBAL_NADEKO
//unload modules which are not available on the public bot
CommandService
.Modules
.ToArray()
.Where(x => x.Preconditions.Any(y => y.GetType() == typeof(NoPublicBot)))
.ForEach(x => CommandService.RemoveModuleAsync(x));
#endif
2016-10-12 22:32:11 +00:00
Ready = true;
2017-05-22 23:59:31 +00:00
_log.Info(await stats.Print().ConfigureAwait(false));
}
2016-08-13 18:45:08 +00:00
2017-01-15 01:08:14 +00:00
private Task Client_Log(LogMessage arg)
{
_log.Warn(arg.Source + " | " + arg.Message);
2017-01-15 01:08:14 +00:00
if (arg.Exception != null)
_log.Warn(arg.Exception);
return Task.CompletedTask;
}
public async Task RunAndBlockAsync(params string[] args)
{
await RunAsync(args).ConfigureAwait(false);
await Task.Delay(-1).ConfigureAwait(false);
2016-08-13 18:45:08 +00:00
}
2016-08-15 14:57:40 +00:00
2016-11-15 09:54:56 +00:00
private static void SetupLogger()
2016-08-18 21:00:54 +00:00
{
try
{
var logConfig = new LoggingConfiguration();
2017-04-15 00:54:19 +00:00
var consoleTarget = new ColoredConsoleTarget()
{
Layout = @"${date:format=HH\:mm\:ss} ${logger} | ${message}"
};
2016-08-18 21:00:54 +00:00
logConfig.AddTarget("Console", consoleTarget);
logConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, consoleTarget));
LogManager.Configuration = logConfig;
}
catch (Exception ex)
{
2016-08-18 21:00:54 +00:00
Console.WriteLine(ex);
}
}
2016-08-13 18:45:08 +00:00
}
}