Переглянути джерело

Moving bot class to separate file, renaming entry script to main.py

tags/2.0.0
Rocketsoup 2 місяці тому
джерело
коміт
f271ff7e62
5 змінених файлів з 76 додано та 51 видалено
  1. 1
    1
      README.md
  2. 1
    1
      docs/setup.md
  3. 27
    0
      main.py
  4. 42
    49
      rocketbot/bot.py
  5. 5
    0
      rocketbot/cogs/generalcog.py

+ 1
- 1
README.md Переглянути файл

@@ -14,7 +14,7 @@ In brief, the full setup process is:
14 14
 - create a Discord application in their developer portal
15 15
 - configure a `config.py`
16 16
 - install Python dependencies
17
-- run the `bot.py` script
17
+- run the `main.py` script
18 18
 - invite the bot to your server
19 19
 - do additional configuration for your guild using chat commands
20 20
 

+ 1
- 1
docs/setup.md Переглянути файл

@@ -83,7 +83,7 @@ Mac-specificness. Linux will be similar. Windows probably won't be as similar.
83 83
 2. Run the bot
84 84
     ```shell
85 85
     source .venv/bin/activate   # skip if you already just did it above
86
-    python bot.py
86
+    python main.py
87 87
     ```
88 88
 
89 89
 It will take a few seconds to connect and when you see output like this it means

+ 27
- 0
main.py Переглянути файл

@@ -0,0 +1,27 @@
1
+"""
2
+Rocketbot Discord bot. Relies on a configured config.py (copy config.sample.py
3
+for a template).
4
+
5
+Author: Ian Albert (@rocketsoup)
6
+Date: 2021-11-11
7
+"""
8
+import asyncio
9
+
10
+from config import CONFIG
11
+from rocketbot.bot import start_bot
12
+from rocketbot.utils import bot_log
13
+
14
+CURRENT_CONFIG_VERSION = 3
15
+if (CONFIG.get('__config_version') or 0) < CURRENT_CONFIG_VERSION:
16
+	# If you're getting this error, it means something changed in config.py's
17
+	# format. Consult config.sample.py and compare it to your own config.py.
18
+	# Rename/move any values as needed. When satisfied, update "__config_version"
19
+	# to the value in config.sample.py. ...I know, pretty janky migration process.
20
+	raise RuntimeError('config.py format may be outdated. Review ' +
21
+		'config.sample.py, update the "__config_version" field to ' +
22
+		f'{CURRENT_CONFIG_VERSION}, and try again.')
23
+
24
+try:
25
+	asyncio.run(start_bot())
26
+except KeyboardInterrupt:
27
+	bot_log(None, None, 'Stopping bot due to Ctrl+C key')

bot.py → rocketbot/bot.py Переглянути файл

@@ -1,39 +1,12 @@
1
-"""
2
-Rocketbot Discord bot. Relies on a configured config.py (copy config.sample.py
3
-for a template).
4
-
5
-Author: Ian Albert (@rocketsoup)
6
-Date: 2021-11-11
7
-"""
8
-import asyncio
9 1
 import traceback
2
+from typing import Optional
10 3
 
11 4
 from discord import Intents
12 5
 from discord.ext import commands
13 6
 
14 7
 from config import CONFIG
15
-from rocketbot.cogs.autokickcog import AutoKickCog
16
-from rocketbot.cogs.configcog import ConfigCog
17
-from rocketbot.cogs.crosspostcog import CrossPostCog
18
-from rocketbot.cogs.generalcog import GeneralCog
19
-from rocketbot.cogs.joinagecog import JoinAgeCog
20
-from rocketbot.cogs.joinraidcog import JoinRaidCog
21
-from rocketbot.cogs.logcog import LoggingCog
22
-from rocketbot.cogs.patterncog import PatternCog
23
-from rocketbot.cogs.urlspamcog import URLSpamCog
24
-from rocketbot.cogs.usernamecog import UsernamePatternCog
25 8
 from rocketbot.utils import bot_log
26 9
 
27
-CURRENT_CONFIG_VERSION = 3
28
-if (CONFIG.get('__config_version') or 0) < CURRENT_CONFIG_VERSION:
29
-	# If you're getting this error, it means something changed in config.py's
30
-	# format. Consult config.sample.py and compare it to your own config.py.
31
-	# Rename/move any values as needed. When satisfied, update "__config_version"
32
-	# to the value in config.sample.py. ...I know, pretty janky migration process.
33
-	raise RuntimeError('config.py format may be outdated. Review ' +
34
-		'config.sample.py, update the "__config_version" field to ' +
35
-		f'{CURRENT_CONFIG_VERSION}, and try again.')
36
-
37 10
 class Rocketbot(commands.Bot):
