2016-05-08 2 views
1

タイトルによれば、これは初めてのことですが、私はPythonを使って実際に大きなことをしています。私はまだその言語に慣れていないので、これはおそらく私の欠けているものです。コードは、ユーザー名と削除プライベートパスで、かなり短く、以下のようにある:言及する私は、Pythonでツィッチに焦点を当てたIRCボットを作成していますが、応答が遅いです。私は間違って何をしていますか?

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+!\[email protected]\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 {}\r\n".format(PASS).encode("utf-8")) 
public.send("NICK {}\r\n".format(NICK).encode("utf-8")) 
public.send("JOIN {}\r\n".format(CHAN).encode("utf-8")) 

private = socket.socket() 
private.connect((HOST, PORT)) 
private.send("PASS {}\r\n".format(PASS).encode("utf-8")) 
private.send("NICK {}\r\n".format(NICK).encode("utf-8")) 
private.send("CAP REQ :twitch.tv/tags twitch.tv/commands {}\r\n".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.tv\r\n": 
     private.send("PONG :tmi.twitch.tv\r\n".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.tv\r\n": 
     public.send("PONG :tmi.twitch.tv\r\n".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) 

ことの一つは、私は基本的なテンプレートのスタイルを以下ました、しかし、それはボットにささやきを実装カバーしていないということです - ので、私はそれを行う方法を研究することで推測する必要があります。最も推奨される方法は、公開用と非公開用の2つの接続です。

答えて

1

コードを構造化したので、publicソケットから何かを得るまで、privateソケットから何も取得できません。 IRCが時折メッセージPINGを送信しなかった場合、これはさらに悪化します。

これを処理する方法は、selectを使用し、2つのソケットを付けることです。読み取ることができるものがあるとすぐに、selectが返され、読み込み可能なバイトを持つソケットが示されます。

This answerにはいくつかの一般的なコードがあります。あなたは、のようなものを見て、それを修正する場合があります

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のメッセージを配信する必要はありません。また、一度に1つずつ配信する必要もありません。 「PI」、「NG:t」、「mi.twitch.tv」、「\ r \ n」を別々のメッセージとして受け取ることができます。したがって、バッファにバイトを蓄積し、少なくとも1つのメッセージ全体を処理して処理し、バッファから削除する必要があります。
  2. UTF-8文字は複数バイトにまたがる可能性があり、ネットワークによって分割される可能性があります。 UTF-8を解読しないでください。完全なメッセージが得られるまでは解読しないでください。
+0

私はこの部分をセットアップしましたが、私はPythonのパブリック/プライベートチャネル応答の配列をチェックする方法がよくわかりません。そうする最善の方法は何ですか? – Merlin

+0

アレイ?文字列である 'privateResponse'と' channelResponse'バッファを意味しますか?あなたにはたくさんのオプションがあります。ほとんどは、IRCのメッセージが改行によって簡単に終わるという事実を中心にしています。バッファに改行がない場合、完全なメッセージはありません。最も簡単なことは、おそらく改行があるかどうかを確認することです。もしあれば、それまでのすべてをメッセージとして処理し、改行の後にすべてをバッファで置き換えます。 –

+0

それはそうしました。最初の一時停止がありますが、両方の接続が適切に動作し、応答が即座に得られます。 – Merlin

関連する問題