diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 0000000..b14c36b --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,2 @@ +identifier_name: + min_length: 1 diff --git a/Package.resolved b/Package.resolved index 69bae57..bc92c75 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "5b140fcd6a36165fb4c1302609ef5353bacb59ce0f82996aa0cf66ee021cbb17", + "originHash" : "3b48af7783bd7fc90049cfb326f7fac3c85fa65bc3afc5b3c1e0444e5e3fe3ac", "pins" : [ { "identity" : "async-http-client", @@ -28,6 +28,15 @@ "version" : "4.15.0" } }, + { + "identity" : "grdb.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/groue/GRDB.swift.git", + "state" : { + "revision" : "2cf6c756e1e5ef6901ebae16576a7e4e4b834622", + "version" : "6.29.3" + } + }, { "identity" : "multipart-kit", "kind" : "remoteSourceControl", diff --git a/Package.swift b/Package.swift index 7cc2feb..8afa7b0 100644 --- a/Package.swift +++ b/Package.swift @@ -4,16 +4,19 @@ import PackageDescription var packageDependencies: [Package.Dependency] = [ - .package(url: "https://github.com/vapor/vapor.git", .upToNextMajor(from: "4.57.0")) + .package(url: "https://github.com/nerzh/swift-telegram-sdk", .upToNextMajor(from: "3.0.3")), + .package(url: "https://github.com/vapor/vapor.git", .upToNextMajor(from: "4.57.0")), + .package(url: "https://github.com/apple/swift-crypto.git", .upToNextMajor(from: "3.0.0")), + .package(url: "https://github.com/groue/GRDB.swift.git", .upToNextMajor(from: "6.0.0")) ] var targetDependencies: [PackageDescription.Target.Dependency] = [ - .product(name: "Vapor", package: "vapor") + .product(name: "Vapor", package: "vapor"), + .product(name: "SwiftTelegramSdk", package: "swift-telegram-sdk"), + .product(name: "Crypto", package: "swift-crypto"), + .product(name: "GRDB", package: "GRDB.swift") ] -packageDependencies.append(.package(url: "https://github.com/nerzh/swift-telegram-sdk", .upToNextMajor(from: "3.0.3"))) -targetDependencies.append(.product(name: "SwiftTelegramSdk", package: "swift-telegram-sdk")) - let package = Package( name: "TelegramModeratorBot", dependencies: packageDependencies, diff --git a/Sources/TelegramModeratorBot/Database.swift b/Sources/TelegramModeratorBot/Database.swift new file mode 100644 index 0000000..d23fa47 --- /dev/null +++ b/Sources/TelegramModeratorBot/Database.swift @@ -0,0 +1,53 @@ +import GRDB + +struct User: Codable, FetchableRecord, PersistableRecord { + var userId: String + var publicKey: String + var isSpammer: Bool +} + +final class Database: Sendable { + + private var dbWriter: any DatabaseWriter + + init(_ dbWriter: any GRDB.DatabaseWriter) throws { + self.dbWriter = dbWriter + try migrator.migrate(dbWriter) + } + + let dbQueue = try DatabaseQueue(path: "./db.sqlite") + + let db = try Connection("./db.sqlite") + +#if DEBUG + // Speed up development by nuking the database when migrations change + // See + migrator.eraseDatabaseOnSchemaChange = true +#endif + private var migrator: DatabaseMigrator { + var migrator = DatabaseMigrator() + migrator.registerMigration("v1") { db in + try db.create(table: "users", { t in + t.primaryKey("userId", .text).NotNull() + t.column("publicKey", .text).NotNull() + t.column("isSpammer", .bool) + }) + return migrator + } + } +} + +extension Database { + static func makeConfiguration(_ base: Configuration = Configuration()) -> Configuration { + var config = base + return config + } +} + +extension Database { + func saveUser(_ userId: String, _ publicKey: String, _ isSpammer: Bool) throws { + try dbWriter.write { db in + try User.init(userId: userId, publicKey: publicKey, isSpammer: isSpammer).insert(db) + } + } +} diff --git a/Sources/TelegramModeratorBot/DefaultBotHandlers.swift b/Sources/TelegramModeratorBot/DefaultBotHandlers.swift index f2b359e..3e28477 100644 --- a/Sources/TelegramModeratorBot/DefaultBotHandlers.swift +++ b/Sources/TelegramModeratorBot/DefaultBotHandlers.swift @@ -1,18 +1,42 @@ import Vapor +import Crypto @preconcurrency import SwiftTelegramSdk final class DefaultBotHandlers { - static func addHandlers() async { - await defaultBaseHandler() + static func addHandlers(_ bot: TGBot) async { + await defaultBaseHandler(bot) } - private static func defaultBaseHandler() async { + private static func defaultBaseHandler(_ bot: TGBot) async { await botActor.bot.dispatcher.add(TGBaseHandler({ update in guard let message = update.message else { return } let params: TGSendMessageParams = .init(chatId: .chat(message.chat.id), text: """ Help message """) - try await botActor.bot.sendMessage(params: params) + try await bot.sendMessage(params: params) })) } + + private static func sendButtonOfAuth(_ bot: TGBot) async throws { + await bot.dispatcher.add(TGCallbackQueryHandler(pattern: "Subscribe", { update in + bot.log.info("press") + let userId = update.callbackQuery!.from.id + + let arrayBytesOfId = withUnsafeBytes(of: userId, Array.init) + let hashedUserIdDigest = SHA512.hash(Data(arrayBytesOfId)) + // Convert Digest to hex string + let hashedUserId = Data(hashedUserIdDigest).map { String(format: "%02x", $0) }.joined() + + try? Database.saveUser(hashedUserId, "", false) + + let params: TGAnswerCallbackQueryParams = .init( + callbackQueryId: update.callbackQuery?.id ?? "0", + text: update.callbackQuery?.data ?? "data not exit", + showAlert: nil, + url: nil, + cacheTime: nil + ) + try await bot.answerCallbackQuery(params: params) + })) + } } diff --git a/Sources/TelegramModeratorBot/configure.swift b/Sources/TelegramModeratorBot/configure.swift index cf13f47..ceeed09 100644 --- a/Sources/TelegramModeratorBot/configure.swift +++ b/Sources/TelegramModeratorBot/configure.swift @@ -3,7 +3,9 @@ import Vapor @preconcurrency import SwiftTelegramSdk public func configure(_ app: Application) async throws { - guard let tgApi: String = Environment.get("TG_BOT_API") else { throw Errors.notVariable("Telegram key is not defined")} + guard let tgApi: String = Environment.get("TG_BOT_API") else { + throw Errors.notVariable("Telegram key is not defined") + } app.logger.logLevel = .debug let bot: TGBot = try await .init(connectionType: .longpolling(limit: nil, timeout: nil, @@ -14,7 +16,7 @@ public func configure(_ app: Application) async throws { botId: tgApi, log: app.logger) await botActor.setBot(bot) - await DefaultBotHandlers.addHandlers() + await DefaultBotHandlers.addHandlers(bot) try await botActor.bot.start() // try routes(app) } diff --git a/Sources/TelegramModeratorBot/errors.swift b/Sources/TelegramModeratorBot/errors.swift index 74146bd..2224b17 100644 --- a/Sources/TelegramModeratorBot/errors.swift +++ b/Sources/TelegramModeratorBot/errors.swift @@ -1,3 +1,4 @@ enum Errors: Error { case notVariable(String) + case `default`(String) }