38 11
 	"""
39 12
 	Bot subclass
@@ -41,8 +14,13 @@ class Rocketbot(commands.Bot):
41 14
 	def __init__(self, command_prefix, **kwargs):
42 15
 		super().__init__(command_prefix, **kwargs)
43 16
 
44
-	async def on_command_error(self, context: commands.Context, exception):
45
-		bot_log(None, None, 'Command error:\n' + '\n'.join(traceback.format_stack()))
17
+	async def on_command_error(self, context: commands.Context, exception: BaseException) -> None:
18
+		bot_log(None, None, f'Command error')
19
+		ex = exception
20
+		while ex is not None:
21
+			print(f'Caused by {ex}')
22
+			traceback.print_exception(type(ex), ex, ex.__traceback__)
23
+			ex = ex.__cause__ if ex.__cause__ != ex else None
46 24
 		if context.guild is None or \
47 25
 				context.message.channel is None or \
48 26
 				context.message.author.bot:
@@ -57,7 +35,6 @@ class Rocketbot(commands.Bot):
57 35
 				mention_author=False)
58 36
 			return
59 37
 		# Stack trace everything else
60
-		# traceback.print_exception(type(exception), exception, exception.__traceback__)
61 38
 
62 39
 	async def on_error(self, event_method, args=None, kwargs=None):
63 40
 		bot_log(None, None, 'Event caused error\n' + \
@@ -66,34 +43,50 @@ class Rocketbot(commands.Bot):
66 43
 			f'	event kwargs: {kwargs}' + \
67 44
 			traceback.format_exc())
68 45
 
69
-async def start_bot():
46
+# Current active bot instance
47
+rocketbot: Optional[Rocketbot] = None
48
+
49
+def __create_bot():
50
+	global rocketbot
51
+	if rocketbot is not None:
52
+		return
53
+	bot_log(None, None, 'Creating bot...')
70 54
 	intents = Intents.default()
71 55
 	intents.messages = True  # pylint: disable=assigning-non-slot
72 56
 	intents.message_content = True  # pylint: disable=assigning-non-slot
73 57
 	intents.members = True  # pylint: disable=assigning-non-slot
74 58
 	intents.presences = True
59
+	rocketbot = Rocketbot(command_prefix=CONFIG['command_prefix'], intents=intents)
60
+__create_bot()
61
+
62
+from rocketbot.cogs.autokickcog import AutoKickCog
63
+from rocketbot.cogs.configcog import ConfigCog
64
+from rocketbot.cogs.crosspostcog import CrossPostCog
65
+from rocketbot.cogs.generalcog import GeneralCog
66
+from rocketbot.cogs.joinagecog import JoinAgeCog
67
+from rocketbot.cogs.joinraidcog import JoinRaidCog
68
+from rocketbot.cogs.logcog import LoggingCog
69
+from rocketbot.cogs.patterncog import PatternCog
70
+from rocketbot.cogs.urlspamcog import URLSpamCog
71
+from rocketbot.cogs.usernamecog import UsernamePatternCog
72
+
73
+async def start_bot():
75 74
 	bot_log(None, None, 'Bot initializing...')
76 75
 	bot_log(None, None, f"Type {CONFIG['command_prefix']}help in Discord for available commands.")
77
-	bot = Rocketbot(command_prefix=CONFIG['command_prefix'], intents=intents)
78 76
 
79 77
 	# Core
80
-	await bot.add_cog(GeneralCog(bot))
81
-	await bot.add_cog(ConfigCog(bot))
78
+	await rocketbot.add_cog(GeneralCog(rocketbot))
79
+	await rocketbot.add_cog(ConfigCog(rocketbot))
82 80
 
83 81
 	# Optional
84
-	await bot.add_cog(AutoKickCog(bot))
85
-	await bot.add_cog(CrossPostCog(bot))
86
-	await bot.add_cog(JoinAgeCog(bot))
87
-	await bot.add_cog(JoinRaidCog(bot))
88
-	await bot.add_cog(LoggingCog(bot))
89
-	await bot.add_cog(PatternCog(bot))
90
-	await bot.add_cog(URLSpamCog(bot))
91
-	await bot.add_cog(UsernamePatternCog(bot))
82
+	await rocketbot.add_cog(AutoKickCog(rocketbot))
83
+	await rocketbot.add_cog(CrossPostCog(rocketbot))
84
+	await rocketbot.add_cog(JoinAgeCog(rocketbot))
85
+	await rocketbot.add_cog(JoinRaidCog(rocketbot))
86
+	await rocketbot.add_cog(LoggingCog(rocketbot))
87
+	await rocketbot.add_cog(PatternCog(rocketbot))
88
+	await rocketbot.add_cog(URLSpamCog(rocketbot))
89
+	await rocketbot.add_cog(UsernamePatternCog(rocketbot))
92 90
 
93
-	await bot.start(CONFIG['client_token'], reconnect=True)
91
+	await rocketbot.start(CONFIG['client_token'], reconnect=True)
94 92
 	print('\nBot aborted')
95
-
96
-try:
97
-	asyncio.run(start_bot())
98
-except KeyboardInterrupt:
99
-	bot_log(None, None, 'Stopping bot due to Ctrl+C key')

+ 5
- 0
rocketbot/cogs/generalcog.py Переглянути файл

@@ -2,6 +2,7 @@
2 2
 Cog for handling most ungrouped commands and basic behaviors.
3 3
 """
4 4
 import re
5
+import traceback
5 6
 from datetime import datetime, timedelta, timezone
6 7
 from typing import Optional
7 8
 
@@ -55,6 +56,10 @@ class GeneralCog(BaseCog, name='General'):
55 56
 		if self.is_first_ready:
56 57
 			print('----------------------------------------------------------')
57 58
 			self.is_first_ready = False
59
+		try:
60
+			await self.bot.tree.sync()
61
+		except Exception as e:
62
+			traceback.print_exception(type(e), e, e.__traceback__)
58 63
 
59 64
 	@commands.Cog.listener()
60 65
 	async def on_resumed(self):

Завантаження…
Відмінити
Зберегти