我如何在 python 中编写一个简单的 IRC 机器人?

Posted

技术标签:

【中文标题】我如何在 python 中编写一个简单的 IRC 机器人?【英文标题】:How do i program a simple IRC bot in python? 【发布时间】:2011-02-27 10:41:29 【问题描述】:

我需要帮助编写一个仅连接到频道的基本 IRC 机器人。有人能解释一下吗?我已经设法让它连接到 IRC 服务器,但我无法加入频道并登录。到目前为止我的代码是:

import sockethost = 'irc.freenode.org'
port = 6667
join_sock = socket.socket()
join_sock.connect((host, port))
<code here> 

任何帮助将不胜感激。

【问题讨论】:

为什么要重新发明***?已经有很多 IRC 机器人是用 Python 编写的。 @jamessan 学习,当然:) @eric 我喜欢这个回复:D 【参考方案1】:

要连接到 IRC 频道,您必须先向 IRC 服务器发送某些特定于 IRC 协议的命令。

当您连接到服务器时,您必须等到服务器发送完所有数据(MOTD 等),然后您必须发送 PASS 命令。

PASS <some_secret_password>

接下来是 NICK 命令。

NICK <username>

那么你必须发送 USER 命令。

USER <username> <hostname> <servername> :<realname>

两者都是强制性的。

那么你很可能会看到来自服务器的 PING 消息,每次服务器向你发送 PING 消息时,你必须用 PONG 命令回复服务器。服务器也可能会在 NICK 和 USER 命令之间请求 PONG。

PING :12345678

使用 PONG 命令在“PING”后回复完全相同的文本:

PONG :12345678

PING 之后的内容对于每台服务器来说都是独一无二的,因此请务必回复服务器发送给您的值。

现在您可以使用 JOIN 命令加入频道:

JOIN <#channel>

现在您可以使用 PRIVMSG 命令向频道和用户发送消息:

PRIVMSG <#channel>|<nick> :<message>

退出

QUIT :<optional_quit_msg>

Telnet 实验!开始

telnet irc.example.com 6667

有关更多命令和选项,请参阅IRC RFC。

希望这会有所帮助!

【讨论】:

谢谢,这太棒了!特别是关于 telnet 的提示.. 甚至没有想到 :) 谢谢.. 我可能还有一些问题.. 让我试试 telnet 的东西然后我会回来的! 这是我的会话: NOTICE AUTH :*** 处理与 irc.mzima.net 的连接 NOTICE AUTH :*** 正在查找您的主机名... NOTICE AUTH :*** 检查 Ident NOTICE AUTH :*** 找到你的主机名 NOTICE AUTH :*** No Ident response NICK PYIRC\r\n USER PYIRC PYIRC PYIRC :Python\r\n JOIN #pytest\r\n :irc.mzima.net 451 * :你有未注册 好像是注册了。。我怎么注册?或者你知道一个不需要的 IRC 服务器吗?我迷路了…… 我认为您不能像那样同时发送命令。尝试单独发送它们,因为服务器可能会在命令之间向您发送一些东西,因此您会收到注册通知,这实际上是指连接注册。显然,您还必须在 NICK/USER 之前发送一个 PASS 命令,我以前从未使用过该命令,所以试试吧,我更新了我的帖子。 我明白了。我很抱歉草率的会话粘贴。我一次发送一个.. 例如:NICK Test\r\n USER ....\r\n 等等。我想知道如何找到密码.. 嘿@Jake,如果这个答案对你有那么大的帮助,为什么不选择他的答案是正确的呢?【参考方案2】:

这是MichaelvdNet's Post的扩展,它支持一些额外的东西:

对套接字使用 SSL 包装器 使用服务器密码验证 使用 nickserv 密码验证 使用非阻塞套接字,以允许触发其他事件

将文本文件的更改记录到频道

#!/usr/local/bin/python

import socket
import ssl
import time

## Settings
### IRC
server = "chat.freenode.net"
port = 6697
channel = "#meLon"
botnick = "meLon-Test"
password = "YOURPASSWORD"

