4 local C = minetest.get_color_escape_sequence
10 detail = C("#FF6683"),
12 braces = C("#FFFAC0"),
15 random = C("#A300BE"),
20 function furrybot.send(msg, color)
21 minetest.send_chat_message("/me " .. furrybot.colors.braces .. "[" .. color .. msg .. furrybot.colors.braces .. "]")
24 function furrybot.ping(player, color)
25 return furrybot.colors.ping .. "@" .. player .. color
28 function furrybot.ping_message(player, message, color)
29 furrybot.send(furrybot.ping(player, color) .. ": " .. message, "")
32 function furrybot.error_message(player, error, detail)
33 furrybot.ping_message(player, error .. (detail and furrybot.colors.detail .. " '" .. detail .. "'" .. furrybot.colors.error or "") .. ".", furrybot.colors.error)
36 function furrybot.recieve(msg)
37 msg = minetest.strip_colors(msg)
38 if msg:find("<") == 1 then
39 local idx = msg:find(">")
40 local player = msg:sub(2, idx - 1)
41 local message = msg:sub(idx + 3, #msg)
42 if message:find("!") == 1 then
43 local args = message:sub(2, #message):split(" ")
44 local cmd = table.remove(args, 1)
45 local func = furrybot.commands[cmd]
47 func(player, unpack(args))
49 furrybot.error_message(player, "Invalid command", cmd)
55 function furrybot.player_online(name)
56 for _, n in ipairs(minetest.get_player_names()) do
63 function furrybot.online_or_error(name, other, allow_self)
65 furrybot.error_message(name, "You need to specify a player")
66 elseif name == other and not allow_self then
67 furrybot.error_message(name, "You need to specify a different player than yourself")
68 elseif furrybot.player_online(other) then
71 furrybot.error_message(name, "Player not online", other)
75 function furrybot.choose(list, color)
76 return furrybot.colors.random .. list[math.random(#list)] .. color
79 function furrybot.random(min, max, color)
80 return furrybot.colors.random .. math.random(#list) .. color
83 function furrybot.http_request(url, name, callback)
84 furrybot.http.fetch({url = url}, function(res)
88 furrybot.ping_player_error(name, "Request failed with code", res.code)
93 function furrybot.json_http_request(url, name, callback)
94 furrybot.http_request(url, name, function(raw)
95 local data = minetest.parse_json(raw)
96 callback(data[1] or data)
100 function furrybot.strrandom(str, seed, ...)
102 local pr = PseudoRandom(seed)
104 v = v + str:byte(i) * pr:next()
106 return PseudoRandom(v):next(...)
109 function furrybot.repeat_string(str, times)
117 function furrybot.simple_rpg_command(action)
118 return function(name, target)
119 if furrybot.online_or_error(name, target) then
120 furrybot.send(name .. " " .. action .. " " .. target .. ".", furrybot.colors.rpg)
125 function furrybot.request_command(on_request, on_accept)
126 return function(name, target)
127 if furrybot.online_or_error(name, target) then
128 furrybot.requests[target] = {
132 on_request(name, target)
140 function furrybot.commands.help()
142 for k in pairs(furrybot.commands) do
143 table.insert(keys, k)
145 furrybot.send("Available commands: " .. table.concat(keys, ", "), furrybot.colors.system)
148 function furrybot.commands.accept(name)
149 local tbl = furrybot.requests[name]
151 furrybot.requests[name] = nil
152 tbl.func(tbl.origin, name)
154 furrybot.error_message(name, "Nothing to accept")
158 function furrybot.commands.deny(name)
159 local tbl = furrybot.requests[name]
161 furrybot.requests[name] = nil
162 furrybot.ping_message(name, "Denied request")
164 furrybot.error_message(name, "Nothing to deny")
168 -- don't bug players that are running ClamityBot commands from discord
169 function furrybot.commands.status()
172 function furrybot.commands.cmd()
176 furrybot.commands.hug = furrybot.simple_rpg_command("hugs")
177 furrybot.commands.cuddle = furrybot.simple_rpg_command("cuddles")
178 furrybot.commands.kiss = furrybot.simple_rpg_command("kisses")
179 furrybot.commands.hit = furrybot.simple_rpg_command("hits")
180 furrybot.commands.slap = furrybot.simple_rpg_command("slap")
181 furrybot.commands.beat = furrybot.simple_rpg_command("beat")
183 furrybot.commands.sex = furrybot.request_command(function(name, target)
184 furrybot.ping_message(target, name .. " wants to have sex with you. Type !accept to accept or !deny to deny.", furrybot.colors.system)
185 end, function(name, target)
186 furrybot.send(name .. " and " .. target .. " are having sex! OwO", furrybot.colors.rpg)
188 furrybot.commands.bang = furrybot.commands.sex
189 furrybot.commands.fuck = furrybot.commands.sex
192 function furrybot.commands.rolldice(name)
193 furrybot.ping_message(name, "rolled a dice and got a " .. furrybot.random(1, 6, furrybot.colors.system) .. ".", furrybot.colors.system)
196 function furrybot.commands.coinflip(name)
197 furrybot.ping_message(name, "flipped a coin and got " .. furrybot.choose({"Heads", "Tails"}, furrybot.colors.system) .. ".", furrybot.colors.system)
200 function furrybot.commands.choose(name, ...)
201 local options = {...}
203 furrybot.ping_message(name, "I choose " .. furrybot.choose(options, "", furrybot.colors.system) .. ".", furrybot.colors.system)
205 furrybot.error_message(name, "Not enough options")
208 furrybot.commands["8ball"] = furrybot.commands.choose
210 function furrybot.commands.dicksize(name, target)
211 target = target or name
212 local size = furrybot.strrandom(target, 31242, 2, 10)
213 local dick = furrybot.repeat_string("=", size) .. "D"
214 furrybot.send(dick .. furrybot.colors.system .. " <= " .. furrybot.ping(target, furrybot.colors.system) .. "'s Dick", C("#FF4DE1"))
216 furrybot.commands.cocksize = furrybot.commands.dicksize
219 function furrybot.commands.verse(name)
220 furrybot.json_http_request("https://labs.bible.org/api/?type=json&passage=random", name, function(data)
221 furrybot.send(data.text .. furrybot.colors.info .. "[" .. data.bookname .. " " .. data.chapter .. "," .. data.verse .. "]", furrybot.colors.fun)
225 function furrybot.commands.define(name, word)
227 furrybot.json_http_request("https://api.dictionaryapi.dev/api/v1/entries/en_US/" .. word, name, function(data)
228 local meaning = data.meaning
229 local selected = meaning.exclamation or meaning.noun or meaning.verb or meaning.adjective or meaning["transitive verb"] or meaning.adverb or meaning["relative adverb"]
232 furrybot.error_message(name, "Error in parsing response")
234 furrybot.send(word:sub(1, 1):upper() .. word:sub(2, #word):lower() .. ": " .. furrybot.colors.fun .. selected[1].definition, furrybot.colors.info)
238 furrybot.error_message(name, "You need to specify a word")
242 function furrybot.commands.insult(name, target)
243 if furrybot.online_or_error(name, target, true) then
244 furrybot.http_request("https://insult.mattbas.org/api/insult", name, function(data)
245 furrybot.ping_message(target, data, furrybot.colors.fun)
250 function furrybot.commands.joke(name, first, last)
257 furrybot.json_http_request("http://api.icndb.com/jokes/random?firstName=" .. first .. "&lastName=" .. last, name, function(data)
258 local joke = data.value.joke:gsub(""", "\""):gsub(" ", " ")
259 furrybot.send(joke, furrybot.colors.fun)
263 -- send reload message
264 if furrybot.loaded then
265 furrybot.send("Reloaded", furrybot.colors.system)
267 furrybot.loaded = true