async def request_full_permissions(self, user):
        chat_id = user.telegram_chat_id
        text = 'To enable "One note" mode you should allow to bot to \
read and update your notes'
        res = self.send_message(chat_id, text, {'hide_keyboard': True})
        await asyncio.wait([res])
        text = 'Please tap on button below to give access to bot.'
        signin_button = {
            'text': 'Waiting for Evernote...',
            'url': self.url,
        }
        inline_keyboard = {'inline_keyboard': [[signin_button]]}
        message_future = self.send_message(chat_id, text, inline_keyboard)
        config_data = config['evernote']['full_access']
        session = StartSession.get({'id': user.id})
        oauth_data = await self.evernote.get_oauth_data(user.id, config_data,
                                                        session.key)
        session.oauth_data = oauth_data
        signin_button['text'] = 'Allow read and update notes to bot'
        signin_button['url'] = oauth_data['oauth_url']
        await asyncio.wait([message_future])
        msg = message_future.result()
        asyncio.ensure_future(
            self.api.editMessageReplyMarkup(
                chat_id,
                msg['message_id'],
                json.dumps(inline_keyboard)
            )
        )
        session.save()
    async def on_message_received(self, message: Message):
        user_id = message.user.id
        if '/start' in message.bot_commands:
            return

        if User.count({'id': user_id}) == 0:
            if StartSession.count({'id': user_id}) > 0:
                message_text = 'Please, sign in to Evernote account first: /start'
                error_text = 'User {0} not authorized in Evernote'.format(user_id)
            else:
                message_text = 'Who are you, stranger? Please, send /start command.'
                error_text = 'Unregistered user {0}'.format(user_id)
            self.send_message(message.chat.id, message_text)
            raise TelegramBotError(error_text)

        user = User.get({'id': user_id})
        if not hasattr(user, 'evernote_access_token') or \
           not user.evernote_access_token:
            self.send_message(
                user.telegram_chat_id,
                'You should authorize first. Please, send /start command.'
            )
            raise TelegramBotError(
                'User {0} not authorized in Evernote'.format(user.id)
            )
        user.last_request_time = datetime.datetime.now()
        user.save()
예제 #3
0
async def oauth_callback_full_access(request):
    logger = request.app.logger
    bot = request.app.bot
    hide_keyboard_markup = json.dumps({'hide_keyboard': True})
    params = parse_qs(request.query_string)
    callback_key = params.get('key', [''])[0]
    session_key = params.get('session_key')[0]

    try:
        session = StartSession.get({'oauth_data.callback_key': callback_key})
        user = User.get({'id': session.id})
    except ModelNotFound as e:
        logger.error(e, exc_info=1)
        return web.HTTPForbidden()

    if session.key != session_key:
        text = "Session is expired. Please, send /start command to create new session"
        asyncio.ensure_future(bot.api.sendMessage(user.telegram_chat_id, text))
        return web.HTTPFound(bot.url)

    try:
        if params.get('oauth_verifier'):
            oauth_verifier = params['oauth_verifier'][0]
            config = settings.EVERNOTE['full_access']
            future = asyncio.ensure_future(
                bot.evernote_api.get_access_token(
                    config['key'], config['secret'],
                    session.oauth_data['oauth_token'],
                    session.oauth_data['oauth_token_secret'], oauth_verifier))
            future.add_done_callback(
                functools.partial(switch_to_one_note_mode, bot, user.id))
            text = 'From now this bot in "One note" mode'
            asyncio.ensure_future(
                bot.api.sendMessage(user.telegram_chat_id, text,
                                    hide_keyboard_markup))
        else:
            # User decline access
            logger.info('User declined full access =(')
            text = "We are sorry, but you deny read/update access😢"
            asyncio.ensure_future(
                bot.api.sendMessage(user.telegram_chat_id, text,
                                    hide_keyboard_markup))

    except TokenRequestDenied as e:
        logger.error(e, exc_info=1)
        text = "We are sorry, but we have some problems with Evernote connection. Please try again later"
        asyncio.ensure_future(
            bot.api.sendMessage(user.telegram_chat_id, text,
                                hide_keyboard_markup))
    except Exception as e:
        logger.fatal(e, exc_info=1)
        text = "Oops. Unknown error. Our best specialist already working to fix it"
        asyncio.ensure_future(
            bot.api.sendMessage(user.telegram_chat_id, text,
                                hide_keyboard_markup))

    return web.HTTPFound(bot.url)
