package main import "core:encoding/cbor" import "core:encoding/json" import "core:fmt" import "core:log" import "core:math/rand" import "core:os" import "core:strings" import "core:thread" import "core:time" import di "discord-interactions" import client "discord-interactions/odin-http/client" PRODUCE_MARKOV :: #config(PRODUCE_MARKOV, false) SEQUENCE_LENGTH :: #config(SEQUENCE_LENGTH, 5) Word :: struct { proceeding: map[string]int `json:"p"`, } Data :: struct { data: [][]string, } Dist :: struct { word: string, sum: int, } process_words :: proc(previous_word, next_word: string, word_map: ^map[string]Word) { word_entry, found := word_map[previous_word] if !found { word_entry = Word{} } word_entry.proceeding[next_word] += 1 word_map[previous_word] = word_entry } word_map: map[string]Word try_find :: proc(input: []string) -> (word: Maybe(Word)) { for i in max(0, len(input) - rand.int_max(SEQUENCE_LENGTH) - 1) ..< len(input) { concat := strings.join(input[i:], " ") found: bool word, found = word_map[concat] if found { break } } return } generate :: proc(input: string) -> string { generated: [dynamic]string append(&generated, input) maybe_word := try_find(strings.split(input, " ")) if maybe_word == nil { return "aint got nothing for that in the ol' markov chain" } word := maybe_word.? loop: for { dists: [dynamic]Dist sum: int for next_word, count in word.proceeding { sum += count append(&dists, Dist{word = next_word, sum = sum}) } if sum <= 0 { break } rand_val := rand.int_max(sum) for dist in dists { if rand_val < dist.sum { append(&generated, dist.word) maybe_word = try_find(generated[:]) if maybe_word == nil { break loop } word = maybe_word.? continue loop } } } return strings.join(generated[:], " ") } main :: proc() { context.logger = log.create_console_logger(.Info) di.load_config("config.json") when PRODUCE_MARKOV { bytes, _ := os.read_entire_file("data.json") data: Data if err := json.unmarshal(bytes, &data); err != nil { log.error(err) } for words in data.data { for i in 0 ..< len(words) { for j in i + 1 ..< min(i + SEQUENCE_LENGTH, len(words)) { process_words(strings.join(words[i:j], " "), words[j], &word_map) } } } out, _ := cbor.marshal(word_map) os.write_entire_file("markov.cbor", out) fmt.println("Produced markov file") } markov_bytes, ok := os.read_entire_file("markov.cbor") if !ok { fmt.eprintln("Failed to read markov cbor") } cbor.unmarshal(string(markov_bytes), &word_map) delete(markov_bytes) di.register_command("lph", proc(interaction: di.Interaction) -> di.Payload { thread.create_and_start_with_poly_data(interaction, proc(interaction: di.Interaction) { request: client.Request client.request_init(&request) defer client.request_destroy(&request) client.with_json( &request, di.Webhook_Payload{content = generate(interaction.data.options[0].value)}, ) request.method = .Patch res, err := client.request( &request, fmt.tprintf( "{}/webhooks/{}/{}/messages/@original", di.DISCORD_API, di.state.application.id, interaction.token, ), ) if err != nil { log.error("Failed to send request:", err) return } }) return di.Payload{type = 5} }) di.serve() }