diff options
| author | 2025-08-03 12:54:12 +0300 | |
|---|---|---|
| committer | 2025-08-03 12:54:12 +0300 | |
| commit | e5185f65051f881bf61e88542a1acd4957f8383b (patch) | |
| tree | a030a8b32cd13ed6a7d9ed736f8fc626501c2749 | |
| parent | Moved inline bot handling to a new file (diff) | |
| download | ukkobot-e5185f65051f881bf61e88542a1acd4957f8383b.tar.gz ukkobot-e5185f65051f881bf61e88542a1acd4957f8383b.tar.xz ukkobot-e5185f65051f881bf61e88542a1acd4957f8383b.zip | |
Move bot configuration to SQL land
| -rw-r--r-- | .gitignore | 7 | ||||
| -rw-r--r-- | config.default.json | 1 | ||||
| -rw-r--r-- | src/Bot.zig | 9 | ||||
| -rw-r--r-- | src/Config.zig | 1 | ||||
| -rw-r--r-- | src/DB.zig | 100 | ||||
| -rw-r--r-- | src/inline_bots.zig | 60 | ||||
| -rw-r--r-- | src/main.zig | 74 | ||||
| -rw-r--r-- | src/types.zig | 1 | ||||
| -rw-r--r-- | src/types/AnswerCallbackQueryParams.zig | 5 | ||||
| -rw-r--r-- | src/types/InlineKeyboardMarkup.zig | 2 | ||||
| -rw-r--r-- | src/types/SendMessageParams.zig | 4 |
11 files changed, 216 insertions, 48 deletions
| @@ -1,3 +1,4 @@ | |||
| 1 | .zig-cache/ | 1 | /config.json |
| 2 | zig-out/ | 2 | /data.db |
| 3 | config.json \ No newline at end of file | 3 | /.zig-cache/ |
| 4 | /zig-out/ | ||
diff --git a/config.default.json b/config.default.json index 51cdda6..c17bf09 100644 --- a/config.default.json +++ b/config.default.json | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | "_": "Copy this file to `config.json` and modify it there", | 2 | "_": "Copy this file to `config.json` and modify it there", |
| 3 | 3 | ||
| 4 | "bot_token": "123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghi", | 4 | "bot_token": "123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghi", |
| 5 | "db_path": "./data.db", | ||
| 5 | "dev_group": -1001234567890, | 6 | "dev_group": -1001234567890, |
| 6 | "owner": 12345678 | 7 | "owner": 12345678 |
| 7 | } | 8 | } |
diff --git a/src/Bot.zig b/src/Bot.zig index b0eb972..fb91b3f 100644 --- a/src/Bot.zig +++ b/src/Bot.zig | |||
| @@ -6,6 +6,7 @@ const Allocator = std.mem.Allocator; | |||
| 6 | const ArrayList = std.ArrayList; | 6 | const ArrayList = std.ArrayList; |
| 7 | const Bot = @This(); | 7 | const Bot = @This(); |
| 8 | const Config = @import("Config.zig"); | 8 | const Config = @import("Config.zig"); |
| 9 | const DB = @import("DB.zig"); | ||
| 9 | const HttpClient = std.http.Client; | 10 | const HttpClient = std.http.Client; |
| 10 | const HttpMethod = std.http.Method; | 11 | const HttpMethod = std.http.Method; |
| 11 | const Parsed = std.json.Parsed; | 12 | const Parsed = std.json.Parsed; |
| @@ -14,6 +15,7 @@ const Uri = std.Uri; | |||
| 14 | allocator: Allocator, | 15 | allocator: Allocator, |
| 15 | http_client: HttpClient, | 16 | http_client: HttpClient, |
| 16 | config: Config, | 17 | config: Config, |
| 18 | db: *DB, | ||
| 17 | base_uri: Uri = Uri.parse("https://api.telegram.org/") catch unreachable, | 19 | base_uri: Uri = Uri.parse("https://api.telegram.org/") catch unreachable, |
| 18 | uri_path_data: ArrayList(u8), | 20 | uri_path_data: ArrayList(u8), |
| 19 | poweron: bool = true, | 21 | poweron: bool = true, |
| @@ -21,7 +23,7 @@ server_header_buffer: [4096]u8 = undefined, | |||
| 21 | username: ?[]const u8 = null, | 23 | username: ?[]const u8 = null, |
| 22 | id: ?i64 = null, | 24 | id: ?i64 = null, |
| 23 | 25 | ||
| 24 | pub fn init(allocator: Allocator, config: Config) !Bot { | 26 | pub fn init(allocator: Allocator, config: Config, db: *DB) !Bot { |
| 25 | var uri_path_data = try ArrayList(u8).initCapacity(allocator, 5 + config.bot_token.len); | 27 | var uri_path_data = try ArrayList(u8).initCapacity(allocator, 5 + config.bot_token.len); |
| 26 | errdefer uri_path_data.deinit(); | 28 | errdefer uri_path_data.deinit(); |
| 27 | 29 | ||
| @@ -35,6 +37,7 @@ pub fn init(allocator: Allocator, config: Config) !Bot { | |||
| 35 | .allocator = allocator, | 37 | .allocator = allocator, |
| 36 | }, | 38 | }, |
| 37 | .config = config, | 39 | .config = config, |
| 40 | .db = db, | ||
| 38 | .uri_path_data = uri_path_data, | 41 | .uri_path_data = uri_path_data, |
| 39 | }; | 42 | }; |
| 40 | } | 43 | } |
| @@ -47,6 +50,10 @@ pub fn deinit(self: *Bot) void { | |||
| 47 | self.* = undefined; | 50 | self.* = undefined; |
| 48 | } | 51 | } |
| 49 | 52 | ||
| 53 | pub inline fn answerCallbackQuery(self: *Bot, args: types.AnswerCallbackQueryParams) !void { | ||
| 54 | (try self.post(bool, "answerCallbackQuery", args)).deinit(); | ||
| 55 | } | ||
| 56 | |||
| 50 | pub inline fn deleteMessage(self: *Bot, args: types.DeleteMessageParams) !void { | 57 | pub inline fn deleteMessage(self: *Bot, args: types.DeleteMessageParams) !void { |
| 51 | (try self.post(bool, "deleteMessage", args)).deinit(); | 58 | (try self.post(bool, "deleteMessage", args)).deinit(); |
| 52 | } | 59 | } |
diff --git a/src/Config.zig b/src/Config.zig index f9d6dab..2732df3 100644 --- a/src/Config.zig +++ b/src/Config.zig | |||
| @@ -41,6 +41,7 @@ pub const Wrapper = struct { | |||
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | bot_token: []const u8, | 43 | bot_token: []const u8, |
| 44 | db_path: [:0]const u8, | ||
| 44 | dev_group: i64, | 45 | dev_group: i64, |
| 45 | owner: i64, | 46 | owner: i64, |
| 46 | 47 | ||
diff --git a/src/DB.zig b/src/DB.zig new file mode 100644 index 0000000..6510e7c --- /dev/null +++ b/src/DB.zig | |||
| @@ -0,0 +1,100 @@ | |||
| 1 | const sqlite = @import("sqlite"); | ||
| 2 | const std = @import("std"); | ||
| 3 | |||
| 4 | const DB = @This(); | ||
| 5 | |||
| 6 | const target_version = 1; | ||
| 7 | |||
| 8 | sql: sqlite.Db, | ||
| 9 | |||
| 10 | pub const InlineBotType = enum(u32) { | ||
| 11 | blacklisted = 0, | ||
| 12 | whitelisted = 1, | ||
| 13 | }; | ||
| 14 | |||
| 15 | pub fn init(db_path: [:0]const u8) !DB { | ||
| 16 | const sql = try sqlite.Db.init(.{ | ||
| 17 | .mode = .{ .File = db_path }, | ||
| 18 | .open_flags = .{ | ||
| 19 | .write = true, | ||
| 20 | .create = true, | ||
| 21 | }, | ||
| 22 | .threading_mode = .MultiThread, | ||
| 23 | }); | ||
| 24 | |||
| 25 | return DB{ | ||
| 26 | .sql = sql, | ||
| 27 | }; | ||
| 28 | } | ||
| 29 | |||
| 30 | pub fn deinit(self: *DB) void { | ||
| 31 | self.sql.deinit(); | ||
| 32 | } | ||
| 33 | |||
| 34 | pub fn getInlineBotType(self: *DB, id: i64) !?InlineBotType { | ||
| 35 | const row = try self.sql.one(u32, "SELECT type FROM inline_bots WHERE id = ?", .{}, .{ .id = id }); | ||
| 36 | if (row) |r| { | ||
| 37 | return @enumFromInt(r); | ||
| 38 | } | ||
| 39 | return null; | ||
| 40 | } | ||
| 41 | |||
| 42 | pub fn setInlineBotType(self: *DB, id: i64, ty: InlineBotType) !void { | ||
| 43 | try self.sql.exec("INSERT OR REPLACE INTO inline_bots (id, type) VALUES (?, ?)", .{}, .{ id, @intFromEnum(ty) }); | ||
| 44 | } | ||
| 45 | |||
| 46 | pub fn upgrade(self: *DB) !void { | ||
| 47 | try self.sql.exec("CREATE TABLE IF NOT EXISTS version(id INTEGER PRIMARY KEY, version INTEGER)", .{}, .{}); | ||
| 48 | const row = try self.sql.one(struct { version: u32 }, "SELECT version FROM version WHERE id = 0", .{}, .{}); | ||
| 49 | var current_ver: u32 = if (row) |r| r.version else 0; | ||
| 50 | |||
| 51 | if (current_ver == target_version) { | ||
| 52 | std.log.info("Database is up to date", .{}); | ||
| 53 | return; | ||
| 54 | } else if (current_ver > target_version) { | ||
| 55 | std.log.err("Database has a higher version than supported?", .{}); | ||
| 56 | return error.CorruptedDatabase; | ||
| 57 | } | ||
| 58 | |||
| 59 | std.log.info("Updating database from version {} to {}", .{ current_ver, target_version }); | ||
| 60 | |||
| 61 | var setVerStmt = try self.sql.prepare("INSERT OR REPLACE INTO version(id, version) VALUES (0, ?)"); | ||
| 62 | defer setVerStmt.deinit(); | ||
| 63 | |||
| 64 | while (current_ver < target_version) : (current_ver += 1) { | ||
| 65 | std.log.info("Updating database step from {}", .{current_ver}); | ||
| 66 | try self.upgradeStep(current_ver + 1); | ||
| 67 | setVerStmt.reset(); | ||
| 68 | try setVerStmt.exec(.{}, .{ current_ver + 1 }); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | fn upgradeStep(self: *DB, new_version: u32) !void { | ||
| 73 | switch (new_version) { | ||
| 74 | 1 => { | ||
| 75 | try self.sql.exec("DROP TABLE IF EXISTS inline_bots_enum", .{}, .{}); | ||
| 76 | try self.sql.exec( | ||
| 77 | \\CREATE TABLE inline_bots_enum ( | ||
| 78 | \\ id INTEGER PRIMARY KEY, | ||
| 79 | \\ value TEXT UNIQUE | ||
| 80 | \\) | ||
| 81 | , .{}, .{}); | ||
| 82 | try self.sql.exec( | ||
| 83 | \\INSERT INTO inline_bots_enum(id, value) | ||
| 84 | \\VALUES (?, 'blacklisted'), (?, 'whitelisted') | ||
| 85 | , .{}, .{ | ||
| 86 | .blacklisted = @intFromEnum(InlineBotType.blacklisted), | ||
| 87 | .whitelisted = @intFromEnum(InlineBotType.whitelisted), | ||
| 88 | }); | ||
| 89 | |||
| 90 | try self.sql.exec("DROP TABLE IF EXISTS inline_bots", .{}, .{}); | ||
| 91 | try self.sql.exec( | ||
| 92 | \\CREATE TABLE inline_bots ( | ||
| 93 | \\ id INTEGER PRIMARY KEY, | ||
| 94 | \\ type INTEGER REFERENCES inline_bots_enum(id) | ||
| 95 | \\) | ||
| 96 | , .{}, .{}); | ||
| 97 | }, | ||
| 98 | else => unreachable, | ||
| 99 | } | ||
| 100 | } | ||
diff --git a/src/inline_bots.zig b/src/inline_bots.zig index c6fa2b7..29824eb 100644 --- a/src/inline_bots.zig +++ b/src/inline_bots.zig | |||
| @@ -4,44 +4,18 @@ const utils = @import("utils.zig"); | |||
| 4 | 4 | ||
| 5 | const Bot = @import("Bot.zig"); | 5 | const Bot = @import("Bot.zig"); |
| 6 | 6 | ||
| 7 | const whitelist = [_]i64{ | 7 | pub inline fn blacklistBot(bot: *Bot, inline_bot_id: i64) !void { |
| 8 | 90832338, // @vid | 8 | return bot.db.setInlineBotType(inline_bot_id, .blacklisted); |
| 9 | 109158646, // @bing | ||
| 10 | 114528005, // @pic | ||
| 11 | 136269978, // @ImageFetcherBot | ||
| 12 | 140267078, // @gif | ||
| 13 | 154595593, // @wiki | ||
| 14 | 184730458, // @UnitConversionBot | ||
| 15 | 223493268, // @minroobot | ||
| 16 | 296635833, // @lastfmrobot | ||
| 17 | 473587803, // @LyBot | ||
| 18 | 595898211, // @DeezerMusicBot | ||
| 19 | 733460033, // @crabravebot | ||
| 20 | 870410041, // @HowGayBot | ||
| 21 | 7904498194, // @tanstiktokbot | ||
| 22 | }; | ||
| 23 | |||
| 24 | const blacklist = [_]i64{ | ||
| 25 | 6465471545, // @DickGrowerBot | ||
| 26 | 7759097490, // @CookieGrowerBot | ||
| 27 | }; | ||
| 28 | |||
| 29 | comptime { | ||
| 30 | std.testing.expect(utils.isSorted(i64, &whitelist)) catch unreachable; | ||
| 31 | std.testing.expect(utils.isSorted(i64, &blacklist)) catch unreachable; | ||
| 32 | } | 9 | } |
| 33 | 10 | ||
| 34 | inline fn isWhitelisted(bot: types.User) bool { | 11 | pub inline fn whitelistBot(bot: *Bot, inline_bot_id: i64) !void { |
| 35 | return utils.isIn(i64, bot.id, &whitelist); | 12 | return bot.db.setInlineBotType(inline_bot_id, .whitelisted); |
| 36 | } | ||
| 37 | |||
| 38 | inline fn isBlacklisted(bot: types.User) bool { | ||
| 39 | return utils.isIn(i64, bot.id, &blacklist); | ||
| 40 | } | 13 | } |
| 41 | 14 | ||
| 42 | // Returns true if processing of message should continue | 15 | // Returns true if processing of message should continue |
| 43 | pub fn onInlineBot(bot: *Bot, msg: types.Message, via: types.User) !bool { | 16 | pub fn onInlineBot(bot: *Bot, msg: types.Message, via: types.User) !bool { |
| 44 | if (isWhitelisted(via)) { | 17 | const ty = try bot.db.getInlineBotType(via.id); |
| 18 | if (ty == .whitelisted) { | ||
| 45 | return true; | 19 | return true; |
| 46 | } | 20 | } |
| 47 | 21 | ||
| @@ -51,7 +25,7 @@ pub fn onInlineBot(bot: *Bot, msg: types.Message, via: types.User) !bool { | |||
| 51 | .message_id = msg.message_id, | 25 | .message_id = msg.message_id, |
| 52 | }); | 26 | }); |
| 53 | 27 | ||
| 54 | if (!isBlacklisted(via)) { | 28 | if (ty != .blacklisted) { |
| 55 | // Not explicitly blacklisted, notify dev group | 29 | // Not explicitly blacklisted, notify dev group |
| 56 | const text = try std.fmt.allocPrint( | 30 | const text = try std.fmt.allocPrint( |
| 57 | bot.allocator, | 31 | bot.allocator, |
| @@ -60,10 +34,30 @@ pub fn onInlineBot(bot: *Bot, msg: types.Message, via: types.User) !bool { | |||
| 60 | ); | 34 | ); |
| 61 | defer bot.allocator.free(text); | 35 | defer bot.allocator.free(text); |
| 62 | 36 | ||
| 37 | const whitelist_cb = try std.fmt.allocPrint( | ||
| 38 | bot.allocator, | ||
| 39 | "bwl:{}", | ||
| 40 | .{ via.id }, | ||
| 41 | ); | ||
| 42 | defer bot.allocator.free(whitelist_cb); | ||
| 43 | |||
| 44 | const blacklist_cb = try std.fmt.allocPrint( | ||
| 45 | bot.allocator, | ||
| 46 | "bbl:{}", | ||
| 47 | .{ via.id }, | ||
| 48 | ); | ||
| 49 | defer bot.allocator.free(blacklist_cb); | ||
| 50 | |||
| 63 | try bot.sendMessage_(.{ | 51 | try bot.sendMessage_(.{ |
| 64 | .chat_id = bot.config.dev_group, | 52 | .chat_id = bot.config.dev_group, |
| 65 | .text = text, | 53 | .text = text, |
| 66 | .parse_mode = .html, | 54 | .parse_mode = .html, |
| 55 | .reply_markup = .{ | ||
| 56 | .inline_keyboard = &.{&.{ | ||
| 57 | .{ .text = "Whitelist", .callback_data = whitelist_cb }, | ||
| 58 | .{ .text = "Blacklist", .callback_data = blacklist_cb }, | ||
| 59 | }}, | ||
| 60 | }, | ||
| 67 | }); | 61 | }); |
| 68 | } | 62 | } |
| 69 | 63 | ||
diff --git a/src/main.zig b/src/main.zig index 942fd90..5931250 100644 --- a/src/main.zig +++ b/src/main.zig | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | const inline_bots = @import("inline_bots.zig"); | ||
| 1 | const std = @import("std"); | 2 | const std = @import("std"); |
| 2 | const types = @import("types.zig"); | 3 | const types = @import("types.zig"); |
| 3 | const utils = @import("utils.zig"); | 4 | const utils = @import("utils.zig"); |
| @@ -6,10 +7,9 @@ const Allocator = std.mem.Allocator; | |||
| 6 | const ArrayList = std.ArrayList; | 7 | const ArrayList = std.ArrayList; |
| 7 | const Bot = @import("Bot.zig"); | 8 | const Bot = @import("Bot.zig"); |
| 8 | const Config = @import("Config.zig"); | 9 | const Config = @import("Config.zig"); |
| 10 | const DB = @import("DB.zig"); | ||
| 9 | const GPA = std.heap.GeneralPurposeAllocator(.{}); | 11 | const GPA = std.heap.GeneralPurposeAllocator(.{}); |
| 10 | 12 | ||
| 11 | const onInlineBot = @import("inline_bots.zig").onInlineBot; | ||
| 12 | |||
| 13 | pub fn main() !void { | 13 | pub fn main() !void { |
| 14 | defer std.log.info("We're done", .{}); | 14 | defer std.log.info("We're done", .{}); |
| 15 | 15 | ||
| @@ -22,7 +22,11 @@ pub fn main() !void { | |||
| 22 | defer config.deinit(); | 22 | defer config.deinit(); |
| 23 | try config.merge("config.json"); | 23 | try config.merge("config.json"); |
| 24 | 24 | ||
| 25 | var bot = try Bot.init(allocator, config.config); | 25 | var db = try DB.init(config.config.db_path); |
| 26 | defer db.deinit(); | ||
| 27 | try db.upgrade(); | ||
| 28 | |||
| 29 | var bot = try Bot.init(allocator, config.config, &db); | ||
| 26 | defer bot.deinit(); | 30 | defer bot.deinit(); |
| 27 | 31 | ||
| 28 | // TODO: Catch fatal errors, report them | 32 | // TODO: Catch fatal errors, report them |
| @@ -48,15 +52,15 @@ fn loadConfig(allocator: Allocator, filename: []const u8) !std.json.Parsed(Confi | |||
| 48 | ); | 52 | ); |
| 49 | } | 53 | } |
| 50 | 54 | ||
| 51 | fn reportError(bot: *Bot, msg: types.Message, err: anyerror) !void { | 55 | fn reportError(bot: *Bot, evt: anytype, err: anyerror) !void { |
| 52 | std.log.err("While handling {}: {}", .{ msg, err }); | 56 | std.log.err("While handling {}: {}", .{ evt, err }); |
| 53 | const msgStr = try std.json.stringifyAlloc(bot.allocator, msg, .{ | 57 | const evtStr = try std.json.stringifyAlloc(bot.allocator, evt, .{ |
| 54 | .whitespace = .indent_2, | 58 | .whitespace = .indent_2, |
| 55 | .emit_null_optional_fields = false, | 59 | .emit_null_optional_fields = false, |
| 56 | }); | 60 | }); |
| 57 | defer bot.allocator.free(msgStr); | 61 | defer bot.allocator.free(evtStr); |
| 58 | 62 | ||
| 59 | const devMsg = try std.fmt.allocPrint(bot.allocator, "<code>{}</code> while handling\n<pre>{s}</pre>", .{ err, msgStr }); | 63 | const devMsg = try std.fmt.allocPrint(bot.allocator, "<code>{}</code> while handling\n<pre>{s}</pre>", .{ err, evtStr }); |
| 60 | defer bot.allocator.free(devMsg); | 64 | defer bot.allocator.free(devMsg); |
| 61 | 65 | ||
| 62 | bot.sendMessage_(.{ | 66 | bot.sendMessage_(.{ |
| @@ -90,6 +94,12 @@ fn wrappedMain(bot: *Bot) !void { | |||
| 90 | try reportError(bot, message, err); | 94 | try reportError(bot, message, err); |
| 91 | }; | 95 | }; |
| 92 | } | 96 | } |
| 97 | |||
| 98 | if (update.callback_query) |cb| { | ||
| 99 | onCallbackQuery(bot, cb) catch |err| { | ||
| 100 | try reportError(bot, cb, err); | ||
| 101 | }; | ||
| 102 | } | ||
| 93 | } | 103 | } |
| 94 | } | 104 | } |
| 95 | 105 | ||
| @@ -104,9 +114,55 @@ fn wrappedMain(bot: *Bot) !void { | |||
| 104 | }); | 114 | }); |
| 105 | } | 115 | } |
| 106 | 116 | ||
| 117 | fn onCallbackQuery(bot: *Bot, cb: types.CallbackQuery) !void { | ||
| 118 | if (cb.data) |cb_data| blk: { | ||
| 119 | if (std.mem.startsWith(u8, cb_data, "bbl:")) { | ||
| 120 | if (cb.from.id != bot.config.owner) { | ||
| 121 | break :blk; | ||
| 122 | } | ||
| 123 | |||
| 124 | const inline_bot_id = try std.fmt.parseInt(i64, cb_data[4..], 10); | ||
| 125 | try inline_bots.blacklistBot(bot, inline_bot_id); | ||
| 126 | if (cb.message) |msg| { | ||
| 127 | try bot.deleteMessage(.{ | ||
| 128 | .chat_id = msg.chat.id, | ||
| 129 | .message_id = msg.message_id, | ||
| 130 | }); | ||
| 131 | } | ||
| 132 | } else if (std.mem.startsWith(u8, cb_data, "bwl:")) { | ||
| 133 | if (cb.from.id != bot.config.owner) { | ||
| 134 | break :blk; | ||
| 135 | } | ||
| 136 | |||
| 137 | const inline_bot_id = try std.fmt.parseInt(i64, cb_data[4..], 10); | ||
| 138 | try inline_bots.whitelistBot(bot, inline_bot_id); | ||
| 139 | if (cb.message) |msg| { | ||
| 140 | try bot.deleteMessage(.{ | ||
| 141 | .chat_id = msg.chat.id, | ||
| 142 | .message_id = msg.message_id, | ||
| 143 | }); | ||
| 144 | } | ||
| 145 | } else { | ||
| 146 | break :blk; | ||
| 147 | } | ||
| 148 | |||
| 149 | return bot.answerCallbackQuery(.{ | ||
| 150 | .callback_query_id = cb.id, | ||
| 151 | .text = "OK", | ||
| 152 | }); | ||
| 153 | } | ||
| 154 | |||
| 155 | std.log.info("Unrecognised callback query data: {?s}", .{ cb.data }); | ||
| 156 | return bot.answerCallbackQuery(.{ | ||
| 157 | .callback_query_id = cb.id, | ||
| 158 | .text = "Unallowed callback query, don't press the button again", | ||
| 159 | .show_alert = true, | ||
| 160 | }); | ||
| 161 | } | ||
| 162 | |||
| 107 | fn onMessage(bot: *Bot, msg: types.Message) !void { | 163 | fn onMessage(bot: *Bot, msg: types.Message) !void { |
| 108 | if (msg.via_bot) |via| { | 164 | if (msg.via_bot) |via| { |
| 109 | if (!try onInlineBot(bot, msg, via)) { | 165 | if (!try inline_bots.onInlineBot(bot, msg, via)) { |
| 110 | return; | 166 | return; |
| 111 | } | 167 | } |
| 112 | } | 168 | } |
diff --git a/src/types.zig b/src/types.zig index b99d24e..d203652 100644 --- a/src/types.zig +++ b/src/types.zig | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | pub const Animation = @import("types/Animation.zig"); | 1 | pub const Animation = @import("types/Animation.zig"); |
| 2 | pub const AnswerCallbackQueryParams = @import("types/AnswerCallbackQueryParams.zig"); | ||
| 2 | pub const Audio = @import("types/Audio.zig"); | 3 | pub const Audio = @import("types/Audio.zig"); |
| 3 | pub const BackgroundFill = @import("types/background_fill.zig").BackgroundFill; | 4 | pub const BackgroundFill = @import("types/background_fill.zig").BackgroundFill; |
| 4 | pub const BackgroundType = @import("types/background_type.zig").BackgroundType; | 5 | pub const BackgroundType = @import("types/background_type.zig").BackgroundType; |
diff --git a/src/types/AnswerCallbackQueryParams.zig b/src/types/AnswerCallbackQueryParams.zig new file mode 100644 index 0000000..875cec1 --- /dev/null +++ b/src/types/AnswerCallbackQueryParams.zig | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | callback_query_id: []const u8, | ||
| 2 | text: ?[]const u8 = null, | ||
| 3 | show_alert: bool = false, | ||
| 4 | url: ?[]const u8 = null, | ||
| 5 | cache_time: u64 = 0, | ||
diff --git a/src/types/InlineKeyboardMarkup.zig b/src/types/InlineKeyboardMarkup.zig index 388d4fc..a246851 100644 --- a/src/types/InlineKeyboardMarkup.zig +++ b/src/types/InlineKeyboardMarkup.zig | |||
| @@ -1,3 +1,3 @@ | |||
| 1 | const InlineKeyboardButton = @import("InlineKeyboardButton.zig"); | 1 | const InlineKeyboardButton = @import("InlineKeyboardButton.zig"); |
| 2 | 2 | ||
| 3 | inline_keyboard: [][]InlineKeyboardButton, | 3 | inline_keyboard: []const []const InlineKeyboardButton, |
diff --git a/src/types/SendMessageParams.zig b/src/types/SendMessageParams.zig index 8c84940..587055c 100644 --- a/src/types/SendMessageParams.zig +++ b/src/types/SendMessageParams.zig | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | const InlineKeyboardMarkup = @import("InlineKeyboardMarkup.zig"); | ||
| 1 | const LinkPreviewOptions = @import("LinkPreviewOptions.zig"); | 2 | const LinkPreviewOptions = @import("LinkPreviewOptions.zig"); |
| 2 | const MessageEntity = @import("MessageEntity.zig"); | 3 | const MessageEntity = @import("MessageEntity.zig"); |
| 3 | const ParseMode = @import("parse_mode.zig").ParseMode; | 4 | const ParseMode = @import("parse_mode.zig").ParseMode; |
| @@ -15,4 +16,5 @@ disable_notification: ?bool = null, | |||
| 15 | protect_content: ?bool = null, | 16 | protect_content: ?bool = null, |
| 16 | message_effect_id: ?[]const u8 = null, | 17 | message_effect_id: ?[]const u8 = null, |
| 17 | reply_parameters: ?ReplyParameters = null, | 18 | reply_parameters: ?ReplyParameters = null, |
| 18 | // TODO: reply_markup: InlineKeyboardMarkup OR ReplyKeyboardMarkup OR ReplyKeyboardRemove OR ForceReply | 19 | // TODO: InlineKeyboardMarkup OR ReplyKeyboardMarkup OR ReplyKeyboardRemove OR ForceReply |
| 20 | reply_markup: ?InlineKeyboardMarkup = null, | ||