class VkHandler(object): _auth_consts = None _vk_session = None _vk_api = None _vk_upload = None _kernel = None _picture_dir = None @logger.class_construct def __init__(self): self._auth_consts = json_handler.auth_constants self._vk_session = VkApi( token=self._auth_consts['api_token'], app_id=self._auth_consts['app_id'], client_secret=self._auth_consts['client_secret']) self._vk_api = self._vk_session.get_api() self._vk_upload = VkUpload(self._vk_session) self._kernel = Kernel() self._picture_dir = os.environ[ 'BISMARCK_HOME'] + os.sep + "pictures" + os.sep def handler(self): longpoll = VkLongPoll(self._vk_session) for event in longpoll.listen(): if event.type == VkEventType.MESSAGE_NEW: logger.debug("New message: '" + str(event.text) + "'") if (event.from_user and not event.from_me) or \ (event.from_chat and event.text.find('id336383265') != -1) or event.from_group: logger.info("New message: '" + str(event.text) + "'") answer = self._kernel.talk(str(event.text), event.from_user) if event.from_user: peer_id = event.user_id elif event.from_chat: peer_id = 2000000000 + event.chat_id else: peer_id = 0 - event.group_id if isinstance(answer, tuple): message, picture = answer picture = self._picture_dir + picture picture_id = self._vk_upload.photo_messages( photos=picture) attachment = "photo{}_{}".format( picture_id[0]['owner_id'], picture_id[0]['id']) self._vk_api.messages.send(peer_id=peer_id, message=message, random_id=randint( 0, 1000000000000000), attachment=attachment) else: self._vk_api.messages.send(peer_id=peer_id, message=answer, random_id=randint( 0, 1000000000000000))
class Vk(VkApiGroup): vk = None def __init__(self, token): super().__init__(token=token) # self.method = VkApiMethod(self) self.upload = VkUpload(self) def get_long_poll(self, token): return self.method(Methods.GET_LP, {'access_token': token}) def send_message(self, message: Message): # @debug m = message.dict() return self.method(Methods.SEND, message.dict()) def upload_message_document(self, filename: str, peer_id): return self.upload.document_message([filename], 'video', peer_id=peer_id) def upload_message_photo(self, filename: str, peer_id): return self.upload.photo_messages([filename], peer_id=peer_id) @staticmethod def str_dict(dictionary): result = '' for i in dictionary: result += str(i) + ',' result = result[:len(result) - 1] return result
def _send_photo_path(vk, id, text, photo_path, delete=True, keyboard=None): upload = VkUpload(vk) uploaded = upload.photo_messages(photo_path) if path.exists(photo_path) and delete: os.remove(photo_path) photo = 'photo' + str(uploaded[0]['owner_id']) + '_' + str(uploaded[0]['id']) send_message({"vk": vk, "id": id, "message": text, "sleep_time": 0, "attachment": photo, "keyboard": keyboard})
def upload_photo(vk, photo): upload = VkUpload(vk) response = upload.photo_messages(photo)[0] owner_id = response['owner_id'] photo_id = response['id'] access_key = response['access_key'] return owner_id, photo_id, access_key
def photo_msg(self, peer_id, path_to_photo, message: str = None, many=False): # TODO переделать совместно с созданием фоток upload = VkUpload(self.__vk_api) resp = upload.photo_messages(peer_id=0, photos=path_to_photo) self.__vk_api.messages.send( user_ids=peer_id, attachment= f"photo{resp[0]['owner_id']}_{resp[0]['id']}_{resp[0]['access_key']}", message=message, random_id=get_random_id())
def picture_send(username1, userid1): file_path = profile_create(username1) upload = VkUpload(vk_session) photo = upload.photo_messages(file_path) owner_id = photo[0]['owner_id'] photo_id = photo[0]['id'] access_key = photo[0]['access_key'] attachment = f'photo{owner_id}_{photo_id}_{access_key}' vk_session.method( 'messages.send', { 'user_id': userid1, 'message': 'бе', 'random_id': 0, 'attachment': attachment })
class Bot: def __init__(self, token: str, group_id: int, testers=None): """ основной класс бота :param token: токен группы со всеми разрешениями :param group_id: id группы к которой привязн токен :param testers: список из id тестеров """ self.group_id = group_id self.testers = testers self.vk_session = vk_api.VkApi(token=token, api_version='5.85', scope='MESSAGE, DOCS, PHOTOS, OFFLINE') self.upload = VkUpload(self.vk_session) # self.vk_session_me self.longpoll = VkBotLongPoll(self.vk_session, self.group_id, wait=25) self.vk = self.vk_session.get_api() self.cmd_keyboard = self.c_keyboard(list(list_cmd.keys())) self.exit_keyboard = self.c_keyboard(list('выйти')) self.first_run = True self.outgoing_mess_queue = Queue() def send(self, user_id, message, **kwargs): self.vk.messages.send(user_id=user_id, message=message, **kwargs) def c_keyboard(self, key_list, one_time=False): """ генерирует клавиатуру (из переданного списка) с 3мя кнопками в одной строке :param key_list: список кнопок, которые хоти видеть :param one_time: True если хотим видеть одноразовый вызов клавиатуры :return: объект VkKeyboard для последующего вызова """ color = VkKeyboardColor.DEFAULT keyboard = VkKeyboard(one_time=one_time) len_key_list = len(key_list) for item in key_list: # TODO цвета как-нибудь бы передать if item == 'выйти': # color = VkKeyboardColor.NEGATIVE keyboard.add_button(item, color=VkKeyboardColor.NEGATIVE, payload='') else: keyboard.add_button(item, color=color, payload='') if (key_list.index(item) + 1) % 3 == 0 and key_list.index(item) != len_key_list - 1: keyboard.add_line() return keyboard def run(self): """ запускает бесконечный цикл в котором слушаем сервер, при получении инфы от сервера запускаем поток с обработчиком :return: """ queue_thread = threading.Thread( target=self.outgoing_mess_queue_handler) queue_thread.start() log.debug('слушаем сервер') for event in self.longpoll.listen(): if event.type == VkBotEventType.MESSAGE_NEW and event.obj.text: # and event.to_me and event.text text = event.obj.text user_id = event.obj.peer_id handler = threading.Thread( target=self.handler_mess, args=(user_id, text)) # event.user_id, event.text handler.start() log.debug('запущен поток для обработки') time.sleep(0.05) def start(self): """ команда для старта бота при старте оповещает тестеров, что бот запустился :return: """ log.debug('старт бота') if self.testers and self.first_run: log.debug('оповещание тестеров') self.first_run = False [ self.send(user_id=t_id, message='йа запустилсо ┐( ˘_˘)┌') for t_id in self.testers ] try: self.run() except Exception as e: log.exception(e) self.start() def outgoing_mess_queue_handler(self): """ обработчик исходящих сообщений в очередь скидываются результаты работы функции handler_mess для ответа юзеру :return: """ while True: try: user_id, mess, attach, key_list = self.outgoing_mess_queue.get( timeout=0.1) except Empty: time.sleep(0.1) continue # чтобы загружать файлы ВК в прикреплёнке не в функции обработчике, а в основном теле # необходимо в аттач складывать dict('тип ВК прикрепления' = [массив ссылок на файлы, ...], ...) if attach: all_attach = list() photo = 'photo' doc = 'doc' if photo in attach.keys(): log.debug(f'{user_id} есть фото в аттаче') for f in attach[photo]: data = self.upload.photo_messages(photos=f, peer_id=user_id)[0] log.debug(f'{user_id} загружено фото: {f}') att = 'photo{}_{}'.format(data['owner_id'], data['id']) all_attach.append(att) if doc in attach.keys(): log.debug(f'{user_id} есть документ в аттаче') for d in attach[doc]: data = self.upload.document_message( d, title=f'doc_{user_id}', peer_id=user_id)[0] log.debug(f'{user_id} загружен документ: {d}') att = 'doc{}_{}'.format(data['owner_id'], data['id']) all_attach.append(att) attach = all_attach # после того как получим нормальный сформированный аттач и текст для ответа # создадим клаву и отправим все это keyboard = self.c_keyboard( key_list) if key_list else self.cmd_keyboard self.send(user_id=user_id, message=mess, keyboard=keyboard.get_keyboard(), attachment=attach) def handler_mess(self, user_id, text): """ обработчик входящих сообщений в папке /command/ лежат файлы с обработчиками комманд my_func переопределяет функцию из list_cmd :param user_id: кто написал сообщение :param text: текст сообщения :return: """ # можно пометить сразу, что прочитали, но тогда при долгом ответе покажется, что мы зависли :) # self.vk.messages.markAsRead(peer_id=user_id) log.debug('запрос к БДшке') bot = psql.get_bot_or_create(user_id, username='', about='', cmd='бот', status=' ') # text = text.lower() if bot.cmd != 'бот': # если текущая команда пользователя != дефолтной, т.е. он находится в какой-то другой # то вызываем тот обработчик, на котором он находится log.debug(f'{user_id} текущее состояние: {bot.cmd}') my_func = list_cmd[bot.cmd] else: # если у пользователя нет текущей команды (т.е. дефолтная), то смотрим какие есть у нас if text in list_cmd.keys(): # если такая есть, то вызываем ее log.debug(f'{user_id} вызвал команда: {text}') my_func = list_cmd[text] else: # если у нас нет такой команды, то намекаем, что надо выбрать из того, что есть (дефолтная клава) log.debug(f'{user_id} вызвал не существующую команду: {text}') self.send(user_id=user_id, message='выбирай', keyboard=self.cmd_keyboard.get_keyboard()) return my_func(user_id, text, bot, self.outgoing_mess_queue) return
message='da' ) if r'kartinochka with luv' in str(event): #for name id_mes = event.message['from_id'] user = vk_session.method("users.get", {'user_ids': id_mes}) name = user[0]['first_name'].lower() id = user[0]['id'] u2 = vk_session.method('users.get', {'user_ids': id_mes,'fields': 'sex'}) sex = u2[0]['sex'] print(u2[0]['sex']) # for photo img, eleven_meme = add_text_on_photo.give_photo(id, name) photo = upload.photo_messages(img) owner_id = photo[0]['owner_id'] photo_id = photo[0]['id'] access_key = photo[0]['access_key'] attachment = f'photo{owner_id}_{photo_id}_{access_key}' #message if sex == 2: vk.messages.send( key=('__'), server="__", ts="31", keyboard=keyboard.get_keyboard(), chat_id=event.chat_id, random_id=get_random_id(), message='https://www.youtube.com/watch?v=SWDTdXH6oF0'