Docs uploading feature, access_token stashing in redis

This commit is contained in:
Kylmakalle 2017-06-23 01:02:13 +03:00
parent eadaa4b387
commit 5be43e8336
2 changed files with 81 additions and 39 deletions

3
.gitignore vendored
View File

@ -140,3 +140,6 @@ $RECYCLE.BIN/
# Bot credentials # Bot credentials
credentials.py credentials.py
# PyCharm project
.idea

111
bot.py
View File

@ -5,49 +5,64 @@ import vk
import threading import threading
import re import re
import logging import logging
import requests
import ujson
import wget
import os
import cherrypy import cherrypy
import redis
from credentials import token, vk_app_id, local_port from credentials import token, vk_app_id, local_port
logging.basicConfig(format='%(levelname)-8s [%(asctime)s] %(message)s', level=logging.WARNING, filename='vk.log') logging.basicConfig(format='%(levelname)-8s [%(asctime)s] %(message)s', level=logging.WARNING, filename='vk.log')
vk_threads = {} vk_threads = {}
vk_tokens = {} FILE_URL = 'https://api.telegram.org/file/bot{0}/{1}'
tokens_pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
vk_tokens = redis.StrictRedis(connection_pool=tokens_pool)
bot = telebot.AsyncTeleBot(token) bot = telebot.AsyncTeleBot(token)
bot.remove_webhook() bot.remove_webhook()
link = 'https://oauth.vk.com/authorize?client_id={}&' \ link = 'https://oauth.vk.com/authorize?client_id={}&' \
'display=page&redirect_uri=https://oauth.vk.com/blank.html&scope=friends,messages,offline' \ 'display=page&redirect_uri=https://oauth.vk.com/blank.html&scope=friends,messages,offline,docs' \
'&response_type=token&v=5.65'.format(vk_app_id) '&response_type=token&v=5.65'.format(vk_app_id)
mark = types.InlineKeyboardMarkup() mark = types.InlineKeyboardMarkup()
yes = types.InlineKeyboardButton('ВХОД', url=link) yes = types.InlineKeyboardButton('ВХОД', url=link)
mark.add(yes) mark.add(yes)
def create_thread(message, vk_token): def create_thread(uid, vk_token):
a = VkPolling() a = VkPolling()
t = threading.Thread(name='vk' + str(message.from_user.id), target=a.run, args=(vk_token, bot, message.chat.id,)) t = threading.Thread(name='vk' + str(uid), target=a.run, args=(VkMessage(vk_token), bot, uid,))
t.setDaemon(True) t.setDaemon(True)
t.start() t.start()
vk_threads[str(message.from_user.id)] = a vk_threads[str(uid)] = a
vk_tokens[str(message.from_user.id)] = vk_token vk_tokens.set(str(uid), vk_token)
def check_thread(message): def check_thread(uid):
for th in threading.enumerate(): for th in threading.enumerate():
if th.getName() == 'vk' + str(message.from_user.id): if th.getName() == 'vk' + str(uid):
return False return False
return True return True
# Creating VkPolling threads after bot reboot using existing tokens
for uid in vk_tokens.scan_iter():
if check_thread(uid.decode("utf-8")):
create_thread(uid.decode("utf-8"), vk_tokens.get(uid))
def stop_thread(message): def stop_thread(message):
for th in threading.enumerate(): for th in threading.enumerate():
if th.getName() == 'vk' + str(message.from_user.id): if th.getName() == 'vk' + str(message.from_user.id):
t = vk_threads[str(message.from_user.id)] t = vk_threads[str(message.from_user.id)]
t.terminate() t.terminate()
th.join() th.join()
vk_tokens.delete(str(message.from_user.id))
def extract_unique_code(text): def extract_unique_code(text):
@ -71,7 +86,7 @@ def info_extractor(info):
@bot.message_handler(commands=['stop']) @bot.message_handler(commands=['stop'])
def stop_command(message): def stop_command(message):
if not check_thread(message): if not check_thread(message.from_user.id):
stop_thread(message) stop_thread(message)
bot.send_message(message.chat.id, 'Успешный выход!').wait() bot.send_message(message.chat.id, 'Успешный выход!').wait()
else: else:
@ -80,7 +95,7 @@ def stop_command(message):
@bot.message_handler(commands=['start']) @bot.message_handler(commands=['start'])
def start_command(message): def start_command(message):
if check_thread(message): if check_thread(message.from_user.id):
bot.send_message(message.chat.id, bot.send_message(message.chat.id,
'Привет, этот бот поможет тебе общаться ВКонтакте, войди по кнопке ниже' 'Привет, этот бот поможет тебе общаться ВКонтакте, войди по кнопке ниже'
' и отправь мне то, что получишь в адресной строке.', ' и отправь мне то, что получишь в адресной строке.',
@ -89,32 +104,54 @@ def start_command(message):
bot.send_message(message.chat.id, 'Вход уже выполнен!\n/stop для выхода.').wait() bot.send_message(message.chat.id, 'Вход уже выполнен!\n/stop для выхода.').wait()
"""def vk_sender(message, method): def vk_sender(message, method):
if message.reply_to_message: if message.reply_to_message:
if str(message.from_user.id) in vk_tokens: if vk_tokens.get(str(message.from_user.id)):
info = info_extractor(message.reply_to_message.entities) info = info_extractor(message.reply_to_message.entities)
if info is not None: if info is not None:
if len(info) - 1: if int(info[1]):
method(message, info[0], False) method(message, info[1], group=True)
vk.API(vk_tokens[str(message.from_user.id)].session).messages.send(chat_id=info[1],
message=message.text)
else: else:
method(message, info[0], True) method(message, info[0], group=False)
vk.API(vk_tokens[str(message.from_user.id)].session).messages.send(user_id=info[0],
message=message.text)
else: else:
bot.send_message(message.chat.id, 'Вход не выполнен! /start дл входа').wait() bot.send_message(message.chat.id, 'Вход не выполнен! /start для входа').wait()
def send_audio(msg, info, private): def send_doc(message, userid, group):
if private: session = VkMessage(vk_tokens.get(str(message.from_user.id))).session
pass file = wget.download(
FILE_URL.format(token, bot.get_file(message.document.file_id).wait().file_path))
openedfile = open(file, 'rb')
files = {'file': openedfile}
fileonserver = ujson.loads(requests.post(vk.API(session).docs.getUploadServer()['upload_url'],
files=files).text)
attachment = vk.API(session).docs.save(file=fileonserver['file'], title=message.document.file_name,
tags='')
if group:
vk.API(session).messages.send(chat_id=userid,
attachment='doc{}_{}'.format(attachment[0]['owner_id'],
attachment[0]['did']))
else: else:
pass vk.API(session).messages.send(user_id=userid,
attachment='doc{}_{}'.format(attachment[0]['owner_id'],
attachment[0]['did']))
openedfile.close()
os.remove(file)
@bot.message_handler(content_types=['audio'])
def reply_audio(message): @bot.message_handler(content_types=['document'])
vk_sender(message, send_audio)""" def reply_document(message):
vk_sender(message, send_doc)
"""if message.reply_to_message:
if vk_tokens.get(str(message.from_user.id)):
info = info_extractor(message.reply_to_message.entities)
if info is not None:
if int(info[1]):
send_doc(message, info[1], True)
else:
send_doc(message, info[0], False)
else:
bot.send_message(message.chat.id, 'Вход не выполнен! /start для входа').wait()"""
@bot.message_handler(content_types=['text']) @bot.message_handler(content_types=['text'])
@ -123,10 +160,10 @@ def reply_text(message):
message.text) message.text)
if m: if m:
code = extract_unique_code(m.group(0)) code = extract_unique_code(m.group(0))
if check_thread(message): if check_thread(message.from_user.id):
try: try:
verifycode(code) verifycode(code)
create_thread(message, VkMessage(code)) create_thread(message.from_user.id, code)
bot.send_message(message.chat.id, 'Вход выполнен!').wait() bot.send_message(message.chat.id, 'Вход выполнен!').wait()
bot.send_message(message.chat.id, 'Бот позволяет получать и отвечать на текстовые сообщения' bot.send_message(message.chat.id, 'Бот позволяет получать и отвечать на текстовые сообщения'
' из ВКонтакте\nПример личного сообщения:').wait() ' из ВКонтакте\nПример личного сообщения:').wait()
@ -147,20 +184,22 @@ def reply_text(message):
return return
if message.reply_to_message: if message.reply_to_message:
if str(message.from_user.id) in vk_tokens: if vk_tokens.get(str(message.from_user.id)):
info = info_extractor(message.reply_to_message.entities) info = info_extractor(message.reply_to_message.entities)
if info is not None: if info is not None:
if len(info) - 1: if int(info[1]):
vk.API(vk_tokens[str(message.from_user.id)].session).messages.send(chat_id=info[1], vk.API(VkMessage(vk_tokens.get(str(message.from_user.id))).session).messages.send(
chat_id=info[1],
message=message.text) message=message.text)
else: else:
vk.API(vk_tokens[str(message.from_user.id)].session).messages.send(user_id=info[0], vk.API(VkMessage(vk_tokens.get(str(message.from_user.id))).session).messages.send(
user_id=info[0],
message=message.text) message=message.text)
else: else:
bot.send_message(message.chat.id, 'Вход не выполнен! /start дл входа').wait() bot.send_message(message.chat.id, 'Вход не выполнен! /start для входа').wait()
#bot.polling() # bot.polling()
class WebhookServer(object): class WebhookServer(object):
# index равнозначно /, т.к. отсутствию части после ip-адреса (грубо говоря) # index равнозначно /, т.к. отсутствию части после ip-адреса (грубо говоря)
@cherrypy.expose @cherrypy.expose