mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 09:18:27 -04:00
WIP db provider support for Mysql and Postgres
This commit is contained in:
18
CHANGELOG.md
18
CHANGELOG.md
@@ -5,7 +5,23 @@ Experimental changelog. Mostly based on [keepachangelog](https://keepachangelog.
|
||||
|
||||
## Unreleased
|
||||
|
||||
- More cool stuff coming soon
|
||||
### Added
|
||||
|
||||
- NadekoBot now supports mysql, postgresql and sqlite
|
||||
- To change the db nadeko will use, simply change the `db type` in `creds.yml`
|
||||
- There is no migration code right now, which means that if you want to switch to another system you'll either have to manually export/import your database or start fresh
|
||||
|
||||
### Changed
|
||||
|
||||
- Minor club rework
|
||||
- Clubs names are now case sensitive (owo and OwO can be 2 different clubs)
|
||||
- Removed discriminators
|
||||
- Current discriminators which are greater than 1 are appended to clubnames to avoid duplicates, you can rename your club with `.clubrename` to remove it
|
||||
- Most of the clubs with #1 discriminator no longer have it (For example MyClub#1 will now just be MyClub)
|
||||
|
||||
### Removed
|
||||
|
||||
- Removed `.clublevelreq` command as it doesn't serve much purpose
|
||||
|
||||
## [4.0.6] - 21.03.2022
|
||||
|
||||
|
@@ -41,10 +41,7 @@ public sealed class Bot
|
||||
_credsProvider = new BotCredsProvider(totalShards);
|
||||
_creds = _credsProvider.GetCreds();
|
||||
|
||||
_db = new(_creds);
|
||||
|
||||
if (shardId == 0)
|
||||
_db.Setup();
|
||||
_db = new(_credsProvider);
|
||||
|
||||
var messageCacheSize =
|
||||
#if GLOBAL_NADEKO
|
||||
@@ -286,6 +283,9 @@ public sealed class Bot
|
||||
|
||||
public async Task RunAsync()
|
||||
{
|
||||
if (ShardId == 0)
|
||||
await _db.SetupAsync();
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
|
||||
await LoginAsync(_creds.Token);
|
||||
|
@@ -99,7 +99,7 @@ Windows default
|
||||
|
||||
public Creds()
|
||||
{
|
||||
Version = 4;
|
||||
Version = 5;
|
||||
Token = string.Empty;
|
||||
UsePrivilegedIntents = true;
|
||||
OwnerIds = new List<ulong>();
|
||||
@@ -124,10 +124,15 @@ Windows default
|
||||
|
||||
public class DbOptions
|
||||
{
|
||||
[Comment(@"Database type. Only sqlite supported atm")]
|
||||
[Comment(@"Database type. ""sqlite"", ""mysql"" and ""postgresql"" are supported.
|
||||
Default is ""sqlite""")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[Comment(@"Connection string. Will default to ""Data Source=data/NadekoBot.db""")]
|
||||
[Comment(@"Database connection string.
|
||||
You MUST change this if you're not using ""sqlite"" type.
|
||||
Default is ""Data Source=data/NadekoBot.db""
|
||||
Example for mysql: ""Server=localhost;Port=3306;Uid=root;Pwd=my_super_secret_mysql_password;Database=nadeko""
|
||||
Example for postgresql: ""Server=localhost;Port=5432;User Id=postgres;Password=my_super_secret_postgres_password;Database=nadeko;""")]
|
||||
public string ConnectionString { get; set; }
|
||||
}
|
||||
|
||||
|
@@ -12,7 +12,7 @@ public static class ClubExtensions
|
||||
.ThenInclude(x => x.User)
|
||||
.Include(x => x.Bans)
|
||||
.ThenInclude(x => x.User)
|
||||
.Include(x => x.Users)
|
||||
.Include(x => x.Members)
|
||||
.AsQueryable();
|
||||
|
||||
public static ClubInfo GetByOwner(this DbSet<ClubInfo> clubs, ulong userId)
|
||||
@@ -20,24 +20,14 @@ public static class ClubExtensions
|
||||
|
||||
public static ClubInfo GetByOwnerOrAdmin(this DbSet<ClubInfo> clubs, ulong userId)
|
||||
=> Include(clubs)
|
||||
.FirstOrDefault(c => c.Owner.UserId == userId || c.Users.Any(u => u.UserId == userId && u.IsClubAdmin));
|
||||
.FirstOrDefault(c => c.Owner.UserId == userId || c.Members.Any(u => u.UserId == userId && u.IsClubAdmin));
|
||||
|
||||
public static ClubInfo GetByMember(this DbSet<ClubInfo> clubs, ulong userId)
|
||||
=> Include(clubs).FirstOrDefault(c => c.Users.Any(u => u.UserId == userId));
|
||||
=> Include(clubs).FirstOrDefault(c => c.Members.Any(u => u.UserId == userId));
|
||||
|
||||
public static ClubInfo GetByName(this DbSet<ClubInfo> clubs, string name, int discrim)
|
||||
public static ClubInfo GetByName(this DbSet<ClubInfo> clubs, string name)
|
||||
=> Include(clubs)
|
||||
.FirstOrDefault(c => EF.Functions.Collate(c.Name, "NOCASE") == EF.Functions.Collate(name, "NOCASE")
|
||||
&& c.Discrim == discrim);
|
||||
|
||||
public static int GetNextDiscrim(this DbSet<ClubInfo> clubs, string name)
|
||||
=> Include(clubs)
|
||||
.Where(x =>
|
||||
EF.Functions.Collate(x.Name, "NOCASE") == EF.Functions.Collate(name, "NOCASE"))
|
||||
.Select(x => x.Discrim)
|
||||
.DefaultIfEmpty()
|
||||
.Max()
|
||||
+ 1;
|
||||
.FirstOrDefault(c => c.Name == name);
|
||||
|
||||
public static List<ClubInfo> GetClubLeaderboardPage(this DbSet<ClubInfo> clubs, int page)
|
||||
=> clubs.AsNoTracking().OrderByDescending(x => x.Xp).Skip(page * 9).Take(9).ToList();
|
||||
|
@@ -9,6 +9,11 @@ namespace NadekoBot.Db;
|
||||
|
||||
public static class DiscordUserExtensions
|
||||
{
|
||||
public static Task<DiscordUser> GetByUserIdAsync(
|
||||
this IQueryable<DiscordUser> set,
|
||||
ulong userId)
|
||||
=> set.FirstOrDefaultAsyncLinqToDB(x => x.UserId == userId);
|
||||
|
||||
public static void EnsureUserCreated(
|
||||
this NadekoContext ctx,
|
||||
ulong userId,
|
||||
@@ -37,20 +42,49 @@ public static class DiscordUserExtensions
|
||||
UserId = userId
|
||||
});
|
||||
|
||||
public static Task EnsureUserCreatedAsync(
|
||||
this NadekoContext ctx,
|
||||
ulong userId)
|
||||
=> ctx.DiscordUser
|
||||
.ToLinqToDBTable()
|
||||
.InsertOrUpdateAsync(
|
||||
() => new()
|
||||
{
|
||||
UserId = userId,
|
||||
Username = "Unknown",
|
||||
Discriminator = "????",
|
||||
AvatarId = string.Empty,
|
||||
TotalXp = 0,
|
||||
CurrencyAmount = 0
|
||||
},
|
||||
old => new()
|
||||
{
|
||||
|
||||
},
|
||||
() => new()
|
||||
{
|
||||
UserId = userId
|
||||
});
|
||||
|
||||
//temp is only used in updatecurrencystate, so that i don't overwrite real usernames/discrims with Unknown
|
||||
public static DiscordUser GetOrCreateUser(
|
||||
this NadekoContext ctx,
|
||||
ulong userId,
|
||||
string username,
|
||||
string discrim,
|
||||
string avatarId)
|
||||
string avatarId,
|
||||
Func<IQueryable<DiscordUser>, IQueryable<DiscordUser>> includes = null)
|
||||
{
|
||||
ctx.EnsureUserCreated(userId, username, discrim, avatarId);
|
||||
return ctx.DiscordUser.Include(x => x.Club).First(u => u.UserId == userId);
|
||||
|
||||
IQueryable<DiscordUser> queryable = ctx.DiscordUser;
|
||||
if (includes is not null)
|
||||
queryable = includes(queryable);
|
||||
return queryable.First(u => u.UserId == userId);
|
||||
}
|
||||
|
||||
public static DiscordUser GetOrCreateUser(this NadekoContext ctx, IUser original)
|
||||
=> ctx.GetOrCreateUser(original.Id, original.Username, original.Discriminator, original.AvatarId);
|
||||
public static DiscordUser GetOrCreateUser(this NadekoContext ctx, IUser original, Func<IQueryable<DiscordUser>, IQueryable<DiscordUser>> includes = null)
|
||||
=> ctx.GetOrCreateUser(original.Id, original.Username, original.Discriminator, original.AvatarId, includes);
|
||||
|
||||
public static int GetUserGlobalRank(this DbSet<DiscordUser> users, ulong id)
|
||||
=> users.AsQueryable()
|
||||
|
@@ -73,7 +73,6 @@ public static class GuildConfigExtensions
|
||||
{
|
||||
GuildConfig config;
|
||||
|
||||
// todo linq2db
|
||||
if (includes is null)
|
||||
config = ctx.GuildConfigs.IncludeEverything().FirstOrDefault(c => c.GuildId == guildId);
|
||||
else
|
||||
|
@@ -8,24 +8,19 @@ public class ClubInfo : DbEntity
|
||||
{
|
||||
[MaxLength(20)]
|
||||
public string Name { get; set; }
|
||||
|
||||
public int Discrim { get; set; }
|
||||
|
||||
public string Description { get; set; }
|
||||
public string ImageUrl { get; set; } = string.Empty;
|
||||
public int MinimumLevelReq { get; set; } = 5;
|
||||
|
||||
public int Xp { get; set; } = 0;
|
||||
|
||||
public int OwnerId { get; set; }
|
||||
public int? OwnerId { get; set; }
|
||||
public DiscordUser Owner { get; set; }
|
||||
|
||||
public List<DiscordUser> Users { get; set; } = new();
|
||||
|
||||
public List<DiscordUser> Members { get; set; } = new();
|
||||
public List<ClubApplicants> Applicants { get; set; } = new();
|
||||
public List<ClubBans> Bans { get; set; } = new();
|
||||
public string Description { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
=> Name + "#" + Discrim;
|
||||
=> Name;
|
||||
}
|
||||
|
||||
public class ClubApplicants
|
||||
|
@@ -10,6 +10,7 @@ public class DiscordUser : DbEntity
|
||||
public string Discriminator { get; set; }
|
||||
public string AvatarId { get; set; }
|
||||
|
||||
public int? ClubId { get; set; }
|
||||
public ClubInfo Club { get; set; }
|
||||
public bool IsClubAdmin { get; set; }
|
||||
|
||||
|
42
src/NadekoBot/Db/MysqlContext.cs
Normal file
42
src/NadekoBot/Db/MysqlContext.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Db.Models;
|
||||
|
||||
namespace NadekoBot.Services.Database;
|
||||
|
||||
public sealed class MysqlContext : NadekoContext
|
||||
{
|
||||
private readonly string _connStr;
|
||||
private readonly string _version;
|
||||
|
||||
protected override string CurrencyTransactionOtherIdDefaultValue
|
||||
=> "NULL";
|
||||
protected override string DiscordUserLastXpGainDefaultValue
|
||||
=> "(UTC_TIMESTAMP - INTERVAL 1 year)";
|
||||
protected override string LastLevelUpDefaultValue
|
||||
=> "(UTC_TIMESTAMP)";
|
||||
|
||||
public MysqlContext(string connStr = "Server=localhost", string version = "8.0")
|
||||
{
|
||||
_connStr = connStr;
|
||||
_version = version;
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
base.OnConfiguring(optionsBuilder);
|
||||
optionsBuilder
|
||||
.UseLowerCaseNamingConvention()
|
||||
.UseMySql(_connStr, ServerVersion.Parse(_version));
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
// mysql is case insensitive by default
|
||||
// we can set binary collation to change that
|
||||
modelBuilder.Entity<ClubInfo>()
|
||||
.Property(x => x.Name)
|
||||
.UseCollation("utf8mb4_bin");
|
||||
}
|
||||
}
|
@@ -1,5 +1,4 @@
|
||||
#nullable disable
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Design;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -10,23 +9,7 @@ using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Services.Database;
|
||||
|
||||
public class NadekoContextFactory : IDesignTimeDbContextFactory<NadekoContext>
|
||||
{
|
||||
public NadekoContext CreateDbContext(string[] args)
|
||||
{
|
||||
LogSetup.SetupLogger(-2);
|
||||
var optionsBuilder = new DbContextOptionsBuilder<NadekoContext>();
|
||||
var creds = new BotCredsProvider().GetCreds();
|
||||
var builder = new SqliteConnectionStringBuilder(creds.Db.ConnectionString);
|
||||
builder.DataSource = Path.Combine(AppContext.BaseDirectory, builder.DataSource);
|
||||
optionsBuilder.UseSqlite(builder.ToString());
|
||||
var ctx = new NadekoContext(optionsBuilder.Options);
|
||||
ctx.Database.SetCommandTimeout(60);
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
|
||||
public class NadekoContext : DbContext
|
||||
public abstract class NadekoContext : DbContext
|
||||
{
|
||||
public DbSet<GuildConfig> GuildConfigs { get; set; }
|
||||
|
||||
@@ -69,11 +52,14 @@ public class NadekoContext : DbContext
|
||||
|
||||
public DbSet<Permissionv2> Permissions { get; set; }
|
||||
|
||||
public NadekoContext(DbContextOptions<NadekoContext> options)
|
||||
: base(options)
|
||||
{
|
||||
}
|
||||
#region Mandatory Provider-Specific Values
|
||||
|
||||
protected abstract string CurrencyTransactionOtherIdDefaultValue { get; }
|
||||
protected abstract string DiscordUserLastXpGainDefaultValue { get; }
|
||||
protected abstract string LastLevelUpDefaultValue { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
#region QUOTES
|
||||
@@ -167,10 +153,10 @@ public class NadekoContext : DbContext
|
||||
.HasDefaultValue(XpNotificationLocation.None);
|
||||
|
||||
du.Property(x => x.LastXpGain)
|
||||
.HasDefaultValueSql("datetime('now', '-1 years')");
|
||||
.HasDefaultValueSql(DiscordUserLastXpGainDefaultValue);
|
||||
|
||||
du.Property(x => x.LastLevelUp)
|
||||
.HasDefaultValueSql("datetime('now')");
|
||||
.HasDefaultValueSql(LastLevelUpDefaultValue);
|
||||
|
||||
du.Property(x => x.TotalXp)
|
||||
.HasDefaultValue(0);
|
||||
@@ -179,7 +165,10 @@ public class NadekoContext : DbContext
|
||||
.HasDefaultValue(0);
|
||||
|
||||
du.HasAlternateKey(w => w.UserId);
|
||||
du.HasOne(x => x.Club).WithMany(x => x.Users).IsRequired(false);
|
||||
du.HasOne(x => x.Club)
|
||||
.WithMany(x => x.Members)
|
||||
.IsRequired(false)
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
du.HasIndex(x => x.TotalXp);
|
||||
du.HasIndex(x => x.CurrencyAmount);
|
||||
@@ -218,7 +207,7 @@ public class NadekoContext : DbContext
|
||||
.IsUnique();
|
||||
|
||||
xps.Property(x => x.LastLevelUp)
|
||||
.HasDefaultValue(new DateTime(2017, 9, 21, 20, 53, 13, 307, DateTimeKind.Local));
|
||||
.HasDefaultValueSql(LastLevelUpDefaultValue);
|
||||
|
||||
xps.HasIndex(x => x.UserId);
|
||||
xps.HasIndex(x => x.GuildId);
|
||||
@@ -248,13 +237,14 @@ public class NadekoContext : DbContext
|
||||
#region Club
|
||||
|
||||
var ci = modelBuilder.Entity<ClubInfo>();
|
||||
ci.HasOne(x => x.Owner).WithOne().HasForeignKey<ClubInfo>(x => x.OwnerId);
|
||||
|
||||
ci.HasOne(x => x.Owner)
|
||||
.WithOne()
|
||||
.HasForeignKey<ClubInfo>(x => x.OwnerId)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
ci.HasAlternateKey(x => new
|
||||
{
|
||||
x.Name,
|
||||
x.Discrim
|
||||
x.Name
|
||||
});
|
||||
|
||||
#endregion
|
||||
@@ -268,9 +258,13 @@ public class NadekoContext : DbContext
|
||||
t.UserId
|
||||
});
|
||||
|
||||
modelBuilder.Entity<ClubApplicants>().HasOne(pt => pt.User).WithMany();
|
||||
modelBuilder.Entity<ClubApplicants>()
|
||||
.HasOne(pt => pt.User)
|
||||
.WithMany();
|
||||
|
||||
modelBuilder.Entity<ClubApplicants>().HasOne(pt => pt.Club).WithMany(x => x.Applicants);
|
||||
modelBuilder.Entity<ClubApplicants>()
|
||||
.HasOne(pt => pt.Club)
|
||||
.WithMany(x => x.Applicants);
|
||||
|
||||
modelBuilder.Entity<ClubBans>()
|
||||
.HasKey(t => new
|
||||
@@ -279,9 +273,13 @@ public class NadekoContext : DbContext
|
||||
t.UserId
|
||||
});
|
||||
|
||||
modelBuilder.Entity<ClubBans>().HasOne(pt => pt.User).WithMany();
|
||||
modelBuilder.Entity<ClubBans>()
|
||||
.HasOne(pt => pt.User)
|
||||
.WithMany();
|
||||
|
||||
modelBuilder.Entity<ClubBans>().HasOne(pt => pt.Club).WithMany(x => x.Bans);
|
||||
modelBuilder.Entity<ClubBans>()
|
||||
.HasOne(pt => pt.Club)
|
||||
.WithMany(x => x.Bans);
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -299,7 +297,7 @@ public class NadekoContext : DbContext
|
||||
.IsUnique(false);
|
||||
|
||||
e.Property(x => x.OtherId)
|
||||
.HasDefaultValueSql("NULL");
|
||||
.HasDefaultValueSql(CurrencyTransactionOtherIdDefaultValue);
|
||||
|
||||
e.Property(x => x.Type)
|
||||
.IsRequired();
|
||||
|
28
src/NadekoBot/Db/PostgreSqlContext.cs
Normal file
28
src/NadekoBot/Db/PostgreSqlContext.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace NadekoBot.Services.Database;
|
||||
|
||||
public sealed class PostgreSqlContext : NadekoContext
|
||||
{
|
||||
private readonly string _connStr;
|
||||
|
||||
protected override string CurrencyTransactionOtherIdDefaultValue
|
||||
=> "NULL";
|
||||
protected override string DiscordUserLastXpGainDefaultValue
|
||||
=> "timezone('utc', now()) - interval '-1 year'";
|
||||
protected override string LastLevelUpDefaultValue
|
||||
=> "timezone('utc', now())";
|
||||
|
||||
public PostgreSqlContext(string connStr = "Host=localhost")
|
||||
{
|
||||
_connStr = connStr;
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
base.OnConfiguring(optionsBuilder);
|
||||
optionsBuilder
|
||||
.UseLowerCaseNamingConvention()
|
||||
.UseNpgsql(_connStr);
|
||||
}
|
||||
}
|
30
src/NadekoBot/Db/SqliteContext.cs
Normal file
30
src/NadekoBot/Db/SqliteContext.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace NadekoBot.Services.Database;
|
||||
|
||||
public sealed class SqliteContext : NadekoContext
|
||||
{
|
||||
private readonly string _connectionString;
|
||||
|
||||
protected override string CurrencyTransactionOtherIdDefaultValue
|
||||
=> "NULL";
|
||||
protected override string DiscordUserLastXpGainDefaultValue
|
||||
=> "datetime('now', '-1 years')";
|
||||
protected override string LastLevelUpDefaultValue
|
||||
=> "datetime('now')";
|
||||
|
||||
public SqliteContext(string connectionString = "Data Source=data/NadekoBot.db", int commandTimeout = 60)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
Database.SetCommandTimeout(commandTimeout);
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
base.OnConfiguring(optionsBuilder);
|
||||
var builder = new SqliteConnectionStringBuilder(_connectionString);
|
||||
builder.DataSource = Path.Combine(AppContext.BaseDirectory, builder.DataSource);
|
||||
optionsBuilder.UseSqlite(builder.ToString());
|
||||
}
|
||||
}
|
3425
src/NadekoBot/Migrations/MySql/20220409170652_mysql-init.Designer.cs
generated
Normal file
3425
src/NadekoBot/Migrations/MySql/20220409170652_mysql-init.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
2343
src/NadekoBot/Migrations/MySql/20220409170652_mysql-init.cs
Normal file
2343
src/NadekoBot/Migrations/MySql/20220409170652_mysql-init.cs
Normal file
File diff suppressed because it is too large
Load Diff
3423
src/NadekoBot/Migrations/MySql/MysqlContextModelSnapshot.cs
Normal file
3423
src/NadekoBot/Migrations/MySql/MysqlContextModelSnapshot.cs
Normal file
File diff suppressed because it is too large
Load Diff
3565
src/NadekoBot/Migrations/Postgresql/20220409170719_mysql-init.Designer.cs
generated
Normal file
3565
src/NadekoBot/Migrations/Postgresql/20220409170719_mysql-init.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
2201
src/NadekoBot/Migrations/Postgresql/20220409170719_mysql-init.cs
Normal file
2201
src/NadekoBot/Migrations/Postgresql/20220409170719_mysql-init.cs
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20210621042359_squash")]
|
||||
partial class squash
|
||||
{
|
@@ -8,7 +8,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20210707002343_cleanup")]
|
||||
partial class cleanup
|
||||
{
|
@@ -8,7 +8,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20210911225622_rero-cascade")]
|
||||
partial class rerocascade
|
||||
{
|
@@ -8,7 +8,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20210912182515_boost-messages")]
|
||||
partial class boostmessages
|
||||
{
|
@@ -8,7 +8,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20210912200106_logsettings-independence")]
|
||||
partial class logsettingsindependence
|
||||
{
|
@@ -8,7 +8,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20210914180026_image-only-channels")]
|
||||
partial class imageonlychannels
|
||||
{
|
@@ -8,7 +8,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20210921204645_logignore-user-channel")]
|
||||
partial class logignoreuserchannel
|
||||
{
|
@@ -8,7 +8,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20211015232708_nsfw-blacklist-tags")]
|
||||
partial class nsfwblacklisttags
|
||||
{
|
@@ -8,7 +8,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20211121002508_weighted-warnings")]
|
||||
partial class weightedwarnings
|
||||
{
|
@@ -8,7 +8,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20211213145407_atl-rework")]
|
||||
partial class atlrework
|
||||
{
|
@@ -10,7 +10,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20220102102344_crs-rename-to-expressions-perm-rename")]
|
||||
partial class crsrenametoexpressionspermrename
|
||||
{
|
@@ -10,7 +10,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20220110105942_filter-settings-cleanup")]
|
||||
partial class filtersettingscleanup
|
||||
{
|
@@ -10,7 +10,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20220125044401_curtrs-rework-discorduser-defaults")]
|
||||
partial class curtrsreworkdiscorduserdefaults
|
||||
{
|
@@ -10,7 +10,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20220213123633_music-autoplay")]
|
||||
partial class musicautoplay
|
||||
{
|
2756
src/NadekoBot/Migrations/Sqlite/20220409170828_clubs-refactor.Designer.cs
generated
Normal file
2756
src/NadekoBot/Migrations/Sqlite/20220409170828_clubs-refactor.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
132
src/NadekoBot/Migrations/Sqlite/20220409170828_clubs-refactor.cs
Normal file
132
src/NadekoBot/Migrations/Sqlite/20220409170828_clubs-refactor.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
public partial class clubsrefactor : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.Sql(@"UPDATE Clubs
|
||||
SET Name = Name || '#' || Discrim
|
||||
WHERE Discrim <> 1;
|
||||
|
||||
UPDATE Clubs as co
|
||||
SET Name =
|
||||
CASE (select count(*) from Clubs as ci where co.Name == ci.Name) = 1
|
||||
WHEN true
|
||||
THEN Name
|
||||
ELSE
|
||||
Name || '#' || Discrim
|
||||
END
|
||||
WHERE Discrim = 1;");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Clubs_DiscordUser_OwnerId",
|
||||
table: "Clubs");
|
||||
|
||||
migrationBuilder.DropUniqueConstraint(
|
||||
name: "AK_Clubs_Name_Discrim",
|
||||
table: "Clubs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Discrim",
|
||||
table: "Clubs");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "MinimumLevelReq",
|
||||
table: "Clubs");
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "LastLevelUp",
|
||||
table: "UserXpStats",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValueSql: "datetime('now')",
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "TEXT",
|
||||
oldDefaultValue: new DateTime(2017, 9, 21, 20, 53, 13, 307, DateTimeKind.Local));
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "OwnerId",
|
||||
table: "Clubs",
|
||||
type: "INTEGER",
|
||||
nullable: true,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "INTEGER");
|
||||
|
||||
migrationBuilder.AddUniqueConstraint(
|
||||
name: "AK_Clubs_Name",
|
||||
table: "Clubs",
|
||||
column: "Name");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Clubs_DiscordUser_OwnerId",
|
||||
table: "Clubs",
|
||||
column: "OwnerId",
|
||||
principalTable: "DiscordUser",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Clubs_DiscordUser_OwnerId",
|
||||
table: "Clubs");
|
||||
|
||||
migrationBuilder.DropUniqueConstraint(
|
||||
name: "AK_Clubs_Name",
|
||||
table: "Clubs");
|
||||
|
||||
migrationBuilder.AlterColumn<DateTime>(
|
||||
name: "LastLevelUp",
|
||||
table: "UserXpStats",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(2017, 9, 21, 20, 53, 13, 307, DateTimeKind.Local),
|
||||
oldClrType: typeof(DateTime),
|
||||
oldType: "TEXT",
|
||||
oldDefaultValueSql: "datetime('now')");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "OwnerId",
|
||||
table: "Clubs",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "INTEGER",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Discrim",
|
||||
table: "Clubs",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "MinimumLevelReq",
|
||||
table: "Clubs",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddUniqueConstraint(
|
||||
name: "AK_Clubs_Name_Discrim",
|
||||
table: "Clubs",
|
||||
columns: new[] { "Name", "Discrim" });
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Clubs_DiscordUser_OwnerId",
|
||||
table: "Clubs",
|
||||
column: "OwnerId",
|
||||
principalTable: "DiscordUser",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
}
|
||||
}
|
@@ -9,13 +9,13 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
partial class NadekoContextModelSnapshot : ModelSnapshot
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
partial class NadekoSqliteContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "6.0.2");
|
||||
modelBuilder.HasAnnotation("ProductVersion", "6.0.3");
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b =>
|
||||
{
|
||||
@@ -29,7 +29,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("ClubApplicants", (string)null);
|
||||
b.ToTable("ClubApplicants");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b =>
|
||||
@@ -44,7 +44,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("ClubBans", (string)null);
|
||||
b.ToTable("ClubBans");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b =>
|
||||
@@ -59,21 +59,15 @@ namespace NadekoBot.Migrations
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Discrim")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ImageUrl")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("MinimumLevelReq")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("OwnerId")
|
||||
b.Property<int?>("OwnerId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Xp")
|
||||
@@ -81,12 +75,12 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasAlternateKey("Name", "Discrim");
|
||||
b.HasAlternateKey("Name");
|
||||
|
||||
b.HasIndex("OwnerId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Clubs", (string)null);
|
||||
b.ToTable("Clubs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b =>
|
||||
@@ -155,7 +149,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("DiscordUser", (string)null);
|
||||
b.ToTable("DiscordUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b =>
|
||||
@@ -189,7 +183,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("FollowedStream", (string)null);
|
||||
b.ToTable("FollowedStream");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiAltSetting", b =>
|
||||
@@ -218,7 +212,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasIndex("GuildConfigId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("AntiAltSetting", (string)null);
|
||||
b.ToTable("AntiAltSetting");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b =>
|
||||
@@ -250,7 +244,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasIndex("GuildConfigId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("AntiRaidSetting", (string)null);
|
||||
b.ToTable("AntiRaidSetting");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b =>
|
||||
@@ -272,7 +266,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("AntiSpamSettingId");
|
||||
|
||||
b.ToTable("AntiSpamIgnore", (string)null);
|
||||
b.ToTable("AntiSpamIgnore");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b =>
|
||||
@@ -304,7 +298,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasIndex("GuildConfigId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("AntiSpamSetting", (string)null);
|
||||
b.ToTable("AntiSpamSetting");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoCommand", b =>
|
||||
@@ -342,7 +336,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("AutoCommands", (string)null);
|
||||
b.ToTable("AutoCommands");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateChannel", b =>
|
||||
@@ -370,7 +364,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.ToTable("AutoTranslateChannels", (string)null);
|
||||
b.ToTable("AutoTranslateChannels");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateUser", b =>
|
||||
@@ -398,7 +392,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasAlternateKey("ChannelId", "UserId");
|
||||
|
||||
b.ToTable("AutoTranslateUsers", (string)null);
|
||||
b.ToTable("AutoTranslateUsers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.BanTemplate", b =>
|
||||
@@ -421,7 +415,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasIndex("GuildId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("BanTemplates", (string)null);
|
||||
b.ToTable("BanTemplates");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistEntry", b =>
|
||||
@@ -441,7 +435,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Blacklist", (string)null);
|
||||
b.ToTable("Blacklist");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b =>
|
||||
@@ -466,7 +460,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("CommandAlias", (string)null);
|
||||
b.ToTable("CommandAlias");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b =>
|
||||
@@ -491,7 +485,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("CommandCooldown", (string)null);
|
||||
b.ToTable("CommandCooldown");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b =>
|
||||
@@ -529,7 +523,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("CurrencyTransactions", (string)null);
|
||||
b.ToTable("CurrencyTransactions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.DelMsgOnCmdChannel", b =>
|
||||
@@ -554,7 +548,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("DelMsgOnCmdChannel", (string)null);
|
||||
b.ToTable("DelMsgOnCmdChannel");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.DiscordPermOverride", b =>
|
||||
@@ -580,7 +574,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasIndex("GuildId", "Command")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("DiscordPermOverrides", (string)null);
|
||||
b.ToTable("DiscordPermOverrides");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b =>
|
||||
@@ -605,7 +599,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("XpSettingsId");
|
||||
|
||||
b.ToTable("ExcludedItem", (string)null);
|
||||
b.ToTable("ExcludedItem");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.FeedSub", b =>
|
||||
@@ -631,7 +625,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasAlternateKey("GuildConfigId", "Url");
|
||||
|
||||
b.ToTable("FeedSub", (string)null);
|
||||
b.ToTable("FeedSub");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
|
||||
@@ -653,7 +647,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("FilterChannelId", (string)null);
|
||||
b.ToTable("FilterChannelId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b =>
|
||||
@@ -675,7 +669,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("FilteredWord", (string)null);
|
||||
b.ToTable("FilteredWord");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b =>
|
||||
@@ -697,7 +691,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("FilterLinksChannelId", (string)null);
|
||||
b.ToTable("FilterLinksChannelId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterWordsChannelId", b =>
|
||||
@@ -719,7 +713,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("FilterWordsChannelId", (string)null);
|
||||
b.ToTable("FilterWordsChannelId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b =>
|
||||
@@ -741,7 +735,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("GCChannelId", (string)null);
|
||||
b.ToTable("GCChannelId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.GroupName", b =>
|
||||
@@ -767,7 +761,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasIndex("GuildConfigId", "Number")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("GroupName", (string)null);
|
||||
b.ToTable("GroupName");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b =>
|
||||
@@ -891,7 +885,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("WarnExpireHours");
|
||||
|
||||
b.ToTable("GuildConfigs", (string)null);
|
||||
b.ToTable("GuildConfigs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogItem", b =>
|
||||
@@ -917,7 +911,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasIndex("LogSettingId", "LogItemId", "ItemType")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("IgnoredLogChannels", (string)null);
|
||||
b.ToTable("IgnoredLogChannels");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b =>
|
||||
@@ -939,7 +933,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("LogSettingId");
|
||||
|
||||
b.ToTable("IgnoredVoicePresenceCHannels", (string)null);
|
||||
b.ToTable("IgnoredVoicePresenceCHannels");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.ImageOnlyChannel", b =>
|
||||
@@ -962,7 +956,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasIndex("ChannelId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("ImageOnlyChannels", (string)null);
|
||||
b.ToTable("ImageOnlyChannels");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b =>
|
||||
@@ -1027,7 +1021,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasIndex("GuildId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("LogSettings", (string)null);
|
||||
b.ToTable("LogSettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlayerSettings", b =>
|
||||
@@ -1064,7 +1058,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasIndex("GuildId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("MusicPlayerSettings", (string)null);
|
||||
b.ToTable("MusicPlayerSettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b =>
|
||||
@@ -1087,7 +1081,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("MusicPlaylists", (string)null);
|
||||
b.ToTable("MusicPlaylists");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b =>
|
||||
@@ -1109,7 +1103,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("MutedUserId", (string)null);
|
||||
b.ToTable("MutedUserId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.NadekoExpression", b =>
|
||||
@@ -1147,7 +1141,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Expressions", (string)null);
|
||||
b.ToTable("Expressions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.NsfwBlacklistedTag", b =>
|
||||
@@ -1169,7 +1163,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.ToTable("NsfwBlacklistedTags", (string)null);
|
||||
b.ToTable("NsfwBlacklistedTags");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b =>
|
||||
@@ -1209,7 +1203,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("Permissions", (string)null);
|
||||
b.ToTable("Permissions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlantedCurrency", b =>
|
||||
@@ -1246,7 +1240,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasIndex("MessageId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("PlantedCurrency", (string)null);
|
||||
b.ToTable("PlantedCurrency");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b =>
|
||||
@@ -1280,7 +1274,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("MusicPlaylistId");
|
||||
|
||||
b.ToTable("PlaylistSong", (string)null);
|
||||
b.ToTable("PlaylistSong");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.Poll", b =>
|
||||
@@ -1306,7 +1300,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasIndex("GuildId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Poll", (string)null);
|
||||
b.ToTable("Poll");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.PollAnswer", b =>
|
||||
@@ -1331,7 +1325,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("PollId");
|
||||
|
||||
b.ToTable("PollAnswer", (string)null);
|
||||
b.ToTable("PollAnswer");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.PollVote", b =>
|
||||
@@ -1356,7 +1350,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("PollId");
|
||||
|
||||
b.ToTable("PollVote", (string)null);
|
||||
b.ToTable("PollVote");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b =>
|
||||
@@ -1392,7 +1386,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("Keyword");
|
||||
|
||||
b.ToTable("Quotes", (string)null);
|
||||
b.ToTable("Quotes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.ReactionRole", b =>
|
||||
@@ -1417,7 +1411,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("ReactionRoleMessageId");
|
||||
|
||||
b.ToTable("ReactionRole", (string)null);
|
||||
b.ToTable("ReactionRole");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.ReactionRoleMessage", b =>
|
||||
@@ -1448,7 +1442,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("ReactionRoleMessage", (string)null);
|
||||
b.ToTable("ReactionRoleMessage");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b =>
|
||||
@@ -1482,7 +1476,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("When");
|
||||
|
||||
b.ToTable("Reminders", (string)null);
|
||||
b.ToTable("Reminders");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b =>
|
||||
@@ -1517,7 +1511,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Repeaters", (string)null);
|
||||
b.ToTable("Repeaters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.RewardedUser", b =>
|
||||
@@ -1546,7 +1540,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasIndex("PatreonUserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("RewardedUsers", (string)null);
|
||||
b.ToTable("RewardedUsers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.RotatingPlayingStatus", b =>
|
||||
@@ -1566,7 +1560,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("RotatingStatus", (string)null);
|
||||
b.ToTable("RotatingStatus");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b =>
|
||||
@@ -1597,7 +1591,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasIndex("GuildId", "RoleId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("SelfAssignableRoles", (string)null);
|
||||
b.ToTable("SelfAssignableRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b =>
|
||||
@@ -1637,7 +1631,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("ShopEntry", (string)null);
|
||||
b.ToTable("ShopEntry");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b =>
|
||||
@@ -1659,7 +1653,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("ShopEntryId");
|
||||
|
||||
b.ToTable("ShopEntryItem", (string)null);
|
||||
b.ToTable("ShopEntryItem");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b =>
|
||||
@@ -1681,7 +1675,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("SlowmodeIgnoredRole", (string)null);
|
||||
b.ToTable("SlowmodeIgnoredRole");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b =>
|
||||
@@ -1703,7 +1697,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("SlowmodeIgnoredUser", (string)null);
|
||||
b.ToTable("SlowmodeIgnoredUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b =>
|
||||
@@ -1728,7 +1722,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("StreamRoleSettingsId");
|
||||
|
||||
b.ToTable("StreamRoleBlacklistedUser", (string)null);
|
||||
b.ToTable("StreamRoleBlacklistedUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b =>
|
||||
@@ -1760,7 +1754,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasIndex("GuildConfigId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("StreamRoleSettings", (string)null);
|
||||
b.ToTable("StreamRoleSettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b =>
|
||||
@@ -1785,7 +1779,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("StreamRoleSettingsId");
|
||||
|
||||
b.ToTable("StreamRoleWhitelistedUser", (string)null);
|
||||
b.ToTable("StreamRoleWhitelistedUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.UnbanTimer", b =>
|
||||
@@ -1810,7 +1804,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("UnbanTimer", (string)null);
|
||||
b.ToTable("UnbanTimer");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b =>
|
||||
@@ -1835,7 +1829,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("UnmuteTimer", (string)null);
|
||||
b.ToTable("UnmuteTimer");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.UnroleTimer", b =>
|
||||
@@ -1863,7 +1857,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("UnroleTimer", (string)null);
|
||||
b.ToTable("UnroleTimer");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.UserXpStats", b =>
|
||||
@@ -1884,7 +1878,7 @@ namespace NadekoBot.Migrations
|
||||
b.Property<DateTime>("LastLevelUp")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("TEXT")
|
||||
.HasDefaultValue(new DateTime(2017, 9, 21, 20, 53, 13, 307, DateTimeKind.Local));
|
||||
.HasDefaultValueSql("datetime('now')");
|
||||
|
||||
b.Property<int>("NotifyOnLevelUp")
|
||||
.HasColumnType("INTEGER");
|
||||
@@ -1908,7 +1902,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasIndex("UserId", "GuildId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("UserXpStats", (string)null);
|
||||
b.ToTable("UserXpStats");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b =>
|
||||
@@ -1933,7 +1927,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("VcRoleInfo", (string)null);
|
||||
b.ToTable("VcRoleInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b =>
|
||||
@@ -1968,7 +1962,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasIndex("WaifuId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("WaifuInfo", (string)null);
|
||||
b.ToTable("WaifuInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b =>
|
||||
@@ -1993,7 +1987,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("WaifuInfoId");
|
||||
|
||||
b.ToTable("WaifuItem", (string)null);
|
||||
b.ToTable("WaifuItem");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b =>
|
||||
@@ -2025,7 +2019,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("WaifuUpdates", (string)null);
|
||||
b.ToTable("WaifuUpdates");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.Warning", b =>
|
||||
@@ -2068,7 +2062,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Warnings", (string)null);
|
||||
b.ToTable("Warnings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b =>
|
||||
@@ -2099,7 +2093,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("GuildConfigId");
|
||||
|
||||
b.ToTable("WarningPunishment", (string)null);
|
||||
b.ToTable("WarningPunishment");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.XpCurrencyReward", b =>
|
||||
@@ -2124,7 +2118,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.HasIndex("XpSettingsId");
|
||||
|
||||
b.ToTable("XpCurrencyReward", (string)null);
|
||||
b.ToTable("XpCurrencyReward");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b =>
|
||||
@@ -2153,7 +2147,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasIndex("XpSettingsId", "Level")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("XpRoleReward", (string)null);
|
||||
b.ToTable("XpRoleReward");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b =>
|
||||
@@ -2176,7 +2170,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasIndex("GuildConfigId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("XpSettings", (string)null);
|
||||
b.ToTable("XpSettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b =>
|
||||
@@ -2222,8 +2216,7 @@ namespace NadekoBot.Migrations
|
||||
b.HasOne("NadekoBot.Db.Models.DiscordUser", "Owner")
|
||||
.WithOne()
|
||||
.HasForeignKey("NadekoBot.Db.Models.ClubInfo", "OwnerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.Navigation("Owner");
|
||||
});
|
||||
@@ -2231,8 +2224,9 @@ namespace NadekoBot.Migrations
|
||||
modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b =>
|
||||
{
|
||||
b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club")
|
||||
.WithMany("Users")
|
||||
.HasForeignKey("ClubId");
|
||||
.WithMany("Members")
|
||||
.HasForeignKey("ClubId")
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
b.Navigation("Club");
|
||||
});
|
||||
@@ -2561,9 +2555,11 @@ namespace NadekoBot.Migrations
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b =>
|
||||
{
|
||||
b.HasOne("NadekoBot.Services.Database.Models.WaifuInfo", null)
|
||||
b.HasOne("NadekoBot.Services.Database.Models.WaifuInfo", "WaifuInfo")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("WaifuInfoId");
|
||||
|
||||
b.Navigation("WaifuInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b =>
|
||||
@@ -2635,7 +2631,7 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.Navigation("Bans");
|
||||
|
||||
b.Navigation("Users");
|
||||
b.Navigation("Members");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b =>
|
@@ -20,7 +20,7 @@ public class DangerousCommandsService : INService
|
||||
await ctx.DiscordUser.UpdateAsync(_ => new DiscordUser()
|
||||
{
|
||||
Club = null,
|
||||
IsClubAdmin = false,
|
||||
// IsClubAdmin = false,
|
||||
TotalXp = 0
|
||||
});
|
||||
await ctx.ClubApplicants.DeleteAsync();
|
||||
@@ -97,6 +97,7 @@ public class DangerousCommandsService : INService
|
||||
|
||||
using var uow = _db.GetDbContext();
|
||||
var conn = uow.Database.GetDbConnection();
|
||||
conn.Open();
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = sql;
|
||||
using var reader = cmd.ExecuteReader();
|
||||
|
@@ -280,7 +280,7 @@ public partial class Utility : NadekoModule
|
||||
$"{_stats.MessageCounter} ({_stats.MessagesPerSecond:F2}/sec)",
|
||||
true)
|
||||
.AddField(GetText(strs.memory),
|
||||
FormattableString.Invariant($"{_stats.GetPrivateMemory():F2} MB"),
|
||||
FormattableString.Invariant($"{_stats.GetPrivateMemoryMegabytes():F2} MB"),
|
||||
true)
|
||||
.AddField(GetText(strs.owner_ids), ownerIds, true)
|
||||
.AddField(GetText(strs.uptime), _stats.GetUptimeString("\n"), true)
|
||||
@@ -337,7 +337,7 @@ public partial class Utility : NadekoModule
|
||||
|
||||
using var http = _httpFactory.CreateClient();
|
||||
using var res = await http.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
|
||||
if (!res.IsImage() || res.GetImageSize() is null or > 262_144)
|
||||
if (!res.IsImage() || res.GetContentLength() > 262_144)
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.invalid_emoji_link);
|
||||
return;
|
||||
|
@@ -7,7 +7,7 @@ namespace NadekoBot.Modules.Xp;
|
||||
public partial class Xp
|
||||
{
|
||||
[Group]
|
||||
public partial class Club : NadekoModule<ClubService>
|
||||
public partial class Club : NadekoModule<IClubService>
|
||||
{
|
||||
private readonly XpService _xps;
|
||||
|
||||
@@ -19,35 +19,33 @@ public partial class Xp
|
||||
{
|
||||
var club = _service.TransferClub(ctx.User, newOwner);
|
||||
|
||||
if (club is not null)
|
||||
if (club is null)
|
||||
{
|
||||
await ReplyConfirmLocalizedAsync(strs.club_transfered(Format.Bold(club.Name),
|
||||
Format.Bold(newOwner.ToString())));
|
||||
await ReplyErrorLocalizedAsync(strs.club_transfer_failed);
|
||||
}
|
||||
else
|
||||
await ReplyErrorLocalizedAsync(strs.club_transfer_failed);
|
||||
{
|
||||
await ReplyConfirmLocalizedAsync(
|
||||
strs.club_transfered(
|
||||
Format.Bold(club.Name),
|
||||
Format.Bold(newOwner.ToString())
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
public async partial Task ClubAdmin([Leftover] IUser toAdmin)
|
||||
{
|
||||
bool admin;
|
||||
try
|
||||
{
|
||||
admin = _service.ToggleAdmin(ctx.User, toAdmin);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
var admin = await _service.ToggleAdminAsync(ctx.User, toAdmin);
|
||||
|
||||
if (admin is null)
|
||||
await ReplyErrorLocalizedAsync(strs.club_admin_error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (admin)
|
||||
else if (admin is true)
|
||||
await ReplyConfirmLocalizedAsync(strs.club_admin_add(Format.Bold(toAdmin.ToString())));
|
||||
else
|
||||
await ReplyConfirmLocalizedAsync(strs.club_admin_remove(Format.Bold(toAdmin.ToString())));
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
public async partial Task ClubCreate([Leftover] string clubName)
|
||||
{
|
||||
@@ -57,20 +55,28 @@ public partial class Xp
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_service.CreateClub(ctx.User, clubName, out var club))
|
||||
var succ = await _service.CreateClubAsync(ctx.User, clubName);
|
||||
|
||||
if (succ is null)
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.club_create_error_name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (succ is false)
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.club_create_error);
|
||||
return;
|
||||
}
|
||||
|
||||
await ReplyConfirmLocalizedAsync(strs.club_created(Format.Bold(club.ToString())));
|
||||
await ReplyConfirmLocalizedAsync(strs.club_created(Format.Bold(clubName)));
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
public async partial Task ClubIcon([Leftover] string url = null)
|
||||
{
|
||||
if ((!Uri.IsWellFormedUriString(url, UriKind.Absolute) && url is not null)
|
||||
|| !await _service.SetClubIcon(ctx.User.Id, url is null ? null : new Uri(url)))
|
||||
|| !await _service.SetClubIconAsync(ctx.User.Id, url))
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.club_icon_error);
|
||||
return;
|
||||
@@ -82,7 +88,7 @@ public partial class Xp
|
||||
private async Task InternalClubInfoAsync(ClubInfo club)
|
||||
{
|
||||
var lvl = new LevelStats(club.Xp);
|
||||
var users = club.Users.OrderByDescending(x =>
|
||||
var users = club.Members.OrderByDescending(x =>
|
||||
{
|
||||
var l = new LevelStats(x.TotalXp).Level;
|
||||
if (club.OwnerId == x.Id)
|
||||
@@ -102,7 +108,7 @@ public partial class Xp
|
||||
.AddField(GetText(strs.desc),
|
||||
string.IsNullOrWhiteSpace(club.Description) ? "-" : club.Description)
|
||||
.AddField(GetText(strs.owner), club.Owner.ToString(), true)
|
||||
.AddField(GetText(strs.level_req), club.MinimumLevelReq.ToString(), true)
|
||||
// .AddField(GetText(strs.level_req), club.MinimumLevelReq.ToString(), true)
|
||||
.AddField(GetText(strs.members),
|
||||
string.Join("\n",
|
||||
users.Skip(page * 10)
|
||||
@@ -123,7 +129,7 @@ public partial class Xp
|
||||
|
||||
return embed;
|
||||
},
|
||||
club.Users.Count,
|
||||
club.Members.Count,
|
||||
10);
|
||||
}
|
||||
|
||||
@@ -187,7 +193,6 @@ public partial class Xp
|
||||
10);
|
||||
}
|
||||
|
||||
|
||||
[Cmd]
|
||||
public partial Task ClubApps(int page = 1)
|
||||
{
|
||||
@@ -310,19 +315,10 @@ public partial class Xp
|
||||
return ReplyErrorLocalizedAsync(strs.club_user_unban_fail);
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
public async partial Task ClubLevelReq(int level)
|
||||
{
|
||||
if (_service.ChangeClubLevelReq(ctx.User.Id, level))
|
||||
await ReplyConfirmLocalizedAsync(strs.club_level_req_changed(Format.Bold(level.ToString())));
|
||||
else
|
||||
await ReplyErrorLocalizedAsync(strs.club_level_req_change_error);
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
public async partial Task ClubDescription([Leftover] string desc = null)
|
||||
{
|
||||
if (_service.ChangeClubDescription(ctx.User.Id, desc))
|
||||
if (_service.SetDescription(ctx.User.Id, desc))
|
||||
await ReplyConfirmLocalizedAsync(strs.club_desc_updated(Format.Bold(desc ?? "-")));
|
||||
else
|
||||
await ReplyErrorLocalizedAsync(strs.club_desc_update_failed);
|
||||
@@ -332,7 +328,7 @@ public partial class Xp
|
||||
public async partial Task ClubDisband()
|
||||
{
|
||||
if (_service.Disband(ctx.User.Id, out var club))
|
||||
await ReplyConfirmLocalizedAsync(strs.club_disbanded(Format.Bold(club.ToString())));
|
||||
await ReplyConfirmLocalizedAsync(strs.club_disbanded(Format.Bold(club.Name)));
|
||||
else
|
||||
await ReplyErrorLocalizedAsync(strs.club_disband_error);
|
||||
}
|
||||
|
@@ -1,10 +1,13 @@
|
||||
#nullable disable
|
||||
using LinqToDB;
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Db;
|
||||
using NadekoBot.Db.Models;
|
||||
|
||||
namespace NadekoBot.Modules.Xp.Services;
|
||||
|
||||
public class ClubService : INService
|
||||
public class ClubService : INService, IClubService
|
||||
{
|
||||
private readonly DbService _db;
|
||||
private readonly IHttpClientFactory _httpFactory;
|
||||
@@ -15,46 +18,42 @@ public class ClubService : INService
|
||||
_httpFactory = httpFactory;
|
||||
}
|
||||
|
||||
public bool CreateClub(IUser user, string clubName, out ClubInfo club)
|
||||
public async Task<bool?> CreateClubAsync(IUser user, string clubName)
|
||||
{
|
||||
//must be lvl 5 and must not be in a club already
|
||||
|
||||
club = null;
|
||||
using var uow = _db.GetDbContext();
|
||||
await using var uow = _db.GetDbContext();
|
||||
var du = uow.GetOrCreateUser(user);
|
||||
uow.SaveChanges();
|
||||
var xp = new LevelStats(du.TotalXp);
|
||||
|
||||
if (xp.Level >= 5 && du.Club is null)
|
||||
{
|
||||
du.IsClubAdmin = true;
|
||||
du.Club = new()
|
||||
{
|
||||
Name = clubName,
|
||||
Discrim = uow.Clubs.GetNextDiscrim(clubName),
|
||||
Owner = du
|
||||
};
|
||||
uow.Clubs.Add(du.Club);
|
||||
uow.SaveChanges();
|
||||
}
|
||||
else
|
||||
|
||||
if (xp.Level < 5 || du.ClubId is not null)
|
||||
return false;
|
||||
|
||||
uow.Set<ClubApplicants>().RemoveRange(uow.Set<ClubApplicants>().AsQueryable().Where(x => x.UserId == du.Id));
|
||||
club = du.Club;
|
||||
uow.SaveChanges();
|
||||
if (await uow.Clubs.AnyAsyncEF(x => x.Name == clubName))
|
||||
return null;
|
||||
|
||||
du.IsClubAdmin = true;
|
||||
du.Club = new()
|
||||
{
|
||||
Name = clubName,
|
||||
Owner = du
|
||||
};
|
||||
uow.Clubs.Add(du.Club);
|
||||
await uow.SaveChangesAsync();
|
||||
|
||||
await uow.GetTable<ClubApplicants>()
|
||||
.DeleteAsync(x => x.UserId == du.Id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public ClubInfo TransferClub(IUser from, IUser newOwner)
|
||||
{
|
||||
ClubInfo club;
|
||||
using var uow = _db.GetDbContext();
|
||||
club = uow.Clubs.GetByOwner(from.Id);
|
||||
var club = uow.Clubs.GetByOwner(@from.Id);
|
||||
var newOwnerUser = uow.GetOrCreateUser(newOwner);
|
||||
|
||||
if (club is null || club.Owner.UserId != from.Id || !club.Users.Contains(newOwnerUser))
|
||||
if (club is null || club.Owner.UserId != from.Id || !club.Members.Contains(newOwnerUser))
|
||||
return null;
|
||||
|
||||
club.Owner.IsClubAdmin = true; // old owner will stay as admin
|
||||
@@ -64,21 +63,20 @@ public class ClubService : INService
|
||||
return club;
|
||||
}
|
||||
|
||||
public bool ToggleAdmin(IUser owner, IUser toAdmin)
|
||||
public async Task<bool?> ToggleAdminAsync(IUser owner, IUser toAdmin)
|
||||
{
|
||||
bool newState;
|
||||
using var uow = _db.GetDbContext();
|
||||
await using var uow = _db.GetDbContext();
|
||||
var club = uow.Clubs.GetByOwner(owner.Id);
|
||||
var adminUser = uow.GetOrCreateUser(toAdmin);
|
||||
|
||||
if (club is null || club.Owner.UserId != owner.Id || !club.Users.Contains(adminUser))
|
||||
throw new InvalidOperationException();
|
||||
if (club is null || club.Owner.UserId != owner.Id || !club.Members.Contains(adminUser))
|
||||
return null;
|
||||
|
||||
if (club.OwnerId == adminUser.Id)
|
||||
return true;
|
||||
|
||||
newState = adminUser.IsClubAdmin = !adminUser.IsClubAdmin;
|
||||
uow.SaveChanges();
|
||||
var newState = adminUser.IsClubAdmin = !adminUser.IsClubAdmin;
|
||||
await uow.SaveChangesAsync();
|
||||
return newState;
|
||||
}
|
||||
|
||||
@@ -89,13 +87,13 @@ public class ClubService : INService
|
||||
return member;
|
||||
}
|
||||
|
||||
public async Task<bool> SetClubIcon(ulong ownerUserId, Uri url)
|
||||
public async Task<bool> SetClubIconAsync(ulong ownerUserId, string url)
|
||||
{
|
||||
if (url is not null)
|
||||
{
|
||||
using var http = _httpFactory.CreateClient();
|
||||
using var temp = await http.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
|
||||
if (!temp.IsImage() || temp.GetImageSize() > 11)
|
||||
if (!temp.IsImage() || temp.GetContentLength() > 5.Megabytes().Bytes)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -105,30 +103,18 @@ public class ClubService : INService
|
||||
if (club is null)
|
||||
return false;
|
||||
|
||||
club.ImageUrl = url.ToString();
|
||||
uow.SaveChanges();
|
||||
club.ImageUrl = url;
|
||||
await uow.SaveChangesAsync();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool GetClubByName(string clubName, out ClubInfo club)
|
||||
{
|
||||
club = null;
|
||||
var arr = clubName.Split('#');
|
||||
if (arr.Length < 2 || !int.TryParse(arr[arr.Length - 1], out var discrim))
|
||||
return false;
|
||||
|
||||
//incase club has # in it
|
||||
var name = string.Concat(arr.Except(new[] { arr[arr.Length - 1] }));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
return false;
|
||||
|
||||
using var uow = _db.GetDbContext();
|
||||
club = uow.Clubs.GetByName(name, discrim);
|
||||
if (club is null)
|
||||
return false;
|
||||
return true;
|
||||
club = uow.Clubs.GetByName(clubName);
|
||||
|
||||
return club is not null;
|
||||
}
|
||||
|
||||
public bool ApplyToClub(IUser user, ClubInfo club)
|
||||
@@ -138,7 +124,6 @@ public class ClubService : INService
|
||||
uow.SaveChanges();
|
||||
|
||||
if (du.Club is not null
|
||||
|| new LevelStats(du.TotalXp).Level < club.MinimumLevelReq
|
||||
|| club.Bans.Any(x => x.UserId == du.Id)
|
||||
|| club.Applicants.Any(x => x.UserId == du.Id))
|
||||
//user banned or a member of a club, or already applied,
|
||||
@@ -202,23 +187,7 @@ public class ClubService : INService
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool ChangeClubLevelReq(ulong userId, int level)
|
||||
{
|
||||
if (level < 5)
|
||||
return false;
|
||||
|
||||
using var uow = _db.GetDbContext();
|
||||
var club = uow.Clubs.GetByOwner(userId);
|
||||
if (club is null)
|
||||
return false;
|
||||
|
||||
club.MinimumLevelReq = level;
|
||||
uow.SaveChanges();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool ChangeClubDescription(ulong userId, string desc)
|
||||
public bool SetDescription(ulong userId, string desc)
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
var club = uow.Clubs.GetByOwner(userId);
|
||||
@@ -250,7 +219,7 @@ public class ClubService : INService
|
||||
if (club is null)
|
||||
return false;
|
||||
|
||||
var usr = club.Users.FirstOrDefault(x => x.ToString().ToUpperInvariant() == userName.ToUpperInvariant())
|
||||
var usr = club.Members.FirstOrDefault(x => x.ToString().ToUpperInvariant() == userName.ToUpperInvariant())
|
||||
?? club.Applicants
|
||||
.FirstOrDefault(x => x.User.ToString().ToUpperInvariant() == userName.ToUpperInvariant())
|
||||
?.User;
|
||||
@@ -266,7 +235,7 @@ public class ClubService : INService
|
||||
Club = club,
|
||||
User = usr
|
||||
});
|
||||
club.Users.Remove(usr);
|
||||
club.Members.Remove(usr);
|
||||
|
||||
var app = club.Applicants.FirstOrDefault(x => x.UserId == usr.Id);
|
||||
if (app is not null)
|
||||
@@ -301,14 +270,14 @@ public class ClubService : INService
|
||||
if (club is null)
|
||||
return false;
|
||||
|
||||
var usr = club.Users.FirstOrDefault(x => x.ToString().ToUpperInvariant() == userName.ToUpperInvariant());
|
||||
var usr = club.Members.FirstOrDefault(x => x.ToString().ToUpperInvariant() == userName.ToUpperInvariant());
|
||||
if (usr is null)
|
||||
return false;
|
||||
|
||||
if (club.OwnerId == usr.Id || (usr.IsClubAdmin && club.Owner.UserId != kickerId))
|
||||
return false;
|
||||
|
||||
club.Users.Remove(usr);
|
||||
club.Members.Remove(usr);
|
||||
var app = club.Applicants.FirstOrDefault(x => x.UserId == usr.Id);
|
||||
if (app is not null)
|
||||
club.Applicants.Remove(app);
|
||||
|
23
src/NadekoBot/Modules/Xp/Club/IClubService.cs
Normal file
23
src/NadekoBot/Modules/Xp/Club/IClubService.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using NadekoBot.Db.Models;
|
||||
|
||||
namespace NadekoBot.Modules.Xp.Services;
|
||||
|
||||
public interface IClubService
|
||||
{
|
||||
Task<bool?> CreateClubAsync(IUser user, string clubName);
|
||||
ClubInfo? TransferClub(IUser from, IUser newOwner);
|
||||
Task<bool?> ToggleAdminAsync(IUser owner, IUser toAdmin);
|
||||
ClubInfo? GetClubByMember(IUser user);
|
||||
Task<bool> SetClubIconAsync(ulong ownerUserId, string? url);
|
||||
bool GetClubByName(string clubName, out ClubInfo club);
|
||||
bool ApplyToClub(IUser user, ClubInfo club);
|
||||
bool AcceptApplication(ulong clubOwnerUserId, string userName, out DiscordUser discordUser);
|
||||
ClubInfo? GetClubWithBansAndApplications(ulong ownerUserId);
|
||||
bool LeaveClub(IUser user);
|
||||
bool SetDescription(ulong userId, string? desc);
|
||||
bool Disband(ulong userId, out ClubInfo club);
|
||||
bool Ban(ulong bannerId, string userName, out ClubInfo club);
|
||||
bool UnBan(ulong ownerUserId, string userName, out ClubInfo club);
|
||||
bool Kick(ulong kickerId, string userName, out ClubInfo club);
|
||||
List<ClubInfo> GetClubLeaderboardPage(int page);
|
||||
}
|
@@ -647,7 +647,7 @@ public class XpService : INService, IReadyExecutor
|
||||
int guildRank;
|
||||
await using (var uow = _db.GetDbContext())
|
||||
{
|
||||
du = uow.GetOrCreateUser(user);
|
||||
du = uow.GetOrCreateUser(user, set => set.Include(x => x.Club));
|
||||
totalXp = du.TotalXp;
|
||||
globalRank = uow.DiscordUser.GetUserGlobalRank(user.Id);
|
||||
guildRank = uow.UserXpStats.GetUserGuildRanking(user.Id, user.GuildId);
|
||||
@@ -1021,8 +1021,9 @@ public class XpService : INService, IReadyExecutor
|
||||
using (var http = _httpFactory.CreateClient())
|
||||
using (var temp = await http.GetAsync(imgUrl, HttpCompletionOption.ResponseHeadersRead))
|
||||
{
|
||||
if (!temp.IsImage() || temp.GetImageSize() > 11)
|
||||
if (!temp.IsImage() || temp.GetContentLength() > 11.Megabytes().Bytes)
|
||||
return;
|
||||
|
||||
var imgData = await temp.Content.ReadAsByteArrayAsync();
|
||||
using (var tempDraw = Image.Load(imgData))
|
||||
{
|
||||
|
@@ -84,6 +84,9 @@
|
||||
<!-- <PrivateAssets>all</PrivateAssets>-->
|
||||
<!-- <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>-->
|
||||
<!-- </PackageReference>-->
|
||||
|
||||
<PackageReference Include="EFCore.NamingConventions" Version="6.0.0" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@@ -1,7 +1,6 @@
|
||||
#nullable disable
|
||||
using LinqToDB.Common;
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Services.Database;
|
||||
|
||||
@@ -9,49 +8,68 @@ namespace NadekoBot.Services;
|
||||
|
||||
public class DbService
|
||||
{
|
||||
private readonly DbContextOptions<NadekoContext> _options;
|
||||
private readonly DbContextOptions<NadekoContext> _migrateOptions;
|
||||
private readonly IBotCredsProvider _creds;
|
||||
|
||||
public DbService(IBotCredentials creds)
|
||||
// these are props because creds can change at runtime
|
||||
private string DbType => _creds.GetCreds().Db.Type.ToLowerInvariant().Trim();
|
||||
private string ConnString => _creds.GetCreds().Db.ConnectionString;
|
||||
|
||||
public DbService(IBotCredsProvider creds)
|
||||
{
|
||||
LinqToDBForEFTools.Initialize();
|
||||
Configuration.Linq.DisableQueryCache = true;
|
||||
|
||||
var builder = new SqliteConnectionStringBuilder(creds.Db.ConnectionString);
|
||||
builder.DataSource = Path.Combine(AppContext.BaseDirectory, builder.DataSource);
|
||||
|
||||
var optionsBuilder = new DbContextOptionsBuilder<NadekoContext>();
|
||||
optionsBuilder.UseSqlite(builder.ToString());
|
||||
_options = optionsBuilder.Options;
|
||||
|
||||
optionsBuilder = new();
|
||||
optionsBuilder.UseSqlite(builder.ToString());
|
||||
_migrateOptions = optionsBuilder.Options;
|
||||
_creds = creds;
|
||||
}
|
||||
|
||||
public void Setup()
|
||||
public async Task SetupAsync()
|
||||
{
|
||||
using var context = new NadekoContext(_options);
|
||||
if (context.Database.GetPendingMigrations().Any())
|
||||
{
|
||||
using var mContext = new NadekoContext(_migrateOptions);
|
||||
mContext.Database.Migrate();
|
||||
mContext.SaveChanges();
|
||||
}
|
||||
var dbType = DbType;
|
||||
var connString = ConnString;
|
||||
|
||||
context.Database.ExecuteSqlRaw("PRAGMA journal_mode=WAL");
|
||||
context.SaveChanges();
|
||||
await using var context = CreateRawDbContext(dbType, connString);
|
||||
|
||||
// make sure sqlite db is in wal journal mode
|
||||
if (context is SqliteContext)
|
||||
{
|
||||
await context.Database.ExecuteSqlRawAsync("PRAGMA journal_mode=WAL");
|
||||
}
|
||||
|
||||
await context.Database.MigrateAsync();
|
||||
}
|
||||
|
||||
private static NadekoContext CreateRawDbContext(string dbType, string connString)
|
||||
{
|
||||
switch (dbType)
|
||||
{
|
||||
case "postgresql":
|
||||
case "postgres":
|
||||
case "pgsql":
|
||||
return new PostgreSqlContext(connString);
|
||||
case "mysql":
|
||||
return new MysqlContext(connString);
|
||||
case "sqlite":
|
||||
return new SqliteContext(connString);
|
||||
default:
|
||||
throw new NotSupportedException($"The database provide type of '{dbType}' is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
private NadekoContext GetDbContextInternal()
|
||||
{
|
||||
var context = new NadekoContext(_options);
|
||||
context.Database.SetCommandTimeout(60);
|
||||
var conn = context.Database.GetDbConnection();
|
||||
conn.Open();
|
||||
using var com = conn.CreateCommand();
|
||||
com.CommandText = "PRAGMA journal_mode=WAL; PRAGMA synchronous=OFF";
|
||||
com.ExecuteNonQuery();
|
||||
var dbType = DbType;
|
||||
var connString = ConnString;
|
||||
|
||||
var context = CreateRawDbContext(dbType, connString);
|
||||
if (context is SqliteContext)
|
||||
{
|
||||
var conn = context.Database.GetDbConnection();
|
||||
conn.Open();
|
||||
using var com = conn.CreateCommand();
|
||||
com.CommandText = "PRAGMA synchronous=OFF";
|
||||
com.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
@@ -52,5 +52,5 @@ public interface IStatsService
|
||||
/// <summary>
|
||||
/// Gets total amount of private memory currently in use by the bot, in Megabytes.
|
||||
/// </summary>
|
||||
double GetPrivateMemory();
|
||||
double GetPrivateMemoryMegabytes();
|
||||
}
|
@@ -166,9 +166,9 @@ public sealed class BotCredsProvider : IBotCredsProvider
|
||||
if (File.Exists(CREDS_FILE_NAME))
|
||||
{
|
||||
var creds = Yaml.Deserializer.Deserialize<Creds>(File.ReadAllText(CREDS_FILE_NAME));
|
||||
if (creds.Version <= 3)
|
||||
if (creds.Version <= 4)
|
||||
{
|
||||
creds.Version = 4;
|
||||
creds.Version = 5;
|
||||
File.WriteAllText(CREDS_FILE_NAME, Yaml.Serializer.Serialize(creds));
|
||||
}
|
||||
}
|
||||
|
@@ -183,9 +183,9 @@ public sealed class StatsService : IStatsService, IReadyExecutor, INService
|
||||
return time.Humanize(3, maxUnit: TimeUnit.Day, minUnit: TimeUnit.Minute);
|
||||
}
|
||||
|
||||
public double GetPrivateMemory()
|
||||
public double GetPrivateMemoryMegabytes()
|
||||
{
|
||||
_currentProcess.Refresh();
|
||||
return _currentProcess.PrivateMemorySize64 / (double)1.MiB();
|
||||
return _currentProcess.PrivateMemorySize64 / 1.Megabytes().Bytes;
|
||||
}
|
||||
}
|
||||
|
@@ -190,13 +190,10 @@ public static class Extensions
|
||||
return false;
|
||||
}
|
||||
|
||||
public static long? GetImageSize(this HttpResponseMessage msg)
|
||||
{
|
||||
if (msg.Content.Headers.ContentLength is null)
|
||||
return null;
|
||||
|
||||
return msg.Content.Headers.ContentLength.Value / 1.Mb();
|
||||
}
|
||||
public static long GetContentLength(this HttpResponseMessage msg)
|
||||
=> msg.Content.Headers.ContentLength is long length
|
||||
? length
|
||||
: long.MaxValue;
|
||||
|
||||
public static string GetText(this IBotStrings strings, in LocStr str, ulong? guildId = null)
|
||||
=> strings.GetText(str.Key, guildId, str.Params);
|
||||
|
@@ -2,45 +2,6 @@ namespace NadekoBot.Extensions;
|
||||
|
||||
public static class NumberExtensions
|
||||
{
|
||||
public static int KiB(this int value)
|
||||
=> value * 1024;
|
||||
|
||||
public static int Kb(this int value)
|
||||
=> value * 1000;
|
||||
|
||||
public static int MiB(this int value)
|
||||
=> value.KiB() * 1024;
|
||||
|
||||
public static int Mb(this int value)
|
||||
=> value.Kb() * 1000;
|
||||
|
||||
public static int GiB(this int value)
|
||||
=> value.MiB() * 1024;
|
||||
|
||||
public static int Gb(this int value)
|
||||
=> value.Mb() * 1000;
|
||||
|
||||
public static ulong KiB(this ulong value)
|
||||
=> value * 1024;
|
||||
|
||||
public static ulong Kb(this ulong value)
|
||||
=> value * 1000;
|
||||
|
||||
public static ulong MiB(this ulong value)
|
||||
=> value.KiB() * 1024;
|
||||
|
||||
public static ulong Mb(this ulong value)
|
||||
=> value.Kb() * 1000;
|
||||
|
||||
public static ulong GiB(this ulong value)
|
||||
=> value.MiB() * 1024;
|
||||
|
||||
public static ulong Gb(this ulong value)
|
||||
=> value.Mb() * 1000;
|
||||
|
||||
public static bool IsInteger(this decimal number)
|
||||
=> number == Math.Truncate(number);
|
||||
|
||||
public static DateTimeOffset ToUnixTimestamp(this double number)
|
||||
=> new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero).AddSeconds(number);
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
# DO NOT CHANGE
|
||||
version: 4
|
||||
version: 5
|
||||
# Bot token. Do not share with anyone ever -> https://discordapp.com/developers/applications/
|
||||
token: ''
|
||||
# List of Ids of the users who have bot owner permissions
|
||||
@@ -47,9 +47,14 @@ cleverbotApiKey: ''
|
||||
redisOptions: localhost:6379,syncTimeout=30000,responseTimeout=30000,allowAdmin=true,password=
|
||||
# Database options. Don't change if you don't know what you're doing. Leave null for default values
|
||||
db:
|
||||
# Database type. Only sqlite supported atm
|
||||
# Database type. "sqlite", "mysql" and "postgresql" are supported.
|
||||
# Default is "sqlite"
|
||||
type: sqlite
|
||||
# Connection string. Will default to "Data Source=data/NadekoBot.db"
|
||||
# Database connection string.
|
||||
# You MUST change this if you're not using "sqlite" type.
|
||||
# Default is "Data Source=data/NadekoBot.db"
|
||||
# Example for mysql: "Server=localhost;Port=3306;Uid=root;Pwd=my_super_secret_mysql_password;Database=nadeko"
|
||||
# Example for postgresql: "Server=localhost;Port=5432;User Id=postgres;Password=my_super_secret_postgres_password;Database=nadeko;"
|
||||
connectionString: Data Source=data/NadekoBot.db
|
||||
# Address and port of the coordinator endpoint. Leave empty for default.
|
||||
# Change only if you've changed the coordinator address or port.
|
||||
|
@@ -1074,8 +1074,6 @@ clubban:
|
||||
- clubban
|
||||
clubunban:
|
||||
- clubunban
|
||||
clublevelreq:
|
||||
- clublevelreq
|
||||
clubdescription:
|
||||
- clubdesc
|
||||
clubicon:
|
||||
|
@@ -1891,10 +1891,6 @@ clubunban:
|
||||
desc: "Unbans the previously banned user from the club. You must be the club owner."
|
||||
args:
|
||||
- "user#1337"
|
||||
clublevelreq:
|
||||
desc: "Sets the club required level to apply to join the club. You must be club owner. You can't set this number below 5."
|
||||
args:
|
||||
- "7"
|
||||
clubdescription:
|
||||
desc: "Sets the club description. Maximum 150 characters. Club owner only."
|
||||
args:
|
||||
|
@@ -818,6 +818,7 @@
|
||||
"server_leaderboard": "Server XP Leaderboard",
|
||||
"global_leaderboard": "Global XP Leaderboard",
|
||||
"modified": "Modified server XP of the user {0} by {1}",
|
||||
"club_create_error_name": "Failed creating the club. A club with that name already exists.",
|
||||
"club_create_error": "Failed creating the club. Make sure you're above level 5 and not a member of a club already.",
|
||||
"club_name_too_long": "Club name is too long.",
|
||||
"club_created": "Club {0} successfully created!",
|
||||
@@ -835,8 +836,6 @@
|
||||
"club_user_ban_fail": "Failed to ban. You're either not the club owner, or that user is not in your club or applied to it.",
|
||||
"club_user_unbanned": "Unbanned user {0} in {1} club.",
|
||||
"club_user_unban_fail": "Failed to unban. You're either not the club owner, or that user is not in your club or applied to it.",
|
||||
"club_level_req_changed": "Changed club's level requirement to {0}",
|
||||
"club_level_req_change_error": "Failed changing level requirement.",
|
||||
"club_desc_updated": "Updated club description to {0}",
|
||||
"club_desc_update_failed": "Failed changing club description.",
|
||||
"club_disbanded": "Club {0} has been disbanded",
|
||||
|
Reference in New Issue
Block a user