remove DiscordBM dependency

This commit is contained in:
2026-03-17 06:33:26 -04:00
parent c6b92d968a
commit 29a2b0370b
9 changed files with 361 additions and 370 deletions

View File

@@ -1,107 +1,107 @@
import DiscordBM
struct Actions {
static func getUserFromMention(_ mention: MentionUser) -> String {
mention.member?.nick ?? mention.global_name ?? mention.username
}
static func performAction(ctx: Gateway.MessageCreate, client: DiscordClient, resOpts: [String]) async throws {
let author = "**\(ctx.member?.nick ?? ctx.author?.global_name ?? ctx.author?.username ?? "Zundamon")**"
let dests = ctx.mentions.map(getUserFromMention).map({ "**\($0)**" })
let orig: String
let dest: String
if let firstDest = dests.first {
orig = "\(author)"
dest = "\(firstDest)"
} else {
orig = "**Zundamon**"
dest = "\(author)"
}
guard let res = resOpts.randomElement()?
.replacingOccurrences(of: "{orig}", with: orig)
.replacingOccurrences(of: "{dest}", with: dest)
else { print("retOptions empty"); return }
let retMsg = res
try await client.createMessage(
channelId: ctx.channel_id,
payload: .init(
embeds: [.init(description: retMsg)],
)
).guardSuccess()
}
static let hugRes = (try? String(contentsOfFile: "resources/choices/hug.txt", encoding: .utf8))?
.split(separator: "\n")
.map({ $0.trimmingCharacters(in: .whitespacesAndNewlines) })
static func hug(
_ args: ArraySlice<String.SubSequence>,
client: DiscordClient,
ctx: Gateway.MessageCreate
) async throws {
guard let hugRes = hugRes else { print("hug.txt not loaded"); return }
let author = "**\(ctx.member?.nick ?? ctx.author?.global_name ?? ctx.author?.username ?? "Zundamon")**"
let dests = ctx.mentions.map(getUserFromMention).map({ "**\($0)**" })
let retMsg: String
if dests.count > 1 {
let groupHugs = [
"{subjects} all huddled together.",
"{subjects} hugged each other pairwise, generating a total of **{total}** hugs.",
"{subjects} hugged each other at the same time in the same place (although I'm not sure how that works with the current understanding of spacetime).",
]
let group = [author] + dests
let total = String(group.count)
let subjects = String(group.joined(by: ", "))
guard let res = groupHugs.randomElement()?
.replacingOccurrences(of: "{subjects}", with: subjects)
.replacingOccurrences(of: "{total}", with: total)
else { print("groupHugs.randomElement() returned null"); return }
retMsg = res
} else {
let orig: String
let dest: String
if let firstDest = dests.first {
orig = "\(author)"
dest = "\(firstDest)"
} else {
orig = "**Zundamon**"
dest = "\(author)"
}
guard let res = hugRes.randomElement()?
.replacingOccurrences(of: "{orig}", with: orig)
.replacingOccurrences(of: "{dest}", with: dest)
else { print("hug.txt empty"); return }
retMsg = res
}
try await client.createMessage(
channelId: ctx.channel_id,
payload: .init(
embeds: [.init(description: retMsg)],
)
).guardSuccess()
}
static let patRes = (try? String(contentsOfFile: "resources/choices/pat.txt", encoding: .utf8))?
.split(separator: "\n")
.map({ $0.trimmingCharacters(in: .whitespacesAndNewlines) })
static func pat(
_ args: ArraySlice<String.SubSequence>,
client: DiscordClient,
ctx: Gateway.MessageCreate
) async throws {
guard let patRes = patRes else { print("pat.txt not loaded"); return }
try await performAction(ctx: ctx, client: client, resOpts: patRes)
}
}
// import DiscordBM
//
// struct Actions {
// static func getUserFromMention(_ mention: MentionUser) -> String {
// mention.member?.nick ?? mention.global_name ?? mention.username
// }
//
// static func performAction(ctx: Gateway.MessageCreate, client: DiscordClient, resOpts: [String]) async throws {
// let author = "**\(ctx.member?.nick ?? ctx.author?.global_name ?? ctx.author?.username ?? "Zundamon")**"
// let dests = ctx.mentions.map(getUserFromMention).map({ "**\($0)**" })
// let orig: String
// let dest: String
// if let firstDest = dests.first {
// orig = "\(author)"
// dest = "\(firstDest)"
// } else {
// orig = "**Zundamon**"
// dest = "\(author)"
// }
//
// guard let res = resOpts.randomElement()?
// .replacingOccurrences(of: "{orig}", with: orig)
// .replacingOccurrences(of: "{dest}", with: dest)
// else { print("retOptions empty"); return }
//
// let retMsg = res
//
// try await client.createMessage(
// channelId: ctx.channel_id,
// payload: .init(
// embeds: [.init(description: retMsg)],
// )
// ).guardSuccess()
// }
//
// static let hugRes = (try? String(contentsOfFile: "resources/choices/hug.txt", encoding: .utf8))?
// .split(separator: "\n")
// .map({ $0.trimmingCharacters(in: .whitespacesAndNewlines) })
//
// static func hug(
// _ args: ArraySlice<String.SubSequence>,
// client: DiscordClient,
// ctx: Gateway.MessageCreate
// ) async throws {
// guard let hugRes = hugRes else { print("hug.txt not loaded"); return }
// let author = "**\(ctx.member?.nick ?? ctx.author?.global_name ?? ctx.author?.username ?? "Zundamon")**"
// let dests = ctx.mentions.map(getUserFromMention).map({ "**\($0)**" })
//
// let retMsg: String
//
// if dests.count > 1 {
// let groupHugs = [
// "{subjects} all huddled together.",
// "{subjects} hugged each other pairwise, generating a total of **{total}** hugs.",
// "{subjects} hugged each other at the same time in the same place (although I'm not sure how that works with the current understanding of spacetime).",
// ]
//
// let group = [author] + dests
// let total = String(group.count)
// let subjects = String(group.joined(by: ", "))
//
// guard let res = groupHugs.randomElement()?
// .replacingOccurrences(of: "{subjects}", with: subjects)
// .replacingOccurrences(of: "{total}", with: total)
// else { print("groupHugs.randomElement() returned null"); return }
//
// retMsg = res
// } else {
// let orig: String
// let dest: String
// if let firstDest = dests.first {
// orig = "\(author)"
// dest = "\(firstDest)"
// } else {
// orig = "**Zundamon**"
// dest = "\(author)"
// }
//
// guard let res = hugRes.randomElement()?
// .replacingOccurrences(of: "{orig}", with: orig)
// .replacingOccurrences(of: "{dest}", with: dest)
// else { print("hug.txt empty"); return }
//
// retMsg = res
// }
//
// try await client.createMessage(
// channelId: ctx.channel_id,
// payload: .init(
// embeds: [.init(description: retMsg)],
// )
// ).guardSuccess()
// }
//
// static let patRes = (try? String(contentsOfFile: "resources/choices/pat.txt", encoding: .utf8))?
// .split(separator: "\n")
// .map({ $0.trimmingCharacters(in: .whitespacesAndNewlines) })
//
// static func pat(
// _ args: ArraySlice<String.SubSequence>,
// client: DiscordClient,
// ctx: Gateway.MessageCreate
// ) async throws {
// guard let patRes = patRes else { print("pat.txt not loaded"); return }
// try await performAction(ctx: ctx, client: client, resOpts: patRes)
// }
// }

