-
Notifications
You must be signed in to change notification settings - Fork 1
/
wortlerino.py
264 lines (237 loc) · 8.82 KB
/
wortlerino.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
"""Wordle-Bot for discord"""
import discord
from image_guesses import get_image_from_guesses
import wordle
import config
# Discord stuff
client = discord.Client()
TOKEN = config.TOKEN
# Constants
VERSION = 1.2
YELLOW = "🟨"
GREEN = "🟩"
BLACK = "⬜"
COLOR_CORRECT = 0x538D4E
COLOR_STANDARD = 0x8D7D4E
COLOR_ERROR = 0x8D4E4E
WIKILINK = "https://XX.wikipedia.org/wiki/"
COMMANDS = [
"wort",
"word",
"wortle",
"wordle",
"wortlerino",
"wordlerino",
"w",
"neu",
"new",
"nochmal",
"again",
"next",
"guess",
"n",
"set",
]
# Stores all wordle states (one per channel)
wordle_states = {}
def parse_message(message):
"""Parses message and returns color and text to respond with
Will only parse messages if first word is in commands
If no further arguments are given, will try to start a new game
If two arguments are given, second one is taken as a guess
If three or more arguments are given, it's treated as trying to change settings:
word_list, guess_list, or length
word_list and guess_list will take one argument to choose the list
length will take two arguments as min_length and max_length, or one argument to set both to be the same"""
split_message = message.content.split()
number_of_messages = len(split_message)
# Chooses the channel-specific wordle state
if message.channel not in wordle_states:
wordle_states[message.channel] = wordle.WordleState()
wordle_state = wordle_states[message.channel]
# Parse message based on number of words in it
if number_of_messages == 0 or split_message[0].lower() not in COMMANDS:
return None, None, None # Ignore this message, it's not for this bot
if number_of_messages == 1:
# Make a new game (if one isn't already in progress)
if not wordle_state.game or wordle_state.game.won:
try:
wordle_state.create_game()
print("new game:", wordle_state.game.word)
return (
False,
COLOR_CORRECT,
f"New game started! (Word has {len(wordle_state.game.word)} letters and is from word list {wordle_state.word_list['name']})",
)
except wordle.NoWordsException as ex:
return False, COLOR_ERROR, str(ex)
else:
return False, COLOR_ERROR, "There's already a game in progress!"
elif number_of_messages == 2:
# Take a guess
guess = split_message[1].lower()
try:
won = wordle_state.game.guess(guess)
img = get_image_from_guesses(wordle_state.game.guesses)
file = discord.File(img, "guesses.png")
if won:
guesses = wordle_state.game.guesses
return (
True,
COLOR_CORRECT,
f"\nCongrats! You guessed right after {len(guesses)} guess{'es' if len(guesses)>1 else ''}.",
file,
)
else:
return (
False,
COLOR_STANDARD,
f"Letters you haven't tried: {wordle_state.game.get_letters_not_tried()}",
file,
)
except wordle.InvalidGuessException as ex:
return False, COLOR_ERROR, str(ex)
elif number_of_messages == 3:
# Change some settings
if split_message[1].lower() in [
"wordlist",
"word_list",
"words",
"wl",
"w",
"worte",
"wörter",
]:
try:
wordle_state.set_word_list(split_message[2])
return (
False,
COLOR_CORRECT,
f"Word list has been changed to {split_message[2]}: {wordle.WORD_LISTS[split_message[2].title()]['description']}!",
)
except wordle.InvalidSettingsException as ex:
return False, COLOR_ERROR, str(ex)
elif split_message[1].lower() in [
"guesslist",
"guess_list",
"guess",
"guesses",
"gl",
"g",
]:
try:
wordle_state.set_guess_list(split_message[2])
return (
False,
COLOR_CORRECT,
f"Guess list has been changed to {split_message[2]}: {wordle.WORD_LISTS[split_message[2].title()]['description']}!",
)
except wordle.InvalidSettingsException as ex:
return False, COLOR_ERROR, str(ex)
elif split_message[1].lower() in [
"alphabet",
"letters",
"buchstaben",
"characters",
]:
try:
wordle_state.set_alphabet(split_message[2])
return (
False,
COLOR_CORRECT,
f"Alphabet has been changed to {split_message[2]}: {wordle.LETTERS[split_message[2].title()]['description']}!",
)
except wordle.InvalidSettingsException as ex:
return False, COLOR_ERROR, str(ex)
elif split_message[1] in ["length", "size", "länge", "l"]:
new_length = split_message[2]
if not new_length.isnumeric():
return False, COLOR_ERROR, "New length must be a number!"
try:
wordle_state.set_length(int(new_length), int(new_length))
return (
False,
COLOR_CORRECT,
f"Length for new words has been set to {new_length}.",
)
except wordle.InvalidSettingsException as ex:
return False, COLOR_ERROR, str(ex)
else:
return (
False,
COLOR_ERROR,
"Not a valid setting. Try word_list, guess_list, or length!",
)
elif number_of_messages == 4:
# Change settings (because length may take two arguments)
if split_message[1] in ["length", "size", "länge", "l"]:
new_min_length = split_message[2]
new_max_length = split_message[3]
if not new_min_length.isnumeric() or not new_max_length.isnumeric():
return False, COLOR_ERROR, "New length must be a number!"
try:
wordle_state.set_length(int(new_min_length), int(new_max_length))
return (
False,
COLOR_CORRECT,
f"Length for new words has been set to {new_min_length}-{new_max_length}.",
)
except wordle.InvalidSettingsException as ex:
return False, COLOR_ERROR, str(ex)
else:
return (
False,
COLOR_ERROR,
"Not a valid setting. Try word_list, guess_list, or length!",
)
else:
return False, COLOR_ERROR, "Too many words!"
return False, COLOR_ERROR, "Are you talking to me? Something went wrong."
async def send_embed(channel, title, color, description, url=None, file=None):
"""Sends an embed to the specified channel"""
embed = discord.Embed(
title=title,
colour=color,
description=description,
)
length_string = f"{wordle_states[channel].min_length if wordle_states[channel].min_length == wordle_states[channel].max_length else str(wordle_states[channel].min_length) + '-' + str(wordle_states[channel].max_length)}"
embed.set_footer(
text=f"Wortlerino v{VERSION} - ({wordle_states[channel].word_list['name']}/{wordle_states[channel].guess_list['name']}/{length_string})"
)
if url:
embed.url = url
if file is not None:
embed.set_image(url=f"attachment://{file.filename}")
await channel.send(embed=embed, file=file)
@client.event
async def on_ready():
"""Connected to discord"""
print("Ready.")
print("Name:", client.user.name)
print("ID:", client.user.id)
print()
@client.event
async def on_message(message):
"""When a message is sent"""
file = None
won, color, response, *rest = parse_message(message)
if rest:
file = rest[0]
if won is not None:
print("Parsed message:", message.content)
if won:
await send_embed(
message.channel,
wordle_states[message.channel].game.word.upper(),
color,
response,
WIKILINK.replace(
"XX", wordle_states[message.channel].word_list["language"]
)
+ wordle_states[message.channel].game.word.title(),
file=file,
)
else:
await send_embed(message.channel, "", color, response, file=file)
# Start the whole thing
client.run(TOKEN)