- Owner only attributes will now use fresh creds every time (no need for restart for owner only commands to start working once creds are changed)

- setgame/setstream use the new pubsub (also setstream will actually apply to all shards now)
- setgame/setstream moved to SelfService
- small cleanup
This commit is contained in:
Kwoth
2021-07-02 23:49:03 +02:00
parent 873eaa290e
commit 65b4c1fab7
7 changed files with 63 additions and 75 deletions

View File

@@ -6,8 +6,6 @@ using NadekoBot.Common;
using NadekoBot.Services; using NadekoBot.Services;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using Newtonsoft.Json;
using StackExchange.Redis;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
@@ -103,6 +101,7 @@ namespace NadekoBot
var svcs = new ServiceCollection() var svcs = new ServiceCollection()
.AddTransient<IBotCredentials>(_ => _creds) // bot creds .AddTransient<IBotCredentials>(_ => _creds) // bot creds
.AddSingleton(_credsProvider)
.AddSingleton(_db) // database .AddSingleton(_db) // database
.AddRedis(_creds.RedisOptions) // redis .AddRedis(_creds.RedisOptions) // redis
.AddSingleton(Client) // discord socket client .AddSingleton(Client) // discord socket client
@@ -282,7 +281,6 @@ namespace NadekoBot
return Task.CompletedTask; return Task.CompletedTask;
} }
// todo cleanup
public async Task RunAsync() public async Task RunAsync()
{ {
var sw = Stopwatch.StartNew(); var sw = Stopwatch.StartNew();
@@ -303,18 +301,13 @@ namespace NadekoBot
sw.Stop(); sw.Stop();
Log.Information("Shard {ShardId} connected in {Elapsed:F2}s", Client.ShardId, sw.Elapsed.TotalSeconds); Log.Information("Shard {ShardId} connected in {Elapsed:F2}s", Client.ShardId, sw.Elapsed.TotalSeconds);
var stats = Services.GetRequiredService<IStatsService>();
stats.Initialize();
var commandHandler = Services.GetRequiredService<CommandHandler>(); var commandHandler = Services.GetRequiredService<CommandHandler>();
// start handling messages received in commandhandler // start handling messages received in commandhandler
await commandHandler.StartHandling().ConfigureAwait(false); await commandHandler.StartHandling().ConfigureAwait(false);
_ = await _commandService.AddModulesAsync(this.GetType().GetTypeInfo().Assembly, Services) await _commandService.AddModulesAsync(typeof(Bot).Assembly, Services);
.ConfigureAwait(false);
HandleStatusChanges();
IsReady = true; IsReady = true;
_ = Task.Run(ExecuteReadySubscriptions); _ = Task.Run(ExecuteReadySubscriptions);
Log.Information("Shard {ShardId} ready", Client.ShardId); Log.Information("Shard {ShardId} ready", Client.ShardId);
@@ -356,53 +349,5 @@ namespace NadekoBot
await RunAsync().ConfigureAwait(false); await RunAsync().ConfigureAwait(false);
await Task.Delay(-1).ConfigureAwait(false); await Task.Delay(-1).ConfigureAwait(false);
} }
// todo status changes don't belong here
private void HandleStatusChanges()
{
var sub = Services.GetService<IDataCache>().Redis.GetSubscriber();
sub.Subscribe(Client.CurrentUser.Id + "_status.game_set", async (ch, game) =>
{
try
{
var obj = new { Name = default(string), Activity = ActivityType.Playing };
obj = JsonConvert.DeserializeAnonymousType(game, obj);
await Client.SetGameAsync(obj.Name, type: obj.Activity).ConfigureAwait(false);
}
catch (Exception ex)
{
Log.Warning(ex, "Error setting game");
}
}, CommandFlags.FireAndForget);
sub.Subscribe(Client.CurrentUser.Id + "_status.stream_set", async (ch, streamData) =>
{
try
{
var obj = new { Name = "", Url = "" };
obj = JsonConvert.DeserializeAnonymousType(streamData, obj);
await Client.SetGameAsync(obj.Name, obj.Url, ActivityType.Streaming).ConfigureAwait(false);
}
catch (Exception ex)
{
Log.Warning(ex, "Error setting stream");
}
}, CommandFlags.FireAndForget);
}
public Task SetGameAsync(string game, ActivityType type)
{
var obj = new { Name = game, Activity = type };
var sub = Services.GetService<IDataCache>().Redis.GetSubscriber();
return sub.PublishAsync(Client.CurrentUser.Id + "_status.game_set", JsonConvert.SerializeObject(obj));
}
public Task SetStreamAsync(string name, string link)
{
var obj = new { Name = name, Url = link };
var sub = Services.GetService<IDataCache>().Redis.GetSubscriber();
return sub.PublishAsync(Client.CurrentUser.Id + "_status.stream_set", JsonConvert.SerializeObject(obj));
}
} }
} }

