Exemple #1
0
    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())
Exemple #2
0
 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
Exemple #3
0
 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
Exemple #4
0
 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
Exemple #5
0
 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()
     )
Exemple #6
0
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)
Exemple #7
0
 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,
     ),
Exemple #8
0
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)
Exemple #9
0
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
Exemple #10
0
    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
Exemple #11
0
 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
Exemple #12
0
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