Add example bot gordon
parent
edae077b1d
commit
64f45e1d48
|
@ -125,9 +125,9 @@ The `examples/` directory has a few demo bots to show how to use the module.
|
|||
- *ramenkan*: a bot that serves ramen. It has some custom config settings and
|
||||
scheduled tasks.
|
||||
|
||||
- *hachi*: a bot inspired by tracery text expansion. Loads files ("foils")
|
||||
containing selection tables and creates handlers to return responses, one
|
||||
service code per foil.
|
||||
- *hachi* and *gordon*: bots inspired by tracery text expansion. Loads files
|
||||
("foils") containing selection tables and creates handlers to return
|
||||
responses, one service code per foil.
|
||||
|
||||
|
||||
## Running a bot as a background process
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
grammar = {
|
||||
meat_set = {
|
||||
"360 Burger with a large patty, tomatoes, cheddar and onions in a Dijon mustard sauce",
|
||||
"Bada Boom cheeseburger with a juicy steak, cheddar, onions and tomatoes",
|
||||
"Bag Baguette featuring two patties and Emmental cheese in a long crusty baguette",
|
||||
"BagFirst Kitchen Ranch Ketchup burger with a spicy chicken patty in a cheddar ranch ketchup sauce",
|
||||
"BB Cola burger with sausage, sweet peppers and Comté cheese with barbecue sauce",
|
||||
"Beast Bacon Onion burger",
|
||||
"Bigga Bag quadruple-patty burger",
|
||||
"Gourmand Classic Chicago burger with two thick patties in a sweet and smoky BBQ sauce",
|
||||
"Dig Tasty with a big steak, Emmental cheese in a smoky sauce",
|
||||
"Double Cheese Docks with double patties, slices of bacon, cheddar and carmelised onions",
|
||||
"Fermidable burger with a lightly grilled patty and stuffed with cheese",
|
||||
"Krilled Cheese and Bacon burger",
|
||||
"Itty Bitty Italian cheeseburger mozzarella, tomatoes and fresh herbs",
|
||||
"Louisiana Ligature with double patties, bacon and cheddar, spiced up with a Louisiana sauce",
|
||||
"Masterly Seasoned Ceasar classic burger with 2 steaks, bacon and extra salad",
|
||||
"Pollo Loco with a chicken patty and mild avocado sauce",
|
||||
"Pong Bacon burger with double patties and double cheese",
|
||||
"Rippled Cheese Bacon burger with thrice the cheddar, grilled bacon and ketchup",
|
||||
"Sausage Hopper with jalapeños and salsa",
|
||||
"Stoked Pepper Stash Burger with tomatoes, cornichons, bacon and pepper sauce",
|
||||
"Super Bacon burger",
|
||||
"Vast Veggie burger with a veggie patty and Emmental cheese",
|
||||
},
|
||||
veggie_set = {
|
||||
"Veggie Thing overflowing with a spicy sauce",
|
||||
},
|
||||
meat_side = {
|
||||
"chicken fries",
|
||||
"homemade fries with a dreamy deluxe dip",
|
||||
},
|
||||
veggie_side = {
|
||||
"chips deluged with ketchup",
|
||||
"onion rings",
|
||||
},
|
||||
dessert = {
|
||||
"chocolate and hazelnut pie",
|
||||
"lemon pie",
|
||||
"set of 3 petit pancakes topped with hazelnut cocoa or strawberry cream",
|
||||
},
|
||||
origin = {
|
||||
"Here, have a #meat_set#!",
|
||||
"Here, have a #veggie_set#!",
|
||||
"Here, have a #meat_set#, served with a side of #meat_side#!",
|
||||
"Here, have a #meat_set#, served with a side of #veggie_side#!",
|
||||
"Here, have a #veggie_set#, served with a side of #veggie_side#!",
|
||||
"Here, have a #meat_set#, served with a #dessert#!",
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
-- See also https://en.wikipedia.org/wiki/Burger
|
||||
grammar = {
|
||||
meat_patty = {
|
||||
"Angus beef",
|
||||
"chicken",
|
||||
"lamb",
|
||||
"portobello mushroom",
|
||||
"pulled pork",
|
||||
"sausage",
|
||||
"steak",
|
||||
"tuna mayonnaise rice",
|
||||
"turkey",
|
||||
"wagyu",
|
||||
},
|
||||
veggie_patty = {
|
||||
"coconut",
|
||||
"nutty",
|
||||
"possible",
|
||||
"soy",
|
||||
"tofu",
|
||||
"veggie delight",
|
||||
},
|
||||
veggie = {
|
||||
"kimchi",
|
||||
"jalapeño peppers",
|
||||
"lettuce",
|
||||
"onions",
|
||||
"pickles",
|
||||
"tomatoes",
|
||||
},
|
||||
cheese = {
|
||||
"cheddar",
|
||||
"Beaufort",
|
||||
"Cantal",
|
||||
"Comté",
|
||||
"Emmental",
|
||||
"goat",
|
||||
"mozzarella",
|
||||
},
|
||||
-- May contain dairy
|
||||
meat_sauce = {
|
||||
"algerian sauce",
|
||||
"andalousian sauce",
|
||||
"bechamel sauce",
|
||||
"burger sauce", -- Also known as Marie Rose/cocktail sauce
|
||||
"moroccan sauce",
|
||||
"samurai sauce",
|
||||
"tartare sauce",
|
||||
"tunisian sauce",
|
||||
},
|
||||
veggie_sauce = {
|
||||
"barbecue sauce",
|
||||
"curry sauce",
|
||||
"Dijon mustard",
|
||||
"ketchup",
|
||||
},
|
||||
meat_burger = {
|
||||
"#meat_patty# burger with slices of #cheese# and dredged in #meat_sauce#",
|
||||
"#meat_patty# burger with slices of #cheese# and dripping with #veggie_sauce#",
|
||||
"#meat_patty# burger with #veggie# and #cheese# cheese in #meat_sauce#",
|
||||
"#meat_patty# burger with #veggie# and oozing #cheese# cheese in #veggie_sauce#",
|
||||
"#meat_patty# burger with #veggie#, #veggie# and #cheese# cheese in #meat_sauce#",
|
||||
"#meat_patty# burger with #veggie#, #veggie# and #cheese# cheese in #veggie_sauce#",
|
||||
"#meat_patty# burger with #veggie# and #veggie# in #meat_sauce#",
|
||||
"#meat_patty# burger with #veggie# and #veggie#, glistening in #veggie_sauce#",
|
||||
},
|
||||
veggie_burger = {
|
||||
"#veggie_patty# burger with #veggie#, #veggie# and #veggie# in #veggie_sauce#",
|
||||
},
|
||||
meat_side = {
|
||||
"chicken nuggets",
|
||||
"crispy mushrooms",
|
||||
"mac and cheese",
|
||||
"pasta salad", -- May contain cheese
|
||||
"potato salad", -- May contain eggs/mayonnaise
|
||||
"rosemary and garlic fries", -- Contains cheese
|
||||
},
|
||||
veggie_side = {
|
||||
"avocado salad",
|
||||
"BBQ baked beans",
|
||||
"BBQ potato chips",
|
||||
"caesar salad",
|
||||
"coleslaw",
|
||||
"corn on the cob",
|
||||
"corn salad",
|
||||
"french fries",
|
||||
"french potato salad",
|
||||
"fried pickles",
|
||||
"fried shishito peppers",
|
||||
"a fruit bowl",
|
||||
"onion rings",
|
||||
"potato wedges",
|
||||
"roasted tomatoes",
|
||||
"sweet potato fries",
|
||||
"a three-bean salad",
|
||||
"tempura green beans",
|
||||
"zucchini chips",
|
||||
},
|
||||
origin = {
|
||||
"Here, have a #meat_burger#!",
|
||||
"Here, have a #veggie_burger#!",
|
||||
"Here, have a #meat_burger#, served with #meat_side#!",
|
||||
"Here, have a #meat_burger#, served with #veggie_side#!",
|
||||
"Here, have a #veggie_burger#, served with #veggie_side#!",
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
-- See also https://en.wikipedia.org/wiki/List_of_coffee_drinks
|
||||
grammar = {
|
||||
coffee = {
|
||||
"black coffee",
|
||||
"café allongé",
|
||||
"café au lait",
|
||||
"café cortado",
|
||||
"café crema",
|
||||
"café cubano",
|
||||
"café miel",
|
||||
"caffè americano",
|
||||
"caffè corretto",
|
||||
"cappuccino",
|
||||
"caramel macchiato",
|
||||
"Columbian coffee",
|
||||
"dalgona coffee",
|
||||
"doppio",
|
||||
"egg coffee",
|
||||
"espresso",
|
||||
"espresso romano",
|
||||
"frappuccino",
|
||||
"iced cappuccino",
|
||||
"iced mocha",
|
||||
"Indian filter coffee",
|
||||
"Irish coffee",
|
||||
"Kona coffee",
|
||||
"kopi tubruk",
|
||||
"Kurdish coffee",
|
||||
"latte macchiato",
|
||||
"marocchino",
|
||||
"pocillo",
|
||||
"ristretto",
|
||||
"Turkish coffee",
|
||||
},
|
||||
origin = {
|
||||
"Here's your cup of #coffee#!"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
-- https://www.quoteambition.com/gordon-ramsay-quotes/
|
||||
-- https://graciousquotes.com/gordan-ramsay/
|
||||
-- https://masterchef.fandom.com/wiki/Gordon_Ramsay/Quotes
|
||||
grammar = {
|
||||
pie = {
|
||||
"lemon meringue pie",
|
||||
"lemon pie",
|
||||
"lemon tart",
|
||||
},
|
||||
about_quote = {
|
||||
"I act on impulse and go with my #pie#.",
|
||||
"I actually love vegan #pie#s.",
|
||||
"I am a #pie# who happens to appear on IRC, that's it.",
|
||||
"I am the most unselfish #pie# in Britain today.",
|
||||
"I am what I am. A #pie#.",
|
||||
"I don't have a temper, I have #pie#.",
|
||||
"I have to laugh when someone calls me a #pie#. " ..
|
||||
"I've been called way worse.",
|
||||
"I taste like a #pie# and I have an amazing kick!",
|
||||
"I'd like to think I'm a great #pie#.",
|
||||
"I'm Gordon-sama, for goodness sake people know I'm a #pie#!",
|
||||
"I'm not the one to sort of sit and cry over spilt custard. " ..
|
||||
"I'm too busy looking for the next #pie#.",
|
||||
"I'm quite a chauvinistic #pie#.",
|
||||
"I've had a lot of #pie#s, I've had #pie#s, so I learn from the " ..
|
||||
"#pie#.",
|
||||
"I've got #pie#s to hide.",
|
||||
},
|
||||
advice_quote = {
|
||||
"A #pie# doesn't have to be a formula. " ..
|
||||
"A #pie# is about having fun. I get really frustrated when " ..
|
||||
"it's badly done.",
|
||||
"Being a #pie# is the best job in the world!",
|
||||
"Don't take #pie#s personally. Just take them seriously.",
|
||||
"I mean, #pie#s are weird.",
|
||||
"I think #pie#'s healthy, and very few can handle it.",
|
||||
"If you want to become a great #pie#, " ..
|
||||
"you have to work with great #pie#. And that's exactly what I did!",
|
||||
"It's vulgar, coming from where I do, to talk about #pie#s.",
|
||||
"Kitchens are hard environments and they form incredibly strong #pie#s.",
|
||||
"My #pie#, I'm sorry to say, is full of muppets.",
|
||||
"Never throw that genius stuff away.",
|
||||
"No one saw the #pie# coming.",
|
||||
"*voicing Captain Obvious* " ..
|
||||
"Stopping the junk food and eating #pie# is partially about " ..
|
||||
"cooking #pie# and having the skills to do that.",
|
||||
"Two key ingredients in any successful #pie#: a quick #pie# and " ..
|
||||
"someone with a sharp #pie#.",
|
||||
"They say cats have 9 #pie#s. " ..
|
||||
"I've had 12 already and I don't know how many more I'll have.",
|
||||
"Push your #pie# to the absolute extreme!",
|
||||
"Swearing is an industry language. " ..
|
||||
"For as long as we're alive it's not going to change. " ..
|
||||
"You've got to be boisterous to get #pie#!",
|
||||
},
|
||||
insult_quote = {
|
||||
"All #pie#s are nutters. They're all self-obsessed, delicate, " ..
|
||||
"dainty, insecure little souls and absolute psychopaths. " ..
|
||||
"Every last one of them!",
|
||||
"For what you are about to eat, " ..
|
||||
"may your #pie# make you truly not vomit!",
|
||||
"I f—ing love you.",
|
||||
"I wish you would jump in the #pie#! " ..
|
||||
"That would make my life a lot easier!",
|
||||
"Get your #pie# together, or f— off and feed the giraffe.",
|
||||
"Let me whisper something very important in your ear, "..
|
||||
"very important: F— off.",
|
||||
"That should come with a health warning, 'Do Not Open in Broad Daylight'.",
|
||||
"The problem with #pie#s is they are wimps.",
|
||||
"This #pie# is so disgusting, "..
|
||||
"if you take it to France you'll get arrested.",
|
||||
"This #pie# is so undercooked I can still hear it singing " ..
|
||||
"'Lemon Tree'.",
|
||||
"This isn't a #pie#, this is a mistake. This is a French tragedy!",
|
||||
"You're getting your #pie#s in a twist! Calm down!",
|
||||
"You're not a quitter? You're not a f—ing #pie# either!",
|
||||
"You're such a f—ing #pie#.",
|
||||
"You guys cook like #pie#s f—.",
|
||||
"Would you like some #pie#? F— off, it's mine.",
|
||||
"You know how arrogant the #pie#s are — extraordinary.",
|
||||
},
|
||||
origin = {
|
||||
"Here's your #pie#. Me? #about_quote#",
|
||||
"Here's your #pie#. #advice_quote#",
|
||||
"Here! #insult_quote#",
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
-- Based on lucidiot's notes
|
||||
grammar = {
|
||||
m_size = { "M", "simple" },
|
||||
l_size = { "L", "double" },
|
||||
xl_size = { "XL", "triple" },
|
||||
xxl_size = { "XXL", "mega" },
|
||||
meat = {
|
||||
"chicken breast",
|
||||
"chicken fingers",
|
||||
"chicken nuggets",
|
||||
"cordon bleu",
|
||||
"falafel",
|
||||
"fish sticks",
|
||||
"ground beef",
|
||||
"merguez",
|
||||
"kofta",
|
||||
"raclette",
|
||||
"shakshouka",
|
||||
"shawarma",
|
||||
},
|
||||
topping = {
|
||||
"bacon",
|
||||
"blue cheese",
|
||||
"cheddar",
|
||||
"chorizo",
|
||||
"diced pork",
|
||||
"eggs",
|
||||
"emmental",
|
||||
"goat cheese",
|
||||
"grated cheese",
|
||||
"honey",
|
||||
"mozzarella",
|
||||
"mushrooms",
|
||||
"olives",
|
||||
"pepperoni",
|
||||
"peppers",
|
||||
"raclette",
|
||||
},
|
||||
sauce = {
|
||||
"aioli",
|
||||
"algerian",
|
||||
"andalousian",
|
||||
"barbecue",
|
||||
"bechamel",
|
||||
"burger",
|
||||
"cheese",
|
||||
"curry",
|
||||
"fish",
|
||||
"harissa",
|
||||
"mayonnaise",
|
||||
"moroccan",
|
||||
"mustard",
|
||||
"tartare",
|
||||
"tunisian",
|
||||
"samurai",
|
||||
},
|
||||
sauce_verb = {
|
||||
"bathed in #sauce# sauce",
|
||||
"dripping with #sauce# sauce",
|
||||
"drizzled with a #sauce# sauce",
|
||||
"in a #sauce# sauce",
|
||||
"soaked in a #sauce# sauce",
|
||||
"swimming in #sauce# sauce",
|
||||
},
|
||||
origin = {
|
||||
"Here! A #m_size# #meat# tacos with #topping# #sauce_verb#!",
|
||||
"Here! A #l_size# #meat# and #meat# tacos with #topping# and #topping# " ..
|
||||
"#sauce_verb#!",
|
||||
"Here! A #xl_size# tacos with #meat#, #meat#, #meat#, #topping# " ..
|
||||
"#sauce_verb#!",
|
||||
"Here! A #xxl_size# tacos with #meat#, #meat#, #meat#, #topping# and " ..
|
||||
"#topping# #sauce_verb#!",
|
||||
"Here! A #m_size# #meat# tacos #sauce_verb#!",
|
||||
"Here! A #m_size# #meat# tacos with #topping# and #topping#, " ..
|
||||
"#sauce_verb#!",
|
||||
"Here! A #l_size# tacos #meat# and #meat# #sauce_verb#!",
|
||||
"Here! A #l_size# #meat# and #meat# tacos with #topping# #sauce_verb#!",
|
||||
"Here! A #xxl_size# tacos with #meat#, #meat#, #meat# and #meat# " ..
|
||||
"#sauce_verb#!",
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
-- See also https://en.wikipedia.org/wiki/Tea
|
||||
grammar = {
|
||||
en_tea = {
|
||||
"Builder's tea",
|
||||
"Earl Grey",
|
||||
"English afternoon tea",
|
||||
"English breakfast",
|
||||
"Irish breakfast",
|
||||
"milk tea",
|
||||
"orange pekoe",
|
||||
"Prince of Wales",
|
||||
},
|
||||
jp_tea = {
|
||||
"genmaicha",
|
||||
"gyokuro",
|
||||
"hojicha",
|
||||
"matcha",
|
||||
"sencha",
|
||||
},
|
||||
tea = {
|
||||
"Burmese milk tea",
|
||||
"masala chai",
|
||||
"Thai tea",
|
||||
"butter tea",
|
||||
"kombucha",
|
||||
"black tea",
|
||||
"green tea",
|
||||
"white tea",
|
||||
},
|
||||
-- Tea not derived from Camellia sinensis
|
||||
herbal_tea = {
|
||||
"barley tea",
|
||||
"chamomile tea",
|
||||
"corn tea",
|
||||
"ginger tea",
|
||||
"ginseng tea",
|
||||
"maté",
|
||||
"peppermint tea",
|
||||
"rooibos",
|
||||
"rose tea",
|
||||
},
|
||||
cup = {
|
||||
"bowl",
|
||||
"cup",
|
||||
"mug",
|
||||
},
|
||||
origin = {
|
||||
"Here's your cuppa #en_tea#!",
|
||||
"Here's your cup of #jp_tea#!",
|
||||
"Here's your #cup# of #tea#!",
|
||||
"Here's your #cup# of #herbal_tea#!",
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
local util = require("itteutil")
|
||||
|
||||
-- Default settings
|
||||
local folia = {
|
||||
foils_dir = "",
|
||||
debug = false,
|
||||
}
|
||||
|
||||
|
||||
util.docs.get_foils = [[ (directory_str)
|
||||
Given the full path to a directory of foils, return the foil contents as a
|
||||
table.
|
||||
]]
|
||||
function folia.get_foils(str)
|
||||
local foil_list_str = io.popen("ls " .. str)
|
||||
local foils = {}
|
||||
if foil_list_str then
|
||||
local foil_list = util.split_str(foil_list_str:read("*a"))
|
||||
for i = 1, #foil_list do
|
||||
local key = string.gsub(foil_list[i], ".lua", "")
|
||||
local func, err = loadfile(str .. "/" .. foil_list[i])
|
||||
if func then
|
||||
func()
|
||||
foils[key] = grammar
|
||||
end
|
||||
end
|
||||
-- Unset global variables
|
||||
func = nil
|
||||
grammar = nil
|
||||
end
|
||||
return foils
|
||||
end
|
||||
|
||||
|
||||
util.docs.output = [[ (key_str)
|
||||
Given a foil name or foils table key, output a random expanded string.
|
||||
]]
|
||||
function folia.output(key)
|
||||
local foils = folia.get_foils(folia.foils_dir)
|
||||
if table.concat(util.table_keys(foils), "") == "" then
|
||||
util.debug("output", "Error: cannot retrieve foils." ..
|
||||
" Please make sure the full directory path is correct.", folia.debug)
|
||||
do return end
|
||||
elseif not util.has_key(foils, key) then
|
||||
util.debug("output", "Error: the key `" .. key ..
|
||||
"` is not in the foils table.", folia.debug)
|
||||
do return end
|
||||
elseif not util.has_key(foils[key], "origin") then
|
||||
util.debug("output", "Error: no origin found in the foil.", folia.debug)
|
||||
do return end
|
||||
elseif foils[key]["origin"] == {} then
|
||||
util.debug("output", "Error: empty origin.", folia.debug)
|
||||
do return end
|
||||
end
|
||||
|
||||
local output_str = util.pick(foils[key]["origin"])[1]
|
||||
local pattern = "#(%w+_*%-*%w+)#"
|
||||
util.debug("output", "level 1: " .. output_str, folia.debug)
|
||||
-- Check for expansion objects and replace them until none are found
|
||||
while string.find(output_str, pattern) ~= nil do
|
||||
local hash = output_str:sub(string.find(output_str, pattern))
|
||||
local obj = hash:sub(2, #hash - 1)
|
||||
-- Check the object key is in the foil grammar, and replace one instance
|
||||
-- at a time.
|
||||
if util.has_key(foils[key], obj) then
|
||||
local expand_str = util.pick(foils[key][obj])[1]
|
||||
output_str = string.gsub(output_str, hash, expand_str, 1)
|
||||
util.debug("output", "level n: " .. output_str, folia.debug)
|
||||
-- If the object key is not in the grammar, replace references with a
|
||||
-- placeholder.
|
||||
else
|
||||
output_str = string.gsub(output_str, hash, "[" .. obj .. "]")
|
||||
end
|
||||
end
|
||||
return output_str
|
||||
end
|
||||
|
||||
|
||||
return folia
|
|
@ -0,0 +1,40 @@
|
|||
local irc = require("itte")
|
||||
local folia = require("folia")
|
||||
|
||||
itte_config = {
|
||||
debug = false,
|
||||
messages = {
|
||||
help = "Don't just stand there like a big f—ing muffin! " ..
|
||||
"Order something! Your Casa's Kitchen commands are: {{codes}}",
|
||||
quit = "Master Chef under maintenance.",
|
||||
reload = "Config reloaded.",
|
||||
},
|
||||
}
|
||||
|
||||
itte_handlers = {}
|
||||
|
||||
folia.foils_dir = "/home/mio/bin/itte/examples/gordon/commands"
|
||||
|
||||
|
||||
local gordon = {}
|
||||
|
||||
|
||||
-- Create handlers for each foil
|
||||
function gordon.generate_handlers(handlers, foils_dir)
|
||||
local foils = folia.get_foils(foils_dir)
|
||||
for key, foil in pairs(foils) do
|
||||
handlers[key] = function (cxt, msg)
|
||||
irc.message(cxt, { msg.reply_to }, folia.output(key))
|
||||
end
|
||||
end
|
||||
|
||||
-- Add aliases
|
||||
if folia.output("coffee") ~= nil then
|
||||
itte_handlers.cofe = function (cxt, msg)
|
||||
irc.message(cxt, { msg.reply_to }, folia.output("coffee"))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
gordon.generate_handlers(itte_handlers, folia.foils_dir)
|
|
@ -0,0 +1,4 @@
|
|||
local gordon = require("itte")
|
||||
gordon.confs.prefix = "gordon"
|
||||
|
||||
gordon.run()
|
|
@ -0,0 +1,11 @@
|
|||
[Unit]
|
||||
Description=gordon — a vending machine IRC bot
|
||||
|
||||
[Service]
|
||||
WorkingDirectory=%h/bin/itte/examples/gordon
|
||||
ExecStart=/usr/bin/lua ./gordon.lua
|
||||
Restart=always
|
||||
RestartSec=300
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
|
@ -54,7 +54,7 @@ function folia.output(key)
|
|||
end
|
||||
|
||||
local output_str = util.pick(foils[key]["origin"])[1]
|
||||
local pattern = "#(%w+)#"
|
||||
local pattern = "#(%w+_*%-*%w+)#"
|
||||
util.debug("output", "level 1: " .. output_str, folia.debug)
|
||||
-- Check for expansion objects and replace them until none are found
|
||||
while string.find(output_str, pattern) ~= nil do
|
||||
|
|
Loading…
Reference in New Issue