### Tail
tail_files = [
    '/tmp/file-to-tail.txt'
]

irc_C = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #defines the socket
irc = ssl.wrap_socket(irc_C)

print "Establishing connection to [%s]" % (server)
# Connect
irc.connect((server, port))
irc.setblocking(False)
irc.send("PASS %s\n" % (password))
irc.send("USER "+ botnick +" "+ botnick +" "+ botnick +" :meLon-Test\n")
irc.send("NICK "+ botnick +"\n")
irc.send("PRIVMSG nickserv :identify %s %s\r\n" % (botnick, password))
irc.send("JOIN "+ channel +"\n")


tail_line = []
for i, tail in enumerate(tail_files):
    tail_line.append('')


while True:
    time.sleep(2)

    # Tail Files
    for i, tail in enumerate(tail_files):
        try:
            f = open(tail, 'r')
            line = f.readlines()[-1]
            f.close()
            if tail_line[i] != line:
                tail_line[i] = line
                irc.send("PRIVMSG %s :%s" % (channel, line))
        except Exception as e:
            print "Error with file %s" % (tail)
            print e

    try:
        text=irc.recv(2040)
        print text

        # Prevent Timeout
        if text.find('PING') != -1:
            irc.send('PONG ' + text.split() [1] + '\r\n')
    except Exception:
        continue

【讨论】:

【参考方案3】:

我用这个作为 MAIN IRC 代码:

import socket
import sys

server = "server"       #settings
channel = "#channel"
botnick = "botname"

irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #defines the socket
print "connecting to:"+server
irc.connect((server, 6667))                                                         #connects to the server
irc.send("USER "+ botnick +" "+ botnick +" "+ botnick +" :This is a fun bot!\n") #user authentication
irc.send("NICK "+ botnick +"\n")                            #sets nick
irc.send("PRIVMSG nickserv :iNOOPE\r\n")    #auth
irc.send("JOIN "+ channel +"\n")        #join the chan

while 1:    #puts it in a loop
   text=irc.recv(2040)  #receive the text
   print text   #print text to console

   if text.find('PING') != -1:                          #check if 'PING' is found
      irc.send('PONG ' + text.split() [1] + '\r\n') #returnes 'PONG' back to the server (prevents pinging out!)

然后,您可以开始设置命令,例如:!hi &lt;nick&gt;

if text.find(':!hi') !=-1: #you can change !hi to whatever you want
    t = text.split(':!hi') #you can change t and to :)
    to = t[1].strip() #this code is for getting the first word after !hi
    irc.send('PRIVMSG '+channel+' :Hello '+str(to)+'! \r\n')

请注意,所有irc.send 文本必须以PRIVMSGNOTICE + channel/user 开头,并且文本应以: 开头!

【讨论】:

这很好,但我只能在 irc.recv(2040) 返回时触发 while 循环。 你可以在 irc.connect() 之后设置 irc.setblocking(False),但一定要在你的 while 循环中添加 time.sleep(),除非你想用你的处理器来温暖你的家.【参考方案4】:

这将打开一个套接字,但你还需要告诉 IRCd 你是谁。我很久以前在 perl 中做过类似的事情,我发现 IRC RFC 非常有帮助。

主要 RFC:http://irchelp.org/irchelp/rfc/rfc.html

其他 RFC:http://irchelp.org/irchelp/rfc/index.html

【讨论】:

【参考方案5】:

将它基于twisted 的IRC 协议实现可能是最简单的。看看:http://github.com/brosner/bosnobot 以获得灵感。

【讨论】:

以上是关于我如何在 python 中编写一个简单的 IRC 机器人?的主要内容,如果未能解决你的问题,请参考以下文章

python irc客户端没有识别响应

Twisted Python IRC bot - 如何异步执行函数以便它不会阻塞机器人?

Twisted Python IRC Bot - 如何在 bot 运行命令时监听命令?

Python twisted irc - 登录时的服务器密码

如何使用 Irssi 将彩色文本写入 irc 频道?

在 Python 中使用 Twitch IRC 时“由对等方重置连接”