init
This commit is contained in:
91
Sources/nahi/nahi.swift
Normal file
91
Sources/nahi/nahi.swift
Normal file
@@ -0,0 +1,91 @@
|
||||
// The Swift Programming Language
|
||||
// https://docs.swift.org/swift-book
|
||||
|
||||
import DiscordBM
|
||||
import GeminiKit
|
||||
|
||||
@main
|
||||
struct Nahi {
|
||||
|
||||
static func main() async throws {
|
||||
let bot = await BotGatewayManager(
|
||||
token: try! String(contentsOfFile: "discord_token.txt", encoding: .utf8).trimmingCharacters(in: .whitespacesAndNewlines),
|
||||
presence: .init(activities: [.init(name: "Vibing", type: .competing)], status: .online, afk: false),
|
||||
intents: [.guildMessages, .messageContent]
|
||||
)
|
||||
|
||||
let gemini = GeminiKit(configuration: .init(apiKey: try! String(contentsOfFile: "gemini_token.txt", encoding: .utf8).trimmingCharacters(in: .whitespacesAndNewlines)))
|
||||
|
||||
await withTaskGroup(of: Void.self) { taskGroup in
|
||||
taskGroup.addTask {
|
||||
await bot.connect()
|
||||
}
|
||||
|
||||
taskGroup.addTask {
|
||||
for await event in await bot.events {
|
||||
await EventHandler(event: event, client: bot.client, gemini: gemini).handleAsync()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct EventHandler: GatewayEventHandler {
|
||||
let event: Gateway.Event
|
||||
let client: any DiscordClient
|
||||
let gemini: GeminiKit
|
||||
|
||||
func onMessageCreate(_ payload: Gateway.MessageCreate) async throws {
|
||||
guard !(payload.author?.bot ?? false) else { return }
|
||||
guard payload.mentions.contains(where: { mention in mention.id.rawValue == client.appId!.rawValue }) else { return }
|
||||
_ = try await client.triggerTypingIndicator(channelId: payload.channel_id)
|
||||
|
||||
let streamRes = await Task {
|
||||
return try await gemini.streamGenerateContent(model: .gemini20Flash, prompt: payload.content)
|
||||
}.result
|
||||
|
||||
var message: DiscordChannel.Message?
|
||||
switch (streamRes) {
|
||||
case .success(let stream):
|
||||
var resStr = ""
|
||||
for try await chunk in stream {
|
||||
switch chunk.candidates?.first?.content.parts.first.unsafelyUnwrapped {
|
||||
case .text(let text):
|
||||
resStr.append(text)
|
||||
if resStr.count > 2000 {
|
||||
resStr = text
|
||||
message = nil
|
||||
}
|
||||
default:
|
||||
print("Unknown content type")
|
||||
}
|
||||
if let message = message {
|
||||
try await client.updateMessage(
|
||||
channelId: message.channel_id,
|
||||
messageId: message.id,
|
||||
payload: .init(content: resStr)
|
||||
).guardSuccess()
|
||||
} else {
|
||||
let messageRes = try await client.createMessage(
|
||||
channelId: payload.channel_id,
|
||||
payload: .init(content: resStr)
|
||||
)
|
||||
try messageRes.guardSuccess()
|
||||
message = try messageRes.decode()
|
||||
}
|
||||
if chunk.candidates?.first?.finishReason == nil {
|
||||
_ = try await client.triggerTypingIndicator(channelId: payload.channel_id)
|
||||
} else {
|
||||
let tmpMsg = try await client.createMessage(channelId: payload.channel_id, payload: .init(content: "a")).decode()
|
||||
_ = try await client.deleteMessage(channelId: tmpMsg.channel_id, messageId: tmpMsg.id)
|
||||
|
||||
}
|
||||
}
|
||||
case .failure(let err):
|
||||
try await client.createMessage(
|
||||
channelId: payload.channel_id,
|
||||
payload: .init(content: "\(err.localizedDescription)")
|
||||
).guardSuccess()
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user