ayaka.on

注册回调

  1'''注册回调'''
  2import asyncio
  3import datetime
  4from typing import Callable, Coroutine, TYPE_CHECKING, Union, List
  5from loguru import logger
  6from .config import INIT_STATE, ayaka_root_config
  7
  8if TYPE_CHECKING:
  9    from .ayaka import AyakaApp
 10
 11
 12class AyakaOn:
 13    def __init__(self, app: "AyakaApp") -> None:
 14        self.app = app
 15
 16    def everyday(self, h: int, m: int, s: int):
 17        '''每日定时触发'''
 18        return self.interval(86400, h, m, s)
 19
 20    def interval(self, gap: int, h=-1, m=-1, s=-1):
 21        '''在指定的时间点后循环触发'''
 22        return self.on_timer(gap, h, m, s)
 23
 24    def state(self, *states: str):
 25        '''注册有状态回调'''
 26        if not states:
 27            states = INIT_STATE
 28
 29        def decorator(func):
 30            # 取出之前存的参数
 31            return self.on_handle(func.cmds, states, False)(func)
 32        return decorator
 33
 34    def idle(self, super=False):
 35        '''注册无状态回调'''
 36        def decorator(func):
 37            # 取出之前存的参数
 38            return self.on_handle(func.cmds, None, super)(func)
 39        return decorator
 40
 41    def command(self, *cmds: str):
 42        def decorator(func):
 43            func.cmds = cmds
 44            return func
 45        return decorator
 46
 47    def text(self):
 48        def decorator(func):
 49            func.cmds = ""
 50            return func
 51        return decorator
 52
 53    def on_handle(self, cmds: Union[List[str], str], states: Union[List[str], str], super: bool):
 54        '''注册'''
 55        cmds = ensure_list(cmds)
 56        states = ensure_list(states)
 57
 58        def decorator(func: Callable[[], Coroutine]):
 59            for state in states:
 60                for cmd in cmds:
 61                    t = AyakaTrigger(self.app.name, cmd, state, super, func)
 62                    self.app.triggers.append(t)
 63
 64                # 如果有帮助,自动添加到_help中
 65                doc = func.__doc__
 66                if doc:
 67                    if state is None:
 68                        state = INIT_STATE
 69                    if state not in self.app._help:
 70                        self.app._help[state] = []
 71                    cmd_str = '/'.join(cmds)
 72                    if not cmd_str:
 73                        cmd_str = "*"
 74                    self.app._help[state].append(f"- {cmd_str} {doc}")
 75
 76            return func
 77        return decorator
 78
 79    def on_timer(self, gap: int, h: int, m: int, s: int):
 80        '''在指定的时间点后循环触发'''
 81        def decorator(func):
 82            t = AyakaTimer(self.app.name, gap, h, m, s, func)
 83            self.app.timers.append(t)
 84            return func
 85        return decorator
 86
 87
 88class AyakaTrigger:
 89    def __repr__(self) -> str:
 90        return f"AyakaTrigger({self.app_name}, {self.cmd}, {self.state}, {self.super}, {self.func.__name__})"
 91
 92    def __init__(self, app_name, cmd, state, super, func) -> None:
 93        self.app_name = app_name
 94        self.cmd = cmd
 95        self.state = state
 96        self.super = super
 97        self.func = func
 98        if ayaka_root_config.debug:
 99            print(self)
