예제 #1
0
파일: commands.py 프로젝트: lih627/nullbot
async def help(session: CommandSession):
    """help: 帮助

用法:
help [cmd]

示例:
help
help progress
"""
    group_id = session.ctx['group_id']

    argv = session.args['argv']

    commands = get_all_commands()
    lines = [get_random_header()]
    try:
        if not argv:
            # global help
            at_str = "@闹闹 "
            for name, cmd in commands.items():
                if cmd.permission == GROUP:
                    docstr = cmd.func.__doc__
                    brief = docstr.split('\n')[0] if docstr else name

                    line = at_str if cmd.only_to_me else ""
                    line += brief
                    lines.append(line)

            for msg in multiline_msg_generator(lines=lines, lineno=False):
                await session.bot.send_msg_rate_limited(group_id=group_id,
                                                        message=msg)

            return

        cmd = argv[0]
        usage = commands[cmd].func.__doc__

        if cmd == "register":
            # render docstring dynamically
            examples = [
                f"{oj}: {url.format('<id>')}"
                for oj, url in PLATFORM_URLS.items()
            ]
            random.shuffle(examples)

            usage %= "\n".join(examples)

        lines += usage.split('\n')
        for msg in multiline_msg_generator(lines=lines, lineno=False):
            await session.bot.send_msg_rate_limited(group_id=group_id,
                                                    message=msg)

    except:
        await session.finish(f"命令{cmd}不存在或文档未定义!@Nuulll 甩锅")
예제 #2
0
async def update_database(session: CommandSession):
    """update: 立刻更新账号数据(冷却时间10分钟)
除此之外,爬虫会在每日18点左右自动更新账号数据(如有bug请 @Nuullll)

用法:
update
"""
    group_id = session.ctx['group_id']
    qq_id = session.ctx['user_id']
    debug = session.ctx.get('debug', False)

    if not debug:
        dm = DataManager(group_id)
        accounts = dm.query_binded_accounts(qq_id)

        await session.send("正在更新数据", at_sender=True)

        if not accounts:
            await session.finish("请先绑定账号!命令:register")

        latest = dm.get_latest_csttime_by_qq(qq_id)
        now = cstnow()
        delta = int((now - latest).total_seconds())
        print(latest, now, delta)

        await session.send(f"最近更新: {latest}")
        if delta < USER_UPDATE_COOLDOWN:
            await session.finish(f"技能冷却中:剩余{USER_UPDATE_COOLDOWN-delta}秒")

        for user_id, platform in accounts:
            ok, snapshot = await dm.get_and_save_user_summary(
                qq_id, user_id, platform)

            if not ok:
                await session.send("ID错误或网络错误!请检查后重试。")

            for msg in multiline_msg_generator(snapshot.lines):
                await session.bot.send_msg_rate_limited(group_id=group_id,
                                                        message=msg)
    else:
        dm = DataManager(group_id)
        accounts = dm.query_binded_accounts(qq_id)

        for user_id, platform in accounts:
            ok, snapshot = await dm.get_and_save_user_summary(
                qq_id, user_id, platform)

            for msg in multiline_msg_generator(snapshot.lines):
                await session.bot.send_msg_rate_limited(user_id=724463877,
                                                        message=msg)
예제 #3
0
async def report_total(session: CommandSession):
    group_id = session.ctx['group_id']
    group_info = await session.bot.get_group_info(group_id=group_id)
    group_name = group_info['group_name']
    member_count = group_info['member_count']

    dm = DataManager(group_id)

    starttime = long_long_ago()
    endtime = cstnow()

    data = dm.report(starttime, endtime)
    data = [[alias, ac_now] for alias, _, ac_now in data if ac_now > 0]

    data.sort(reverse=True, key=itemgetter(1))

    lines = autoalign(data, formatter=lambda x: "| {} | {:<5} |".format(*x))

    entries = min(member_count, REPORT_TOTAL_MAX_ENTRIES, len(data))
    header = f"{group_name} Top {entries} / {member_count}\n"
    header += "# | Name | Accepted |"
    await session.send(header)

    for msg in multiline_msg_generator(lines[:entries], lineno=True):
        await session.bot.send_msg_rate_limited(group_id=group_id, message=msg)
예제 #4
0
파일: commands.py 프로젝트: lih627/nullbot
async def handle_ls(session: CommandSession):
    group_id = session.ctx['group_id']
    user_id = session.ctx['user_id']

    # args
    argv = session.args['argv']
    ls_all = True if '-a' in argv or '--all' in argv else False

    try:
        members = await session.bot.get_group_member_list(group_id=group_id)
    except Exception as e:
        print(type(e), e)

    lines = [
        '{} [{}]'.format(
            member['card'] if member['card'] else member['nickname'],
            member['user_id']) for member in members
    ]

    count = len(lines)
    header = '正在获取群成员列表...共{}人'.format(count)
    try:
        await session.bot.send_msg(group_id=group_id, message=header)

        for msg in multiline_msg_generator(lines=lines, lineno=True):
            await session.bot.send_msg_rate_limited(group_id=group_id,
                                                    message=msg)

            if not ls_all:
                await session.bot.send_msg(
                    group_id=group_id,
                    message="Try `ls -a` or `ls --all` for full message.")
                break
    except Exception as e:
        print(type(e), e)
