mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2026-09-20 12:00:56 -04:00
WIP db provider support for Mysql and Postgres
This commit is contained in:
+17
-1
@@ -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; }
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -8,7 +8,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20210621042359_squash")]
|
||||
partial class squash
|
||||
{
|
||||
+1
-1
@@ -8,7 +8,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20210707002343_cleanup")]
|
||||
partial class cleanup
|
||||
{
|
||||
+1
-1
@@ -8,7 +8,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20210911225622_rero-cascade")]
|
||||
partial class rerocascade
|
||||
{
|
||||
+1
-1
@@ -8,7 +8,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20210912182515_boost-messages")]
|
||||
partial class boostmessages
|
||||
{
|
||||
+1
-1
@@ -8,7 +8,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20210912200106_logsettings-independence")]
|
||||
partial class logsettingsindependence
|
||||
{
|
||||
+1
-1
@@ -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
|
||||
{
|
||||
+1
-1
@@ -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
|
||||
{
|
||||
+1
-1
@@ -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
|
||||
{
|
||||
+1
-1
@@ -8,7 +8,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20211121002508_weighted-warnings")]
|
||||
partial class weightedwarnings
|
||||
{
|
||||
+1
-1
@@ -8,7 +8,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20211213145407_atl-rework")]
|
||||
partial class atlrework
|
||||
{
|
||||
+1
-1
@@ -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
|
||||
{
|
||||
+1
-1
@@ -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
|
||||
{
|
||||
+1
-1
@@ -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
|
||||
{
|
||||
+1
-1
@@ -10,7 +10,7 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
[DbContext(typeof(NadekoContext))]
|
||||
[DbContext(typeof(SqliteContext))]
|
||||
[Migration("20220213123633_music-autoplay")]
|
||||
partial class musicautoplay
|
||||
{
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+85
-89
@@ -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);
|
||||
|
||||
@@ -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