Docker ready
This commit is contained in:
parent
aad32e1947
commit
3926727a28
5
.gitignore
vendored
5
.gitignore
vendored
@ -2,4 +2,7 @@
|
|||||||
__pycache__/
|
__pycache__/
|
||||||
data/migrations/*
|
data/migrations/*
|
||||||
!data/migrations/__init__.py
|
!data/migrations/__init__.py
|
||||||
config.py
|
config.py
|
||||||
|
*.pem
|
||||||
|
env_file
|
||||||
|
openssl_config
|
||||||
|
11
Dockerfile
Normal file
11
Dockerfile
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
FROM python:3.6
|
||||||
|
# MAINTAINER Sergey (@Kylmakalle) <iceman9831@gmail.com>
|
||||||
|
|
||||||
|
ENV PYTHONUNBUFFERED 1
|
||||||
|
RUN mkdir /src
|
||||||
|
WORKDIR /src
|
||||||
|
COPY requirements.txt /src/
|
||||||
|
RUN pip install -r requirements.txt
|
||||||
|
COPY . /src
|
||||||
|
|
||||||
|
|
14
README.md
14
README.md
@ -1,11 +1,15 @@
|
|||||||
# tgvkbot
|
# tgvkbot
|
||||||
Send and recieve VK messages in telegram.
|
Send and recieve VK messages in telegram.
|
||||||
|
|
||||||
|
# Установка (Ubuntu 16.04)
|
||||||
```
|
```
|
||||||
git clone ...
|
git clone https://github.com/Kylmakalle/tgvkbot
|
||||||
cd tgvkbot
|
cd tgvkbot
|
||||||
pip install -r requirements.txt
|
chmod +x install.sh
|
||||||
# Edit config.py file
|
./install.sh
|
||||||
python manage.py makemigrations data && python manage.py migrate data
|
|
||||||
python telegram.py
|
...
|
||||||
|
|
||||||
|
Telegram Token: 123456789:AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLL
|
||||||
|
VK APP ID: 1234567
|
||||||
```
|
```
|
||||||
|
2
bot.py
2
bot.py
@ -14,6 +14,7 @@ from aiogram.dispatcher import Dispatcher
|
|||||||
from aiogram.types import ParseMode, MediaGroup, InlineKeyboardMarkup, InlineKeyboardButton, ChatActions
|
from aiogram.types import ParseMode, MediaGroup, InlineKeyboardMarkup, InlineKeyboardButton, ChatActions
|
||||||
from aiogram.utils.exceptions import *
|
from aiogram.utils.exceptions import *
|
||||||
from aiogram.utils.parts import safe_split_text, split_text, MAX_MESSAGE_LENGTH
|
from aiogram.utils.parts import safe_split_text, split_text, MAX_MESSAGE_LENGTH
|
||||||
|
from aiogram.utils import context
|
||||||
from aiovk import TokenSession, API
|
from aiovk import TokenSession, API
|
||||||
from aiovk.drivers import HttpDriver
|
from aiovk.drivers import HttpDriver
|
||||||
from aiovk.exceptions import *
|
from aiovk.exceptions import *
|
||||||
@ -100,3 +101,4 @@ async def get_content(url, docname='tgvkbot.document', chrome_headers=True, rewr
|
|||||||
|
|
||||||
bot = Bot(token=BOT_TOKEN)
|
bot = Bot(token=BOT_TOKEN)
|
||||||
dp = Dispatcher(bot)
|
dp = Dispatcher(bot)
|
||||||
|
dp.loop.set_task_factory(context.task_factory)
|
||||||
|
23
conf.d/web.conf
Normal file
23
conf.d/web.conf
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
upstream tgbot {
|
||||||
|
ip_hash;
|
||||||
|
server tgbot:7777;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 8443 ssl;
|
||||||
|
ssl_certificate /src/webhook_cert.pem;
|
||||||
|
ssl_certificate_key /src/webhook_pkey.pem;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Host $server_name;
|
||||||
|
|
||||||
|
proxy_pass http://tgbot/;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
24
config.py
24
config.py
@ -10,23 +10,27 @@ def get_external_host():
|
|||||||
HOST = ''
|
HOST = ''
|
||||||
|
|
||||||
WEBHOOK_HOST = os.environ.get('WEBHOOK_HOST', HOST or get_external_host())
|
WEBHOOK_HOST = os.environ.get('WEBHOOK_HOST', HOST or get_external_host())
|
||||||
WEBHOOK_PORT = os.environ.get('WEBHOOK_PORT', 443)
|
WEBHOOK_PORT = os.environ.get('WEBHOOK_PORT', 8443)
|
||||||
WEBHOOK_URL_PATH = os.environ.get('WEBHOOK_URL_PATH', '/tgwebhook')
|
WEBHOOK_URL_PATH = os.environ.get('WEBHOOK_URL_PATH', '/tgwebhook')
|
||||||
|
|
||||||
WEBHOOK_URL = f"https://{WEBHOOK_HOST}:{WEBHOOK_PORT}{WEBHOOK_URL_PATH}"
|
WEBHOOK_URL = "https://{WEBHOOK_HOST}:{WEBHOOK_PORT}{WEBHOOK_URL_PATH}".format(WEBHOOK_HOST=WEBHOOK_HOST,
|
||||||
|
WEBHOOK_PORT=WEBHOOK_PORT,
|
||||||
|
WEBHOOK_URL_PATH=WEBHOOK_URL_PATH)
|
||||||
|
|
||||||
WEBAPP_HOST = os.environ.get('WEBAPP_HOST', 'localhost')
|
WEBHOOK_SSL_CERT = './webhook_cert.pem'
|
||||||
WEBAPP_PORT = os.environ.get('WEBAPP_PORT', 3001)
|
|
||||||
|
|
||||||
DATABASE_USER = os.environ.get('DATABASE_USER', 'postgres')
|
WEBAPP_HOST = os.environ.get('WEBAPP_HOST', '0.0.0.0')
|
||||||
DATABASE_PASSWORD = os.environ.get('DATABASE_PASSWORD', 'postgres')
|
WEBAPP_PORT = os.environ.get('WEBAPP_PORT', 7777)
|
||||||
DATABASE_HOST = os.environ.get('DATABASE_HOST', 'localhost')
|
|
||||||
|
DATABASE_USER = os.environ.get('POSTGRES_USER', 'postgres')
|
||||||
|
DATABASE_PASSWORD = os.environ.get('POSTGRES_PASSWORD', 'postgres')
|
||||||
|
DATABASE_HOST = os.environ.get('DATABASE_HOST', 'db')
|
||||||
DATABASE_PORT = os.environ.get('DATABASE_PORT', '5432')
|
DATABASE_PORT = os.environ.get('DATABASE_PORT', '5432')
|
||||||
DATABASE_NAME = os.environ.get('DATABASE_NAME', 'tgvkbot')
|
DATABASE_NAME = os.environ.get('POSTGRES_DB', 'tgvkbot')
|
||||||
|
|
||||||
VK_APP_ID = os.environ.get('VK_APP_ID', 1234567)
|
VK_APP_ID = os.environ.get('VK_APP_ID')
|
||||||
|
|
||||||
BOT_TOKEN = os.environ.get('BOT_TOKEN', '123456789:AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLL')
|
BOT_TOKEN = os.environ.get('BOT_TOKEN')
|
||||||
|
|
||||||
SETTINGS_VAR = os.environ.get('SETTINGS_VAR', 'DJANGO_TGVKBOT_SETTINGS_MODULE')
|
SETTINGS_VAR = os.environ.get('SETTINGS_VAR', 'DJANGO_TGVKBOT_SETTINGS_MODULE')
|
||||||
|
|
||||||
|
45
docker-compose.yml
Normal file
45
docker-compose.yml
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: "postgres:9.6.5"
|
||||||
|
volumes:
|
||||||
|
- "dbdata:/var/lib/postgresql/data"
|
||||||
|
env_file:
|
||||||
|
- env_file
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- db_nw
|
||||||
|
tgbot:
|
||||||
|
build: .
|
||||||
|
volumes:
|
||||||
|
- .:/src
|
||||||
|
env_file:
|
||||||
|
- env_file
|
||||||
|
command: bash -c "python manage.py makemigrations data && python manage.py migrate data && python telegram.py"
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- db_nw
|
||||||
|
- web_nw
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
nginx:
|
||||||
|
image: "nginx:1.13.5"
|
||||||
|
ports:
|
||||||
|
- "8443:8443"
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- .:/src
|
||||||
|
- ./conf.d:/etc/nginx/conf.d
|
||||||
|
env_file:
|
||||||
|
- env_file
|
||||||
|
networks:
|
||||||
|
- web_nw
|
||||||
|
depends_on:
|
||||||
|
- tgbot
|
||||||
|
networks:
|
||||||
|
db_nw:
|
||||||
|
driver: bridge
|
||||||
|
web_nw:
|
||||||
|
driver: bridge
|
||||||
|
volumes:
|
||||||
|
dbdata:
|
10
install.sh
Executable file
10
install.sh
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
sudo apt-get update && sudo apt-get upgrade && \
|
||||||
|
sudo apt-get install docker.io -y && \
|
||||||
|
sudo usermod -aG docker $(whoami) && \
|
||||||
|
sudo curl -L https://github.com/docker/compose/releases/download/1.20.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose && \
|
||||||
|
sudo chmod +x /usr/local/bin/docker-compose && \
|
||||||
|
python3 set_env.py && \
|
||||||
|
python3 obtaincert.py && \
|
||||||
|
sudo docker-compose build && \
|
||||||
|
sudo docker-compose up -d
|
35
obtaincert.py
Normal file
35
obtaincert.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
from subprocess import call
|
||||||
|
from config import WEBHOOK_HOST
|
||||||
|
|
||||||
|
OPENSSL_CONFIG_TEMPLATE = """
|
||||||
|
prompt = no
|
||||||
|
distinguished_name = req_distinguished_name
|
||||||
|
req_extensions = v3_req
|
||||||
|
[ req_distinguished_name ]
|
||||||
|
C = RU
|
||||||
|
ST = Saint-Petersburg
|
||||||
|
L = Saint-Petersburg
|
||||||
|
O = tgvkbot
|
||||||
|
OU = tgvkbot
|
||||||
|
CN = %(domain)s
|
||||||
|
emailAddress = tgvkbot@gmail.com
|
||||||
|
[ v3_req ]
|
||||||
|
# Extensions to add to a certificate request
|
||||||
|
basicConstraints = CA:FALSE
|
||||||
|
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
subjectAltName = @alt_names
|
||||||
|
[ alt_names ]
|
||||||
|
DNS.1 = %(domain)s
|
||||||
|
DNS.2 = *.%(domain)s
|
||||||
|
"""
|
||||||
|
|
||||||
|
call([
|
||||||
|
'openssl', 'genrsa', '-out', 'webhook_pkey.pem', '2048'
|
||||||
|
])
|
||||||
|
config = open('openssl_config', 'w')
|
||||||
|
config.write(OPENSSL_CONFIG_TEMPLATE % {'domain': WEBHOOK_HOST})
|
||||||
|
config.close()
|
||||||
|
call([
|
||||||
|
'openssl', 'req', '-new', '-x509', '-days', '3650', '-key', 'webhook_pkey.pem', '-out', 'webhook_cert.pem',
|
||||||
|
'-config', 'openssl_config'
|
||||||
|
])
|
64
set_env.py
Normal file
64
set_env.py
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
from config import API_VERSION
|
||||||
|
from urllib.request import urlopen, Request
|
||||||
|
from urllib.error import HTTPError
|
||||||
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
|
ENV_FILE_TEMPLATE = """
|
||||||
|
POSTGRES_DB=tgvkbot
|
||||||
|
BOT_TOKEN=%(tg_token)s
|
||||||
|
VK_APP_ID=%(vk_app_id)s
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def check_token(token):
|
||||||
|
response = urlopen("https://api.telegram.org/bot{token}/{method}".format(token=token, method='getMe'))
|
||||||
|
if response.code == 200:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
raise HTTPError
|
||||||
|
|
||||||
|
|
||||||
|
def get_auth_page(app_id):
|
||||||
|
AUTH_URL = 'https://oauth.vk.com/authorize'
|
||||||
|
params = {'client_id': app_id,
|
||||||
|
'redirect_uri': 'https://oauth.vk.com/blank.html',
|
||||||
|
'display': 'mobile',
|
||||||
|
'response_type': 'token',
|
||||||
|
'v': API_VERSION
|
||||||
|
}
|
||||||
|
post_args = urlencode(params).encode('UTF-8')
|
||||||
|
request = Request(AUTH_URL, post_args)
|
||||||
|
response = urlopen(request)
|
||||||
|
if response.code == 200:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
raise HTTPError
|
||||||
|
|
||||||
|
|
||||||
|
def set_env():
|
||||||
|
while True:
|
||||||
|
tg_token = input('Telegram Token: ')
|
||||||
|
tg_token = tg_token.strip()
|
||||||
|
try:
|
||||||
|
check_token(tg_token)
|
||||||
|
break
|
||||||
|
except HTTPError:
|
||||||
|
print('Token is invalid, try again!')
|
||||||
|
|
||||||
|
while True:
|
||||||
|
vk_app_id = input('VK APP ID: ')
|
||||||
|
vk_app_id = vk_app_id.strip()
|
||||||
|
try:
|
||||||
|
get_auth_page(vk_app_id)
|
||||||
|
break
|
||||||
|
except HTTPError:
|
||||||
|
print('VK APP ID is invalid, try again!')
|
||||||
|
|
||||||
|
with open('env_file', 'w') as env_file:
|
||||||
|
env_file.write(ENV_FILE_TEMPLATE % {'tg_token': tg_token, 'vk_app_id': vk_app_id})
|
||||||
|
|
||||||
|
print('Success!')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
set_env()
|
12
telegram.py
12
telegram.py
@ -860,16 +860,8 @@ async def handle_chat_migration(msg: types.Message):
|
|||||||
|
|
||||||
|
|
||||||
async def on_startup(app):
|
async def on_startup(app):
|
||||||
webhook = await bot.get_webhook_info()
|
# Set new URL for webhook
|
||||||
|
await bot.set_webhook(WEBHOOK_URL, certificate=open(WEBHOOK_SSL_CERT, 'rb'))
|
||||||
# If URL is bad
|
|
||||||
if webhook.url != WEBHOOK_URL:
|
|
||||||
# If URL doesnt match current - remove webhook
|
|
||||||
if not webhook.url:
|
|
||||||
await bot.delete_webhook()
|
|
||||||
|
|
||||||
# Set new URL for webhook
|
|
||||||
await bot.set_webhook(WEBHOOK_URL)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from concurrent.futures._base import CancelledError
|
from concurrent.futures._base import CancelledError, TimeoutError
|
||||||
|
|
||||||
from aiovk.longpoll import LongPoll
|
from aiovk.longpoll import LongPoll
|
||||||
|
|
||||||
@ -869,7 +869,7 @@ async def vk_polling(vkuser: VkUser):
|
|||||||
lp = LongPoll(session, mode=10, version=4)
|
lp = LongPoll(session, mode=10, version=4)
|
||||||
while VkUser.objects.filter(token=vkuser.token, is_polling=True).exists():
|
while VkUser.objects.filter(token=vkuser.token, is_polling=True).exists():
|
||||||
data = await lp.wait()
|
data = await lp.wait()
|
||||||
log.debug('Longpoll: ' + str(data))
|
log.warning('Longpoll: ' + str(data))
|
||||||
if data['updates']:
|
if data['updates']:
|
||||||
for update in data['updates']:
|
for update in data['updates']:
|
||||||
await process_longpoll_event(api, update)
|
await process_longpoll_event(api, update)
|
||||||
@ -882,6 +882,9 @@ async def vk_polling(vkuser: VkUser):
|
|||||||
vkuser.is_polling = False
|
vkuser.is_polling = False
|
||||||
vkuser.save()
|
vkuser.save()
|
||||||
break
|
break
|
||||||
|
except TimeoutError:
|
||||||
|
log.warning('Polling timeout')
|
||||||
|
asyncio.sleep(5)
|
||||||
except CancelledError:
|
except CancelledError:
|
||||||
log.warning('Stopped polling for: id ' + str(vkuser.pk))
|
log.warning('Stopped polling for: id ' + str(vkuser.pk))
|
||||||
break
|
break
|
||||||
|
Loading…
x
Reference in New Issue
Block a user