1
0
Fork 1
mirror of https://github.com/TeamOctolings/Octobot.git synced 2025-04-20 00:43:36 +03:00

Add /kick command

This commit is contained in:
Macintxsh 2023-06-11 17:37:46 +03:00
parent 2ee30ddfb8
commit 6bee9ac0fc
WARNING! Although there is a key with this ID in the database it does not verify this commit! This commit is SUSPICIOUS.
GPG key ID: 57156EBA2C282D9A
7 changed files with 1475 additions and 835 deletions

View file

@ -76,7 +76,8 @@ public class Boyfriend {
.AddSingleton<UtilityService>() .AddSingleton<UtilityService>()
.AddHostedService<GuildUpdateService>() .AddHostedService<GuildUpdateService>()
.AddCommandTree() .AddCommandTree()
.WithCommandGroup<BanCommandGroup>(); .WithCommandGroup<BanCommandGroup>()
.WithCommandGroup<KickCommandGroup>();
var responderTypes = typeof(Boyfriend).Assembly var responderTypes = typeof(Boyfriend).Assembly
.GetExportedTypes() .GetExportedTypes()
.Where(t => t.IsResponder()); .Where(t => t.IsResponder());

View file

@ -56,14 +56,14 @@ public class BanCommandGroup : CommandGroup {
/// A feedback sending result which may or may not have succeeded. A successful result does not mean that the user /// A feedback sending result which may or may not have succeeded. A successful result does not mean that the user
/// was banned and vice-versa. /// was banned and vice-versa.
/// </returns> /// </returns>
/// <seealso cref="UnBanUserAsync" /> /// <seealso cref="UnbanUserAsync" />
[Command("ban", "бан")] [Command("ban", "бан")]
[RequireContext(ChannelContext.Guild)] [RequireContext(ChannelContext.Guild)]
[RequireDiscordPermission(DiscordPermission.BanMembers)] [RequireDiscordPermission(DiscordPermission.BanMembers)]
[RequireBotDiscordPermissions(DiscordPermission.BanMembers)] [RequireBotDiscordPermissions(DiscordPermission.BanMembers)]
[Description("банит пидора")] [Description("банит пидора")]
public async Task<Result> BanUserAsync( public async Task<Result> BanUserAsync(
[Description("Юзер, кого банить")] IUser target, string reason, TimeSpan? duration = null) { [Description("юзер кого банить")] IUser target, [Description("причина зачем банить")] string reason, TimeSpan? duration = null) {
// Data checks // Data checks
if (!_context.TryGetGuildID(out var guildId)) if (!_context.TryGetGuildID(out var guildId))
return Result.FromError(new ArgumentNullError(nameof(guildId))); return Result.FromError(new ArgumentNullError(nameof(guildId)));
@ -122,7 +122,7 @@ public class BanCommandGroup : CommandGroup {
|| (cfg.PrivateFeedbackChannel is not 0 && cfg.PrivateFeedbackChannel != channelId.Value)) { || (cfg.PrivateFeedbackChannel is not 0 && cfg.PrivateFeedbackChannel != channelId.Value)) {
var logEmbed = new EmbedBuilder().WithSmallTitle( var logEmbed = new EmbedBuilder().WithSmallTitle(
string.Format(Messages.UserBanned, target.GetTag()), target) string.Format(Messages.UserBanned, target.GetTag()), target)
.WithDescription(string.Format(Messages.DescriptionUserBanned, reason)) .WithDescription(string.Format(Messages.DescriptionUserPunished, reason))
.WithActionFooter(user) .WithActionFooter(user)
.WithCurrentTimestamp() .WithCurrentTimestamp()
.WithColour(ColorsList.Red) .WithColour(ColorsList.Red)
@ -169,7 +169,7 @@ public class BanCommandGroup : CommandGroup {
[RequireDiscordPermission(DiscordPermission.BanMembers)] [RequireDiscordPermission(DiscordPermission.BanMembers)]
[RequireBotDiscordPermissions(DiscordPermission.BanMembers)] [RequireBotDiscordPermissions(DiscordPermission.BanMembers)]
[Description("разбанит пидора")] [Description("разбанит пидора")]
public async Task<Result> UnBanUserAsync([Description("Юзер, кого разбанить")] IUser target, string reason) { public async Task<Result> UnbanUserAsync([Description("Юзер, кого разбанить")] IUser target, string reason) {
// Data checks // Data checks
if (!_context.TryGetGuildID(out var guildId)) if (!_context.TryGetGuildID(out var guildId))
return Result.FromError(new ArgumentNullError(nameof(guildId))); return Result.FromError(new ArgumentNullError(nameof(guildId)));

View file

@ -0,0 +1,145 @@
using System.ComponentModel;
using Boyfriend.Services;
using Boyfriend.Services.Data;
using Remora.Commands.Attributes;
using Remora.Commands.Groups;
using Remora.Discord.API.Abstractions.Objects;
using Remora.Discord.API.Abstractions.Rest;
using Remora.Discord.API.Objects;
using Remora.Discord.Commands.Conditions;
using Remora.Discord.Commands.Contexts;
using Remora.Discord.Commands.Extensions;
using Remora.Discord.Commands.Feedback.Services;
using Remora.Discord.Extensions.Embeds;
using Remora.Results;
// ReSharper disable ClassNeverInstantiated.Global
// ReSharper disable UnusedMember.Global
namespace Boyfriend.Commands;
public class KickCommandGroup : CommandGroup {
private readonly IDiscordRestChannelAPI _channelApi;
private readonly ICommandContext _context;
private readonly GuildDataService _dataService;
private readonly FeedbackService _feedbackService;
private readonly IDiscordRestGuildAPI _guildApi;
private readonly IDiscordRestUserAPI _userApi;
private readonly UtilityService _utility;
public KickCommandGroup(
ICommandContext context, IDiscordRestChannelAPI channelApi, GuildDataService dataService,
FeedbackService feedbackService, IDiscordRestGuildAPI guildApi, IDiscordRestUserAPI userApi,
UtilityService utility) {
_context = context;
_channelApi = channelApi;
_dataService = dataService;
_feedbackService = feedbackService;
_guildApi = guildApi;
_userApi = userApi;
_utility = utility;
}
/// <summary>
/// A slash command that kicks a Discord user with the specified reason.
/// </summary>
/// <param name="target">The user to kick.</param>
/// <param name="reason">
/// The reason for this kick. Must be encoded with <see cref="Extensions.EncodeHeader" /> when passed to
/// <see cref="IDiscordRestGuildAPI.RemoveGuildMemberAsync" />.
/// </param>
/// <returns>
/// A feedback sending result which may or may not have succeeded. A successful result does not mean that the user
/// was kicked and vice-versa.
/// </returns>
[Command("kick", "кик")]
[RequireContext(ChannelContext.Guild)]
[RequireDiscordPermission(DiscordPermission.KickMembers)]
[RequireBotDiscordPermissions(DiscordPermission.KickMembers)]
[Description("кикает твоего друга <3")]
public async Task<Result> KickUserAsync(
[Description("друг которого кикать")] IUser target, [Description("причина зачем кикать")] string reason) {
// Data checks
if (!_context.TryGetGuildID(out var guildId))
return Result.FromError(new ArgumentNullError(nameof(guildId)));
if (!_context.TryGetUserID(out var userId))
return Result.FromError(new ArgumentNullError(nameof(userId)));
if (!_context.TryGetChannelID(out var channelId))
return Result.FromError(new ArgumentNullError(nameof(channelId)));
// The current user's avatar is used when sending error messages
var currentUserResult = await _userApi.GetCurrentUserAsync(CancellationToken);
if (!currentUserResult.IsDefined(out var currentUser))
return Result.FromError(currentUserResult);
var data = await _dataService.GetData(guildId.Value, CancellationToken);
var cfg = data.Configuration;
Messages.Culture = data.Culture;
var existingKickResult = await _guildApi.GetGuildMemberAsync(guildId.Value, target.ID);
if (!existingKickResult.IsSuccess) {
var embed = new EmbedBuilder().WithSmallTitle(Messages.UserNotFoundShort, currentUser)
.WithColour(ColorsList.Red).Build();
if (!embed.IsDefined(out var alreadyBuilt))
return Result.FromError(embed);
return (Result)await _feedbackService.SendContextualEmbedAsync(alreadyBuilt, ct: CancellationToken);
}
var interactionResult
= await _utility.CheckInteractionsAsync(guildId.Value, userId.Value, target.ID, "Kick", CancellationToken);
if (!interactionResult.IsSuccess)
return Result.FromError(interactionResult);
Result<Embed> responseEmbed;
if (interactionResult.Entity is not null) {
responseEmbed = new EmbedBuilder().WithSmallTitle(interactionResult.Entity, currentUser)
.WithColour(ColorsList.Red).Build();
} else {
var userResult = await _userApi.GetUserAsync(userId.Value, CancellationToken);
if (!userResult.IsDefined(out var user))
return Result.FromError(userResult);
var kickResult = await _guildApi.RemoveGuildMemberAsync(
guildId.Value, target.ID, reason: $"({user.GetTag()}) {reason.EncodeHeader()}",
ct: CancellationToken);
if (!kickResult.IsSuccess)
return Result.FromError(kickResult.Error);
responseEmbed = new EmbedBuilder().WithSmallTitle(
string.Format(Messages.UserKicked, target.GetTag()), target)
.WithColour(ColorsList.Green).Build();
if ((cfg.PublicFeedbackChannel is not 0 && cfg.PublicFeedbackChannel != channelId.Value)
|| (cfg.PrivateFeedbackChannel is not 0 && cfg.PrivateFeedbackChannel != channelId.Value)) {
var logEmbed = new EmbedBuilder().WithSmallTitle(
string.Format(Messages.UserKicked, target.GetTag()), target)
.WithDescription(string.Format(Messages.DescriptionUserPunished, reason))
.WithActionFooter(user)
.WithCurrentTimestamp()
.WithColour(ColorsList.Red)
.Build();
if (!logEmbed.IsDefined(out var logBuilt))
return Result.FromError(logEmbed);
var builtArray = new[] { logBuilt };
// Not awaiting to reduce response time
if (cfg.PrivateFeedbackChannel != channelId.Value)
_ = _channelApi.CreateMessageAsync(
cfg.PrivateFeedbackChannel.ToDiscordSnowflake(), embeds: builtArray,
ct: CancellationToken);
if (cfg.PublicFeedbackChannel != channelId.Value)
_ = _channelApi.CreateMessageAsync(
cfg.PublicFeedbackChannel.ToDiscordSnowflake(), embeds: builtArray,
ct: CancellationToken);
}
}
if (!responseEmbed.IsDefined(out var built))
return Result.FromError(responseEmbed);
return (Result)await _feedbackService.SendContextualEmbedAsync(built, ct: CancellationToken);
}
}

1733
Messages.Designer.cs generated

File diff suppressed because it is too large Load diff

View file

@ -1,52 +1,52 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<root> <root>
<!-- <!--
Microsoft ResX Schema Microsoft ResX Schema
Version 2.0 Version 2.0
The primary goals of this format is to allow a simple XML format The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes various data types are done through the TypeConverter classes
associated with the data types. associated with the data types.
Example: Example:
... ado.net/XML headers & schema ... ... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader><resheader name="version">2.0</resheader><resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader><resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader><data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data><data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data><data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"><value>[base64 mime encoded serialized .NET Framework object]</value></data><data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"><value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value><comment>This is a comment</comment></data> <resheader name="resmimetype">text/microsoft-resx</resheader><resheader name="version">2.0</resheader><resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader><resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader><data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data><data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data><data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"><value>[base64 mime encoded serialized .NET Framework object]</value></data><data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"><value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value><comment>This is a comment</comment></data>
There are any number of "resheader" rows that contain simple There are any number of "resheader" rows that contain simple
name/value pairs. name/value pairs.
Each data row contains a name, and value. The row also contains a Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture. text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the Classes that don't support this are serialized and stored with the
mimetype set. mimetype set.
The mimetype is used for serialized objects, and tells the The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly: extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below. read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64 mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64 mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64 mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter : using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
--> -->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true"> <xsd:element name="root" msdata:IsDataSet="true">
@ -205,8 +205,8 @@
<value>You need to specify an integer from {0} to {1} instead of {2}!</value> <value>You need to specify an integer from {0} to {1} instead of {2}!</value>
</data> </data>
<data name="UserBanned" xml:space="preserve"> <data name="UserBanned" xml:space="preserve">
<value>{0} was banned</value> <value>{0} was banned</value>
</data> </data>
<data name="SettingDoesntExist" xml:space="preserve"> <data name="SettingDoesntExist" xml:space="preserve">
<value>That setting doesn't exist!</value> <value>That setting doesn't exist!</value>
</data> </data>
@ -231,37 +231,37 @@
<data name="EventCreated" xml:space="preserve"> <data name="EventCreated" xml:space="preserve">
<value>{0} has created event {1}! It will take place in {2} and will start &lt;t:{3}:R&gt;! \n {4}</value> <value>{0} has created event {1}! It will take place in {2} and will start &lt;t:{3}:R&gt;! \n {4}</value>
</data> </data>
<data name="SettingsEventNotificationRole" xml:space="preserve"> <data name="SettingsEventNotificationRole" xml:space="preserve">
<value>Role for event creation notifications</value> <value>Role for event creation notifications</value>
</data> </data>
<data name="SettingsEventNotificationChannel" xml:space="preserve"> <data name="SettingsEventNotificationChannel" xml:space="preserve">
<value>Channel for event notifications</value> <value>Channel for event notifications</value>
</data> </data>
<data name="SettingsEventStartedReceivers" xml:space="preserve"> <data name="SettingsEventStartedReceivers" xml:space="preserve">
<value>Event start notifications receivers</value> <value>Event start notifications receivers</value>
</data> </data>
<data name="EventStarted" xml:space="preserve"> <data name="EventStarted" xml:space="preserve">
<value>Event "{0}" started</value> <value>Event "{0}" started</value>
</data> </data>
<data name="SettingsFrowningFace" xml:space="preserve"> <data name="SettingsFrowningFace" xml:space="preserve">
<value>:(</value> <value>:(</value>
</data> </data>
<data name="EventCancelled" xml:space="preserve"> <data name="EventCancelled" xml:space="preserve">
<value>Event "{0}" is cancelled!</value> <value>Event "{0}" is cancelled!</value>
</data> </data>
<data name="EventCompleted" xml:space="preserve"> <data name="EventCompleted" xml:space="preserve">
<value>Event "{0}" has completed!</value> <value>Event "{0}" has completed!</value>
</data> </data>
<data name="Ever" xml:space="preserve"> <data name="Ever" xml:space="preserve">
<value>ever</value> <value>ever</value>
</data> </data>
<data name="FeedbackMessagesCleared" xml:space="preserve"> <data name="FeedbackMessagesCleared" xml:space="preserve">
<value>Deleted {0} messages in {1}</value> <value>Deleted {0} messages in {1}</value>
</data> </data>
<data name="FeedbackMemberKicked" xml:space="preserve"> <data name="FeedbackMemberKicked" xml:space="preserve">
<value>Kicked {0}: {1}</value> <value>Kicked {0}: {1}</value>
</data> </data>
<data name="FeedbackMemberMuted" xml:space="preserve"> <data name="FeedbackMemberMuted" xml:space="preserve">
<value>Muted {0} for{1}: {2}</value> <value>Muted {0} for{1}: {2}</value>
</data> </data>
<data name="FeedbackUserUnbanned" xml:space="preserve"> <data name="FeedbackUserUnbanned" xml:space="preserve">
@ -436,8 +436,8 @@
<value>I could not find this user in any guild I'm a member of! Check if the ID is correct and that the user was on this server no longer than 30 days ago</value> <value>I could not find this user in any guild I'm a member of! Check if the ID is correct and that the user was on this server no longer than 30 days ago</value>
</data> </data>
<data name="SettingsDefaultRole" xml:space="preserve"> <data name="SettingsDefaultRole" xml:space="preserve">
<value>Default role</value> <value>Default role</value>
</data> </data>
<data name="CommandDescriptionRemind" xml:space="preserve"> <data name="CommandDescriptionRemind" xml:space="preserve">
<value>Adds a reminder</value> <value>Adds a reminder</value>
</data> </data>
@ -474,25 +474,40 @@
<data name="DescriptionExternalEventCreated" xml:space="preserve"> <data name="DescriptionExternalEventCreated" xml:space="preserve">
<value>The event will start at {0} until {1} in {2}</value> <value>The event will start at {0} until {1} in {2}</value>
</data> </data>
<data name="EventDetailsButton" xml:space="preserve"> <data name="EventDetailsButton" xml:space="preserve">
<value>Event details</value> <value>Event details</value>
</data> </data>
<data name="EventDuration" xml:space="preserve"> <data name="EventDuration" xml:space="preserve">
<value>The event has lasted for `{0}`</value> <value>The event has lasted for `{0}`</value>
</data> </data>
<data name="DescriptionLocalEventStarted" xml:space="preserve"> <data name="DescriptionLocalEventStarted" xml:space="preserve">
<value>The event is happening at {0}</value> <value>The event is happening at {0}</value>
</data> </data>
<data name="DescriptionExternalEventStarted" xml:space="preserve"> <data name="DescriptionExternalEventStarted" xml:space="preserve">
<value>The event is happening at {0} until {1}</value> <value>The event is happening at {0} until {1}</value>
</data> </data>
<data name="DescriptionUserBanned" xml:space="preserve">
<value>Reason: {0}</value>
</data>
<data name="UserAlreadyBanned" xml:space="preserve"> <data name="UserAlreadyBanned" xml:space="preserve">
<value>This user is already banned!</value> <value>This user is already banned!</value>
</data> </data>
<data name="UserUnbanned" xml:space="preserve"> <data name="UserUnbanned" xml:space="preserve">
<value>{0} was unbanned</value> <value>{0} was unbanned</value>
</data> </data>
<data name="UserMuted" xml:space="preserve">
<value>{0} was muted</value>
</data>
<data name="UserUnmuted" xml:space="preserve">
<value>{0} was unmuted</value>
</data>
<data name="UserNotMuted" xml:space="preserve">
<value>This member is not muted!</value>
</data>
<data name="UserNotFoundShort" xml:space="preserve">
<value>I could not find this user!</value>
</data>
<data name="UserKicked" xml:space="preserve">
<value>{0} was kicked</value>
</data>
<data name="DescriptionUserPunished" xml:space="preserve">
<value>Reason: {0}</value>
</data>
</root> </root>

View file

@ -1,52 +1,52 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<root> <root>
<!-- <!--
Microsoft ResX Schema Microsoft ResX Schema
Version 2.0 Version 2.0
The primary goals of this format is to allow a simple XML format The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes various data types are done through the TypeConverter classes
associated with the data types. associated with the data types.
Example: Example:
... ado.net/XML headers & schema ... ... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader><resheader name="version">2.0</resheader><resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader><resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader><data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data><data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data><data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"><value>[base64 mime encoded serialized .NET Framework object]</value></data><data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"><value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value><comment>This is a comment</comment></data> <resheader name="resmimetype">text/microsoft-resx</resheader><resheader name="version">2.0</resheader><resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader><resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader><data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data><data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data><data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"><value>[base64 mime encoded serialized .NET Framework object]</value></data><data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"><value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value><comment>This is a comment</comment></data>
There are any number of "resheader" rows that contain simple There are any number of "resheader" rows that contain simple
name/value pairs. name/value pairs.
Each data row contains a name, and value. The row also contains a Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture. text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the Classes that don't support this are serialized and stored with the
mimetype set. mimetype set.
The mimetype is used for serialized objects, and tells the The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly: extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below. read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64 mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64 mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64 mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter : using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
--> -->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true"> <xsd:element name="root" msdata:IsDataSet="true">
@ -205,8 +205,8 @@
<value>Надо указать целое число от {0} до {1} вместо {2}!</value> <value>Надо указать целое число от {0} до {1} вместо {2}!</value>
</data> </data>
<data name="UserBanned" xml:space="preserve"> <data name="UserBanned" xml:space="preserve">
<value>{0} был(-а) забанен(-а)</value> <value>{0} был(-а) забанен(-а)</value>
</data> </data>
<data name="SettingDoesntExist" xml:space="preserve"> <data name="SettingDoesntExist" xml:space="preserve">
<value>Такая настройка не существует!</value> <value>Такая настройка не существует!</value>
</data> </data>
@ -241,17 +241,17 @@
<value>Получатели уведомлений о начале событий</value> <value>Получатели уведомлений о начале событий</value>
</data> </data>
<data name="EventStarted" xml:space="preserve"> <data name="EventStarted" xml:space="preserve">
<value>Событие "{0}" началось</value> <value>Событие "{0}" началось</value>
</data> </data>
<data name="SettingsFrowningFace" xml:space="preserve"> <data name="SettingsFrowningFace" xml:space="preserve">
<value>:( </value> <value>:( </value>
</data> </data>
<data name="EventCancelled" xml:space="preserve"> <data name="EventCancelled" xml:space="preserve">
<value>Событие "{0}" отменено!</value> <value>Событие "{0}" отменено!</value>
</data> </data>
<data name="EventCompleted" xml:space="preserve"> <data name="EventCompleted" xml:space="preserve">
<value>Событие "{0}" завершено!</value> <value>Событие "{0}" завершено!</value>
</data> </data>
<data name="Ever" xml:space="preserve"> <data name="Ever" xml:space="preserve">
<value>всегда</value> <value>всегда</value>
</data> </data>
@ -436,8 +436,8 @@
<value>Я не смог найти этого пользователя ни в одном из серверов, в которых я есть. Проверь правильность ID и нахождение пользователя на этом сервере максимум 30 дней назад</value> <value>Я не смог найти этого пользователя ни в одном из серверов, в которых я есть. Проверь правильность ID и нахождение пользователя на этом сервере максимум 30 дней назад</value>
</data> </data>
<data name="SettingsDefaultRole" xml:space="preserve"> <data name="SettingsDefaultRole" xml:space="preserve">
<value>Общая роль</value> <value>Общая роль</value>
</data> </data>
<data name="CommandDescriptionRemind" xml:space="preserve"> <data name="CommandDescriptionRemind" xml:space="preserve">
<value>Добавляет напоминание</value> <value>Добавляет напоминание</value>
</data> </data>
@ -474,25 +474,40 @@
<data name="DescriptionExternalEventCreated" xml:space="preserve"> <data name="DescriptionExternalEventCreated" xml:space="preserve">
<value>Событие пройдёт с {0} до {1} в {2}</value> <value>Событие пройдёт с {0} до {1} в {2}</value>
</data> </data>
<data name="EventDetailsButton" xml:space="preserve"> <data name="EventDetailsButton" xml:space="preserve">
<value>Подробнее о событии</value> <value>Подробнее о событии</value>
</data> </data>
<data name="EventDuration" xml:space="preserve"> <data name="EventDuration" xml:space="preserve">
<value>Событие длилось `{0}`</value> <value>Событие длилось `{0}`</value>
</data> </data>
<data name="DescriptionLocalEventStarted" xml:space="preserve"> <data name="DescriptionLocalEventStarted" xml:space="preserve">
<value>Событие происходит в {0}</value> <value>Событие происходит в {0}</value>
</data> </data>
<data name="DescriptionExternalEventStarted" xml:space="preserve"> <data name="DescriptionExternalEventStarted" xml:space="preserve">
<value>Событие происходит в {0} до {1}</value> <value>Событие происходит в {0} до {1}</value>
</data> </data>
<data name="DescriptionUserBanned" xml:space="preserve">
<value>Причина: {0}</value>
</data>
<data name="UserAlreadyBanned" xml:space="preserve"> <data name="UserAlreadyBanned" xml:space="preserve">
<value>Этот пользователь уже забанен!</value> <value>Этот пользователь уже забанен!</value>
</data> </data>
<data name="UserUnbanned" xml:space="preserve"> <data name="UserUnbanned" xml:space="preserve">
<value>{0} был(-а) разбанен(-а)</value> <value>{0} был(-а) разбанен(-а)</value>
</data> </data>
<data name="UserMuted" xml:space="preserve">
<value>{0} был(-а) заглушен(-а)</value>
</data>
<data name="UserNotMuted" xml:space="preserve">
<value>Этот участник не заглушен!</value>
</data>
<data name="UserUnmuted" xml:space="preserve">
<value>{0} был(-а) разглушен(-а)</value>
</data>
<data name="UserNotFoundShort" xml:space="preserve">
<value>Я не смог найти этого пользователя!</value>
</data>
<data name="UserKicked" xml:space="preserve">
<value>{0} был(-а) выгнан(-а)</value>
</data>
<data name="DescriptionUserPunished" xml:space="preserve">
<value>Причина: {0}</value>
</data>
</root> </root>

View file

@ -1,52 +1,52 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<root> <root>
<!-- <!--
Microsoft ResX Schema Microsoft ResX Schema
Version 2.0 Version 2.0
The primary goals of this format is to allow a simple XML format The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes various data types are done through the TypeConverter classes
associated with the data types. associated with the data types.
Example: Example:
... ado.net/XML headers & schema ... ... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader><resheader name="version">2.0</resheader><resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader><resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader><data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data><data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data><data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"><value>[base64 mime encoded serialized .NET Framework object]</value></data><data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"><value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value><comment>This is a comment</comment></data> <resheader name="resmimetype">text/microsoft-resx</resheader><resheader name="version">2.0</resheader><resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader><resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader><data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data><data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data><data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"><value>[base64 mime encoded serialized .NET Framework object]</value></data><data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"><value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value><comment>This is a comment</comment></data>
There are any number of "resheader" rows that contain simple There are any number of "resheader" rows that contain simple
name/value pairs. name/value pairs.
Each data row contains a name, and value. The row also contains a Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture. text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the Classes that don't support this are serialized and stored with the
mimetype set. mimetype set.
The mimetype is used for serialized objects, and tells the The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly: extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below. read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64 mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64 mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64 mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter : using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
--> -->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true"> <xsd:element name="root" msdata:IsDataSet="true">
@ -205,8 +205,8 @@
<value>выбери число от {0} до {1} вместо {2}!</value> <value>выбери число от {0} до {1} вместо {2}!</value>
</data> </data>
<data name="UserBanned" xml:space="preserve"> <data name="UserBanned" xml:space="preserve">
<value>{0} забанен</value> <value>{0} забанен</value>
</data> </data>
<data name="SettingDoesntExist" xml:space="preserve"> <data name="SettingDoesntExist" xml:space="preserve">
<value>такой прикол не существует</value> <value>такой прикол не существует</value>
</data> </data>
@ -241,17 +241,17 @@
<value>получатели уведомлений о начале движух</value> <value>получатели уведомлений о начале движух</value>
</data> </data>
<data name="EventStarted" xml:space="preserve"> <data name="EventStarted" xml:space="preserve">
<value>движуха "{0}" начинается</value> <value>движуха "{0}" начинается</value>
</data> </data>
<data name="SettingsFrowningFace" xml:space="preserve"> <data name="SettingsFrowningFace" xml:space="preserve">
<value>оъмъомоъемъъео((((</value> <value>оъмъомоъемъъео((((</value>
</data> </data>
<data name="EventCancelled" xml:space="preserve"> <data name="EventCancelled" xml:space="preserve">
<value>движуха "{0}" отменен!</value> <value>движуха "{0}" отменен!</value>
</data> </data>
<data name="EventCompleted" xml:space="preserve"> <data name="EventCompleted" xml:space="preserve">
<value>движуха "{0}" завершен!</value> <value>движуха "{0}" завершен!</value>
</data> </data>
<data name="Ever" xml:space="preserve"> <data name="Ever" xml:space="preserve">
<value>всегда</value> <value>всегда</value>
</data> </data>
@ -436,8 +436,8 @@
<value>у нас такого шизоида нету, проверь, валиден ли ID уважаемого (я забываю о шизоидах если они ливнули минимум месяц назад)</value> <value>у нас такого шизоида нету, проверь, валиден ли ID уважаемого (я забываю о шизоидах если они ливнули минимум месяц назад)</value>
</data> </data>
<data name="SettingsDefaultRole" xml:space="preserve"> <data name="SettingsDefaultRole" xml:space="preserve">
<value>дефолтное звание</value> <value>дефолтное звание</value>
</data> </data>
<data name="CommandDescriptionRemind" xml:space="preserve"> <data name="CommandDescriptionRemind" xml:space="preserve">
<value>крафтит напоминалку</value> <value>крафтит напоминалку</value>
</data> </data>
@ -474,25 +474,40 @@
<data name="DescriptionExternalEventCreated" xml:space="preserve"> <data name="DescriptionExternalEventCreated" xml:space="preserve">
<value>движуха будет происходить с {0} до {1} в {2}</value> <value>движуха будет происходить с {0} до {1} в {2}</value>
</data> </data>
<data name="EventDetailsButton" xml:space="preserve"> <data name="EventDetailsButton" xml:space="preserve">
<value>побольше о движухе</value> <value>побольше о движухе</value>
</data> </data>
<data name="EventDuration" xml:space="preserve"> <data name="EventDuration" xml:space="preserve">
<value>все это длилось `{0}`</value> <value>все это длилось `{0}`</value>
</data> </data>
<data name="DescriptionLocalEventStarted" xml:space="preserve"> <data name="DescriptionLocalEventStarted" xml:space="preserve">
<value>движуха происходит в {0}</value> <value>движуха происходит в {0}</value>
</data> </data>
<data name="DescriptionExternalEventStarted" xml:space="preserve"> <data name="DescriptionExternalEventStarted" xml:space="preserve">
<value>движуха происходит в {0} до {1}</value> <value>движуха происходит в {0} до {1}</value>
</data> </data>
<data name="DescriptionUserBanned" xml:space="preserve">
<value>причина: {0}</value>
</data>
<data name="UserAlreadyBanned" xml:space="preserve"> <data name="UserAlreadyBanned" xml:space="preserve">
<value>этот шизоид уже лежит в бане</value> <value>этот шизоид уже лежит в бане</value>
</data> </data>
<data name="UserUnbanned" xml:space="preserve"> <data name="UserUnbanned" xml:space="preserve">
<value>{0} раззабанен</value> <value>{0} раззабанен</value>
</data> </data>
<data name="UserMuted" xml:space="preserve">
<value>{0} в муте</value>
</data>
<data name="UserUnmuted" xml:space="preserve">
<value>{0} в размуте</value>
</data>
<data name="UserNotMuted" xml:space="preserve">
<value>этого шизоида никто не мутил.</value>
</data>
<data name="UserNotFoundShort" xml:space="preserve">
<value>у нас такого шизоида нету...</value>
</data>
<data name="UserKicked" xml:space="preserve">
<value>{0} вышел с посторонней помощью</value>
</data>
<data name="DescriptionUserPunished" xml:space="preserve">
<value>причина: {0}</value>
</data>
</root> </root>