View File

@@ -1,116 +1,116 @@
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
import DiscordBM
struct MessageHandler {
let ctx: Gateway.MessageCreate
let client: any DiscordClient
static let prefix = ":"
static let zundaGifData = try? Data(contentsOf: URL(filePath: "resources/media/zundamone.gif"))
func handle() async throws {
guard !(ctx.author?.bot ?? false) else { return }
if (ctx.content.hasPrefix(MessageHandler.prefix)) {
let split = ctx.content.split(separator: " ")
let command = split.first?.trimmingPrefix(MessageHandler.prefix)
let args = split[1...]
switch command {
case "wow": try await handleWow(args)
case "domath": try await Wolfram.handleMath(args, client: client, ctx: ctx)
case "hug": try await Actions.hug(args, client: client, ctx: ctx)
case "pat": try await Actions.pat(args, client: client, ctx: ctx)
case "pet": try await Actions.pat(args, client: client, ctx: ctx)
default: break
}
} else if ctx.mentions.contains(where: { $0.id == Zundamon.ownID }) {
if ctx.content
.replacingOccurrences(of: "<@\(Zundamon.ownID!.rawValue)>", with: "")
.trimmingCharacters(in: .whitespacesAndNewlines)
.count == 0,
let zundaGif = MessageHandler.zundaGifData
{
try await client.createMessage(
channelId: ctx.channel_id,
payload: .init(
message_reference: .init(
type: .default,
message_id: ctx.id,
channel_id: ctx.channel_id,
guild_id: ctx.guild_id,
),
files: [.init(data: .init(data: zundaGif), filename: "zundamone.gif")],
attachments: [.init(index: 0, filename: "zundamone.gif")],
)
).guardSuccess()
} else {
try await handle8Ball()
}
}
}
static let ballResponses = [
"It is certain.",
"It is decidedly so.",
"Without a doubt.",
"Yes definitely.",
"You may rely on it.",
"As I see it, yes.",
"Most likely.",
"Outlook good.",
"Yes.",
"Signs point to yes.",
"Reply hazy, try again.",
"Ask again later.",
"Better not tell you now.",
"Cannot predict now.",
"Concentrate and ask again.",
"Dont count on it.",
"My reply is no.",
"My sources say no.",
"Outlook not so good.",
"Very doubtful.",
"Ui beam",
"We are Shigure Ui",
"We are Shigure Ux",
]
func handle8Ball() async throws {
try await client.createMessage(
channelId: ctx.channel_id,
payload: .init(
content: MessageHandler.ballResponses.randomElement(),
message_reference: .init(
type: .default,
message_id: ctx.id,
channel_id: ctx.channel_id,
guild_id: ctx.guild_id,
),
)
).guardSuccess()
}
static let wows = [
"<:wow:1477062414913634334>",
"<:wow2:1477062432357875948>",
"<:wow4:1477062471746588713>",
"<:wow5:1477062452804849845>"
]
func handleWow(_ args: ArraySlice<String.SubSequence>) async throws {
try await client.createMessage(
channelId: ctx.channel_id,
payload: .init(
content: MessageHandler.wows.randomElement(),
message_reference: .init(
type: .default,
message_id: ctx.id,
channel_id: ctx.channel_id,
guild_id: ctx.guild_id,
),
)
).guardSuccess()
}
}
// import Foundation
// #if canImport(FoundationNetworking)
// import FoundationNetworking
// #endif
// import DiscordBM
//
// struct MessageHandler {
// let ctx: Gateway.MessageCreate
// let client: any DiscordClient
//
// static let prefix = ":"
// static let zundaGifData = try? Data(contentsOf: URL(filePath: "resources/media/zundamone.gif"))
//
// func handle() async throws {
// guard !(ctx.author?.bot ?? false) else { return }
// if (ctx.content.hasPrefix(MessageHandler.prefix)) {
// let split = ctx.content.split(separator: " ")
// let command = split.first?.trimmingPrefix(MessageHandler.prefix)
// let args = split[1...]
//
// switch command {
// case "wow": try await handleWow(args)
// case "domath": try await Wolfram.handleMath(args, client: client, ctx: ctx)
// case "hug": try await Actions.hug(args, client: client, ctx: ctx)
// case "pat": try await Actions.pat(args, client: client, ctx: ctx)
// case "pet": try await Actions.pat(args, client: client, ctx: ctx)
// default: break
// }
// } else if ctx.mentions.contains(where: { $0.id == Zundamon.ownID }) {
// if ctx.content
// .replacingOccurrences(of: "<@\(Zundamon.ownID!.rawValue)>", with: "")
// .trimmingCharacters(in: .whitespacesAndNewlines)
// .count == 0,
// let zundaGif = MessageHandler.zundaGifData
// {
// try await client.createMessage(
// channelId: ctx.channel_id,
// payload: .init(
// message_reference: .init(
// type: .default,
// message_id: ctx.id,
// channel_id: ctx.channel_id,
// guild_id: ctx.guild_id,
// ),
// files: [.init(data: .init(data: zundaGif), filename: "zundamone.gif")],
// attachments: [.init(index: 0, filename: "zundamone.gif")],
// )
// ).guardSuccess()
// } else {
// try await handle8Ball()
// }
// }
// }
//
// static let ballResponses = [
// "It is certain.",
// "It is decidedly so.",
// "Without a doubt.",
// "Yes definitely.",
// "You may rely on it.",
// "As I see it, yes.",
// "Most likely.",
// "Outlook good.",
// "Yes.",
// "Signs point to yes.",
// "Reply hazy, try again.",
// "Ask again later.",
// "Better not tell you now.",
// "Cannot predict now.",
// "Concentrate and ask again.",
// "Dont count on it.",
// "My reply is no.",
// "My sources say no.",
// "Outlook not so good.",
// "Very doubtful.",
// "Ui beam",
// "We are Shigure Ui",
// "We are Shigure Ux",
// ]
// func handle8Ball() async throws {
// try await client.createMessage(
// channelId: ctx.channel_id,
// payload: .init(
// content: MessageHandler.ballResponses.randomElement(),
// message_reference: .init(
// type: .default,
// message_id: ctx.id,
// channel_id: ctx.channel_id,
// guild_id: ctx.guild_id,
// ),
// )
// ).guardSuccess()
// }
//
// static let wows = [
// "<:wow:1477062414913634334>",
// "<:wow2:1477062432357875948>",
// "<:wow4:1477062471746588713>",
// "<:wow5:1477062452804849845>"
// ]
// func handleWow(_ args: ArraySlice<String.SubSequence>) async throws {
// try await client.createMessage(
// channelId: ctx.channel_id,
// payload: .init(
// content: MessageHandler.wows.randomElement(),
// message_reference: .init(
// type: .default,
// message_id: ctx.id,
// channel_id: ctx.channel_id,
// guild_id: ctx.guild_id,
// ),
// )
// ).guardSuccess()
// }
//
// }

