Skip to content

Commit 9754fa2

Browse files
committed
add summary command
1 parent fa30ab8 commit 9754fa2

File tree

3 files changed

+87
-2
lines changed

3 files changed

+87
-2
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import Foundation
2+
import DiscordBM
3+
4+
struct SummarizeCommand: MessageCommand {
5+
let helpText = "`!summarize`: Fasse einen Link im Reply zusammen."
6+
7+
func run(client: DiscordClient, message: Gateway.MessageCreate) async throws {
8+
guard message.content == "!summarize" else { return }
9+
10+
guard let replyContent = message.referenced_message?.value.content else {
11+
try await client.send(
12+
"Schicke bitte `!summarize` als Reply auf eine Nachricht mit einem Link.",
13+
to: message.channel_id
14+
)
15+
return
16+
}
17+
guard let url = replyContent.firstURL else {
18+
try await client.send(
19+
"In der referenzierten Nachricht sehe ich leider keine URL 🤨",
20+
to: message.channel_id
21+
)
22+
return
23+
}
24+
log.info("Summarizing \(url)")
25+
26+
try await client.setTyping(in: message.channel_id)
27+
28+
guard let encodedURL = url.absoluteString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {
29+
log.error("Unable to URL encode \(url)")
30+
return
31+
}
32+
33+
guard let apiToken = ProcessInfo.processInfo.environment["KAGI_API_TOKEN"] else {
34+
log.error("Necessary env var not found, please set KAGI_API_TOKEN.")
35+
return
36+
}
37+
38+
let response = try await httpClient.get(
39+
"https://kagi.com/api/v0/summarize?target_language=DE&url=\(encodedURL)",
40+
headers: ["Authorization": "Bot \(apiToken)"],
41+
response: KagiResponse.self
42+
)
43+
44+
let summary = response.data.output
45+
46+
guard !summary.isEmpty else {
47+
try await client.send(
48+
"Das kann ich leider nicht zusammenfassen 🫥",
49+
to: message.channel_id
50+
)
51+
return
52+
}
53+
54+
try await client.send(summary, to: message.channel_id)
55+
}
56+
}
57+
58+
private extension String {
59+
var firstURL: URL? {
60+
var foundURL: URL?
61+
let detector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
62+
detector?.enumerateMatches(in: self, options: [], range: .init(location: 0, length: self.utf16.count), using: { (result, _, _) in
63+
if let match = result, let url = match.url {
64+
foundURL = url
65+
}
66+
})
67+
return foundURL
68+
}
69+
}
70+
71+
private struct KagiResponse: Decodable {
72+
let data: ResponseData
73+
74+
struct ResponseData: Decodable {
75+
let output: String
76+
}
77+
}

Sources/SwiftDEBot/Commands.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ let messageCommands: [MessageCommand] = [
66
SwiftEvolutionCommand(),
77
AppleStatusCommand(),
88
SPICommand(),
9+
SummarizeCommand(),
910

1011
CowsCommand(),
1112

Sources/SwiftDEBot/Utils/HTTPClient+get.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,15 @@ import AsyncHTTPClient
22
import Foundation
33

44
extension HTTPClient {
5-
func get<Response>(_ url: String, response: Response.Type) async throws -> Response where Response: Decodable {
6-
let request = HTTPClientRequest(url: url)
5+
func get<Response>(
6+
_ url: String,
7+
headers: [String: String]? = nil,
8+
response: Response.Type
9+
) async throws -> Response where Response: Decodable {
10+
var request = HTTPClientRequest(url: url)
11+
if let headers {
12+
request.headers = .init(headers.map{ ($0.key, $0.value) })
13+
}
714
let response = try await self.execute(request, timeout: .seconds(30))
815
if response.status == .ok {
916
let body = try await response.body.collect(upTo: 50 * 1024 * 1024) // 50 MB

0 commit comments

Comments
 (0)