Exemplo n.º 1
0
    async def callback_processor(self, request):
        try:
            data = await request.json()

            if "type" not in data or "object" not in data:
                raise ValueError("Damaged data received.")

        except (UnicodeDecodeError, ValueError):
            return web.Response(text="ok")

        data_type = data["type"]

        if data_type == "confirmation":
            return web.Response(text=self.settings.CONF_CODE)

        obj = data["object"]

        if "user_id" in obj:
            obj['user_id'] = int(obj['user_id'])

        if data_type == 'message_new':
            await self.process_message(
                Message(self.api, MessageEventData.from_message_body(obj)))

        else:
            await self.process_event(CallbackEvent(self.api, data_type, obj))

        return web.Response(text="ok")
Exemplo n.º 2
0
    async def check_event(self, new_event):
        if not new_event:
            return  # На всякий случай

        event_id = new_event.pop(0)

        if event_id != 4:
            return  # Если событие - не новое сообщение

        msg_id, flags, peer_id, ts, subject, text, attaches = new_event
        # Если ID находится в чёрном списке
        if peer_id in self.BLACKLIST:
            return
        # Получаем параметры сообщения
        # https://vk.com/dev/using_longpoll_2
        flags = parse_msg_flags(flags)
        # Если сообщение - исходящее
        if flags['outbox']:
            return

        # Тип сообщения - конференция или ЛС?
        try:
            # Пробуем получить ID пользователя, который отправил
            # сообщение в беседе
            user_id = attaches['from']
            peer_id -= 2000000000
            conf = True
        except KeyError:
            # Если ключа from нет - это ЛС
            user_id = peer_id
            conf = False
        user_id = int(user_id)

        cleaned_body = text.replace('<br>', '\n')

        data = MessageEventData(conf, peer_id, user_id, cleaned_body, ts, msg_id, attaches)

        user = await get_or_none(User, uid=user_id)
        if user:
            if ts - user.message_date <= self.FLOOD_INTERVAL:
                user.message_date = ts
                await db.update(user)
                return

            user.message_date = ts
            await db.update(user)
        else:
            await db.create(User, uid=user_id)

        await self.check_if_command(data, msg_id)
Exemplo n.º 3
0
    async def process_callback(self, request):
        """Функция для обработки запроса от VK Callback API группы"""
        try:
            data = await request.json()
        except Exception:
            # Почти невозможно, что будет эта ошибка
            return web.Response(text="ok")

        type = data['type']
        if type == 'confirmation':
            # Нам нужно подтвердить наш сервер
            return web.Response(text=self.CONF_CODE)
        obj = data['object']

        if type == 'message_new':
            uid = int(obj['user_id'])

            data = MessageEventData(False, 0, uid, obj['body'], obj['date'],
                                    obj["id"], ["yes"] if
                                    ("attachments" in obj) else [])

            user, create = await db.get_or_create(User, uid=uid)

            await self.check_if_command(data, user)
        if type == 'group_join':
            # Человек присоединился к группе
            uid = int(obj['user_id'])

            user, create = await db.get_or_create(uid=uid)

            user.in_group = True

            await db.update(user)

        if type == 'group_leave':
            # Человек вышел из группы
            uid = int(obj['user_id'])

            user, create = await db.get_or_create(uid=uid)

            user.in_group = False

            await db.update(user)

        return web.Response(text='ok')
Exemplo n.º 4
0
    async def check_event(self, new_event):
        if not new_event:
            return  # На всякий случай
        if not new_event.pop(0) == 4:
            return  # Если событие - не новое сообщение

        msg_id, flags, peer_id, ts, subject, text, attaches = new_event
        # Если ID находится в чёрном списке
        if peer_id in self.BLACKLIST:
            return
        # Получаем параметры сообщения
        # https://vk.com/dev/using_longpoll_2
        flags = parse_msg_flags(flags)
        # Если сообщение - исходящее
        if flags['outbox']:
            return

        # Тип сообщения - конференция или ЛС?
        try:
            # Пробуем получить ID пользователя, который отправил
            # сообщение в беседе
            user_id = attaches['from']
            peer_id -= 2000000000
            conf = True
        except KeyError:
            # Если ключа from нет - это ЛС
            user_id = peer_id
            conf = False

        cleaned_body = text.replace('<br>', '\n')
        data = MessageEventData(conf, peer_id, user_id, cleaned_body, attaches,
                                ts)
        try:
            # Если разница между сообщениями меньше 1 сек - игнорим
            if ts - self.messages_date[user_id] <= 1:
                self.messages_date[user_id] = ts
                return
            else:
                self.messages_date[user_id] = ts
        except KeyError:
            self.messages_date[user_id] = ts
        await self.check_if_command(data, msg_id)