예제 #5
0
파일: commands.py 프로젝트: lih627/nullbot
async def send_repo_info(session: CommandSession):
    """repo: 查看闹闹机器人开源仓库

用法:
repo
"""
    lines = [get_random_header()]

    lines += [
        'GITHUB: https://github.com/Nuullll/nullbot',
        '欢迎大家follow, star, watch三连'
    ]

    for msg in multiline_msg_generator(lines=lines, lineno=False):
        await session.send(msg)
예제 #6
0
async def report(session: CommandSession):
    group_id = session.ctx['group_id']

    dm = DataManager(group_id)

    starttime = last_sunday()
    endtime = cstnow()

    data = dm.report(starttime, endtime)
    data = [[alias, ac_now, ac_now - ac_before] for alias, ac_before, ac_now in data if ac_now > 0]

    data.sort(reverse=True, key=itemgetter(2, 1))

    lines = autoalign(data, formatter=lambda x: "| {} | {:<5} (+{}) |".format(*x))

    header = f"{starttime} - {endtime}\n"
    header += "| Name | Accepted (+delta) |"
    await session.send(header)

    for msg in multiline_msg_generator(lines, lineno=True):
        await session.bot.send_msg_rate_limited(group_id=group_id, message=msg)
예제 #7
0
파일: scheduler.py 프로젝트: lih627/nullbot
async def get_latest_blogs():
    bot = nb.get_bot()
    # members = await session.bot.get_group_member_list(group_id=group_id)
    # # build qq_id -> card dict
    # card_dict = {member['user_id']: (member['card'] if member['card'] else member['nickname']) for member in members}

    # query all
    recent_updated = []
    now = datetime.now()

    url_map = DataManager.query_blog()
    for qq_id, blog_urls in url_map.items():
        for url in blog_urls:
            # if qq_id not in card_dict:
            #     line = f"{render_cq_at(qq_id)} {url}"
            # else:
            #     line = f"{card_dict[qq_id]} {url}"
            # lines.append(line)
            text, dt = guess_blog_update_time(url)

            if text is None:
                continue

            if (now - dt).days <= 2:
                recent_updated.append((qq_id, url, dt.strftime("%Y-%m-%d")))

    if not recent_updated:
        return

    lines = [f"{render_cq_at('all')} 以下博客近2天内有更新,大家快去学习吧"]
    for qq_id, url, dt_str in recent_updated:
        line = f"{render_cq_at(qq_id)} {url} {dt_str}"
        lines.append(line)

    for group_id in AUTO_BLOG_PUSHES:
        for msg in multiline_msg_generator(lines=lines, lineno=False):
            await bot.send_msg_rate_limited(group_id=group_id, message=msg)
예제 #8
0
async def query_registered(session: CommandSession):
    argv = session.args['argv']
    
    group_id = session.ctx['group_id']
    dm = DataManager(group_id)

    members = await session.bot.get_group_member_list(group_id=group_id)

    lines = []
    for member in members:
        alias = member['card'] if member['card'] else member['nickname']
        qq_id = member['user_id']

        accounts = dm.query_binded_accounts(qq_id)
        msg = f"{alias}: "
        if accounts:
            msg += ", ".join([f"{u}@{p}" for u, p in accounts])
        else:
            msg += "NaN"

        lines.append(msg)
    
    for msg in multiline_msg_generator(lines=lines, lineno=True):
        await session.bot.send_msg_rate_limited(group_id=group_id, message=msg)
예제 #9
0
async def handle_blog(session: CommandSession):
    """blog: 查询本群公开博客列表/绑定博客/解绑博客

用法:
blog    // 查询博客列表
blog add <your blog url>
blog remove <your blog url> [-a]

示例:
blog add https://blog.nuullll.com
blog remove https://blog.nuullll.com
blog remove -a  // 解绑本人所有博客
"""
    argv = session.args['argv']

    group_id = session.event.group_id
    qq_id = session.event.user_id
    dm = DataManager(group_id)

    try:
        op = argv[0].lower()
        url = argv[1]
        
        if op == "add":
            if not is_valid_url(url):
                await session.send("闹闹无法获取博客内容,请检查url或网站可达性,或稍后再试")
                return
            
            dm.bind_blog(qq_id, url)
            await session.send("绑定成功!")
            
        elif op == "remove":
            remove_all = url == "-a"
            valid = is_valid_url(url)
            if not valid and not remove_all:
                await session.send("闹闹无法获取博客内容,请检查url或网站可达性,或稍后再试")
                return

            if valid:
                if not dm.unbind_blog(qq_id, url):
                    await session.send("该博客未绑定,请检查url")
                    return

            if remove_all:
                url_map = dm.query_blog(qq_id=qq_id)
                for url in url_map[qq_id]:
                    dm.unbind_blog(qq_id, url)
                
            await session.send("解绑成功!")
        else:
            raise ValueError("Usage error.")

        return
    except:
        pass

    # query all
    lines = [get_random_header()]
    url_map = dm.query_blog()
    for qq_id, blog_urls in url_map.items():
        for url in blog_urls:
            line = f"{render_cq_at(qq_id)} {url}"
            lines.append(line)
    
    for msg in multiline_msg_generator(lines=lines, lineno=False):
        await session.bot.send_msg_rate_limited(group_id=group_id, message=msg)
