[quote] Crappy chat quote implementation.

This commit is contained in:
West14
2022-01-21 00:10:27 +02:00
parent d9d5221280
commit 7cd1a295bb
10 changed files with 331 additions and 10 deletions
+32
View File
@@ -0,0 +1,32 @@
using System.Globalization;
using Kruzya.TelegramBot.Core;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using West.TelegramBot.ChatQuotes.Json;
namespace West.TelegramBot.ChatQuotes
{
public class ChatQuotes : Module
{
public static readonly JsonSerializerSettings SerializerSettings = new()
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters =
{
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal },
new StringEnumConverter(new CamelCaseNamingStrategy())
},
ContractResolver = new NullToEmptyObjectResolver()
};
public ChatQuotes(Core core) : base(core) { }
public override void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<QuoteGeneratorService>();
}
}
}
+22
View File
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>West.TelegramBot.ChatQuotes</RootNamespace>
<AssemblyName>TelegramBot.ChatQuotes</AssemblyName>
</PropertyGroup>
<ItemGroup>
<Folder Include="Handler\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Core\Core.csproj" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Delete Files="$(OutDir)\TelegramBot.dll" />
</Target>
</Project>
+31
View File
@@ -0,0 +1,31 @@
using BotFramework;
using BotFramework.Attributes;
using BotFramework.Enums;
using Telegram.Bot;
using Telegram.Bot.Types.InputFiles;
namespace West.TelegramBot.ChatQuotes.Handler;
public class Quote : BotEventHandler
{
private readonly QuoteGeneratorService _quoteGenerator;
public Quote(QuoteGeneratorService quoteGenerator)
{
_quoteGenerator = quoteGenerator;
}
[Command(InChat.Public, "q", CommandParseMode.Both)]
public async Task HandleQuote()
{
var msg = RawUpdate.Message;
var replyToMessage = msg?.ReplyToMessage;
if (msg == null || replyToMessage == null)
{
return;
}
var file = new InputOnlineFile(await _quoteGenerator.GenerateQuoteImage(replyToMessage));
await Bot.SendStickerAsync(Chat.Id, file, replyToMessageId: msg.MessageId);
}
}
@@ -0,0 +1,18 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace West.TelegramBot.ChatQuotes.Json
{
class NullToEmptyObjectResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
return type.GetProperties()
.Select(p => {
var jp = base.CreateProperty(p, memberSerialization);
jp.ValueProvider = new NullToEmptyStringValueProvider(p);
return jp;
}).ToList();
}
}
}
@@ -0,0 +1,26 @@
using System.Reflection;
using Newtonsoft.Json.Serialization;
using Telegram.Bot.Types;
namespace West.TelegramBot.ChatQuotes.Json;
public class NullToEmptyStringValueProvider : IValueProvider
{
private readonly PropertyInfo _memberInfo;
public NullToEmptyStringValueProvider(PropertyInfo memberInfo)
{
_memberInfo = memberInfo;
}
public object? GetValue(object target)
{
var result = _memberInfo.GetValue(target);
if (_memberInfo.PropertyType == typeof(Message) && result == null) result = new object();
return result;
}
public void SetValue(object target, object value)
{
_memberInfo.SetValue(target, value);
}
}
+82
View File
@@ -0,0 +1,82 @@
#nullable enable
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Telegram.Bot.Types;
using File = Telegram.Bot.Types.File;
namespace West.TelegramBot.ChatQuotes.Model;
[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
public class QuoteRequest
{
public QuoteRequest(Message msg)
{
// TODO: move default values to config
Format = "webp";
BackgroundColor = "#1b1429";
Width = 512;
Height = 768;
Scale = 2;
Messages = new List<QuoteMessage> {QuoteMessage.FromMessage(msg)};
}
public QuoteType Type { get; set; }
public string Format { get; set; }
public string BackgroundColor { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public int Scale { get; set; }
public List<QuoteMessage>? Messages { get; set; }
public string ToJson()
{
return JsonConvert.SerializeObject(this, ChatQuotes.SerializerSettings);
}
}
[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
public class QuoteMessage
{
public List<File>? Media { get; set; }
public QuoteMediaType? MediaType { get; set; }
public long ChatId { get; set; }
public bool Avatar { get; set; } = true;
public User? From { get; set; }
public string? Text { get; set; }
public Message? ReplyMessage { get; set; }
public static QuoteMessage FromMessage(Message msg)
{
var quoteMessage = new QuoteMessage();
if (msg.Text != null)
{
quoteMessage.Text = msg.Text;
}
var sticker = msg.Sticker;
if (sticker != null)
{
var file = new File
{
FileId = sticker.FileId,
FileSize = sticker.FileSize,
FileUniqueId = sticker.FileUniqueId
};
quoteMessage.Media = new List<File> {file};
quoteMessage.MediaType = QuoteMediaType.Sticker;
}
quoteMessage.ChatId = msg.Chat.Id;
quoteMessage.ReplyMessage = msg.ReplyToMessage;
quoteMessage.From = User.FromTgUser(msg.From!);
return quoteMessage;
}
}
public enum QuoteMediaType
{
Sticker = 0
}
+35
View File
@@ -0,0 +1,35 @@
#nullable disable
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace West.TelegramBot.ChatQuotes.Model;
[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
public class QuoteResponse
{
public bool Ok { get; set; }
public Result Result { get; set; }
public static QuoteResponse FromJson(string json)
=> JsonConvert.DeserializeObject<QuoteResponse>(json, ChatQuotes.SerializerSettings);
}
[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
public class Result
{
public string Image { get; set; }
public QuoteType Type { get; set; }
public long Width { get; set; }
public long Height { get; set; }
}
public enum QuoteType
{
Quote = 0,
Image,
Null
}
+22
View File
@@ -0,0 +1,22 @@
using Newtonsoft.Json;
namespace West.TelegramBot.ChatQuotes.Model;
public class User : Telegram.Bot.Types.User
{
[JsonProperty]
public string Name => LastName != null ? $"{FirstName} {LastName}" : FirstName;
public static User FromTgUser(Telegram.Bot.Types.User user)
{
return new User
{
Id = user.Id,
FirstName = user.FirstName,
LastName = user.LastName,
Username = user.Username,
LanguageCode = user.LanguageCode,
IsBot = user.IsBot
};
}
}
@@ -0,0 +1,38 @@
using System.Net.Http.Headers;
using System.Text;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Telegram.Bot.Types;
using West.TelegramBot.ChatQuotes.Model;
namespace West.TelegramBot.ChatQuotes;
public class QuoteGeneratorService
{
private readonly HttpClient _httpClient;
public QuoteGeneratorService(IConfiguration configuration)
{
_httpClient = new HttpClient
{
BaseAddress = new Uri(configuration.GetValue<string>("QuoteApiUrl"))
};
}
public async Task<Stream> GenerateQuoteImage(Message msg)
{
var request = new QuoteRequest(msg);
var content = new ByteArrayContent(Encoding.UTF8.GetBytes(request.ToJson().ToCharArray()))
{
Headers =
{
ContentType = MediaTypeHeaderValue.Parse("application/json")
}
};
var resp = await _httpClient.PostAsync("/generate", content);
var quoteResponse = JsonConvert.DeserializeObject<QuoteResponse>(await resp.Content.ReadAsStringAsync());
return new MemoryStream(Convert.FromBase64String(quoteResponse.Result.Image));
}
}