예제 #4
0
    async def execute(self, message: Message):
        chat_id = message.chat.id
        user_id = message.user.id
        self.bot.track(message)
        config = settings.EVERNOTE['basic_access']

        welcome_text = '''Welcome! It's bot for saving your notes to Evernote on fly.
Please tap on button below to link your Evernote account with bot.'''
        signin_button = {
            'text': 'Waiting for Evernote...',
            'url': self.bot.url,
        }
        inline_keyboard = {'inline_keyboard': [[signin_button]]}
        welcome_message_future = asyncio.ensure_future(
            self.bot.api.sendMessage(chat_id, welcome_text,
                                     json.dumps(inline_keyboard)))
        session_key = "".join([
            random.choice(string.ascii_letters + string.digits)
            for i in range(32)
        ])
        oauth_data = await self.bot.evernote_api.get_oauth_data(
            user_id, config['key'], config['secret'], config['oauth_callback'],
            session_key)

        session_data = {
            'user': {
                'username': message.user.username,
                'first_name': message.user.first_name,
                'last_name': message.user.last_name,
            },
            'chat_id': chat_id,
        }
        StartSession.create(id=user_id,
                            key=session_key,
                            data=session_data,
                            oauth_data=oauth_data)

        signin_button['text'] = 'Sign in to Evernote'
        signin_button['url'] = oauth_data["oauth_url"]
        await asyncio.wait([welcome_message_future])
        msg = welcome_message_future.result()
        asyncio.ensure_future(
            self.bot.api.editMessageReplyMarkup(chat_id, msg['message_id'],
                                                json.dumps(inline_keyboard)))
async def oauth_callback(request):
    logger = request.app.logger
    bot = request.app.bot
    config_data = config['evernote']['basic_access']
    params = parse_qs(request.query_string)
    callback_key = params.get('key', [''])[0]
    session_key = params.get('session_key')[0]
    try:
        session = StartSession.get({'oauth_data.callback_key': callback_key})
    except ModelNotFound as e:
        logger.error(e, exc_info=1)
        return web.HTTPForbidden()

    if not params.get('oauth_verifier'):
        logger.info('User declined access. No access token =(')
        bot.send_message(session.data['chat_id'],
                         'We are sorry, but you declined authorization 😢')
        return web.HTTPFound(bot.url)
    if session.key != session_key:
        text = 'Session is expired. \
Please, send /start command to create new session'

        bot.send_message(session.data['chat_id'], text)
        return web.HTTPFound(bot.url)

    user_data = session.data['user']
    name = '{0} {1}'.format(user_data['first_name'], user_data['last_name'])
    user = User(id=session.id,
                name=name,
                username=user_data['username'],
                telegram_chat_id=session.data['chat_id'],
                mode='multiple_notes',
                places={},
                settings={'evernote_access': 'basic'})
    try:
        future = asyncio.ensure_future(
            bot.evernote.get_access_token(config_data, session.oauth_data,
                                          params['oauth_verifier'][0]))
        future.add_done_callback(functools.partial(set_access_token, bot,
                                                   user))
    except TokenRequestDenied as e:
        logger.error(e, exc_info=1)
        text = 'We are sorry, but we have some problems with Evernote \
connection. Please try again later'

        bot.send_message(user.telegram_chat_id, text)
    except Exception as e:
        logger.fatal(e, exc_info=1)
        bot.send_message(user.telegram_chat_id, 'Oops. Unknown error')

    text = 'Evernote account is connected.\n\
From now you can just send message and note be created.'

    bot.send_message(user.telegram_chat_id, text)
    user.save()
    return web.HTTPFound(bot.url)
async def test_start_command(testbot: EvernoteBot, text_update):
    update = text_update
    start_cmd = StartCommand(testbot)
    await start_cmd.execute(update.message)
    await asyncio.sleep(0.0001)
    sessions = StartSession.find()
    assert len(sessions) == 1
    assert sessions[0].id == update.message.user.id
    assert sessions[0].oauth_data['oauth_url'] == 'test_oauth_url'
    assert testbot.api.sendMessage.call_count == 1
    args = testbot.api.sendMessage.call_args[0]
    assert len(args) == 4
    assert 'Welcome' in args[1]
    assert testbot.api.editMessageReplyMarkup.call_count == 1
