Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] 关键词拦截 #551

Open
8 of 10 tasks
RH-Xie opened this issue Jun 5, 2024 · 2 comments
Open
8 of 10 tasks

[Feature Request] 关键词拦截 #551

RH-Xie opened this issue Jun 5, 2024 · 2 comments

Comments

@RH-Xie
Copy link

RH-Xie commented Jun 5, 2024

概况

  • 我已阅读文档
  • 我已查阅Issues和PR
  • 我使用本插件/Bot并阅读过本插件的部分代码
  • 我已实现本issue提出的部分需求
  • 我已实现本issue思路完善的完整需求

动机和需求

需求:支持关键词屏蔽
动机:以关注@明日方舟(微博) 为例,抽奖结果的转发推文比较刷屏,如下:
image

那我可以关闭转发么?是可以的,但是考虑到转发的推文不一定是抽奖结果,可能是别的重要信息(比如联动转发)

据此最好的办法应该是设置关键词屏蔽(Issue #50 曾提及过该功能),如方舟的微博抽奖带有“微博官方唯一抽奖工具”,配置读入后正则过滤。

但是直接做成“包含关键词就不转发”有点不灵活,用户可以选择不转发或者使用替代文本(比如抽奖信息就是太长了,可以转换成一段包含关键信息的文本即可)

在此之上,替换文本里可以包含变量如$source$携带原消息的重要部分(全量替换,原来构建的Post没要了,因为我不太会重新构建一个Post

过滤后示意图:

image

添加的配置(bison_block_keyword项,值为json):
image

需求粗分析(打勾为已实现)

  • 读取关键词配置
  • 检查关键词
  • 替换文本/不转发(配置项为""则不转发,有文字则替换为文字)
  • 替换文本里加入变量(如$source$代表addon来源信息)
  • 根据群号或者订阅id启用对应过滤规则(需在上面的基础多套一层对象)

关键代码示意:send.py

def is_contain_keyword(msg_str: str):
    try:
        for keyword in block_keywords:
            if keyword in msg_str:
                # 包含屏蔽词
                logger.info(f"检测到屏蔽词 {keyword}")
                if not block_set[keyword]:
                    return True, ''
                return True, f"{block_set[keyword]}"
        return False, '' # 不过滤
    except Exception as e:
        logger.error(f"过滤失败 {str(e)}")
        logger.error(f"过滤失败消息: {msg_str}")
        return False, '' # 不过滤

async def _do_send(send_target: PlatformTarget, msg: Sendable):
    # 关键词屏蔽
    msg_str = str(msg)
    addon_info = "来源" + msg_str.split("来源")[-1]
    logger.info(f"addon_info: {addon_info}")
    is_blocked, block_info = is_contain_keyword(msg_str)
    logger.info(f"检测到屏蔽词\nis_blocked: {is_blocked}\n替代消息:{block_info}")
    if is_blocked and not block_info:
        return; # 直接结束
    to_send_msg = msg
    if is_blocked:
        to_send_msg = MessageFactory(block_info.replace("$source$", addon_info))
    try:
        await to_send_msg.send_to(send_target)
    except ActionFailed:  # TODO: catch exception of other adapters
        await refresh_bots()
        logger.warning("send msg failed, refresh bots")

问题

一是目前是全平台、全群组拦截的,不能具体到群组或者某个订阅,另一方面就算是实现了,考虑到配置里些多层嵌套,对用户来说,可能会没那么好配置,望指点

二是而且这种直接str(msg)的写法貌似不太符合规范

目前是能用了,可以极大避免抽奖转发消息的刷屏

@RH-Xie RH-Xie changed the title [Feature Reqeust] 关键词拦截 [Feature Request] 关键词拦截 Jun 5, 2024
@AzideCupric
Copy link
Collaborator

AzideCupric commented Jun 6, 2024

应该类似于订阅Tag的部分,不过这样待屏蔽文本想替换成其他内容可能有点麻烦
转发里的#转发抽奖#tag好像不能参与过滤 坏

@RH-Xie
Copy link
Author

RH-Xie commented Jun 10, 2024

确实是的,还会把原消息屏蔽掉(比如4.29逻各斯的实装预览消息,附带了#转发抽奖#tag)
至于“给每个群聊or订阅配置单独的屏蔽规则”,后来想了下,应该跟随插件的使用习惯,在群组/超管私聊命令or后台去配置屏蔽关键词,维护一个json文件,而不是像我上面那样在.env中写(当时没考虑太多XD

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants