コード例 #1
0
    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()
コード例 #2
0
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)
コード例 #3
0
async def list_users(request):
    page = request.GET.get('page', 0)
    page_size = 50
    total_cnt = User.count()
    num_pages = total_cnt / page_size + 1
    users = [
        x for x in User.find({},
                             skip=page * page_size,
                             limit=page_size,
                             sort=[('last_request_time', -1)])
    ]
    return aiohttp_jinja2.render_template('users.html', request, {
        'users': users,
        'num_pages': num_pages,
    })
コード例 #4
0
 async def on_voice(self, message: Message):
     user = User.get({'id': message.user.id})
     voice = message.voice
     DownloadTask.create(user_id=user.id,
                         file_id=voice.file_id,
                         file_size=voice.file_size,
                         completed=False)
     self.accept_request(user, 'voice', message)
コード例 #5
0
 async def on_document(self, message: Message):
     user = User.get({'id': message.user.id})
     self.accept_request(user, 'document', message)
     document = message.document
     DownloadTask.create(user_id=user.id,
                         file_id=document.file_id,
                         file_size=document.file_size,
                         completed=False)
コード例 #6
0
 async def on_video(self, message: Message):
     user = User.get({'id': message.user.id})
     self.accept_request(user, 'video', message)
     video = message.video
     DownloadTask.create(user_id=user.id,
                         file_id=video.file_id,
                         file_size=video.file_size,
                         completed=False)
コード例 #7
0
 async def on_photo(self, message: Message):
     user = User.get({'id': message.user.id})
     self.accept_request(user, 'photo', message)
     files = sorted(message.photos, key=lambda x: x.file_size, reverse=True)
     DownloadTask.create(user_id=user.id,
                         file_id=files[0].file_id,
                         file_size=files[0].file_size,
                         completed=False)
コード例 #8
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)
コード例 #9
0
 async def on_text(self, message: Message):
     user = User.get({'id': message.user.id})
     text = message.text
     if user.state == 'select_notebook':
         if text.startswith('> ') and text.endswith(' <'):
             text = text[2:-2]
         await self.set_current_notebook(user, text)
     elif user.state == 'switch_mode':
         await self.set_mode(user, text)
     else:
         self.accept_request(user, 'text', message)
コード例 #10
0
def switch_to_one_note_mode(bot, user_id, access_token_future):
    user = User.get({'id': user_id})
    access_token = access_token_future.result()
    user.evernote_access_token = access_token
    user.settings['evernote_access'] = 'full'
    user.mode = 'one_note'
    user.save()
    future = asyncio.ensure_future(
        bot.evernote.create_note(user.evernote_access_token,
                                 'Note for Evernoterobot', '',
                                 user.current_notebook['guid']))
    future.add_done_callback(functools.partial(save_default_note_guid,
                                               user_id))
コード例 #11
0
async def list_users(request):
    page = request.GET.get('page', 0)
    page_size = 50
    total_cnt = User.count()
    now = datetime.datetime.now()
    week_ago = now - datetime.timedelta(days=7)
    month_ago = now - datetime.timedelta(days=30)
    weekly_active = User.count({'last_request_time': {'$gte': week_ago}})
    monthly_active = User.count({'last_request_time': {'$gte': month_ago}})
    num_pages = total_cnt / page_size + 1
    all_users = User.find({}, skip=page*page_size, limit=page_size,
                          sort=[('last_request_time', -1)])
    users = [x for x in all_users]
    return aiohttp_jinja2.render_template(
        'users.html',
        request,
        {
            'users': users,
            'num_pages': num_pages,
            'total': total_cnt,
            'monthly_active': monthly_active,
            'weekly_active': weekly_active,
        }
    )
コード例 #12
0
def user():
    note_guid = generate_string(32)
    notebook_guid = generate_string(32)
    user = User.create(id=random.randint(1, 100),
                       name=generate_string(5),
                       username=generate_string(5),
                       telegram_chat_id=random.randint(1, 100),
                       mode='one_note',
                       evernote_access_token='token',
                       current_notebook={
                           'guid': notebook_guid,
                           'name': 'test_notebook'
                       },
                       places={notebook_guid: note_guid})
    return user
コード例 #13
0
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)
コード例 #14
0
 async def execute(self, message: Message):
     user = User.get({'id': message.user.id})
     buttons = []
     for mode in ['one_note', 'multiple_notes']:
         if user.mode == mode:
             name = "> %s <" % mode.capitalize().replace('_', ' ')
         else:
             name = mode.capitalize().replace('_', ' ')
         buttons.append({'text': name})
     self.bot.send_message(
         user.telegram_chat_id, 'Please, select mode', {
             'keyboard': [[b] for b in buttons],
             'resize_keyboard': True,
             'one_time_keyboard': True,
         })
     user.state = 'switch_mode'
     user.save()
