mirror of
https://github.com/TriM-Organization/LiteyukiBot-TriM.git
synced 2025-09-07 20:56:23 +00:00
๐ๆๅจMerge่ฝป้ชไธปไปๅบa77f97f
This commit is contained in:
@ -1,103 +1,102 @@
|
||||
import asyncio
|
||||
import atexit
|
||||
import os
|
||||
import platform
|
||||
import signal
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
from typing import Any, Optional
|
||||
|
||||
from watchdog.events import FileSystemEventHandler
|
||||
from watchdog.observers import Observer
|
||||
|
||||
from liteyuki.bot.lifespan import LIFESPAN_FUNC, Lifespan
|
||||
from liteyuki.core import IS_MAIN_PROCESS
|
||||
from liteyuki.bot.lifespan import LIFESPAN_FUNC, Lifespan, PROCESS_LIFESPAN_FUNC
|
||||
from liteyuki.comm.channel import get_channel
|
||||
from liteyuki.core.manager import ProcessManager
|
||||
from liteyuki.core.spawn_process import mb_run, nb_run
|
||||
from liteyuki.log import init_log, logger
|
||||
from liteyuki.plugin import load_plugins
|
||||
from liteyuki.plugin import load_plugin
|
||||
from liteyuki.utils import IS_MAIN_PROCESS
|
||||
|
||||
__all__ = ["LiteyukiBot", "get_bot"]
|
||||
__all__ = [
|
||||
"LiteyukiBot",
|
||||
"get_bot",
|
||||
"get_config",
|
||||
"get_config_with_compat",
|
||||
]
|
||||
|
||||
|
||||
class LiteyukiBot:
|
||||
def __init__(self, *args, **kwargs):
|
||||
def __init__(self, **kwargs) -> None:
|
||||
"""
|
||||
ๅๅงๅ่ฝป้ชๅฎไพ
|
||||
Args:
|
||||
**kwargs: ้
็ฝฎ
|
||||
"""
|
||||
"""ๅธธ่งๆไฝ"""
|
||||
print_logo()
|
||||
global _BOT_INSTANCE
|
||||
_BOT_INSTANCE = self # ๅผ็จ
|
||||
|
||||
"""้
็ฝฎ"""
|
||||
self.config: dict[str, Any] = kwargs
|
||||
|
||||
"""ๅๅงๅ"""
|
||||
self.init(**self.config) # ๅๅงๅ
|
||||
logger.info("ๅฐน็ตๆธฉ ๆญฃๅจๅๅงๅโฆ")
|
||||
|
||||
self.lifespan: Lifespan = Lifespan()
|
||||
"""็ๅฝๅจๆ็ฎก็"""
|
||||
self.lifespan = Lifespan()
|
||||
self.process_manager: ProcessManager = ProcessManager(lifespan=self.lifespan)
|
||||
|
||||
self.process_manager: ProcessManager = ProcessManager(bot=self)
|
||||
"""ไบไปถๅพช็ฏ"""
|
||||
self.loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(self.loop)
|
||||
self.loop_thread = threading.Thread(target=self.loop.run_forever, daemon=True)
|
||||
self.stop_event = threading.Event()
|
||||
self.call_restart_count = 0
|
||||
|
||||
"""ๅ ่ฝฝๆไปถๅ ่ฝฝๅจ"""
|
||||
load_plugin("liteyuki.plugins.plugin_loader") # ๅ ่ฝฝ่ฝป้ชๆไปถ
|
||||
|
||||
async def _run(self):
|
||||
"""
|
||||
ๅฏๅจ้ป่พ
|
||||
"""
|
||||
await self.lifespan.before_start() # ๅฏๅจๅ้ฉๅญ
|
||||
await self.lifespan.after_start() # ๅฏๅจๅ้ฉๅญ
|
||||
await self.keep_alive()
|
||||
|
||||
def run(self):
|
||||
load_plugins("liteyuki/plugins") # ๅ ่ฝฝ่ฝป้ชๆไปถ
|
||||
"""
|
||||
ๅค้จๅฏๅจๆฅๅฃ
|
||||
"""
|
||||
self.process_manager.start_all()
|
||||
try:
|
||||
asyncio.run(self._run())
|
||||
except KeyboardInterrupt:
|
||||
logger.opt(colors=True).info("<y>ๅฐน็ตๆธฉ ๅ
ณ้ญไธญโฆ</y>")
|
||||
self.stop()
|
||||
logger.opt(colors=True).info("<y>ๅฐน็ตๆธฉ ๅทฒๅ
ณๅ</y>")
|
||||
|
||||
self.loop_thread.start() # ๅฏๅจไบไปถๅพช็ฏ
|
||||
asyncio.run(self.lifespan.before_start()) # ๅฏๅจๅ้ฉๅญ
|
||||
|
||||
self.process_manager.add_target("nonebot", nb_run, **self.config)
|
||||
self.process_manager.start("nonebot")
|
||||
|
||||
self.process_manager.add_target("melobot", mb_run, **self.config)
|
||||
self.process_manager.start("melobot")
|
||||
|
||||
asyncio.run(self.lifespan.after_start()) # ๅฏๅจๅ้ฉๅญ
|
||||
|
||||
self.start_watcher() # ๅฏๅจๆไปถ็่งๅจ
|
||||
|
||||
def start_watcher(self):
|
||||
if self.config.get("debug", False):
|
||||
|
||||
src_directories = (
|
||||
"liteyuki",
|
||||
"src/liteyuki_main",
|
||||
"src/liteyuki_plugins",
|
||||
"src/nonebot_plugins",
|
||||
"src/utils",
|
||||
)
|
||||
src_excludes_extensions = ("pyc",)
|
||||
|
||||
logger.debug("่ฝป้ช้่ฝฝ ๅทฒๅฏ็จ๏ผๆญฃๅจๅ ่ฝฝๆไปถไฟฎๆน็ๆตโฆโฆ")
|
||||
restart = self.restart_process
|
||||
|
||||
class CodeModifiedHandler(FileSystemEventHandler):
|
||||
"""
|
||||
Handler for code file changes
|
||||
"""
|
||||
|
||||
def on_modified(self, event):
|
||||
if (
|
||||
event.src_path.endswith(src_excludes_extensions)
|
||||
or event.is_directory
|
||||
or "__pycache__" in event.src_path
|
||||
):
|
||||
return
|
||||
logger.info(f"ๆไปถ {event.src_path} ๅทฒไฟฎๆน๏ผๆบๅจไบบ่ชๅจ้ๅฏโฆโฆ")
|
||||
restart()
|
||||
|
||||
code_modified_handler = CodeModifiedHandler()
|
||||
|
||||
observer = Observer()
|
||||
for directory in src_directories:
|
||||
observer.schedule(code_modified_handler, directory, recursive=True)
|
||||
observer.start()
|
||||
async def keep_alive(self):
|
||||
"""
|
||||
ไฟๆ่ฝป้ช่ฟ่ก
|
||||
"""
|
||||
logger.info("ๅฐน็ตๆธฉ ๆ็ปญ่ฟ่กไธญโฆ")
|
||||
try:
|
||||
while not self.stop_event.is_set():
|
||||
await asyncio.sleep(0.1)
|
||||
except Exception:
|
||||
logger.info("ๅฐน็ตๆธฉ ็ฐ้ๅโฆ")
|
||||
self.stop()
|
||||
|
||||
def restart(self, delay: int = 0):
|
||||
"""
|
||||
้ๅฏ่ฝป้ชๆฌไฝ
|
||||
Returns:
|
||||
|
||||
Args:
|
||||
delay ([`int`](https%3A//docs.python.org/3/library/functions.html#int), optional): ๅปถ่ฟ้ๅฏๆถ้ด. Defaults to 0.
|
||||
"""
|
||||
|
||||
if self.call_restart_count < 1:
|
||||
executable = sys.executable
|
||||
args = sys.argv
|
||||
logger.info("ๆญฃๅจ้ๅฏ ๅฐน็ตๆธฉ...")
|
||||
logger.info("ๆญฃๅจ้ๅฏ ๅฐน็ตๆธฉๆบๅจไบบๆกๆถ")
|
||||
time.sleep(delay)
|
||||
if platform.system() == "Windows":
|
||||
cmd = "start"
|
||||
@ -110,7 +109,9 @@ class LiteyukiBot:
|
||||
self.process_manager.terminate_all()
|
||||
# ่ฟ็จ้ๅบๅ้ๅฏ
|
||||
threading.Thread(
|
||||
target=os.system, args=(f"{cmd} {executable} {' '.join(args)}",)
|
||||
target=os.system,
|
||||
args=(f"{cmd} {executable} {' '.join(args)}",),
|
||||
daemon=True,
|
||||
).start()
|
||||
sys.exit(0)
|
||||
self.call_restart_count += 1
|
||||
@ -119,44 +120,46 @@ class LiteyukiBot:
|
||||
"""
|
||||
ๅๆญข่ฝป้ช
|
||||
Args:
|
||||
name: ่ฟ็จๅ็งฐ, ้ป่ฎคไธบNone, ๆๆ่ฟ็จ
|
||||
name ([`Optional`](https%3A//docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https%3A//docs.python.org/3/library/stdtypes.html#str)]): ่ฟ็จๅ. Defaults to None.
|
||||
Returns:
|
||||
|
||||
"""
|
||||
logger.info("Stopping LiteyukiBot...")
|
||||
|
||||
self.loop.create_task(self.lifespan.before_shutdown()) # ้ๅฏๅ้ฉๅญ
|
||||
self.loop.create_task(self.lifespan.before_shutdown()) # ๅๆญขๅ้ฉๅญ
|
||||
|
||||
if name:
|
||||
self.process_manager.terminate(name)
|
||||
if name is not None:
|
||||
chan_active = get_channel(f"{name}-active")
|
||||
chan_active.send(1)
|
||||
else:
|
||||
self.process_manager.terminate_all()
|
||||
for process_name in self.process_manager.processes:
|
||||
chan_active = get_channel(f"{process_name}-active")
|
||||
chan_active.send(1)
|
||||
|
||||
def init(self, *args, **kwargs):
|
||||
"""
|
||||
ๅๅงๅ่ฝป้ช, ่ชๅจ่ฐ็จ
|
||||
Returns:
|
||||
|
||||
Args:
|
||||
*args: ๅๆฐ
|
||||
**kwargs: ๅ
ณ้ฎๅญๅๆฐ
|
||||
"""
|
||||
self.init_config()
|
||||
self.init_logger()
|
||||
|
||||
def init_logger(self):
|
||||
# ไฟฎๆนnonebot็ๆฅๅฟ้
็ฝฎ
|
||||
"""
|
||||
ๅๅงๅๆฅๅฟ
|
||||
"""
|
||||
init_log(config=self.config)
|
||||
|
||||
def init_config(self):
|
||||
pass
|
||||
def stop(self):
|
||||
"""
|
||||
ๅๆญข่ฝป้ช
|
||||
"""
|
||||
self.process_manager.terminate_all()
|
||||
self.stop_event.set()
|
||||
|
||||
def on_before_start(self, func: LIFESPAN_FUNC):
|
||||
def on_before_start(self, func: LIFESPAN_FUNC) -> LIFESPAN_FUNC:
|
||||
"""
|
||||
ๆณจๅๅฏๅจๅ็ๅฝๆฐ
|
||||
Args:
|
||||
func:
|
||||
|
||||
func ([`LIFESPAN_FUNC`](./lifespan#var-lifespan-func)): ็ๅฝๅจๆๅฝๆฐ
|
||||
Returns:
|
||||
|
||||
[`LIFESPAN_FUNC`](./lifespan#var-lifespan-func): ็ๅฝๅจๆๅฝๆฐ
|
||||
"""
|
||||
return self.lifespan.on_before_start(func)
|
||||
|
||||
@ -164,81 +167,128 @@ class LiteyukiBot:
|
||||
"""
|
||||
ๆณจๅๅฏๅจๅ็ๅฝๆฐ
|
||||
Args:
|
||||
func:
|
||||
|
||||
func ([`LIFESPAN_FUNC`](./lifespan#var-lifespan-func)): ็ๅฝๅจๆๅฝๆฐ
|
||||
Returns:
|
||||
|
||||
[`LIFESPAN_FUNC`](./lifespan#var-lifespan-func): ็ๅฝๅจๆๅฝๆฐ
|
||||
"""
|
||||
return self.lifespan.on_after_start(func)
|
||||
|
||||
def on_before_shutdown(self, func: LIFESPAN_FUNC):
|
||||
"""
|
||||
ๆณจๅๅๆญขๅ็ๅฝๆฐ๏ผไธบๅญ่ฟ็จๅๆญขๆถ่ฐ็จ
|
||||
Args:
|
||||
func:
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
return self.lifespan.on_before_shutdown(func)
|
||||
|
||||
def on_after_shutdown(self, func: LIFESPAN_FUNC):
|
||||
"""
|
||||
ๆณจๅๅๆญขๅ็ๅฝๆฐ๏ผๆชๅฎ็ฐ
|
||||
Args:
|
||||
func:
|
||||
|
||||
func ([`LIFESPAN_FUNC`](./lifespan#var-lifespan-func)): ็ๅฝๅจๆๅฝๆฐ
|
||||
Returns:
|
||||
|
||||
[`LIFESPAN_FUNC`](./lifespan#var-lifespan-func): ็ๅฝๅจๆๅฝๆฐ
|
||||
"""
|
||||
return self.lifespan.on_after_shutdown(func)
|
||||
|
||||
def on_before_restart(self, func: LIFESPAN_FUNC):
|
||||
def on_before_process_shutdown(self, func: PROCESS_LIFESPAN_FUNC):
|
||||
"""
|
||||
ๆณจๅ้ๅฏๅ็ๅฝๆฐ๏ผไธบๅญ่ฟ็จ้ๅฏๆถ่ฐ็จ
|
||||
ๆณจๅ่ฟ็จๅๆญขๅ็ๅฝๆฐ๏ผไธบๅญ่ฟ็จๅๆญขๆถ่ฐ็จ
|
||||
Args:
|
||||
func:
|
||||
|
||||
func ([`PROCESS_LIFESPAN_FUNC`](./lifespan#var-process-lifespan-func)): ็ๅฝๅจๆๅฝๆฐ
|
||||
Returns:
|
||||
[`PROCESS_LIFESPAN_FUNC`](./lifespan#var-process-lifespan-func): ็ๅฝๅจๆๅฝๆฐ
|
||||
"""
|
||||
return self.lifespan.on_before_process_shutdown(func)
|
||||
|
||||
def on_before_process_restart(
|
||||
self, func: PROCESS_LIFESPAN_FUNC
|
||||
) -> PROCESS_LIFESPAN_FUNC:
|
||||
"""
|
||||
ๆณจๅ่ฟ็จ้ๅฏๅ็ๅฝๆฐ๏ผไธบๅญ่ฟ็จ้ๅฏๆถ่ฐ็จ
|
||||
Args:
|
||||
func ([`PROCESS_LIFESPAN_FUNC`](./lifespan#var-process-lifespan-func)): ็ๅฝๅจๆๅฝๆฐ
|
||||
Returns:
|
||||
[`PROCESS_LIFESPAN_FUNC`](./lifespan#var-process-lifespan-func): ็ๅฝๅจๆๅฝๆฐ
|
||||
"""
|
||||
|
||||
return self.lifespan.on_before_restart(func)
|
||||
return self.lifespan.on_before_process_restart(func)
|
||||
|
||||
def on_after_restart(self, func: LIFESPAN_FUNC):
|
||||
"""
|
||||
ๆณจๅ้ๅฏๅ็ๅฝๆฐ๏ผๆชๅฎ็ฐ
|
||||
Args:
|
||||
func:
|
||||
|
||||
func ([`LIFESPAN_FUNC`](./lifespan#var-lifespan-func)): ็ๅฝๅจๆๅฝๆฐ
|
||||
Returns:
|
||||
|
||||
[`LIFESPAN_FUNC`](./lifespan#var-lifespan-func): ็ๅฝๅจๆๅฝๆฐ
|
||||
"""
|
||||
return self.lifespan.on_after_restart(func)
|
||||
|
||||
def on_after_nonebot_init(self, func: LIFESPAN_FUNC):
|
||||
"""
|
||||
ๆณจๅnonebotๅๅงๅๅ็ๅฝๆฐ
|
||||
Args:
|
||||
func:
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
return self.lifespan.on_after_nonebot_init(func)
|
||||
_BOT_INSTANCE: LiteyukiBot
|
||||
|
||||
|
||||
_BOT_INSTANCE: Optional[LiteyukiBot] = None
|
||||
|
||||
|
||||
def get_bot() -> Optional[LiteyukiBot]:
|
||||
def get_bot() -> LiteyukiBot:
|
||||
"""
|
||||
่ทๅ่ฝป้ชๅฎไพ
|
||||
Returns:
|
||||
LiteyukiBot: ๅฝๅ็่ฝป้ชๅฎไพ
|
||||
[`LiteyukiBot`](#class-liteyukibot): ่ฝป้ชๅฎไพ
|
||||
"""
|
||||
|
||||
if IS_MAIN_PROCESS:
|
||||
if _BOT_INSTANCE is None:
|
||||
raise RuntimeError("ๅฐน็ตๆธฉ ๅฎไพๆชๅๅงๅ")
|
||||
return _BOT_INSTANCE
|
||||
else:
|
||||
# ไปๅค่ฟ็จไธไธๆไธญ่ทๅ
|
||||
pass
|
||||
raise RuntimeError("ๆ ๆณๅจๅญ่ฟ็จไธญ่ทๅๆบๅจไบบๅฎไพ")
|
||||
|
||||
|
||||
def get_config(key: str, default: Any = None) -> Any:
|
||||
"""
|
||||
่ทๅ้
็ฝฎ
|
||||
Args:
|
||||
key ([`str`](https%3A//docs.python.org/3/library/stdtypes.html#str)): ้
็ฝฎ้ฎ
|
||||
default ([`Any`](https%3A//docs.python.org/3/library/functions.html#any), optional): ้ป่ฎคๅผ. Defaults to None.
|
||||
Returns:
|
||||
[`Any`](https%3A//docs.python.org/3/library/functions.html#any): ้
็ฝฎๅผ
|
||||
"""
|
||||
return get_bot().config.get(key, default)
|
||||
|
||||
|
||||
def get_config_with_compat(
|
||||
key: str, compat_keys: tuple[str], default: Any = None
|
||||
) -> Any:
|
||||
"""
|
||||
่ทๅ้
็ฝฎ๏ผๅ
ผๅฎนๆง็ๆฌ
|
||||
Args:
|
||||
key ([`str`](https%3A//docs.python.org/3/library/stdtypes.html#str)): ้
็ฝฎ้ฎ
|
||||
compat_keys ([`tuple`](https%3A//docs.python.org/3/library/stdtypes.html#tuple)[`str`](https%3A//docs.python.org/3/library/stdtypes.html#str)): ๅ
ผๅฎน้ฎ
|
||||
default ([`Any`](https%3A//docs.python.org/3/library/functions.html#any), optional): ้ป่ฎคๅผ. Defaults to None.
|
||||
|
||||
Returns:
|
||||
[`Any`](https%3A//docs.python.org/3/library/functions.html#any): ้
็ฝฎๅผ
|
||||
"""
|
||||
if key in get_bot().config:
|
||||
return get_bot().config[key]
|
||||
for compat_key in compat_keys:
|
||||
if compat_key in get_bot().config:
|
||||
logger.warning(f'้
็ฝฎ้ฎ "{compat_key}" ๅณๅฐ่ขซ "{key}" ๅไปฃ๏ผ่ฏทๅๆถๆดๆฐ')
|
||||
return get_bot().config[compat_key]
|
||||
return default
|
||||
|
||||
|
||||
def print_logo():
|
||||
"""@litedoc-hide"""
|
||||
print(
|
||||
"\033[34m"
|
||||
+ r"""
|
||||
โ
โ
โ
โ
โ
โ
โ
โ
โ
โ
โ
โ
โ
โ
โโ โ
โ
โ
โ
โ
โ
โ
โ
โ
โ
โ
โ
โ
โ
โโ โโ โ
โ
โ
โ
โ
โ
โ
โ
โ
โ
โโข
|
||||
โ โโ โโ โ โโ โโโ โโ โโ
|
||||
โโ โโ โโโโโโโโโโโโโโโ โโ โโโโโโโโโ
โโ
|
||||
โโโโโโโโโโโโโโโ โโ โโโ โโ โโ
|
||||
โโ โโ โ
โโโโโโโโโโโโโโโ โโ โโโโโโโโโโโโ
|
||||
โโ โโ โโโ โโโ
|
||||
โโโโโโโโโโโโโโโโ โโโ
โโโ โโ โ
โ
โ
โ
โ
โ
โ
โ
โ
โ
โ
โโ
|
||||
โโโ โ โโโโโโโโ โโ โโโ โโ โโ โโ โโ
|
||||
โโโ โโโ โโโโโโ โโ โโ โโ โโ โโ
|
||||
โโโ โโ โโโ โ โโ โโ โโ โโ โโ
|
||||
โโโ โโโโโ โโโโโโ โโโ โโโโโโโโโโโโโโ
|
||||
ๅไธๆ ่ฎฐ ็ๆๆๆ ยฉ 2024 ้็พฟEilles
|
||||
ๆบๅจ่ฝฏไปถ ็ๆๆๆ ยฉ 2020-2024 ็ฅ็พฝSnowyKami & ้็พฟEilles\\
|
||||
ไผๅ LiteyukiStudio & ็ฟไน็ป็ป
|
||||
ไฟ็ๆๆๆๅฉ
|
||||
"""
|
||||
+ "\033[0m"
|
||||
)
|
||||
|
Reference in New Issue
Block a user