我正在研究Discord Bot进行审核。我使用JDA库。我目前无法处理命令。
有4种命令方案:
".ban <@302390080104955904> advertising"
".ban <@!302390080104955904> advertising"
".ban 302390080104955904 advertising"
".ban et advertising"
当bot收到命令时,我会将命令和前缀放在子字符串中。
在第一种情况下,我想提取ID“ 302390080104955904”并将其从字符串中删除,这样我就知道了原因
第二种情况与第一种情况相同,但是在@之后有感叹号
在第三种情况下,我只需要提取ID并将其删除
在最后一种情况下,我只需要提供用户名并搜索用户即可。
我试图多次实现,但是我总是失败。 关于如何进行这项工作的任何想法
编辑:我接受Kotlin和Java答案
答案 0 :(得分:3)
我假设您已经有一种将命令与命令内容分离的技术-如果我误解了该部分,请纠正我。
一旦命令本身与内容分开,您将得到类似于以下内容的字符串:
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
如果找不到ID,则 getMatch(target)
返回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}
处拆分用户名来检查{{1}}是否存在,并确保获得两部分,而第二部分仅由数字组成:
#
鉴别符的范围是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
至0001
。无论哪种方式,它始终具有4位数字。请注意,到long的转换将丢失所有带前缀的0,因此请坚持使用字符串进行验证。而且,如果您运行此验证,则需要针对用户名(不)昵称(昵称可以包含9999
,用户名不能)