コード例 #15
0
 async def async_run(self):
     try:
         while True:
             updates_by_user = self.fetch_updates()
             if not updates_by_user:
                 await asyncio.sleep(0.1)
                 continue
             for user_id, updates in updates_by_user.items():
                 try:
                     user = User.get({'id': user_id})
                     asyncio.ensure_future(
                         self.process_user_updates(user, updates))
                 except Exception as e:
                     self.logger.error(
                         "Can't process updates for user {0}\n{1}".format(
                             user_id, e),
                         exc_info=1)
     except Exception:
         self.logger.fatal('Dealer DOWN!!!', exc_info=1)
コード例 #16
0
 async def execute(self, message: Message):
     user = User.get({'id': message.user.id})
     notebooks = await self.bot.evernote.list_notebooks(
         user.evernote_access_token)
     buttons = []
     for notebook in notebooks:
         if notebook['guid'] == user.current_notebook['guid']:
             name = '> {} <'.format(notebook['name'])
         else:
             name = notebook['name']
         buttons.append({'text': name})
     self.bot.send_message(
         user.telegram_chat_id, 'Please, select notebook', {
             'keyboard': [[b] for b in buttons],
             'resize_keyboard': True,
             'one_time_keyboard': True,
         })
     user.state = 'select_notebook'
     user.save()
コード例 #17
0
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
コード例 #18
0
 async def on_location(self, message: Message):
     user = User.get({'id': message.user.id})
     await self.handle_request(user, 'location', message)
コード例 #19
0
 async def on_voice(self, message: Message):
     user = User.get({'id': message.user.id})
     await self.handle_request(user, 'voice', message)
コード例 #20
0
 async def on_document(self, message: Message):
     user = User.get({'id': message.user.id})
     await self.handle_request(user, 'document', message)
コード例 #21
0
 async def on_photo(self, message: Message):
     user = User.get({'id': message.user.id})
     await self.handle_request(user, 'photo', message)
コード例 #22
0
 async def on_location(self, message: Message):
     user = User.get({'id': message.user.id})
     self.accept_request(user, 'location', message)
コード例 #23
0
 async def handle_callback_query(self, query: CallbackQuery):
     data = json.loads(query.data)
     if data['cmd'] == 'set_nb':
         user = User.get({'id': query.user.id})
         await self.set_current_notebook(user, notebook_guid=data['nb'])
コード例 #24
0
def save_default_note_guid(user_id, note_guid_future):
    user = User.get({'id': user_id})
    note_guid = note_guid_future.result()
    user.places[user.current_notebook['guid']] = note_guid
    user.save()
コード例 #25
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)
コード例 #26
0
async def test_switch_notebook(user):
    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': '/notebook',
            'entities': [
                {
                    'type': 'bot_command',
                    'offset': 0,
                    'length': 9
                },
            ],
        },
    }

    bot = EvernoteBot('token', 'test_bot')
    Notebook = namedtuple('Notebook', ['guid', 'name'])
    notebooks = [
        Notebook(user.current_notebook['guid'], user.current_notebook['name']),
        Notebook(guid='123', name='test_nb')
    ]
    bot.evernote.api.list_notebooks = AsyncMock(return_value=notebooks)
    bot.evernote.create_note = AsyncMock()
    bot.evernote.get_note_link = AsyncMock()
    bot.api.editMessageText = AsyncMock()
    bot.api.sendMessage = AsyncMock()

    await bot.handle_update(update_data)

    user = User.get({'id': user.id})
    user.mode = 'multiple_notes'
    user.save()
    assert user.state == 'select_notebook'
    await asyncio.sleep(0.1)
    assert bot.api.sendMessage.call_args[0][1] == 'Please, select notebook'
    markup = json.loads(bot.api.sendMessage.call_args[0][2])
    assert markup['one_time_keyboard']
    assert markup['keyboard']
    nb = markup['keyboard'][0][0]
    assert nb['text'] == '> {0} <'.format(user.current_notebook['name'])

    bot.evernote.api.list_notebooks = AsyncMock(return_value=notebooks)
    bot.evernote.create_note.reset_mock()
    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': 'test_nb',
        },
    }
    await bot.handle_update(update_data)
    await asyncio.sleep(0.1)

    user = User.get({'id': user.id})
    assert user.current_notebook['guid'] == '123'
    assert bot.evernote.api.list_notebooks.call_count == 1
    assert bot.api.sendMessage.call_count == 1
    assert bot.api.sendMessage.call_args[0][1].startswith(
        'From now your current notebook is: test_nb'
    )