mirror of
https://github.com/RPCS3/discord-bot.git
synced 2025-01-19 00:52:26 +00:00
make warnings permanent, log retractions, but leave the records intact
This commit is contained in:
parent
a1f3bb3736
commit
981bc40712
@ -9,6 +9,7 @@ using CompatBot.Database.Providers;
|
||||
using CompatBot.Utils;
|
||||
using DSharpPlus.CommandsNext;
|
||||
using DSharpPlus.CommandsNext.Attributes;
|
||||
using DSharpPlus.CommandsNext.Converters;
|
||||
using DSharpPlus.Entities;
|
||||
|
||||
namespace CompatBot.Commands
|
||||
@ -45,25 +46,27 @@ namespace CompatBot.Commands
|
||||
[Description("List users with warnings, sorted from most warned to least")]
|
||||
public async Task Users(CommandContext ctx, [Description("Optional number of items to show. Default is 10")] int number = 10)
|
||||
{
|
||||
var isMod = ctx.User.IsWhitelisted(ctx.Client, ctx.Guild);
|
||||
if (number < 1)
|
||||
number = 10;
|
||||
var table = new AsciiTable(
|
||||
new AsciiColumn("Username", maxWidth: 24),
|
||||
new AsciiColumn("User ID", disabled: !ctx.Channel.IsPrivate, alignToRight: true),
|
||||
new AsciiColumn("Count", alignToRight: true)
|
||||
new AsciiColumn("Count", alignToRight: true),
|
||||
new AsciiColumn("Including removed", disabled: !ctx.Channel.IsPrivate || !isMod, alignToRight: true)
|
||||
);
|
||||
using (var db = new BotDb())
|
||||
{
|
||||
var query = from warn in db.Warning
|
||||
group warn by warn.DiscordId
|
||||
into userGroup
|
||||
let row = new {discordId = userGroup.Key, count = userGroup.Count()}
|
||||
let row = new {discordId = userGroup.Key, count = userGroup.Count(w => !w.Retracted), total = userGroup.Count()}
|
||||
orderby row.count descending
|
||||
select row;
|
||||
foreach (var row in query.Take(number))
|
||||
{
|
||||
var username = await ctx.GetUserNameAsync(row.discordId).ConfigureAwait(false);
|
||||
table.Add(username, row.discordId.ToString(), row.count.ToString());
|
||||
table.Add(username, row.discordId.ToString(), row.count.ToString(), row.total.ToString());
|
||||
}
|
||||
}
|
||||
await ctx.SendAutosplitMessageAsync(new StringBuilder("Warning count per user:").Append(table)).ConfigureAwait(false);
|
||||
@ -101,19 +104,24 @@ namespace CompatBot.Commands
|
||||
|
||||
}
|
||||
|
||||
[Command("by"), RequiresBotModRole]
|
||||
public Task By(CommandContext ctx, DiscordUser moderator, [Description("Optional number of items to show. Default is 10")] int number = 10)
|
||||
=> By(ctx, moderator.Id, number);
|
||||
|
||||
[Command("by"), RequiresBotModRole]
|
||||
public Task By(CommandContext ctx, string me, [Description("Optional number of items to show. Default is 10")] int number = 10)
|
||||
[Command("by"), Priority(1), RequiresBotModRole]
|
||||
public async Task By(CommandContext ctx, string me, [Description("Optional number of items to show. Default is 10")] int number = 10)
|
||||
{
|
||||
if (me?.ToLowerInvariant() == "me")
|
||||
return By(ctx, ctx.User.Id, number);
|
||||
{
|
||||
await By(ctx, ctx.User.Id, number).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
var user = await new DiscordUserConverter().ConvertAsync(me, ctx).ConfigureAwait(false);
|
||||
if (user.HasValue)
|
||||
await By(ctx, user.Value, number).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[Command("by"), Priority(10), RequiresBotModRole]
|
||||
public Task By(CommandContext ctx, DiscordUser moderator, [Description("Optional number of items to show. Default is 10")] int number = 10)
|
||||
=> By(ctx, moderator.Id, number);
|
||||
|
||||
[Command("recent"), Aliases("last", "all"), RequiresBotModRole]
|
||||
[Description("Shows last issued warnings in chronological order")]
|
||||
public async Task Last(CommandContext ctx, [Description("Optional number of items to show. Default is 10")] int number = 10)
|
||||
|
@ -10,6 +10,7 @@ using DSharpPlus;
|
||||
using DSharpPlus.CommandsNext;
|
||||
using DSharpPlus.CommandsNext.Attributes;
|
||||
using DSharpPlus.Entities;
|
||||
using DSharpPlus.Interactivity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace CompatBot.Commands
|
||||
@ -48,11 +49,26 @@ namespace CompatBot.Commands
|
||||
[Description("Removes specified warnings")]
|
||||
public async Task Remove(CommandContext ctx, [Description("Warning IDs to remove separated with space")] params int[] ids)
|
||||
{
|
||||
var interact = ctx.Client.GetInteractivity();
|
||||
var msg = await ctx.RespondAsync("What is the reason for removal?").ConfigureAwait(false);
|
||||
var response = await interact.WaitForMessageAsync(m => m.Author == ctx.User && m.Channel == ctx.Channel && !string.IsNullOrEmpty(m.Content)).ConfigureAwait(false);
|
||||
if (string.IsNullOrEmpty(response?.Message?.Content))
|
||||
{
|
||||
await msg.UpdateOrCreateMessageAsync(ctx.Channel, "Can't remove warnings without a reason").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
int removedCount;
|
||||
using (var db = new BotDb())
|
||||
{
|
||||
var warningsToRemove = await db.Warning.Where(w => ids.Contains(w.Id)).ToListAsync().ConfigureAwait(false);
|
||||
db.Warning.RemoveRange(warningsToRemove);
|
||||
foreach (var w in warningsToRemove)
|
||||
{
|
||||
w.Retracted = true;
|
||||
w.RetractedBy = ctx.User.Id;
|
||||
w.RetractionReason = response.Message.Content;
|
||||
w.RetractionTimestamp = DateTime.UtcNow.Ticks;
|
||||
}
|
||||
removedCount = await db.SaveChangesAsync().ConfigureAwait(false);
|
||||
}
|
||||
if (removedCount == ids.Length)
|
||||
@ -71,14 +87,28 @@ namespace CompatBot.Commands
|
||||
[Command("clear"), RequiresBotModRole]
|
||||
public async Task Clear(CommandContext ctx, [Description("User ID to clear warnings for")] ulong userId)
|
||||
{
|
||||
var interact = ctx.Client.GetInteractivity();
|
||||
var msg = await ctx.RespondAsync("What is the reason for removing all the warnings?").ConfigureAwait(false);
|
||||
var response = await interact.WaitForMessageAsync(m => m.Author == ctx.User && m.Channel == ctx.Channel && !string.IsNullOrEmpty(m.Content)).ConfigureAwait(false);
|
||||
if (string.IsNullOrEmpty(response?.Message?.Content))
|
||||
{
|
||||
await msg.UpdateOrCreateMessageAsync(ctx.Channel, "Can't remove warnings without a reason").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
//var removed = await BotDb.Instance.Database.ExecuteSqlCommandAsync($"DELETE FROM `warning` WHERE `discord_id`={userId}").ConfigureAwait(false);
|
||||
int removed;
|
||||
using (var db = new BotDb())
|
||||
{
|
||||
var warningsToRemove = await db.Warning.Where(w => w.DiscordId == userId).ToListAsync().ConfigureAwait(false);
|
||||
db.Warning.RemoveRange(warningsToRemove);
|
||||
foreach (var w in warningsToRemove)
|
||||
{
|
||||
w.Retracted = true;
|
||||
w.RetractedBy = ctx.User.Id;
|
||||
w.RetractionReason = response.Message.Content;
|
||||
w.RetractionTimestamp = DateTime.UtcNow.Ticks;
|
||||
}
|
||||
removed = await db.SaveChangesAsync().ConfigureAwait(false);
|
||||
}
|
||||
await ctx.RespondAsync($"{removed} warning{StringUtils.GetSuffix(removed)} successfully removed!").ConfigureAwait(false);
|
||||
@ -137,13 +167,27 @@ namespace CompatBot.Commands
|
||||
{
|
||||
try
|
||||
{
|
||||
var isWhitelisted = client.GetMember(message.Author)?.IsWhitelisted() ?? false;
|
||||
if (message.Author.Id != userId && !isWhitelisted)
|
||||
{
|
||||
Config.Log.Error($"Somehow {message.Author.Username} ({message.Author.Id}) triggered warning list for {userId}");
|
||||
return;
|
||||
}
|
||||
|
||||
var channel = message.Channel;
|
||||
int count;
|
||||
var isPrivate = channel.IsPrivate;
|
||||
int count, removed;
|
||||
using (var db = new BotDb())
|
||||
count = await db.Warning.CountAsync(w => w.DiscordId == userId).ConfigureAwait(false);
|
||||
{
|
||||
count = await db.Warning.CountAsync(w => w.DiscordId == userId && !w.Retracted).ConfigureAwait(false);
|
||||
removed = await db.Warning.CountAsync(w => w.DiscordId == userId && w.Retracted).ConfigureAwait(false);
|
||||
}
|
||||
if (count == 0)
|
||||
{
|
||||
await message.RespondAsync(userName + " has no warnings, is a standup citizen, and a pillar of this community").ConfigureAwait(false);
|
||||
if (removed == 0)
|
||||
await message.RespondAsync(userName + " has no warnings, is a standup citizen, and a pillar of this community").ConfigureAwait(false);
|
||||
else
|
||||
await message.RespondAsync(userName + " has no warnings" + (isPrivate ? $" ({removed} retracted warning{(removed == 1 ? "" : "s")})" : "")).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -151,15 +195,13 @@ namespace CompatBot.Commands
|
||||
return;
|
||||
|
||||
const int maxWarningsInPublicChannel = 3;
|
||||
var isPrivate = channel.IsPrivate;
|
||||
var isWhitelisted = client.GetMember(message.Author)?.IsWhitelisted() ?? false;
|
||||
using (var db = new BotDb())
|
||||
{
|
||||
var totalWarningCount = db.Warning.Count(w => w.DiscordId == userId);
|
||||
var showCount = Math.Min(maxWarningsInPublicChannel, totalWarningCount);
|
||||
var showCount = Math.Min(maxWarningsInPublicChannel, count);
|
||||
var table = new AsciiTable(
|
||||
new AsciiColumn("ID", alignToRight: true),
|
||||
new AsciiColumn("Issued by", maxWidth: 15),
|
||||
new AsciiColumn("±", disabled: !isPrivate || !isWhitelisted),
|
||||
new AsciiColumn("By", maxWidth: 15),
|
||||
new AsciiColumn("On date (UTC)"),
|
||||
new AsciiColumn("Reason"),
|
||||
new AsciiColumn("Context", disabled: !isPrivate)
|
||||
@ -169,17 +211,41 @@ namespace CompatBot.Commands
|
||||
query = query.Take(maxWarningsInPublicChannel);
|
||||
foreach (var warning in await query.ToListAsync().ConfigureAwait(false))
|
||||
{
|
||||
var issuerName = warning.IssuerId == 0
|
||||
? ""
|
||||
: await client.GetUserNameAsync(channel, warning.IssuerId, isPrivate, "unknown mod").ConfigureAwait(false);
|
||||
var timestamp = warning.Timestamp.HasValue
|
||||
? new DateTime(warning.Timestamp.Value, DateTimeKind.Utc).ToString("u")
|
||||
: null;
|
||||
table.Add(warning.Id.ToString(), issuerName, timestamp, warning.Reason, warning.FullReason);
|
||||
if (warning.Retracted)
|
||||
{
|
||||
if (isWhitelisted && isPrivate)
|
||||
{
|
||||
var retractedByName = !warning.RetractedBy.HasValue
|
||||
? ""
|
||||
: await client.GetUserNameAsync(channel, warning.RetractedBy.Value, isPrivate, "unknown mod").ConfigureAwait(false);
|
||||
var retractionTimestamp = warning.RetractionTimestamp.HasValue
|
||||
? new DateTime(warning.RetractionTimestamp.Value, DateTimeKind.Utc).ToString("u")
|
||||
: null;
|
||||
table.Add(warning.Id.ToString(), "-", retractedByName, retractionTimestamp, warning.RetractionReason, "");
|
||||
|
||||
var issuerName = warning.IssuerId == 0
|
||||
? ""
|
||||
: await client.GetUserNameAsync(channel, warning.IssuerId, isPrivate, "unknown mod").ConfigureAwait(false);
|
||||
var timestamp = warning.Timestamp.HasValue
|
||||
? new DateTime(warning.Timestamp.Value, DateTimeKind.Utc).ToString("u")
|
||||
: null;
|
||||
table.Add(warning.Id.ToString().StrikeThrough(), "+", issuerName.StrikeThrough(), timestamp.StrikeThrough(), warning.Reason.StrikeThrough(), warning.FullReason.StrikeThrough());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var issuerName = warning.IssuerId == 0
|
||||
? ""
|
||||
: await client.GetUserNameAsync(channel, warning.IssuerId, isPrivate, "unknown mod").ConfigureAwait(false);
|
||||
var timestamp = warning.Timestamp.HasValue
|
||||
? new DateTime(warning.Timestamp.Value, DateTimeKind.Utc).ToString("u")
|
||||
: null;
|
||||
table.Add(warning.Id.ToString(), "+", issuerName, timestamp, warning.Reason, warning.FullReason);
|
||||
}
|
||||
}
|
||||
var result = new StringBuilder("Warning list for ").Append(userName);
|
||||
if (!isPrivate && !isWhitelisted && totalWarningCount > maxWarningsInPublicChannel)
|
||||
result.Append($" (last {showCount} of {totalWarningCount}, full list in DMs)");
|
||||
if (!isPrivate && !isWhitelisted && count > maxWarningsInPublicChannel)
|
||||
result.Append($" (last {showCount} of {count}, full list in DMs)");
|
||||
result.AppendLine(":").Append(table);
|
||||
await channel.SendAutosplitMessageAsync(result).ConfigureAwait(false);
|
||||
}
|
||||
|
@ -76,6 +76,10 @@ namespace CompatBot.Database
|
||||
[Required]
|
||||
public string FullReason { get; set; }
|
||||
public long? Timestamp { get; set; }
|
||||
public bool Retracted { get; set; }
|
||||
public ulong? RetractedBy { get; set; }
|
||||
public string RetractionReason { get; set; }
|
||||
public long? RetractionTimestamp { get; set; }
|
||||
}
|
||||
|
||||
internal class Explanation
|
||||
|
268
CompatBot/Database/Migrations/BotDb/20190307173026_PermanentWarnings.Designer.cs
generated
Normal file
268
CompatBot/Database/Migrations/BotDb/20190307173026_PermanentWarnings.Designer.cs
generated
Normal file
@ -0,0 +1,268 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using CompatBot.Database;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
namespace CompatBot.Database.Migrations
|
||||
{
|
||||
[DbContext(typeof(BotDb))]
|
||||
[Migration("20190307173026_PermanentWarnings")]
|
||||
partial class PermanentWarnings
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.2.2-servicing-10034");
|
||||
|
||||
modelBuilder.Entity("CompatBot.Database.BotState", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("id");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.HasColumnName("key");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnName("value");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("id");
|
||||
|
||||
b.HasIndex("Key")
|
||||
.IsUnique()
|
||||
.HasName("bot_state_key");
|
||||
|
||||
b.ToTable("bot_state");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CompatBot.Database.DisabledCommand", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("id");
|
||||
|
||||
b.Property<string>("Command")
|
||||
.IsRequired()
|
||||
.HasColumnName("command");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("id");
|
||||
|
||||
b.HasIndex("Command")
|
||||
.IsUnique()
|
||||
.HasName("disabled_command_command");
|
||||
|
||||
b.ToTable("disabled_commands");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CompatBot.Database.EventSchedule", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("id");
|
||||
|
||||
b.Property<long>("End")
|
||||
.HasColumnName("end");
|
||||
|
||||
b.Property<string>("EventName")
|
||||
.HasColumnName("event_name");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.Property<long>("Start")
|
||||
.HasColumnName("start");
|
||||
|
||||
b.Property<int>("Year")
|
||||
.HasColumnName("year");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("id");
|
||||
|
||||
b.HasIndex("Year", "EventName")
|
||||
.HasName("event_schedule_year_event_name");
|
||||
|
||||
b.ToTable("event_schedule");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CompatBot.Database.Explanation", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("id");
|
||||
|
||||
b.Property<byte[]>("Attachment")
|
||||
.HasColumnName("attachment")
|
||||
.HasMaxLength(7340032);
|
||||
|
||||
b.Property<string>("AttachmentFilename")
|
||||
.HasColumnName("attachment_filename");
|
||||
|
||||
b.Property<string>("Keyword")
|
||||
.IsRequired()
|
||||
.HasColumnName("keyword");
|
||||
|
||||
b.Property<string>("Text")
|
||||
.IsRequired()
|
||||
.HasColumnName("text");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("id");
|
||||
|
||||
b.HasIndex("Keyword")
|
||||
.IsUnique()
|
||||
.HasName("explanation_keyword");
|
||||
|
||||
b.ToTable("explanation");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CompatBot.Database.Moderator", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("id");
|
||||
|
||||
b.Property<ulong>("DiscordId")
|
||||
.HasColumnName("discord_id");
|
||||
|
||||
b.Property<bool>("Sudoer")
|
||||
.HasColumnName("sudoer");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("id");
|
||||
|
||||
b.HasIndex("DiscordId")
|
||||
.IsUnique()
|
||||
.HasName("moderator_discord_id");
|
||||
|
||||
b.ToTable("moderator");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CompatBot.Database.Piracystring", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("id");
|
||||
|
||||
b.Property<string>("String")
|
||||
.IsRequired()
|
||||
.HasColumnName("string")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("id");
|
||||
|
||||
b.HasIndex("String")
|
||||
.IsUnique()
|
||||
.HasName("piracystring_string");
|
||||
|
||||
b.ToTable("piracystring");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CompatBot.Database.Stats", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("id");
|
||||
|
||||
b.Property<string>("Category")
|
||||
.IsRequired()
|
||||
.HasColumnName("category");
|
||||
|
||||
b.Property<long>("ExpirationTimestamp")
|
||||
.HasColumnName("expiration_timestamp");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasColumnName("key");
|
||||
|
||||
b.Property<int>("Value")
|
||||
.HasColumnName("value");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("id");
|
||||
|
||||
b.HasIndex("Category", "Key")
|
||||
.IsUnique()
|
||||
.HasName("stats_category_key");
|
||||
|
||||
b.ToTable("stats");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CompatBot.Database.Warning", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("id");
|
||||
|
||||
b.Property<ulong>("DiscordId")
|
||||
.HasColumnName("discord_id");
|
||||
|
||||
b.Property<string>("FullReason")
|
||||
.IsRequired()
|
||||
.HasColumnName("full_reason");
|
||||
|
||||
b.Property<ulong>("IssuerId")
|
||||
.HasColumnName("issuer_id");
|
||||
|
||||
b.Property<string>("Reason")
|
||||
.IsRequired()
|
||||
.HasColumnName("reason");
|
||||
|
||||
b.Property<bool>("Retracted")
|
||||
.HasColumnName("retracted");
|
||||
|
||||
b.Property<ulong?>("RetractedBy")
|
||||
.HasColumnName("retracted_by");
|
||||
|
||||
b.Property<string>("RetractionReason")
|
||||
.HasColumnName("retraction_reason");
|
||||
|
||||
b.Property<long?>("RetractionTimestamp")
|
||||
.HasColumnName("retraction_timestamp");
|
||||
|
||||
b.Property<long?>("Timestamp")
|
||||
.HasColumnName("timestamp");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("id");
|
||||
|
||||
b.HasIndex("DiscordId")
|
||||
.HasName("warning_discord_id");
|
||||
|
||||
b.ToTable("warning");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("CompatBot.Database.WhitelistedInvite", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnName("id");
|
||||
|
||||
b.Property<ulong>("GuildId")
|
||||
.HasColumnName("guild_id");
|
||||
|
||||
b.Property<string>("InviteCode")
|
||||
.HasColumnName("invite_code");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("id");
|
||||
|
||||
b.HasIndex("GuildId")
|
||||
.IsUnique()
|
||||
.HasName("whitelisted_invite_guild_id");
|
||||
|
||||
b.ToTable("whitelisted_invites");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace CompatBot.Database.Migrations
|
||||
{
|
||||
public partial class PermanentWarnings : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "retracted",
|
||||
table: "warning",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<ulong>(
|
||||
name: "retracted_by",
|
||||
table: "warning",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "retraction_reason",
|
||||
table: "warning",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<long>(
|
||||
name: "retraction_timestamp",
|
||||
table: "warning",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "retracted",
|
||||
table: "warning");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "retracted_by",
|
||||
table: "warning");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "retraction_reason",
|
||||
table: "warning");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "retraction_timestamp",
|
||||
table: "warning");
|
||||
}
|
||||
}
|
||||
}
|
@ -212,6 +212,18 @@ namespace CompatBot.Database.Migrations
|
||||
.IsRequired()
|
||||
.HasColumnName("reason");
|
||||
|
||||
b.Property<bool>("Retracted")
|
||||
.HasColumnName("retracted");
|
||||
|
||||
b.Property<ulong?>("RetractedBy")
|
||||
.HasColumnName("retracted_by");
|
||||
|
||||
b.Property<string>("RetractionReason")
|
||||
.HasColumnName("retraction_reason");
|
||||
|
||||
b.Property<long?>("RetractionTimestamp")
|
||||
.HasColumnName("retraction_timestamp");
|
||||
|
||||
b.Property<long?>("Timestamp")
|
||||
.HasColumnName("timestamp");
|
||||
|
||||
|
@ -18,6 +18,7 @@ namespace CompatBot.Utils
|
||||
?? Encoding.ASCII;
|
||||
private static readonly Encoding Utf8 = new UTF8Encoding(false);
|
||||
private static readonly MemoryCache FuzzyPairCache = new MemoryCache(new MemoryCacheOptions {ExpirationScanFrequency = TimeSpan.FromMinutes(10)});
|
||||
private const char StrikeThroughChar = '\u0336'; // 0x0335 = short dash, 0x0336 = long dash, 0x0337 = short slash, 0x0338 = long slash
|
||||
|
||||
private static readonly HashSet<char> SpaceCharacters = new HashSet<char>
|
||||
{
|
||||
@ -118,7 +119,7 @@ namespace CompatBot.Utils
|
||||
while (e.MoveNext())
|
||||
{
|
||||
var strEl = e.GetTextElement();
|
||||
if (char.IsControl(strEl[0]) || char.GetUnicodeCategory(strEl[0]) == UnicodeCategory.Format)
|
||||
if (char.IsControl(strEl[0]) || char.GetUnicodeCategory(strEl[0]) == UnicodeCategory.Format || strEl[0] == StrikeThroughChar)
|
||||
continue;
|
||||
|
||||
c++;
|
||||
@ -144,7 +145,7 @@ namespace CompatBot.Utils
|
||||
{
|
||||
var strEl = e.GetTextElement();
|
||||
result.Append(strEl);
|
||||
if (char.IsControl(strEl[0]) || char.GetUnicodeCategory(strEl[0]) == UnicodeCategory.Format)
|
||||
if (char.IsControl(strEl[0]) || char.GetUnicodeCategory(strEl[0]) == UnicodeCategory.Format || strEl[0] == StrikeThroughChar)
|
||||
continue;
|
||||
|
||||
c++;
|
||||
@ -170,6 +171,22 @@ namespace CompatBot.Utils
|
||||
return s.PadRight(totalWidth, padding);
|
||||
}
|
||||
|
||||
public static string StrikeThrough(this string str)
|
||||
{
|
||||
if (string.IsNullOrEmpty(str))
|
||||
return str;
|
||||
|
||||
var result = new StringBuilder(str.Length*2);
|
||||
result.Append(StrikeThroughChar);
|
||||
foreach (var c in str)
|
||||
{
|
||||
result.Append(c);
|
||||
if (char.IsLetterOrDigit(c) || char.IsLowSurrogate(c))
|
||||
result.Append(StrikeThroughChar);
|
||||
}
|
||||
return result.ToString(0, result.Length-1);
|
||||
}
|
||||
|
||||
public static string GetMoons(decimal? stars)
|
||||
{
|
||||
if (!stars.HasValue)
|
||||
|
Loading…
x
Reference in New Issue
Block a user