Exemplo n.º 5
0
    async def bots_longpoll_processor(self):
        pack = [{'act': 'a_check', 'key': '', 'ts': 0, 'wait': 25}, ""]

        await self.init_bots_long_polling(pack)

        session = aiohttp.ClientSession(loop=self.loop)
        self.sessions.append(session)

        while True:
            try:
                requ = session.get(pack[1], params=pack[0])
            except aiohttp.ClientOSError:
                await asyncio.sleep(0.5)
                continue

            self.requests.append(requ)

            try:
                events = json.loads(await (await requ).text())

            except aiohttp.ClientOSError:
                try:
                    self.sessions.remove(session)
                except ValueError:
                    pass

                await asyncio.sleep(0.5)

                session = aiohttp.ClientSession(loop=self.loop)
                self.sessions.append(session)
                continue

            except (asyncio.TimeoutError, aiohttp.ServerDisconnectedError):
                self.logger.warning(
                    "Long polling server doesn't respond. Changing server.")
                await asyncio.sleep(0.5)

                await self.init_bots_long_polling(pack)
                continue

            except ValueError:
                await asyncio.sleep(0.5)
                continue

            finally:
                if requ in self.requests:
                    self.requests.remove(requ)

            failed = events.get('failed')

            if failed:
                err_num = int(failed)

                if err_num == 1:  # 1 - update timestamp
                    if 'ts' not in events:
                        await self.init_bots_long_polling(pack)
                    else:
                        pack[0]['ts'] = events['ts']

                elif err_num in (2, 3):  # 2, 3 - new data for long polling
                    await self.init_bots_long_polling(pack, err_num)

                continue

            pack[0]['ts'] = events['ts']

            for event in events['updates']:
                if "type" not in event or "object" not in event:
                    continue

                data_type = event["type"]
                obj = event["object"]

                if "user_id" in obj:
                    obj['user_id'] = int(obj['user_id'])

                if data_type == 'message_new':
                    await self.process_message(
                        Message(self.api,
                                MessageEventData.from_message_body(obj)))

                else:
                    await self.process_event(
                        CallbackEvent(self.api, data_type, obj))
Exemplo n.º 6
0
    async def process_longpoll_event(self, new_event):
        if not new_event:
            return

        event_id = new_event[0]

        if event_id != 4:
            evnt = LongpollEvent(self.api, event_id, new_event)

            return await self.process_event(evnt)

        data = MessageEventData()
        data.msg_id = new_event[1]
        data.attaches = new_event[6]
        data.time = int(new_event[4])

        if 'from' in data.attaches and len(new_event) > 3:
            data.user_id = int(data.attaches.pop('from'))
            data.chat_id = int(new_event[3]) - 2000000000
            data.is_multichat = True

        else:
            data.user_id = int(new_event[3])
            data.is_multichat = False

        # https://vk.com/dev/using_longpoll_2
        flags = parse_msg_flags(new_event[2])

        if flags['outbox']:
            if not self.settings.READ_OUT:
                return

            data.is_out = True

        data.full_text = new_event[5].replace('<br>', '\n')

        if "fwd" in data.attaches:
            data.forwarded = MessageEventData.\
                parse_brief_forwarded_messages_from_lp(data.attaches.pop("fwd"))

        else:
            data.forwarded = []

        msg = Message(self.api, data)

        if await self.check_event(data.user_id, data.chat_id, data.attaches):
            msg.is_event = True

        await self.process_message(msg)