View File

@@ -3,15 +3,17 @@ using System.Threading.Tasks;
using Discord.Commands; using Discord.Commands;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services;
namespace NadekoBot.Common.Attributes namespace NadekoBot.Common.Attributes
{ {
// todo all getservice to getrequiredservice
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)] [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public sealed class OwnerOnlyAttribute : PreconditionAttribute public sealed class OwnerOnlyAttribute : PreconditionAttribute
{ {
public override Task<PreconditionResult> CheckPermissionsAsync(ICommandContext context, CommandInfo executingCommand, IServiceProvider services) public override Task<PreconditionResult> CheckPermissionsAsync(ICommandContext context, CommandInfo executingCommand, IServiceProvider services)
{ {
var creds = services.GetService<IBotCredentials>(); var creds = services.GetRequiredService<BotCredsProvider>().GetCreds();
return Task.FromResult((creds.IsOwner(context.User) || context.Client.CurrentUser.Id == context.User.Id ? PreconditionResult.FromSuccess() : PreconditionResult.FromError("Not owner"))); return Task.FromResult((creds.IsOwner(context.User) || context.Client.CurrentUser.Id == context.User.Id ? PreconditionResult.FromSuccess() : PreconditionResult.FromError("Not owner")));
} }

View File

@@ -432,7 +432,7 @@ namespace NadekoBot.Modules.Administration
.WithDefault(Context) .WithDefault(Context)
.Build(); .Build();
await _bot.SetGameAsync(game is null ? game : rep.Replace(game), type).ConfigureAwait(false); await _service.SetGameAsync(game is null ? game : rep.Replace(game), type).ConfigureAwait(false);
await ReplyConfirmLocalizedAsync("set_game").ConfigureAwait(false); await ReplyConfirmLocalizedAsync("set_game").ConfigureAwait(false);
} }
@@ -443,7 +443,7 @@ namespace NadekoBot.Modules.Administration
{ {
name = name ?? ""; name = name ?? "";
await _client.SetGameAsync(name, url, ActivityType.Streaming).ConfigureAwait(false); await _service.SetStreamAsync(name, url).ConfigureAwait(false);
await ReplyConfirmLocalizedAsync("set_stream").ConfigureAwait(false); await ReplyConfirmLocalizedAsync("set_stream").ConfigureAwait(false);
} }

View File

@@ -18,6 +18,7 @@ namespace NadekoBot.Modules.Administration.Services
{ {
private readonly Timer _t; private readonly Timer _t;
private readonly BotConfigService _bss; private readonly BotConfigService _bss;
private readonly SelfService _selfService;
private readonly Replacer _rep; private readonly Replacer _rep;
private readonly DbService _db; private readonly DbService _db;
private readonly Bot _bot; private readonly Bot _bot;
@@ -28,11 +29,12 @@ namespace NadekoBot.Modules.Administration.Services
} }
public PlayingRotateService(DiscordSocketClient client, DbService db, Bot bot, public PlayingRotateService(DiscordSocketClient client, DbService db, Bot bot,
BotConfigService bss, IEnumerable<IPlaceholderProvider> phProviders) BotConfigService bss, IEnumerable<IPlaceholderProvider> phProviders, SelfService selfService)
{ {
_db = db; _db = db;
_bot = bot; _bot = bot;
_bss = bss; _bss = bss;
_selfService = selfService;
if (client.ShardId == 0) if (client.ShardId == 0)
{ {
@@ -70,7 +72,7 @@ namespace NadekoBot.Modules.Administration.Services
: rotatingStatuses[state.Index++]; : rotatingStatuses[state.Index++];
var statusText = _rep.Replace(playingStatus.Status); var statusText = _rep.Replace(playingStatus.Status);
await _bot.SetGameAsync(statusText, playingStatus.Type); await _selfService.SetGameAsync(statusText, playingStatus.Type);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -14,6 +14,7 @@ using System.Threading;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System; using System;
using System.Net.Http; using System.Net.Http;
using NadekoBot.Common;
using Serilog; using Serilog;
namespace NadekoBot.Modules.Administration.Services namespace NadekoBot.Modules.Administration.Services
@@ -38,10 +39,14 @@ namespace NadekoBot.Modules.Administration.Services
private readonly IImageCache _imgs; private readonly IImageCache _imgs;
private readonly IHttpClientFactory _httpFactory; private readonly IHttpClientFactory _httpFactory;
private readonly BotConfigService _bss; private readonly BotConfigService _bss;
private readonly IPubSub _pubSub;
//keys
private readonly TypedKey<ActivityPubData> _activitySetKey;
public SelfService(DiscordSocketClient client, CommandHandler cmdHandler, DbService db, public SelfService(DiscordSocketClient client, CommandHandler cmdHandler, DbService db,
IBotStrings strings, IBotCredentials creds, IDataCache cache, IHttpClientFactory factory, IBotStrings strings, IBotCredentials creds, IDataCache cache, IHttpClientFactory factory,
BotConfigService bss) BotConfigService bss, IPubSub pubSub)
{ {
_redis = cache.Redis; _redis = cache.Redis;
_cmdHandler = cmdHandler; _cmdHandler = cmdHandler;
@@ -53,6 +58,10 @@ namespace NadekoBot.Modules.Administration.Services
_imgs = cache.LocalImages; _imgs = cache.LocalImages;
_httpFactory = factory; _httpFactory = factory;
_bss = bss; _bss = bss;
_pubSub = pubSub;
_activitySetKey = new("activity.set");
HandleStatusChanges();
var sub = _redis.GetSubscriber(); var sub = _redis.GetSubscriber();
if (_client.ShardId == 0) if (_client.ShardId == 0)
@@ -384,5 +393,34 @@ namespace NadekoBot.Modules.Administration.Services
_bss.ModifyConfig(config => { isToAll = config.ForwardToAllOwners = !config.ForwardToAllOwners; }); _bss.ModifyConfig(config => { isToAll = config.ForwardToAllOwners = !config.ForwardToAllOwners; });
return isToAll; return isToAll;
} }
// todo pubsub via IPubSub
private void HandleStatusChanges()
{
_pubSub.Sub(_activitySetKey, async data =>
{
try
{
await _client.SetGameAsync(data.Name, data.Link, type: data.Type);
}
catch (Exception ex)
{
Log.Warning(ex, "Error setting activity");
}
});
}
public Task SetGameAsync(string game, ActivityType type)
=> _pubSub.Pub(_activitySetKey, new() {Name = game, Link = null, Type = type});
public Task SetStreamAsync(string name, string link)
=> _pubSub.Pub(_activitySetKey, new() { Name = name, Link = link, Type = ActivityType.Streaming });
private class ActivityPubData
{
public string Name { get; init; }
public string Link { get; init; }
public ActivityType Type { get; init; }
}
} }
} }

View File

@@ -15,6 +15,5 @@ namespace NadekoBot.Services
TimeSpan GetUptime(); TimeSpan GetUptime();
string GetUptimeString(string separator = ", "); string GetUptimeString(string separator = ", ");
void Initialize();
} }
} }

