Exemple #1
0
async def gmail_pubsub_push(request: web.Request):
    """
        Handle webhooks from gmail (google pub/sub subscribition)
    """
    MAX_SIZE = 26214400
    if request.content_length > MAX_SIZE:
        raise web.HTTPRequestEntityTooLarge(MAX_SIZE, request.content_length)
    request_data = await request.json()
    logging.info(str(request_data))
    if request_data.get('message'):
        notification_data = request_data['message']['data']
        update = json.loads(
            urlsafe_b64decode(notification_data).decode('utf-8'))
        email: str = update["emailAddress"]
        new_history_id: int = int(update["historyId"])
        creds = tuple(await psqldb.get_gmail_creds(email=email))
        user_creds = gmail_API.make_user_creds(*creds)
        history_id = await psqldb.update_watch_history(
            email=email, history_id=new_history_id)
        if history_id:
            # TODO: Catch 404 and make a full sync in that case
            # https://developers.google.com/gmail/api/guides/sync#full_synchronization
            hist = await gmail_API.read_history(user_creds=user_creds,
                                                email=email,
                                                history_id=str(history_id))
            if hist.get("history"):
                creds = tuple(await psqldb.get_gmail_creds(email=email))
                user_creds = gmail_API.make_user_creds(*creds)
                watched_chats_records = tuple(
                    await psqldb.get_watched_chats(email=email))
                for history_record in hist["history"]:
                    for message_record in history_record["messages"]:
                        message_id = message_record["id"]
                        msg = await gmail_API.get_message_full(
                            user_creds=user_creds,
                            message_id=message_id,
                        )
                        # ON new messages -- send it to all the watched chats linked with this email
                        for chat_id_record in watched_chats_records:
                            for text in msg['text_list']:
                                await dp.bot.send_message(
                                    chat_id_record["chat_id"], text)
                            for file in msg['attachments']:
                                await dp.bot.send_document(
                                    chat_id_record["chat_id"],
                                    types.input_file.InputFile(
                                        BytesIO(file['file']),
                                        filename=file['filename']))
        else:
            logging.info(f"Problems with updating history_id in {email}")
    return web.Response(text='OK')
Exemple #2
0
async def update_one_watched_email(email):
    logging.info("Updating last_watch: " + email)
    creds = tuple(await psqldb.get_gmail_creds(email=email))
    user_creds = gmail_API.make_user_creds(*creds)
    watch_response = await gmail_API.start_watch(user_creds=user_creds,
                                                 email=email)
    if watch_response:
        await psqldb.watch_email(email=email,
                                 history_id=int(watch_response["historyId"]))
Exemple #3
0
async def remove(message: types.Message, state: FSMContext):
    email = message.text.strip()
    chat_id = message.chat.id
    if not match(r'^[\w\.-]+@gmail\.com$', email):
        logging.info(f"Mail {email} was rejected")
        await message.answer('Невідомий формат пошти')
    else:
        await psqldb.remove_watched_chat_emails(email=email, chat_id=chat_id)
        await message.answer(f'Сповіщення від пошти {email} відключені')
        watched_chats = tuple(await psqldb.get_watched_chats(email=email))
        if not watched_chats:
            creds = tuple(await psqldb.get_gmail_creds(email=email))
            user_creds = gmail_API.make_user_creds(*creds)
            await gmail_API.stop_watch(user_creds=user_creds, email=email)
            await psqldb.remove_watched_email(email=email)
    await state.finish()
Exemple #4
0
async def add(message: types.Message, state: FSMContext):
    email = message.text.strip()
    chat_id = message.chat.id
    if not match(r'^[\w\.-]+@gmail\.com$', email):
        logging.info(f"Mail {email} was rejected")
        await message.answer('Невідомий формат пошти')
    else:
        # TODO: check if that email is attached to the chat
        match_email_chat = await psqldb.email_in_chat(email=email,
                                                      chat_id=chat_id)
        if not match_email_chat:
            await message.answer(f'Пошта {email} не приєднана до чату')
        else:
            # link email to chat to send emails in the future
            await psqldb.add_watched_chat_emails(email=email, chat_id=chat_id)
            # then only watch email if it not already watched
            is_email_watched = await psqldb.email_watched(email=email)
            # if email already watched -- thats all, just add to the chat, not watch
            if not is_email_watched:
                creds = tuple(await psqldb.get_gmail_creds(email=email))
                user_creds = gmail_API.make_user_creds(*creds)
                watch_response = await gmail_API.start_watch(
                    user_creds=user_creds, email=email)
                # watch response example
                # {'historyId': '1336627', 'expiration': '1612395124174'}
                logging.info(str(watch_response))
                if watch_response:
                    await psqldb.watch_email(email=email,
                                             history_id=int(
                                                 watch_response["historyId"]))
                    await message.answer(
                        f'Сповіщення від пошти {email} додані до чату')
                else:
                    await message.answer(
                        f'Не вдалося додати сповіщення від пошти {email}')
            else:
                await message.answer(
                    f'Сповіщення від пошти {email} прикріплені до чату')
    await state.finish()
Exemple #5
0
async def last_email(message: types.Message):
    """
    Handle command such as `/last [email protected]`
    Send user text and attachment from last email from that email
    """
    # a lot of bugs here
    args = message.get_args()
    # yeah it need at least some verification
    email = args
    creds = tuple(await psqldb.get_gmail_creds(email=email))
    user_creds = gmail_API.make_user_creds(*creds)
    messages = await gmail_API.messages_list(
        user_creds=user_creds,
        messages_num=1,
    )
    messages = [gmail_API.get_text_attachments(msg) for msg in messages]
    for msg in messages:
        for text in msg['text_list']:
            await message.answer(text)
        for file in msg['attachments']:
            await message.answer_document(
                types.input_file.InputFile(BytesIO(file['file']),
                                           filename=file['filename']))
    del messages