async def oauth_callback_full_access(request):
    logger = request.app.logger
    bot = request.app.bot
    params = parse_qs(request.query_string)
    callback_key = params.get('key', [''])[0]
    session_key = params.get('session_key')[0]
    try:
        session = StartSession.get({'oauth_data.callback_key': callback_key})
        user = User.get({'id': session.id})
    except ModelNotFound as e:
        logger.error(e, exc_info=1)
        return web.HTTPForbidden()

    if not params.get('oauth_verifier'):
        logger.info('User declined full access =(')
        bot.send_message(user.telegram_chat_id,
                         'We are sorry, but you deny read/update access😢',
                         {'hide_keyboard': True})
        return web.HTTPFound(bot.url)
    if session.key != session_key:
        text = 'Session is expired. Please, send /start command to create \
new session'

        bot.send_message(user.telegram_chat_id, text)
        return web.HTTPFound(bot.url)
    try:
        oauth_verifier = params['oauth_verifier'][0]
        config_data = config['evernote']['full_access']
        future = asyncio.ensure_future(
            bot.evernote.get_access_token(config_data, session.oauth_data,
                                          oauth_verifier))
        future.add_done_callback(
            functools.partial(switch_to_one_note_mode, bot, user.id))
    except TokenRequestDenied as e:
        logger.error(e, exc_info=1)
        bot.send_message(
            user.telegram_chat_id,
            'We are sorry, but we have some problems with Evernote connection.\
 Please try again later', {'hide_keyboard': True})
    except Exception as e:
        logger.fatal(e, exc_info=1)
        bot.send_message(user.telegram_chat_id, 'Oops. Unknown error',
                         {'hide_keyboard': True})
    text = 'From now this bot in "One note" mode'
    bot.send_message(user.telegram_chat_id, text, {'hide_keyboard': True})
    return web.HTTPFound(bot.url)
async def test_start_command(testbot: EvernoteBot, text_update: str):
    update = TelegramUpdate(json.loads(text_update))
    start_cmd = StartCommand(testbot)
    await start_cmd.execute(update.message)
    await asyncio.sleep(0.0001)
    sessions = StartSession.find()
    assert len(sessions) == 1
    assert sessions[0].id == update.message.user.id
    assert sessions[0].oauth_data['oauth_url'] == 'test_oauth_url'
    # TODO:
    # assert new_user.username == 'testuser'
    # assert new_user.first_name == 'test_first'
    # assert new_user.last_name == 'test_last'
    assert testbot.api.sendMessage.call_count == 1
    args = testbot.api.sendMessage.call_args[0]
    assert len(args) == 3
    assert 'Welcome' in args[1]
    assert testbot.api.editMessageReplyMarkup.call_count == 1
async def test_requre_full_permissions(user):
    StartSession.create(id=user.id, key='', data={}, oauth_data={})
    config['evernote']['full_access'] = {}

    update_data = {
        'update_id': 93710840,
        'message': {
            'date': datetime.datetime.now(),
            'from': {
                'username': user.username,
                'id': user.id,
            },
            'chat': {
                'id': user.id,
                'type': 'private',
                'username': user.username,
            },
            'message_id': 164,
            'text': '/switch_mode',
            'entities': [
                {
                    'type': 'bot_command',
                    'offset': 0,
                    'length': 12
                },
            ],
        },
    }

    bot = EvernoteBot('token', 'test_bot')
    bot.api.sendMessage = AsyncMock()

    await bot.handle_update(update_data)
    await asyncio.sleep(0.1)
    user = User.get({'id': user.id})
    user.mode = 'multiple_notes'
    user.save()
    assert user.state == 'switch_mode'
    assert bot.api.sendMessage.call_count == 1
    args = bot.api.sendMessage.call_args[0]
    assert args[1] == 'Please, select mode'

    bot.api.sendMessage.reset_mock()

    update_data = {
        'update_id': 93710840,
        'message': {
            'date': datetime.datetime.now(),
            'from': {
                'username': user.username,
                'id': user.id,
            },
            'chat': {
                'id': user.id,
                'type': 'private',
                'username': user.username,
            },
            'message_id': 164,
            'text': 'One note',
        },
    }

    bot.api.sendMessage = AsyncMock(return_value={'message_id': 123})
    bot.api.editMessageReplyMarkup = AsyncMock()
    bot.evernote.get_oauth_data = AsyncMock(return_value={'oauth_url': 'url'})
    await bot.handle_update(update_data)
    await asyncio.sleep(0.1)

    session = StartSession.get({'id': user.id})
    assert session.oauth_data['oauth_url'] == 'url'
    assert bot.evernote.get_oauth_data.call_count == 1
    assert bot.api.editMessageReplyMarkup.call_count == 1
    assert bot.api.sendMessage.call_count == 2