100
101    async def run(self):
102        # 日志记录
103        items = []
104
105        if self.cmd:
106            items.append("<y>命令</y>")
107        else:
108            items.append("<g>消息</g>")
109
110        app_name = f"<y>{self.app_name}</y>"
111        if self.state is not None:
112            app_name += f" <g>{self.state}</g>"
113        items.append(app_name)
114
115        if self.cmd:
116            items.append(f"<y>{self.cmd}</y>")
117
118        items.append(f"执行回调 <c>{self.func.__name__}</c>")
119        info = " | ".join(items)
120        logger.opt(colors=True).debug(info)
121
122        # 运行回调
123        await self.func()
124
125
126class AyakaTimer:
127    def __repr__(self) -> str:
128        return f"AyakaTimer({self.name}, {self.gap}, {self.func.__name__})"
129
130    def __init__(self, name: str, gap: int, h: int, m: int, s: int, func) -> None:
131        self.name = name
132        self.h = h
133        self.m = m
134        self.s = s
135        self.gap = gap
136        self.func = func
137        if ayaka_root_config.debug:
138            print(self)
139
140    def start(self):
141        asyncio.create_task(self.run_forever())
142
143    async def run_forever(self):
144        # 有启动时间点要求的
145        time_i = int(datetime.datetime.now().timestamp())
146        if self.h >= 0:
147            _time_i = self.h*3600+self.m*60+self.s
148            # 移除时区偏差
149            time_i -= 57600
150            gap = 86400 - (time_i - _time_i) % 86400
151            await asyncio.sleep(gap)
152        elif self.m >= 0:
153            _time_i = self.m*60+self.s
154            gap = 3600 - (time_i-_time_i) % 3600
155            await asyncio.sleep(gap)
156        elif self.s >= 0:
157            _time_i = self.s
158            gap = 60 - (time_i-_time_i) % 60
159            await asyncio.sleep(gap)
160
161        while True:
162            logger.opt(colors=True).debug(f"触发定时任务 <y>{self.name}</y>")
163            asyncio.create_task(self.func())
164            await asyncio.sleep(self.gap)
165
166
167def ensure_list(items):
168    if isinstance(items, tuple):
169        return [item for item in items]
170    if not isinstance(items, list):
171        return [items]
172    return items
class AyakaOn:
13class AyakaOn:
14    def __init__(self, app: "AyakaApp") -> None:
15        self.app = app
16
17    def everyday(self, h: int, m: int, s: int):
18        '''每日定时触发'''
19        return self.interval(86400, h, m, s)
20
21    def interval(self, gap: int, h=-1, m=-1, s=-1):
22        '''在指定的时间点后循环触发'''
23        return self.on_timer(gap, h, m, s)
24
25    def state(self, *states: str):
26        '''注册有状态回调'''
27        if not states:
28            states = INIT_STATE
29
30        def decorator(func):
31            # 取出之前存的参数
32            return self.on_handle(func.cmds, states, False)(func)
33        return decorator
34
35    def idle(self, super=False):
36        '''注册无状态回调'''
37        def decorator(func):
38            # 取出之前存的参数
39            return self.on_handle(func.cmds, None, super)(func)
40        return decorator
41
42    def command(self, *cmds: str):
43        def decorator(func):
44            func.cmds = cmds
45            return func
46        return decorator
47
48    def text(self):
49        def decorator(func):
50            func.cmds = ""
51            return func
52        return decorator
53
54    def on_handle(self, cmds: Union[List[str], str], states: Union[List[str], str], super: bool):
55        '''注册'''
56        cmds = ensure_list(cmds)
57        states = ensure_list(states)
58
59        def decorator(func: Callable[[], Coroutine]):
60            for state in states:
61                for cmd in cmds:
62                    t = AyakaTrigger(self.app.name, cmd, state, super, func)
63                    self.app.triggers.append(t)
64
65                # 如果有帮助,自动添加到_help中
66                doc = func.__doc__
67                if doc:
68                    if state is None:
69                        state = INIT_STATE
70                    if state not in self.app._help:
71                        self.app._help[state] = []
72                    cmd_str = '/'.join(cmds)
73                    if not cmd_str:
74                        cmd_str = "*"
75                    self.app._help[state].append(f"- {cmd_str} {doc}")
76
77            return func
78        return decorator
79
80    def on_timer(self, gap: int, h: int, m: int, s: int):
81        '''在指定的时间点后循环触发'''
82        def decorator(func):
83            t = AyakaTimer(self.app.name, gap, h, m, s, func)
84            self.app.timers.append(t)
85            return func
86        return decorator
AyakaOn(app: ayaka.ayaka.AyakaApp)
14    def __init__(self, app: "AyakaApp") -> None:
15        self.app = app
def everyday(self, h: int, m: int, s: int):
17    def everyday(self, h: int, m: int, s: int):
18        '''每日定时触发'''
19        return self.interval(86400, h, m, s)

