Docker ready

This commit is contained in:
Kylmakalle 2018-04-13 15:05:19 +03:00
parent aad32e1947
commit 3926727a28
12 changed files with 224 additions and 28 deletions

5
.gitignore vendored
View File

@ -2,4 +2,7 @@
__pycache__/
data/migrations/*
!data/migrations/__init__.py
config.py
config.py
*.pem
env_file
openssl_config

11
Dockerfile Normal file
View 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

View File

@ -1,11 +1,15 @@
# tgvkbot
Send and recieve VK messages in telegram.
# Установка (Ubuntu 16.04)
```
git clone ...
git clone https://github.com/Kylmakalle/tgvkbot
cd tgvkbot
pip install -r requirements.txt
# Edit config.py file
python manage.py makemigrations data && python manage.py migrate data
python telegram.py
chmod +x install.sh
./install.sh
...
Telegram Token: 123456789:AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLL
VK APP ID: 1234567
```

2
bot.py
View File

@ -14,6 +14,7 @@ from aiogram.dispatcher import Dispatcher
from aiogram.types import ParseMode, MediaGroup, InlineKeyboardMarkup, InlineKeyboardButton, ChatActions
from aiogram.utils.exceptions import *
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.drivers import HttpDriver
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)
dp = Dispatcher(bot)
dp.loop.set_task_factory(context.task_factory)

23
conf.d/web.conf Normal file
View 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/;
}
}

View File

@ -10,23 +10,27 @@ def get_external_host():
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 = 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')
WEBAPP_PORT = os.environ.get('WEBAPP_PORT', 3001)
WEBHOOK_SSL_CERT = './webhook_cert.pem'
DATABASE_USER = os.environ.get('DATABASE_USER', 'postgres')
DATABASE_PASSWORD = os.environ.get('DATABASE_PASSWORD', 'postgres')
DATABASE_HOST = os.environ.get('DATABASE_HOST', 'localhost')
WEBAPP_HOST = os.environ.get('WEBAPP_HOST', '0.0.0.0')
WEBAPP_PORT = os.environ.get('WEBAPP_PORT', 7777)
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_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')

45
docker-compose.yml Normal file
View 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
View 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
View 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
View 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()

View File

@ -860,16 +860,8 @@ async def handle_chat_migration(msg: types.Message):
async def on_startup(app):
webhook = await bot.get_webhook_info()
# 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)
# Set new URL for webhook
await bot.set_webhook(WEBHOOK_URL, certificate=open(WEBHOOK_SSL_CERT, 'rb'))
if __name__ == '__main__':

View File

@ -1,4 +1,4 @@
from concurrent.futures._base import CancelledError
from concurrent.futures._base import CancelledError, TimeoutError
from aiovk.longpoll import LongPoll
@ -869,7 +869,7 @@ async def vk_polling(vkuser: VkUser):
lp = LongPoll(session, mode=10, version=4)
while VkUser.objects.filter(token=vkuser.token, is_polling=True).exists():
data = await lp.wait()
log.debug('Longpoll: ' + str(data))
log.warning('Longpoll: ' + str(data))
if data['updates']:
for update in data['updates']:
await process_longpoll_event(api, update)
@ -882,6 +882,9 @@ async def vk_polling(vkuser: VkUser):
vkuser.is_polling = False
vkuser.save()
break
except TimeoutError:
log.warning('Polling timeout')
asyncio.sleep(5)
except CancelledError:
log.warning('Stopped polling for: id ' + str(vkuser.pk))
break