<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>聊天机器人 on 勇气</title><link>https://courages.us/tag/%E8%81%8A%E5%A4%A9%E6%9C%BA%E5%99%A8%E4%BA%BA/</link><description>Recent content in 聊天机器人 on 勇气</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Fri, 20 Nov 2020 11:32:28 +0800</lastBuildDate><atom:link href="https://courages.us/tag/%E8%81%8A%E5%A4%A9%E6%9C%BA%E5%99%A8%E4%BA%BA/index.xml" rel="self" type="application/rss+xml"/><item><title>即时通信IRC服务Oragono</title><link>https://courages.us/%E5%8D%B3%E6%97%B6%E9%80%9A%E4%BF%A1irc%E6%9C%8D%E5%8A%A1oragono/</link><pubDate>Wed, 18 Nov 2020 15:19:05 +0800</pubDate><guid>https://courages.us/%E5%8D%B3%E6%97%B6%E9%80%9A%E4%BF%A1irc%E6%9C%8D%E5%8A%A1oragono/</guid><description>&lt;p&gt;前一篇讲了&lt;a class="link" href="https://courages.us/%e5%8d%b3%e6%97%b6%e9%80%9a%e4%bf%a1xmpp%e6%9c%8d%e5%8a%a1%e5%99%a8ejabberd-openfire/" target="_blank" rel="noopener"&#10; &gt;XMPP通信&lt;/a&gt;，还有一种比它还早的协议&lt;a class="link" href="https://zh.wikipedia.org/wiki/IRC" target="_blank" rel="noopener"&#10; &gt;IRC（Internet Relay Chat）&lt;/a&gt;，是一种简单的文本聊天协议，支持一对一聊天和群聊（频道）。通常IRC聊天只需要昵称而不需要密码（也可以使用密码），这与XMML不同，使得它可以作为公开的聊天频道，比如游戏直播平台Twitch就使用类似的功能来实现聊天。IRC同样有许多服务端，比如&lt;a class="link" href="https://www.inspircd.org/" target="_blank" rel="noopener"&#10; &gt;InspIRCd&lt;/a&gt;和客户端软件，比如&lt;a class="link" href="https://irssi.org/" target="_blank" rel="noopener"&#10; &gt;Irssi&lt;/a&gt;，也可以直接连接公开的IRC服务器，比如&lt;a class="link" href="https://freenode.net/" target="_blank" rel="noopener"&#10; &gt;Freenode&lt;/a&gt;。事实上IRC协议非常简单，只要能对相应的&lt;a class="link" href="https://ircv3.net/irc/" target="_blank" rel="noopener"&#10; &gt;命令&lt;/a&gt;作出响应就可以在各个客户端之间通信，因此有许多不同编程语言的服务端/客户端实现。&lt;a class="link" href="https://github.com/oragono/oragono" target="_blank" rel="noopener"&#10; &gt;Oragono&lt;/a&gt;便是IRC 服务器的Golang实现，支持&lt;a class="link" href="https://ircv3.net/" target="_blank" rel="noopener"&#10; &gt;IRCv3&lt;/a&gt;，支持SASL/LDAP认证，支持服务端保存消息历史记录。&lt;br&gt;&#10;Oragono运行很简单，克隆代码，编辑配置文件就可以了&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜  oragono24 ls&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CHANGELOG.md     README           default.yaml     docs             languages        oragono          oragono.motd     traditional.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜  oragono24 cp default.yaml ircd.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜  oragono24 ./oragono mkcerts&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020/11/11 12:01:04 making self-signed certificates&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020/11/11 12:01:04  making cert &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; :6697 listener&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020/11/11 12:01:04   Certificate created at fullchain.pem : privkey.pem&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜  oragono24 ls&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CHANGELOG.md     README           default.yaml     docs             fullchain.pem    ircd.yaml        languages        oragono          oragono.motd     privkey.pem      traditional.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜  oragono24 ./oragono run&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.320Z : info : server : oragono-2.4.0 starting&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.320Z : info : server : Using config file : ircd.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.320Z : info : server : Using datastore : ircd.db&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.344Z : info : server : Proxied IPs will be accepted from : localhost&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.345Z : info : listeners : now listening on &lt;span style="color:#f92672"&gt;[&lt;/span&gt;::1&lt;span style="color:#f92672"&gt;]&lt;/span&gt;:6667, tls&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, tlsproxy&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, tor&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, websocket&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.345Z : info : listeners : now listening on :6697, tls&lt;span style="color:#f92672"&gt;=&lt;/span&gt;true, tlsproxy&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, tor&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, websocket&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.345Z : info : listeners : now listening on :8097, tls&lt;span style="color:#f92672"&gt;=&lt;/span&gt;true, tlsproxy&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, tor&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, websocket&lt;span style="color:#f92672"&gt;=&lt;/span&gt;true.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.345Z : info : listeners : now listening on 127.0.0.1:6667, tls&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, tlsproxy&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, tor&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, websocket&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.345Z : info : server : Server running&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:38.386Z : info : connect-ip : Client connecting: real IP 192.168.33.1, proxied IP &amp;lt;nil&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:38.439Z : info : accounts : client : * : logged into account : kiwi-n30&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:38.442Z : info : connect : Client connected &lt;span style="color:#f92672"&gt;[&lt;/span&gt;kiwi-n30&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;u:~u&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;r:https://kiwiirc.com/&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:40.955Z : info : connect-ip : Client connecting: real IP 192.168.33.1, proxied IP &amp;lt;nil&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:40.963Z : info : connect : Client connected &lt;span style="color:#f92672"&gt;[&lt;/span&gt;kiwi-n28&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;u:~u&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;r:https://kiwiirc.com/&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:56.198Z : info : connect-ip : Client connecting: real IP 192.168.33.1, proxied IP &amp;lt;nil&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:56.209Z : info : connect : Client connected &lt;span style="color:#f92672"&gt;[&lt;/span&gt;kiwi-n29&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;u:~u&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;r:https://kiwiirc.com/&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;编辑ircd.yml，设置管理密码，启用一下WebSocket，保存历史消息到MySQL。opers/admin管理密码在认证管理员的时候使用的，可以使用命令oragono genpasswd生成。ircd.db用来保存注册用户，使用的并不是SQLite，而是Golang实现的一个嵌入式的内存Key/Value存储&lt;a class="link" href="https://github.com/tidwall/buntdb" target="_blank" rel="noopener"&#10; &gt;BuntDB&lt;/a&gt;，可以持久化到硬盘。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# network configuration&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;network&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# name of the network&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;OragonoTest&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# server configuration&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;server&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# server name&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;oragono.test&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# addresses to listen on&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;listeners&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# The standard plaintext port for IRC is 6667. Allowing plaintext over the&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# public Internet poses serious security and privacy issues. Accordingly,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# we recommend using plaintext only on local (loopback) interfaces:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;127.0.0.1:6667&amp;#34;: &lt;/span&gt;&lt;span style="color:#75715e"&gt;# (loopback ipv4, localhost-only)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;[::1]:6667&amp;#34;: &lt;/span&gt; &lt;span style="color:#75715e"&gt;# (loopback ipv6, localhost-only)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# If you need to serve plaintext on public interfaces, comment out the above&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# two lines and uncomment the line below (which listens on all interfaces):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# &amp;#34;:6667&amp;#34;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Alternately, if you have a TLS certificate issued by a recognized CA,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# you can configure port 6667 as an STS-only listener that only serves&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# &amp;#34;redirects&amp;#34; to the TLS port, but doesn&amp;#39;t allow chat. See the manual&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# for details.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# The standard SSL/TLS port for IRC is 6697. This will listen on all interfaces:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;:6697&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;tls&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;cert&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;fullchain.pem&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;key&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;privkey.pem&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# &amp;#39;proxy&amp;#39; should typically be false. It&amp;#39;s only for Kubernetes-style load&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# balancing that does not terminate TLS, but sends an initial PROXY line&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# in plaintext.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;proxy&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Example of a Unix domain socket for proxying:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# &amp;#34;/tmp/oragono_sock&amp;#34;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Example of a Tor listener: any connection that comes in on this listener will&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# be considered a Tor connection. It is strongly recommended that this listener&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# *not* be on a public interface --- it should be on 127.0.0.0/8 or unix domain:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# &amp;#34;/hidden_service_sockets/oragono_tor_sock&amp;#34;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# tor: true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Example of a WebSocket listener:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;:8097&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;websocket&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;tls&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;cert&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;fullchain.pem&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;key&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;privkey.pem&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ircd operators&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;opers&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# operator named &amp;#39;admin&amp;#39;; log in with /OPER admin [password]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;admin&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# which capabilities this oper has access to&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;class&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;server-admin&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# custom whois line&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;whois-line&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;is a server admin&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# custom hostname&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;vhost&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;staff&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# normally, operator status is visible to unprivileged users in WHO and WHOIS&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# responses. this can be disabled with &amp;#39;hidden&amp;#39;. (&amp;#39;hidden&amp;#39; also causes the&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# &amp;#39;vhost&amp;#39; line above to be ignored.)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;hidden&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# modes are modes to auto-set upon opering-up. uncomment this to automatically&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# enable snomasks (&amp;#34;server notification masks&amp;#34; that alert you to server events;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# see `/quote help snomasks` while opered-up for more information):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;#modes: +is acjknoqtuxv&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# operators can be authenticated either by password (with the /OPER command),&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# or by certificate fingerprint, or both. if a password hash is set, then a&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# password is required to oper up (e.g., /OPER dan mypassword). to generate&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# the hash, use `oragono genpasswd`.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;password&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;$2a$04$I2Yhr7UF4p3iyEZcKTPJgukLA9mm00B1wQgicJvGZP/gf0u0tbQQy&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# datastore configuration&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;datastore&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# path to the datastore&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;path&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ircd.db&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# if the database schema requires an upgrade, `autoupgrade` will attempt to&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# perform it automatically on startup. the database will be backed&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# up, and if the upgrade fails, the original database will be restored.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;autoupgrade&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# connection information for MySQL (currently only used for persistent history):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;mysql&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;enabled&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;host&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;port&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;3306&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# if socket-path is set, it will be used instead of host:port&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;#socket-path: &amp;#34;/var/run/mysqld/mysqld.sock&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;user&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;password&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;history-database&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;oragono_history&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;timeout&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;30s&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;IRC服务端设置好了，使用客户端连上去就可以聊天了。IRC协议类似HTTP协议，服务器地址类似irc://irc.freenode.net，但是也可以使用web来连接，前面配置了监听来自8097端口的websocket请求。这里使用web的IRC客户端&lt;a class="link" href="https://kiwiirc.com/" target="_blank" rel="noopener"&#10; &gt;Kiwi IRC&lt;/a&gt;，这是Vue实现的一个web客户端，各个组件之间通过触发/订阅Vue实例状态/事件变化进行通信，支持自定义组件/中间件，这也是Freenode使用的客户端。Kiwiirc主要聚焦连接和消息的处理，比如websocket连接/发送/监听，消息的格式化/通知/声音/状态。它能够连接websocket的IRC服务器，甚至还提供在线&lt;a class="link" href="https://kiwiirc.com/clientbuilder/#/" target="_blank" rel="noopener"&#10; &gt;生成器&lt;/a&gt;，只需要添加websocket url就好了&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;windowTitle&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Kiwi IRC with Oragono Test&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;startupScreen&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;welcome&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;kiwiServer&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;http://oragono.test&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;restricted&amp;#34;&lt;/span&gt;: false,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;theme&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Default&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;themes&amp;#34;&lt;/span&gt;: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Default&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/default&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Dark&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/dark&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Coffee&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/coffee&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;GrayFox&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/grayfox&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Nightswatch&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/nightswatch&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Osprey&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/osprey&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Radioactive&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/radioactive&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Sky&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/sky&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Elite&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/elite&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;startupOptions&amp;#34;&lt;/span&gt; : &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;websocket&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;wss://127.0.0.1:8097&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;channel&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;#kiwiirc-default&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;nick&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;kiwi-n?&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;embedly&amp;#34;&lt;/span&gt;: &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;plugins&amp;#34;&lt;/span&gt;: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;customise&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/plugins/customise.html&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;运行登录后的效果&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_action.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="310px" data-flex-grow="129" height="232" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_action-300x232.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_auth.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="566px" data-flex-grow="236" height="127" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_auth-300x127.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_auth_no.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="660px" data-flex-grow="275" height="109" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_auth_no-300x109.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_channel.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="960px" data-flex-grow="400" height="75" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_channel-300x75.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_channel_register.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="406px" data-flex-grow="169" height="177" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_channel_register-300x177.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_invite.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="293px" data-flex-grow="122" height="245" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_invite-300x245.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_join_history.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="431px" data-flex-grow="179" height="167" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_join_history-300x167.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_join_self.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="452px" data-flex-grow="188" height="159" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_join_self-300x159.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_login.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="566px" data-flex-grow="236" height="127" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_login-300x127.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_oper.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="231px" data-flex-grow="96" height="300" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_oper-289x300.png" width="289"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_preload.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="489px" data-flex-grow="204" height="147" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_preload-300x147.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;其实IRC是基于TCP连接的文本交互的，也可以使用telnet来模拟&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ ~ telnet 127.0.0.1 &lt;span style="color:#ae81ff"&gt;6667&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Trying 127.0.0.1...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Connected to localhost.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Escape character is &lt;span style="color:#e6db74"&gt;&amp;#39;^]&amp;#39;&lt;/span&gt;.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CAP LS &lt;span style="color:#ae81ff"&gt;302&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:oragono.test CAP * LS * :account-notify account-tag away-notify batch cap-notify chghost draft/channel-rename draft/chathistory draft/event-playback draft/languages&lt;span style="color:#f92672"&gt;=&lt;/span&gt;16,en,~bs,~de,~el,~en-AU,~es,~fi,~fr-FR,~it,~nl,~no,~pl,~pt-BR,~ro,~tr-TR,~zh-CN draft/multiline&lt;span style="color:#f92672"&gt;=&lt;/span&gt;max-bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;4096,max-lines&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; draft/register&lt;span style="color:#f92672"&gt;=&lt;/span&gt;before-connect draft/relaymsg&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/ draft/resume-0.5 echo-message extended-join invite-notify labeled-response message-tags multi-prefix oragono.io/nope sasl&lt;span style="color:#f92672"&gt;=&lt;/span&gt;PLAIN,EXTERNAL server-time setname&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:oragono.test CAP * LS :userhost-in-names znc.in/playback znc.in/self-message&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NICK kiwi-n26&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;USER kiwi-n26 &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; * https://kiwiirc.com/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CAP REQ :account-notify account-tag away-notify batch cap-notify draft/chathistory extended-join invite-notify message-tags multi-prefix server-time userhost-in-names znc.in/self-message&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:02.201Z :oragono.test CAP * ACK :account-notify account-tag away-notify batch cap-notify draft/chathistory extended-join invite-notify message-tags multi-prefix server-time userhost-in-names znc.in/self-message&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CAP END&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;001&lt;/span&gt; kiwi-n26 :Welcome to the Internet Relay Network kiwi-n26&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;002&lt;/span&gt; kiwi-n26 :Your host is oragono.test, running version oragono-2.4.0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;003&lt;/span&gt; kiwi-n26 :This server was created Fri, &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; Nov &lt;span style="color:#ae81ff"&gt;2020&lt;/span&gt; 00:35:48 UTC&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;004&lt;/span&gt; kiwi-n26 oragono.test oragono-2.4.0 BERTZios CEIMRUabehiklmnoqstuv Iabehkloqv&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;005&lt;/span&gt; kiwi-n26 AWAYLEN&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;390&lt;/span&gt; BOT&lt;span style="color:#f92672"&gt;=&lt;/span&gt;B CASEMAPPING&lt;span style="color:#f92672"&gt;=&lt;/span&gt;ascii CHANLIMIT&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#75715e"&gt;#:100 CHANMODES=Ibe,k,l,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m INVEX KICKLEN=390 MAXLIST=beI:60 :are supported by this server&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;005&lt;/span&gt; kiwi-n26 MAXTARGETS&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; MODES MONITOR&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; NETWORK&lt;span style="color:#f92672"&gt;=&lt;/span&gt;OragonoTest NICKLEN&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt; PREFIX&lt;span style="color:#f92672"&gt;=(&lt;/span&gt;qaohv&lt;span style="color:#f92672"&gt;)&lt;/span&gt;~&amp;amp;@%+ STATUSMSG&lt;span style="color:#f92672"&gt;=&lt;/span&gt;~&amp;amp;@%+ TARGMAX&lt;span style="color:#f92672"&gt;=&lt;/span&gt;NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;390&lt;/span&gt; UTF8MAPPING&lt;span style="color:#f92672"&gt;=&lt;/span&gt;rfc8265 WHOX draft/CHATHISTORY&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; :are supported by this server&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;251&lt;/span&gt; kiwi-n26 :There are &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; users and &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; invisible on &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; server&lt;span style="color:#f92672"&gt;(&lt;/span&gt;s&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;252&lt;/span&gt; kiwi-n26 &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; :IRC Operators online&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;253&lt;/span&gt; kiwi-n26 &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; :unregistered connections&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;254&lt;/span&gt; kiwi-n26 &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; :channels formed&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;255&lt;/span&gt; kiwi-n26 :I have &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; clients and &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; servers&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;265&lt;/span&gt; kiwi-n26 &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; :Current local users 4, max &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;266&lt;/span&gt; kiwi-n26 &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; :Current global users 4, max &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;375&lt;/span&gt; kiwi-n26 :- oragono.test Message of the day -&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- ▄▄▄ ▄▄▄· ▄▄ • ▐ ▄&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- ▪ ▀▄ █·▐█ ▀█ ▐█ ▀ ▪▪ •█▌▐█▪&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- ▄█▀▄ ▐▀▀▄ ▄█▀▀█ ▄█ ▀█▄ ▄█▀▄▪▐█▐▐▌ ▄█▀▄&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- ▐█▌.▐▌▐█•█▌▐█ ▪▐▌▐█▄▪▐█▐█▌ ▐▌██▐█▌▐█▌.▐▌&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- ▀█▄▀▪.▀ ▀ ▀ ▀ ·▀▀▀▀ ▀█▄▀ ▀▀ █▪ ▀█▄▀▪&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- This is the default Oragono MOTD.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- If motd-formatting is enabled in the config file, you can use the dollarsign character to&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- create special formatting such as bold, italics and color codes.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- For example, here are a few formatted lines &lt;span style="color:#f92672"&gt;(&lt;/span&gt;enable motd-formatting to see these in action&lt;span style="color:#f92672"&gt;)&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- - this is bold text.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- - this is italics text.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- - this is 4red and 2blue text.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- - this is 4,12red text with a light blue background.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- - this is a normal escaped dollarsign: $&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- And now a few fun colour charts!&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 1,0 &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; 0,1 &lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; 0,2 &lt;span style="color:#ae81ff"&gt;02&lt;/span&gt; 0,3 &lt;span style="color:#ae81ff"&gt;03&lt;/span&gt; 1,4 &lt;span style="color:#ae81ff"&gt;04&lt;/span&gt; 0,5 &lt;span style="color:#ae81ff"&gt;05&lt;/span&gt; 0,6 &lt;span style="color:#ae81ff"&gt;06&lt;/span&gt; 1,7 &lt;span style="color:#ae81ff"&gt;07&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 1,8 &lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; 1,9 &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt; 0,10 &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; 1,11 &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt; 0,12 &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt; 1,13 &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; 1,14 &lt;span style="color:#ae81ff"&gt;14&lt;/span&gt; 1,15 &lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 0,16 &lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; 0,17 &lt;span style="color:#ae81ff"&gt;17&lt;/span&gt; 0,18 &lt;span style="color:#ae81ff"&gt;18&lt;/span&gt; 0,19 &lt;span style="color:#ae81ff"&gt;19&lt;/span&gt; 0,20 &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; 0,21 &lt;span style="color:#ae81ff"&gt;21&lt;/span&gt; 0,22 &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt; 0,23 &lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; 0,24 &lt;span style="color:#ae81ff"&gt;24&lt;/span&gt; 0,25 &lt;span style="color:#ae81ff"&gt;25&lt;/span&gt; 0,26 &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; 0,27 &lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 0,28 &lt;span style="color:#ae81ff"&gt;28&lt;/span&gt; 0,29 &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 0,30 &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt; 0,31 &lt;span style="color:#ae81ff"&gt;31&lt;/span&gt; 0,32 &lt;span style="color:#ae81ff"&gt;32&lt;/span&gt; 0,33 &lt;span style="color:#ae81ff"&gt;33&lt;/span&gt; 0,34 &lt;span style="color:#ae81ff"&gt;34&lt;/span&gt; 0,35 &lt;span style="color:#ae81ff"&gt;35&lt;/span&gt; 0,36 &lt;span style="color:#ae81ff"&gt;36&lt;/span&gt; 0,37 &lt;span style="color:#ae81ff"&gt;37&lt;/span&gt; 0,38 &lt;span style="color:#ae81ff"&gt;38&lt;/span&gt; 0,39 &lt;span style="color:#ae81ff"&gt;39&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 0,40 &lt;span style="color:#ae81ff"&gt;40&lt;/span&gt; 0,41 &lt;span style="color:#ae81ff"&gt;41&lt;/span&gt; 0,42 &lt;span style="color:#ae81ff"&gt;42&lt;/span&gt; 0,43 &lt;span style="color:#ae81ff"&gt;43&lt;/span&gt; 0,44 &lt;span style="color:#ae81ff"&gt;44&lt;/span&gt; 0,45 &lt;span style="color:#ae81ff"&gt;45&lt;/span&gt; 0,46 &lt;span style="color:#ae81ff"&gt;46&lt;/span&gt; 0,47 &lt;span style="color:#ae81ff"&gt;47&lt;/span&gt; 0,48 &lt;span style="color:#ae81ff"&gt;48&lt;/span&gt; 0,49 &lt;span style="color:#ae81ff"&gt;49&lt;/span&gt; 0,50 &lt;span style="color:#ae81ff"&gt;50&lt;/span&gt; 0,51 &lt;span style="color:#ae81ff"&gt;51&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 0,52 &lt;span style="color:#ae81ff"&gt;52&lt;/span&gt; 0,53 &lt;span style="color:#ae81ff"&gt;53&lt;/span&gt; 1,54 &lt;span style="color:#ae81ff"&gt;54&lt;/span&gt; 1,55 &lt;span style="color:#ae81ff"&gt;55&lt;/span&gt; 1,56 &lt;span style="color:#ae81ff"&gt;56&lt;/span&gt; 1,57 &lt;span style="color:#ae81ff"&gt;57&lt;/span&gt; 1,58 &lt;span style="color:#ae81ff"&gt;58&lt;/span&gt; 0,59 &lt;span style="color:#ae81ff"&gt;59&lt;/span&gt; 0,60 &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt; 0,61 &lt;span style="color:#ae81ff"&gt;61&lt;/span&gt; 0,62 &lt;span style="color:#ae81ff"&gt;62&lt;/span&gt; 0,63 &lt;span style="color:#ae81ff"&gt;63&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 0,64 &lt;span style="color:#ae81ff"&gt;64&lt;/span&gt; 1,65 &lt;span style="color:#ae81ff"&gt;65&lt;/span&gt; 1,66 &lt;span style="color:#ae81ff"&gt;66&lt;/span&gt; 1,67 &lt;span style="color:#ae81ff"&gt;67&lt;/span&gt; 1,68 &lt;span style="color:#ae81ff"&gt;68&lt;/span&gt; 1,69 &lt;span style="color:#ae81ff"&gt;69&lt;/span&gt; 1,70 &lt;span style="color:#ae81ff"&gt;70&lt;/span&gt; 1,71 &lt;span style="color:#ae81ff"&gt;71&lt;/span&gt; 0,72 &lt;span style="color:#ae81ff"&gt;72&lt;/span&gt; 0,73 &lt;span style="color:#ae81ff"&gt;73&lt;/span&gt; 0,74 &lt;span style="color:#ae81ff"&gt;74&lt;/span&gt; 0,75 &lt;span style="color:#ae81ff"&gt;75&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 1,76 &lt;span style="color:#ae81ff"&gt;76&lt;/span&gt; 1,77 &lt;span style="color:#ae81ff"&gt;77&lt;/span&gt; 1,78 &lt;span style="color:#ae81ff"&gt;78&lt;/span&gt; 1,79 &lt;span style="color:#ae81ff"&gt;79&lt;/span&gt; 1,80 &lt;span style="color:#ae81ff"&gt;80&lt;/span&gt; 1,81 &lt;span style="color:#ae81ff"&gt;81&lt;/span&gt; 1,82 &lt;span style="color:#ae81ff"&gt;82&lt;/span&gt; 1,83 &lt;span style="color:#ae81ff"&gt;83&lt;/span&gt; 1,84 &lt;span style="color:#ae81ff"&gt;84&lt;/span&gt; 1,85 &lt;span style="color:#ae81ff"&gt;85&lt;/span&gt; 1,86 &lt;span style="color:#ae81ff"&gt;86&lt;/span&gt; 1,87 &lt;span style="color:#ae81ff"&gt;87&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 0,88 &lt;span style="color:#ae81ff"&gt;88&lt;/span&gt; 0,89 &lt;span style="color:#ae81ff"&gt;89&lt;/span&gt; 0,90 &lt;span style="color:#ae81ff"&gt;90&lt;/span&gt; 0,91 &lt;span style="color:#ae81ff"&gt;91&lt;/span&gt; 0,92 &lt;span style="color:#ae81ff"&gt;92&lt;/span&gt; 0,93 &lt;span style="color:#ae81ff"&gt;93&lt;/span&gt; 0,94 &lt;span style="color:#ae81ff"&gt;94&lt;/span&gt; 0,95 &lt;span style="color:#ae81ff"&gt;95&lt;/span&gt; 1,96 &lt;span style="color:#ae81ff"&gt;96&lt;/span&gt; 1,97 &lt;span style="color:#ae81ff"&gt;97&lt;/span&gt; 1,98 &lt;span style="color:#ae81ff"&gt;98&lt;/span&gt; 99,99 &lt;span style="color:#ae81ff"&gt;99&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- For more information on using these, see MOTDFORMATTING.md&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;376&lt;/span&gt; kiwi-n26 :End of MOTD command&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.715Z :oragono.test &lt;span style="color:#ae81ff"&gt;221&lt;/span&gt; kiwi-n26 +Zi&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WHO kiwi-n26&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:15.649Z :oragono.test &lt;span style="color:#ae81ff"&gt;352&lt;/span&gt; kiwi-n26 * ~u gcjc79gmtbe42.irc oragono.test kiwi-n26 H :0 https://kiwiirc.com/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:15.649Z :oragono.test &lt;span style="color:#ae81ff"&gt;315&lt;/span&gt; kiwi-n26 kiwi-n26!*@* :End of WHO list&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;JOIN &lt;span style="color:#75715e"&gt;#kiwiirc-default&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@msgid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;bidkvpja5njjtgchub8u65pxgn;time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:26.706Z :kiwi-n26!~u@gcjc79gmtbe42.irc JOIN &lt;span style="color:#75715e"&gt;#kiwiirc-default * https://kiwiirc.com/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:26.706Z :oragono.test &lt;span style="color:#ae81ff"&gt;353&lt;/span&gt; kiwi-n26 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#75715e"&gt;#kiwiirc-default :@kiwi-n28!~u@5g96q93tqw3vn.irc kiwi-n30!~u@5g96q93tqw3vn.irc kiwi-n29!~u@5g96q93tqw3vn.irc kiwi-n26!~u@gcjc79gmtbe42.irc&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:26.706Z :oragono.test &lt;span style="color:#ae81ff"&gt;366&lt;/span&gt; kiwi-n26 &lt;span style="color:#75715e"&gt;#kiwiirc-default :End of NAMES list&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;JOIN &lt;span style="color:#75715e"&gt;#ops&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@msgid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;hftqmpu4ieyjybx9bbgf4vpbia;time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:32.145Z :kiwi-n26!~u@gcjc79gmtbe42.irc JOIN &lt;span style="color:#75715e"&gt;#ops * https://kiwiirc.com/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:32.145Z :oragono.test &lt;span style="color:#ae81ff"&gt;353&lt;/span&gt; kiwi-n26 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#75715e"&gt;#ops :@kiwi-n28!~u@5g96q93tqw3vn.irc kiwi-n30!~u@5g96q93tqw3vn.irc kiwi-n29!~u@5g96q93tqw3vn.irc kiwi-n26!~u@gcjc79gmtbe42.irc&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:32.145Z :oragono.test &lt;span style="color:#ae81ff"&gt;366&lt;/span&gt; kiwi-n26 &lt;span style="color:#75715e"&gt;#ops :End of NAMES list&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PRIVMSG &lt;span style="color:#75715e"&gt;#ops hello&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PRIVMSG &lt;span style="color:#75715e"&gt;#ops :kiwi-n28 good morning&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PRIVMSG kiwi-n28 &lt;span style="color:#f92672"&gt;=&lt;/span&gt;D&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PING kiwitime-1605232555315&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:57:14.150Z :oragono.test PONG oragono.test kiwitime-1605232555315&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CHATHISTORY BEFORE kiwi-n28 * &lt;span style="color:#ae81ff"&gt;50&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:57:38.462Z :oragono.test BATCH +1 chathistory kiwi-n28&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@msgid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;rqdbvmytzppssc5ymp7ffhmkga;time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:56:05.705Z;batch&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; :kiwi-n26!~u@gcjc79gmtbe42.irc PRIVMSG kiwi-n28 :&lt;span style="color:#f92672"&gt;=&lt;/span&gt;D&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:57:38.462Z :oragono.test BATCH -1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:59:08.466Z PING kiwi-n26&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:kiwi-n26!~u@gcjc79gmtbe42.irc QUIT :Ping timeout: 2m30s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ERROR :Ping timeout: 2m30s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Connection closed by foreign host.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;可以看到这些消息都带有一定的格式，客户端根据特地的格式解析就可以个性化显示来。带有符号@/：前缀的消息都是服务器推送下来的消息，反之都是客户端请求的消息。“CAP LS 302”即协商会话协议版本，随即用命令“NICK ”设置昵称（登录名），和“USER 0 * ”设置该昵称显示的用户名，最后以“CAP END”结束协商，开始会话。服务端推送过来的消息格式为时间戳+服务器+响应码+接受者昵称+消息内容，即“@time=2020-11-13T01:55:07.714Z :oragono.test 001 :Welcome to the Internet Relay Network ”，001代表欢迎信息，具体响应码可以参考&lt;a class="link" href="https://tools.ietf.org/html/rfc2812#section-5.2" target="_blank" rel="noopener"&#10; &gt;这里&lt;/a&gt;。客户端发送消息则直接发送，比如使用“JOIN #channel”加入某个频道，服务器会向该频道里的每个人广播对JOIN应的消息“@msgid=hftqmpu4ieyjybx9bbgf4vpbia;time=2020-11-13T01:55:32.145Z :@gcjc79gmtbe42.irc JOIN #channel * ”并向操作者推送频道用户列表“@time=2020-11-13T01:55:32.145Z :oragono.test 353 = #channel :@!~&lt;a class="link" href="mailto:u@5g96q93tqw3vn.irc" &gt;u@5g96q93tqw3vn.irc&lt;/a&gt; !~&lt;a class="link" href="mailto:u@5g96q93tqw3vn.irc" &gt;u@5g96q93tqw3vn.irc&lt;/a&gt; !~&lt;a class="link" href="mailto:u@5g96q93tqw3vn.irc" &gt;u@5g96q93tqw3vn.irc&lt;/a&gt;&lt;br&gt;&#10;”。Twitch则在消息的基础上加入了其他格式化控制，比如&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@badge-info&lt;span style="color:#f92672"&gt;=&lt;/span&gt;;badges&lt;span style="color:#f92672"&gt;=&lt;/span&gt;premium/1;client-nonce&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2f70a1efd6f84523d0f180cc44f76c61;color&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#75715e"&gt;#B22222;display-name=Khodeine;emotes=58765:9-19;flags=;id=50d8790f-c474-42a8-b873-2d5e8008bd52;mod=0;room-id=30220059;subscriber=0;tmi-sent-ts=1605279854692;turbo=0;user-id=49980352;user-type= :khodeine!khodeine@khodeine.tmi.twitch.tv PRIVMSG #esl_sc2 :the scvs NotLikeThis&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;会显示以一定的颜色/图标显示用户名/消息。空闲状态下IRC服务端与客户端需要维持心跳信息，比如“PING kiwitime-1605232555315”和“time=2020-11-13T01:57:14.150Z :oragono.test PONG oragono.test kiwitime-1605232555315”，否则连接会被关闭。一些常用的命令，可以看出IRC交互非常简单，&lt;a class="link" href="https://en.wikipedia.org/wiki/IRC_services" target="_blank" rel="noopener"&#10; &gt;IRC核心组件&lt;/a&gt;也不多。使用“@+dratf/typing=active TAGMSG ”显示输入状态，借助&lt;a class="link" href="https://tools.ietf.org/id/draft-oakley-irc-ctcp-01.html" target="_blank" rel="noopener"&#10; &gt;CTCP&lt;/a&gt;协议甚至可以点对点发送文件&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#使用password注册当前nickname&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/NS REGISTER &amp;lt;your password&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#注册一个频道&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/CS REGISTER &lt;span style="color:#75715e"&gt;#channelname&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/CS REGISTER &lt;span style="color:#75715e"&gt;#channe&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#要去某人加入频道&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/INVITE nickname &lt;span style="color:#75715e"&gt;#channel&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#给予某个用户频道管理权限&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/mode +o nickname&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#认证成为管理员&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/OPER admin &amp;lt;admin passowrd&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#在频道发送消息&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/PRIVMSG &lt;span style="color:#75715e"&gt;#channe hello&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#给频道某人发送消息&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/PRIVMSG &lt;span style="color:#75715e"&gt;#channe :&amp;lt;nick&amp;gt; good morning&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#给频道某人发送消息&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/INVITE &amp;lt;nick&amp;gt; &lt;span style="color:#75715e"&gt;#channe&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#使用密码登录&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;AUTHENTICATE PLAIN&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;AUTHENTICATE +&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;AUTHENTICATE a2l3aS1uMzAAa2l3aS1uMzAAMTAyMDMwNDA&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://thelounge.chat/" target="_blank" rel="noopener"&#10; &gt;Thelounge&lt;/a&gt;是另外一个Vue实现的web的IRC客户端，同样支持websocket。它还用express实现了服务端，支持额外的密码/LDAP登录，即先认证通过才能连接IRC服务器，它本身也可以作为一个服务代理网关，为用户提供永远在线服务/消息存储-如果一个IRC用户不在线是不能够给它发送消息的，这一点也跟XMPP不一样。&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/lounge_join.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="480px" data-flex-grow="200" height="150" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/lounge_join-300x150.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/lounge_send.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="431px" data-flex-grow="179" height="167" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/lounge_send-300x167.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;Kiwiirc和Thelounge的设计实现良好，可以作为web chat实现的参考，比如在线客服/销售。比较两个web的IRC客户端发现，他们使用的websocket库并不一样。Kiwiirc使用的是&lt;a class="link" href="https://github.com/sockjs/sockjs-client" target="_blank" rel="noopener"&#10; &gt;sockjs-client&lt;/a&gt;，一个类似websocket的JavaScript网络连接库，支持不同浏览器，能够跨域名通信，在浏览器不支持websocket的情况下退化为&lt;a class="link" href="https://www.pubnub.com/blog/http-long-polling/" target="_blank" rel="noopener"&#10; &gt;polling&lt;/a&gt;（需要&lt;a class="link" href="https://github.com/sockjs/sockjs-node" target="_blank" rel="noopener"&#10; &gt;服务端&lt;/a&gt;配合）。而Thelounge使用的是&lt;a class="link" href="https://github.com/socketio/socket.io" target="_blank" rel="noopener"&#10; &gt;socket.io&lt;/a&gt;。Socket.IO由Engine.IO发展而来，致力于为web提供实时通信能力。Socket.IO并不是WebSocket的一个实现，只是提供了类似的连接能力，需要服务端配合。两个连接库在浏览器支持websocket的情况下都可以直接与websocket服务端通信（不需要对应的库）。Kiwiirc还提供了irc-framework开发库，可以快速搭建一个IRC客户端，比如IRC Bot。至今仍然存在着许多&lt;a class="link" href="https://en.wikipedia.org/wiki/IRC_bot" target="_blank" rel="noopener"&#10; &gt;IRC聊天机器人&lt;/a&gt;，为用户提供方便/服务器报警。Twitch一个用户加入频道时甚至能收到广告！&lt;/p&gt;&#10;&lt;p&gt;Websocket提供了与其他socket一样的能力，能够持续连接和双向通讯，甚至可以服用80/443端口（nginx支持101协议升级）。它不止可以使用在web上，也可以使用在非web上面，因为能够穿透防火墙，对树莓派的远程链接支持。传统的web应用都是一应一答，这节省的服务器/客户端的资源能够不需要持续请求的话。而对于有些应用而言，比如消息通知，希望是能够持续从服务器推送的，websocket增强了它的能力，在这之前都是long polling（所以才有那些包装库）。&lt;br&gt;&#10;Http协议在tcp基础上实现，请求头里面带有host、cookie，url里面带有路径等，这样后端能够识别、路由、分发请求。而tcp并没有这些，websocket必须自己实现类似的路由分发/调用，可以在连接建立初期，鉴别授权（可以在url上面带参数token/jwt/security key），对于后续消息的应答可以在url上面指定，也可以在事件上面指定。这样实现出来似乎与http差不多，仍然有event对应route，但却可以持续交互。&lt;br&gt;&#10;再观察IRC协议也不过是对各个命令的应答，其实也跟经典web MVC差不多-使用URL映射对应的controller/action。IRC每个会话都是一个队列，join #channel命令即订阅消息，part #channel命令则是取消订阅。再看Rabbitmq消息队列，实现了exchange，route，queue，channel，topic等，然后是持续的消费/推送，与前面所诉差不多，这样子看IRC也是个消息服务器。IRC实现简单，通过扩展支持的命令，也能够与内部/外部系统结合，快速搭建一个即时消息平台。&lt;br&gt;&#10;再看邮件服务，其实也是消息服务，也有一对一/群发消息/历史消息，甚至能够给不认识（不在线）的人发送邮件！而邮件服务至今流行，在许多平台，不论服务器还是手机都自带，不需要额外安装软件。&lt;a class="link" href="https://slack.com/intl/en-cn/features" target="_blank" rel="noopener"&#10; &gt;Slack&lt;/a&gt;的产品宣传即对比了自己相对邮件服务的优势。其实手机默认带的电话和短信功能是基于硬件模块的在线功能。&lt;br&gt;&#10;相比Ejabberd/Openfire，IRC服务器的部署简单许多，甚至可以部署在树莓派上！&lt;/p&gt;&#10;&lt;p&gt;参考连接：&lt;br&gt;&#10;&lt;a class="link" href="http://IRC%20bot" target="_blank" rel="noopener"&#10; &gt;IRC Bot&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://developer.ibm.com/zh/technologies/messaging/articles/os-cn-rabbit-mq/" target="_blank" rel="noopener"&#10; &gt;基于 RabbitMQ 的实时消息推送&lt;/a&gt;&lt;/p&gt;&#10;</description></item></channel></rss>