summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Uko Kokņevičs2024-08-29 20:41:04 +0800
committerGravatar Uko Kokņevičs2024-08-29 20:41:04 +0800
commit34b7dc964b3516457f04d00d3ec910d3b6fd585b (patch)
tree7a0a44ce334cc1411952cdbde056b7b57720f06e /src
parentDo some extra user input validation (diff)
downloadukkobot-34b7dc964b3516457f04d00d3ec910d3b6fd585b.tar.gz
ukkobot-34b7dc964b3516457f04d00d3ec910d3b6fd585b.tar.xz
ukkobot-34b7dc964b3516457f04d00d3ec910d3b6fd585b.zip
thank you Q&A, now theres proper unicode support n shit
Diffstat (limited to 'src')
-rw-r--r--src/main.zig50
-rw-r--r--src/utils.zig55
2 files changed, 85 insertions, 20 deletions
diff --git a/src/main.zig b/src/main.zig
index 544b105..2e33cfc 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -199,22 +199,29 @@ fn onTextMessage(bot: *Bot, msg: types.Message, text: []const u8) !void {
199 }, 199 },
200 }); 200 });
201 } else if (std.ascii.startsWithIgnoreCase(text, "big ")) { 201 } else if (std.ascii.startsWithIgnoreCase(text, "big ")) {
202 var output = ArrayList(u8).init(bot.allocator); 202 const trimmed = try utils.trim(text[4..]);
203 defer output.deinit(); 203 const cd = try utils.getCD();
204 if (trimmed.len > 0) {
205 const uppercased = try cd.toUpperStr(bot.allocator, trimmed);
206 defer bot.allocator.free(uppercased);
204 207
205 try output.appendSlice("<b>"); 208 var output = ArrayList(u8).init(bot.allocator);
206 try utils.escapeXml(output.writer(), text[4..]); 209 defer output.deinit();
207 try output.appendSlice("</b>");
208 210
209 try bot.sendMessage_(.{ 211 try output.appendSlice("<b>");
210 .chat_id = msg.chat.id, 212 try utils.escapeXml(output.writer(), uppercased);
211 .text = output.items, 213 try output.appendSlice("</b>");
212 .parse_mode = .html, 214
213 .reply_parameters = .{ 215 try bot.sendMessage_(.{
214 .message_id = msg.message_id,
215 .chat_id = msg.chat.id, 216 .chat_id = msg.chat.id,
216 }, 217 .text = output.items,
217 }); 218 .parse_mode = .html,
219 .reply_parameters = .{
220 .message_id = msg.message_id,
221 .chat_id = msg.chat.id,
222 },
223 });
224 }
218 } else if (std.ascii.eqlIgnoreCase(text, "forgor")) { 225 } else if (std.ascii.eqlIgnoreCase(text, "forgor")) {
219 try bot.sendMessage_(.{ 226 try bot.sendMessage_(.{
220 .chat_id = msg.chat.id, 227 .chat_id = msg.chat.id,
@@ -244,14 +251,17 @@ fn onTextMessage(bot: *Bot, msg: types.Message, text: []const u8) !void {
244 }, 251 },
245 }); 252 });
246 } else if (std.ascii.startsWithIgnoreCase(text, "say ")) { 253 } else if (std.ascii.startsWithIgnoreCase(text, "say ")) {
247 try bot.sendMessage_(.{ 254 const trimmed = try utils.trim(text[4..]);
248 .chat_id = msg.chat.id, 255 if (trimmed.len > 0) {
249 .text = text[4..], 256 try bot.sendMessage_(.{
250 .reply_parameters = .{
251 .message_id = msg.message_id,
252 .chat_id = msg.chat.id, 257 .chat_id = msg.chat.id,
253 }, 258 .text = trimmed,
254 }); 259 .reply_parameters = .{
260 .message_id = msg.message_id,
261 .chat_id = msg.chat.id,
262 },
263 });
264 }
255 } else if (std.ascii.eqlIgnoreCase(text, "uwu")) { 265 } else if (std.ascii.eqlIgnoreCase(text, "uwu")) {
256 try bot.sendMessage_(.{ 266 try bot.sendMessage_(.{
257 .chat_id = msg.chat.id, 267 .chat_id = msg.chat.id,
diff --git a/src/utils.zig b/src/utils.zig
index c6e8508..631e464 100644
--- a/src/utils.zig
+++ b/src/utils.zig
@@ -2,6 +2,9 @@ const std = @import("std");
2 2
3const Allocator = std.mem.Allocator; 3const Allocator = std.mem.Allocator;
4const ArrayList = std.ArrayList; 4const ArrayList = std.ArrayList;
5const CaseData = @import("CaseData");
6const GenCatData = @import("GenCatData");
7const Utf8View = std.unicode.Utf8View;
5 8
6pub fn escapeXml(writer: anytype, text: []const u8) !void { 9pub fn escapeXml(writer: anytype, text: []const u8) !void {
7 for (text) |ch| { 10 for (text) |ch| {
@@ -15,6 +18,26 @@ pub fn escapeXml(writer: anytype, text: []const u8) !void {
15 } 18 }
16} 19}
17 20
21var gcd_global: ?GenCatData = null;
22
23pub fn getGCD() !GenCatData {
24 if (gcd_global) |gcd| {
25 return gcd;
26 }
27 gcd_global = try GenCatData.init(std.heap.page_allocator);
28 return gcd_global.?;
29}
30
31var cd_global: ?CaseData = null;
32
33pub fn getCD() !CaseData {
34 if (cd_global) |cd| {
35 return cd;
36 }
37 cd_global = try CaseData.init(std.heap.page_allocator);
38 return cd_global.?;
39}
40
18pub inline fn isNull(value: anytype) bool { 41pub inline fn isNull(value: anytype) bool {
19 return switch (@typeInfo(@TypeOf(value))) { 42 return switch (@typeInfo(@TypeOf(value))) {
20 .Null => true, 43 .Null => true,
@@ -22,3 +45,35 @@ pub inline fn isNull(value: anytype) bool {
22 else => false, 45 else => false,
23 }; 46 };
24} 47}
48
49pub fn trim(str: []const u8) ![]const u8 {
50 const view = try Utf8View.init(str);
51 const gcd = try getGCD();
52
53 var it = view.iterator();
54 var idx: usize = 0;
55 const first = while (it.nextCodepoint()) |cp| {
56 if (!isTrimmable(gcd, cp)) {
57 break idx;
58 }
59 idx = it.i;
60 } else {
61 return "";
62 };
63
64 idx = it.i;
65
66 var last = first;
67 while (it.nextCodepoint()) |cp| {
68 if (!isTrimmable(gcd, cp)) {
69 last = idx + (std.unicode.utf8CodepointSequenceLength(cp) catch unreachable) - 1;
70 }
71 idx = it.i;
72 }
73
74 return str[first .. last + 1];
75}
76
77inline fn isTrimmable(gcd: GenCatData, cp: u21) bool {
78 return gcd.isSeparator(cp) or gcd.isControl(cp);
79}