public RoleplayingDatabaseContext CreateDbContext(string[] args)
        {
            var optionsBuilder = new DbContextOptionsBuilder <RoleplayingDatabaseContext>();

            new SchemaAwareDbContextService(new ContentService(FileSystemFactory.CreateContentFileSystem()))
            .ConfigureSchemaAwareContext <RoleplayingDatabaseContext>(optionsBuilder);

            return(new RoleplayingDatabaseContext(optionsBuilder.Options));
        }
    /// <inheritdoc />
    public CharactersDatabaseContext CreateDbContext(string[] args)
    {
        var optionsBuilder = new DbContextOptionsBuilder <CharactersDatabaseContext>();

        new ContextConfigurationService(new ContentService(FileSystemFactory.CreateContentFileSystem()))
        .ConfigureSchemaAwareContext <CharactersDatabaseContext>(optionsBuilder);

        return(new CharactersDatabaseContext(optionsBuilder.Options));
    }
 /// <inheritdoc />
 protected override void RegisterServices(IServiceCollection serviceCollection)
 {
     serviceCollection
     .AddDbContext <CoreDatabaseContext>(ConfigureOptions <CoreDatabaseContext>)
     .AddSingleton(FileSystemFactory.CreateContentFileSystem())
     .AddSingleton <DelayedActionService>()
     .AddScoped <ContentService>()
     .AddScoped <UserFeedbackService>()
     .AddScoped <PrivacyService>();
 }
        /// <inheritdoc />
        protected override void RegisterServices(IServiceCollection serviceCollection)
        {
            serviceCollection.AddDbContext <CoreDatabaseContext>(ConfigureOptions <CoreDatabaseContext>);

            serviceCollection
            .AddSingleton(FileSystemFactory.CreateContentFileSystem())
            .AddSingleton <DelayedActionService>()
            .AddScoped <ContentService>()
            .AddScoped <UserFeedbackService>()
            .AddScoped <PrivacyService>()
            .AddLogging(c => c.AddProvider(NullLoggerProvider.Instance));
        }
Exemple #5
0
        /// <inheritdoc />
        protected override void RegisterServices(IServiceCollection serviceCollection)
        {
            serviceCollection
            .AddDbContext <CoreDatabaseContext>(ConfigureOptions <CoreDatabaseContext>)
            .AddDbContext <CharactersDatabaseContext>(ConfigureOptions <CharactersDatabaseContext>);

            serviceCollection
            .AddSingleton(FileSystemFactory.CreateContentFileSystem())
            .AddSingleton <PronounService>()
            .AddScoped <CommandService>()
            .AddScoped <ContentService>()
            .AddScoped <ServerService>()
            .AddScoped <UserService>()
            .AddScoped <OwnedEntityService>()
            .AddScoped <CharacterService>();
        }
        /// <inheritdoc />
        protected override void RegisterServices(IServiceCollection serviceCollection)
        {
            serviceCollection
            .AddDbContext <CoreDatabaseContext>(ConfigureOptions <CoreDatabaseContext>)
            .AddDbContext <TransformationsDatabaseContext>(ConfigureOptions <TransformationsDatabaseContext>)
            .AddDbContext <CharactersDatabaseContext>(ConfigureOptions <CharactersDatabaseContext>);

            serviceCollection
            .AddSingleton(FileSystemFactory.CreateContentFileSystem())
            .AddSingleton <PronounService>()
            .AddSingleton <TransformationDescriptionBuilder>()
            .AddScoped <TransformationService>()
            .AddScoped <ContentService>()
            .AddScoped <UserService>()
            .AddScoped <ServerService>()
            .AddScoped <UserService>();
        }
Exemple #7
0
    /// <inheritdoc />
    protected override void RegisterServices(IServiceCollection serviceCollection)
    {
        serviceCollection
        .AddDbContext <CoreDatabaseContext>(o => ConfigureOptions(o, "Core"))
        .AddDbContext <CharactersDatabaseContext>(o => ConfigureOptions(o, "Characters"));

        serviceCollection
        .AddSingleton(FileSystemFactory.CreateContentFileSystem())
        .AddSingleton <PronounService>()
        .AddScoped <ContentService>()
        .AddScoped <ServerService>()
        .AddScoped <UserService>()
        .AddScoped <OwnedEntityService>()
        .AddScoped <CharacterService>()
        .AddScoped <ICharacterService>(s => s.GetRequiredService <CharacterService>())
        .AddScoped <ICharacterEditor>(s => s.GetRequiredService <CharacterService>())
        .AddLogging(c => c.AddProvider(NullLoggerProvider.Instance));
    }
