【问题标题】:Command handling for Discord BotDiscord Bot 的命令处理
【发布时间】:2019-11-12 00:12:38
【问题描述】:

我正在开发一个 Discord Bot 以进行审核。我使用 JDA 库。我目前卡在命令处理上。

有4种命令场景:

".ban <@302390080104955904> advertising"
".ban <@!302390080104955904> advertising"
".ban 302390080104955904 advertising"
".ban et advertising"

当机器人收到命令时,我将命令和前缀子串起来。

在第一种情况下,我想提取 ID“302390080104955904”并将其从字符串中删除,这样我就知道了原因

第二种情况和第一种一样,但@后面有一个感叹号

在第三种情况下,我只需提取 ID 并将其删除

在最后一个场景中,我只需要提供用户名并搜索用户。

我多次尝试实现这一点,但总是失败。 关于如何完成这项工作的任何想法

编辑:我接受 Kotlin 和 Java 的答案

【问题讨论】:

    标签: java string parsing kotlin


    【解决方案1】:

    我假设您已经有一种将命令与命令内容分开的技术 - 如果我误解了那部分,请纠正我。

    一旦您将命令本身与内容分开,您将得到一个类似于以下内容的字符串:

    val commandContent = "<@!302390080104955904> advertising";
    

    从这里开始,您需要将其拆分:

    val cache = commandContent.split(" ", limit=2);
    

    您现在拥有的是一个最多两个大小的数组。

    从那里,稍微进一步解析以保持数据清晰:

    // Note: I haven't implemented any safety. If you get an unexpected size, you'll need to handle that yourself
    val target = cache[0];
    val reason = cache[1];
    

    从这里,您可以使用正则表达式。在我进入代码之前,让我解释一下正则表达式:

    <?        - Attempt to match an opening bracket
    @?        - Attempt to find @
    !?        - Attempt to find !
    ([0-9]+)  - Constant: find a group of numbers
    >?        - Attempt to find a closing bracket
    

    这也有助于过滤掉 username#discriminator 格式的用户名 - 任何非数字字符都会将字符串识别为不是 ID。您也可以在regex101.com 上玩弄它。

    从这里,您可以设置匹配:

    val regex = """<?@?!?([0-9]+)>?""".toRegex()
    fun getMatch(target: String) : String? = regex.matchEntire(target)?.groups?.get(1)?.value
    

    getMatch(target) 如果未找到 ID,则返回 null,否则将 ID 作为字符串。

    现在,您需要做的就是调用该方法并做任何您想做的事情:

    val match = getMatch(target); 
    if (match != null) {
        // You have the UID. 
    } else {
        // You have a username. Use `target` to retrieve the user ID. 
    } 
    

    虽然这可行,但您需要记住一些事情:当涉及到用户名时,您的示例仅包含用户名没有鉴别符。如果你的机器人加入了一个足够大的服务器,并且你遍历用户以找到一个匹配的用户名,你可能会发现自己禁止了错误的人,或者如果你忘记打破循环,则禁止使用该用户名的所有人。

    如果我是你,我会检查 #[0-9]{4} 的存在,方法是使用正则表达式,或者将用户名拆分为 #,并确保你得到两部分,并且第二部分只包含数字:

    val split = target.split("#")
    if (split.size != 2) // Fail
    if (split[1].toLongOrNull() == null || split[1].length != 4 || split[1].contains("-")) // fail - non-number long, invalid discriminator (discriminators are always 4 digits), or negative discriminator 
    

    鉴别器在00019999 的范围内。无论哪种方式,它总是有 4 位数字。请注意,转换为 long 会丢失任何前缀 0,因此请坚持使用字符串进行验证。如果你运行这个验证,你需要对用户名运行它,不是昵称(昵称可以包含#,用户名不能)

    【讨论】:

      猜你喜欢
      • 2020-11-18
      • 2018-03-04
      • 1970-01-01
      • 1970-01-01
      • 2020-10-25
      • 2018-10-21
      • 2021-03-01
      • 1970-01-01
      • 2021-04-11
      相关资源
      最近更新 更多