예제 #10
0
async def oauth_callback(request):
    logger = request.app.logger
    bot = request.app.bot
    config = settings.EVERNOTE['basic_access']

    params = parse_qs(request.query_string)
    callback_key = params.get('key', [''])[0]
    session_key = params.get('session_key')[0]

    try:
        session = StartSession.get({'oauth_data.callback_key': callback_key})
        user_data = session.data['user']
        first_name = user_data['first_name']
        last_name = user_data['last_name']
        username = user_data['username']
        user = User(id=session.id,
                    name="{0} {1}".format(first_name, last_name),
                    username=username,
                    telegram_chat_id=session.data['chat_id'],
                    mode='multiple_notes',
                    places={},
                    settings={'evernote_access': 'basic'})
    except ModelNotFound as e:
        logger.error(e, exc_info=1)
        return web.HTTPForbidden()

    if session.key != session_key:
        text = "Session is expired. Please, send /start command to create new session"
        asyncio.ensure_future(bot.api.sendMessage(user.telegram_chat_id, text))
        return web.HTTPFound(bot.url)

    try:
        if params.get('oauth_verifier'):
            future = asyncio.ensure_future(
                bot.evernote_api.get_access_token(
                    config['key'], config['secret'],
                    session.oauth_data['oauth_token'],
                    session.oauth_data['oauth_token_secret'],
                    params['oauth_verifier'][0]))
            future.add_done_callback(
                functools.partial(set_access_token, bot, user))
            text = 'Evernote account is connected.\nFrom now you can just send message and note be created.'
            asyncio.ensure_future(
                bot.api.sendMessage(user.telegram_chat_id, text))
            user.save()
        else:
            # User decline access
            logger.info('User declined access. No access token =(')
            text = "We are sorry, but you declined authorization 😢"
            asyncio.ensure_future(
                bot.api.sendMessage(user.telegram_chat_id, text))

    except TokenRequestDenied as e:
        logger.error(e, exc_info=1)
        text = "We are sorry, but we have some problems with Evernote connection. Please try again later"
        asyncio.ensure_future(bot.api.sendMessage(user.telegram_chat_id, text))
    except Exception as e:
        logger.fatal(e, exc_info=1)
        text = "Oops. Unknown error. Our best specialist already working to fix it"
        if user:
            asyncio.ensure_future(
                bot.api.sendMessage(user.telegram_chat_id, text))

    return web.HTTPFound(bot.url)
예제 #11
0
    async def set_mode(self, user, mode):
        if mode.startswith('> ') and mode.endswith(' <'):
            mode = mode[2:-2]
        text_mode = '{0}'.format(mode)
        mode = mode.replace(' ', '_').lower()

        if mode == 'one_note':
            if user.settings.get('evernote_access', 'basic') == 'full':
                user.mode = mode
                reply = await self.api.sendMessage(user.telegram_chat_id,
                                                   'Please wait')
                notebook_guid = user.current_notebook['guid']
                note_guid = await self.evernote_api.new_note(
                    user.evernote_access_token,
                    notebook_guid,
                    text='',
                    title='Note for Evernoterobot')
                user.places[user.current_notebook['guid']] = note_guid

                text = 'Bot switched to mode "{0}"'.format(text_mode)
                asyncio.ensure_future(
                    self.api.editMessageText(user.telegram_chat_id,
                                             reply["message_id"], text))
                text = 'New note was created in notebook "{0}"'.format(
                    user.current_notebook['name'])
                asyncio.ensure_future(
                    self.api.sendMessage(user.telegram_chat_id, text,
                                         json.dumps({'hide_keyboard': True})))
            else:
                text = 'To enable "One note" mode you should allow to bot to read and update your notes'
                await self.api.sendMessage(user.telegram_chat_id, text,
                                           json.dumps({'hide_keyboard': True}))
                text = 'Please tap on button below to give access to bot.'
                signin_button = {
                    'text': 'Waiting for Evernote...',
                    'url': self.url,
                }
                inline_keyboard = {'inline_keyboard': [[signin_button]]}
                message_future = asyncio.ensure_future(
                    self.api.sendMessage(user.telegram_chat_id, text,
                                         json.dumps(inline_keyboard)))
                config = settings.EVERNOTE['full_access']
                session = StartSession.get({'id': user.id})
                oauth_data = await self.evernote_api.get_oauth_data(
                    user.id, config['key'], config['secret'],
                    config['oauth_callback'], session.key)
                session.oauth_data = oauth_data
                signin_button['text'] = 'Allow read and update notes to bot'
                signin_button['url'] = oauth_data["oauth_url"]
                await asyncio.wait([message_future])
                msg = message_future.result()
                asyncio.ensure_future(
                    self.api.editMessageReplyMarkup(
                        user.telegram_chat_id, msg['message_id'],
                        json.dumps(inline_keyboard)))
                session.save()
        else:
            user.mode = mode
            asyncio.ensure_future(
                self.api.sendMessage(
                    user.telegram_chat_id,
                    'From now this bot in mode "{0}"'.format(text_mode),
                    reply_markup=json.dumps({'hide_keyboard': True})))

        user.state = None
        user.save()