--- title: "IRC бот на Python 3" date: 2022-09-23T22:54:34+03:00 draft: false tags: [python, irc, tutorial] --- ## Введение Это руководство своего рода обобщение уже размешённой в сети информации, по написанию IRC бота. ## Протокол IRC Протокол IRC предназначен для обмена сообщениями в режиме реального времени. IRC использует протокол **TCP** и опционально криптографический **TLS**. В данном руководстве для общения я буду использовать библиотеку `socket` из страндартной библиотеки Python. Общение с сервером осуществаляется посредством отправки команд, вот основные из них: ### `USER` Команда, для приветствия с сервером. ```text USER : ``` Например: ```text USER iiiypuk localhost localhost :Alexander ``` ### PASS Пароль, если необходимо для захода на сервер. ### NICK Команда для смены ника. ### PONG Ответ на команду сервера `PING`. ### JOIN Команда для входа в канал. ```text JOIN # ``` ### PART Команда, чтобы выйти из канала. Можно указать причину ухода из канала, добисав второй необязательный аргумет. ```text PART #support_chanel ``` ### PRIVMSG Команда, чтобы послать сообщение пользователю или на канал. ```text PRIVMSG : ``` ### QUIT Команда, чтобы отсоединиться от сервера. ## Команды сервера Помимо команд, которые можно отправить на сервер, клиент также получает команды от сервера. ### PING Сервер время от времени посылает команду PING, на случай, если клиент повиснет. Если быстро не ответить на команду пинг командой PONG, сервер разорвёт соединение. ### : ```text :!@ ``` `` событие, созданное пользователем ``. Например `` отправил тебе сообщение или выкинул тебя из канала. ### PRIVMSG ```text PRIVMSG : ``` Новое сообщение, личное или в канал. ### KICK ```text KICK ``` Пользователя `` кикнули с канала ``. ## Подключение к серверу Определим некоторые переменные ```python server = 'iiiypuk.me' # адрес сервера channel = '#admin' # имя канала botnick = 'porteus' # ник бота ``` Инициализируем socket и подключимся к серверу. ```python import socket irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) irc.connect((server, 6667)) ``` Для работы с сервером этого не достаточно, но необходимо. Следующий шаг, это "регистрация" бота на сервере. ```python irc.send(str.encode('USER ' + botnick + ' localhost localhost :This is a bot!\n')) irc.send(str.encode('NICK ' + botnick + '\n')) irc.send(str.encode('JOIN '+ channel +'\n')) ``` Обратил внимание на функцию `str.encode`, которая преобразует **UTF-8** строку в набор байтов. Если попытаться передать обычною строку, получим ошибку `TypeError`: ```text Traceback (most recent call last): File "/home/user/Temp/IRCBOT/./bot.py", line 14, in irc.send('USER ' + botnick + ' localhost localhost :This is a bot!\n') TypeError: a bytes-like object is required, not 'str' ``` Можно добавить `b` перед строкой и использовать функцию `bytes()` для преобразования строк в набор байтов, но я лучше воспринимаею код, когда используется метод `encode`. ```python irc.send(b'USER ' + bytes(botnick, encoding = 'utf-8') + b' localhost localhost :This is a bot!\n') ``` И в конечном итоге получаем сообщения от сервера. ```python while True: text = irc.recv(2040) print(text) ``` Ниже представлю полный листинг программы. ```python #!/usr/bin/env python3 import socket server = 'iiiypuk.me' channel = '#admin' botnick = 'porteus' irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print('Connecting to: ' + server) irc.connect((server, 6667)) irc.send(str.encode('USER ' + botnick + ' localhost localhost :This is a bot!\n')) irc.send(str.encode('NICK ' + botnick + '\n')) irc.send(str.encode('JOIN '+ channel +'\n')) while True: text = irc.recv(2040) print(text) if text.find(str.encode('PING')) != -1: irc.send(str.encode('PONG ' + str(text.split()[1]) + '\r\n')) ``` Я в главный цикл программы добавил ответ за команду сервера **PING**. ## Полезные действия Через инстукцию `if` добавим боту полезную функцию. Бот будет возвращать текущее время в формате UNIX. ```python # !time - return current timestamp if text.find(str.encode('!time')) != -1: ts = time.time() irc.send(str.encode('PRIVMSG #admin :{}\r\n'.format(int(ts)))) ``` Код бота можно найти по этой ссылке. [iiiypuk/snipplets.dev:Python/irc-bot.py](https://git.a2s.su/iiiypuk/snipplets.dev/src/branch/master/~/Python/irc-bot.py) ## Потребление памяти На моей конфигурации скрипт потребляет примерно 6,8-7.0Mb. ```text Linux porteus.example.net 5.18.8-porteus #1 SMP PREEMPT_DYNAMIC Sat Jul 2 10:05:31 MSK 2022 x86_64 Intel(R) Core(TM)2 Duo CPU T6570 @ 2.10GHz GenuineIntel GNU/Linux ``` Тот же самый код, но на [Crystal](https://crystal-lang.org/) потребляет 1.7Mb памяти. ## Используемые материалы * Internet Relay Chat Protocol RFC [[Ссылка]](http://web.archive.org/web/20170929015000/http://www2.irchelp.org:80/irchelp/rfc/rfc.html) * How do i program a simple IRC bot in python? [[Ссылка]](https://stackoverflow.com/questions/2968408/how-do-i-program-a-simple-irc-bot-in-python) * Краткое описание протокола IRC и пример бота [[Ссылка]](https://eax.me/irc-descr/) * Простейший IRC-бот на Python, а также при чем тут Slack, Gitter и прочие веб-чаты [[Ссылка]](https://eax.me/python-irc-bot/)