Complete rework of how permissions are stored. Also permissions indexes are inverted now (;asm enable is always #1)

This commit is contained in:
Kwoth 2017-03-09 00:58:58 +01:00
parent cf44ff9b79
commit 39b66cd5b4
24 changed files with 1882 additions and 606 deletions

View File

@ -0,0 +1,140 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using NadekoBot.Services.Database.Models;
namespace NadekoBot.DataStructures
{
public class PermissionsCollection<T> : IList<T> where T : IIndexed
{
public List<T> Source { get; }
private readonly object _locker = new object();
public PermissionsCollection(IEnumerable<T> source)
{
lock (_locker)
{
Source = source.OrderBy(x => x.Index).ToList();
for (var i = 0; i < Source.Count; i++)
{
if(Source[i].Index != i)
Source[i].Index = i;
}
}
}
public static implicit operator List<T>(PermissionsCollection<T> x) =>
x.Source;
public IEnumerator<T> GetEnumerator() =>
Source.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() =>
Source.GetEnumerator();
public void Add(T item)
{
lock (_locker)
{
item.Index = Source.Count;
Source.Add(item);
}
}
public void Clear()
{
lock (_locker)
{
var first = Source[0];
Source.Clear();
Source[0] = first;
}
}
public bool Contains(T item)
{
lock (_locker)
{
return Source.Contains(item);
}
}
public void CopyTo(T[] array, int arrayIndex)
{
lock (_locker)
{
Source.CopyTo(array, arrayIndex);
}
}
public bool Remove(T item)
{
bool removed;
lock (_locker)
{
if(Source.IndexOf(item) == 0)
throw new ArgumentException("You can't remove first permsission (allow all)");
if (removed = Source.Remove(item))
{
for (int i = 0; i < Source.Count; i++)
{
// hm, no idea how ef works, so I don't want to set if it's not changed,
// maybe it will try to update db?
// But most likely it just compares old to new values, meh.
if (Source[i].Index != i)
Source[i].Index = i;
}
}
}
return removed;
}
public int Count => Source.Count;
public bool IsReadOnly => false;
public int IndexOf(T item) => item.Index;
public void Insert(int index, T item)
{
lock (_locker)
{
if(index == 0) // can't insert on first place. Last item is always allow all.
throw new IndexOutOfRangeException(nameof(index));
Source.Insert(index, item);
for (int i = index; i < Source.Count; i++)
{
Source[i].Index = i;
}
}
}
public void RemoveAt(int index)
{
lock (_locker)
{
if(index == 0) // you can't remove first permission (allow all)
throw new IndexOutOfRangeException(nameof(index));
Source.RemoveAt(index);
for (int i = index; i < Source.Count; i++)
{
Source[i].Index = i;
}
}
}
public T this[int index] {
get { return Source[index]; }
set {
lock (_locker)
{
if(index == 0) // can't set first element. It's always allow all
throw new IndexOutOfRangeException(nameof(index));
value.Index = index;
Source[index] = value;
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class permsv2 : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Permissionv2",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
DateAdded = table.Column<DateTime>(nullable: true),
GuildConfigId = table.Column<int>(nullable: true),
Index = table.Column<int>(nullable: false),
PrimaryTarget = table.Column<int>(nullable: false),
PrimaryTargetId = table.Column<ulong>(nullable: false),
SecondaryTarget = table.Column<int>(nullable: false),
SecondaryTargetName = table.Column<string>(nullable: true),
State = table.Column<bool>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Permissionv2", x => x.Id);
table.ForeignKey(
name: "FK_Permissionv2_GuildConfigs_GuildConfigId",
column: x => x.GuildConfigId,
principalTable: "GuildConfigs",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_Permissionv2_GuildConfigId",
table: "Permissionv2",
column: "GuildConfigId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Permissionv2");
}
}
}

View File

@ -764,6 +764,34 @@ namespace NadekoBot.Migrations
b.ToTable("Permission"); b.ToTable("Permission");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime?>("DateAdded");
b.Property<int?>("GuildConfigId");
b.Property<int>("Index");
b.Property<int>("PrimaryTarget");
b.Property<ulong>("PrimaryTargetId");
b.Property<int>("SecondaryTarget");
b.Property<string>("SecondaryTargetName");
b.Property<bool>("State");
b.HasKey("Id");
b.HasIndex("GuildConfigId");
b.ToTable("Permissionv2");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -1112,6 +1140,13 @@ namespace NadekoBot.Migrations
.HasForeignKey("NadekoBot.Services.Database.Models.Permission", "NextId"); .HasForeignKey("NadekoBot.Services.Database.Models.Permission", "NextId");
}); });
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
.WithMany("Permissions")
.HasForeignKey("GuildConfigId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b =>
{ {
b.HasOne("NadekoBot.Services.Database.Models.BotConfig") b.HasOne("NadekoBot.Services.Database.Models.BotConfig")

View File

@ -11,6 +11,7 @@ using Discord.WebSocket;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using static NadekoBot.Modules.Permissions.Permissions; using static NadekoBot.Modules.Permissions.Permissions;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using Microsoft.EntityFrameworkCore;
using NLog; using NLog;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
@ -56,20 +57,12 @@ namespace NadekoBot.Modules.Administration
[RequireUserPermission(GuildPermission.Administrator)] [RequireUserPermission(GuildPermission.Administrator)]
public async Task ResetPermissions() public async Task ResetPermissions()
{ {
var channel = (ITextChannel)Context.Channel;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.PermissionsFor(Context.Guild.Id); var config = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.Permissions));
config.RootPermission = Permission.GetDefaultRoot(); config.Permissions = Permissionv2.GetDefaultPermlist;
var toAdd = new PermissionCache()
{
RootPermission = config.RootPermission,
PermRole = config.PermissionRole,
Verbose = config.VerbosePermissions,
};
Cache.AddOrUpdate(channel.Guild.Id,
toAdd, (id, old) => toAdd);
await uow.CompleteAsync(); await uow.CompleteAsync();
UpdateCache(config);
} }
await ReplyConfirmLocalized("perms_reset").ConfigureAwait(false); await ReplyConfirmLocalized("perms_reset").ConfigureAwait(false);
} }

View File

