-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patherpgbot.py
193 lines (150 loc) · 7.73 KB
/
erpgbot.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
#!/usr/bin/python3
import logging
import random
import os
import re
import discord
from discord.ext import commands
import asyncio
from dotenv import load_dotenv
load_dotenv()
from handlers import *
from helpers import *
class ERPGBot(discord.Client):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Read env vars
self.bot_stuff_channel = int(os.getenv("EPIC_RPG_BOT_CHANNEL"))
self.work_command = os.getenv("WORK_COMMAND")
self.hp_threshold = int(os.getenv("HP_THRESHOLD"))
# Set up logging
self.logger = logging.getLogger("discord")
self.logger.setLevel(logging.DEBUG)
self.handler = logging.FileHandler(filename="log/erpgbot.log", encoding="utf-8", mode="w")
self.handler.setFormatter(logging.Formatter("%(asctime)s:%(levelname)s:%(name)s: %(message)s"))
self.logger.addHandler(self.handler)
# Set up our queue
self.msg_queue = asyncio.PriorityQueue()
# Initialize an empty variable to hold the channel ID. We set this at 0
# to start so that we can wait for the channels to be populated. Normally
# these would get populated after waiting for ready, but this doesn't
# work when bot=False is set in the client at runtime
self.channel = 0
# Set up our handler classes (if they're classes)
self.training_handler = HandleTraining()
# Keep a list of various actions to perform with our queue handler
self.ready_actions_todo = []
self.inventory_actions_todo = []
# Keep an up-to-date dictionary of our player's inventory
self.player_inventory = {}
# create our background tasks
self.loop.create_task(self.perform_action_handler())
self.loop.create_task(self.perform_ready_check_handler())
self.loop.create_task(self.perform_inventory_handler())
async def on_ready(self):
print("We're ready!")
async def on_message(self, message):
# Ignore messages from "EPIC RPG Support Server" explicitly
if str(message.guild) == "EPIC RPG Support Server":
return
# Ignore messages that aren't in the bot channel
elif message.channel.id != self.bot_stuff_channel:
return
# Detect the EPIC GUARD captcha and shut 'er down until we can reliably solve captcha
elif message.content.startswith(f':police_car: **EPIC GUARD**: stop there, <@{client.user.id}>'):
guard_answer = handle_guard(message)
print(f"GUARD ANSWER: {guard_answer}")
if guard_answer == "none found":
await self.close()
else:
await self.msg_queue.put((0, guard_answer))
# Handle "IN THE JAIL" events:
elif f"{client.user.name} is now in the jail!" in message.content:
await self.close()
# Handle healing ones self
elif message.content.startswith(f'**{client.user.name}** found'):
if (handle_life_check(message.content, self.hp_threshold) == True) or (r'**Your horse** saved you') in message.content:
await self.msg_queue.put((1, "rpg heal"))
# Handle receiving a lootbox
elif re.search(r'.+got (a|an)\s(.+lootbox)\s', message.content):
match = re.search(r'.+got (a|an)\s(.+lootbox)\s', message.content).group(2).lower()
await self.msg_queue.put((2, f"rpg open {match}"))
# Handle "GOD DROPPED" events
elif (message.author == "EPIC RPG#4117") and ("OOPS! God accidentally dropped" in message.embeds[0].fields[0].name):
god_made_me_say = re.search(r'\*{2}(.+?)\*{2}', message.embeds[0].fields[0].value).group(1)
print(f"GOD MADE ME SAY IT: {god_made_me_say}")
await self.msg_queue.put((0, god_made_me_say))
# "RPG DUEL" - Handle duel requests
elif f'rpg duel <@{client.user.id}>' in message.content.lower():
await asyncio.sleep(1)
await handle_duels(self.msg_queue)
# "RPG TRAINING" - Handle training messages
elif message.content.startswith(f'**{client.user.name}** is training in the'):
training_answer = self.training_handler.handle_training(message.content, self.player_inventory)
await self.msg_queue.put((0, training_answer))
# "RPG RD" - Parse 'rpg rd' responses and place ready actions into self.ready_actions_todo
elif (message.embeds) and (message.embeds[0].author.name == f"{client.user.name}'s ready"):
self.ready_actions_todo = await parse_cooldown(message.embeds[0])
while self.ready_actions_todo:
action = self.ready_actions_todo.pop(0)
if action == "chop | fish | pickup | mine":
action = self.work_command
if action == "adventure":
await self.msg_queue.put((1, "rpg heal"))
await self.msg_queue.put((2, f'rpg {action}'))
# "RPG INVENTORY" - Parse 'rpg inventory' responses and put into self.player_inventory,
# then put inventory actions onto the queue
elif (message.embeds) and (message.embeds[0].author.name == f"{client.user.name}'s inventory"):
self.player_inventory = await parse_inventory(message.embeds[0])
self.inventory_actions_todo = await handle_inventory(self.player_inventory)
while self.inventory_actions_todo:
action = self.inventory_actions_todo.pop(0)
await self.msg_queue.put((action[0], f'rpg {action[1]}'))
# Print everything
print(f"{message.guild} | {message.channel} | {message.author} | {message.content} | {message.attachments}")
self.print_embeds(message.embeds)
async def perform_action_handler(self):
''' This is the FIFO queue that will accept action commands
that will be sent to the channel to be read/handled by
the Epic RPG Bot. It uses the following priorities.
0 : must be done immediately because of blocking by the bot
1 : things like healing or buying potions when empty
2 : last priority / do whenever
'''
await asyncio.sleep(5)
self.channel = self.get_channel(self.bot_stuff_channel)
while True:
msg = await self.msg_queue.get()
await self.channel.send(msg[1])
self.msg_queue.task_done()
await asyncio.sleep(5)
async def perform_ready_check_handler(self):
''' Perform a ready check every (n) seconds'''
while True:
# If the queue is empty and there's no items in self.ready_actions_todo,
# put a ready check into the queue
if (self.msg_queue.empty()) and not (self.ready_actions_todo):
await self.msg_queue.put((2, 'rpg rd'))
await asyncio.sleep(65)
async def perform_inventory_handler(self):
''' Every (n) seconds, perform an 'rpg inventory' '''
while True:
await self.msg_queue.put((2, 'rpg inventory'))
await asyncio.sleep(300)
# Pretty print message embeds (for testing)
def print_embeds(self, embeds):
for embed in embeds:
print("=====================\n" \
f"Author: {embed.author.name}\n" \
f"Title: {embed.title}\n" \
f"Description: {embed.description}\n" \
f"URL: {embed.url}\n" \
"---------------\n")
for field in embed.fields:
print("%s" % field.name)
print("------------------")
for each in field.value.split("\n"):
print("%s" % each)
print("=====================")
client = ERPGBot()
client.run(os.getenv("DISCORD_TOKEN"), bot=False)