View File

@@ -8,17 +8,18 @@ using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Common.ModuleBehaviors;
using Serilog; using Serilog;
namespace NadekoBot.Services namespace NadekoBot.Services
{ {
public class StatsService : IStatsService, INService public class StatsService : IStatsService, IReadyExecutor, INService
{ {
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
private readonly IBotCredentials _creds; private readonly IBotCredentials _creds;
private readonly DateTime _started; private readonly DateTime _started;
public const string BotVersion = "3.0.0-alpha1"; public const string BotVersion = "3.0.0-beta1";
public string Author => "Kwoth#2452"; public string Author => "Kwoth#2452";
public string Library => "Discord.Net"; public string Library => "Discord.Net";
@@ -156,13 +157,6 @@ namespace NadekoBot.Services
}, null, TimeSpan.FromMinutes(5), TimeSpan.FromHours(1)); }, null, TimeSpan.FromMinutes(5), TimeSpan.FromHours(1));
} }
public void Initialize()
{
var guilds = _client.Guilds.ToArray();
_textChannels = guilds.Sum(g => g.Channels.Count(cx => cx is ITextChannel));
_voiceChannels = guilds.Sum(g => g.Channels.Count(cx => cx is IVoiceChannel));
}
public TimeSpan GetUptime() => public TimeSpan GetUptime() =>
DateTime.UtcNow - _started; DateTime.UtcNow - _started;
@@ -171,5 +165,13 @@ namespace NadekoBot.Services
var time = GetUptime(); var time = GetUptime();
return $"{time.Days} days{separator}{time.Hours} hours{separator}{time.Minutes} minutes"; return $"{time.Days} days{separator}{time.Hours} hours{separator}{time.Minutes} minutes";
} }
public Task OnReadyAsync()
{
var guilds = _client.Guilds;
_textChannels = guilds.Sum(g => g.Channels.Count(cx => cx is ITextChannel));
_voiceChannels = guilds.Sum(g => g.Channels.Count(cx => cx is IVoiceChannel));
return Task.CompletedTask;
}
} }
} }