Skip to content

Commit d22ae0a

Browse files
committed
Transition attacks.py to a hook generation system
1 parent d4af4e8 commit d22ae0a

File tree

1 file changed

+89
-173
lines changed

1 file changed

+89
-173
lines changed

plugins/attacks.py

Lines changed: 89 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
1-
import codecs
21
import json
3-
import os
4-
import random
52
import re
3+
from collections import defaultdict
4+
from enum import Enum, unique
5+
from pathlib import Path
66

77
from cloudbot import hook
88
from cloudbot.util import textgen
99

1010

11+
@unique
12+
class RespType(Enum):
13+
ACTION = 1
14+
MESSAGE = 2
15+
REPLY = 3
16+
17+
1118
def is_self(conn, target):
1219
""" Checks if a string is "****self" or contains conn.name. """
1320
if re.search("(^..?.?.?self|{})".format(re.escape(conn.nick)), target, re.I):
@@ -16,200 +23,109 @@ def is_self(conn, target):
1623
return False
1724

1825

19-
@hook.on_start()
20-
def load_attacks(bot):
21-
"""
22-
:type bot: cloudbot.bot.CloudBot
23-
"""
24-
global larts, flirts, kills, slaps, north_korea, insults, strax, compliments, presents
25-
26-
with codecs.open(os.path.join(bot.data_dir, "larts.txt"), encoding="utf-8") as f:
27-
larts = [line.strip() for line in f.readlines() if not line.startswith("//")]
28-
29-
with codecs.open(os.path.join(bot.data_dir, "flirts.txt"), encoding="utf-8") as f:
30-
flirts = [line.strip() for line in f.readlines() if not line.startswith("//")]
31-
32-
with codecs.open(os.path.join(bot.data_dir, "insults.txt"), encoding="utf-8") as f:
33-
insults = [line.strip() for line in f.readlines() if not line.startswith("//")]
34-
35-
with codecs.open(os.path.join(bot.data_dir, "kills.json"), encoding="utf-8") as f:
36-
kills = json.load(f)
37-
38-
with codecs.open(os.path.join(bot.data_dir, "slaps.json"), encoding="utf-8") as f:
39-
slaps = json.load(f)
40-
41-
with codecs.open(os.path.join(bot.data_dir, "strax.json"), encoding="utf-8") as f:
42-
strax = json.load(f)
43-
44-
with codecs.open(os.path.join(bot.data_dir, "compliments.json"), encoding="utf-8") as f:
45-
compliments = json.load(f)
46-
47-
with codecs.open(os.path.join(bot.data_dir, "north_korea.txt"), encoding="utf-8") as f:
48-
north_korea = [line.strip() for line in f.readlines() if not line.startswith("//")]
49-
50-
with codecs.open(os.path.join(bot.data_dir, "presents.json"), encoding="utf-8") as f:
51-
presents = json.load(f)
52-
53-
54-
@hook.command
55-
def lart(text, conn, nick, action, is_nick_valid):
56-
"""<user> - LARTs <user>"""
57-
target = text.strip()
58-
59-
if not is_nick_valid(target):
60-
return "I can't lart that."
61-
62-
if is_self(conn, target):
63-
# user is trying to make the bot attack itself!
64-
target = nick
65-
66-
phrase = random.choice(larts)
67-
68-
# act out the message
69-
action(phrase.format(user=target))
70-
26+
attack_data = defaultdict(dict)
7127

72-
@hook.command("flirt", "sexup", "jackmeoff")
73-
def flirt(text, conn, nick, message, is_nick_valid):
74-
"""<user> - flirts with <user>"""
75-
target = text.strip()
7628

77-
if not is_nick_valid(target):
78-
return "I can't flirt with that."
29+
class BasicAttack:
30+
def __init__(self, name, doc, *commands, action=None, file=None, response=RespType.ACTION, require_target=True):
31+
self.name = name
32+
self.action = action or name
33+
self.doc = doc
34+
self.commands = commands or [name]
35+
if file is None:
36+
file = "{}.json".format(name)
7937

80-
if is_self(conn, target):
81-
# user is trying to make the bot attack itself!
82-
target = nick
38+
self.file = file
39+
self.response = response
40+
self.require_target = require_target
8341

84-
message('{}, {}'.format(target, random.choice(flirts)))
8542

43+
ATTACKS = (
44+
BasicAttack("lart", "<user> - LARTs <user>"),
45+
BasicAttack(
46+
"flirt", "<user> - flirts with <user>", "flirt", "sexup", "jackmeoff", action="flirt with",
47+
response=RespType.MESSAGE
48+
),
49+
BasicAttack("kill", "<user> - kills <user>", "kill", "end"),
50+
BasicAttack("slap", "<user> - Makes the bot slap <user>."),
51+
BasicAttack("compliment", "<user> - Makes the bot compliment <user>.", response=RespType.MESSAGE),
52+
BasicAttack(
53+
"strax", "[user] - Generates a quote from Strax, optionally targeting [user]", action="attack",
54+
response=RespType.MESSAGE, require_target=False
55+
),
56+
BasicAttack(
57+
"nk", "- outputs a random North Korea propaganda slogan", action="target", response=RespType.MESSAGE,
58+
require_target=False
59+
),
60+
BasicAttack("insult", "<user> - insults <user>", response=RespType.MESSAGE),
61+
BasicAttack("present", "<user> - gives gift to <user>", action="give a gift to"),
62+
)
8663

87-
@hook.command("kill", "end")
88-
def kill(text, conn, nick, action, is_nick_valid):
89-
"""<user> - kills <user>"""
90-
target = text.strip()
9164

