def run(self, func, *, mutex_mode='default', args=None, kwargs=None): """ 使用本UI执行函数。互斥的UI同一时刻只能有一个通过run执行函数。 func会以await func(self, *args, **kwargs)的形式调用。 该函数即刻返回,不等待func执行结束。 :param func: 待执行的函数。必须为异步函数,且接受至少一个位置参数。 :param mutex_mode: 互斥粒度,可以为'default'、'group'或'user' :param args: 需传入的其他位置参数 :param kwargs: 需传入的其他命名参数 :return: 无 :raise BotContextUI.RunningException: 若有互斥的UI正在通过run执行函数 """ if args is None: args = () if kwargs is None: kwargs = {} async def _run(): try: await func(self, *args, **kwargs) except BotContextUI._CancelException: pass finally: del _running[self._ctx_id] _mutex[mutex_mode].remove(mutex_id) for mode, locked in _mutex.items(): if context_id(self._ctx, mode=mode) in locked: raise BotContextUI.RunningException mutex_id = context_id(self._ctx, mode=mutex_mode) _mutex[mutex_mode].add(mutex_id) _running[self._ctx_id] = self asyncio.ensure_future(_run())
async def remove_sub(cls, event: Event, url: str): ctx_id = context_id(event, mode="group") sub = (await cls.query.where(cls.link == url).where(cls.ctx_id == ctx_id ).gino.first()) await sub.delete() return True
async def get_sub(cls, event: Event, url: str): ctx_id = context_id(event, mode="group") loader = SubUser.load(sub_content=SubContent) sub = (await cls.outerjoin(SubContent).select().where(cls.link == url).where( cls.ctx_id == ctx_id).gino.load(loader).first()) return sub
def __init__(self, bot: NoneBot, ctx: aiocqhttp.Event): super().__init__() self._bot = bot self._ctx = ctx self._ctx_id = context_id(ctx) self._pending_input = None self.at_sender = True
async def get_last_msg(cls, event: Event): return ( await ChatRecords.query.where(cls.ctx_id == context_id(event)) .where(cls.self_id == str(event.self_id),) .order_by(cls.id_.desc()) .gino.first() )
async def _(session: NLPSession): msg = session.msg_text.replace('\u202d', '').replace('\u202e', '') # LRO, RLO ctx_id = context_id(session.ctx) ui = _running.get(ctx_id) if msg and ui is not None and ui.input_pending: return IntentCommand(80, ('_ui', 'feed_input'), current_arg=msg)
async def add_msg(cls, event: Event, out: bool = False): await ChatRecords.create( self_id=str(event.self_id), ctx_id=context_id(event), msg=str(event.message), out=out, ),
async def gomoku(session: CommandSession): if not __enabled__: logger.warning("Gomoku plugin is disabled due to the failure of loading clib. See https://233a344a455.github.io/DeltaBot/setup.html#gomoku%E6%A8%A1%E5%9D%97-%E4%BA%94%E5%AD%90%E6%A3%8B-%E5%AE%89%E8%A3%85.") await session.send('插件未启用!') return await session.send("游戏开始!\n" "玩家黑棋,机器人白棋\n" "落子格式: 例如'e9'或'E9'\n" "字母在前数字在后,不分大小写") g = GomokuGame(clib, context_id(session.ctx, use_hash=True)) await session.send(MessageSegment.image(g.get_img())) await asyncio.sleep(0.5) while True: inp = await session.aget('input', force_update=True, prompt="请玩家落子", arg_filters=[ str.strip, not_empty(message="输入不能为空!请重新输入"), handle_cancellation(session), match_regex(r'[a-oA-O](1[0-5]|[1-9])', fullmatch=True, message="无效的输入!请重新输入\n落子格式: 例如'e9'或'E9'," "字母在前数字在后,不分大小写\n【发送'取消'结束游戏】")]) x, y = re.match(r'([a-oA-O])(1[0-5]|[1-9])', inp).groups() x, y = ALPHABET.index(x.upper()), int(y) - 1 if not g.set_chess(x, y, USER): await session.send(f"位置'{inp}'已存在旗子,请重新输入") continue sco = -g.estimate() g.update_display() if sco > 1e6: await session.send("恭喜!你赢了" + MessageSegment.image(g.get_img())) return x, y = g.search() g.set_chess(x, y, BOT) g.display.draw_chess(x, y, BOT, high_lighted=True) sco = -g.estimate() if sco < -1e6: await session.send("你输啦 ~\(≧▽≦)/~" + MessageSegment.image(g.get_img())) return await session.send(f"估计分数: {sco}" + MessageSegment.image(g.get_img())) await asyncio.sleep(0.8)
def make_job_id(plugin_name: str, event: Event = None, job_name: str = "") -> str: """ Make a scheduler job id. :param plugin_name: the plugin that the user is calling :param context_id: context id :param job_name: name of the job, if not given, job id prefix is returned :return: job id, or job id prefix if job_name is not given """ job_id = f"/{plugin_name}" if event: job_id += context_id(event) if job_name: if not re.fullmatch(r"[_a-zA-Z][_a-zA-Z0-9]*", job_name): raise ValueError(r'job name should match "[_a-zA-Z][_a-zA-Z0-9]*"') job_id += f"/{job_name}" return job_id
async def add_sub(cls, event: Event, url: str, only_title=False): try: d = await get_rss_info(url) except Exception as e: logger.exception(e) await send(get_bot(), event, f"获取 {url} 订阅信息失败,请稍后重试。") return None if not d: return None info = d["channel"] title = info.get("title", url) sub = await SubContent.add_or_update( link=url, name=title, content=pickle.dumps(d), ) await SubUser.create(ctx_id=context_id(event, mode="group"), link=sub.link, only_title=only_title) return title
async def get_user_subs(cls, event: Event) -> List["SubUser"]: ctx_id = context_id(event, mode="group") loader = SubUser.load(sub_content=SubContent) sub = (await cls.outerjoin(SubContent).select().where( cls.ctx_id == ctx_id).gino.load(loader).all()) return sub
async def _(session: CommandSession): ctx_id = context_id(session.ctx) ui = _running.get(ctx_id) if ui is not None: ui.input_pending = session.current_arg