View File

@@ -1,107 +1,107 @@
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
import XMLCoder
import DiscordBM
struct Wolfram {
static let token = ProcessInfo.processInfo.environment["WOLFRAM_APP_ID"]!
static let apiUrl = "http://api.wolframalpha.com/v2/query"
static func getWolfram(_ question: String) async throws -> (String, URL?) {
let encQuestion = question.addingPercentEncoding(withAllowedCharacters: .alphanumerics)
let url = URL(string: "\(apiUrl)?appid=\(token)&input=\(encQuestion!)")!
let (data, _) = try await URLSession.shared.data(from: url)
let wolframRes = try XMLDecoder().decode(WolframQueryResult.self, from: data)
let resultPod = wolframRes.pod.first(where: { $0.primary ?? false || $0.id == "Result" })
var ans: String?
var img: URL?
if let resultPod = resultPod {
ans = String(resultPod.subpod.compactMap(\.plaintext).joined(by: "\n"))
.replacingOccurrences(of: " | ", with: ": ")
}
if let imgPod = wolframRes.pod.first(where: {
["RootPlot", "NumberLine", "Plot", "ImplicitPlot", "3DPlot"].contains($0.id) ||
($0.id == "Example" && $0.scanner == "Dice")
}) {
ans = ans ?? "Plot:"
img = imgPod.subpod.first?.img.src
}
if ans == nil,
let maybePod = wolframRes.pod.first(where: { $0.title == "Input interpretation" }),
let maybeText = maybePod.subpod.first?.plaintext
.replacingOccurrences(of: " | ", with: ": ") {
ans = "<:smol_rise:852763040452575252> I don't know. Maybe you meant '\(maybeText)'"
}
return (ans ?? "<:smol_rise:852763040452575252> sorry, I have no idea (´._.`)", img)
}
static func handleMath(
_ args: ArraySlice<String.SubSequence>,
client: DiscordClient,
ctx: Gateway.MessageCreate
) async throws {
try await client.triggerTypingIndicator(channelId: ctx.channel_id).guardSuccess()
let question = String(args.joined(by: " "))
let (answer, img) = try await getWolfram(question)
var attachments: [Payloads.Attachment] = []
var files: [RawFile] = []
if let img = img {
let data = try? await URLSession.shared.data(from: img)
if let data = data?.0 {
attachments.append(.init(index: 0, filename: "img.gif"))
files.append(.init(data: .init(data: data), filename: "img.gif"))
}
}
try await client.createMessage(channelId: ctx.channel_id, payload: .init(
content: answer,
message_reference: .init(
type: .default,
message_id: ctx.id,
channel_id: ctx.channel_id,
guild_id: ctx.guild_id,
),
files: files,
attachments: attachments
)).guardSuccess()
}
}
struct WolframQueryResult: Codable {
struct Pod: Codable {
let title: String
let id: String
let scanner: String
let primary: Bool?
let subpod: [Subpod]
}
struct Subpod: Codable {
let title: String
let img: Image
let plaintext: String
}
struct Image: Codable {
let src: URL
}
let success: Bool
let numpods: Int
let pod: [Pod]
}
// import Foundation
// #if canImport(FoundationNetworking)
// import FoundationNetworking
// #endif
// import XMLCoder
// import DiscordBM
//
// struct Wolfram {
// static let token = ProcessInfo.processInfo.environment["WOLFRAM_APP_ID"]!
// static let apiUrl = "http://api.wolframalpha.com/v2/query"
//
// static func getWolfram(_ question: String) async throws -> (String, URL?) {
// let encQuestion = question.addingPercentEncoding(withAllowedCharacters: .alphanumerics)
// let url = URL(string: "\(apiUrl)?appid=\(token)&input=\(encQuestion!)")!
// let (data, _) = try await URLSession.shared.data(from: url)
//
// let wolframRes = try XMLDecoder().decode(WolframQueryResult.self, from: data)
//
// let resultPod = wolframRes.pod.first(where: { $0.primary ?? false || $0.id == "Result" })
//
// var ans: String?
// var img: URL?
//
// if let resultPod = resultPod {
// ans = String(resultPod.subpod.compactMap(\.plaintext).joined(by: "\n"))
// .replacingOccurrences(of: " | ", with: ": ")
// }
// if let imgPod = wolframRes.pod.first(where: {
// ["RootPlot", "NumberLine", "Plot", "ImplicitPlot", "3DPlot"].contains($0.id) ||
// ($0.id == "Example" && $0.scanner == "Dice")
// }) {
// ans = ans ?? "Plot:"
// img = imgPod.subpod.first?.img.src
// }
//
// if ans == nil,
// let maybePod = wolframRes.pod.first(where: { $0.title == "Input interpretation" }),
// let maybeText = maybePod.subpod.first?.plaintext
// .replacingOccurrences(of: " | ", with: ": ") {
// ans = "<:smol_rise:852763040452575252> I don't know. Maybe you meant '\(maybeText)'"
// }
//
// return (ans ?? "<:smol_rise:852763040452575252> sorry, I have no idea (´._.`)", img)
// }
//
// static func handleMath(
// _ args: ArraySlice<String.SubSequence>,
// client: DiscordClient,
// ctx: Gateway.MessageCreate
// ) async throws {
// try await client.triggerTypingIndicator(channelId: ctx.channel_id).guardSuccess()
//
// let question = String(args.joined(by: " "))
//
// let (answer, img) = try await getWolfram(question)
//
// var attachments: [Payloads.Attachment] = []
// var files: [RawFile] = []
//
// if let img = img {
// let data = try? await URLSession.shared.data(from: img)
// if let data = data?.0 {
// attachments.append(.init(index: 0, filename: "img.gif"))
// files.append(.init(data: .init(data: data), filename: "img.gif"))
// }
// }
//
// try await client.createMessage(channelId: ctx.channel_id, payload: .init(
// content: answer,
// message_reference: .init(
// type: .default,
// message_id: ctx.id,
// channel_id: ctx.channel_id,
// guild_id: ctx.guild_id,
// ),
// files: files,
// attachments: attachments
// )).guardSuccess()
// }
// }
//
// struct WolframQueryResult: Codable {
// struct Pod: Codable {
// let title: String
// let id: String
// let scanner: String
// let primary: Bool?
//
// let subpod: [Subpod]
// }
//
// struct Subpod: Codable {
// let title: String
// let img: Image
// let plaintext: String
// }
//
// struct Image: Codable {
// let src: URL
// }
//
// let success: Bool
// let numpods: Int
//
// let pod: [Pod]
// }
//

View File

@@ -1,11 +1,10 @@
import Foundation
import DiscordBM
import DiscordKit
import SwiftDotenv
@main
struct Zundamon {
nonisolated(unsafe) static private(set) var ownID: UserSnowflake? = nil
//nonisolated(unsafe) static private(set) var ownID: UserSnowflake? = nil
static func main() async throws {
let tmp = Result { try Dotenv.configure() }
@@ -41,12 +40,12 @@ struct Zundamon {
}
}
struct EventHandler: GatewayEventHandler {
let event: Gateway.Event
let client: any DiscordClient
func onMessageCreate(_ payload: Gateway.MessageCreate) async throws {
try await MessageHandler(ctx: payload, client: client).handle()
}
}
//struct EventHandler: GatewayEventHandler {
// let event: Gateway.Event
// let client: any DiscordClient
//
// func onMessageCreate(_ payload: Gateway.MessageCreate) async throws {
// try await MessageHandler(ctx: payload, client: client).handle()
// }
//
//}