Compare commits
2 Commits
c79c12f694
...
e4de575a61
Author | SHA1 | Date | |
---|---|---|---|
e4de575a61 | |||
fb86d10390 |
222
content/posts/2022/python-irc-bot.md
Normal file
222
content/posts/2022/python-irc-bot.md
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
---
|
||||||
|
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 <username> <hostname> <servername> :<realname>
|
||||||
|
```
|
||||||
|
|
||||||
|
Например:
|
||||||
|
|
||||||
|
```text
|
||||||
|
USER iiiypuk localhost localhost :Alexander
|
||||||
|
```
|
||||||
|
|
||||||
|
### PASS
|
||||||
|
|
||||||
|
Пароль, если необходимо для захода на сервер.
|
||||||
|
|
||||||
|
### NICK
|
||||||
|
|
||||||
|
Команда для смены ника.
|
||||||
|
|
||||||
|
### PONG
|
||||||
|
|
||||||
|
Ответ на команду сервера `PING`.
|
||||||
|
|
||||||
|
### JOIN
|
||||||
|
|
||||||
|
Команда для входа в канал.
|
||||||
|
|
||||||
|
```text
|
||||||
|
JOIN #<chanel_name>
|
||||||
|
```
|
||||||
|
|
||||||
|
### PART
|
||||||
|
|
||||||
|
Команда, чтобы выйти из канала.
|
||||||
|
|
||||||
|
Можно указать причину ухода из канала, добисав второй необязательный аргумет.
|
||||||
|
|
||||||
|
```text
|
||||||
|
PART #support_chanel
|
||||||
|
```
|
||||||
|
|
||||||
|
### PRIVMSG
|
||||||
|
|
||||||
|
Команда, чтобы послать сообщение пользователю или на канал.
|
||||||
|
|
||||||
|
```text
|
||||||
|
PRIVMSG <user_name> :<message>
|
||||||
|
```
|
||||||
|
|
||||||
|
### QUIT
|
||||||
|
|
||||||
|
Команда, чтобы отсоединиться от сервера.
|
||||||
|
|
||||||
|
## Команды сервера
|
||||||
|
|
||||||
|
Помимо команд, которые можно отправить на сервер, клиент также получает команды от сервера.
|
||||||
|
|
||||||
|
### PING
|
||||||
|
|
||||||
|
Сервер время от времени посылает команду PING, на случай, если клиент повиснет.
|
||||||
|
|
||||||
|
Если быстро не ответить на команду пинг командой PONG, сервер разорвёт соединение.
|
||||||
|
|
||||||
|
### :
|
||||||
|
|
||||||
|
```text
|
||||||
|
:<nickname>!<username>@<hostname> <event>
|
||||||
|
```
|
||||||
|
|
||||||
|
`<event>` событие, созданное пользователем `<nickname>`.
|
||||||
|
|
||||||
|
Например `<nickname>` отправил тебе сообщение или выкинул тебя из канала.
|
||||||
|
|
||||||
|
### PRIVMSG
|
||||||
|
|
||||||
|
```text
|
||||||
|
PRIVMSG <receiver> :<message>
|
||||||
|
```
|
||||||
|
|
||||||
|
Новое сообщение, личное или в канал.
|
||||||
|
|
||||||
|
### KICK
|
||||||
|
|
||||||
|
```text
|
||||||
|
KICK <chanel> <nickname>
|
||||||
|
```
|
||||||
|
|
||||||
|
Пользователя `<nickname>` кикнули с канала `<chanel>`.
|
||||||
|
|
||||||
|
## Подключение к серверу
|
||||||
|
|
||||||
|
Определим некоторые переменные
|
||||||
|
|
||||||
|
```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 <module>
|
||||||
|
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)
|
||||||
|
|
||||||
|
## Используемые материалы
|
||||||
|
|
||||||
|
* 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/)
|
96
content/posts/2022/ssh-auth-with-key.md
Normal file
96
content/posts/2022/ssh-auth-with-key.md
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
---
|
||||||
|
title: "🔐 Авторизация SSH по ключам"
|
||||||
|
date: 2022-09-24T10:13:30+03:00
|
||||||
|
draft: false
|
||||||
|
tags: [ssh, tips, privacy]
|
||||||
|
---
|
||||||
|
|
||||||
|
## Шаг первый - создание ключа на локальной машине
|
||||||
|
|
||||||
|
Для генерации ключа на локальной машине необходимо выполнить команду `ssh-keygen`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Generating public/private rsa key pair.
|
||||||
|
Enter file in which to save the key (/home/user/.ssh/id_rsa):
|
||||||
|
```
|
||||||
|
|
||||||
|
В ответ прошрамме необходимо указать путь куда будет сохранён ключ.
|
||||||
|
|
||||||
|
В моём случае имя ключа будет `kvm`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/home/user/.ssh/kvm
|
||||||
|
```
|
||||||
|
|
||||||
|
Далее необходимо дважды ввести пароль для ключа:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Enter passphrase (empty for no passphrase):
|
||||||
|
```
|
||||||
|
|
||||||
|
После этого ключ будет создан,
|
||||||
|
а в директории `~/.ssh` появится два файла: `kvm` и `kvm.pub`.
|
||||||
|
|
||||||
|
```text
|
||||||
|
The key's randomart image is:
|
||||||
|
+---[RSA 3072]----+
|
||||||
|
| .. |
|
||||||
|
+----[SHA256]-----+
|
||||||
|
```
|
||||||
|
|
||||||
|
## Шаг второй - копирование публичного ключа на удалённую машину
|
||||||
|
|
||||||
|
Выполняем команду:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ssh-copy-id -i ~/.ssh/kvm <username>@<remotehost>
|
||||||
|
```
|
||||||
|
|
||||||
|
и вводим пароль от `username`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
username@remotehost's password:
|
||||||
|
```
|
||||||
|
|
||||||
|
Если всё сделано верно, программа вернёт следующий ответ:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Number of key(s) added: 1
|
||||||
|
|
||||||
|
Now try logging into the machine, with: "ssh 'user_name@remote_host'"
|
||||||
|
and check to make sure that only the key(s) you wanted were added.
|
||||||
|
```
|
||||||
|
|
||||||
|
Готово.
|
||||||
|
|
||||||
|
Можно ещё создать файл `~/.ssh/config`, чтобы задать алиасы, а также другие настройки.
|
||||||
|
Например можно указать имя пользователя и путь к ключу.
|
||||||
|
|
||||||
|
```text
|
||||||
|
Host github.com
|
||||||
|
User iiiypuk
|
||||||
|
IdentityFile /home/user/.ssh/github
|
||||||
|
|
||||||
|
Host remote_host
|
||||||
|
User alex
|
||||||
|
HostName 0.0.0.0
|
||||||
|
IdentityFile /home/user/.ssh/kvm
|
||||||
|
ServerAliveInterval 59
|
||||||
|
```
|
||||||
|
|
||||||
|
А после уже можно будет подключаться просто указывая хост.
|
||||||
|
|
||||||
|
```text
|
||||||
|
$ ssh remotehost
|
||||||
|
```
|
||||||
|
|
||||||
|
## Установка ключа вручную
|
||||||
|
|
||||||
|
Добавить ключа на удалённую машину можно ещё одним способом.
|
||||||
|
|
||||||
|
На удаленной машине необходимо добавить содержимое локального файла `kvm.pub`
|
||||||
|
в файл `~/.ssh/authorized_keys` на сервере.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
echo public_key_string >> ~/.ssh/authorized_keys
|
||||||
|
```
|
Loading…
Reference in New Issue
Block a user