sar rework, improved
This commit is contained in:
parent
af71e88985
commit
3532554a13
30 changed files with 8417 additions and 569 deletions
|
@ -2,6 +2,7 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using EllieBot.Db.Models;
|
||||
using EllieBot.Modules.Administration.Services;
|
||||
|
||||
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||
|
||||
|
@ -14,7 +15,6 @@ public abstract class EllieContext : DbContext
|
|||
|
||||
public DbSet<Quote> Quotes { get; set; }
|
||||
public DbSet<Reminder> Reminders { get; set; }
|
||||
public DbSet<SelfAssignedRole> SelfAssignableRoles { get; set; }
|
||||
public DbSet<MusicPlaylist> MusicPlaylists { get; set; }
|
||||
public DbSet<EllieExpression> Expressions { get; set; }
|
||||
public DbSet<CurrencyTransaction> CurrencyTransactions { get; set; }
|
||||
|
@ -74,6 +74,34 @@ public abstract class EllieContext : DbContext
|
|||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
#region New Sar
|
||||
|
||||
modelBuilder.Entity<SarGroup>(sg =>
|
||||
{
|
||||
sg.HasAlternateKey(x => new
|
||||
{
|
||||
x.GuildId,
|
||||
x.GroupNumber
|
||||
});
|
||||
|
||||
sg.HasMany(x => x.Roles)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Sar>()
|
||||
.HasAlternateKey(x => new
|
||||
{
|
||||
x.GuildId,
|
||||
x.RoleId
|
||||
});
|
||||
|
||||
modelBuilder.Entity<SarAutoDelete>()
|
||||
.HasIndex(x => x.GuildId)
|
||||
.IsUnique();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rakeback
|
||||
|
||||
modelBuilder.Entity<Rakeback>()
|
||||
|
@ -84,16 +112,23 @@ public abstract class EllieContext : DbContext
|
|||
#region UserBetStats
|
||||
|
||||
modelBuilder.Entity<UserBetStats>()
|
||||
.HasIndex(x => new { x.UserId, x.Game })
|
||||
.HasIndex(x => new
|
||||
{
|
||||
x.UserId,
|
||||
x.Game
|
||||
})
|
||||
.IsUnique();
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Flag Translate
|
||||
#region Flag Translate
|
||||
|
||||
modelBuilder.Entity<FlagTranslateChannel>()
|
||||
.HasIndex(x => new { x.GuildId, x.ChannelId })
|
||||
.HasIndex(x => new
|
||||
{
|
||||
x.GuildId,
|
||||
x.ChannelId
|
||||
})
|
||||
.IsUnique();
|
||||
|
||||
#endregion
|
||||
|
@ -286,11 +321,6 @@ public abstract class EllieContext : DbContext
|
|||
.HasForeignKey(x => x.GuildConfigId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.SelfAssignableRoleGroupNames)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<FeedSub>()
|
||||
.HasAlternateKey(x => new
|
||||
{
|
||||
|
@ -319,21 +349,6 @@ public abstract class EllieContext : DbContext
|
|||
|
||||
#endregion
|
||||
|
||||
#region Self Assignable Roles
|
||||
|
||||
var selfassignableRolesEntity = modelBuilder.Entity<SelfAssignedRole>();
|
||||
|
||||
selfassignableRolesEntity.HasIndex(s => new
|
||||
{
|
||||
s.GuildId,
|
||||
s.RoleId
|
||||
})
|
||||
.IsUnique();
|
||||
|
||||
selfassignableRolesEntity.Property(x => x.Group).HasDefaultValue(0);
|
||||
|
||||
#endregion
|
||||
|
||||
#region MusicPlaylists
|
||||
|
||||
var musicPlaylistEntity = modelBuilder.Entity<MusicPlaylist>();
|
||||
|
@ -401,10 +416,10 @@ public abstract class EllieContext : DbContext
|
|||
|
||||
var xps = modelBuilder.Entity<UserXpStats>();
|
||||
xps.HasIndex(x => new
|
||||
{
|
||||
x.UserId,
|
||||
x.GuildId
|
||||
})
|
||||
{
|
||||
x.UserId,
|
||||
x.GuildId
|
||||
})
|
||||
.IsUnique();
|
||||
|
||||
xps.HasIndex(x => x.UserId);
|
||||
|
@ -450,9 +465,9 @@ public abstract class EllieContext : DbContext
|
|||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
ci.HasIndex(x => new
|
||||
{
|
||||
x.Name
|
||||
})
|
||||
{
|
||||
x.Name
|
||||
})
|
||||
.IsUnique();
|
||||
|
||||
#endregion
|
||||
|
@ -516,23 +531,6 @@ public abstract class EllieContext : DbContext
|
|||
|
||||
#endregion
|
||||
|
||||
#region GroupName
|
||||
|
||||
modelBuilder.Entity<GroupName>()
|
||||
.HasIndex(x => new
|
||||
{
|
||||
x.GuildConfigId,
|
||||
x.Number
|
||||
})
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<GroupName>()
|
||||
.HasOne(x => x.GuildConfig)
|
||||
.WithMany(x => x.SelfAssignableRoleGroupNames)
|
||||
.IsRequired();
|
||||
|
||||
#endregion
|
||||
|
||||
#region BanTemplate
|
||||
|
||||
modelBuilder.Entity<BanTemplate>().HasIndex(x => x.GuildId).IsUnique();
|
||||
|
@ -571,10 +569,10 @@ public abstract class EllieContext : DbContext
|
|||
.IsUnique(false);
|
||||
|
||||
rr2.HasIndex(x => new
|
||||
{
|
||||
x.MessageId,
|
||||
x.Emote
|
||||
})
|
||||
{
|
||||
x.MessageId,
|
||||
x.Emote
|
||||
})
|
||||
.IsUnique();
|
||||
});
|
||||
|
||||
|
@ -649,11 +647,11 @@ public abstract class EllieContext : DbContext
|
|||
{
|
||||
// user can own only one of each item
|
||||
x.HasIndex(model => new
|
||||
{
|
||||
model.UserId,
|
||||
model.ItemType,
|
||||
model.ItemKey
|
||||
})
|
||||
{
|
||||
model.UserId,
|
||||
model.ItemType,
|
||||
model.ItemKey
|
||||
})
|
||||
.IsUnique();
|
||||
});
|
||||
|
||||
|
@ -678,10 +676,10 @@ public abstract class EllieContext : DbContext
|
|||
#region Sticky Roles
|
||||
|
||||
modelBuilder.Entity<StickyRole>(sr => sr.HasIndex(x => new
|
||||
{
|
||||
x.GuildId,
|
||||
x.UserId
|
||||
})
|
||||
{
|
||||
x.GuildId,
|
||||
x.UserId
|
||||
})
|
||||
.IsUnique());
|
||||
|
||||
#endregion
|
||||
|
@ -726,10 +724,10 @@ public abstract class EllieContext : DbContext
|
|||
|
||||
modelBuilder
|
||||
.Entity<GreetSettings>(gs => gs.HasIndex(x => new
|
||||
{
|
||||
x.GuildId,
|
||||
x.GreetType
|
||||
})
|
||||
{
|
||||
x.GuildId,
|
||||
x.GreetType
|
||||
})
|
||||
.IsUnique());
|
||||
|
||||
modelBuilder.Entity<GreetSettings>(gs =>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#nullable disable
|
||||
using LinqToDB;
|
||||
using LinqToDB;
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using EllieBot.Db.Models;
|
||||
|
@ -8,6 +7,9 @@ namespace EllieBot.Db;
|
|||
|
||||
public static class UserXpExtensions
|
||||
{
|
||||
public static async Task<UserXpStats?> GetGuildUserXp(this ITable<UserXpStats> table, ulong guildId, ulong userId)
|
||||
=> await table.FirstOrDefaultAsyncLinqToDB(x => x.GuildId == guildId && x.UserId == userId);
|
||||
|
||||
public static UserXpStats GetOrCreateUserXpStats(this DbContext ctx, ulong guildId, ulong userId)
|
||||
{
|
||||
var usr = ctx.Set<UserXpStats>().FirstOrDefault(x => x.UserId == userId && x.GuildId == guildId);
|
||||
|
|
|
@ -9,7 +9,8 @@ public class FollowedStream : DbEntity
|
|||
Picarto = 3,
|
||||
Youtube = 4,
|
||||
Facebook = 5,
|
||||
Trovo = 6
|
||||
Trovo = 6,
|
||||
Kick = 7,
|
||||
}
|
||||
|
||||
public ulong GuildId { get; set; }
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
#nullable disable
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace EllieBot.Db.Models;
|
||||
|
||||
public class GroupName : DbEntity
|
||||
public sealed class SarGroup : DbEntity
|
||||
{
|
||||
public int GuildConfigId { get; set; }
|
||||
public GuildConfig GuildConfig { get; set; }
|
||||
[Key]
|
||||
public int Id { get; set; }
|
||||
|
||||
public int Number { get; set; }
|
||||
public string Name { get; set; }
|
||||
public int GroupNumber { get; set; }
|
||||
public ulong GuildId { get; set; }
|
||||
public ulong? RoleReq { get; set; }
|
||||
public ICollection<Sar> Roles { get; set; } = [];
|
||||
public bool IsExclusive { get; set; }
|
||||
|
||||
[MaxLength(100)]
|
||||
public string? Name { get; set; }
|
||||
}
|
|
@ -31,10 +31,11 @@ public class GuildConfig : DbEntity
|
|||
// public bool SendBoostMessage { get; set; }
|
||||
// pulic int BoostMessageDeleteAfter { get; set; }
|
||||
|
||||
//self assignable roles
|
||||
//todo FUTURE: DELETE, UNUSED
|
||||
public bool ExclusiveSelfAssignedRoles { get; set; }
|
||||
public bool AutoDeleteSelfAssignedRoleMessages { get; set; }
|
||||
|
||||
|
||||
//stream notifications
|
||||
public HashSet<FollowedStream> FollowedStreams { get; set; } = new();
|
||||
|
||||
|
@ -91,7 +92,6 @@ public class GuildConfig : DbEntity
|
|||
public List<FeedSub> FeedSubs { get; set; } = new();
|
||||
public bool NotifyStreamOffline { get; set; }
|
||||
public bool DeleteStreamOnlineMessage { get; set; }
|
||||
public List<GroupName> SelfAssignableRoleGroupNames { get; set; }
|
||||
public int WarnExpireHours { get; set; }
|
||||
public WarnExpireAction WarnExpireAction { get; set; } = WarnExpireAction.Clear;
|
||||
|
||||
|
|
|
@ -1,11 +1,24 @@
|
|||
#nullable disable
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace EllieBot.Db.Models;
|
||||
|
||||
public class SelfAssignedRole : DbEntity
|
||||
public sealed class Sar
|
||||
{
|
||||
[Key]
|
||||
public int Id { get; set; }
|
||||
|
||||
public ulong GuildId { get; set; }
|
||||
public ulong RoleId { get; set; }
|
||||
|
||||
public int Group { get; set; }
|
||||
public int LevelRequirement { get; set; }
|
||||
public int SarGroupId { get; set; }
|
||||
public int LevelReq { get; set; }
|
||||
}
|
||||
|
||||
public sealed class SarAutoDelete
|
||||
{
|
||||
[Key]
|
||||
public int Id { get; set; }
|
||||
|
||||
public ulong GuildId { get; set; }
|
||||
public bool IsEnabled { get; set; } = false;
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>true</ImplicitUsings>
|
||||
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
|
||||
<Version>5.1.20</Version>
|
||||
<Version>5.2.0</Version>
|
||||
|
||||
<!-- Output/build -->
|
||||
<RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>
|
||||
|
|
|
@ -5,6 +5,37 @@ namespace EllieBot.Migrations;
|
|||
|
||||
public static class MigrationQueries
|
||||
{
|
||||
public static void MigrateSar(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.Sql("""
|
||||
INSERT INTO GroupName (Number, GuildConfigId)
|
||||
SELECT DISTINCT "Group", GC.Id
|
||||
FROM SelfAssignableRoles as SAR
|
||||
INNER JOIN GuildConfigs as GC
|
||||
ON SAR.GuildId = GC.GuildId
|
||||
WHERE SAR.GuildId not in (SELECT GuildConfigs.GuildId from GroupName LEFT JOIN GuildConfigs ON GroupName.GuildConfigId = GuildConfigs.Id);
|
||||
|
||||
INSERT INTO SarGroup (Id, GroupNumber, Name, IsExclusive, GuildId)
|
||||
SELECT GN.Id, GN.Number, GN.Name, GC.ExclusiveSelfAssignedRoles, GC.GuildId
|
||||
FROM GroupName as GN
|
||||
INNER JOIN GuildConfigs as GC ON GN.GuildConfigId = GC.Id;
|
||||
|
||||
INSERT INTO Sar (GuildId, RoleId, SarGroupId, LevelReq)
|
||||
SELECT SAR.GuildId, SAR.RoleId, MIN(SG2.Id), MIN(SAR.LevelRequirement)
|
||||
FROM SelfAssignableRoles as SAR
|
||||
INNER JOIN (SELECT GuildId FROM GroupName as gn
|
||||
INNER JOIN GuildConfigs as gc ON gn.GuildConfigId =gc.Id
|
||||
) as SG
|
||||
ON SG.GuildId = SAR.GuildId
|
||||
INNER JOIN GroupName as SG2
|
||||
ON SG2.Number = SAR."Group"
|
||||
GROUP BY SAR.GuildId, SAR.RoleId;
|
||||
|
||||
INSERT INTO SarAutoDelete (GuildId, IsEnabled)
|
||||
SELECT GuildId, AutoDeleteSelfAssignedRoleMessages FROM GuildConfigs WHERE AutoDeleteSelfAssignedRoleMessages = TRUE;
|
||||
""");
|
||||
}
|
||||
|
||||
public static void UpdateUsernames(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.Sql("UPDATE DiscordUser SET Username = '??' || Username WHERE Discriminator = '????';");
|
||||
|
|
|
@ -12,8 +12,6 @@ namespace EllieBot.Migrations.PostgreSql
|
|||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
MigrationQueries.UpdateUsernames(migrationBuilder);
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "discriminator",
|
||||
table: "discorduser");
|
||||
|
|
3951
src/EllieBot/Migrations/PostgreSql/20241127092257_sar-rework.Designer.cs
generated
Normal file
3951
src/EllieBot/Migrations/PostgreSql/20241127092257_sar-rework.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
153
src/EllieBot/Migrations/PostgreSql/20241127092257_sar-rework.cs
Normal file
153
src/EllieBot/Migrations/PostgreSql/20241127092257_sar-rework.cs
Normal file
|
@ -0,0 +1,153 @@
|
|||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace EllieBot.Migrations.PostgreSql
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class sarrework : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "groupname");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "selfassignableroles");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "sarautodelete",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
guildid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||
isenabled = table.Column<bool>(type: "boolean", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_sarautodelete", x => x.id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "sargroup",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
groupnumber = table.Column<int>(type: "integer", nullable: false),
|
||||
guildid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||
rolereq = table.Column<decimal>(type: "numeric(20,0)", nullable: true),
|
||||
isexclusive = table.Column<bool>(type: "boolean", nullable: false),
|
||||
name = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
dateadded = table.Column<DateTime>(type: "timestamp without time zone", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_sargroup", x => x.id);
|
||||
table.UniqueConstraint("ak_sargroup_guildid_groupnumber", x => new { x.guildid, x.groupnumber });
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "sar",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
guildid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||
roleid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||
sargroupid = table.Column<int>(type: "integer", nullable: false),
|
||||
levelreq = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_sar", x => x.id);
|
||||
table.UniqueConstraint("ak_sar_guildid_roleid", x => new { x.guildid, x.roleid });
|
||||
table.ForeignKey(
|
||||
name: "fk_sar_sargroup_sargroupid",
|
||||
column: x => x.sargroupid,
|
||||
principalTable: "sargroup",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_sar_sargroupid",
|
||||
table: "sar",
|
||||
column: "sargroupid");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_sarautodelete_guildid",
|
||||
table: "sarautodelete",
|
||||
column: "guildid",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "sar");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "sarautodelete");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "sargroup");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "groupname",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
guildconfigid = table.Column<int>(type: "integer", nullable: false),
|
||||
dateadded = table.Column<DateTime>(type: "timestamp without time zone", nullable: true),
|
||||
name = table.Column<string>(type: "text", nullable: true),
|
||||
number = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_groupname", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "fk_groupname_guildconfigs_guildconfigid",
|
||||
column: x => x.guildconfigid,
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "selfassignableroles",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
dateadded = table.Column<DateTime>(type: "timestamp without time zone", nullable: true),
|
||||
group = table.Column<int>(type: "integer", nullable: false, defaultValue: 0),
|
||||
guildid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||
levelrequirement = table.Column<int>(type: "integer", nullable: false),
|
||||
roleid = table.Column<decimal>(type: "numeric(20,0)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_selfassignableroles", x => x.id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_groupname_guildconfigid_number",
|
||||
table: "groupname",
|
||||
columns: new[] { "guildconfigid", "number" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_selfassignableroles_guildid_roleid",
|
||||
table: "selfassignableroles",
|
||||
columns: new[] { "guildid", "roleid" },
|
||||
unique: true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1253,41 +1253,6 @@ namespace EllieBot.Migrations.PostgreSql
|
|||
b.ToTable("giveawayuser", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.GroupName", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTime?>("DateAdded")
|
||||
.HasColumnType("timestamp without time zone")
|
||||
.HasColumnName("dateadded");
|
||||
|
||||
b.Property<int>("GuildConfigId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("guildconfigid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.Property<int>("Number")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("number");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_groupname");
|
||||
|
||||
b.HasIndex("GuildConfigId", "Number")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_groupname_guildconfigid_number");
|
||||
|
||||
b.ToTable("groupname", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.GuildConfig", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
@ -2200,7 +2165,71 @@ namespace EllieBot.Migrations.PostgreSql
|
|||
b.ToTable("rotatingstatus", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.SelfAssignedRole", b =>
|
||||
modelBuilder.Entity("EllieBot.Db.Models.Sar", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<decimal>("GuildId")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("guildid");
|
||||
|
||||
b.Property<int>("LevelReq")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("levelreq");
|
||||
|
||||
b.Property<decimal>("RoleId")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("roleid");
|
||||
|
||||
b.Property<int>("SarGroupId")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("sargroupid");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_sar");
|
||||
|
||||
b.HasAlternateKey("GuildId", "RoleId")
|
||||
.HasName("ak_sar_guildid_roleid");
|
||||
|
||||
b.HasIndex("SarGroupId")
|
||||
.HasDatabaseName("ix_sar_sargroupid");
|
||||
|
||||
b.ToTable("sar", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.SarAutoDelete", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<decimal>("GuildId")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("guildid");
|
||||
|
||||
b.Property<bool>("IsEnabled")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("isenabled");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_sarautodelete");
|
||||
|
||||
b.HasIndex("GuildId")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_sarautodelete_guildid");
|
||||
|
||||
b.ToTable("sarautodelete", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.SarGroup", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
@ -2213,32 +2242,34 @@ namespace EllieBot.Migrations.PostgreSql
|
|||
.HasColumnType("timestamp without time zone")
|
||||
.HasColumnName("dateadded");
|
||||
|
||||
b.Property<int>("Group")
|
||||
.ValueGeneratedOnAdd()
|
||||
b.Property<int>("GroupNumber")
|
||||
.HasColumnType("integer")
|
||||
.HasDefaultValue(0)
|
||||
.HasColumnName("group");
|
||||
.HasColumnName("groupnumber");
|
||||
|
||||
b.Property<decimal>("GuildId")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("guildid");
|
||||
|
||||
b.Property<int>("LevelRequirement")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("levelrequirement");
|
||||
b.Property<bool>("IsExclusive")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("isexclusive");
|
||||
|
||||
b.Property<decimal>("RoleId")
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.Property<decimal?>("RoleReq")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("roleid");
|
||||
.HasColumnName("rolereq");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_selfassignableroles");
|
||||
.HasName("pk_sargroup");
|
||||
|
||||
b.HasIndex("GuildId", "RoleId")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_selfassignableroles_guildid_roleid");
|
||||
b.HasAlternateKey("GuildId", "GroupNumber")
|
||||
.HasName("ak_sargroup_guildid_groupnumber");
|
||||
|
||||
b.ToTable("selfassignableroles", (string)null);
|
||||
b.ToTable("sargroup", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b =>
|
||||
|
@ -3527,18 +3558,6 @@ namespace EllieBot.Migrations.PostgreSql
|
|||
.HasConstraintName("fk_giveawayuser_giveawaymodel_giveawayid");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.GroupName", b =>
|
||||
{
|
||||
b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig")
|
||||
.WithMany("SelfAssignableRoleGroupNames")
|
||||
.HasForeignKey("GuildConfigId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_groupname_guildconfigs_guildconfigid");
|
||||
|
||||
b.Navigation("GuildConfig");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.IgnoredLogItem", b =>
|
||||
{
|
||||
b.HasOne("EllieBot.Db.Models.LogSetting", "LogSetting")
|
||||
|
@ -3578,6 +3597,16 @@ namespace EllieBot.Migrations.PostgreSql
|
|||
.HasConstraintName("fk_playlistsong_musicplaylists_musicplaylistid");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.Sar", b =>
|
||||
{
|
||||
b.HasOne("EllieBot.Db.Models.SarGroup", null)
|
||||
.WithMany("Roles")
|
||||
.HasForeignKey("SarGroupId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_sar_sargroup_sargroupid");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b =>
|
||||
{
|
||||
b.HasOne("EllieBot.Db.Models.GuildConfig", null)
|
||||
|
@ -3854,8 +3883,6 @@ namespace EllieBot.Migrations.PostgreSql
|
|||
|
||||
b.Navigation("Permissions");
|
||||
|
||||
b.Navigation("SelfAssignableRoleGroupNames");
|
||||
|
||||
b.Navigation("ShopEntries");
|
||||
|
||||
b.Navigation("SlowmodeIgnoredRoles");
|
||||
|
@ -3885,6 +3912,11 @@ namespace EllieBot.Migrations.PostgreSql
|
|||
b.Navigation("Songs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.SarGroup", b =>
|
||||
{
|
||||
b.Navigation("Roles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
|
|
|
@ -11,8 +11,6 @@ namespace EllieBot.Migrations
|
|||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
MigrationQueries.UpdateUsernames(migrationBuilder);
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Discriminator",
|
||||
table: "DiscordUser");
|
||||
|
|
3048
src/EllieBot/Migrations/Sqlite/20241127092212_sar-rework.Designer.cs
generated
Normal file
3048
src/EllieBot/Migrations/Sqlite/20241127092212_sar-rework.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
152
src/EllieBot/Migrations/Sqlite/20241127092212_sar-rework.cs
Normal file
152
src/EllieBot/Migrations/Sqlite/20241127092212_sar-rework.cs
Normal file
|
@ -0,0 +1,152 @@
|
|||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace EllieBot.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class sarrework : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "GroupName");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "SelfAssignableRoles");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "SarAutoDelete",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
GuildId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||
IsEnabled = table.Column<bool>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_SarAutoDelete", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "SarGroup",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
GroupNumber = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
GuildId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||
RoleReq = table.Column<ulong>(type: "INTEGER", nullable: true),
|
||||
IsExclusive = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||
Name = table.Column<string>(type: "TEXT", maxLength: 100, nullable: true),
|
||||
DateAdded = table.Column<DateTime>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_SarGroup", x => x.Id);
|
||||
table.UniqueConstraint("AK_SarGroup_GuildId_GroupNumber", x => new { x.GuildId, x.GroupNumber });
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Sar",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
GuildId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||
RoleId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||
SarGroupId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
LevelReq = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Sar", x => x.Id);
|
||||
table.UniqueConstraint("AK_Sar_GuildId_RoleId", x => new { x.GuildId, x.RoleId });
|
||||
table.ForeignKey(
|
||||
name: "FK_Sar_SarGroup_SarGroupId",
|
||||
column: x => x.SarGroupId,
|
||||
principalTable: "SarGroup",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Sar_SarGroupId",
|
||||
table: "Sar",
|
||||
column: "SarGroupId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_SarAutoDelete_GuildId",
|
||||
table: "SarAutoDelete",
|
||||
column: "GuildId",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Sar");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "SarAutoDelete");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "SarGroup");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "GroupName",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
GuildConfigId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
DateAdded = table.Column<DateTime>(type: "TEXT", nullable: true),
|
||||
Name = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Number = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_GroupName", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_GroupName_GuildConfigs_GuildConfigId",
|
||||
column: x => x.GuildConfigId,
|
||||
principalTable: "GuildConfigs",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "SelfAssignableRoles",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
DateAdded = table.Column<DateTime>(type: "TEXT", nullable: true),
|
||||
Group = table.Column<int>(type: "INTEGER", nullable: false, defaultValue: 0),
|
||||
GuildId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||
LevelRequirement = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
RoleId = table.Column<ulong>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_SelfAssignableRoles", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_GroupName_GuildConfigId_Number",
|
||||
table: "GroupName",
|
||||
columns: new[] { "GuildConfigId", "Number" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_SelfAssignableRoles_GuildId_RoleId",
|
||||
table: "SelfAssignableRoles",
|
||||
columns: new[] { "GuildId", "RoleId" },
|
||||
unique: true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -932,32 +932,6 @@ namespace EllieBot.Migrations
|
|||
b.ToTable("GiveawayUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.GroupName", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime?>("DateAdded")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("GuildConfigId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Number")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GuildConfigId", "Number")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("GroupName");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.GuildConfig", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
@ -1640,7 +1614,54 @@ namespace EllieBot.Migrations
|
|||
b.ToTable("RotatingStatus");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.SelfAssignedRole", b =>
|
||||
modelBuilder.Entity("EllieBot.Db.Models.Sar", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<ulong>("GuildId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("LevelReq")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<ulong>("RoleId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("SarGroupId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasAlternateKey("GuildId", "RoleId");
|
||||
|
||||
b.HasIndex("SarGroupId");
|
||||
|
||||
b.ToTable("Sar");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.SarAutoDelete", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<ulong>("GuildId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("IsEnabled")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GuildId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("SarAutoDelete");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.SarGroup", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
|
@ -1649,26 +1670,27 @@ namespace EllieBot.Migrations
|
|||
b.Property<DateTime?>("DateAdded")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Group")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasDefaultValue(0);
|
||||
b.Property<int>("GroupNumber")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<ulong>("GuildId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("LevelRequirement")
|
||||
b.Property<bool>("IsExclusive")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<ulong>("RoleId")
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<ulong?>("RoleReq")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GuildId", "RoleId")
|
||||
.IsUnique();
|
||||
b.HasAlternateKey("GuildId", "GroupNumber");
|
||||
|
||||
b.ToTable("SelfAssignableRoles");
|
||||
b.ToTable("SarGroup");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b =>
|
||||
|
@ -2660,17 +2682,6 @@ namespace EllieBot.Migrations
|
|||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.GroupName", b =>
|
||||
{
|
||||
b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig")
|
||||
.WithMany("SelfAssignableRoleGroupNames")
|
||||
.HasForeignKey("GuildConfigId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("GuildConfig");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.IgnoredLogItem", b =>
|
||||
{
|
||||
b.HasOne("EllieBot.Db.Models.LogSetting", "LogSetting")
|
||||
|
@ -2706,6 +2717,15 @@ namespace EllieBot.Migrations
|
|||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.Sar", b =>
|
||||
{
|
||||
b.HasOne("EllieBot.Db.Models.SarGroup", null)
|
||||
.WithMany("Roles")
|
||||
.HasForeignKey("SarGroupId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b =>
|
||||
{
|
||||
b.HasOne("EllieBot.Db.Models.GuildConfig", null)
|
||||
|
@ -2960,8 +2980,6 @@ namespace EllieBot.Migrations
|
|||
|
||||
b.Navigation("Permissions");
|
||||
|
||||
b.Navigation("SelfAssignableRoleGroupNames");
|
||||
|
||||
b.Navigation("ShopEntries");
|
||||
|
||||
b.Navigation("SlowmodeIgnoredRoles");
|
||||
|
@ -2991,6 +3009,11 @@ namespace EllieBot.Migrations
|
|||
b.Navigation("Songs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.SarGroup", b =>
|
||||
{
|
||||
b.Navigation("Roles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
|
|
|
@ -75,7 +75,7 @@ public sealed class CleanupService : ICleanupService, IReadyExecutor, IEService
|
|||
Log.Information("Leaving {RemainingCount} guilds, 1 every second. {DontDeleteCount} will remain",
|
||||
allGuildIds.Length - dontDelete.Count,
|
||||
dontDelete.Count);
|
||||
|
||||
|
||||
foreach (var guildId in allGuildIds)
|
||||
{
|
||||
if (dontDelete.Contains(guildId))
|
||||
|
@ -136,7 +136,7 @@ public sealed class CleanupService : ICleanupService, IReadyExecutor, IEService
|
|||
await using var linqCtx = ctx.CreateLinqToDBContext();
|
||||
await using var tempTable = linqCtx.CreateTempTable<CleanupId>();
|
||||
|
||||
foreach (var chunk in allIds.Chunk(20000))
|
||||
foreach (var chunk in allIds.Chunk(10000))
|
||||
{
|
||||
await tempTable.BulkCopyAsync(chunk.Select(x => new CleanupId()
|
||||
{
|
||||
|
@ -187,13 +187,6 @@ public sealed class CleanupService : ICleanupService, IReadyExecutor, IEService
|
|||
.Contains(x.GuildId))
|
||||
.DeleteAsync();
|
||||
|
||||
// delete ignored users
|
||||
await ctx.GetTable<DiscordPermOverride>()
|
||||
.Where(x => x.GuildId != null
|
||||
&& !tempTable.Select(x => x.GuildId)
|
||||
.Contains(x.GuildId.Value))
|
||||
.DeleteAsync();
|
||||
|
||||
// delete perm overrides
|
||||
await ctx.GetTable<DiscordPermOverride>()
|
||||
.Where(x => x.GuildId != null
|
||||
|
@ -219,6 +212,48 @@ public sealed class CleanupService : ICleanupService, IReadyExecutor, IEService
|
|||
.Contains(x.GuildId))
|
||||
.DeleteAsync();
|
||||
|
||||
// delete sar
|
||||
await ctx.GetTable<SarGroup>()
|
||||
.Where(x => !tempTable.Select(x => x.GuildId)
|
||||
.Contains(x.GuildId))
|
||||
.DeleteAsync();
|
||||
|
||||
// delete warnings
|
||||
await ctx.GetTable<Warning>()
|
||||
.Where(x => !tempTable.Select(x => x.GuildId)
|
||||
.Contains(x.GuildId))
|
||||
.DeleteAsync();
|
||||
|
||||
// delete warn punishments
|
||||
await ctx.GetTable<WarningPunishment>()
|
||||
.Where(x => !tempTable.Select(x => x.GuildId)
|
||||
.Contains(x.GuildId))
|
||||
.DeleteAsync();
|
||||
|
||||
// delete sticky roles
|
||||
await ctx.GetTable<StickyRole>()
|
||||
.Where(x => !tempTable.Select(x => x.GuildId)
|
||||
.Contains(x.GuildId))
|
||||
.DeleteAsync();
|
||||
|
||||
// delete at channels
|
||||
await ctx.GetTable<AutoTranslateChannel>()
|
||||
.Where(x => !tempTable.Select(x => x.GuildId)
|
||||
.Contains(x.GuildId))
|
||||
.DeleteAsync();
|
||||
|
||||
// delete ban templates
|
||||
await ctx.GetTable<BanTemplate>()
|
||||
.Where(x => !tempTable.Select(x => x.GuildId)
|
||||
.Contains(x.GuildId))
|
||||
.DeleteAsync();
|
||||
|
||||
// delete reminders
|
||||
await ctx.GetTable<Reminder>()
|
||||
.Where(x => !tempTable.Select(x => x.GuildId)
|
||||
.Contains(x.ServerId))
|
||||
.DeleteAsync();
|
||||
|
||||
return new()
|
||||
{
|
||||
GuildCount = guildIds.Keys.Count,
|
||||
|
|
|
@ -6,16 +6,155 @@ namespace EllieBot.Modules.Administration;
|
|||
|
||||
public partial class Administration
|
||||
{
|
||||
[Group]
|
||||
public partial class SelfAssignedRolesHelpers : EllieModule<SelfAssignedRolesService>
|
||||
{
|
||||
private readonly SarAssignerService _sas;
|
||||
|
||||
public SelfAssignedRolesHelpers(SarAssignerService sas)
|
||||
{
|
||||
_sas = sas;
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Iam([Leftover] IRole role)
|
||||
{
|
||||
var guildUser = (IGuildUser)ctx.User;
|
||||
|
||||
var group = await _service.GetRoleGroup(ctx.User.Id, role.Id);
|
||||
|
||||
IUserMessage msg = null;
|
||||
try
|
||||
{
|
||||
if (group is null)
|
||||
{
|
||||
msg = await Response().Error(strs.self_assign_not).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
var tcs = new TaskCompletionSource<SarAssignResult>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
await _sas.Add(new()
|
||||
{
|
||||
Group = group,
|
||||
RoleId = role.Id,
|
||||
User = guildUser,
|
||||
CompletionTask = tcs
|
||||
});
|
||||
|
||||
var res = await tcs.Task;
|
||||
|
||||
if (res.TryPickT0(out _, out var error))
|
||||
{
|
||||
msg = await Response()
|
||||
.Confirm(strs.self_assign_success(Format.Bold(role.Name)))
|
||||
.SendAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
var resStr = error.Match(
|
||||
_ => strs.error_occured,
|
||||
lvlReq => strs.self_assign_not_level(Format.Bold(lvlReq.Level.ToString())),
|
||||
roleRq => strs.self_assign_role_req(Format.Bold(ctx.Guild.GetRole(roleRq.RoleId).ToString()
|
||||
?? "missing role " + roleRq.RoleId),
|
||||
group.Name),
|
||||
_ => strs.self_assign_already(Format.Bold(role.Name)),
|
||||
_ => strs.self_assign_perms);
|
||||
|
||||
msg = await Response().Error(resStr).SendAsync();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
var ad = _service.GetAutoDelete(ctx.Guild.Id);
|
||||
|
||||
if (ad)
|
||||
{
|
||||
msg?.DeleteAfter(3);
|
||||
ctx.Message.DeleteAfter(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Iamnot([Leftover] IRole role)
|
||||
{
|
||||
var guildUser = (IGuildUser)ctx.User;
|
||||
|
||||
IUserMessage msg = null;
|
||||
try
|
||||
{
|
||||
if (guildUser.RoleIds.Contains(role.Id))
|
||||
{
|
||||
msg = await Response().Error(strs.self_assign_not_have(Format.Bold(role.Name))).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
var group = await _service.GetRoleGroup(role.Guild.Id, role.Id);
|
||||
|
||||
if (group is null || group.Roles.All(x => x.RoleId != role.Id))
|
||||
{
|
||||
msg = await Response().Error(strs.self_assign_not).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
if (role.Position >= ((SocketGuild)ctx.Guild).CurrentUser.Roles.Max(x => x.Position))
|
||||
{
|
||||
msg = await Response().Error(strs.self_assign_perms).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
await guildUser.RemoveRoleAsync(role);
|
||||
msg = await Response().Confirm(strs.self_assign_remove(Format.Bold(role.Name))).SendAsync();
|
||||
}
|
||||
finally
|
||||
{
|
||||
var ad = _service.GetAutoDelete(ctx.Guild.Id);
|
||||
if (ad)
|
||||
{
|
||||
msg?.DeleteAfter(3);
|
||||
ctx.Message.DeleteAfter(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Group("sar")]
|
||||
public partial class SelfAssignedRolesCommands : EllieModule<SelfAssignedRolesService>
|
||||
{
|
||||
private readonly SarAssignerService _sas;
|
||||
|
||||
public SelfAssignedRolesCommands(SarAssignerService sas)
|
||||
{
|
||||
_sas = sas;
|
||||
}
|
||||
|
||||
protected async Task<bool> CheckRoleHierarchy(IRole role)
|
||||
{
|
||||
var botUser = ((SocketGuild)ctx.Guild).CurrentUser;
|
||||
var ownerId = ctx.Guild.OwnerId;
|
||||
var modMaxRole = ((IGuildUser)ctx.User).GetRoles().Max(r => r.Position);
|
||||
var botMaxRole = botUser.GetRoles().Max(r => r.Position);
|
||||
|
||||
// role must be lower than the bot role
|
||||
// and the mod must have a higher role
|
||||
if (botMaxRole <= role.Position
|
||||
|| (ctx.User.Id != ownerId && role.Position >= modMaxRole))
|
||||
{
|
||||
await Response().Error(strs.hierarchy).SendAsync();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageMessages)]
|
||||
[BotPerm(GuildPerm.ManageMessages)]
|
||||
public async Task AdSarm()
|
||||
public async Task SarAutoDelete()
|
||||
{
|
||||
var newVal = _service.ToggleAdSarm(ctx.Guild.Id);
|
||||
var newVal = await _service.ToggleAutoDelete(ctx.Guild.Id);
|
||||
|
||||
if (newVal)
|
||||
await Response().Confirm(strs.adsarm_enable(prefix)).SendAsync();
|
||||
|
@ -28,30 +167,24 @@ public partial class Administration
|
|||
[UserPerm(GuildPerm.ManageRoles)]
|
||||
[BotPerm(GuildPerm.ManageRoles)]
|
||||
[Priority(1)]
|
||||
public Task Asar([Leftover] IRole role)
|
||||
=> Asar(0, role);
|
||||
public Task SarAdd([Leftover] IRole role)
|
||||
=> SarAdd(0, role);
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageRoles)]
|
||||
[BotPerm(GuildPerm.ManageRoles)]
|
||||
[Priority(0)]
|
||||
public async Task Asar(int group, [Leftover] IRole role)
|
||||
public async Task SarAdd(int group, [Leftover] IRole role)
|
||||
{
|
||||
var guser = (IGuildUser)ctx.User;
|
||||
if (ctx.User.Id != guser.Guild.OwnerId && guser.GetRoles().Max(x => x.Position) <= role.Position)
|
||||
if (!await CheckRoleHierarchy(role))
|
||||
return;
|
||||
|
||||
var succ = _service.AddNew(ctx.Guild.Id, role, group);
|
||||
await _service.AddAsync(ctx.Guild.Id, role.Id, group);
|
||||
|
||||
if (succ)
|
||||
{
|
||||
await Response()
|
||||
.Confirm(strs.role_added(Format.Bold(role.Name), Format.Bold(group.ToString())))
|
||||
.SendAsync();
|
||||
}
|
||||
else
|
||||
await Response().Error(strs.role_in_list(Format.Bold(role.Name))).SendAsync();
|
||||
await Response()
|
||||
.Confirm(strs.role_added(Format.Bold(role.Name), Format.Bold(group.ToString())))
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
|
@ -59,9 +192,9 @@ public partial class Administration
|
|||
[UserPerm(GuildPerm.ManageRoles)]
|
||||
[BotPerm(GuildPerm.ManageRoles)]
|
||||
[Priority(0)]
|
||||
public async Task Sargn(int group, [Leftover] string name = null)
|
||||
public async Task SarGroupName(int group, [Leftover] string name = null)
|
||||
{
|
||||
var set = await _service.SetNameAsync(ctx.Guild.Id, group, name);
|
||||
var set = await _service.SetGroupNameAsync(ctx.Guild.Id, group, name);
|
||||
|
||||
if (set)
|
||||
{
|
||||
|
@ -70,19 +203,19 @@ public partial class Administration
|
|||
.SendAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
await Response().Confirm(strs.group_name_removed(Format.Bold(group.ToString()))).SendAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageRoles)]
|
||||
public async Task Rsar([Leftover] IRole role)
|
||||
public async Task SarRemove([Leftover] IRole role)
|
||||
{
|
||||
var guser = (IGuildUser)ctx.User;
|
||||
if (ctx.User.Id != guser.Guild.OwnerId && guser.GetRoles().Max(x => x.Position) <= role.Position)
|
||||
return;
|
||||
|
||||
var success = _service.RemoveSar(role.Guild.Id, role.Id);
|
||||
var success = await _service.RemoveAsync(role.Guild.Id, role.Id);
|
||||
if (!success)
|
||||
await Response().Error(strs.self_assign_not).SendAsync();
|
||||
else
|
||||
|
@ -91,59 +224,81 @@ public partial class Administration
|
|||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Lsar(int page = 1)
|
||||
public async Task SarList(int page = 1)
|
||||
{
|
||||
if (--page < 0)
|
||||
return;
|
||||
|
||||
var (exclusive, roles, groups) = _service.GetRoles(ctx.Guild);
|
||||
var groups = await _service.GetSarsAsync(ctx.Guild.Id);
|
||||
|
||||
var gDict = groups.ToDictionary(x => x.Id, x => x);
|
||||
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(roles.OrderBy(x => x.Model.Group).ToList())
|
||||
.Items(groups.SelectMany(x => x.Roles).ToList())
|
||||
.PageSize(20)
|
||||
.CurrentPage(page)
|
||||
.Page((items, _) =>
|
||||
.Page(async (items, _) =>
|
||||
{
|
||||
var rolesStr = new StringBuilder();
|
||||
var roleGroups = items
|
||||
.GroupBy(x => x.Model.Group)
|
||||
.GroupBy(x => x.SarGroupId)
|
||||
.OrderBy(x => x.Key);
|
||||
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.self_assign_list(groups.Sum(x => x.Roles.Count))));
|
||||
|
||||
foreach (var kvp in roleGroups)
|
||||
{
|
||||
string groupNameText;
|
||||
if (!groups.TryGetValue(kvp.Key, out var name))
|
||||
groupNameText = Format.Bold(GetText(strs.self_assign_group(kvp.Key)));
|
||||
else
|
||||
groupNameText = Format.Bold($"{kvp.Key} - {name.TrimTo(25, true)}");
|
||||
var group = gDict[kvp.Key];
|
||||
|
||||
rolesStr.AppendLine("\t\t\t\t ⟪" + groupNameText + "⟫");
|
||||
foreach (var (model, role) in kvp.AsEnumerable())
|
||||
var groupNameText = "";
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(group.Name))
|
||||
groupNameText += $" **{group.Name}**";
|
||||
|
||||
groupNameText = $"`{group.GroupNumber}` {groupNameText}";
|
||||
|
||||
var rolesStr = new StringBuilder();
|
||||
|
||||
if (group.IsExclusive)
|
||||
{
|
||||
if (role is null)
|
||||
rolesStr.AppendLine(Format.Italics(GetText(strs.choose_one)));
|
||||
}
|
||||
|
||||
if (group.RoleReq is ulong rrId)
|
||||
{
|
||||
var rr = ctx.Guild.GetRole(rrId);
|
||||
|
||||
if (rr is null)
|
||||
{
|
||||
await _service.SetGroupRoleReq(group.GuildId, group.GroupNumber, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// first character is invisible space
|
||||
if (model.LevelRequirement == 0)
|
||||
rolesStr.AppendLine(" " + role.Name);
|
||||
else
|
||||
rolesStr.AppendLine(" " + role.Name + $" (lvl {model.LevelRequirement}+)");
|
||||
rolesStr.AppendLine(
|
||||
Format.Italics(GetText(strs.requires_role(Format.Bold(rr.Name)))));
|
||||
}
|
||||
}
|
||||
|
||||
rolesStr.AppendLine();
|
||||
foreach (var sar in kvp)
|
||||
{
|
||||
var roleName = (ctx.Guild.GetRole(sar.RoleId)?.Name ?? (sar.RoleId + " (deleted)"));
|
||||
rolesStr.Append("- " + Format.Code(roleName));
|
||||
|
||||
if (sar.LevelReq > 0)
|
||||
{
|
||||
rolesStr.Append($" *[lvl {sar.LevelReq}+]*");
|
||||
}
|
||||
|
||||
rolesStr.AppendLine();
|
||||
}
|
||||
|
||||
|
||||
eb.AddField(groupNameText, rolesStr, false);
|
||||
}
|
||||
|
||||
return _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithTitle(Format.Bold(GetText(strs.self_assign_list(roles.Count()))))
|
||||
.WithDescription(rolesStr.ToString())
|
||||
.WithFooter(exclusive
|
||||
? GetText(strs.self_assign_are_exclusive)
|
||||
: GetText(strs.self_assign_are_not_exclusive));
|
||||
return eb;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
@ -152,9 +307,9 @@ public partial class Administration
|
|||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageRoles)]
|
||||
[BotPerm(GuildPerm.ManageRoles)]
|
||||
public async Task Togglexclsar()
|
||||
public async Task SarExclusive(int groupNumber)
|
||||
{
|
||||
var areExclusive = _service.ToggleEsar(ctx.Guild.Id);
|
||||
var areExclusive = await _service.SetGroupExclusivityAsync(ctx.Guild.Id, groupNumber);
|
||||
if (areExclusive)
|
||||
await Response().Confirm(strs.self_assign_excl).SendAsync();
|
||||
else
|
||||
|
@ -165,12 +320,12 @@ public partial class Administration
|
|||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageRoles)]
|
||||
[BotPerm(GuildPerm.ManageRoles)]
|
||||
public async Task RoleLevelReq(int level, [Leftover] IRole role)
|
||||
public async Task SarRoleLevelReq(int level, [Leftover] IRole role)
|
||||
{
|
||||
if (level < 0)
|
||||
return;
|
||||
|
||||
var succ = _service.SetLevelReq(ctx.Guild.Id, role, level);
|
||||
var succ = await _service.SetRoleLevelReq(ctx.Guild.Id, role.Id, level);
|
||||
|
||||
if (!succ)
|
||||
{
|
||||
|
@ -186,54 +341,35 @@ public partial class Administration
|
|||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Iam([Leftover] IRole role)
|
||||
[UserPerm(GuildPerm.ManageRoles)]
|
||||
[BotPerm(GuildPerm.ManageRoles)]
|
||||
public async Task SarGroupRoleReq(int groupNumber, [Leftover] IRole role)
|
||||
{
|
||||
var guildUser = (IGuildUser)ctx.User;
|
||||
var succ = await _service.SetGroupRoleReq(ctx.Guild.Id, groupNumber, role.Id);
|
||||
|
||||
var (result, autoDelete, extra) = await _service.Assign(guildUser, role);
|
||||
|
||||
IUserMessage msg;
|
||||
if (result == SelfAssignedRolesService.AssignResult.ErrNotAssignable)
|
||||
msg = await Response().Error(strs.self_assign_not).SendAsync();
|
||||
else if (result == SelfAssignedRolesService.AssignResult.ErrLvlReq)
|
||||
msg = await Response().Error(strs.self_assign_not_level(Format.Bold(extra.ToString()))).SendAsync();
|
||||
else if (result == SelfAssignedRolesService.AssignResult.ErrAlreadyHave)
|
||||
msg = await Response().Error(strs.self_assign_already(Format.Bold(role.Name))).SendAsync();
|
||||
else if (result == SelfAssignedRolesService.AssignResult.ErrNotPerms)
|
||||
msg = await Response().Error(strs.self_assign_perms).SendAsync();
|
||||
else
|
||||
msg = await Response().Confirm(strs.self_assign_success(Format.Bold(role.Name))).SendAsync();
|
||||
|
||||
if (autoDelete)
|
||||
if (!succ)
|
||||
{
|
||||
msg.DeleteAfter(3);
|
||||
ctx.Message.DeleteAfter(3);
|
||||
await Response().Error(strs.sar_group_not_found).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
await Response()
|
||||
.Confirm(strs.self_assign_group_role_req(
|
||||
Format.Bold(groupNumber.ToString()),
|
||||
Format.Bold(role.Name)))
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Iamnot([Leftover] IRole role)
|
||||
[UserPerm(GuildPerm.ManageRoles)]
|
||||
public async Task SarGroupDelete(int groupNumber)
|
||||
{
|
||||
var guildUser = (IGuildUser)ctx.User;
|
||||
|
||||
var (result, autoDelete) = await _service.Remove(guildUser, role);
|
||||
|
||||
IUserMessage msg;
|
||||
if (result == SelfAssignedRolesService.RemoveResult.ErrNotAssignable)
|
||||
msg = await Response().Error(strs.self_assign_not).SendAsync();
|
||||
else if (result == SelfAssignedRolesService.RemoveResult.ErrNotHave)
|
||||
msg = await Response().Error(strs.self_assign_not_have(Format.Bold(role.Name))).SendAsync();
|
||||
else if (result == SelfAssignedRolesService.RemoveResult.ErrNotPerms)
|
||||
msg = await Response().Error(strs.self_assign_perms).SendAsync();
|
||||
var succ = await _service.DeleteRoleGroup(ctx.Guild.Id, groupNumber);
|
||||
if (succ)
|
||||
await Response().Confirm(strs.sar_group_deleted(Format.Bold(groupNumber.ToString()))).SendAsync();
|
||||
else
|
||||
msg = await Response().Confirm(strs.self_assign_remove(Format.Bold(role.Name))).SendAsync();
|
||||
|
||||
if (autoDelete)
|
||||
{
|
||||
msg.DeleteAfter(3);
|
||||
ctx.Message.DeleteAfter(3);
|
||||
}
|
||||
await Response().Error(strs.sar_group_not_found).SendAsync();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,233 +1,327 @@
|
|||
#nullable disable
|
||||
using LinqToDB;
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using EllieBot.Common.ModuleBehaviors;
|
||||
using EllieBot.Db.Models;
|
||||
using EllieBot.Modules.Xp.Services;
|
||||
using OneOf;
|
||||
using OneOf.Types;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Threading.Channels;
|
||||
|
||||
namespace EllieBot.Modules.Administration.Services;
|
||||
|
||||
public class SelfAssignedRolesService : IEService
|
||||
public class SelfAssignedRolesService : IEService, IReadyExecutor
|
||||
{
|
||||
public enum AssignResult
|
||||
private readonly DbService _db;
|
||||
private readonly DiscordSocketClient _client;
|
||||
private readonly IBotCreds _creds;
|
||||
|
||||
private ConcurrentHashSet<ulong> _sarAds = new();
|
||||
|
||||
public SelfAssignedRolesService(DbService db, DiscordSocketClient client, IBotCreds creds)
|
||||
{
|
||||
Assigned, // successfully removed
|
||||
ErrNotAssignable, // not assignable (error)
|
||||
ErrAlreadyHave, // you already have that role (error)
|
||||
ErrNotPerms, // bot doesn't have perms (error)
|
||||
ErrLvlReq // you are not required level (error)
|
||||
_db = db;
|
||||
_client = client;
|
||||
_creds = creds;
|
||||
}
|
||||
|
||||
public enum RemoveResult
|
||||
public async Task AddAsync(ulong guildId, ulong roleId, int groupNumber)
|
||||
{
|
||||
Removed, // successfully removed
|
||||
ErrNotAssignable, // not assignable (error)
|
||||
ErrNotHave, // you don't have a role you want to remove (error)
|
||||
ErrNotPerms // bot doesn't have perms (error)
|
||||
await using var ctx = _db.GetDbContext();
|
||||
|
||||
await ctx.GetTable<SarGroup>()
|
||||
.InsertOrUpdateAsync(() => new()
|
||||
{
|
||||
GuildId = guildId,
|
||||
GroupNumber = groupNumber,
|
||||
IsExclusive = false
|
||||
},
|
||||
_ => new()
|
||||
{
|
||||
},
|
||||
() => new()
|
||||
{
|
||||
GuildId = guildId,
|
||||
GroupNumber = groupNumber
|
||||
});
|
||||
|
||||
await ctx.GetTable<Sar>()
|
||||
.InsertOrUpdateAsync(() => new()
|
||||
{
|
||||
RoleId = roleId,
|
||||
LevelReq = 0,
|
||||
GuildId = guildId,
|
||||
SarGroupId = ctx.GetTable<SarGroup>()
|
||||
.Where(x => x.GuildId == guildId && x.GroupNumber == groupNumber)
|
||||
.Select(x => x.Id)
|
||||
.First()
|
||||
},
|
||||
_ => new()
|
||||
{
|
||||
},
|
||||
() => new()
|
||||
{
|
||||
RoleId = roleId,
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<bool> RemoveAsync(ulong guildId, ulong roleId)
|
||||
{
|
||||
await using var ctx = _db.GetDbContext();
|
||||
|
||||
var deleted = await ctx.GetTable<Sar>()
|
||||
.Where(x => x.RoleId == roleId && x.GuildId == guildId)
|
||||
.DeleteAsync();
|
||||
|
||||
return deleted > 0;
|
||||
}
|
||||
|
||||
public async Task<bool> SetGroupNameAsync(ulong guildId, int groupNumber, string? name)
|
||||
{
|
||||
await using var ctx = _db.GetDbContext();
|
||||
|
||||
var changes = await ctx.GetTable<SarGroup>()
|
||||
.Where(x => x.GuildId == guildId && x.GroupNumber == groupNumber)
|
||||
.UpdateAsync(x => new()
|
||||
{
|
||||
Name = name
|
||||
});
|
||||
|
||||
return changes > 0;
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyCollection<SarGroup>> GetSarsAsync(ulong guildId)
|
||||
{
|
||||
await using var ctx = _db.GetDbContext();
|
||||
|
||||
var sgs = await ctx.GetTable<SarGroup>()
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.LoadWith(x => x.Roles)
|
||||
.ToListAsyncLinqToDB();
|
||||
|
||||
return sgs;
|
||||
}
|
||||
|
||||
public async Task<bool> SetRoleLevelReq(ulong guildId, ulong roleId, int levelReq)
|
||||
{
|
||||
await using var ctx = _db.GetDbContext();
|
||||
var changes = await ctx.GetTable<Sar>()
|
||||
.Where(x => x.GuildId == guildId && x.RoleId == roleId)
|
||||
.UpdateAsync(_ => new()
|
||||
{
|
||||
LevelReq = levelReq,
|
||||
});
|
||||
|
||||
return changes > 0;
|
||||
}
|
||||
|
||||
public async Task<bool> SetGroupRoleReq(ulong guildId, int groupNumber, ulong? roleId)
|
||||
{
|
||||
await using var ctx = _db.GetDbContext();
|
||||
var changes = await ctx.GetTable<SarGroup>()
|
||||
.Where(x => x.GuildId == guildId && x.GroupNumber == groupNumber)
|
||||
.UpdateAsync(_ => new()
|
||||
{
|
||||
RoleReq = roleId
|
||||
});
|
||||
|
||||
return changes > 0;
|
||||
}
|
||||
|
||||
public async Task<bool> SetGroupExclusivityAsync(ulong guildId, int groupNumber)
|
||||
{
|
||||
await using var ctx = _db.GetDbContext();
|
||||
var changes = await ctx.GetTable<SarGroup>()
|
||||
.Where(x => x.GuildId == guildId && x.GroupNumber == groupNumber)
|
||||
.UpdateWithOutputAsync(old => new()
|
||||
{
|
||||
IsExclusive = !old.IsExclusive
|
||||
},
|
||||
(o, n) => n.IsExclusive);
|
||||
|
||||
if (changes.Length == 0)
|
||||
{
|
||||
// todo group not found
|
||||
return false;
|
||||
}
|
||||
|
||||
return changes[0];
|
||||
}
|
||||
|
||||
public async Task<SarGroup?> GetRoleGroup(ulong guildId, ulong roleId)
|
||||
{
|
||||
await using var ctx = _db.GetDbContext();
|
||||
|
||||
var group = await ctx.GetTable<SarGroup>()
|
||||
.Where(x => x.Roles.Any(x => x.RoleId == roleId))
|
||||
.LoadWith(x => x.Roles)
|
||||
.FirstOrDefaultAsyncLinqToDB();
|
||||
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteRoleGroup(ulong guildId, int groupNumber)
|
||||
{
|
||||
await using var ctx = _db.GetDbContext();
|
||||
|
||||
var deleted = await ctx.GetTable<SarGroup>()
|
||||
.Where(x => x.GuildId == guildId && x.GroupNumber == groupNumber)
|
||||
.DeleteAsync();
|
||||
|
||||
return deleted > 0;
|
||||
}
|
||||
|
||||
public async Task<bool> ToggleAutoDelete(ulong guildId)
|
||||
{
|
||||
await using var ctx = _db.GetDbContext();
|
||||
|
||||
var delted = await ctx.GetTable<SarAutoDelete>()
|
||||
.DeleteAsync(x => x.GuildId == guildId);
|
||||
|
||||
if (delted > 0)
|
||||
{
|
||||
_sarAds.TryRemove(guildId);
|
||||
return false;
|
||||
}
|
||||
|
||||
await ctx.GetTable<SarAutoDelete>()
|
||||
.InsertOrUpdateAsync(() => new()
|
||||
{
|
||||
IsEnabled = true,
|
||||
GuildId = guildId,
|
||||
},
|
||||
(_) => new()
|
||||
{
|
||||
IsEnabled = true
|
||||
},
|
||||
() => new()
|
||||
{
|
||||
GuildId = guildId
|
||||
});
|
||||
|
||||
_sarAds.Add(guildId);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool GetAutoDelete(ulong guildId)
|
||||
=> _sarAds.Contains(guildId);
|
||||
|
||||
public async Task OnReadyAsync()
|
||||
{
|
||||
await using var uow = _db.GetDbContext();
|
||||
var guilds = await uow.GetTable<SarAutoDelete>()
|
||||
.Where(x => x.IsEnabled && Linq2DbExpressions.GuildOnShard(x.GuildId, _creds.TotalShards, _client.ShardId))
|
||||
.Select(x => x.GuildId)
|
||||
.ToListAsyncLinqToDB();
|
||||
|
||||
_sarAds = new(guilds);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class SarAssignerService : IEService, IReadyExecutor
|
||||
{
|
||||
private readonly XpService _xp;
|
||||
private readonly DbService _db;
|
||||
|
||||
public SelfAssignedRolesService(DbService db)
|
||||
=> _db = db;
|
||||
private readonly Channel<SarAssignerDataItem> _channel =
|
||||
Channel.CreateBounded<SarAssignerDataItem>(100);
|
||||
|
||||
public bool AddNew(ulong guildId, IRole role, int group)
|
||||
|
||||
public SarAssignerService(XpService xp, DbService db)
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
var roles = uow.Set<SelfAssignedRole>().GetFromGuild(guildId);
|
||||
if (roles.Any(s => s.RoleId == role.Id && s.GuildId == role.Guild.Id))
|
||||
return false;
|
||||
|
||||
uow.Set<SelfAssignedRole>().Add(new()
|
||||
{
|
||||
Group = group,
|
||||
RoleId = role.Id,
|
||||
GuildId = role.Guild.Id
|
||||
});
|
||||
uow.SaveChanges();
|
||||
return true;
|
||||
_xp = xp;
|
||||
_db = db;
|
||||
}
|
||||
|
||||
public bool ToggleAdSarm(ulong guildId)
|
||||
public async Task OnReadyAsync()
|
||||
{
|
||||
bool newval;
|
||||
using var uow = _db.GetDbContext();
|
||||
var config = uow.GuildConfigsForId(guildId, set => set);
|
||||
newval = config.AutoDeleteSelfAssignedRoleMessages = !config.AutoDeleteSelfAssignedRoleMessages;
|
||||
uow.SaveChanges();
|
||||
return newval;
|
||||
}
|
||||
|
||||
public async Task<(AssignResult Result, bool AutoDelete, object extra)> Assign(IGuildUser guildUser, IRole role)
|
||||
{
|
||||
LevelStats userLevelData;
|
||||
await using (var uow = _db.GetDbContext())
|
||||
var reader = _channel.Reader;
|
||||
while (true)
|
||||
{
|
||||
var stats = uow.GetOrCreateUserXpStats(guildUser.Guild.Id, guildUser.Id);
|
||||
userLevelData = new(stats.Xp + stats.AwardedXp);
|
||||
}
|
||||
var item = await reader.ReadAsync();
|
||||
|
||||
var (autoDelete, exclusive, roles) = GetAdAndRoles(guildUser.Guild.Id);
|
||||
|
||||
var theRoleYouWant = roles.FirstOrDefault(r => r.RoleId == role.Id);
|
||||
if (theRoleYouWant is null)
|
||||
return (AssignResult.ErrNotAssignable, autoDelete, null);
|
||||
if (theRoleYouWant.LevelRequirement > userLevelData.Level)
|
||||
return (AssignResult.ErrLvlReq, autoDelete, theRoleYouWant.LevelRequirement);
|
||||
if (guildUser.RoleIds.Contains(role.Id))
|
||||
return (AssignResult.ErrAlreadyHave, autoDelete, null);
|
||||
|
||||
var roleIds = roles.Where(x => x.Group == theRoleYouWant.Group).Select(x => x.RoleId).ToArray();
|
||||
if (exclusive)
|
||||
{
|
||||
var sameRoles = guildUser.RoleIds.Where(r => roleIds.Contains(r));
|
||||
|
||||
foreach (var roleId in sameRoles)
|
||||
try
|
||||
{
|
||||
var sameRole = guildUser.Guild.GetRole(roleId);
|
||||
if (sameRole is not null)
|
||||
var sar = item.Group.Roles.First(x => x.RoleId == item.RoleId);
|
||||
|
||||
if (item.User.RoleIds.Contains(item.RoleId))
|
||||
{
|
||||
try
|
||||
{
|
||||
await guildUser.RemoveRoleAsync(sameRole);
|
||||
await Task.Delay(300);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
item.CompletionTask.TrySetResult(new SarAlreadyHasRole());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.Group.RoleReq is { } rid)
|
||||
{
|
||||
if (!item.User.RoleIds.Contains(rid))
|
||||
{
|
||||
item.CompletionTask.TrySetResult(new SarRoleRequirement(rid));
|
||||
continue;
|
||||
}
|
||||
|
||||
// passed
|
||||
}
|
||||
|
||||
// check level requirement
|
||||
if (sar.LevelReq > 0)
|
||||
{
|
||||
await using var ctx = _db.GetDbContext();
|
||||
var xpStats = await ctx.GetTable<UserXpStats>().GetGuildUserXp(sar.GuildId, item.User.Id);
|
||||
var lvlData = new LevelStats(xpStats?.Xp ?? 0);
|
||||
|
||||
if (lvlData.Level < sar.LevelReq)
|
||||
{
|
||||
item.CompletionTask.TrySetResult(new SarLevelRequirement(sar.LevelReq));
|
||||
continue;
|
||||
}
|
||||
|
||||
// passed
|
||||
}
|
||||
|
||||
if (item.Group.IsExclusive)
|
||||
{
|
||||
var rolesToRemove = item.Group.Roles.Select(x => x.RoleId);
|
||||
await item.User.RemoveRolesAsync(rolesToRemove);
|
||||
}
|
||||
|
||||
await item.User.AddRoleAsync(item.RoleId);
|
||||
|
||||
item.CompletionTask.TrySetResult(new Success());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Unknown error ocurred in SAR runner: {Error}", ex.Message);
|
||||
item.CompletionTask.TrySetResult(new Error());
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await guildUser.AddRoleAsync(role);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (AssignResult.ErrNotPerms, autoDelete, ex);
|
||||
}
|
||||
|
||||
return (AssignResult.Assigned, autoDelete, null);
|
||||
}
|
||||
|
||||
public async Task<bool> SetNameAsync(ulong guildId, int group, string name)
|
||||
public async Task Add(SarAssignerDataItem item)
|
||||
{
|
||||
var set = false;
|
||||
await using var uow = _db.GetDbContext();
|
||||
var gc = uow.GuildConfigsForId(guildId, y => y.Include(x => x.SelfAssignableRoleGroupNames));
|
||||
var toUpdate = gc.SelfAssignableRoleGroupNames.FirstOrDefault(x => x.Number == group);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
if (toUpdate is not null)
|
||||
gc.SelfAssignableRoleGroupNames.Remove(toUpdate);
|
||||
}
|
||||
else if (toUpdate is null)
|
||||
{
|
||||
gc.SelfAssignableRoleGroupNames.Add(new()
|
||||
{
|
||||
Name = name,
|
||||
Number = group
|
||||
});
|
||||
set = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
toUpdate.Name = name;
|
||||
set = true;
|
||||
}
|
||||
|
||||
await uow.SaveChangesAsync();
|
||||
|
||||
return set;
|
||||
await _channel.Writer.WriteAsync(item);
|
||||
}
|
||||
|
||||
public async Task<(RemoveResult Result, bool AutoDelete)> Remove(IGuildUser guildUser, IRole role)
|
||||
{
|
||||
var (autoDelete, _, roles) = GetAdAndRoles(guildUser.Guild.Id);
|
||||
}
|
||||
|
||||
if (roles.FirstOrDefault(r => r.RoleId == role.Id) is null)
|
||||
return (RemoveResult.ErrNotAssignable, autoDelete);
|
||||
if (!guildUser.RoleIds.Contains(role.Id))
|
||||
return (RemoveResult.ErrNotHave, autoDelete);
|
||||
try
|
||||
{
|
||||
await guildUser.RemoveRoleAsync(role);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return (RemoveResult.ErrNotPerms, autoDelete);
|
||||
}
|
||||
public sealed class SarAssignerDataItem
|
||||
{
|
||||
public required SarGroup Group { get; init; }
|
||||
public required IGuildUser User { get; init; }
|
||||
public required ulong RoleId { get; init; }
|
||||
public required TaskCompletionSource<SarAssignResult> CompletionTask { get; init; }
|
||||
}
|
||||
|
||||
return (RemoveResult.Removed, autoDelete);
|
||||
}
|
||||
[GenerateOneOf]
|
||||
public sealed partial class SarAssignResult
|
||||
: OneOfBase<Success, Error, SarLevelRequirement, SarRoleRequirement, SarAlreadyHasRole, SarInsuffPerms>
|
||||
{
|
||||
}
|
||||
|
||||
public bool RemoveSar(ulong guildId, ulong roleId)
|
||||
{
|
||||
bool success;
|
||||
using var uow = _db.GetDbContext();
|
||||
success = uow.Set<SelfAssignedRole>().DeleteByGuildAndRoleId(guildId, roleId);
|
||||
uow.SaveChanges();
|
||||
return success;
|
||||
}
|
||||
public record class SarLevelRequirement(int Level);
|
||||
|
||||
public (bool AutoDelete, bool Exclusive, IReadOnlyCollection<SelfAssignedRole>) GetAdAndRoles(ulong guildId)
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
var gc = uow.GuildConfigsForId(guildId, set => set);
|
||||
var autoDelete = gc.AutoDeleteSelfAssignedRoleMessages;
|
||||
var exclusive = gc.ExclusiveSelfAssignedRoles;
|
||||
var roles = uow.Set<SelfAssignedRole>().GetFromGuild(guildId);
|
||||
public record class SarRoleRequirement(ulong RoleId);
|
||||
|
||||
return (autoDelete, exclusive, roles);
|
||||
}
|
||||
public record class SarAlreadyHasRole();
|
||||
|
||||
public bool SetLevelReq(ulong guildId, IRole role, int level)
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
var roles = uow.Set<SelfAssignedRole>().GetFromGuild(guildId);
|
||||
var sar = roles.FirstOrDefault(x => x.RoleId == role.Id);
|
||||
if (sar is not null)
|
||||
{
|
||||
sar.LevelRequirement = level;
|
||||
uow.SaveChanges();
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool ToggleEsar(ulong guildId)
|
||||
{
|
||||
bool areExclusive;
|
||||
using var uow = _db.GetDbContext();
|
||||
var config = uow.GuildConfigsForId(guildId, set => set);
|
||||
|
||||
areExclusive = config.ExclusiveSelfAssignedRoles = !config.ExclusiveSelfAssignedRoles;
|
||||
uow.SaveChanges();
|
||||
return areExclusive;
|
||||
}
|
||||
|
||||
public (bool Exclusive, IReadOnlyCollection<(SelfAssignedRole Model, IRole Role)> Roles, IDictionary<int, string>
|
||||
GroupNames
|
||||
) GetRoles(IGuild guild)
|
||||
{
|
||||
var exclusive = false;
|
||||
|
||||
IReadOnlyCollection<(SelfAssignedRole Model, IRole Role)> roles;
|
||||
IDictionary<int, string> groupNames;
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var gc = uow.GuildConfigsForId(guild.Id, set => set.Include(x => x.SelfAssignableRoleGroupNames));
|
||||
exclusive = gc.ExclusiveSelfAssignedRoles;
|
||||
groupNames = gc.SelfAssignableRoleGroupNames.ToDictionary(x => x.Number, x => x.Name);
|
||||
var roleModels = uow.Set<SelfAssignedRole>().GetFromGuild(guild.Id);
|
||||
roles = roleModels.Select(x => (Model: x, Role: guild.GetRole(x.RoleId)))
|
||||
.ToList();
|
||||
uow.Set<SelfAssignedRole>().RemoveRange(roles.Where(x => x.Role is null).Select(x => x.Model).ToArray());
|
||||
uow.SaveChanges();
|
||||
}
|
||||
|
||||
return (exclusive, roles.Where(x => x.Role is not null).ToList(), groupNames);
|
||||
}
|
||||
}
|
||||
public record class SarInsuffPerms();
|
|
@ -23,27 +23,6 @@ public partial class Administration
|
|||
_mute = mute;
|
||||
}
|
||||
|
||||
private async Task<bool> CheckRoleHierarchy(IGuildUser target)
|
||||
{
|
||||
var curUser = ((SocketGuild)ctx.Guild).CurrentUser;
|
||||
var ownerId = ctx.Guild.OwnerId;
|
||||
var modMaxRole = ((IGuildUser)ctx.User).GetRoles().Max(r => r.Position);
|
||||
var targetMaxRole = target.GetRoles().Max(r => r.Position);
|
||||
var botMaxRole = curUser.GetRoles().Max(r => r.Position);
|
||||
// bot can't punish a user who is higher in the hierarchy. Discord will return 403
|
||||
// moderator can be owner, in which case role hierarchy doesn't matter
|
||||
// otherwise, moderator has to have a higher role
|
||||
if (botMaxRole <= targetMaxRole
|
||||
|| (ctx.User.Id != ownerId && targetMaxRole >= modMaxRole)
|
||||
|| target.Id == ownerId)
|
||||
{
|
||||
await Response().Error(strs.hierarchy).SendAsync();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.BanMembers)]
|
||||
|
|
|
@ -6,9 +6,9 @@ namespace EllieBot.Modules.Gambling.Common.AnimalRacing;
|
|||
|
||||
public sealed class AnimalRace : IDisposable
|
||||
{
|
||||
public const double BASE_MULTIPLIER = 0.82;
|
||||
public const double BASE_MULTIPLIER = 0.87;
|
||||
public const double MAX_MULTIPLIER = 0.94;
|
||||
public const double MULTI_PER_USER = 0.01;
|
||||
public const double MULTI_PER_USER = 0.005;
|
||||
|
||||
public enum Phase
|
||||
{
|
||||
|
|
|
@ -154,16 +154,16 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||
{
|
||||
var password = _service.GeneratePassword();
|
||||
|
||||
var img = new Image<Rgba32>(70, 35);
|
||||
var img = new Image<Rgba32>(60, 30);
|
||||
|
||||
var font = _fonts.NotoSans.CreateFont(30);
|
||||
var font = _fonts.NotoSans.CreateFont(25);
|
||||
var outlinePen = new SolidPen(Color.Black, 1f);
|
||||
var strikeoutRun = new RichTextRun
|
||||
{
|
||||
Start = 0,
|
||||
End = password.GetGraphemeCount(),
|
||||
Font = font,
|
||||
StrikeoutPen = new SolidPen(Color.White, 3),
|
||||
StrikeoutPen = new SolidPen(Color.White, 4),
|
||||
TextDecorations = TextDecorations.Strikeout
|
||||
};
|
||||
// draw password on the image
|
||||
|
|
92
src/EllieBot/Modules/Gambling/Loan/LoanCommands.cs
Normal file
92
src/EllieBot/Modules/Gambling/Loan/LoanCommands.cs
Normal file
|
@ -0,0 +1,92 @@
|
|||
// namespace EllieBot.Modules.Gambling;
|
||||
// public sealed class Loan
|
||||
// {
|
||||
// public int Id { get; set; }
|
||||
// public ulong LenderId { get; set; }
|
||||
// public string LenderName { get; set; }
|
||||
// public ulong BorrowerId { get; set; }
|
||||
// public string BorrowerName { get; set; }
|
||||
// public long Amount { get; set; }
|
||||
// public decimal Interest { get; set; }
|
||||
// public DateTime DueDate { get; set; }
|
||||
// public bool Repaid { get; set; }
|
||||
// }
|
||||
//
|
||||
// public sealed class LoanService : INService
|
||||
// {
|
||||
// public async Task<IReadOnlyList<Loan>> GetLoans(ulong userId)
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// public async Task<object> RepayAsync(object loandId)
|
||||
// {
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public partial class Gambling
|
||||
// {
|
||||
// public partial class LoanCommands : EllieModule<LoanService>
|
||||
// {
|
||||
// [Cmd]
|
||||
// public async Task Loan(
|
||||
// IUser lender,
|
||||
// long amount,
|
||||
// decimal interest = 0,
|
||||
// TimeSpan dueIn = default)
|
||||
// {
|
||||
// var eb = _sender.CreateEmbed()
|
||||
// .WithOkColor()
|
||||
// .WithDescription("User 0 Requests a loan from User {1}")
|
||||
// .AddField("Amount", amount, true)
|
||||
// .AddField("Interest", (interest * 0.01m).ToString("P2"), true);
|
||||
// }
|
||||
//
|
||||
// public Task Loans()
|
||||
// => Loans(ctx.User);
|
||||
//
|
||||
// public async Task Loans([Leftover] IUser user)
|
||||
// {
|
||||
// var loans = await _service.GetLoans(user.Id);
|
||||
//
|
||||
// Response()
|
||||
// .Paginated()
|
||||
// .PageItems(loans)
|
||||
// .Page((items, page) =>
|
||||
// {
|
||||
// var eb = _sender.CreateEmbed()
|
||||
// .WithOkColor()
|
||||
// .WithDescription("Current Loans");
|
||||
//
|
||||
// foreach (var item in items)
|
||||
// {
|
||||
// eb.AddField(new kwum(item.id).ToString(),
|
||||
// $"""
|
||||
// To: {item.LenderName}
|
||||
// Amount: {}
|
||||
// """,
|
||||
// true);
|
||||
// }
|
||||
//
|
||||
// return eb;
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// [Cmd]
|
||||
// public async Task Repay(kwum loanId)
|
||||
// {
|
||||
// var res = await _service.RepayAsync(loandId);
|
||||
//
|
||||
// if (res.TryPickT0(out var _, out var err))
|
||||
// {
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// var errStr = err.Match(
|
||||
// _ => "Not enough funds",
|
||||
// _ => "Loan not found");
|
||||
//
|
||||
// await Response().Error(errStr).SendAsync();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
|
@ -5,6 +5,48 @@ using JsonSerializer = System.Text.Json.JsonSerializer;
|
|||
|
||||
namespace EllieBot.Modules.Searches.Common.StreamNotifications.Providers;
|
||||
|
||||
public sealed class YoutubeProvide : Provider
|
||||
{
|
||||
private readonly IGoogleApiService _api;
|
||||
private readonly IHttpClientFactory _httpFactory;
|
||||
|
||||
public override FollowedStream.FType Platform
|
||||
=> FollowedStream.FType.Youtube;
|
||||
|
||||
public YoutubeProvide(IGoogleApiService api, IHttpClientFactory httpFactory)
|
||||
{
|
||||
_api = api;
|
||||
_httpFactory = httpFactory;
|
||||
}
|
||||
|
||||
public override async Task<bool> IsValidUrl(string url)
|
||||
{
|
||||
await Task.Yield();
|
||||
// todo implement
|
||||
return url.Contains("youtube.com");
|
||||
}
|
||||
|
||||
public override Task<StreamData?> GetStreamDataByUrlAsync(string url)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
public override Task<StreamData?> GetStreamDataAsync(string login)
|
||||
{
|
||||
var client = _httpFactory.CreateClient();
|
||||
|
||||
client.GetAsync();
|
||||
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public override Task<IReadOnlyCollection<StreamData>> GetStreamDataAsync(List<string> usernames)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TwitchHelixProvider : Provider
|
||||
{
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
|
@ -94,9 +136,9 @@ public sealed class TwitchHelixProvider : Provider
|
|||
var loginsSet = logins.Select(x => x.ToLowerInvariant())
|
||||
.Distinct()
|
||||
.ToHashSet();
|
||||
|
||||
|
||||
var dataDict = new Dictionary<string, StreamData>();
|
||||
|
||||
|
||||
foreach (var chunk in logins.Chunk(100))
|
||||
{
|
||||
try
|
||||
|
@ -125,13 +167,13 @@ public sealed class TwitchHelixProvider : Provider
|
|||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// any item left over loginsSet is an invalid username
|
||||
foreach (var login in loginsSet)
|
||||
{
|
||||
_failingStreams.TryAdd(login, DateTime.UtcNow);
|
||||
}
|
||||
|
||||
|
||||
// only get streams for users which exist
|
||||
foreach (var chunk in dataDict.Keys.Chunk(100))
|
||||
{
|
||||
|
@ -178,7 +220,7 @@ public sealed class TwitchHelixProvider : Provider
|
|||
StreamType = FollowedStream.FType.Twitch,
|
||||
Preview = user.OfflineImageUrl
|
||||
};
|
||||
|
||||
|
||||
private StreamData FillStreamData(StreamData partial, HelixStreamsResponse.StreamData apiData)
|
||||
=> partial with
|
||||
{
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
using EllieBot.Db.Models;
|
||||
|
||||
namespace Ellie.Common;
|
||||
|
||||
public static class Extensions
|
||||
{
|
||||
public static long ToTimestamp(this in DateTime value)
|
||||
=> (value.Ticks - 621355968000000000) / 10000000;
|
||||
=> (value.Ticks 621355968000000000) / 10000000;
|
||||
}
|
|
@ -100,6 +100,27 @@ public abstract class EllieModule : ModuleBase
|
|||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task<bool> CheckRoleHierarchy(IGuildUser target)
|
||||
{
|
||||
var curUser = ((SocketGuild)ctx.Guild).CurrentUser;
|
||||
var ownerId = ctx.Guild.OwnerId;
|
||||
var modMaxRole = ((IGuildUser)ctx.User).GetRoles().Max(r => r.Position);
|
||||
var targetMaxRole = target.GetRoles().Max(r => r.Position);
|
||||
var botMaxRole = curUser.GetRoles().Max(r => r.Position);
|
||||
// bot can't punish a user who is higher in the hierarchy. Discord will return 403
|
||||
// moderator can be owner, in which case role hierarchy doesn't matter
|
||||
// otherwise, moderator has to have a higher role
|
||||
if (botMaxRole <= targetMaxRole
|
||||
|| (ctx.User.Id != ownerId && targetMaxRole >= modMaxRole)
|
||||
|| target.Id == ownerId)
|
||||
{
|
||||
await Response().Error(strs.hierarchy).SendAsync();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class EllieModule<TService> : EllieModule
|
||||
|
|
|
@ -81,17 +81,43 @@ vcrole:
|
|||
- vcrole
|
||||
vcrolerm:
|
||||
- vcrolerm
|
||||
asar:
|
||||
saradd:
|
||||
- add
|
||||
- a
|
||||
- asar
|
||||
rsar:
|
||||
sarremove:
|
||||
- remove
|
||||
- rm
|
||||
- rem
|
||||
- rsar
|
||||
lsar:
|
||||
sarlist:
|
||||
- list
|
||||
- l
|
||||
- ls
|
||||
- lsar
|
||||
sargn:
|
||||
sarautodelete:
|
||||
- ad
|
||||
- autodel
|
||||
- adsarm
|
||||
sargroupname:
|
||||
- groupname
|
||||
- gn
|
||||
- sargn
|
||||
togglexclsar:
|
||||
- togglexclsar
|
||||
sargrouprolereq:
|
||||
- grouprolereq
|
||||
- grr
|
||||
sargroupdelete:
|
||||
- groupdelete
|
||||
- gd
|
||||
- gdel
|
||||
sarexclusive:
|
||||
- exclusive
|
||||
- ex
|
||||
- excl
|
||||
- tesar
|
||||
sarrolelevelreq:
|
||||
- rolelvlreq
|
||||
- rlr
|
||||
iam:
|
||||
- iam
|
||||
iamnot:
|
||||
|
@ -772,8 +798,6 @@ voicemute:
|
|||
muterole:
|
||||
- muterole
|
||||
- setmuterole
|
||||
adsarm:
|
||||
- adsarm
|
||||
setstream:
|
||||
- setstream
|
||||
chatunmute:
|
||||
|
@ -1184,9 +1208,6 @@ timelyreset:
|
|||
crypto:
|
||||
- crypto
|
||||
- c
|
||||
rolelevelreq:
|
||||
- rolelevelreq
|
||||
- rlr
|
||||
massban:
|
||||
- massban
|
||||
masskill:
|
||||
|
|
|
@ -28,7 +28,7 @@ betRoll:
|
|||
multiplyBy: 10
|
||||
- whenAbove: 90
|
||||
multiplyBy: 4
|
||||
- whenAbove: 65
|
||||
- whenAbove: 64
|
||||
multiplyBy: 2
|
||||
# Automatic currency generation settings.
|
||||
generation:
|
||||
|
|
|
@ -323,7 +323,7 @@ vcrolerm:
|
|||
params:
|
||||
- vcId:
|
||||
desc: "The voice channel ID to remove the vcrole from."
|
||||
asar:
|
||||
saradd:
|
||||
desc: Adds a role to the list of self-assignable roles. You can also specify a group. If 'Exclusive self-assignable roles' feature is enabled (`{0}tesar`), users will be able to pick one role per group.
|
||||
ex:
|
||||
- Gamer
|
||||
|
@ -336,7 +336,7 @@ asar:
|
|||
desc: "The ID of a group that the designated role should belong to."
|
||||
role:
|
||||
desc: "The role that can be assigned by the user."
|
||||
rsar:
|
||||
sarremove:
|
||||
desc: Removes a specified role from the list of self-assignable roles.
|
||||
ex:
|
||||
- Gamer
|
||||
|
@ -345,7 +345,7 @@ rsar:
|
|||
params:
|
||||
- role:
|
||||
desc: "The role to remove from the list of self-assignable roles."
|
||||
lsar:
|
||||
sarlist:
|
||||
desc: Lists self-assignable roles. Shows 20 roles per page.
|
||||
ex:
|
||||
- ''
|
||||
|
@ -353,22 +353,53 @@ lsar:
|
|||
params:
|
||||
- page:
|
||||
desc: "The page number to show."
|
||||
sargn:
|
||||
sarautodelete:
|
||||
desc: Toggles the automatic deletion of the user's message and Nadeko's confirmations for `{0}iam` and `{0}iamn` commands.
|
||||
ex:
|
||||
- ''
|
||||
params:
|
||||
- { }
|
||||
sargroupname:
|
||||
desc: Sets a self assignable role group name. Provide no name to remove.
|
||||
ex:
|
||||
- 1 Faction
|
||||
- 2
|
||||
params:
|
||||
- group:
|
||||
desc: "The ID of the group to name."
|
||||
desc: "The group number"
|
||||
name:
|
||||
desc: "The name to assign."
|
||||
togglexclsar:
|
||||
sargroupdelete:
|
||||
desc: "Deletes a self-assignable role group"
|
||||
ex:
|
||||
- 0
|
||||
params:
|
||||
- group:
|
||||
desc: "The number of the group to delete."
|
||||
sarexclusive:
|
||||
desc: Toggles whether self-assigned roles are exclusive. While enabled, users can only have one self-assignable role per group.
|
||||
ex:
|
||||
- ''
|
||||
params:
|
||||
- { }
|
||||
sarrolelevelreq:
|
||||
desc: Set a level requirement on a self-assignable role.
|
||||
ex:
|
||||
- 5 SomeRole
|
||||
params:
|
||||
- level:
|
||||
desc: "The minimum level required for the role."
|
||||
role:
|
||||
desc: "The role that must be assigned before the user can assign this one."
|
||||
sargrouprolereq:
|
||||
desc: Set a role that users have to have in order to assign a self-assignable role from the specified group.
|
||||
ex:
|
||||
- 1 SomeRole
|
||||
params:
|
||||
- group:
|
||||
desc: "The group number."
|
||||
role:
|
||||
desc: "The role that is required."
|
||||
iam:
|
||||
desc: Adds a role to you that you choose. Role must be on the list of self-assignable roles.
|
||||
ex:
|
||||
|
@ -2464,12 +2495,6 @@ muterole:
|
|||
params:
|
||||
- role:
|
||||
desc: "The role that determines whether users are muted or not."
|
||||
adsarm:
|
||||
desc: Toggles the automatic deletion of the user's message and Ellie's confirmations for `{0}iam` and `{0}iamn` commands.
|
||||
ex:
|
||||
- ''
|
||||
params:
|
||||
- { }
|
||||
setstream:
|
||||
desc: Sets the bots stream. First parameter is the twitch link, second parameter is stream name.
|
||||
ex:
|
||||
|
@ -3356,7 +3381,7 @@ globalcommand:
|
|||
globalmodule:
|
||||
desc: Toggles whether a module can be used on any server.
|
||||
ex:
|
||||
- 'Gambling'
|
||||
- 'Gambling'
|
||||
params:
|
||||
- module:
|
||||
desc: "The type of module or configuration information being toggled."
|
||||
|
@ -3919,15 +3944,6 @@ stock:
|
|||
params:
|
||||
- query:
|
||||
desc: "The ticker symbol or company name used to retrieve the stock's information."
|
||||
rolelevelreq:
|
||||
desc: Set a level requirement on a self-assignable role.
|
||||
ex:
|
||||
- 5 SomeRole
|
||||
params:
|
||||
- level:
|
||||
desc: "The minimum level required for the role."
|
||||
role:
|
||||
desc: "The role that must be assigned before the user can assign this one."
|
||||
massban:
|
||||
desc: Bans multiple users at once. Specify a space separated list of IDs of users who you wish to ban.
|
||||
ex:
|
||||
|
@ -4676,7 +4692,7 @@ betstats:
|
|||
- '@someone lula'
|
||||
- 'bd'
|
||||
params:
|
||||
- {}
|
||||
- { }
|
||||
- user:
|
||||
desc: 'The user for who to show the betstats for.'
|
||||
- user:
|
||||
|
@ -4691,10 +4707,10 @@ rakeback:
|
|||
Rakeback is accumulated by betting (not by winning or losing).
|
||||
Default rakeback is 0.05 * house edge
|
||||
House edge is defined per game
|
||||
ex:
|
||||
ex:
|
||||
- ''
|
||||
params:
|
||||
- {}
|
||||
- { }
|
||||
snipe:
|
||||
desc: |-
|
||||
Snipe the message you replied to with this command.
|
||||
|
|
|
@ -896,9 +896,6 @@
|
|||
"rank": "Rank",
|
||||
"template_reloaded": "Xp template has been reloaded.",
|
||||
"expr_edited": "Expression Edited",
|
||||
"self_assign_are_exclusive": "You can only choose 1 role from each group.",
|
||||
"self_assign_are_not_exclusive": "You can choose any number of roles from any group.",
|
||||
"self_assign_group": "Group {0}",
|
||||
"new_reaction_event": "Add {0} reaction to this message to get {1}\n{2} left to be awarded.",
|
||||
"new_gamestatus_event": "Type the secret code in any channel to receive {1}\n{2} left to be awarded.",
|
||||
"event_duration_footer": "This event is active for up to {0} hours.",
|
||||
|
@ -947,6 +944,7 @@
|
|||
"did_you_mean": "Did you mean {0}?",
|
||||
"self_assign_level_req": "Self assignable role {0} now requires at least server level {1}.",
|
||||
"self_assign_not_level": "That self-assignable role requires at least server level {0}.",
|
||||
"self_assign_role_req": "You need {0} role in order to assign yourself a role from group {1}",
|
||||
"invalid": "Invalid / Can't be found ({0})",
|
||||
"mass_kill_in_progress": "Mass Banning and Blacklisting of {0} users is in progress...",
|
||||
"mass_ban_in_progress": "Banning {0} users...",
|
||||
|
@ -1118,5 +1116,10 @@
|
|||
"rakeback_claimed": "You've claimed {0} as rakeback!",
|
||||
"rakeback_none": "You don't have any rakeback to claim yet.",
|
||||
"rakeback_available": "You have {0} rakeback available. Click the button to claim.",
|
||||
"sniped_by": "Sniped by {0}"
|
||||
"sniped_by": "Sniped by {0}",
|
||||
"self_assign_group_role_req": "Users can now self-assign a role from group {0} only if they have {1} role.",
|
||||
"sar_group_not_found": "Group with that number doesn't exist.",
|
||||
"sar_group_deleted": "Group {0} deleted.",
|
||||
"choose_one": "Choose one",
|
||||
"requires_role": "Requires role: {0}"
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue