mirror of
https://github.com/Bubuni-Team/telegram-bot.git
synced 2026-07-31 00:29:24 +03:00
[store] Basic content store implementation.
- Bump Telegram Bot Framework to 0.6.9-gf1e77653ff
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
using Kruzya.TelegramBot.Core;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using West.TelegramBot.ContentStore.Service;
|
||||
|
||||
namespace West.TelegramBot.ContentStore;
|
||||
|
||||
public class ContentStore : Module
|
||||
{
|
||||
public ContentStore(Core core) : base(core)
|
||||
{
|
||||
}
|
||||
|
||||
public override void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<OBoobsService>();
|
||||
services.AddSingleton<CatApiService>();
|
||||
services.AddSingleton<DogApiService>();
|
||||
services.AddSingleton<AnimBoobsService>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<AssemblyName>TelegramBot.ContentStore</AssemblyName>
|
||||
<RootNamespace>West.TelegramBot.ContentStore</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Core\Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Handler\" />
|
||||
<Folder Include="Model\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,163 @@
|
||||
#nullable enable
|
||||
|
||||
using BotFramework;
|
||||
using BotFramework.Attributes;
|
||||
using BotFramework.Enums;
|
||||
using Kruzya.TelegramBot.Core.Extensions;
|
||||
using Kruzya.TelegramBot.Core.Service;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Telegram.Bot;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegram.Bot.Types.InputFiles;
|
||||
using Telegram.Bot.Types.ReplyMarkups;
|
||||
using West.TelegramBot.ContentStore.Model;
|
||||
using West.TelegramBot.ContentStore.Service;
|
||||
|
||||
namespace West.TelegramBot.ContentStore.Handler;
|
||||
|
||||
public class Store : BotEventHandler
|
||||
{
|
||||
private readonly IReputation? _reputation;
|
||||
private readonly IServiceProvider _provider;
|
||||
|
||||
private readonly Dictionary<string, StoreItem> _storeItemMap = new()
|
||||
{
|
||||
{ "cat", new StoreItem("cat", "Котэ", 40) },
|
||||
{ "dog", new StoreItem("dog", "Пёсель", 40) },
|
||||
{ "boobs", new StoreItem("boobs", "Сиськи", 60) },
|
||||
{ "anim_boobs", new StoreItem("anim_boobs", "Сиськи движущиеся", 120) }
|
||||
};
|
||||
|
||||
public Store(IServiceProvider provider)
|
||||
{
|
||||
_reputation = provider.GetService<IReputation>();
|
||||
_provider = provider;
|
||||
}
|
||||
|
||||
[Command(InChat.Public, "store", CommandParseMode.Both)]
|
||||
public async Task HandleStore()
|
||||
{
|
||||
if (_reputation == null)
|
||||
{
|
||||
await Bot.SendTextMessageAsync(Chat.Id, "Reputation is unavailable.");
|
||||
return;
|
||||
}
|
||||
|
||||
var rowList = new List<List<InlineKeyboardButton>>();
|
||||
|
||||
var counter = 0;
|
||||
var list = new List<InlineKeyboardButton>();
|
||||
foreach (var item in _storeItemMap)
|
||||
{
|
||||
var btn = item.Value.ToButton(From.Id);
|
||||
if ((counter & 1) == 0) // 0 - even, 1 - odd
|
||||
{
|
||||
list = new List<InlineKeyboardButton>
|
||||
{
|
||||
btn
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Add(btn);
|
||||
rowList.Add(list);
|
||||
}
|
||||
|
||||
counter++;
|
||||
}
|
||||
|
||||
await Bot.SendTextMessageAsync(Chat.Id, "Чего пожелаете?", replyMarkup: new InlineKeyboardMarkup(rowList));
|
||||
}
|
||||
|
||||
[Update(InChat.Public, UpdateFlag.CallbackQuery)]
|
||||
public async Task HandleStoreCallback()
|
||||
{
|
||||
var query = CallbackQuery;
|
||||
var queryData = query.Data;
|
||||
if (queryData == null || !queryData.StartsWith("store|") || _reputation == null)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
var answer = "Unknown action.";
|
||||
if (paramList[2] == "purchase")
|
||||
{
|
||||
var purchaseType = paramList[3];
|
||||
answer = "Спасибо за покупку";
|
||||
|
||||
if (!_storeItemMap.TryGetValue(purchaseType, out var storeItem)
|
||||
|| !TryGetMediaService(purchaseType, out var mediaService))
|
||||
{
|
||||
await AnswerQuery(query.Id, "Unknown purchasable.");
|
||||
return;
|
||||
}
|
||||
|
||||
var messageId = query.Message!.MessageId;
|
||||
if (await _reputation.GetUserReputationAsync(Chat, From) < storeItem.Price)
|
||||
{
|
||||
await Bot.EditMessageTextAsync(
|
||||
Chat.Id,
|
||||
messageId,
|
||||
$"{From.ToHtml()}, продолжай работать и тебе обязательно хватит на покупку.",
|
||||
ParseMode.Html);
|
||||
await AnswerQuery(query.Id);
|
||||
return;
|
||||
}
|
||||
|
||||
await _reputation.IncrementReputationAsync(Chat, From, -storeItem.Price);
|
||||
await Bot.EditMessageTextAsync(Chat.Id, messageId, $"{From.ToHtml()} купил \"{storeItem.Name}\".");
|
||||
|
||||
var randomMedia = await mediaService!.GetRandomMediaAsync();
|
||||
var file = new InputOnlineFile(randomMedia.Url);
|
||||
switch (randomMedia.Type)
|
||||
{
|
||||
case InputMediaType.Photo:
|
||||
await Bot.SendPhotoAsync(Chat.Id, file, randomMedia.Caption, replyToMessageId: messageId);
|
||||
break;
|
||||
case InputMediaType.Video:
|
||||
await Bot.SendVideoAsync(Chat.Id, file, caption: randomMedia.Caption, replyToMessageId: messageId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
await AnswerQuery(query.Id, answer);
|
||||
}
|
||||
|
||||
private bool TryGetMediaService(string name, out IRandomMediaService? mediaService)
|
||||
{
|
||||
var serviceType = name switch
|
||||
{
|
||||
"boobs" => typeof(OBoobsService),
|
||||
"cat" => typeof(CatApiService),
|
||||
"dog" => typeof(DogApiService),
|
||||
"anim_boobs" => typeof(AnimBoobsService),
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (serviceType == null)
|
||||
{
|
||||
mediaService = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
mediaService = _provider.GetService(serviceType) as IRandomMediaService;
|
||||
return mediaService != null;
|
||||
}
|
||||
|
||||
private async Task AnswerQuery(string id, string? message = null)
|
||||
{
|
||||
await Bot.AnswerCallbackQueryAsync(id, message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace West.TelegramBot.ContentStore.Model;
|
||||
|
||||
public class AnimalImage
|
||||
{
|
||||
public string Id { get; set; } = null!;
|
||||
public string Url { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace West.TelegramBot.ContentStore.Model;
|
||||
|
||||
public class OBoobsItem
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int Rank { get; set; }
|
||||
public string? Author { get; set; }
|
||||
public string? Model { get; set; }
|
||||
public string Preview { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
|
||||
namespace West.TelegramBot.ContentStore.Model;
|
||||
|
||||
public class RandomMedia
|
||||
{
|
||||
public RandomMedia(string url, string? caption = null)
|
||||
{
|
||||
Url = url;
|
||||
Caption = caption;
|
||||
}
|
||||
|
||||
public string Url;
|
||||
public string? Caption;
|
||||
|
||||
public InputMediaType Type { get; set; } = InputMediaType.Photo;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Telegram.Bot.Types.ReplyMarkups;
|
||||
|
||||
namespace West.TelegramBot.ContentStore.Model;
|
||||
|
||||
class StoreItem
|
||||
{
|
||||
public string Id;
|
||||
public readonly string Name;
|
||||
public readonly double Price;
|
||||
|
||||
public StoreItem(string id, string name, double price)
|
||||
{
|
||||
Id = id;
|
||||
Name = name;
|
||||
Price = price;
|
||||
}
|
||||
|
||||
public InlineKeyboardButton ToButton(long userId)
|
||||
{
|
||||
return new InlineKeyboardButton($"{Name} ({Price})")
|
||||
{
|
||||
CallbackData = $"store|{userId}|purchase|{Id}"
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using West.TelegramBot.ContentStore.Model;
|
||||
|
||||
namespace West.TelegramBot.ContentStore.Service;
|
||||
|
||||
public class AnimBoobsService : IRandomMediaService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
public AnimBoobsService()
|
||||
{
|
||||
_httpClient = new HttpClient()
|
||||
{
|
||||
BaseAddress = new Uri("https://westdev.me/_boobs/")
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<RandomMedia> GetRandomMediaAsync()
|
||||
{
|
||||
var fileName = await _httpClient.GetStringAsync("index.php");
|
||||
return new RandomMedia($"https://westdev.me/_boobs/media/{fileName}")
|
||||
{
|
||||
Type = InputMediaType.Video
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using Newtonsoft.Json;
|
||||
using West.TelegramBot.ContentStore.Model;
|
||||
|
||||
namespace West.TelegramBot.ContentStore.Service;
|
||||
|
||||
public abstract class AnimalAsAService : IRandomMediaService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
protected AnimalAsAService(Uri baseAddress)
|
||||
{
|
||||
_httpClient = new HttpClient
|
||||
{
|
||||
BaseAddress = baseAddress
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<RandomMedia> GetRandomMediaAsync()
|
||||
{
|
||||
var resp = await _httpClient.GetAsync("images/search");
|
||||
var catImage = JsonConvert.DeserializeObject<List<AnimalImage>>(await resp.Content.ReadAsStringAsync())[0];
|
||||
return new RandomMedia(catImage.Url);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using Newtonsoft.Json;
|
||||
using Telegram.Bot.Types;
|
||||
using West.TelegramBot.ContentStore.Model;
|
||||
|
||||
namespace West.TelegramBot.ContentStore.Service;
|
||||
|
||||
public class CatApiService : AnimalAsAService
|
||||
{
|
||||
public CatApiService() : base(new Uri("https://api.thecatapi.com/v1/")) {}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace West.TelegramBot.ContentStore.Service;
|
||||
|
||||
public class DogApiService : AnimalAsAService
|
||||
{
|
||||
public DogApiService() : base(new Uri("https://api.thedogapi.com/v1/")) {}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using Telegram.Bot.Types;
|
||||
using West.TelegramBot.ContentStore.Model;
|
||||
|
||||
namespace West.TelegramBot.ContentStore.Service;
|
||||
|
||||
public interface IRandomMediaService
|
||||
{
|
||||
public Task<RandomMedia> GetRandomMediaAsync();
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using Newtonsoft.Json;
|
||||
using Telegram.Bot.Types;
|
||||
using West.TelegramBot.ContentStore.Model;
|
||||
|
||||
namespace West.TelegramBot.ContentStore.Service;
|
||||
|
||||
public class OBoobsService : IRandomMediaService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
public OBoobsService()
|
||||
{
|
||||
_httpClient = new HttpClient
|
||||
{
|
||||
BaseAddress = new Uri("http://api.oboobs.ru")
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<RandomMedia> GetRandomMediaAsync()
|
||||
{
|
||||
var httpResp = await _httpClient.GetAsync("boobs/1/1/random");
|
||||
var boobsResponse = JsonConvert.DeserializeObject<List<OBoobsItem>>(await httpResp.Content.ReadAsStringAsync());
|
||||
var boobsItem = boobsResponse[0];
|
||||
var boobsId = boobsItem.Id.ToString("D5");
|
||||
|
||||
return new RandomMedia($"https://media.oboobs.ru/boobs/{boobsId}.jpg", boobsItem.Model);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user