92-
if not is_nick_valid(target):
93-
return "I can't attack that."
65+
def load_data(path, data_dict):
66+
data_dict.clear()
67+
with path.open(encoding='utf-8') as f:
68+
data_dict.update(json.load(f))
9469

95-
if is_self(conn, target):
96-
# user is trying to make the bot attack itself!
97-
target = nick
9870

99-
generator = textgen.TextGenerator(kills["templates"], kills["parts"], variables={"user": target})
100-
101-
# act out the message
102-
action(generator.generate_string())
103-
104-
105-
@hook.command
106-
def slap(text, action, nick, conn, is_nick_valid):
107-
"""<user> -- Makes the bot slap <user>."""
108-
target = text.strip()
109-
110-
if not is_nick_valid(target):
111-
return "I can't slap that."
112-
113-
if is_self(conn, target):
114-
# user is trying to make the bot attack itself!
115-
target = nick
116-
117-
variables = {
118-
"user": target
119-
}
120-
generator = textgen.TextGenerator(slaps["templates"], slaps["parts"], variables=variables)
121-
122-
# act out the message
123-
action(generator.generate_string())
124-
125-
126-
@hook.command
127-
def compliment(text, nick, conn, is_nick_valid, message):
128-
"""<user> -- Makes the bot compliment <user>."""
129-
target = text.strip()
130-
131-
if not is_nick_valid(target):
132-
return "I can't compliment that."
133-
134-
if is_self(conn, target):
135-
# user is trying to make the bot attack itself!
136-
target = nick
137-
138-
variables = {
139-
"user": target
140-
}
141-
generator = textgen.TextGenerator(compliments["templates"], compliments["parts"], variables=variables)
142-
143-
# act out the message
144-
message(generator.generate_string())
71+
@hook.on_start()
72+
def load_attacks(bot):
73+
"""
74+
:type bot: cloudbot.bot.CloudBot
75+
"""
76+
attack_data.clear()
77+
data_dir = Path(bot.data_dir) / "attacks"
78+
for data_file in ATTACKS:
79+
load_data(data_dir / data_file.file, attack_data[data_file.name])
14580

14681

147-
@hook.command(autohelp=False)
148-
def strax(text, conn, message, nick, is_nick_valid):
149-
"""Strax quote."""
82+
def basic_format(text, data, **kwargs):
83+
user = text
84+
kwargs['user'] = user
15085

15186
if text:
152-
target = text.strip()
153-
if not is_nick_valid(target):
154-
return "I can't do that."
155-
156-
if is_self(conn, target):
157-
# user is trying to make the bot attack itself!
158-
target = nick
159-
variables = {
160-
"user": target
161-
}
162-
163-
generator = textgen.TextGenerator(strax["target_template"], strax["parts"], variables=variables)
87+
try:
88+
templates = data["target_templates"]
89+
except KeyError:
90+
templates = data["templates"]
16491
else:
165-
generator = textgen.TextGenerator(strax["template"], strax["parts"])
166-
167-
# Become Strax
168-
message(generator.generate_string())
92+
templates = data["templates"]
16993

94+
generator = textgen.TextGenerator(
95+
templates, data["parts"], variables=kwargs
96+
)
17097

171-
@hook.command(autohelp=False)
172-
def nk(message):
173-
"""outputs a random North Korea propoganda slogan"""
174-
slogan = random.choice(north_korea)
175-
message(slogan)
98+
return generator.generate_string()
17699

177100

178-
@hook.command()
179-
def insult(text, conn, nick, notice, message, is_nick_valid):
180-
"""<user> - insults <user>
181-
:type text: str
182-
:type conn: cloudbot.client.Client
183-
:type nick: str
184-
"""
185-
target = text.strip()
101+
def basic_attack(attack):
102+
def func(text, conn, nick, action, message, reply, is_nick_valid):
103+
responses = {
104+
RespType.ACTION: action,
105+
RespType.REPLY: reply,
106+
RespType.MESSAGE: message,
107+
}
186108

187-
if not is_nick_valid(target):
188-
notice("Invalid username!")
189-
return
109+
target = text
110+
if target:
111+
if not is_nick_valid(target):
112+
return "I can't {action} that.".format(action=attack.action)
190113

191-
# if the user is trying to make the bot target itself, target them
192-
if is_self(conn, target):
193-
target = nick
114+
if is_self(conn, target):
115+
target = nick
194116

195-
message("{}, {}".format(target, random.choice(insults)))
117+
out = basic_format(target, attack_data[attack.name])
196118

119+
responses[attack.response](out)
197120

198-
@hook.command("present", "gift")
199-
def present(text, conn, nick, action, is_nick_valid):
200-
"""<user> - gives gift to <user>"""
201-
target = text.strip()
121+
func.__name__ = attack.name
122+
func.__doc__ = attack.doc
123+
return func
202124

203-
if not is_nick_valid(target):
204-
return "I can't gift that."
205125

206-
if is_self(conn, target):
207-
# user is trying to make the bot gift itself!
208-
target = nick
126+
def create_basic_hooks():
127+
for attack in ATTACKS:
128+
globals()[attack.name] = hook.command(*attack.commands, autohelp=attack.require_target)(basic_attack(attack))
209129

210-
variables = {
211-
"user": target
212-
}
213130

214-
generator = textgen.TextGenerator(presents["templates"], presents["parts"], variables=variables)
215-
action(generator.generate_string())
131+
create_basic_hooks()

0 commit comments

Comments
 (0)