@ -81,8 +81,10 @@ namespace NadekoBot.Modules.Games
var msgs = new IUserMessage[dropAmount]; var msgs = new IUserMessage[dropAmount];
var prefix = NadekoBot.ModulePrefixes[typeof(Games).Name]; var prefix = NadekoBot.ModulePrefixes[typeof(Games).Name];
var toSend = dropAmount == 1 var toSend = dropAmount == 1
? GetLocalText(channel, "curgen_sn", NadekoBot.BotConfig.CurrencySign, prefix) ? GetLocalText(channel, "curgen_sn", NadekoBot.BotConfig.CurrencySign)
: GetLocalText(channel, "curgen_pl", dropAmount, NadekoBot.BotConfig.CurrencySign, prefix); + GetLocalText(channel, "pick_sn", prefix)
: GetLocalText(channel, "curgen_pl", dropAmount, NadekoBot.BotConfig.CurrencySign)
+ GetLocalText(channel, "pick_pl", prefix);
var file = GetRandomCurrencyImage(); var file = GetRandomCurrencyImage();
using (var fileStream = file.Value.ToStream()) using (var fileStream = file.Value.ToStream())
{ {
@ -159,6 +161,11 @@ namespace NadekoBot.Modules.Games
amount + NadekoBot.BotConfig.CurrencySign, amount + NadekoBot.BotConfig.CurrencySign,
Prefix); Prefix);
if (amount > 1)
msgToSend += GetText("pick_pl", Prefix);
else
msgToSend += GetText("pick_sn", Prefix);
IUserMessage msg; IUserMessage msg;
using (var toSend = imgData.Value.ToStream()) using (var toSend = imgData.Value.ToStream())
{ {

View File

@ -236,7 +236,7 @@ namespace NadekoBot.Modules.Games
{ {
hot = NextDouble(8, 10); hot = NextDouble(8, 10);
crazy = NextDouble(5, 7); crazy = NextDouble(5, 7);
advice = "Above an 8 hot, and between about 7 and a 5 crazy - this is WIFE ZONE. You you meet this girl, you should consider long-term " + advice = "Above an 8 hot, and between about 7 and a 5 crazy - this is WIFE ZONE. If you meet this girl, you should consider long-term " +
"relationship. Rare."; "relationship. Rare.";
} }
else if (roll < 999) else if (roll < 999)
@ -244,7 +244,7 @@ namespace NadekoBot.Modules.Games
hot = NextDouble(8, 10); hot = NextDouble(8, 10);
crazy = NextDouble(2, 3.99d); crazy = NextDouble(2, 3.99d);
advice = "You've met a girl she's above 8 hot, and not crazy at all (below 4)... totally cool?" + advice = "You've met a girl she's above 8 hot, and not crazy at all (below 4)... totally cool?" +
" You should be careful. That's a dude. It's a tranny."; " You should be careful. That's a dude. You're talking to a tranny!";
} }
else else
{ {

View File

@ -10,25 +10,12 @@ namespace NadekoBot.Modules.Permissions
{ {
public static class PermissionExtensions public static class PermissionExtensions
{ {
public static bool CheckPermissions(this IEnumerable<Permission> permsEnumerable, IUserMessage message, CommandInfo command) public static bool CheckPermissions(this IEnumerable<Permissionv2> permsEnumerable, IUserMessage message,
string commandName, string moduleName, out int permIndex)
{ {
var perms = permsEnumerable as List<Permission> ?? permsEnumerable.ToList(); var perms = permsEnumerable as List<Permissionv2> ?? permsEnumerable.ToList();
int throwaway;
return perms.CheckPermissions(message, command.Name, command.Module.Name, out throwaway);
}
public static bool CheckPermissions(this IEnumerable<Permission> permsEnumerable, IUserMessage message, string commandName, string moduleName) for (int i = perms.Count - 1; i >= 0; i--)
{
var perms = permsEnumerable as List<Permission> ?? permsEnumerable.ToList();
int throwaway;
return perms.CheckPermissions(message, commandName, moduleName, out throwaway);
}
public static bool CheckPermissions(this IEnumerable<Permission> permsEnumerable, IUserMessage message, string commandName, string moduleName, out int permIndex)
{
var perms = permsEnumerable as List<Permission> ?? permsEnumerable.ToList();
for (int i = 0; i < perms.Count; i++)
{ {
var perm = perms[i]; var perm = perms[i];
@ -38,12 +25,9 @@ namespace NadekoBot.Modules.Permissions
{ {
continue; continue;
} }
else
{
permIndex = i; permIndex = i;
return result.Value; return result.Value;
} }
}
permIndex = -1; //defaut behaviour permIndex = -1; //defaut behaviour
return true; return true;
} }
@ -51,7 +35,7 @@ namespace NadekoBot.Modules.Permissions
//null = not applicable //null = not applicable
//true = applicable, allowed //true = applicable, allowed
//false = applicable, not allowed //false = applicable, not allowed
public static bool? CheckPermission(this Permission perm, IUserMessage message, string commandName, string moduleName) public static bool? CheckPermission(this Permissionv2 perm, IUserMessage message, string commandName, string moduleName)
{ {
if (!((perm.SecondaryTarget == SecondaryPermissionType.Command && if (!((perm.SecondaryTarget == SecondaryPermissionType.Command &&
perm.SecondaryTargetName.ToLowerInvariant() == commandName.ToLowerInvariant()) || perm.SecondaryTargetName.ToLowerInvariant() == commandName.ToLowerInvariant()) ||
@ -86,7 +70,7 @@ namespace NadekoBot.Modules.Permissions
return null; return null;
} }
public static string GetCommand(this Permission perm, SocketGuild guild = null) public static string GetCommand(this Permissionv2 perm, SocketGuild guild = null)
{ {
var com = ""; var com = "";
switch (perm.PrimaryTarget) switch (perm.PrimaryTarget)
@ -143,98 +127,10 @@ namespace NadekoBot.Modules.Permissions
return NadekoBot.ModulePrefixes[typeof(Permissions).Name] + com; return NadekoBot.ModulePrefixes[typeof(Permissions).Name] + com;
} }
public static void Prepend(this Permission perm, Permission toAdd)
{
perm = perm.GetRoot();
perm.Previous = toAdd;
toAdd.Next = perm;
}
/* /this can't work if index < 0 and perm isn't roo
public static void Insert(this Permission perm, int index, Permission toAdd)
{
if (index < 0)
throw new IndexOutOfRangeException();
if (index == 0)
{
perm.Prepend(toAdd);
return;
}
var atIndex = perm;
var i = 0;
while (i != index)
{
atIndex = atIndex.Next;
i++;
if (atIndex == null)
throw new IndexOutOfRangeException();
}
var previous = atIndex.Previous;
//connect right side
atIndex.Previous = toAdd;
toAdd.Next = atIndex;
//connect left side
toAdd.Previous = previous;
previous.Next = toAdd;
}
*/
public static Permission RemoveAt(this Permission perm, int index)
{
if (index <= 0) //can't really remove at 0, that means deleting the element right now. Just use perm.Next if its 0
throw new IndexOutOfRangeException();
var toRemove = perm;
var i = 0;
while (i != index)
{
toRemove = toRemove.Next;
i++;
if (toRemove == null)
throw new IndexOutOfRangeException();
}
toRemove.Previous.Next = toRemove.Next;
if (toRemove.Next != null)
toRemove.Next.Previous = toRemove.Previous;
return toRemove;
}
public static Permission GetAt(this Permission perm, int index)
{
if (index < 0)
throw new IndexOutOfRangeException();
var temp = perm;
while (index > 0) { temp = temp?.Next; index--; }
if (temp == null)
throw new IndexOutOfRangeException();
return temp;
}
public static int Count(this Permission perm)
{
var i = 1;
var temp = perm;
while ((temp = temp.Next) != null) { i++; }
return i;
}
public static IEnumerable<Permission> AsEnumerable(this Permission perm) public static IEnumerable<Permission> AsEnumerable(this Permission perm)
{ {
do yield return perm; do yield return perm;
while ((perm = perm.Next) != null); while ((perm = perm.Next) != null);
} }
public static Permission GetRoot(this Permission perm)
{
Permission toReturn;
do toReturn = perm;
while ((perm = perm.Previous) != null);
return toReturn;
}
} }
} }

View File

@ -7,9 +7,11 @@ using NadekoBot.Services;
using Discord; using Discord;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using NadekoBot.Extensions; using System.Collections.Generic;
using Discord.WebSocket; using Discord.WebSocket;
using System.Diagnostics; using System.Diagnostics;
using Microsoft.EntityFrameworkCore;
using NadekoBot.DataStructures;
using NLog; using NLog;
namespace NadekoBot.Modules.Permissions namespace NadekoBot.Modules.Permissions
@ -17,36 +19,137 @@ namespace NadekoBot.Modules.Permissions
[NadekoModule("Permissions", ";")] [NadekoModule("Permissions", ";")]
public partial class Permissions : NadekoTopLevelModule public partial class Permissions : NadekoTopLevelModule
{ {
public class PermissionCache public class OldPermissionCache
{ {
public string PermRole { get; set; } public string PermRole { get; set; }
public bool Verbose { get; set; } = true; public bool Verbose { get; set; } = true;
public Permission RootPermission { get; set; } public Permission RootPermission { get; set; }
} }
public class PermissionCache
{
public string PermRole { get; set; }
public bool Verbose { get; set; } = true;
public PermissionsCollection<Permissionv2> Permissions { get; set; }
}
//guildid, root permission //guildid, root permission
public static ConcurrentDictionary<ulong, PermissionCache> Cache { get; } public static ConcurrentDictionary<ulong, PermissionCache> Cache { get; } =
new ConcurrentDictionary<ulong, PermissionCache>();
static Permissions() static Permissions()
{ {
var log = LogManager.GetCurrentClassLogger(); var log = LogManager.GetCurrentClassLogger();
var sw = Stopwatch.StartNew(); var sw = Stopwatch.StartNew();
TryMigratePermissions();
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
Cache = new ConcurrentDictionary<ulong, PermissionCache>(uow.GuildConfigs foreach (var x in uow.GuildConfigs.Permissionsv2ForAll())
.PermissionsForAll() {
Cache.TryAdd(x.GuildId, new PermissionCache()
{
Verbose = x.VerbosePermissions,
PermRole = x.PermissionRole,
Permissions = new PermissionsCollection<Permissionv2>(x.Permissions)
});
}
}
sw.Stop();
log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
}
private static void TryMigratePermissions()
{
var log = LogManager.GetCurrentClassLogger();
using (var uow = DbHandler.UnitOfWork())
{
var oldCache = new ConcurrentDictionary<ulong, OldPermissionCache>(uow.GuildConfigs
.OldPermissionsForAll()
.Where(x => x.RootPermission != null) // there is a check inside already, but just in case
.ToDictionary(k => k.GuildId, .ToDictionary(k => k.GuildId,
v => new PermissionCache() v => new OldPermissionCache()
{ {
RootPermission = v.RootPermission, RootPermission = v.RootPermission,
Verbose = v.VerbosePermissions, Verbose = v.VerbosePermissions,
PermRole = v.PermissionRole PermRole = v.PermissionRole
})); }));
if (oldCache.Any())
{
log.Info("Old permissions found. Performing one-time migration to v2.");
var i = 0;
foreach (var oc in oldCache)
{
if (i % 3 == 0)
log.Info("Migrating Permissions #" + ++i + " - GuildId: " + oc.Key);
var gc = uow.GuildConfigs.For(oc.Key, set => set.Include(x => x.Permissions));
var oldPerms = oc.Value.RootPermission.AsEnumerable().Reverse().ToList();
gc.RootPermission = null;
if (oldPerms.Count > 2)
{
var newPerms = oldPerms.Take(oldPerms.Count - 1)
.Select(x => x.Tov2())
.ToList();
var allowPerm = Permissionv2.AllowAllPerm;
var firstPerm = newPerms[0];
if (allowPerm.State != firstPerm.State ||
allowPerm.PrimaryTarget != firstPerm.PrimaryTarget ||
allowPerm.SecondaryTarget != firstPerm.SecondaryTarget ||
allowPerm.PrimaryTargetId != firstPerm.PrimaryTargetId ||
allowPerm.SecondaryTargetName != firstPerm.SecondaryTargetName)
newPerms.Insert(0, Permissionv2.AllowAllPerm);
Cache.TryAdd(oc.Key, new PermissionCache
{
Permissions = new PermissionsCollection<Permissionv2>(newPerms),
Verbose = gc.VerbosePermissions,
PermRole = gc.PermissionRole,
});
gc.Permissions = newPerms;
}
}
log.Info("Permission migration to v2 is done.");
uow.Complete();
}
}
} }
sw.Stop(); private static async Task AddPermissions(ulong guildId, params Permissionv2[] perms)
log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s"); {
using (var uow = DbHandler.UnitOfWork())
{
var config = uow.GuildConfigs.For(guildId, set => set.Include(x => x.Permissions));
//var orderedPerms = new PermissionsCollection<Permissionv2>(config.Permissions);
var max = config.Permissions.Max(x => x.Index); //have to set its index to be the highest
foreach (var perm in perms)
{
perm.Index = ++max;
config.Permissions.Add(perm);
}
await uow.CompleteAsync().ConfigureAwait(false);
UpdateCache(config);
}
}
public static void UpdateCache(GuildConfig config)
{
Cache.AddOrUpdate(config.GuildId, new PermissionCache()
{
Permissions = new PermissionsCollection<Permissionv2>(config.Permissions),
PermRole = config.PermissionRole,
Verbose = config.VerbosePermissions
}, (id, old) =>
{
old.Permissions = new PermissionsCollection<Permissionv2>(config.Permissions);
old.PermRole = config.PermissionRole;
old.Verbose = config.VerbosePermissions;
return old;
});
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
@ -57,13 +160,8 @@ namespace NadekoBot.Modules.Permissions
{ {
var config = uow.GuildConfigs.For(Context.Guild.Id, set => set); var config = uow.GuildConfigs.For(Context.Guild.Id, set => set);
config.VerbosePermissions = action.Value; config.VerbosePermissions = action.Value;
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = Permission.GetDefaultRoot(),
Verbose = config.VerbosePermissions
}, (id, old) => { old.Verbose = config.VerbosePermissions; return old; });
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
UpdateCache(config);
} }
if (action.Value) if (action.Value)
{ {
@ -91,13 +189,8 @@ namespace NadekoBot.Modules.Permissions
return; return;
} }
config.PermissionRole = role.Name.Trim(); config.PermissionRole = role.Name.Trim();
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = Permission.GetDefaultRoot(),
Verbose = config.VerbosePermissions
}, (id, old) => { old.PermRole = role.Name.Trim(); return old; });
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
UpdateCache(config);
} }
await ReplyConfirmLocalized("permrole_changed", Format.Bold(role.Name)).ConfigureAwait(false); await ReplyConfirmLocalized("permrole_changed", Format.Bold(role.Name)).ConfigureAwait(false);
@ -109,19 +202,32 @@ namespace NadekoBot.Modules.Permissions
{ {
if (page < 1 || page > 4) if (page < 1 || page > 4)
return; return;
string toSend;
using (var uow = DbHandler.UnitOfWork()) PermissionCache permCache;
IList<Permissionv2> perms;
if (Cache.TryGetValue(Context.Guild.Id, out permCache))
{ {
var perms = uow.GuildConfigs.PermissionsFor(Context.Guild.Id).RootPermission; perms = permCache.Permissions.Source.ToList();
var i = 1 + 20 * (page - 1); }
toSend = Format.Bold(GetText("page", page)) + "\n\n" + string.Join("\n", else
perms.AsEnumerable() {
perms = Permissionv2.GetDefaultPermlist;
}
var startPos = 20 * (page - 1);
var toSend = Format.Bold(GetText("page", page)) + "\n\n" + string.Join("\n",
perms.Reverse()
.Skip((page - 1) * 20) .Skip((page - 1) * 20)
.Take(20) .Take(20)
.Select( .Select(p =>
p => {
$"`{(i++)}.` {(p.Next == null ? Format.Bold(p.GetCommand((SocketGuild) Context.Guild) + $" [{GetText("uneditable")}]") : (p.GetCommand((SocketGuild) Context.Guild)))}")); var str =
} $"`{p.Index + startPos + 1}.` {Format.Bold(p.GetCommand((SocketGuild) Context.Guild))}";
if (p.Index == 0)
str += $" [{GetText("uneditable")}]";
return str;
}));
await Context.Channel.SendMessageAsync(toSend).ConfigureAwait(false); await Context.Channel.SendMessageAsync(toSend).ConfigureAwait(false);
} }
@ -131,39 +237,20 @@ namespace NadekoBot.Modules.Permissions
public async Task RemovePerm(int index) public async Task RemovePerm(int index)
{ {
index -= 1; index -= 1;
if (index < 0)
return;
try try
{ {
Permission p; Permissionv2 p;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.PermissionsFor(Context.Guild.Id); var config = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.Permissions));
var perms = config.RootPermission; var permsCol = new PermissionsCollection<Permissionv2>(config.Permissions);
if (index == perms.Count() - 1) p = permsCol[index];
{ permsCol.RemoveAt(index);
return; uow._context.Remove(p);
}
if (index == 0)
{
p = perms;
config.RootPermission = perms.Next;
}
else
{
p = perms.RemoveAt(index);
}
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} UpdateCache(config);
using (var uow2 = DbHandler.UnitOfWork())
{
uow2._context.Remove<Permission>(p);
uow2._context.SaveChanges();
} }
await ReplyConfirmLocalized("removed", await ReplyConfirmLocalized("removed",
index + 1, index + 1,
@ -185,36 +272,15 @@ namespace NadekoBot.Modules.Permissions
{ {
try try
{ {
Permission fromPerm = null; Permissionv2 fromPerm;
Permission toPerm = null;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.PermissionsFor(Context.Guild.Id); var config = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.Permissions));
var perms = config.RootPermission; var permsCol = new PermissionsCollection<Permissionv2>(config.Permissions);
var index = 0;
var fromFound = false; var fromFound = from < permsCol.Count;
var toFound = false; var toFound = to < permsCol.Count;
while ((!toFound || !fromFound) && perms != null)
{
if (index == from)
{
fromPerm = perms;
fromFound = true;
}
if (index == to)
{
toPerm = perms;
toFound = true;
}
if (!toFound)
{
toPerm = perms; //In case of to > size
}
perms = perms.Next;
index++;
}
if (perms == null)
{
if (!fromFound) if (!fromFound)
{ {
await ReplyErrorLocalized("not_found", ++from).ConfigureAwait(false); await ReplyErrorLocalized("not_found", ++from).ConfigureAwait(false);
@ -226,51 +292,12 @@ namespace NadekoBot.Modules.Permissions
await ReplyErrorLocalized("not_found", ++to).ConfigureAwait(false); await ReplyErrorLocalized("not_found", ++to).ConfigureAwait(false);
return; return;
} }
} fromPerm = permsCol[from];
//Change chain for from indx permsCol.RemoveAt(from);
var next = fromPerm.Next; permsCol.Insert(to, fromPerm);
var pre = fromPerm.Previous;
if (pre != null)
pre.Next = next;
if (fromPerm.Next == null || toPerm.Next == null)
{
throw new IndexOutOfRangeException();
}
next.Previous = pre;
if (from == 0)
{
}
await uow.CompleteAsync().ConfigureAwait(false);
//Inserting
if (to > from)
{
fromPerm.Previous = toPerm;
fromPerm.Next = toPerm.Next;
toPerm.Next.Previous = fromPerm;
toPerm.Next = fromPerm;
}
else
{
pre = toPerm.Previous;
fromPerm.Next = toPerm;
fromPerm.Previous = pre;
toPerm.Previous = fromPerm;
if (pre != null)
pre.Next = fromPerm;
}
config.RootPermission = fromPerm.GetRoot();
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
UpdateCache(config);
} }
await ReplyConfirmLocalized("moved_permission", await ReplyConfirmLocalized("moved_permission",
Format.Code(fromPerm.GetCommand((SocketGuild) Context.Guild)), Format.Code(fromPerm.GetCommand((SocketGuild) Context.Guild)),
@ -290,26 +317,14 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task SrvrCmd(CommandInfo command, PermissionAction action) public async Task SrvrCmd(CommandInfo command, PermissionAction action)
{ {
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.Server, PrimaryTarget = PrimaryPermissionType.Server,
PrimaryTargetId = 0, PrimaryTargetId = 0,
SecondaryTarget = SecondaryPermissionType.Command, SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Aliases.First().ToLowerInvariant(), SecondaryTargetName = command.Aliases.First().ToLowerInvariant(),
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
@ -329,25 +344,14 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task SrvrMdl(ModuleInfo module, PermissionAction action) public async Task SrvrMdl(ModuleInfo module, PermissionAction action)
{ {
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.Server, PrimaryTarget = PrimaryPermissionType.Server,
PrimaryTargetId = 0, PrimaryTargetId = 0,
SecondaryTarget = SecondaryPermissionType.Module, SecondaryTarget = SecondaryPermissionType.Module,
SecondaryTargetName = module.Name.ToLowerInvariant(), SecondaryTargetName = module.Name.ToLowerInvariant(),
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
@ -367,25 +371,14 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task UsrCmd(CommandInfo command, PermissionAction action, [Remainder] IGuildUser user) public async Task UsrCmd(CommandInfo command, PermissionAction action, [Remainder] IGuildUser user)
{ {
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.User, PrimaryTarget = PrimaryPermissionType.User,
PrimaryTargetId = user.Id, PrimaryTargetId = user.Id,
SecondaryTarget = SecondaryPermissionType.Command, SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Aliases.First().ToLowerInvariant(), SecondaryTargetName = command.Aliases.First().ToLowerInvariant(),
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
@ -407,25 +400,14 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task UsrMdl(ModuleInfo module, PermissionAction action, [Remainder] IGuildUser user) public async Task UsrMdl(ModuleInfo module, PermissionAction action, [Remainder] IGuildUser user)
{ {
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.User, PrimaryTarget = PrimaryPermissionType.User,
PrimaryTargetId = user.Id, PrimaryTargetId = user.Id,
SecondaryTarget = SecondaryPermissionType.Module, SecondaryTarget = SecondaryPermissionType.Module,
SecondaryTargetName = module.Name.ToLowerInvariant(), SecondaryTargetName = module.Name.ToLowerInvariant(),
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
@ -450,25 +432,14 @@ namespace NadekoBot.Modules.Permissions
if (role == role.Guild.EveryoneRole) if (role == role.Guild.EveryoneRole)
return; return;
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.Role, PrimaryTarget = PrimaryPermissionType.Role,
PrimaryTargetId = role.Id, PrimaryTargetId = role.Id,
SecondaryTarget = SecondaryPermissionType.Command, SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Aliases.First().ToLowerInvariant(), SecondaryTargetName = command.Aliases.First().ToLowerInvariant(),
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
@ -493,25 +464,14 @@ namespace NadekoBot.Modules.Permissions
if (role == role.Guild.EveryoneRole) if (role == role.Guild.EveryoneRole)
return; return;
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.Role, PrimaryTarget = PrimaryPermissionType.Role,
PrimaryTargetId = role.Id, PrimaryTargetId = role.Id,
SecondaryTarget = SecondaryPermissionType.Module, SecondaryTarget = SecondaryPermissionType.Module,
SecondaryTargetName = module.Name.ToLowerInvariant(), SecondaryTargetName = module.Name.ToLowerInvariant(),
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
@ -534,25 +494,14 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ChnlCmd(CommandInfo command, PermissionAction action, [Remainder] ITextChannel chnl) public async Task ChnlCmd(CommandInfo command, PermissionAction action, [Remainder] ITextChannel chnl)
{ {
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.Channel, PrimaryTarget = PrimaryPermissionType.Channel,
PrimaryTargetId = chnl.Id, PrimaryTargetId = chnl.Id,
SecondaryTarget = SecondaryPermissionType.Command, SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Aliases.First().ToLowerInvariant(), SecondaryTargetName = command.Aliases.First().ToLowerInvariant(),
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
@ -574,25 +523,14 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ChnlMdl(ModuleInfo module, PermissionAction action, [Remainder] ITextChannel chnl) public async Task ChnlMdl(ModuleInfo module, PermissionAction action, [Remainder] ITextChannel chnl)
{ {
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.Channel, PrimaryTarget = PrimaryPermissionType.Channel,
PrimaryTargetId = chnl.Id, PrimaryTargetId = chnl.Id,
SecondaryTarget = SecondaryPermissionType.Module, SecondaryTarget = SecondaryPermissionType.Module,
SecondaryTargetName = module.Name.ToLowerInvariant(), SecondaryTargetName = module.Name.ToLowerInvariant(),
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
@ -614,25 +552,14 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task AllChnlMdls(PermissionAction action, [Remainder] ITextChannel chnl) public async Task AllChnlMdls(PermissionAction action, [Remainder] ITextChannel chnl)
{ {
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.Channel, PrimaryTarget = PrimaryPermissionType.Channel,
PrimaryTargetId = chnl.Id, PrimaryTargetId = chnl.Id,
SecondaryTarget = SecondaryPermissionType.AllModules, SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*", SecondaryTargetName = "*",
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
@ -653,25 +580,14 @@ namespace NadekoBot.Modules.Permissions
if (role == role.Guild.EveryoneRole) if (role == role.Guild.EveryoneRole)
return; return;
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.Role, PrimaryTarget = PrimaryPermissionType.Role,
PrimaryTargetId = role.Id, PrimaryTargetId = role.Id,
SecondaryTarget = SecondaryPermissionType.AllModules, SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*", SecondaryTargetName = "*",
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
@ -689,25 +605,14 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task AllUsrMdls(PermissionAction action, [Remainder] IUser user) public async Task AllUsrMdls(PermissionAction action, [Remainder] IUser user)
{ {
using (var uow = DbHandler.UnitOfWork()) await AddPermissions(Context.Guild.Id, new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.User, PrimaryTarget = PrimaryPermissionType.User,
PrimaryTargetId = user.Id, PrimaryTargetId = user.Id,
SecondaryTarget = SecondaryPermissionType.AllModules, SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*", SecondaryTargetName = "*",
State = action.Value, State = action.Value,
}; });
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {
@ -725,9 +630,7 @@ namespace NadekoBot.Modules.Permissions
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task AllSrvrMdls(PermissionAction action) public async Task AllSrvrMdls(PermissionAction action)
{ {
using (var uow = DbHandler.UnitOfWork()) var newPerm = new Permissionv2
{
var newPerm = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.Server, PrimaryTarget = PrimaryPermissionType.Server,
PrimaryTargetId = 0, PrimaryTargetId = 0,
@ -735,9 +638,8 @@ namespace NadekoBot.Modules.Permissions
SecondaryTargetName = "*", SecondaryTargetName = "*",
State = action.Value, State = action.Value,
}; };
uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
var allowUser = new Permission var allowUser = new Permissionv2
{ {
PrimaryTarget = PrimaryPermissionType.User, PrimaryTarget = PrimaryPermissionType.User,
PrimaryTargetId = Context.User.Id, PrimaryTargetId = Context.User.Id,
@ -746,15 +648,9 @@ namespace NadekoBot.Modules.Permissions
State = true, State = true,
}; };
var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, allowUser); await AddPermissions(Context.Guild.Id,
Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache() newPerm,
{ allowUser);
PermRole = config.PermissionRole,
RootPermission = config.RootPermission,
Verbose = config.VerbosePermissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action.Value) if (action.Value)
{ {

View File

@ -22,7 +22,7 @@ namespace NadekoBot.Modules.Utility
[NadekoModule("Utility", ".")] [NadekoModule("Utility", ".")]
public partial class Utility : NadekoTopLevelModule public partial class Utility : NadekoTopLevelModule
{ {
private static ConcurrentDictionary<ulong, Timer> rotatingRoleColors = new ConcurrentDictionary<ulong, Timer>(); private static ConcurrentDictionary<ulong, Timer> _rotatingRoleColors = new ConcurrentDictionary<ulong, Timer>();
//[NadekoCommand, Usage, Description, Aliases] //[NadekoCommand, Usage, Description, Aliases]
//[RequireContext(ContextType.Guild)] //[RequireContext(ContextType.Guild)]
@ -114,7 +114,7 @@ namespace NadekoBot.Modules.Utility
Timer t; Timer t;
if (timeout == 0 || hexes.Length == 0) if (timeout == 0 || hexes.Length == 0)
{ {
if (rotatingRoleColors.TryRemove(role.Id, out t)) if (_rotatingRoleColors.TryRemove(role.Id, out t))
{ {
t.Change(Timeout.Infinite, Timeout.Infinite); t.Change(Timeout.Infinite, Timeout.Infinite);
await ReplyConfirmLocalized("rrc_stop", Format.Bold(role.Name)).ConfigureAwait(false); await ReplyConfirmLocalized("rrc_stop", Format.Bold(role.Name)).ConfigureAwait(false);
@ -157,7 +157,7 @@ namespace NadekoBot.Modules.Utility
catch { } catch { }
}, null, 0, timeout * 1000); }, null, 0, timeout * 1000);
rotatingRoleColors.AddOrUpdate(role.Id, t, (key, old) => _rotatingRoleColors.AddOrUpdate(role.Id, t, (key, old) =>
{ {
old.Change(Timeout.Infinite, Timeout.Infinite); old.Change(Timeout.Infinite, Timeout.Infinite);
return t; return t;

View File

@ -96,7 +96,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Starts an Acrophobia game. Second argment is optional round length in seconds. (default is 60). /// Looks up a localized string similar to Starts an Acrophobia game. Second argument is optional round length in seconds. (default is 60).
/// </summary> /// </summary>
public static string acro_desc { public static string acro_desc {
get { get {

View File

@ -2794,7 +2794,7 @@
<value>acrophobia acro</value> <value>acrophobia acro</value>
</data> </data>
<data name="acro_desc" xml:space="preserve"> <data name="acro_desc" xml:space="preserve">
<value>Starts an Acrophobia game. Second argment is optional round length in seconds. (default is 60)</value> <value>Starts an Acrophobia game. Second argument is optional round length in seconds. (default is 60)</value>
</data> </data>
<data name="acro_usage" xml:space="preserve"> <data name="acro_usage" xml:space="preserve">
<value>`{0}acro` or `{0}acro 30`</value> <value>`{0}acro` or `{0}acro 30`</value>

View File

@ -2914,7 +2914,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to {0} random {1} appeared! Pick them up by typing `{2}pick`. /// Looks up a localized string similar to {0} random {1} appeared!.
/// </summary> /// </summary>
public static string games_curgen_pl { public static string games_curgen_pl {
get { get {
@ -2923,7 +2923,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to A random {0} appeared! Pick it up by typing `{1}pick`. /// Looks up a localized string similar to A random {0} appeared!.
/// </summary> /// </summary>
public static string games_curgen_sn { public static string games_curgen_sn {
get { get {
@ -3030,6 +3030,24 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Pick them up by typing `{0}pick`.
/// </summary>
public static string games_pick_pl {
get {
return ResourceManager.GetString("games_pick_pl", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Pick it up by typing `{0}pick`.
/// </summary>
public static string games_pick_sn {
get {
return ResourceManager.GetString("games_pick_sn", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to picked {0}. /// Looks up a localized string similar to picked {0}.
/// </summary> /// </summary>

View File

@ -1239,11 +1239,11 @@ Don't forget to leave your discord name or id in the message.
<value>Currency generation has been enabled on this channel.</value> <value>Currency generation has been enabled on this channel.</value>
</data> </data>
<data name="games_curgen_pl" xml:space="preserve"> <data name="games_curgen_pl" xml:space="preserve">
<value>{0} random {1} appeared! Pick them up by typing `{2}pick`</value> <value>{0} random {1} appeared!</value>
<comment>plural</comment> <comment>plural</comment>
</data> </data>
<data name="games_curgen_sn" xml:space="preserve"> <data name="games_curgen_sn" xml:space="preserve">
<value>A random {0} appeared! Pick it up by typing `{1}pick`</value> <value>A random {0} appeared!</value>
</data> </data>
<data name="games_failed_loading_question" xml:space="preserve"> <data name="games_failed_loading_question" xml:space="preserve">
<value>Failed loading a question.</value> <value>Failed loading a question.</value>
@ -2218,4 +2218,10 @@ Owner ID: {2}</value>
<data name="games_x_votes_cast" xml:space="preserve"> <data name="games_x_votes_cast" xml:space="preserve">
<value>{0} total votes cast.</value> <value>{0} total votes cast.</value>
</data> </data>
<data name="games_pick_pl" xml:space="preserve">
<value>Pick them up by typing `{0}pick`</value>
</data>
<data name="games_pick_sn" xml:space="preserve">
<value>Pick it up by typing `{0}pick`</value>
</data>
</root> </root>

View File

@ -16,6 +16,7 @@ using NadekoBot.Modules.CustomReactions;
using NadekoBot.Modules.Games; using NadekoBot.Modules.Games;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Threading; using System.Threading;
using Microsoft.EntityFrameworkCore;
using NadekoBot.DataStructures; using NadekoBot.DataStructures;
namespace NadekoBot.Services namespace NadekoBot.Services
@ -378,28 +379,26 @@ namespace NadekoBot.Services
} }
var cmd = commands[i].Command; var cmd = commands[i].Command;
bool resetCommand = cmd.Name == "resetperms"; var resetCommand = cmd.Name == "resetperms";
var module = cmd.Module.GetTopLevelModule(); var module = cmd.Module.GetTopLevelModule();
PermissionCache pc; PermissionCache pc;
if (context.Guild != null) if (context.Guild != null)
{ {
pc = Permissions.Cache.GetOrAdd(context.Guild.Id, (id) => if (!Permissions.Cache.TryGetValue(context.Guild.Id, out pc))
{ {
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.PermissionsFor(context.Guild.Id); var config = uow.GuildConfigs.For(context.Guild.Id, set => set.Include(x => x.Permissions));
return new PermissionCache() Permissions.UpdateCache(config);
{ }
Verbose = config.VerbosePermissions, Permissions.Cache.TryGetValue(context.Guild.Id, out pc);
RootPermission = config.RootPermission, if(pc == null)
PermRole = config.PermissionRole.Trim().ToLowerInvariant(), throw new Exception("Cache is null.");
};
} }
});
int index; int index;
if (!resetCommand && !pc.RootPermission.AsEnumerable().CheckPermissions(context.Message, cmd.Aliases.First(), module.Name, out index)) if (!resetCommand && !pc.Permissions.CheckPermissions(context.Message, cmd.Aliases.First(), module.Name, out index))
{ {
var returnMsg = $"Permission number #{index + 1} **{pc.RootPermission.GetAt(index).GetCommand((SocketGuild)context.Guild)}** is preventing this action."; var returnMsg = $"Permission number #{index + 1} **{pc.Permissions[index].GetCommand((SocketGuild)context.Guild)}** is preventing this action.";
return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, returnMsg)); return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, returnMsg));
} }

View File

@ -41,7 +41,8 @@ namespace NadekoBot.Services.Database.Models
public HashSet<GCChannelId> GenerateCurrencyChannelIds { get; set; } = new HashSet<GCChannelId>(); public HashSet<GCChannelId> GenerateCurrencyChannelIds { get; set; } = new HashSet<GCChannelId>();
//permissions //permissions
public Permission RootPermission { get; set; } public Permission RootPermission { get; set; } = null;
public List<Permissionv2> Permissions { get; set; }
public bool VerbosePermissions { get; set; } = true; public bool VerbosePermissions { get; set; } = true;
public string PermissionRole { get; set; } = "Nadeko"; public string PermissionRole { get; set; } = "Nadeko";

View File

@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations.Schema; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics; using System.Diagnostics;
namespace NadekoBot.Services.Database.Models namespace NadekoBot.Services.Database.Models
@ -17,46 +18,100 @@ namespace NadekoBot.Services.Database.Models
public bool State { get; set; } public bool State { get; set; }
public Permissionv2 Tov2() =>
new Permissionv2()
{
PrimaryTarget = PrimaryTarget,
PrimaryTargetId = PrimaryTargetId,
SecondaryTarget = SecondaryTarget,
SecondaryTargetName = SecondaryTargetName,
State = State,
};
//[NotMapped]
//private static Permission AllowAllPerm => new Permission()
//{
// PrimaryTarget = PrimaryPermissionType.Server,
// PrimaryTargetId = 0,
// SecondaryTarget = SecondaryPermissionType.AllModules,
// SecondaryTargetName = "*",
// State = true,
//};
//[NotMapped]
//private static Permission BlockNsfwPerm => new Permission()
//{
// PrimaryTarget = PrimaryPermissionType.Server,
// PrimaryTargetId = 0,
// SecondaryTarget = SecondaryPermissionType.Module,
// SecondaryTargetName = "nsfw",
// State = false,
//};
//public Permission Clone() => new Permission()
//{
// PrimaryTarget = PrimaryTarget,
// SecondaryTarget = SecondaryTarget,
// PrimaryTargetId = PrimaryTargetId,
// SecondaryTargetName = SecondaryTargetName,
// State = State,
//};
}
public interface IIndexed
{
int Index { get; set; }
}
public class Permissionv2 : DbEntity, IIndexed
{
public int GuildConfigId { get; set; }
public int Index { get; set; }
public PrimaryPermissionType PrimaryTarget { get; set; }
public ulong PrimaryTargetId { get; set; }
public SecondaryPermissionType SecondaryTarget { get; set; }
public string SecondaryTargetName { get; set; }
public bool State { get; set; }
[NotMapped] [NotMapped]
private static Permission AllowAllPerm => new Permission() public static Permissionv2 AllowAllPerm => new Permissionv2()
{ {
PrimaryTarget = PrimaryPermissionType.Server, PrimaryTarget = PrimaryPermissionType.Server,
PrimaryTargetId = 0, PrimaryTargetId = 0,
SecondaryTarget = SecondaryPermissionType.AllModules, SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*", SecondaryTargetName = "*",
State = true, State = true,
Index = 0,
}; };
[NotMapped] [NotMapped]
private static Permission BlockNsfwPerm => new Permission() private static Permissionv2 BlockNsfwPerm => new Permissionv2()
{ {
PrimaryTarget = PrimaryPermissionType.Server, PrimaryTarget = PrimaryPermissionType.Server,
PrimaryTargetId = 0, PrimaryTargetId = 0,
SecondaryTarget = SecondaryPermissionType.Module, SecondaryTarget = SecondaryPermissionType.Module,
SecondaryTargetName = "nsfw", SecondaryTargetName = "nsfw",
State = false, State = false,
Index = 1
}; };
public static Permission GetDefaultRoot() public static List<Permissionv2> GetDefaultPermlist =>
new List<Permissionv2>
{ {
var root = AllowAllPerm; BlockNsfwPerm,
var blockNsfw = BlockNsfwPerm; AllowAllPerm
root.Previous = blockNsfw;
blockNsfw.Next = root;
return blockNsfw;
}
public Permission Clone() => new Permission()
{
PrimaryTarget = PrimaryTarget,
SecondaryTarget = SecondaryTarget,
PrimaryTargetId = PrimaryTargetId,
SecondaryTargetName = SecondaryTargetName,
State = State,
}; };
}
//public Permission Clone() => new Permission()
//{
// PrimaryTarget = PrimaryTarget,
// SecondaryTarget = SecondaryTarget,
// PrimaryTargetId = PrimaryTargetId,
// SecondaryTargetName = SecondaryTargetName,
// State = State,
//};
}
public enum PrimaryPermissionType public enum PrimaryPermissionType
{ {
User, User,

View File

@ -10,11 +10,10 @@ namespace NadekoBot.Services.Database.Repositories
{ {
GuildConfig For(ulong guildId, Func<DbSet<GuildConfig>, IQueryable<GuildConfig>> includes = null); GuildConfig For(ulong guildId, Func<DbSet<GuildConfig>, IQueryable<GuildConfig>> includes = null);
GuildConfig LogSettingsFor(ulong guildId); GuildConfig LogSettingsFor(ulong guildId);
GuildConfig PermissionsFor(ulong guildId); IEnumerable<GuildConfig> OldPermissionsForAll();
IEnumerable<GuildConfig> PermissionsForAll();
IEnumerable<GuildConfig> GetAllGuildConfigs(); IEnumerable<GuildConfig> GetAllGuildConfigs();
GuildConfig SetNewRootPermission(ulong guildId, Permission p);
IEnumerable<FollowedStream> GetAllFollowedStreams(); IEnumerable<FollowedStream> GetAllFollowedStreams();
void SetCleverbotEnabled(ulong id, bool cleverbotEnabled); void SetCleverbotEnabled(ulong id, bool cleverbotEnabled);
IEnumerable<GuildConfig> Permissionsv2ForAll();
} }
} }

View File

@ -2,7 +2,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using NadekoBot.Modules.Permissions;
using System; using System;
namespace NadekoBot.Services.Database.Repositories.Impl namespace NadekoBot.Services.Database.Repositories.Impl
@ -16,10 +15,6 @@ namespace NadekoBot.Services.Database.Repositories.Impl
public IEnumerable<GuildConfig> GetAllGuildConfigs() => public IEnumerable<GuildConfig> GetAllGuildConfigs() =>
_set.Include(gc => gc.LogSetting) _set.Include(gc => gc.LogSetting)
.ThenInclude(ls => ls.IgnoredChannels) .ThenInclude(ls => ls.IgnoredChannels)
.Include(gc => gc.RootPermission)
.ThenInclude(gc => gc.Previous)
.Include(gc => gc.RootPermission)
.ThenInclude(gc => gc.Next)
.Include(gc => gc.MutedUsers) .Include(gc => gc.MutedUsers)
.Include(gc => gc.GenerateCurrencyChannelIds) .Include(gc => gc.GenerateCurrencyChannelIds)
.Include(gc => gc.FilterInvitesChannelIds) .Include(gc => gc.FilterInvitesChannelIds)
@ -65,10 +60,15 @@ namespace NadekoBot.Services.Database.Repositories.Impl
_set.Add((config = new GuildConfig _set.Add((config = new GuildConfig
{ {
GuildId = guildId, GuildId = guildId,
RootPermission = Permission.GetDefaultRoot(), Permissions = Permissionv2.GetDefaultPermlist
})); }));
_context.SaveChanges(); _context.SaveChanges();
} }
else if (config.Permissions == null)
{
config.Permissions = Permissionv2.GetDefaultPermlist;
_context.SaveChanges();
}
return config; return config;
} }
@ -79,36 +79,11 @@ namespace NadekoBot.Services.Database.Repositories.Impl
.FirstOrDefault(); .FirstOrDefault();
} }
public GuildConfig PermissionsFor(ulong guildId) public IEnumerable<GuildConfig> OldPermissionsForAll()
{ {
var query = _set.Include(gc => gc.RootPermission); var query = _set
.Where(gc => gc.RootPermission != null)
//todo this is possibly a disaster for performance .Include(gc => gc.RootPermission);
//What i could do instead is count the number of permissions in the permission table for this guild
// and make a for loop with those.
// or just select permissions for this guild and manually chain them
for (int i = 0; i < 60; i++)
{
query = query.ThenInclude(gc => gc.Next);
}
var config = query.FirstOrDefault(c => c.GuildId == guildId);
if (config == null)
{
_set.Add((config = new GuildConfig
{
GuildId = guildId,
RootPermission = Permission.GetDefaultRoot(),
}));
_context.SaveChanges();
}
return config;
}
public IEnumerable<GuildConfig> PermissionsForAll()
{
var query = _set.Include(gc => gc.RootPermission);
//todo this is possibly a disaster for performance //todo this is possibly a disaster for performance
//What i could do instead is count the number of permissions in the permission table for this guild //What i could do instead is count the number of permissions in the permission table for this guild
@ -122,20 +97,19 @@ namespace NadekoBot.Services.Database.Repositories.Impl
return query.ToList(); return query.ToList();
} }
public IEnumerable<GuildConfig> Permissionsv2ForAll()
{
var query = _set
.Include(gc => gc.Permissions);
return query.ToList();
}
public IEnumerable<FollowedStream> GetAllFollowedStreams() => public IEnumerable<FollowedStream> GetAllFollowedStreams() =>
_set.Include(gc => gc.FollowedStreams) _set.Include(gc => gc.FollowedStreams)
.SelectMany(gc => gc.FollowedStreams) .SelectMany(gc => gc.FollowedStreams)
.ToList(); .ToList();
public GuildConfig SetNewRootPermission(ulong guildId, Permission p)
{
var data = PermissionsFor(guildId);
data.RootPermission.Prepend(p);
data.RootPermission = p;
return data;
}
public void SetCleverbotEnabled(ulong id, bool cleverbotEnabled) public void SetCleverbotEnabled(ulong id, bool cleverbotEnabled)
{ {
var conf = _set.FirstOrDefault(gc => gc.GuildId == id); var conf = _set.FirstOrDefault(gc => gc.GuildId == id);

View File

@ -42,6 +42,8 @@ namespace NadekoBot.Services
CultureInfo cultureInfo = null; CultureInfo cultureInfo = null;
try try
{ {
if (x.Value == null)
return null;
cultureInfo = new CultureInfo(x.Value); cultureInfo = new CultureInfo(x.Value);
} }
catch { } catch { }

View File

@ -16,7 +16,7 @@ namespace NadekoBot.Services.Impl
private readonly DiscordShardedClient _client; private readonly DiscordShardedClient _client;
private readonly DateTime _started; private readonly DateTime _started;
public const string BotVersion = "1.21"; public const string BotVersion = "1.22";
public string Author => "Kwoth#2560"; public string Author => "Kwoth#2560";
public string Library => "Discord.Net"; public string Library => "Discord.Net";