我正在用Python创建一个以Twitch为中心的IRC机器人,但它得到的响应很慢.我做错了什么



正如标题所说,尽管这也是我第一次使用Python真正做大事。我还不太习惯这种语言,所以这可能是我缺少的东西。代码相当短,如下所示,删除了用户名和私人通行证:

import re
import socket
import sys
import time
import string
HOST = "irc.twitch.tv"
PORT = 6667                        
NICK = ""
PASS = ""
CHAN = ""                   
RATE = (20/30) # messages per second
CHAT_MSG=re.compile(r"^:w+!w+@w+.tmi.twitch.tv PRIVMSG #w+ :")
def chat(sock, msg):
    sock.send("PRIVMSG #{} :{}".format(cfg.CHAN, msg))
public = socket.socket()
public.connect((HOST, PORT))
public.send("PASS {}rn".format(PASS).encode("utf-8"))
public.send("NICK {}rn".format(NICK).encode("utf-8"))
public.send("JOIN {}rn".format(CHAN).encode("utf-8"))
private = socket.socket()
private.connect((HOST, PORT))
private.send("PASS {}rn".format(PASS).encode("utf-8"))
private.send("NICK {}rn".format(NICK).encode("utf-8"))
private.send("CAP REQ :twitch.tv/tags twitch.tv/commands  {}rn".format(CHAN).encode("utf-8"))
while True:
    channelResponse = public.recv(1024).decode("utf-8")
    privateResponse = private.recv(1024).decode("utf-8")
    if privateResponse == "PING :tmi.twitch.tvrn":
        private.send("PONG :tmi.twitch.tvrn".encode("utf-8"))
    else:
        privateResponseUsername = re.search(r"w+", privateResponse).group(0) # return the entire match
        privateResponseMessage = CHAT_MSG.sub("", privateResponse)
        print(privateResponseUsername + ": " + privateResponseMessage)
    if channelResponse == "PING :tmi.twitch.tvrn":
        public.send("PONG :tmi.twitch.tvrn".encode("utf-8"))
    else:
        username = re.search(r"w+", channelResponse).group(0) # return the    entire match
        message = CHAT_MSG.sub("", channelResponse)
        print(username + ": " + message)
        time.sleep(1 / RATE)

值得一提的是,我遵循的是一种基本的模板风格,但它没有涵盖在机器人中实现悄悄话——所以我不得不通过研究如何做到这一点来猜测,似乎最推荐的方式是两种连接,一种用于公共,一种为私人。

在构建代码时,只有从public套接字中得到一些东西,才能从private套接字中得到任何东西。如果IRC不偶尔发送PING消息,情况会更糟。

处理此问题的方法是使用select,并为其提供两个套接字。一旦有了可以读取的东西,select就会返回,并指示哪个套接字有字节可供读取。

这个答案有一些通用代码。你可能想修改它,使其看起来像:

while True:
    # this will block until at least one socket is ready
    ready_socks,_,_ = select.select([private, public], [], [])
    if private in ready_socks:
        privateResponse += private.recv()
    if public in ready_socks:
        channelResponse += public.recv()
    # check privateResponse buffer, do stuff
    # check channelResponse buffer, do stuff

还有一些其他的事情你应该记住:

  1. 网络不必同时传递整个IRC消息,也不必一次传递一个消息。你可以得到"PI","NG:t","mi.titch.tv","\r\n"作为单独的消息。因此,您应该在缓冲区中累积字节,然后当您至少有一条完整的消息时,处理它,并将其从缓冲区中删除
  2. UTF-8字符可以跨越多个字节,并且可能会被网络分割。在确定有完整的消息要处理之前,不要解码UTF-8

相关内容

最新更新