每日定时触发

def interval(self, gap: int, h=-1, m=-1, s=-1):
21    def interval(self, gap: int, h=-1, m=-1, s=-1):
22        '''在指定的时间点后循环触发'''
23        return self.on_timer(gap, h, m, s)

在指定的时间点后循环触发

def state(self, *states: str):
25    def state(self, *states: str):
26        '''注册有状态回调'''
27        if not states:
28            states = INIT_STATE
29
30        def decorator(func):
31            # 取出之前存的参数
32            return self.on_handle(func.cmds, states, False)(func)
33        return decorator

注册有状态回调

def idle(self, super=False):
35    def idle(self, super=False):
36        '''注册无状态回调'''
37        def decorator(func):
38            # 取出之前存的参数
39            return self.on_handle(func.cmds, None, super)(func)
40        return decorator

注册无状态回调

def command(self, *cmds: str):
42    def command(self, *cmds: str):
43        def decorator(func):
44            func.cmds = cmds
45            return func
46        return decorator
def text(self):
48    def text(self):
49        def decorator(func):
50            func.cmds = ""
51            return func
52        return decorator
def on_handle( self, cmds: Union[List[str], str], states: Union[List[str], str], super: bool):
54    def on_handle(self, cmds: Union[List[str], str], states: Union[List[str], str], super: bool):
55        '''注册'''
56        cmds = ensure_list(cmds)
57        states = ensure_list(states)
58
59        def decorator(func: Callable[[], Coroutine]):
60            for state in states:
61                for cmd in cmds:
62                    t = AyakaTrigger(self.app.name, cmd, state, super, func)
63                    self.app.triggers.append(t)
64
65                # 如果有帮助,自动添加到_help中
66                doc = func.__doc__
67                if doc:
68                    if state is None:
69                        state = INIT_STATE
70                    if state not in self.app._help:
71                        self.app._help[state] = []
72                    cmd_str = '/'.join(cmds)
73                    if not cmd_str:
74                        cmd_str = "*"
75                    self.app._help[state].append(f"- {cmd_str} {doc}")
76
77            return func
78        return decorator

注册

def on_timer(self, gap: int, h: int, m: int, s: int):
80    def on_timer(self, gap: int, h: int, m: int, s: int):
81        '''在指定的时间点后循环触发'''
82        def decorator(func):
83            t = AyakaTimer(self.app.name, gap, h, m, s, func)
84            self.app.timers.append(t)
85            return func
86        return decorator

在指定的时间点后循环触发

class AyakaTrigger:
 89class AyakaTrigger:
 90    def __repr__(self) -> str:
 91        return f"AyakaTrigger({self.app_name}, {self.cmd}, {self.state}, {self.super}, {self.func.__name__})"
 92
 93    def __init__(self, app_name, cmd, state, super, func) -> None:
 94        self.app_name = app_name
 95        self.cmd = cmd
 96        self.state = state
 97        self.super = super
 98        self.func = func
 99        if ayaka_root_config.debug:
100            print(self)
101
102    async def run(self):
103        # 日志记录
104        items = []
105
106        if self.cmd:
107            items.append("<y>命令</y>")
108        else:
109            items.append("<g>消息</g>")
110
111        app_name = f"<y>{self.app_name}</y>"
112        if self.state is not None:
113            app_name += f" <g>{self.state}</g>"
114        items.append(app_name)
115
116        if self.cmd:
117            items.append(f"<y>{self.cmd}</y>")
118
119        items.append(f"执行回调 <c>{self.func.__name__}</c>")
120        info = " | ".join(items)
121        logger.opt(colors=True).debug(info)
122
123        # 运行回调
124        await self.func()
AyakaTrigger(app_name, cmd, state, super, func)
 93    def __init__(self, app_name, cmd, state, super, func) -> None:
 94        self.app_name = app_name
 95        self.cmd = cmd
 96        self.state = state
 97        self.super = super
 98        self.func = func
 99        if ayaka_root_config.debug:
