【问题标题】:IRC message parser can't handle URLsIRC 消息解析器无法处理 URL
【发布时间】:2016-05-19 04:12:21
【问题描述】:

我在解析 IRC 数据时遇到问题。我有它的工作代码,但是当用户在消息中包含一个 URL 时,它会变得一团糟,我找不到解决方法。这是我当前的代码。

string message = inputStream.ReadLine();
if (message.Contains("PRIVMSG"))
{
    string[] parms = message.Split(':');
    string userMessage = parms[2];
    return userMessage;
}

例子

:*****!*****@*****.tmi.twitch.tv PRIVMSG #***** :http://www.twitch.tv/

由于http:// 部分,它无法获取完整消息。

【问题讨论】:

  • 在继续拆分之前检查http:...
  • 如果它有http,我需要拆分它。
  • 使用 if 语句来检查它是否有 http 以及它是否改变了你的拆分方式,使用正则表达式,或者其他库来处理 url。如果不是“http”,则照常进行。
  • 或者他可以只根据协议解析行,而不是玩弄拆分、正则表达式或其他什么。
  • 如果您对解析很认真,请使用更完整的实现,即ircmessagesharp

标签: c# irc


【解决方案1】:

根据Internet Relay Chat Protocol (RFC 1459),您的消息(开头的控制部分)将始终以: 开头,您的参数也将始终以: 开头(如果您有任何参数 - 例如聊天消息)。

最简单的开始方法是通过查找不在行首的 first 冒号来分隔这两个组件。

string example = @":*****!*****@*****.tmi.twitch.tv PRIVMSG #***** :http://www.twitch.tv/";
int indexOfColon = example.IndexOf(':', 1);
if (indexOfColon > 0)
{
    string command = example.SubString(0,indexOfColon);
    string message = example.SubString(indexOfColon +1);
}

演示:https://dotnetfiddle.net/wBoKlC

使用相同的概念,您可以解析行的任何部分。例如,您可以在此处提取命令 (:PRIVMSG)、用户名 (!*****) 和主机 (@*****.tmi.twitch.tv),只需了解协议结构即可,无需和不必要的 SplitJoin 甚至 RegEx

因此,与其寻找PRIVMSG,不如只解析每一行并决定以后如何处理它。这条线可能很麻烦:

if (message.Contains("PRIVMSG"))

想象一下包含该字符串的任何其他命令(用户名、频道或常规消息)。它会完全破坏你的代码。

顺便说一句:IRC 的“伪”BNF 是:

<message>  ::= [':' <prefix> <SPACE> ] <command> <params> <crlf>
<prefix>   ::= <servername> | <nick> [ '!' <user> ] [ '@' <host> ]
<command>  ::= <letter> { <letter> } | <number> <number> <number>
<SPACE>    ::= ' ' { ' ' }
<params>   ::= <SPACE> [ ':' <trailing> | <middle> <params> ]

<middle>   ::= <Any *non-empty* sequence of octets not including SPACE
               or NUL or CR or LF, the first of which may not be ':'>
<trailing> ::= <Any, possibly *empty*, sequence of octets not including
                 NUL or CR or LF>

<crlf>     ::= CR LF

【讨论】:

  • +1。正是出于这个原因,我在几年前为一个机器人推出了自己的 IRC 处理程序。它实现了整个协议以防止意外,例如您提到的其他地方出现的命令。
【解决方案2】:

试试这个:

if (message.Contains("PRIVMSG"))
{
    string[] parms = message.Split(':');
    string userMessage = string.Join(":", parms.Skip(2));
    return userMessage;
}

【讨论】:

    【解决方案3】:

    您可以按照SO answer 使用正则表达式:

    :(?<nick>[^ ]+?)\!(?<user>[^ ]+?)@(?<host>[^ ]+?) PRIVMSG (?<target>[^ ]+?) :(?<message>.*)
    

    群组消息会有链接:

    使用组:

       var match = Regex.Match(@":*****!*****@*****.tmi.twitch.tv PRIVMSG #***** :http://www.twitch.tv/",
                @":(?<nick>[^ ]+?)\!(?<user>[^ ]+?)@(?<host>[^ ]+?) PRIVMSG (?<target>[^ ]+?) :(?<message>.*)");
            if (match.Success)
            {
                var message = match.Groups["message"].Value;
            }
        }
    

    【讨论】:

    • 这是您用来显示正则表达式数据的网站吗?
    猜你喜欢
    • 1970-01-01
    • 2016-02-20
    • 2015-11-07
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多