mirror of
https://github.com/Bubuni-Team/telegram-bot.git
synced 2026-07-31 00:29:24 +03:00
Merge pull request #33 from Bubuni-Team/feature/core/chat-options
[core] New fancy option system
This commit is contained in:
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Kruzya.TelegramBot.Core.Data;
|
||||||
|
|
||||||
|
[PrimaryKey(nameof(ChatId), nameof(OptionId))]
|
||||||
|
public class ChatOptionValue
|
||||||
|
{
|
||||||
|
public long ChatId { get; set; }
|
||||||
|
public string OptionId { get; set; }
|
||||||
|
public byte[] Value { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public T GetValue<T>(T defVal = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return JsonSerializer.Deserialize<T>(new ReadOnlySpan<byte>(Value));
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return defVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetValue<T>(T value)
|
||||||
|
{
|
||||||
|
Value = JsonSerializer.SerializeToUtf8Bytes(value, new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
WriteIndented = false,
|
||||||
|
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,8 @@ namespace Kruzya.TelegramBot.Core.Data
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public DbSet<BotUserValue> UserValues { get; set; }
|
public DbSet<BotUserValue> UserValues { get; set; }
|
||||||
|
|
||||||
|
public DbSet<ChatOptionValue> ChatOptionValues { get; set; }
|
||||||
|
|
||||||
public CoreContext(DbContextOptions<CoreContext> ctx) : base(ctx)
|
public CoreContext(DbContextOptions<CoreContext> ctx) : base(ctx)
|
||||||
{
|
{
|
||||||
Database.Migrate();
|
Database.Migrate();
|
||||||
|
|||||||
@@ -22,14 +22,14 @@ namespace Kruzya.TelegramBot.Core.Extensions
|
|||||||
public static async Task<bool> IsUserAdminAsync(this ITelegramBotClient bot, Chat chat, User user)
|
public static async Task<bool> IsUserAdminAsync(this ITelegramBotClient bot, Chat chat, User user)
|
||||||
{
|
{
|
||||||
var callerMember = await bot.GetChatMemberAsync(chat, user.Id);
|
var callerMember = await bot.GetChatMemberAsync(chat, user.Id);
|
||||||
var canUse = callerMember is ChatMemberOwner;
|
var isAdmin = callerMember is ChatMemberOwner;
|
||||||
|
|
||||||
if (callerMember is ChatMemberAdministrator callerAdmin)
|
if (callerMember is ChatMemberAdministrator callerAdmin)
|
||||||
{
|
{
|
||||||
canUse = callerAdmin.CanRestrictMembers;
|
isAdmin = callerAdmin.CanRestrictMembers;
|
||||||
}
|
}
|
||||||
|
|
||||||
return canUse;
|
return isAdmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<bool> CanDeleteMessagesAsync(this ITelegramBotClient bot, Chat chat)
|
public static async Task<bool> CanDeleteMessagesAsync(this ITelegramBotClient bot, Chat chat)
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Kruzya.TelegramBot.Core.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Kruzya.TelegramBot.Core.Extensions;
|
||||||
|
|
||||||
|
public partial class RepositoryExtension
|
||||||
|
{
|
||||||
|
public static async Task<ChatOptionValue> FindOption(this DbSet<ChatOptionValue> repository, long chatId,
|
||||||
|
string optionId)
|
||||||
|
{
|
||||||
|
return await repository.SingleOrDefaultAsync(x => x.ChatId == chatId && x.OptionId == optionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<ChatOptionValue> FindOrCreateOption(this DbSet<ChatOptionValue> repository, long chatId,
|
||||||
|
string optionId)
|
||||||
|
{
|
||||||
|
var opt = await repository.FindOption(chatId, optionId) ?? new ChatOptionValue
|
||||||
|
{
|
||||||
|
ChatId = chatId,
|
||||||
|
OptionId = optionId
|
||||||
|
};
|
||||||
|
|
||||||
|
return opt;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,20 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using Kruzya.TelegramBot.Core.Cache;
|
using Kruzya.TelegramBot.Core.Cache;
|
||||||
|
using Kruzya.TelegramBot.Core.Options;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace Kruzya.TelegramBot.Core.Extensions
|
namespace Kruzya.TelegramBot.Core.Extensions;
|
||||||
{
|
|
||||||
public static class StartupExtension
|
public static class StartupExtension
|
||||||
{
|
{
|
||||||
public static IServiceCollection AddQueue<T>(this IServiceCollection collection)
|
public static IServiceCollection AddQueue<T>(this IServiceCollection collection)
|
||||||
=> collection.AddSingleton<ConcurrentQueue<T>>();
|
=> collection.AddSingleton<ConcurrentQueue<T>>();
|
||||||
|
|
||||||
|
public static IServiceCollection AddMemoryCache<TKey, TValue>(this IServiceCollection collection)
|
||||||
|
=> collection.AddSingleton<MemoryCache<TKey, TValue>>();
|
||||||
|
|
||||||
|
public static IServiceCollection AddOption<T>(this IServiceCollection collection) where T : class, IOption
|
||||||
|
=> collection.AddScoped<T>()
|
||||||
|
.AddScoped<IOption, T>(s => s.GetService<T>());
|
||||||
|
|
||||||
public static IServiceCollection AddMemoryCache<TKey, TValue>(this IServiceCollection collection)
|
|
||||||
=> collection.AddSingleton<MemoryCache<TKey, TValue>>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@ using Telegram.Bot;
|
|||||||
using Telegram.Bot.Types;
|
using Telegram.Bot.Types;
|
||||||
using Telegram.Bot.Types.Enums;
|
using Telegram.Bot.Types.Enums;
|
||||||
|
|
||||||
namespace Kruzya.TelegramBot.Core
|
namespace Kruzya.TelegramBot.Core.Handler
|
||||||
{
|
{
|
||||||
public abstract class CommonHandler : BotEventHandler
|
public abstract class CommonHandler : BotEventHandler
|
||||||
{
|
{
|
||||||
@@ -18,7 +18,7 @@ namespace Kruzya.TelegramBot.Core
|
|||||||
protected Message? Message => RawUpdate.Message;
|
protected Message? Message => RawUpdate.Message;
|
||||||
|
|
||||||
protected User? RepliedUser => Message?.ReplyToMessage?.From;
|
protected User? RepliedUser => Message?.ReplyToMessage?.From;
|
||||||
|
|
||||||
protected CommonHandler(CoreContext db)
|
protected CommonHandler(CoreContext db)
|
||||||
{
|
{
|
||||||
Db = db;
|
Db = db;
|
||||||
@@ -34,8 +34,8 @@ namespace Kruzya.TelegramBot.Core
|
|||||||
{
|
{
|
||||||
return RepliedUser != null && await Bot.CanPunishMember(Chat, From, RepliedUser);
|
return RepliedUser != null && await Bot.CanPunishMember(Chat, From, RepliedUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected async Task BanMember(long userId, DateTime banEnd)
|
protected async Task BanMember(long userId, DateTime banEnd)
|
||||||
{
|
{
|
||||||
await Bot.RestrictChatMemberAsync(
|
await Bot.RestrictChatMemberAsync(
|
||||||
@@ -48,10 +48,15 @@ namespace Kruzya.TelegramBot.Core
|
|||||||
banEnd
|
banEnd
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task<BotUserValue> GetWarnOption(User user)
|
protected async Task<BotUserValue> GetWarnOption(User user)
|
||||||
{
|
{
|
||||||
return await Db.UserValues.FindOrCreateOption(Chat.Id, user.Id, "warnCount");
|
return await Db.UserValues.FindOrCreateOption(Chat.Id, user.Id, "warnCount");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected async Task AnswerQuery(string id, string? message = null)
|
||||||
|
{
|
||||||
|
await Bot.AnswerCallbackQueryAsync(id, message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BotFramework;
|
using BotFramework;
|
||||||
using BotFramework.Attributes;
|
using BotFramework.Attributes;
|
||||||
using Kruzya.TelegramBot.Core.Data;
|
using Kruzya.TelegramBot.Core.Data;
|
||||||
using Kruzya.TelegramBot.Core.Extensions;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Telegram.Bot.Types;
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
namespace Kruzya.TelegramBot.Core
|
namespace Kruzya.TelegramBot.Core.Handler
|
||||||
{
|
{
|
||||||
public class GeneralHandler : BotEventHandler
|
public class GeneralHandler : BotEventHandler
|
||||||
{
|
{
|
||||||
@@ -22,7 +20,7 @@ namespace Kruzya.TelegramBot.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected readonly CoreContext databaseContext;
|
protected readonly CoreContext databaseContext;
|
||||||
|
|
||||||
public GeneralHandler(CoreContext dbCtx)
|
public GeneralHandler(CoreContext dbCtx)
|
||||||
{
|
{
|
||||||
databaseContext = dbCtx;
|
databaseContext = dbCtx;
|
||||||
@@ -32,7 +30,7 @@ namespace Kruzya.TelegramBot.Core
|
|||||||
[Priority(short.MaxValue - 10)]
|
[Priority(short.MaxValue - 10)]
|
||||||
public async Task<bool> Listener()
|
public async Task<bool> Listener()
|
||||||
{
|
{
|
||||||
foreach (var message in new Message[] {RawUpdate.Message, RawUpdate.EditedMessage, RawUpdate.ChannelPost, RawUpdate.EditedChannelPost})
|
foreach (var message in new Message[] { RawUpdate.Message, RawUpdate.EditedMessage, RawUpdate.ChannelPost, RawUpdate.EditedChannelPost })
|
||||||
{
|
{
|
||||||
if (message == null)
|
if (message == null)
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,184 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BotFramework.Attributes;
|
||||||
|
using BotFramework.Enums;
|
||||||
|
using Kruzya.TelegramBot.Core.Data;
|
||||||
|
using Kruzya.TelegramBot.Core.Extensions;
|
||||||
|
using Kruzya.TelegramBot.Core.Options;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Telegram.Bot;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
|
|
||||||
|
namespace Kruzya.TelegramBot.Core.Handler;
|
||||||
|
|
||||||
|
public class SettingsHandler : CommonHandler
|
||||||
|
{
|
||||||
|
private readonly IEnumerable<IOption> _options;
|
||||||
|
|
||||||
|
public SettingsHandler(CoreContext db, IServiceProvider serviceProvider) : base(db)
|
||||||
|
{
|
||||||
|
_options = serviceProvider.GetServices<IOption>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Command(InChat.Public, "settings", CommandParseMode.WithUsername)]
|
||||||
|
public async Task HandleSettings()
|
||||||
|
{
|
||||||
|
if (!await Bot.IsUserAdminAsync(Chat, From))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Bot.SendTextMessageAsync(
|
||||||
|
Chat.Id,
|
||||||
|
"What do you want to change?",
|
||||||
|
replyMarkup: GetSettingsMarkup()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Update(InChat.Public, UpdateFlag.CallbackQuery)]
|
||||||
|
public async Task HandleCallback()
|
||||||
|
{
|
||||||
|
var query = CallbackQuery;
|
||||||
|
var queryData = query.Data;
|
||||||
|
|
||||||
|
if (queryData == null || !queryData.StartsWith("option") || !await Bot.IsUserAdminAsync(Chat, From))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var paramList = queryData.Split('|');
|
||||||
|
if (!long.TryParse(paramList[1], out var senderId))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (senderId != From.Id)
|
||||||
|
{
|
||||||
|
await AnswerQuery(query.Id, "Keyboard called by another user");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (paramList[2] == "main_menu")
|
||||||
|
{
|
||||||
|
await AnswerQuery(query.Id);
|
||||||
|
await Bot.EditMessageTextAsync(Chat.Id, query.Message!.MessageId, "What do you want to change?",
|
||||||
|
replyMarkup: GetSettingsMarkup());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (paramList[2] == "edit" || paramList[2] == "select")
|
||||||
|
{
|
||||||
|
var option = GetOptionById(paramList[3]);
|
||||||
|
if (option == null)
|
||||||
|
{
|
||||||
|
await AnswerQuery(query.Id, "Invalid option ID");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (paramList[2])
|
||||||
|
{
|
||||||
|
case "edit":
|
||||||
|
await HandleOptionEdit(option, paramList, query);
|
||||||
|
break;
|
||||||
|
case "select":
|
||||||
|
await HandleOptionSelect(option, paramList, query);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task HandleOptionEdit(IOption option, string[] paramList, CallbackQuery query)
|
||||||
|
{
|
||||||
|
var chatId = Chat.Id;
|
||||||
|
var messageId = query.Message!.MessageId;
|
||||||
|
switch (option.OptionType)
|
||||||
|
{
|
||||||
|
case OptionType.OnOff:
|
||||||
|
var onOffOpt = (IOption<bool>) option;
|
||||||
|
await onOffOpt.SetValueAsync(chatId, !await onOffOpt.GetValueAsync(chatId));
|
||||||
|
await AnswerQuery(query.Id);
|
||||||
|
|
||||||
|
await Bot.EditMessageReplyMarkupAsync(chatId, messageId, GetSettingsMarkup());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OptionType.Select:
|
||||||
|
var selectOpt = (IOption<string>) option;
|
||||||
|
await AnswerQuery(query.Id);
|
||||||
|
|
||||||
|
await Bot.EditMessageTextAsync(Chat.Id, messageId, "Here's what you can choose:",
|
||||||
|
replyMarkup: await GetChoiceSelectKeyboard(selectOpt));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
await AnswerQuery(query.Id, "Not implemented");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task HandleOptionSelect(IOption option, string[] paramList, CallbackQuery query)
|
||||||
|
{
|
||||||
|
var choice = option.ChoiceList.SingleOrDefault(x => x.Id == paramList[4]);
|
||||||
|
if (choice == null)
|
||||||
|
{
|
||||||
|
await AnswerQuery(query.Id, "Invalid option choice");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var selectOption = (IOption<string>) option;
|
||||||
|
await selectOption.SetValueAsync(Chat.Id, choice.Id);
|
||||||
|
await AnswerQuery(query.Id);
|
||||||
|
|
||||||
|
await Bot.EditMessageReplyMarkupAsync(Chat.Id, query.Message!.MessageId, await GetChoiceSelectKeyboard(selectOption));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<InlineKeyboardButton> GetKeyboardButton(IOption option)
|
||||||
|
{
|
||||||
|
var button = new InlineKeyboardButton(option.OptionName)
|
||||||
|
{
|
||||||
|
CallbackData = $"option|{From.Id}|edit|{option.OptionId}"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (option.OptionType == OptionType.OnOff)
|
||||||
|
{
|
||||||
|
var isEnabled = await ((IOption<bool>) option).GetValueAsync(Chat.Id);
|
||||||
|
button.Text += isEnabled ? " 🟢" : " 🔴";
|
||||||
|
}
|
||||||
|
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<InlineKeyboardMarkup> GetChoiceSelectKeyboard(IOption<string> option)
|
||||||
|
{
|
||||||
|
var value = await option.GetValueAsync(Chat.Id);
|
||||||
|
var choices = option.ChoiceList.Select(x => x.ToButton(From.Id, option.OptionId, x.Id == value))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
choices.Add(new []
|
||||||
|
{
|
||||||
|
new InlineKeyboardButton("Main menu")
|
||||||
|
{
|
||||||
|
CallbackData = $"option|{From.Id}|main_menu"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return new InlineKeyboardMarkup(choices);
|
||||||
|
}
|
||||||
|
|
||||||
|
private InlineKeyboardMarkup GetSettingsMarkup()
|
||||||
|
{
|
||||||
|
var keyboardLayout = _options.ToAsyncEnumerable()
|
||||||
|
.SelectAwait(async x => await GetKeyboardButton(x))
|
||||||
|
.ToEnumerable()
|
||||||
|
.Chunk(3);
|
||||||
|
|
||||||
|
return new InlineKeyboardMarkup(keyboardLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IOption GetOptionById(string optionId)
|
||||||
|
{
|
||||||
|
return _options.SingleOrDefault(x => x.OptionId == optionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Kruzya.TelegramBot.Core.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Kruzya.TelegramBot.Core.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(CoreContext))]
|
||||||
|
[Migration("20230720171645_AddChatOptions")]
|
||||||
|
partial class AddChatOptions
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "7.0.1")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kruzya.TelegramBot.Core.Data.BotUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("BotUserId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<long>("ChatId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<long>("UserId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.HasKey("BotUserId");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kruzya.TelegramBot.Core.Data.BotUserValue", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("BotUserValueId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("BotUserId")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Value")
|
||||||
|
.HasColumnType("longblob");
|
||||||
|
|
||||||
|
b.Property<string>("ValueType")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("BotUserValueId");
|
||||||
|
|
||||||
|
b.HasIndex("BotUserId");
|
||||||
|
|
||||||
|
b.ToTable("UserValues");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kruzya.TelegramBot.Core.Data.ChatOptionValue", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("ChatId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("OptionId")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Value")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longblob");
|
||||||
|
|
||||||
|
b.HasKey("ChatId", "OptionId");
|
||||||
|
|
||||||
|
b.ToTable("ChatOptionValues");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kruzya.TelegramBot.Core.Data.BotUserValue", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Kruzya.TelegramBot.Core.Data.BotUser", "BotUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BotUserId");
|
||||||
|
|
||||||
|
b.Navigation("BotUser");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Kruzya.TelegramBot.Core.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddChatOptions : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ChatOptionValues",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
ChatId = table.Column<long>(type: "bigint", nullable: false),
|
||||||
|
OptionId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
Value = table.Column<byte[]>(type: "longblob", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ChatOptionValues", x => new { x.ChatId, x.OptionId });
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ChatOptionValues");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "ValueType",
|
||||||
|
table: "UserValues",
|
||||||
|
type: "longtext CHARACTER SET utf8mb4",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "longtext",
|
||||||
|
oldNullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4")
|
||||||
|
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "Name",
|
||||||
|
table: "UserValues",
|
||||||
|
type: "longtext CHARACTER SET utf8mb4",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "longtext",
|
||||||
|
oldNullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4")
|
||||||
|
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
namespace Kruzya.TelegramBot.Core.Migrations
|
namespace Kruzya.TelegramBot.Core.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(CoreContext))]
|
[DbContext(typeof(CoreContext))]
|
||||||
@@ -14,7 +16,7 @@ namespace Kruzya.TelegramBot.Core.Migrations
|
|||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.HasAnnotation("ProductVersion", "3.1.2")
|
.HasAnnotation("ProductVersion", "7.0.1")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||||
|
|
||||||
modelBuilder.Entity("Kruzya.TelegramBot.Core.Data.BotUser", b =>
|
modelBuilder.Entity("Kruzya.TelegramBot.Core.Data.BotUser", b =>
|
||||||
@@ -44,13 +46,13 @@ namespace Kruzya.TelegramBot.Core.Migrations
|
|||||||
.HasColumnType("char(36)");
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
b.Property<string>("Name")
|
b.Property<string>("Name")
|
||||||
.HasColumnType("longtext CHARACTER SET utf8mb4");
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
b.Property<byte[]>("Value")
|
b.Property<byte[]>("Value")
|
||||||
.HasColumnType("longblob");
|
.HasColumnType("longblob");
|
||||||
|
|
||||||
b.Property<string>("ValueType")
|
b.Property<string>("ValueType")
|
||||||
.HasColumnType("longtext CHARACTER SET utf8mb4");
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
b.HasKey("BotUserValueId");
|
b.HasKey("BotUserValueId");
|
||||||
|
|
||||||
@@ -59,11 +61,30 @@ namespace Kruzya.TelegramBot.Core.Migrations
|
|||||||
b.ToTable("UserValues");
|
b.ToTable("UserValues");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kruzya.TelegramBot.Core.Data.ChatOptionValue", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("ChatId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("OptionId")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<byte[]>("Value")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longblob");
|
||||||
|
|
||||||
|
b.HasKey("ChatId", "OptionId");
|
||||||
|
|
||||||
|
b.ToTable("ChatOptionValues");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kruzya.TelegramBot.Core.Data.BotUserValue", b =>
|
modelBuilder.Entity("Kruzya.TelegramBot.Core.Data.BotUserValue", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Kruzya.TelegramBot.Core.Data.BotUser", "BotUser")
|
b.HasOne("Kruzya.TelegramBot.Core.Data.BotUser", "BotUser")
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("BotUserId");
|
.HasForeignKey("BotUserId");
|
||||||
|
|
||||||
|
b.Navigation("BotUser");
|
||||||
});
|
});
|
||||||
#pragma warning restore 612, 618
|
#pragma warning restore 612, 618
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Kruzya.TelegramBot.Core.Options;
|
||||||
|
|
||||||
|
public abstract class AbstractOption<TOption, TValue> : IOption<TValue>
|
||||||
|
where TOption: AbstractOption<TOption, TValue>
|
||||||
|
{
|
||||||
|
public abstract string OptionId { get; }
|
||||||
|
public abstract string OptionName { get; }
|
||||||
|
public abstract OptionType OptionType { get; }
|
||||||
|
public abstract TValue DefaultValue { get; }
|
||||||
|
public List<SelectChoice> ChoiceList { get; } = new();
|
||||||
|
|
||||||
|
private readonly IOptionProvider _optionProvider;
|
||||||
|
|
||||||
|
protected AbstractOption(IOptionProvider optionProvider)
|
||||||
|
{
|
||||||
|
_optionProvider = optionProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<TValue> GetValueAsync(long chatId)
|
||||||
|
{
|
||||||
|
return await _optionProvider.GetValueAsync(chatId, OptionId, DefaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SetValueAsync(long chatId, TValue value)
|
||||||
|
{
|
||||||
|
await _optionProvider.SetValueAsync(chatId, OptionId, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Kruzya.TelegramBot.Core.Data;
|
||||||
|
using Kruzya.TelegramBot.Core.Extensions;
|
||||||
|
|
||||||
|
namespace Kruzya.TelegramBot.Core.Options;
|
||||||
|
|
||||||
|
public class DbOptionProvider : IOptionProvider
|
||||||
|
{
|
||||||
|
private readonly CoreContext _db;
|
||||||
|
|
||||||
|
public DbOptionProvider(CoreContext db)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<TValue> GetValueAsync<TValue>(long chatId, string optionId, TValue defVal)
|
||||||
|
{
|
||||||
|
return (await _db.ChatOptionValues.FindOrCreateOption(chatId, optionId)).GetValue(defVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SetValueAsync<TValue>(long chatId, string optionId, TValue value)
|
||||||
|
{
|
||||||
|
var chatOption = await _db.ChatOptionValues.FindOrCreateOption(chatId, optionId);
|
||||||
|
chatOption.SetValue(value);
|
||||||
|
_db.AddOrUpdate(chatOption);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Kruzya.TelegramBot.Core.Options;
|
||||||
|
|
||||||
|
public interface IOption
|
||||||
|
{
|
||||||
|
public string OptionId { get; }
|
||||||
|
public string OptionName { get; }
|
||||||
|
public OptionType OptionType { get; }
|
||||||
|
public List<SelectChoice> ChoiceList { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IOption<TValue> : IOption
|
||||||
|
{
|
||||||
|
public TValue DefaultValue { get; }
|
||||||
|
|
||||||
|
public Task<TValue> GetValueAsync(long chatId);
|
||||||
|
public Task SetValueAsync(long chatId, TValue value);
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Kruzya.TelegramBot.Core.Options;
|
||||||
|
|
||||||
|
public interface IOptionProvider
|
||||||
|
{
|
||||||
|
public Task<TValue> GetValueAsync<TValue>(long chatId, string optionId, TValue defVal);
|
||||||
|
public Task SetValueAsync<TValue>(long chatId, string optionId, TValue value);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Kruzya.TelegramBot.Core.Options;
|
||||||
|
|
||||||
|
public enum OptionType
|
||||||
|
{
|
||||||
|
OnOff,
|
||||||
|
Select
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
|
|
||||||
|
namespace Kruzya.TelegramBot.Core.Options;
|
||||||
|
|
||||||
|
public class SelectChoice
|
||||||
|
{
|
||||||
|
public string Id { get; }
|
||||||
|
public string FullName { get; }
|
||||||
|
public string ShortName { get; }
|
||||||
|
|
||||||
|
public SelectChoice(string id, string fullName, string shortName)
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
FullName = fullName;
|
||||||
|
ShortName = shortName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<InlineKeyboardButton> ToButton(long userId, string optionId, bool isActive = false)
|
||||||
|
{
|
||||||
|
return new[]
|
||||||
|
{
|
||||||
|
new InlineKeyboardButton((isActive ? "🟢 " : "🔴 ") + FullName)
|
||||||
|
{
|
||||||
|
CallbackData = $"option|{userId}|select|{optionId}|{Id}"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ using Microsoft.Extensions.Configuration;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using Kruzya.TelegramBot.Core.Options;
|
||||||
using Telegram.Bot.Types;
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
namespace Kruzya.TelegramBot.Core
|
namespace Kruzya.TelegramBot.Core
|
||||||
@@ -53,6 +54,8 @@ namespace Kruzya.TelegramBot.Core
|
|||||||
services.AddSingleton<ConcurrentBag<DeleteRequest>>();
|
services.AddSingleton<ConcurrentBag<DeleteRequest>>();
|
||||||
services.AddHostedService<DeleteService>();
|
services.AddHostedService<DeleteService>();
|
||||||
|
|
||||||
|
services.AddScoped<IOptionProvider, DbOptionProvider>();
|
||||||
|
|
||||||
// Trigger module handlers.
|
// Trigger module handlers.
|
||||||
_core.Modules.ConfigureServices(services);
|
_core.Modules.ConfigureServices(services);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ using System;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BotFramework.Attributes;
|
using BotFramework.Attributes;
|
||||||
using BotFramework.Enums;
|
using BotFramework.Enums;
|
||||||
using Kruzya.TelegramBot.Core;
|
|
||||||
using Kruzya.TelegramBot.Core.Data;
|
using Kruzya.TelegramBot.Core.Data;
|
||||||
using Kruzya.TelegramBot.Core.Extensions;
|
using Kruzya.TelegramBot.Core.Extensions;
|
||||||
|
using Kruzya.TelegramBot.Core.Handler;
|
||||||
using Telegram.Bot;
|
using Telegram.Bot;
|
||||||
using Telegram.Bot.Types;
|
using Telegram.Bot.Types;
|
||||||
using Telegram.Bot.Types.Enums;
|
using Telegram.Bot.Types.Enums;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using Kruzya.TelegramBot.Core;
|
using Kruzya.TelegramBot.Core.Data;
|
||||||
using Kruzya.TelegramBot.Core.Data;
|
using Kruzya.TelegramBot.Core.Handler;
|
||||||
|
|
||||||
namespace West.TelegramBot.ChatManagement.Handler;
|
namespace West.TelegramBot.ChatManagement.Handler;
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BotFramework.Attributes;
|
using BotFramework.Attributes;
|
||||||
using BotFramework.Enums;
|
using BotFramework.Enums;
|
||||||
using Kruzya.TelegramBot.Core;
|
|
||||||
using Kruzya.TelegramBot.Core.Data;
|
using Kruzya.TelegramBot.Core.Data;
|
||||||
using Kruzya.TelegramBot.Core.Extensions;
|
using Kruzya.TelegramBot.Core.Extensions;
|
||||||
|
using Kruzya.TelegramBot.Core.Handler;
|
||||||
using Telegram.Bot;
|
using Telegram.Bot;
|
||||||
using Telegram.Bot.Exceptions;
|
using Telegram.Bot.Exceptions;
|
||||||
using West.TelegramBot.ChatManagement.Service;
|
using West.TelegramBot.ChatManagement.Service;
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BotFramework.Attributes;
|
using BotFramework.Attributes;
|
||||||
using BotFramework.Enums;
|
using BotFramework.Enums;
|
||||||
using Kruzya.TelegramBot.Core;
|
|
||||||
using Kruzya.TelegramBot.Core.Data;
|
using Kruzya.TelegramBot.Core.Data;
|
||||||
|
using Kruzya.TelegramBot.Core.Handler;
|
||||||
using West.TelegramBot.ChatManagement.Service;
|
using West.TelegramBot.ChatManagement.Service;
|
||||||
|
|
||||||
namespace West.TelegramBot.ChatManagement.Handler;
|
namespace West.TelegramBot.ChatManagement.Handler;
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ using System;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BotFramework.Attributes;
|
using BotFramework.Attributes;
|
||||||
using BotFramework.Enums;
|
using BotFramework.Enums;
|
||||||
using Kruzya.TelegramBot.Core;
|
|
||||||
using Kruzya.TelegramBot.Core.Data;
|
using Kruzya.TelegramBot.Core.Data;
|
||||||
using Kruzya.TelegramBot.Core.Extensions;
|
using Kruzya.TelegramBot.Core.Extensions;
|
||||||
|
using Kruzya.TelegramBot.Core.Handler;
|
||||||
using Kruzya.TelegramBot.Core.Service;
|
using Kruzya.TelegramBot.Core.Service;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Telegram.Bot;
|
using Telegram.Bot;
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
using Kruzya.TelegramBot.Core;
|
using Kruzya.TelegramBot.Core;
|
||||||
|
using Kruzya.TelegramBot.Core.Extensions;
|
||||||
|
using Kruzya.TelegramBot.Core.Options;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using West.TelegramBot.ContentStore.Option;
|
||||||
using West.TelegramBot.ContentStore.Service;
|
using West.TelegramBot.ContentStore.Service;
|
||||||
|
|
||||||
namespace West.TelegramBot.ContentStore;
|
namespace West.TelegramBot.ContentStore;
|
||||||
@@ -22,6 +25,8 @@ public class ContentStore : Module
|
|||||||
|
|
||||||
public override void ConfigureServices(IServiceCollection services)
|
public override void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
services.AddOption<AllowNsfw>();
|
||||||
|
|
||||||
foreach (var serviceType in MediaServiceTypes)
|
foreach (var serviceType in MediaServiceTypes)
|
||||||
{
|
{
|
||||||
services.AddScoped(typeof(IRandomMediaService), serviceType);
|
services.AddScoped(typeof(IRandomMediaService), serviceType);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
using BotFramework;
|
|
||||||
using BotFramework.Attributes;
|
using BotFramework.Attributes;
|
||||||
using BotFramework.Enums;
|
using BotFramework.Enums;
|
||||||
|
using Kruzya.TelegramBot.Core.Data;
|
||||||
using Kruzya.TelegramBot.Core.Extensions;
|
using Kruzya.TelegramBot.Core.Extensions;
|
||||||
|
using Kruzya.TelegramBot.Core.Handler;
|
||||||
using Kruzya.TelegramBot.Core.Service;
|
using Kruzya.TelegramBot.Core.Service;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Telegram.Bot;
|
using Telegram.Bot;
|
||||||
using Telegram.Bot.Types;
|
|
||||||
using Telegram.Bot.Types.Enums;
|
using Telegram.Bot.Types.Enums;
|
||||||
using Telegram.Bot.Types.ReplyMarkups;
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
using West.TelegramBot.ContentStore.Service;
|
using West.TelegramBot.ContentStore.Service;
|
||||||
|
|
||||||
namespace West.TelegramBot.ContentStore.Handler;
|
namespace West.TelegramBot.ContentStore.Handler;
|
||||||
|
|
||||||
public class Store : BotEventHandler
|
public class Store : CommonHandler
|
||||||
{
|
{
|
||||||
private readonly IReputation? _reputation;
|
private readonly IReputation? _reputation;
|
||||||
private readonly IServiceProvider _provider;
|
private readonly IServiceProvider _provider;
|
||||||
private readonly ContentStore _store;
|
private readonly ContentStore _store;
|
||||||
|
|
||||||
public Store(IServiceProvider provider, ContentStore store)
|
public Store(CoreContext db, IServiceProvider provider, ContentStore store) : base(db)
|
||||||
{
|
{
|
||||||
_reputation = provider.GetService<IReputation>();
|
_reputation = provider.GetService<IReputation>();
|
||||||
_provider = provider;
|
_provider = provider;
|
||||||
@@ -110,7 +110,7 @@ public class Store : BotEventHandler
|
|||||||
{
|
{
|
||||||
await PerformPurchase(mediaService, messageId);
|
await PerformPurchase(mediaService, messageId);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
answer = "Товар недоступен";
|
answer = "Товар недоступен";
|
||||||
await Bot.EditMessageTextAsync(Chat.Id,
|
await Bot.EditMessageTextAsync(Chat.Id,
|
||||||
@@ -164,9 +164,4 @@ public class Store : BotEventHandler
|
|||||||
|
|
||||||
return mediaService != null;
|
return mediaService != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AnswerQuery(string id, string? message = null)
|
|
||||||
{
|
|
||||||
await Bot.AnswerCallbackQueryAsync(id, message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using Kruzya.TelegramBot.Core.Options;
|
||||||
|
|
||||||
|
namespace West.TelegramBot.ContentStore.Option;
|
||||||
|
|
||||||
|
public class AllowNsfw : AbstractOption<AllowNsfw, bool>
|
||||||
|
{
|
||||||
|
public override string OptionId => "allowNSFW";
|
||||||
|
public override string OptionName => "NSFW";
|
||||||
|
public override OptionType OptionType => OptionType.OnOff;
|
||||||
|
public override bool DefaultValue => false;
|
||||||
|
|
||||||
|
public AllowNsfw(IOptionProvider optionProvider) : base(optionProvider)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,25 +1,23 @@
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using BotFramework.Utils;
|
using BotFramework.Utils;
|
||||||
using Kruzya.TelegramBot.Core.Data;
|
|
||||||
using Kruzya.TelegramBot.Core.Extensions;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Telegram.Bot.Types;
|
using Telegram.Bot.Types;
|
||||||
using West.TelegramBot.ContentStore.Model;
|
using West.TelegramBot.ContentStore.Model;
|
||||||
|
using West.TelegramBot.ContentStore.Option;
|
||||||
|
|
||||||
namespace West.TelegramBot.ContentStore.Service;
|
namespace West.TelegramBot.ContentStore.Service;
|
||||||
|
|
||||||
public abstract class AbstractKittiesService : IRandomMediaService
|
public abstract class AbstractKittiesService : IRandomMediaService
|
||||||
{
|
{
|
||||||
private readonly CoreContext _db;
|
private readonly AllowNsfw _allowNsfw;
|
||||||
protected abstract string VideoType { get; }
|
protected abstract string VideoType { get; }
|
||||||
|
|
||||||
public abstract StoreItem StoreItem { get; }
|
public abstract StoreItem StoreItem { get; }
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
|
|
||||||
protected AbstractKittiesService(IConfiguration configuration, CoreContext db)
|
protected AbstractKittiesService(IConfiguration configuration, AllowNsfw allowNsfw)
|
||||||
{
|
{
|
||||||
_db = db;
|
|
||||||
var section = configuration.GetSection("KittiesService");
|
var section = configuration.GetSection("KittiesService");
|
||||||
|
|
||||||
var uri = section.GetValue<Uri>("Uri");
|
var uri = section.GetValue<Uri>("Uri");
|
||||||
@@ -33,6 +31,7 @@ public abstract class AbstractKittiesService : IRandomMediaService
|
|||||||
Authorization = new AuthenticationHeaderValue("Bearer", token)
|
Authorization = new AuthenticationHeaderValue("Bearer", token)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
_allowNsfw = allowNsfw;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<RandomMedia> GetRandomMediaAsync()
|
public async Task<RandomMedia> GetRandomMediaAsync()
|
||||||
@@ -52,8 +51,6 @@ public abstract class AbstractKittiesService : IRandomMediaService
|
|||||||
|
|
||||||
public async Task<bool> CanView(Chat chat, User user)
|
public async Task<bool> CanView(Chat chat, User user)
|
||||||
{
|
{
|
||||||
var option = await _db.UserValues.FindOrCreateOption(chat.Id, "AllowNSFW");
|
return await _allowNsfw.GetValueAsync(chat.Id);
|
||||||
|
|
||||||
return option.GetValue(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using Telegram.Bot.Types;
|
||||||
|
using West.TelegramBot.ContentStore.Model;
|
||||||
|
using West.TelegramBot.ContentStore.Option;
|
||||||
|
|
||||||
|
namespace West.TelegramBot.ContentStore.Service;
|
||||||
|
|
||||||
|
public abstract class AbstractNsfwService : IRandomMediaService
|
||||||
|
{
|
||||||
|
private readonly AllowNsfw _allowNsfw;
|
||||||
|
public abstract StoreItem StoreItem { get; }
|
||||||
|
public abstract Task<RandomMedia> GetRandomMediaAsync();
|
||||||
|
|
||||||
|
protected AbstractNsfwService(AllowNsfw allowNsfw)
|
||||||
|
{
|
||||||
|
_allowNsfw = allowNsfw;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> CanView(Chat chat, User user) => await _allowNsfw.GetValueAsync(chat.Id);
|
||||||
|
}
|
||||||
@@ -1,27 +1,24 @@
|
|||||||
using Kruzya.TelegramBot.Core.Data;
|
using Telegram.Bot.Types;
|
||||||
using Kruzya.TelegramBot.Core.Extensions;
|
|
||||||
using Telegram.Bot.Types;
|
|
||||||
using Telegram.Bot.Types.Enums;
|
using Telegram.Bot.Types.Enums;
|
||||||
using West.TelegramBot.ContentStore.Model;
|
using West.TelegramBot.ContentStore.Model;
|
||||||
|
using West.TelegramBot.ContentStore.Option;
|
||||||
|
|
||||||
namespace West.TelegramBot.ContentStore.Service;
|
namespace West.TelegramBot.ContentStore.Service;
|
||||||
|
|
||||||
public class AnimBoobsService : IRandomMediaService
|
public class AnimBoobsService : AbstractNsfwService
|
||||||
{
|
{
|
||||||
private readonly CoreContext _db;
|
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
public StoreItem StoreItem { get; } = new("anim_boobs", "Сиськи движущиеся", 120, 40);
|
public override StoreItem StoreItem { get; } = new("anim_boobs", "Сиськи движущиеся", 120, 40);
|
||||||
|
|
||||||
public AnimBoobsService(CoreContext db)
|
public AnimBoobsService(AllowNsfw allowNsfw) : base(allowNsfw)
|
||||||
{
|
{
|
||||||
_db = db;
|
_httpClient = new HttpClient
|
||||||
_httpClient = new HttpClient()
|
|
||||||
{
|
{
|
||||||
BaseAddress = new Uri("https://westdev.me/_boobs/")
|
BaseAddress = new Uri("https://westdev.me/_boobs/")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<RandomMedia> GetRandomMediaAsync()
|
public override async Task<RandomMedia> GetRandomMediaAsync()
|
||||||
{
|
{
|
||||||
var fileName = await _httpClient.GetStringAsync("index.php");
|
var fileName = await _httpClient.GetStringAsync("index.php");
|
||||||
// https://bugs.telegram.org/c/23674 workaround
|
// https://bugs.telegram.org/c/23674 workaround
|
||||||
@@ -33,11 +30,4 @@ public class AnimBoobsService : IRandomMediaService
|
|||||||
Nsfw = true
|
Nsfw = true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> CanView(Chat chat, User user)
|
|
||||||
{
|
|
||||||
var option = await _db.UserValues.FindOrCreateOption(chat.Id, "AllowNSFW");
|
|
||||||
|
|
||||||
return option.GetValue(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -6,8 +6,8 @@ namespace West.TelegramBot.ContentStore.Service;
|
|||||||
public class CapyApiService : IRandomMediaService
|
public class CapyApiService : IRandomMediaService
|
||||||
{
|
{
|
||||||
public StoreItem StoreItem { get; } = new("capybara", "Капибара", 60, 25);
|
public StoreItem StoreItem { get; } = new("capybara", "Капибара", 60, 25);
|
||||||
public async Task<RandomMedia> GetRandomMediaAsync()
|
public Task<RandomMedia> GetRandomMediaAsync()
|
||||||
{
|
{
|
||||||
return new RandomMedia(new InputFileUrl($"https://api.capy.lol/v1/capybara?{new Random().Next(0, 10000)}"));
|
return Task.FromResult(new RandomMedia(new InputFileUrl($"https://api.capy.lol/v1/capybara?{new Random().Next(0, 10000)}")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
using Kruzya.TelegramBot.Core.Data;
|
using Kruzya.TelegramBot.Core.Data;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using West.TelegramBot.ContentStore.Model;
|
using West.TelegramBot.ContentStore.Model;
|
||||||
|
using West.TelegramBot.ContentStore.Option;
|
||||||
|
|
||||||
namespace West.TelegramBot.ContentStore.Service;
|
namespace West.TelegramBot.ContentStore.Service;
|
||||||
|
|
||||||
public class GayKittiesService : AbstractKittiesService
|
public class GayKittiesService : AbstractKittiesService
|
||||||
{
|
{
|
||||||
public GayKittiesService(IConfiguration configuration, CoreContext db) : base(configuration, db)
|
public GayKittiesService(IConfiguration configuration, AllowNsfw allowNsfw) : base(configuration, allowNsfw)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,5 +8,5 @@ public interface IRandomMediaService
|
|||||||
public StoreItem StoreItem { get; }
|
public StoreItem StoreItem { get; }
|
||||||
|
|
||||||
public Task<RandomMedia> GetRandomMediaAsync();
|
public Task<RandomMedia> GetRandomMediaAsync();
|
||||||
public async Task<bool> CanView(Chat chat, User user) => true;
|
public Task<bool> CanView(Chat chat, User user) => Task.FromResult(true);
|
||||||
}
|
}
|
||||||
@@ -3,25 +3,24 @@ using Kruzya.TelegramBot.Core.Extensions;
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Telegram.Bot.Types;
|
using Telegram.Bot.Types;
|
||||||
using West.TelegramBot.ContentStore.Model;
|
using West.TelegramBot.ContentStore.Model;
|
||||||
|
using West.TelegramBot.ContentStore.Option;
|
||||||
|
|
||||||
namespace West.TelegramBot.ContentStore.Service;
|
namespace West.TelegramBot.ContentStore.Service;
|
||||||
|
|
||||||
public class OBoobsService : IRandomMediaService
|
public class OBoobsService : AbstractNsfwService
|
||||||
{
|
{
|
||||||
private readonly CoreContext _db;
|
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
public StoreItem StoreItem { get; } = new("boobs", "Сиськи", 60, 30);
|
public override StoreItem StoreItem { get; } = new("boobs", "Сиськи", 60, 30);
|
||||||
|
|
||||||
public OBoobsService(CoreContext db)
|
public OBoobsService(AllowNsfw allowNsfw) : base(allowNsfw)
|
||||||
{
|
{
|
||||||
_db = db;
|
|
||||||
_httpClient = new HttpClient
|
_httpClient = new HttpClient
|
||||||
{
|
{
|
||||||
BaseAddress = new Uri("http://api.oboobs.ru")
|
BaseAddress = new Uri("http://api.oboobs.ru")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<RandomMedia> GetRandomMediaAsync()
|
public override async Task<RandomMedia> GetRandomMediaAsync()
|
||||||
{
|
{
|
||||||
// "/boobs/{start=0; sql offset}/{count=1; sql limit}/{order=-id;[id,rank,-rank,interest,-interest,random]}/
|
// "/boobs/{start=0; sql offset}/{count=1; sql limit}/{order=-id;[id,rank,-rank,interest,-interest,random]}/
|
||||||
var httpResp = await _httpClient.GetAsync("boobs/1/1/random");
|
var httpResp = await _httpClient.GetAsync("boobs/1/1/random");
|
||||||
@@ -31,11 +30,4 @@ public class OBoobsService : IRandomMediaService
|
|||||||
|
|
||||||
return new RandomMedia(new InputFileUrl($"https://media.oboobs.ru/boobs/{boobsId}.jpg"), boobsItem.Model, true);
|
return new RandomMedia(new InputFileUrl($"https://media.oboobs.ru/boobs/{boobsId}.jpg"), boobsItem.Model, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> CanView(Chat chat, User user)
|
|
||||||
{
|
|
||||||
var option = await _db.UserValues.FindOrCreateOption(chat.Id, "AllowNSFW");
|
|
||||||
|
|
||||||
return option.GetValue(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -22,7 +22,7 @@ public abstract class SomeRandomApiAbstractService : IRandomMediaService
|
|||||||
public async Task<RandomMedia> GetRandomMediaAsync()
|
public async Task<RandomMedia> GetRandomMediaAsync()
|
||||||
{
|
{
|
||||||
var response = await _httpClient.GetStringAsync($"https://some-random-api.com/animal/{ApiId}");
|
var response = await _httpClient.GetStringAsync($"https://some-random-api.com/animal/{ApiId}");
|
||||||
var image = JsonConvert.DeserializeObject<SomeRandomApiAnimalResponse>(response);
|
var image = JsonConvert.DeserializeObject<SomeRandomApiAnimalResponse>(response)!;
|
||||||
|
|
||||||
return new RandomMedia(new InputFileUrl(image.Image), image.Fact);
|
return new RandomMedia(new InputFileUrl(image.Image), image.Fact);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Kruzya.TelegramBot.Core.Data;
|
using Kruzya.TelegramBot.Core.Data;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using West.TelegramBot.ContentStore.Model;
|
using West.TelegramBot.ContentStore.Model;
|
||||||
|
using West.TelegramBot.ContentStore.Option;
|
||||||
|
|
||||||
namespace West.TelegramBot.ContentStore.Service;
|
namespace West.TelegramBot.ContentStore.Service;
|
||||||
|
|
||||||
@@ -9,7 +10,7 @@ public class StraightKittiesService : AbstractKittiesService
|
|||||||
protected override string VideoType => "straight";
|
protected override string VideoType => "straight";
|
||||||
public override StoreItem StoreItem { get; } = new("kitties_straight", "Прон", 40, 100);
|
public override StoreItem StoreItem { get; } = new("kitties_straight", "Прон", 40, 100);
|
||||||
|
|
||||||
public StraightKittiesService(IConfiguration configuration, CoreContext db) : base(configuration, db)
|
public StraightKittiesService(IConfiguration configuration, AllowNsfw allowNsfw) : base(configuration, allowNsfw)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ global using GuessCache = Kruzya.TelegramBot.Core.Cache.MemoryCache<Telegram.Bot
|
|||||||
|
|
||||||
|
|
||||||
using Kruzya.TelegramBot.Core;
|
using Kruzya.TelegramBot.Core;
|
||||||
|
using Kruzya.TelegramBot.Core.Options;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Kruzya.TelegramBot.Core;
|
|||||||
using Kruzya.TelegramBot.Core.AutoDelete;
|
using Kruzya.TelegramBot.Core.AutoDelete;
|
||||||
using Kruzya.TelegramBot.Core.Data;
|
using Kruzya.TelegramBot.Core.Data;
|
||||||
using Kruzya.TelegramBot.Core.Extensions;
|
using Kruzya.TelegramBot.Core.Extensions;
|
||||||
|
using Kruzya.TelegramBot.Core.Handler;
|
||||||
using Kruzya.TelegramBot.Core.Service;
|
using Kruzya.TelegramBot.Core.Service;
|
||||||
using Telegram.Bot;
|
using Telegram.Bot;
|
||||||
using Telegram.Bot.Types;
|
using Telegram.Bot.Types;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ using System.Collections.Concurrent;
|
|||||||
using Telegram.Bot.Types.Enums;
|
using Telegram.Bot.Types.Enums;
|
||||||
using Telegram.Bot.Types;
|
using Telegram.Bot.Types;
|
||||||
using Microsoft.AspNetCore.Components.Forms;
|
using Microsoft.AspNetCore.Components.Forms;
|
||||||
|
using Kruzya.TelegramBot.Core.Handler;
|
||||||
|
|
||||||
namespace West.Entertainment.Handler;
|
namespace West.Entertainment.Handler;
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
using BotFramework.Attributes;
|
using BotFramework.Attributes;
|
||||||
using BotFramework.Enums;
|
using BotFramework.Enums;
|
||||||
using BotFramework.Utils;
|
using BotFramework.Utils;
|
||||||
using Kruzya.TelegramBot.Core;
|
|
||||||
using Kruzya.TelegramBot.Core.Data;
|
using Kruzya.TelegramBot.Core.Data;
|
||||||
using Kruzya.TelegramBot.Core.Extensions;
|
using Kruzya.TelegramBot.Core.Extensions;
|
||||||
|
using Kruzya.TelegramBot.Core.Handler;
|
||||||
using Kruzya.TelegramBot.Core.Service;
|
using Kruzya.TelegramBot.Core.Service;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Telegram.Bot;
|
using Telegram.Bot;
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using Kruzya.TelegramBot.Core.Options;
|
||||||
|
|
||||||
|
namespace West.TelegramBot.Reputation.Options;
|
||||||
|
|
||||||
|
public class KarmaMode : AbstractOption<KarmaMode, string>
|
||||||
|
{
|
||||||
|
public override string OptionId => "karmaMode";
|
||||||
|
public override string OptionName => "Karma Mode";
|
||||||
|
public override OptionType OptionType => OptionType.Select;
|
||||||
|
public override string DefaultValue => "geometric";
|
||||||
|
|
||||||
|
public KarmaMode(IOptionProvider optionProvider) : base(optionProvider)
|
||||||
|
{
|
||||||
|
ChoiceList.AddRange(new []
|
||||||
|
{
|
||||||
|
new SelectChoice("geometric", "Geometric", "G"),
|
||||||
|
new SelectChoice("linear", "Linear", "L")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
using Kruzya.TelegramBot.Core;
|
using Kruzya.TelegramBot.Core;
|
||||||
|
using Kruzya.TelegramBot.Core.Extensions;
|
||||||
using Kruzya.TelegramBot.Core.Service;
|
using Kruzya.TelegramBot.Core.Service;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using West.TelegramBot.Reputation.Data;
|
using West.TelegramBot.Reputation.Data;
|
||||||
|
using West.TelegramBot.Reputation.Options;
|
||||||
using West.TelegramBot.Reputation.Service;
|
using West.TelegramBot.Reputation.Service;
|
||||||
|
|
||||||
namespace West.TelegramBot.Reputation;
|
namespace West.TelegramBot.Reputation;
|
||||||
@@ -19,6 +21,7 @@ public class Reputation : Module
|
|||||||
var dsn = Configuration.GetConnectionString("Reputation");
|
var dsn = Configuration.GetConnectionString("Reputation");
|
||||||
services.AddDbContext<ReputationContext>(options => options.UseMySql(dsn, ServerVersion.AutoDetect(dsn)));
|
services.AddDbContext<ReputationContext>(options => options.UseMySql(dsn, ServerVersion.AutoDetect(dsn)));
|
||||||
|
|
||||||
|
services.AddOption<KarmaMode>();
|
||||||
services.AddScoped<IReputation, ReputationService>();
|
services.AddScoped<IReputation, ReputationService>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
|||||||
@@ -4,16 +4,19 @@ using Kruzya.TelegramBot.Core.Service;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Telegram.Bot.Types;
|
using Telegram.Bot.Types;
|
||||||
using West.TelegramBot.Reputation.Data;
|
using West.TelegramBot.Reputation.Data;
|
||||||
|
using West.TelegramBot.Reputation.Options;
|
||||||
|
|
||||||
namespace West.TelegramBot.Reputation.Service;
|
namespace West.TelegramBot.Reputation.Service;
|
||||||
|
|
||||||
public class ReputationService : IReputation
|
public class ReputationService : IReputation
|
||||||
{
|
{
|
||||||
private readonly ReputationContext _reputationContext;
|
private readonly ReputationContext _reputationContext;
|
||||||
|
private readonly KarmaMode _karmaMode;
|
||||||
|
|
||||||
public ReputationService(ReputationContext reputationContext)
|
public ReputationService(ReputationContext reputationContext, KarmaMode karmaMode)
|
||||||
{
|
{
|
||||||
_reputationContext = reputationContext;
|
_reputationContext = reputationContext;
|
||||||
|
_karmaMode = karmaMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<double> GetUserReputationAsync(Chat chat, User user)
|
public async Task<double> GetUserReputationAsync(Chat chat, User user)
|
||||||
@@ -45,14 +48,25 @@ public class ReputationService : IReputation
|
|||||||
public async Task<double> GetReputationDiffAsync(Chat chat, User sender, User receiver)
|
public async Task<double> GetReputationDiffAsync(Chat chat, User sender, User receiver)
|
||||||
{
|
{
|
||||||
var senderRep = await FindUserReputation(chat, sender);
|
var senderRep = await FindUserReputation(chat, sender);
|
||||||
|
|
||||||
if (senderRep == null)
|
if (senderRep == null)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var karmaMode = await _karmaMode.GetValueAsync(chat.Id);
|
||||||
var senderValue = senderRep.Value;
|
var senderValue = senderRep.Value;
|
||||||
return Math.Round(senderValue == 0 ? 1 : Math.Sqrt(senderValue), 2);
|
|
||||||
|
double diff;
|
||||||
|
if (senderValue == 0 || karmaMode == "linear")
|
||||||
|
{
|
||||||
|
diff = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diff = Math.Round(Math.Sqrt(senderValue), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<IReputationEntity>> GetChatRatingAsync(Chat chat, int limit = 10, int offset = 0)
|
public async Task<IEnumerable<IReputationEntity>> GetChatRatingAsync(Chat chat, int limit = 10, int offset = 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user