예제 #10
0
async def register_helper(session, for_other=False):

    examples = [f"{oj}: {url.format('<id>')}" for oj, url in PLATFORM_URLS.items()]
    shuffle(examples)

    USAGE = """
用法:
register <your OJ profile url>

目前支持的OJ平台:
""" + "\n".join(examples) + """

示例:
register https://leetcode.com/nuullll
"""

    group_id = session.ctx['group_id']

    if not for_other:
        url = session.current_arg_text.strip()

        if not url:
            await session.finish("未检测到url\n" + USAGE)
            return
        
        url = url.split()[0]
        
        qq_id = session.ctx['user_id']
    else:
        argv = session.args['argv']
        qq_id, url = argv

        try:
            if qq_id.isnumeric():
                qq_id = int(qq_id)
            else:
                # infer CQ code
                qq_id = parse_cq_at(qq_id)
        except:
            await session.finish('参数错误!')
            return
    
    platform = ''
    user_id = ''
    for oj, template in PLATFORM_URLS.items():
        # escape special character in template
        template = template.replace('?', '\?')
        m = re.search(template.format('([a-zA-Z0-9_-]+)'), url)
        if m:
            platform = oj
            user_id = m.group(1)
            break
    
    if not user_id:
        await session.finish("请检查URL格式\n" + USAGE)
        return

    dm = DataManager(group_id)

    binded, bind_qq = dm.is_account_binded(user_id, platform)
    if binded:
        if bind_qq == qq_id:
            await session.finish(f"您已绑定{user_id}@{platform},请勿重复操作。")
        else:
            await session.finish(f"绑定失败,{user_id}@{platform}已被用户[CQ:at,qq={bind_qq}]绑定!")
        return

    ok, snapshot = await dm.get_and_save_user_summary(qq_id, user_id, platform)

    if not ok:
        await session.send("ID错误或网络错误!请检查后重试。")
        return
    
    if not dm.bind_account(qq_id, user_id, platform):
        await session.finish("绑定失败,代码线程不安全。")
        return

    await session.send(f"{user_id}@{platform}绑定成功!")
    for msg in multiline_msg_generator(snapshot.lines):
        await session.send(msg)
예제 #11
0
async def handle_blog(session: CommandSession):
    """blog: 查询本群公开博客列表/绑定博客/解绑博客

用法:
blog    // 查询博客列表
blog add <your blog url>
blog remove <your blog url> [-a]

示例:
blog add https://blog.nuullll.com
blog remove https://blog.nuullll.com
blog remove -a  // 解绑本人所有博客
"""
    argv = session.args['argv']

    group_id = session.event.group_id
    qq_id = session.event.user_id
    dm = DataManager(group_id)

    try:
        op = argv[0].lower()
        url = argv[1]

        if op == "add":
            if not is_valid_url(url):
                await session.send("闹闹无法获取博客内容,请检查url或网站可达性,或稍后再试")
                return

            if dm.bind_blog(qq_id, url):
                await session.send("绑定成功!")
            else:
                await session.send("该博客你已经绑定过啦!")

        elif op == "remove":
            remove_all = url == "-a"

            if remove_all:
                url_map = dm.query_blog(qq_id=qq_id)
                for url in url_map[qq_id]:
                    dm.unbind_blog(qq_id, url)
            else:
                if not dm.unbind_blog(qq_id, url):
                    await session.send("该博客未绑定,请检查url")
                    return

            await session.send("解绑成功!")
        else:
            raise ValueError("Usage error.")

        return
    except:
        pass

    members = await session.bot.get_group_member_list(group_id=group_id)
    # build qq_id -> card dict
    name_dict = {
        member['user_id']: (member['card'], member['nickname'])
        for member in members
    }

    # query all
    lines = []
    url_map = dm.query_blog()
    for qq_id, blog_urls in url_map.items():
        for url in blog_urls:
            if qq_id not in name_dict:
                line = f"{render_cq_at(qq_id)} {url}"
            else:
                card, nickname = name_dict[qq_id]
                card = f"({card})" if card else ""
                line = f"{nickname}{card} {url}"
            lines.append(line)

    shuffle(lines)
    lines = [get_random_header()] + lines
    for msg in multiline_msg_generator(lines=lines, lineno=False):
        await session.bot.send_msg_rate_limited(group_id=group_id, message=msg)