-
Notifications
You must be signed in to change notification settings - Fork 19
/
main.py
228 lines (186 loc) · 8.83 KB
/
main.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
from discord.ext import commands
from discord.commands import slash_command, ApplicationContext
import discord
import config
from db.seta_pgsql import S_PgSQL
from db.seta_sqlite import S_SQLite
from utils import logger
import traceback
import os
from datetime import datetime
from constants import Constants
from classes.user import fishing_now
logger.info("이프가 잠에서 깨어나는 중...")
boot_start = datetime.today()
LOADING_DIR = ["cogs", "cogs/fishing"]
db = S_PgSQL()
intents = discord.Intents.default()
# intents.message_content = True
fishdb = S_SQLite("static/fishing.db")
class EpBot(discord.AutoShardedBot):
def __init__(self):
super().__init__(
help_command=None,
intents=intents,
debug_guilds=config.SLASH_COMMAND_REGISTER_SERVER,
)
# Cogs 로드(Cogs 폴더 안에 있는 것이라면 자동으로 인식합니다)
self.add_cog(ManagementCog(self)) # 기본 제공 명령어 Cog
for _dir in LOADING_DIR:
cog_list = [i.split(".")[0] for i in os.listdir(_dir) if ".py" in i]
cog_list.remove("__init__")
for i in cog_list:
logger.info(f"{_dir.replace('/', '.')}.{i} 로드")
self.load_extension(f"{_dir.replace('/', '.')}.{i}")
async def on_ready(self):
"""봇이 구동되면 시작되는 부분"""
boot_end = datetime.today()
boot_time = boot_end - boot_start
logger.info("///////////////////// ! 이프 기상 ! /////////////////////")
logger.info(f"봇 계정 정보 : {self.user.name} ({self.user.id})")
logger.info(f"서버 수 : {len(self.guilds)}곳")
logger.info(f"디스코드 버전 : {discord.__version__}")
logger.info(f"계정 길드 인텐트 활성화 : {self.intents.guilds}")
logger.info(f"계정 멤버 인텐트 활성화 : {self.intents.members}")
logger.info(f"디버그 모드 활성화 : {config.debug}")
logger.info(f"일어날 때까지 {boot_time.total_seconds()}초 만큼 걸렸어!")
logger.info(f"슬래시 커맨드 등록 서버 지정 : {bool(config.SLASH_COMMAND_REGISTER_SERVER)}")
if config.SLASH_COMMAND_REGISTER_SERVER:
logger.info(f"sid {config.SLASH_COMMAND_REGISTER_SERVER}")
logger.info("////////////////////////////////////////////////////////")
await self.change_presence(status=discord.Status.online)
# 기본 제공 명령어
class ManagementCog(commands.Cog):
def __init__(self, bot):
self.bot = bot
@slash_command(name="물고기로드", guild_ids=config.ADMIN_COMMAND_GUILD)
async def reload_fish(self, ctx: discord.ApplicationContext):
await ctx.defer()
logger.info("Refreshing fish data...")
await db.delete_sql("fish", "")
data = fishdb.select_sql("fish", "*")
for i in data:
logger.info(str(i))
engname = f"'{i[10]}'" if i[10] else "NULL"
await db.insert_sql(
"fish",
"id, name, cost, length, seasons, rarity, biomes, user_num, historic, room_level, eng_name",
f"{i[0]}, '{i[1]}', {i[2]}, '{i[3]}', {i[4]}, '{i[5]}', {i[6]}, {i[7]}, {i[8]}, {i[9]}, {engname}",
)
logger.info("Fish data refreshed.")
await ctx.respond("끝!")
# cogs 폴더 안의 코드를 수정했다면 굳이 껐다 키지 않아도 다시시작 명령어로 적용이 가능해!
@slash_command(name="다시시작", guild_ids=config.ADMIN_COMMAND_GUILD)
async def 다시시작(self, ctx: discord.ApplicationContext):
if ctx.author.id not in config.ADMINS:
return await ctx.respond("흐음... 권한이 부족한 것 같은데?" "\n`❗ 권한이 부족합니다.`")
w = await ctx.respond("`❗ Cogs를 다시 불러오고 이써...`")
logger.info("이프 다시시작 중...")
for _dir in LOADING_DIR:
cog_list = [i.split(".")[0] for i in os.listdir(_dir) if ".py" in i]
cog_list.remove("__init__")
if "cycle" in cog_list:
cog_list.remove("cycle") # 스케듈러가 제거가 안 되어서 제외
for i in cog_list:
self.bot.reload_extension(f"{_dir.replace('/', '.')}.{i}")
logger.info(f"'{i}' 다시 불러옴")
logger.info("다시시작 완료!")
await ctx.edit(content="`✔️ 전부 다시 불러와써!`")
"""
@slash_command(name="info", description="Show Information about EpBot!")
async def info(self, ctx: discord.ApplicationContext):
embed = discord.Embed(
title="Information about EpBot(이프)",
description="This bot is a project designed based on Kimusoft's Thetabot V2 framework.",
colour=0x1DDB16,
)
embed.add_field(
name="'키뮤의 과학실' Official Support Sever Link",
value="🔗 https://discord.gg/XQuexpQ",
inline=True,
)
embed.set_footer(
text="Since this bot is originally a Korean bot, English support is still insufficient. 😭"
)
await ctx.respond(embed=embed)
"""
@commands.Cog.listener()
async def on_application_command(self, ctx: ApplicationContext):
args = ""
if ctx.selected_options:
for option in ctx.selected_options:
args += f"[Name: {option['name']}, Value: {option['value']}, Type: {Constants.OPTION_TYPES[option['type']]}] "
args = args[:-1]
guild = f"{ctx.guild}({ctx.guild.id})" if ctx.guild else "DM"
logger.info(f"{ctx.user}({ctx.user.id}) in {guild}: /{ctx.command.name} {args}")
@commands.Cog.listener()
async def on_application_command_error(
self, ctx: discord.ApplicationContext, error: Exception
):
"""명령어 내부에서 오류 발생 시 작동하는 코드 부분"""
user = ctx.author
if user.id in fishing_now:
fishing_now.remove(user.id)
if isinstance(error, discord.CheckFailure):
return
if isinstance(error, discord.ApplicationCommandInvokeError):
try:
if isinstance(error.original, discord.errors.NotFound):
return await ctx.respond(
"저기 혹시... 갑자기 메시지를 지우거나 한 건 아니지...? 그러지 말아 줘..."
)
raise error.original
except Exception as e:
logger.err(e)
await ctx.respond(f"으앙 오류가 발생했어...\n`❗ {str(e)}`")
await error_send(ctx, self.bot, e)
return
# 명령어 쿨타임이 다 차지 않은 경우
elif isinstance(error, commands.CommandOnCooldown):
await ctx.respond(
f"이 명령어는 {error.cooldown.rate}번 쓰면 {error.cooldown.per}초의 쿨타임이 생겨!"
f"\n`❗ {int(error.retry_after)}초 후에 다시 시도해 주십시오.`"
)
elif isinstance(error, commands.errors.CheckFailure):
pass
# ServerDisconnectedError의 경우 섭렉으로 판정
elif "ServerDisconnectedError" in str(error):
await ctx.respond(f"미, 미아내! 디스코드 랙이 있던 것 같아...\n`❗ {error}`")
await error_send(ctx, self.bot, error, 0xFFBB00)
else:
logger.err(error)
await ctx.respond(f"으앙 오류가 발생했어...\n`❗ {str(error)}`")
await error_send(ctx, self.bot, error)
@commands.Cog.listener()
async def on_message(self, msg: discord.Message): # 메시지 처리
if (
msg.content.startswith("이프야")
or msg.content == "ㅇ낚시"
or msg.content == "ㅇㄴㅅ"
):
await msg.reply("머랭!\n`❗ 이제 이프는 슬래시 커맨드를 지원합니다! 채팅창에 한 번 '/'를 쳐 보세요!`")
async def error_send(ctx, bot, error, color=0x980000):
try:
raise error
except Exception:
error_message = traceback.format_exc().split(
"The above exception was the direct cause of the following exception:"
)[0]
error_message.strip()
time = datetime.today()
embed = discord.Embed(
title=f"❗ 오류 발생 / {error}",
description=f"```{error_message}```",
colour=color,
)
embed.set_author(name=ctx.author)
embed.set_footer(
text=f"(서버) {ctx.guild.name} / (채널) {ctx.channel.name} / (시간) {time.strftime('%Y-%m-%d %Hh %Mmin')}"
)
try:
await bot.get_channel(config.ERROR_LOGGING_CHANNEL).send(embed=embed)
except Exception as e:
logger.warn(f"오류 보드에 전송 실패\n{e}")
logger.err(error)
epbot = EpBot()
epbot.run(token=config.token())