Exemple #8
0
    /// <inheritdoc />
    protected override void RegisterServices(IServiceCollection serviceCollection)
    {
        serviceCollection.AddDbContext <CoreDatabaseContext>(o => ConfigureOptions(o, "Core"));

        var channelAPIMock     = new Mock <IDiscordRestChannelAPI>();
        var userAPIMock        = new Mock <IDiscordRestUserAPI>();
        var interactionAPIMock = new Mock <IDiscordRestInteractionAPI>();

        serviceCollection
        .AddSingleton(FileSystemFactory.CreateContentFileSystem())
        .AddScoped <ContentService>()
        .AddScoped <FeedbackService>()
        .AddScoped <PrivacyService>()
        .AddScoped <ContextInjectionService>()
        .AddSingleton(FeedbackTheme.DiscordDark)
        .AddSingleton(channelAPIMock.Object)
        .AddSingleton(userAPIMock.Object)
        .AddSingleton(interactionAPIMock.Object)
        .AddLogging(c => c.AddProvider(NullLoggerProvider.Instance));
    }
Exemple #9
0
        /// <inheritdoc />
        protected override void RegisterServices(IServiceCollection serviceCollection)
        {
            serviceCollection
            .AddDbContext <CoreDatabaseContext>(ConfigureOptions <CoreDatabaseContext>)
            .AddDbContext <TransformationsDatabaseContext>(ConfigureOptions <TransformationsDatabaseContext>)
            .AddDbContext <CharactersDatabaseContext>(ConfigureOptions <CharactersDatabaseContext>);

            serviceCollection
            .AddSingleton(s =>
            {
                var content = s.GetRequiredService <ContentService>();
                return(content.GetTransformationMessages().Entity);
            })
            .AddSingleton(FileSystemFactory.CreateContentFileSystem())
            .AddSingleton <PronounService>()
            .AddSingleton <TransformationDescriptionBuilder>()
            .AddScoped <TransformationService>()
            .AddScoped <ContentService>()
            .AddScoped <UserService>()
            .AddScoped <ServerService>()
            .AddScoped <UserService>();
        }
    /// <inheritdoc />
    protected override void RegisterServices(IServiceCollection serviceCollection)
    {
        serviceCollection
        .AddDbContext <CoreDatabaseContext>(o => ConfigureOptions(o, "Core"))
        .AddDbContext <TransformationsDatabaseContext>(o => ConfigureOptions(o, "Transformations"))
        .AddDbContext <CharactersDatabaseContext>(o => ConfigureOptions(o, "Characters"));

        serviceCollection
        .AddSingleton(s =>
        {
            var content = s.GetRequiredService <ContentService>();
            return(content.GetTransformationMessages().Entity);
        })
        .AddSingleton(FileSystemFactory.CreateContentFileSystem())
        .AddSingleton <PronounService>()
        .AddSingleton <TransformationDescriptionBuilder>()
        .AddScoped <TransformationService>()
        .AddScoped <ContentService>()
        .AddScoped <UserService>()
        .AddScoped <ServerService>()
        .AddScoped <UserService>()
        .AddLogging(c => c.AddProvider(NullLoggerProvider.Instance));
    }
 public ExecuteSnippetAsync()
 {
     _lua = new LuaService(new ContentService(FileSystemFactory.CreateContentFileSystem()));
 }
