Added .streamrole, needs testing.

This commit is contained in:
Master Kwoth 2017-07-14 05:00:30 +02:00
parent 67f0cfb717
commit b8573f11b5
12 changed files with 1905 additions and 2 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class streamrole : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "StreamRoleSettings",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
AddRoleId = table.Column<ulong>(nullable: false),
DateAdded = table.Column<DateTime>(nullable: true),
FromRoleId = table.Column<ulong>(nullable: false),
GuildConfigId = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_StreamRoleSettings", x => x.Id);
table.ForeignKey(
name: "FK_StreamRoleSettings_GuildConfigs_GuildConfigId",
column: x => x.GuildConfigId,
principalTable: "GuildConfigs",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_StreamRoleSettings_GuildConfigId",
table: "StreamRoleSettings",
column: "GuildConfigId",
unique: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "StreamRoleSettings");
}
}
}

View File

@ -1126,6 +1126,27 @@ namespace NadekoBot.Migrations
b.ToTable("StartupCommand");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<ulong>("AddRoleId");
b.Property<DateTime?>("DateAdded");
b.Property<ulong>("FromRoleId");
b.Property<int>("GuildConfigId");
b.HasKey("Id");
b.HasIndex("GuildConfigId")
.IsUnique();
b.ToTable("StreamRoleSettings");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b =>
{
b.Property<int>("Id")
@ -1510,6 +1531,14 @@ namespace NadekoBot.Migrations
.HasForeignKey("BotConfigId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig")
.WithOne("StreamRole")
.HasForeignKey("NadekoBot.Services.Database.Models.StreamRoleSettings", "GuildConfigId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")

View File

@ -0,0 +1,39 @@
using Discord;
using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Services.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Utility.Commands
{
public class StreamRoleCommands : NadekoSubmodule
{
private readonly StreamRoleService service;
public StreamRoleCommands(StreamRoleService service)
{
this.service = service;
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task StreamRole(IRole fromRole, IRole addRole)
{
this.service.SetStreamRole(fromRole, addRole);
await ReplyConfirmLocalized("stream_role_enabled", Format.Bold(fromRole.ToString()), Format.Bold(addRole.ToString())).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task StreamRole()
{
this.service.StopStreamRole(Context.Guild.Id);
await ReplyConfirmLocalized("stream_role_disabled").ConfigureAwait(false);
}
}
}

View File

@ -91,6 +91,5 @@
<ItemGroup>
<Folder Include="Modules\Music\Classes\" />
<Folder Include="Utility\Services\" />
</ItemGroup>
</Project>

View File

@ -1700,6 +1700,15 @@
</data>
<data name="save_usage" xml:space="preserve">
<value>`{0}save classical1`</value>
</data>
<data name="streamrole_cmd" xml:space="preserve">
<value>streamrole</value>
</data>
<data name="streamrole_desc" xml:space="preserve">
<value>Sets a role which is monitored for streamers (FromRole), and a role to add if a user from 'FromRole' is streaming (AddRole). When a user from 'FromRole' starts streaming, they will receive an 'AddRole'. Provide no arguments to disable</value>
</data>
<data name="streamrole_usage" xml:space="preserve">
<value>`{0}streamrole "Eligible Streamers" "Featured Streams"`</value>
</data>
<data name="load_cmd" xml:space="preserve">
<value>load</value>

View File

@ -83,6 +83,8 @@ namespace NadekoBot.Services.Database.Models
public ulong? GameVoiceChannel { get; set; } = null;
public bool VerboseErrors { get; set; } = false;
public StreamRoleSettings StreamRole { get; set; } = new StreamRoleSettings();
//public List<ProtectionIgnoredChannel> ProtectionIgnoredChannels { get; set; } = new List<ProtectionIgnoredChannel>();
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Services.Database.Models
{
public class StreamRoleSettings : DbEntity
{
public int GuildConfigId { get; set; }
public GuildConfig GuildConfig { get; set; }
/// <summary>
/// Id of the role to give to the users in the role 'FromRole' when they start streaming
/// </summary>
public ulong AddRoleId { get; set; }
/// <summary>
/// Id of the role whose users are eligible to get the 'AddRole'
/// </summary>
public ulong FromRoleId { get; set; }
}
}

View File

@ -169,13 +169,19 @@ namespace NadekoBot.Services.Database
#endregion
#region streamrole
modelBuilder.Entity<StreamRoleSettings>()
.HasOne(x => x.GuildConfig)
.WithOne(x => x.StreamRole);
#endregion
#region BotConfig
//var botConfigEntity = modelBuilder.Entity<BotConfig>();
//botConfigEntity
// .HasMany(c => c.ModulePrefixes)
// .WithOne(mp => mp.BotConfig)
// .HasForeignKey(mp => mp.BotConfigId);
#endregion
#region ClashOfClans

View File

@ -45,6 +45,7 @@ namespace NadekoBot.Services.Database.Repositories.Impl
.Include(gc => gc.AntiSpamSetting)
.ThenInclude(x => x.IgnoredChannels)
.Include(gc => gc.FollowedStreams)
.Include(gc => gc.StreamRole)
.ToList();
/// <summary>

View File

@ -0,0 +1,150 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Discord;
using NadekoBot.Services.Database.Models;
using System.Collections.Concurrent;
using NadekoBot.Extensions;
using Discord.WebSocket;
using Microsoft.EntityFrameworkCore;
using NLog;
namespace NadekoBot.Services.Utility
{
public class StreamRoleService
{
private readonly DbService _db;
private readonly ConcurrentDictionary<ulong, StreamRoleSettings> guildSettings;
//(guildId, userId), roleId
private readonly ConcurrentDictionary<(ulong GuildId, ulong UserId), ulong> toRemove = new ConcurrentDictionary<(ulong GuildId, ulong UserId), ulong>();
private readonly Logger _log;
public StreamRoleService(DiscordSocketClient client, DbService db, IEnumerable<GuildConfig> gcs)
{
this._db = db;
this._log = LogManager.GetCurrentClassLogger();
guildSettings = gcs.ToDictionary(x => x.GuildId, x => x.StreamRole)
.ToConcurrent();
client.GuildMemberUpdated += Client_GuildMemberUpdated;
}
private Task Client_GuildMemberUpdated(SocketGuildUser before, SocketGuildUser after)
{
var _ = Task.Run(async () =>
{
//if user wasn't streaming or didn't have a game status at all
// and has a game status now
// and that status is a streaming status
// and we are supposed to give him a role
if ((!before.Game.HasValue || before.Game.Value.StreamType == StreamType.NotStreaming) &&
after.Game.HasValue &&
after.Game.Value.StreamType != StreamType.NotStreaming
&& guildSettings.TryGetValue(after.Guild.Id, out var setting))
{
IRole fromRole;
IRole addRole;
try
{
//get needed roles
fromRole = after.Guild.GetRole(setting.FromRoleId);
addRole = after.Guild.GetRole(setting.AddRoleId);
}
catch (Exception ex)
{
StopStreamRole(before.Guild.Id);
_log.Warn("Error getting Stream Role(s). Disabling stream role feature.");
_log.Error(ex);
return;
}
try
{
//check if user is in the fromrole
if (after.Roles.Contains(fromRole))
{
//check if he doesn't have addrole already, to avoid errors
if(!after.Roles.Contains(addRole))
await after.AddRoleAsync(addRole).ConfigureAwait(false);
//schedule him for the role removal when he stops streaming
toRemove.TryAdd((addRole.Guild.Id, after.Id), addRole.Id);
}
}
catch (Exception ex)
{
_log.Warn("Failed adding stream role.");
_log.Error(ex);
}
}
// try removing a role that was given to the user
// if user had a game status
// and he was streaming
// and he no longer has a game status, or has a game status which is not a stream
// and if he's scheduled for role removal, get the roleid to remove
else if (before.Game.HasValue &&
before.Game.Value.StreamType != StreamType.NotStreaming &&
(!after.Game.HasValue || after.Game.Value.StreamType == StreamType.NotStreaming) &&
toRemove.TryRemove((after.Guild.Id, after.Id), out var roleId))
{
try
{
//get the role to remove from the role id
var role = after.Guild.GetRole(roleId);
if (role == null)
return;
//check if user has the role which needs to be removed to avoid errors
if (after.Roles.Contains(role))
await after.RemoveRoleAsync(role).ConfigureAwait(false);
}
catch (Exception ex)
{
_log.Warn("Failed removing the stream role from the user who stopped streaming.");
_log.Error(ex);
}
}
});
return Task.CompletedTask;
}
public void SetStreamRole(IRole fromRole, IRole addRole)
{
StreamRoleSettings setting;
using (var uow = _db.UnitOfWork)
{
var gc = uow.GuildConfigs.For(fromRole.Guild.Id, x => x.Include(y => y.StreamRole));
if (gc.StreamRole == null)
gc.StreamRole = new StreamRoleSettings()
{
AddRoleId = addRole.Id,
FromRoleId = fromRole.Id
};
else
{
gc.StreamRole.AddRoleId = addRole.Id;
gc.StreamRole.FromRoleId = fromRole.Id;
}
setting = gc.StreamRole;
uow.Complete();
}
guildSettings.AddOrUpdate(fromRole.Guild.Id, (key) => setting, (key, old) => setting);
}
public void StopStreamRole(ulong guildId)
{
using (var uow = _db.UnitOfWork)
{
var gc = uow.GuildConfigs.For(guildId, x => x.Include(y => y.StreamRole));
gc.StreamRole = null;
uow.Complete();
}
guildSettings.TryRemove(guildId, out _);
}
}
}

View File

@ -608,6 +608,8 @@
"searches_wind_speed": "Wind speed",
"searches_x_most_banned_champs": "The {0} most banned champions",
"searches_yodify_error": "Failed to yodify your sentence.",
"utility_stream_role_enabled": "When a user from {0} role starts streaming, I will give them {1} role.",
"utility_stream_role_disabled": "Stream role feature has been disabled.",
"utiliity_joined": "Joined",
"utility_activity_line": "`{0}.` {1} [{2:F2}/s] - {3} total",
"utility_activity_page": "Activity page #{0}",