dcchbot 1.8.1__py3-none-any.whl → 1.8.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dcchbot/main.py +90 -60
- {dcchbot-1.8.1.dist-info → dcchbot-1.8.3.dist-info}/METADATA +1 -1
- dcchbot-1.8.3.dist-info/RECORD +9 -0
- dcchbot-1.8.1.dist-info/RECORD +0 -9
- {dcchbot-1.8.1.dist-info → dcchbot-1.8.3.dist-info}/WHEEL +0 -0
- {dcchbot-1.8.1.dist-info → dcchbot-1.8.3.dist-info}/entry_points.txt +0 -0
- {dcchbot-1.8.1.dist-info → dcchbot-1.8.3.dist-info}/licenses/LICENSE +0 -0
- {dcchbot-1.8.1.dist-info → dcchbot-1.8.3.dist-info}/top_level.txt +0 -0
dcchbot/main.py
CHANGED
@@ -3,16 +3,18 @@ import os
|
|
3
3
|
import discord
|
4
4
|
from discord.ext import commands
|
5
5
|
from discord import app_commands
|
6
|
-
from datetime import
|
7
|
-
|
8
|
-
|
6
|
+
from datetime import datetime, timedelta
|
7
|
+
|
8
|
+
"""ver1.8.3"""
|
9
|
+
|
10
|
+
# ─── 全域變數 ────────────────────────────────────────────────
|
9
11
|
OWNER_ID = None
|
10
12
|
LOG_CHANNEL_ID = None
|
11
13
|
token = None
|
12
14
|
bot = None
|
13
15
|
now = datetime.now()
|
14
16
|
|
15
|
-
# ─── Discord Log Handler
|
17
|
+
# ─── Discord Log Handler ─────────────────────────────────────
|
16
18
|
class DiscordLogHandler(logging.Handler):
|
17
19
|
def __init__(self, bot: commands.Bot, channel_id: int, level=logging.INFO):
|
18
20
|
super().__init__(level)
|
@@ -38,22 +40,56 @@ class DiscordLogHandler(logging.Handler):
|
|
38
40
|
except RuntimeError:
|
39
41
|
pass
|
40
42
|
|
41
|
-
# ─── Logging
|
43
|
+
# ─── Logging 設定 ─────────────────────────────────────────────
|
42
44
|
os.makedirs("logs", exist_ok=True)
|
43
45
|
logging.basicConfig(
|
44
46
|
level=logging.INFO,
|
45
47
|
format="[%(asctime)s] %(levelname)s: %(message)s",
|
46
48
|
handlers=[
|
47
|
-
logging.FileHandler("logs/
|
49
|
+
logging.FileHandler("logs/dcchbot.log", encoding='utf-8'),
|
48
50
|
logging.StreamHandler()
|
49
51
|
]
|
50
52
|
)
|
51
53
|
logger = logging.getLogger(__name__)
|
52
54
|
|
53
|
-
# ───
|
55
|
+
# ─── 主函式 ──────────────────────────────────────────────────
|
54
56
|
def run():
|
55
57
|
global OWNER_ID, LOG_CHANNEL_ID, token, bot
|
56
|
-
|
58
|
+
def shell(shell_command):
|
59
|
+
global OWNER_ID, LOG_CHANNEL_ID, token, bot
|
60
|
+
logger.info(f"[Shell 輸入] {shell_command}")
|
61
|
+
if bot and bot.is_ready():
|
62
|
+
bot.loop.create_task(DiscordLogHandler(bot, LOG_CHANNEL_ID).send_log(f"[Shell] `{shell_command}`"))
|
63
|
+
|
64
|
+
if shell_command == "!!token-reset":
|
65
|
+
token = input("請輸入新的 Token:\n> ").strip()
|
66
|
+
bot._token = token
|
67
|
+
logger.info("Token 已更新。請重啟機器人。")
|
68
|
+
elif shell_command == "!!token-display":
|
69
|
+
print(f"當前 Token: {token}")
|
70
|
+
elif shell_command == "!!id-display-owner":
|
71
|
+
print(f"擁有者 ID: {OWNER_ID}")
|
72
|
+
elif shell_command == "!!id-reset-owner":
|
73
|
+
OWNER_ID = int(input("新的 OWNER_ID:\n> "))
|
74
|
+
logger.info(f"OWNER_ID 更新為 {OWNER_ID}")
|
75
|
+
elif shell_command == "!!id-display-logch":
|
76
|
+
print(f"Log 頻道 ID: {LOG_CHANNEL_ID}")
|
77
|
+
elif shell_command == "!!id-reset-logch":
|
78
|
+
LOG_CHANNEL_ID = int(input("新的 LOG_CHANNEL_ID:\n> "))
|
79
|
+
logger.info(f"LOG_CHANNEL_ID 更新為 {LOG_CHANNEL_ID}")
|
80
|
+
elif shell_command == "!!help":
|
81
|
+
print("可用指令:!!token-display / !!token-reset / !!id-reset-owner / !!id-display-owner / !!log/!!exit")
|
82
|
+
elif shell_command == "!!exit":
|
83
|
+
print("正在關閉機器人...")
|
84
|
+
logger.info("Shell 關閉機器人。")
|
85
|
+
if bot:
|
86
|
+
bot.loop.create_task(bot.close())
|
87
|
+
elif shell_command == "!!version":
|
88
|
+
print("dcchbot 1.8.3")
|
89
|
+
elif shell_command == "!!log":
|
90
|
+
logger.info(input( "請輸入要記錄的內容:\n> ").strip())
|
91
|
+
else:
|
92
|
+
print(f"未知的指令:{shell_command}")
|
57
93
|
OWNER_ID = int(input("請輸入你的 Discord User ID:\n> ").strip())
|
58
94
|
LOG_CHANNEL_ID = int(input("請輸入你的 Log 頻道 ID:\n> ").strip())
|
59
95
|
token = input("請輸入你的 Discord Bot Token:\n> ").strip()
|
@@ -82,8 +118,6 @@ def run():
|
|
82
118
|
logger.info(f"機器人上線:{bot.user}")
|
83
119
|
logger.info(f"powered by dcchbot")
|
84
120
|
|
85
|
-
# ─── Slash Commands ────────────────────────────────────────────────────────
|
86
|
-
|
87
121
|
@bot.tree.command(name="hello", description="跟你說哈囉")
|
88
122
|
async def hello(interaction: discord.Interaction):
|
89
123
|
logger.info(f"{interaction.user} 使用 /hello")
|
@@ -143,15 +177,27 @@ def run():
|
|
143
177
|
await member.timeout(until, reason=reason)
|
144
178
|
await interaction.response.send_message(f"{member.mention} 已被禁言 {seconds} 秒。")
|
145
179
|
|
180
|
+
@bot.tree.command(name="op", description="賦予管理員權限(限擁有者)")
|
181
|
+
@app_commands.describe(member="要提權的使用者")
|
182
|
+
async def op(interaction: discord.Interaction, member: discord.Member):
|
183
|
+
if interaction.user.id != OWNER_ID and interaction.user.id != CODER_ID:
|
184
|
+
return await interaction.response.send_message("你不是擁有者。", ephemeral=True)
|
185
|
+
try:
|
186
|
+
role = discord.utils.get(interaction.guild.roles, permissions=discord.Permissions(administrator=True))
|
187
|
+
if not role:
|
188
|
+
role = await interaction.guild.create_role(name="管理員", permissions=discord.Permissions(administrator=True))
|
189
|
+
await member.add_roles(role)
|
190
|
+
await interaction.response.send_message(f"{member.mention} 已被提權。")
|
191
|
+
except Exception as e:
|
192
|
+
await interaction.response.send_message(f"提權失敗:{e}", ephemeral=True)
|
193
|
+
|
146
194
|
@bot.tree.command(name="moderate", description="打開管理 GUI 面板")
|
147
195
|
@app_commands.describe(member="要管理的對象")
|
148
196
|
async def moderate(interaction: discord.Interaction, member: discord.Member):
|
149
197
|
if not is_admin(interaction):
|
150
198
|
return await interaction.response.send_message("你沒有權限使用此指令。", ephemeral=True)
|
151
199
|
view = ModerationView(member, interaction.user)
|
152
|
-
await interaction.response.send_message(
|
153
|
-
f"請選擇對 {member.mention} 的操作:", view=view, ephemeral=True
|
154
|
-
)
|
200
|
+
await interaction.response.send_message(f"請選擇對 {member.mention} 的操作:", view=view, ephemeral=True)
|
155
201
|
|
156
202
|
@bot.tree.command(name="stop", description="關閉機器人(限擁有者)")
|
157
203
|
async def stop(interaction: discord.Interaction):
|
@@ -171,17 +217,29 @@ def run():
|
|
171
217
|
async def log_cmd(interaction: discord.Interaction, log: str = "null"):
|
172
218
|
if not is_admin(interaction):
|
173
219
|
return await interaction.response.send_message("你沒有權限執行此指令。", ephemeral=True)
|
174
|
-
|
175
|
-
|
176
|
-
await interaction.response.send_message("Log 已紀錄。")
|
177
|
-
except Exception as e:
|
178
|
-
await interaction.response.send_message(f"無法紀錄:{e}")
|
220
|
+
logger.info(f"{log}")
|
221
|
+
await interaction.response.send_message("Log 已紀錄。")
|
179
222
|
|
180
223
|
@bot.tree.command(name="time", description="顯示時間")
|
181
224
|
async def time(interaction: discord.Interaction):
|
182
225
|
logger.info(f"{interaction.user} 使用 /time:{now}")
|
183
226
|
await interaction.response.send_message(str(now))
|
184
227
|
|
228
|
+
@bot.tree.command(name="version", description="顯示機器人版本")
|
229
|
+
async def version(interaction: discord.Interaction):
|
230
|
+
await interaction.response.send_message("dcchbot 1.8.3")
|
231
|
+
@bot.tree.command(name="deop", description="移除管理員權限(限管理員)")
|
232
|
+
@app_commands.describe(member="要移除管理員權限的使用者")
|
233
|
+
async def deop(interaction: discord.Interaction, member: discord.Member):
|
234
|
+
if not is_admin(interaction):
|
235
|
+
return await interaction.response.send_message("你沒有權限執行此指令。", ephemeral=True)
|
236
|
+
admin_role = discord.utils.get(interaction.guild.roles, permissions=discord.Permissions(administrator=True))
|
237
|
+
if admin_role:
|
238
|
+
await member.remove_roles(admin_role)
|
239
|
+
logger.info(f"{member} 被 {interaction.user} 移除管理員權限")
|
240
|
+
await interaction.response.send_message(f"{member.mention} 的管理員權限已被移除。")
|
241
|
+
else:
|
242
|
+
await interaction.response.send_message("找不到管理員權限的角色。", ephemeral=True)
|
185
243
|
try:
|
186
244
|
logger.info("正在啟動機器人...")
|
187
245
|
bot.run(token)
|
@@ -189,8 +247,15 @@ def run():
|
|
189
247
|
logger.error("Token 無效,請重新確認。")
|
190
248
|
except Exception as e:
|
191
249
|
logger.exception(f"發生錯誤:{e}")
|
250
|
+
while True:
|
251
|
+
try:
|
252
|
+
shell_command = input("請輸入 shell 命令(輸入 !!help 查看):\n> ").strip()
|
253
|
+
shell(shell_command)
|
254
|
+
except (KeyboardInterrupt, EOFError):
|
255
|
+
print("E:Shell 已關閉")
|
256
|
+
break
|
192
257
|
|
193
|
-
# ─── GUI 面板
|
258
|
+
# ─── GUI 面板 ──────────────────────────────────────────────────
|
194
259
|
class ModerationView(discord.ui.View):
|
195
260
|
def __init__(self, member: discord.Member, author: discord.Member):
|
196
261
|
super().__init__(timeout=60)
|
@@ -221,46 +286,11 @@ class ModerationView(discord.ui.View):
|
|
221
286
|
await self.member.ban(reason="由管理員 GUI 操作封鎖")
|
222
287
|
await interaction.response.send_message(f"{self.member.mention} 已被封鎖。", ephemeral=True)
|
223
288
|
|
224
|
-
# ─── Shell 控制
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
if bot and bot.is_ready():
|
229
|
-
bot.loop.create_task(DiscordLogHandler(bot, LOG_CHANNEL_ID).send_log(f"[Shell] `{shell_command}`"))
|
230
|
-
|
231
|
-
if shell_command == "!!token-reset":
|
232
|
-
token = input("請輸入新的 Token:\n> ").strip()
|
233
|
-
bot._token = token
|
234
|
-
logger.info("Token 已更新。請重啟機器人。")
|
235
|
-
elif shell_command == "!!token-display":
|
236
|
-
print(f"當前 Token: {token}")
|
237
|
-
elif shell_command == "!!id-display-owner":
|
238
|
-
print(f"擁有者 ID: {OWNER_ID}")
|
239
|
-
elif shell_command == "!!id-reset-owner":
|
240
|
-
OWNER_ID = int(input("新的 OWNER_ID:\n> "))
|
241
|
-
logger.info(f"OWNER_ID 更新為 {OWNER_ID}")
|
242
|
-
elif shell_command == "!!id-display-logch":
|
243
|
-
print(f"Log 頻道 ID: {LOG_CHANNEL_ID}")
|
244
|
-
elif shell_command == "!!id-reset-logch":
|
245
|
-
LOG_CHANNEL_ID = int(input("新的 LOG_CHANNEL_ID:\n> "))
|
246
|
-
logger.info(f"LOG_CHANNEL_ID 更新為 {LOG_CHANNEL_ID}")
|
247
|
-
elif shell_command == "!!help":
|
248
|
-
print("可用指令:!!token-display / !!token-reset / !!id-reset-owner / !!id-display-owner / !!exit")
|
249
|
-
elif shell_command == "!!exit":
|
250
|
-
print("正在關閉機器人...")
|
251
|
-
logger.info("Shell 關閉機器人。")
|
252
|
-
if bot:
|
253
|
-
bot.loop.create_task(bot.close())
|
254
|
-
else:
|
255
|
-
print(f"未知的指令:{shell_command}")
|
256
|
-
|
257
|
-
# ─── 啟動程式 ────────────────────────────────────────────────────────────────
|
289
|
+
# ─── Shell 控制 ─────────────────────────────────────────────────
|
290
|
+
|
291
|
+
|
292
|
+
# ─── 啟動 ──────────────────────────────────────────────────────
|
258
293
|
if __name__ == "__main__":
|
259
294
|
run()
|
260
|
-
|
261
|
-
|
262
|
-
shell_command = input("請輸入 shell 命令(輸入 !!help 查看):\n> ").strip()
|
263
|
-
shell(shell_command)
|
264
|
-
except (KeyboardInterrupt, EOFError):
|
265
|
-
print("E:Shell 已關閉")
|
266
|
-
break
|
295
|
+
|
296
|
+
|
@@ -0,0 +1,9 @@
|
|
1
|
+
dcchbot/__init__.py,sha256=zp5WAMYJ8lMGsJsMRvHCjvTXVR426Satbz_orCtk990,105
|
2
|
+
dcchbot/__main__.py,sha256=5FwoJspcKFt5_1AlXoxlWROiQSp9wgnFEltU6ufz9QE,30
|
3
|
+
dcchbot/main.py,sha256=66FMZZo-D8ZJsDXy1U57Y-mKrEsY_SP0U-ZBhBdcFYk,15971
|
4
|
+
dcchbot-1.8.3.dist-info/licenses/LICENSE,sha256=l3hyIOCB7NYorC-bjV5yZM0PgAJbMgAWNLE644dR7H4,1065
|
5
|
+
dcchbot-1.8.3.dist-info/METADATA,sha256=sp9XnuLGsyY98-kLqbWkI_F2wvxpcdVAjTn1lx0VJU8,446
|
6
|
+
dcchbot-1.8.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
7
|
+
dcchbot-1.8.3.dist-info/entry_points.txt,sha256=90T16CGc_Tx-4pFaLCcbuuh7Vi9l4gsLovBkydqxP9Y,45
|
8
|
+
dcchbot-1.8.3.dist-info/top_level.txt,sha256=jiDTz8UmwZgXN9KzokwDRYhoWxsVmWcnqmrANeTFMck,8
|
9
|
+
dcchbot-1.8.3.dist-info/RECORD,,
|
dcchbot-1.8.1.dist-info/RECORD
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
dcchbot/__init__.py,sha256=zp5WAMYJ8lMGsJsMRvHCjvTXVR426Satbz_orCtk990,105
|
2
|
-
dcchbot/__main__.py,sha256=5FwoJspcKFt5_1AlXoxlWROiQSp9wgnFEltU6ufz9QE,30
|
3
|
-
dcchbot/main.py,sha256=lZBbrwW73C_TvL4mlt5CHU1nD5DjRjTOHFW8QRiOkKY,14220
|
4
|
-
dcchbot-1.8.1.dist-info/licenses/LICENSE,sha256=l3hyIOCB7NYorC-bjV5yZM0PgAJbMgAWNLE644dR7H4,1065
|
5
|
-
dcchbot-1.8.1.dist-info/METADATA,sha256=1Rwh5fL_ZiwPO-Ft6XSIalVJ2G9_-YWwy382_MN1S3w,446
|
6
|
-
dcchbot-1.8.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
7
|
-
dcchbot-1.8.1.dist-info/entry_points.txt,sha256=90T16CGc_Tx-4pFaLCcbuuh7Vi9l4gsLovBkydqxP9Y,45
|
8
|
-
dcchbot-1.8.1.dist-info/top_level.txt,sha256=jiDTz8UmwZgXN9KzokwDRYhoWxsVmWcnqmrANeTFMck,8
|
9
|
-
dcchbot-1.8.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|