Exemple #12
0
    /// <summary>
    /// The main entry point of the program.
    /// </summary>
    /// <returns>A task.</returns>
    public static async Task Main()
    {
        var cancellationSource = new CancellationTokenSource();

        Console.CancelKeyPress += (_, eventArgs) =>
        {
            eventArgs.Cancel = true;
            cancellationSource.Cancel();
        };

        // Configure logging
        const string configurationName = "DIGOS.Ambassador.log4net.config";
        var          logConfig         = new XmlDocument();

        await using (var configStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(configurationName))
        {
            if (configStream is null)
            {
                throw new InvalidOperationException("The log4net configuration stream could not be found.");
            }

            logConfig.Load(configStream);
        }

        var repo = LogManager.CreateRepository(Assembly.GetEntryAssembly(), typeof(Hierarchy));

        XmlConfigurator.Configure(repo, logConfig["log4net"]);

        var contentFileSystem = FileSystemFactory.CreateContentFileSystem();
        var contentService    = new ContentService(contentFileSystem);

        var getBotToken = await contentService.GetBotTokenAsync();

        if (!getBotToken.IsSuccess)
        {
            throw new InvalidOperationException("No bot token available.");
        }

        var token = getBotToken.Entity.Trim();

        var options       = Options.Create(new PluginServiceOptions(Array.Empty <string>()));
        var pluginService = new PluginService(options);

        var plugins = pluginService.LoadPluginTree();

        var hostBuilder = Host.CreateDefaultBuilder()
                          .AddDiscordService(_ => token)
                          .UseSystemd()
                          .ConfigureServices(services =>
        {
            services.Configure <DiscordGatewayClientOptions>(o =>
            {
                o.Intents |= GatewayIntents.MessageContents;
            });

            services.Configure <ServiceProviderOptions>(s =>
            {
                s.ValidateScopes  = true;
                s.ValidateOnBuild = true;
            });

            services.Configure <CommandResponderOptions>(o => o.Prefix = "!");

            services.AddSingleton <BehaviourService>();

            services
            .AddSingleton(pluginService)
            .AddSingleton(contentService)
            .AddSingleton(contentFileSystem)
            .AddSingleton <Random>();

            services
            .AddDiscordCommands(true)
            .AddDiscordCaching();

            // Configure cache times
            services.Configure <CacheSettings>(settings =>
            {
                settings.SetAbsoluteExpiration <IGuildMember>(TimeSpan.FromDays(1));
                settings.SetAbsoluteExpiration <IMessage>(TimeSpan.FromDays(1));
            });

            // Set up the feedback theme
            var theme = (FeedbackTheme) FeedbackTheme.DiscordDark with
            {
                Secondary = Color.MediumPurple
            };

            services.AddSingleton <IFeedbackTheme>(theme);

            // Add execution events
            services
            .AddPreExecutionEvent <ConsentCheckingPreExecutionEvent>()
            .AddPostExecutionEvent <MessageRelayingPostExecutionEvent>();

            // Ensure we're automatically joining created threads
            services.AddResponder <ThreadJoinResponder>();

            // Override the default responders
            services.Replace(ServiceDescriptor.Scoped <CommandResponder, AmbassadorCommandResponder>());
            services.Replace(ServiceDescriptor.Scoped <InteractionResponder, AmbassadorInteractionResponder>());

            services
            .AddParser <MessageReader>()
            .AddParser <HumanTimeSpanReader>();

            var configurePlugins = plugins.ConfigureServices(services);
            if (!configurePlugins.IsSuccess)
            {
                throw new InvalidOperationException();
            }
        })
                          .ConfigureLogging(l =>
        {
            l.ClearProviders();

            l.AddLog4Net()
            .AddFilter("Microsoft.EntityFrameworkCore.Infrastructure", LogLevel.Warning)
            .AddFilter("Microsoft.EntityFrameworkCore.Database.Command", LogLevel.Critical)
            .AddFilter("Microsoft.EntityFrameworkCore.Migrations", LogLevel.Warning)
            .AddFilter("Microsoft.EntityFrameworkCore.Update", LogLevel.Critical);
        });

        var host         = hostBuilder.Build();
        var hostServices = host.Services;

        var log = hostServices.GetRequiredService <ILogger <Program> >();

        log.LogInformation("Running on {Framework}", RuntimeInformation.FrameworkDescription);

        Snowflake?debugServer       = null;
        var       debugServerString = Environment.GetEnvironmentVariable("REMORA_DEBUG_SERVER");

        if (debugServerString is not null)
        {
            if (!Snowflake.TryParse(debugServerString, out debugServer))
            {
                log.LogWarning("Failed to parse debug server from environment");
            }
        }

        var slashService = hostServices.GetRequiredService <SlashService>();

        var checkSlashSupport = slashService.SupportsSlashCommands();

        if (!checkSlashSupport.IsSuccess)
        {
            var error = checkSlashSupport.Error;
            if (error is UnsupportedFeatureError ufe)
            {
                var location = ufe.Node is not null
                    ? GetCommandLocation(ufe.Node)
                    : "unknown";

                log.LogWarning
                (
                    "The registered commands of the bot don't support slash commands: {Reason} ({Location})",
                    error.Message,
                    location
                );
            }
            else
            {
                log.LogError("Failed to check slash command compatibility: {Reason}", error.Message);
                return;
            }
        }
        else
        {
            var updateSlash = await slashService.UpdateSlashCommandsAsync(debugServer, ct : cancellationSource.Token);

            if (!updateSlash.IsSuccess)
            {
                log.LogWarning("Failed to update slash commands: {Reason}", updateSlash.Error.Message);
            }
        }

        log.LogInformation("Initializing plugins...");
        var initializePlugins = await plugins.InitializeAsync(hostServices, cancellationSource.Token);

        if (!initializePlugins.IsSuccess)
        {
            log.LogError("Failed to initialize the plugin tree");

            if (initializePlugins.Error is AggregateError a)
            {
                foreach (var error in a.Errors)
                {
                    if (error.IsSuccess)
                    {
                        continue;
                    }

                    log.LogError("Initialization error: {Error}", error.Error !.Message);
                }
            }
            else
            {
                log.LogError("Initialization error: {Error}", initializePlugins.Error);
            }

            return;
        }

        log.LogInformation("Migrating plugins...");
        var migratePlugins = await plugins.MigrateAsync(hostServices, cancellationSource.Token);

        if (!migratePlugins.IsSuccess)
        {
            log.LogError("Failed to initialize the plugin tree");

            if (migratePlugins.Error is AggregateError a)
            {
                foreach (var error in a.Errors)
                {
                    if (error.IsSuccess)
                    {
                        continue;
                    }

                    log.LogError("Migration error: {Error}", error.Error !.Message);
                }
            }
            else
            {
                log.LogError("Migration error: {Error}", migratePlugins.Error);
            }

            return;
        }

        var behaviourService = hostServices.GetRequiredService <BehaviourService>();
        await behaviourService.StartBehavioursAsync();

        await host.RunAsync(cancellationSource.Token);

        await behaviourService.StopBehavioursAsync();
    }
        /// <summary>
        /// Initializes the bot and its services.
        /// </summary>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public async Task InitializeAsync()
        {
            var pluginService = new PluginService();

            var serviceCollection = new ServiceCollection()
                                    .AddSingleton(this)
                                    .AddSingleton(_client)
                                    .AddSingleton <BaseSocketClient>(_client)
                                    .AddSingleton(_behaviours)
                                    .AddSingleton <ContentService>()
                                    .AddSingleton(_commands)
                                    .AddSingleton <DiscordService>()
                                    .AddSingleton <UserFeedbackService>()
                                    .AddSingleton <InteractivityService>()
                                    .AddSingleton <DelayedActionService>()
                                    .AddSingleton <HelpService>()
                                    .AddSingleton <Random>()
                                    .AddSingleton(pluginService)
                                    .AddSingleton <SchemaAwareDbContextService>()
                                    .AddSingleton(FileSystemFactory.CreateContentFileSystem());

            var successfullyRegisteredPlugins = new List <IPluginDescriptor>();

            var availablePlugins = pluginService.LoadAvailablePlugins();

            foreach (var availablePlugin in availablePlugins)
            {
                if (!await availablePlugin.RegisterServicesAsync(serviceCollection))
                {
                    Log.Warn
                    (
                        $"The plugin \"{availablePlugin.Name}\" (v{availablePlugin.Version}) failed to " +
                        $"register its services. It will not be loaded."
                    );

                    continue;
                }

                successfullyRegisteredPlugins.Add(availablePlugin);
            }

            _services = serviceCollection.BuildServiceProvider();

            var contentService = _services.GetRequiredService <ContentService>();
            await contentService.InitializeAsync();

            // Create plugin databases
            foreach (var plugin in successfullyRegisteredPlugins)
            {
                if (!(plugin is IMigratablePlugin migratablePlugin))
                {
                    continue;
                }

                if (await migratablePlugin.IsDatabaseCreatedAsync(_services))
                {
                    continue;
                }

                if (!await migratablePlugin.MigratePluginAsync(_services))
                {
                    Log.Warn
                    (
                        $"The plugin \"{plugin.Name}\"" +
                        $" (v{plugin.Version}) failed to migrate its database. It may not " +
                        $"be functional."
                    );
                }
            }

            // Then, run migrations in reverse
            foreach (var plugin in successfullyRegisteredPlugins.AsEnumerable().Reverse())
            {
                if (!(plugin is IMigratablePlugin migratablePlugin))
                {
                    continue;
                }

                if (!await migratablePlugin.MigratePluginAsync(_services))
                {
                    Log.Warn
                    (
                        $"The plugin \"{plugin.Name}\"" +
                        $" (v{plugin.Version}) failed to migrate its database. It may not " +
                        $"be functional."
                    );
                }
            }

            foreach (var plugin in successfullyRegisteredPlugins)
            {
                if (!await plugin.InitializeAsync(_services))
                {
                    Log.Warn
                    (
                        $"The plugin \"{plugin.Name}\"" +
                        $" (v{plugin.Version}) failed to initialize. It may not be functional."
                    );
                }
            }
        }
        /// <summary>
        /// The main entry point of the program.
        /// </summary>
        /// <returns>A task.</returns>
        public static async Task Main()
        {
            // Configure logging
            const string configurationName = "DIGOS.Ambassador.log4net.config";
            var          logConfig         = new XmlDocument();

            await using (var configStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(configurationName))
            {
                if (configStream is null)
                {
                    throw new InvalidOperationException("The log4net configuration stream could not be found.");
                }

                logConfig.Load(configStream);
            }

            var repo = LogManager.CreateRepository(Assembly.GetEntryAssembly(), typeof(Hierarchy));

            XmlConfigurator.Configure(repo, logConfig["log4net"]);

            var hostBuilder = Host.CreateDefaultBuilder()
                              .UseSystemd()
                              .ConfigureServices(services =>
            {
                var pluginService = new PluginService();

                services
                .AddHostedService <AmbassadorBotService>()
                .AddSingleton(pluginService)
                .AddSingleton
                (
                    provider => new DiscordSocketClient(new DiscordSocketConfig {
                    MessageCacheSize = 100
                })
                )
                .AddSingleton <IDiscordClient>(s => s.GetRequiredService <DiscordSocketClient>())
                .AddSingleton <BaseSocketClient>(s => s.GetRequiredService <DiscordSocketClient>())
                .AddSingleton <CommandService>()
                .AddSingleton <BehaviourService>()
                .AddSingleton <ContentService>()
                .AddSingleton <DiscordService>()
                .AddSingleton <UserFeedbackService>()
                .AddSingleton <InteractivityService>()
                .AddSingleton <DelayedActionService>()
                .AddSingleton <SchemaAwareDbContextService>()
                .AddSingleton <ContextConfigurationService>()
                .AddSingleton(FileSystemFactory.CreateContentFileSystem())
                .AddSingleton <Random>();

                var plugins = pluginService.LoadAvailablePlugins();
                foreach (var plugin in plugins)
                {
                    plugin.ConfigureServices(services);
                }
            })
                              .ConfigureLogging(l =>
            {
                l.ClearProviders();

                l.AddLog4Net()
                .AddFilter("Microsoft.EntityFrameworkCore.Infrastructure", LogLevel.Warning)
                .AddFilter("Microsoft.EntityFrameworkCore.Database.Command", LogLevel.Warning)
                .AddFilter("Microsoft.EntityFrameworkCore.Migrations", LogLevel.Warning);
            });

            var host = hostBuilder.Build();

            var logger = host.Services.GetRequiredService <ILogger <Program> >();

            logger.LogInformation($"Running on {RuntimeInformation.FrameworkDescription}");

            await host.RunAsync();
        }