100            print(self)
async def run(self):
102    async def run(self):
103        # 日志记录
104        items = []
105
106        if self.cmd:
107            items.append("<y>命令</y>")
108        else:
109            items.append("<g>消息</g>")
110
111        app_name = f"<y>{self.app_name}</y>"
112        if self.state is not None:
113            app_name += f" <g>{self.state}</g>"
114        items.append(app_name)
115
116        if self.cmd:
117            items.append(f"<y>{self.cmd}</y>")
118
119        items.append(f"执行回调 <c>{self.func.__name__}</c>")
120        info = " | ".join(items)
121        logger.opt(colors=True).debug(info)
122
123        # 运行回调
124        await self.func()
class AyakaTimer:
127class AyakaTimer:
128    def __repr__(self) -> str:
129        return f"AyakaTimer({self.name}, {self.gap}, {self.func.__name__})"
130
131    def __init__(self, name: str, gap: int, h: int, m: int, s: int, func) -> None:
132        self.name = name
133        self.h = h
134        self.m = m
135        self.s = s
136        self.gap = gap
137        self.func = func
138        if ayaka_root_config.debug:
139            print(self)
140
141    def start(self):
142        asyncio.create_task(self.run_forever())
143
144    async def run_forever(self):
145        # 有启动时间点要求的
146        time_i = int(datetime.datetime.now().timestamp())
147        if self.h >= 0:
148            _time_i = self.h*3600+self.m*60+self.s
149            # 移除时区偏差
150            time_i -= 57600
151            gap = 86400 - (time_i - _time_i) % 86400
152            await asyncio.sleep(gap)
153        elif self.m >= 0:
154            _time_i = self.m*60+self.s
155            gap = 3600 - (time_i-_time_i) % 3600
156            await asyncio.sleep(gap)
157        elif self.s >= 0:
158            _time_i = self.s
159            gap = 60 - (time_i-_time_i) % 60
160            await asyncio.sleep(gap)
161
162        while True:
163            logger.opt(colors=True).debug(f"触发定时任务 <y>{self.name}</y>")
164            asyncio.create_task(self.func())
165            await asyncio.sleep(self.gap)
AyakaTimer(name: str, gap: int, h: int, m: int, s: int, func)
131    def __init__(self, name: str, gap: int, h: int, m: int, s: int, func) -> None:
132        self.name = name
133        self.h = h
134        self.m = m
135        self.s = s
136        self.gap = gap
137        self.func = func
138        if ayaka_root_config.debug:
139            print(self)
def start(self):
141    def start(self):
142        asyncio.create_task(self.run_forever())
async def run_forever(self):
144    async def run_forever(self):
145        # 有启动时间点要求的
146        time_i = int(datetime.datetime.now().timestamp())
147        if self.h >= 0:
148            _time_i = self.h*3600+self.m*60+self.s
149            # 移除时区偏差
150            time_i -= 57600
151            gap = 86400 - (time_i - _time_i) % 86400
152            await asyncio.sleep(gap)
153        elif self.m >= 0:
154            _time_i = self.m*60+self.s
155            gap = 3600 - (time_i-_time_i) % 3600
156            await asyncio.sleep(gap)
157        elif self.s >= 0:
158            _time_i = self.s
159            gap = 60 - (time_i-_time_i) % 60
160            await asyncio.sleep(gap)
161
162        while True:
163            logger.opt(colors=True).debug(f"触发定时任务 <y>{self.name}</y>")
164            asyncio.create_task(self.func())
165            await asyncio.sleep(self.gap)
def ensure_list(items):
168def ensure_list(items):
169    if isinstance(items, tuple):
170        return [item for item in items]
171    if not isinstance(items, list):
172        return [items]
173    return items