Example #1
0
 def accept_request(body, num_tries=1) -> bool:
     if body['type'] == 'message':
         uid = body['from']['id']
         chat_id = body['conversation']['id']
         get_redis().set('chat_message_id:{}'.format(chat_id),
                         body['id'])  # TODO
         MicrosoftInterface.set_base_url(chat_id, body['serviceUrl'])
         MicrosoftInterface.set_bot_id(chat_id, body['recipient']['id'])
         accept_user_message.delay(MicrosoftInterface.name,
                                   uid,
                                   body,
                                   chat_id=chat_id)
         return True
     return False
Example #2
0
    def _retrieve_attachment(self, url):
        """Retrieves an attachment ID from FB servers."""
        from botshot.core.persistence import get_redis

        redis = get_redis()
        att_id = redis.get("FB_ATTACHMENT_FOR_{url}".format(url=url))
        return att_id.decode("utf8") if att_id else None
Example #3
0
def get_set_task_flag(task_id):
    """Prevents duplicate scheduled tasks."""
    from botshot.core.persistence import get_redis
    redis = get_redis()
    key = "botshot_task_flag_{}".format(task_id)
    is_done = redis.exists(key)
    # remove the flag 3600 sec. after executing for the first time
    redis.set(name=key, value=1, ex=3600)
    return is_done
Example #4
0
 def _upload_attachment(self, meta, url, type, allow_cache):
     """Uploads an attachment to FB servers."""
     from botshot.core.persistence import get_redis
     att_id = self.interface.upload_attachment(meta, url, type, allow_cache)
     redis = get_redis()
     if att_id is not None and redis is not None:
         expiry = 60 * 60 * 24  # a day
         redis.set("FB_ATTACHMENT_FOR_{url}".format(url=url), att_id, ex=expiry)
     return att_id
Example #5
0
 def get_bot_id(chat_id):
     if chat_id is None:
         raise Exception('Chat id must not be null')
     redis = get_redis()
     bot_id = redis.get('ms_reply_botid_' + str(chat_id))
     if bot_id is None:
         raise Exception('Bot ID not found for chat {}'.format(
             str(chat_id)))
     return bot_id.decode()
Example #6
0
def _run_test_module(name, benchmark=False):

    path = settings.BOT_CONFIG.get("TEST_MODULE", 'tests')

    module = importlib.import_module("." + name, package=path)
    importlib.reload(module)

    result = _run_test_actions(name, module.actions, benchmark=benchmark)
    test = {'name': name, 'result': result}
    db = get_redis()
    db.hset('test_results', name, json.dumps(test))
    return test
Example #7
0
 def accept_request(body):
     uid = body['user']['userId']
     chat_id = body['conversation']['conversationId']
     meta = {"uid": uid, "chat_id": chat_id}
     profile = Profile(uid, None, None)
     session = ChatSession(GoogleActionsInterface, chat_id, meta, profile)
     accept_user_message.delay(session, body).get()
     # responses = GoogleActionsInterface.response_cache.get(session.chat_id)
     responses = get_redis().get(
         "response_for_{id}".format(id=session.chat_id))  # TODO
     return GoogleActionsInterface.convert_responses(
         session, responses.decode('utf8'))
Example #8
0
 def set_bot_id(chat_id, bot_id):
     """
     Because the microsoft bot api doesn't send the requests to recipient "BOT_ID",
     but to recipient "BOT_ID@nnnn" instead and this ID is required to reply,
     it is saved in redis. When MS updates their documentation about IDs this will hopefully be removed.
     :param chat_id:
     :param bot_id:
     :return:
     """
     if chat_id is None or bot_id is None:
         raise Exception('Chat id and bot id must not be null')
     redis = get_redis()
     redis.set('ms_reply_botid_' + str(chat_id), str(bot_id))
Example #9
0
    def _upload_attachment(self, conversation, url, type, allow_cache):
        """Uploads an attachment to FB servers."""
        from botshot.core.persistence import get_redis
        from botshot.core.interfaces.facebook import FacebookInterface

        redis = get_redis()
        att_id = FacebookInterface.upload_attachment(conversation, url, type,
                                                     allow_cache)
        if att_id is not None:
            expiry = 60 * 60 * 24  # a day
            redis.set("FB_ATTACHMENT_FOR_{url}".format(url=url),
                      att_id,
                      ex=expiry)
Example #10
0
 def _persist_callback(cls, payload) -> str:
     """
     Persists payload to be used with Telegram callbacks (which can be max. 64B)
     and returns a string that can be used to retrieve the payload from redis.
     The payload will be persisted for a week.
     :param  payload     Payload to be persisted in Redis.
     :return             Unique string associated with the payload, which can be sent to Telegram.
     """
     redis = get_redis()
     key = ''.join(random.choice(string.hexdigits) for i in range(63))
     while redis.exists(key):
         key = ''.join(random.choice(string.hexdigits) for i in range(63))
     redis.set(key, payload, ex=3600 * 24 * 7)
     return key
Example #11
0
    def post_message(uid, chat_id, response):
        if uid and not chat_id:
            # TODO initiate conversation
            return

        message_id = get_redis().get('chat_message_id:{}'.format(chat_id))
        if message_id:
            message_id = message_id.decode()

        bot_id = MicrosoftInterface.get_bot_id(chat_id)

        payload = {
            "type": "message",
            "from": {
                "id": bot_id
            },
            "conversation": {
                "id": chat_id
            },
            "recipient": {
                "id": uid
            },
            "replyToId": message_id
        }
        payload.update(MicrosoftAdapter(chat_id).to_response(response))

        url = MicrosoftInterface.get_base_url(
            chat_id) + 'conversations/' + chat_id + '/activities'
        if message_id and False:  # replying to message TODO get and clear atomically or set timeout or something
            url += '/' + message_id
        headers = {
            "Authorization": "Bearer " + MicrosoftInterface.get_auth_token(),
            "Content-Type": "application/json"
        }
        logging.warning(url)
        logging.warning(payload)
        response = requests.post(url,
                                 data=json.dumps(payload),
                                 headers=headers)
        if response.status_code != 200:
            logging.warning(str(payload))
            logging.warning(response)
            logging.warning(response.text)
        response.raise_for_status()
Example #12
0
    def get_base_url(chat_id) -> Optional[str]:
        """
        Loads the correct endpoint url for a chat from redis.
        :param chat_id: Id of the chat.
        :return: url, throws Exception if chat_id not valid or url not found
        """
        if not chat_id:
            raise Exception('Chat id must not be null')
        redis = get_redis()
        url = redis.get('ms_service_url_' + str(chat_id))
        if url is None:
            raise Exception('Service url not found for chat id ' +
                            str(chat_id))

        url = url.decode()
        if not url.endswith('/'):
            url += '/'
        url += 'v3/'
        return url
Example #13
0
def test(request):
    # TODO use SQL database
    db = get_redis()
    results = db.hgetall('test_results')
    results = [
        json.loads(results[k].decode('utf-8')) for k in sorted(list(results))
    ] if results else []

    updated_time = db.get('test_time')
    updated_time = db.get('test_time').decode(
        'utf-8') if updated_time else None
    updated_time = datetime.strptime(
        updated_time, "%Y-%m-%d %H:%M:%S.%f") if updated_time else None
    # updated_time = naturaltime(updated_time) if updated_time else None

    status = 'passed'
    avg = {'duration': 0, 'total': 0, 'init': 0, 'parsing': 0, 'processing': 0}
    passed = 0
    for test in results:
        result = test['result']
        if result['status'] == 'passed':
            passed += 1
            avg['duration'] += result['duration']
            avg['total'] += result['report']['avg']['total']
            avg['init'] += result['report']['avg']['init']
            avg['parsing'] += result['report']['avg']['parsing']
            avg['processing'] += result['report']['avg']['processing']
        elif status != 'exception':
            status = result['status']

    if passed > 0:
        for key in avg:
            avg[key] = avg[key] / passed

    context = {
        'tests': results,
        'avg': avg,
        'status': status,
        'updated_time': updated_time
    }
    template = loader.get_template('botshot/test.html')
    return HttpResponse(template.render(context, request))
Example #14
0
 def get_auth_token():
     """
     :returns: Auth token for Microsoft Bot API.
     """
     redis = get_redis()
     if redis.exists('ms_token'):
         return redis.get('ms_token').decode()
     else:
         url = 'https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token'
         headers = {"Content-Type": "application/x-www-form-urlencoded"}
         payload = ('grant_type=client_credentials' + '&client_id=' +
                    settings.BOT_CONFIG.get('MS_BOT_ID') +
                    '&client_secret=' +
                    settings.BOT_CONFIG.get('MS_BOT_TOKEN') + '&scope=' +
                    'https://api.botframework.com/.default')
         response = requests.post(url, data=payload, headers=headers)
         if response.status_code != 200:
             logging.error(response.text)
             response.raise_for_status()
         auth_data = response.json()
         token = auth_data['access_token']
         ex = auth_data['expires_in']
         redis.set('ms_token', str(token), ex=ex)
         return token
Example #15
0
 def post_message(session, response):
     GoogleActionsInterface.messages.append(response)
     get_redis().set("response_for_{id}".format(id=session.chat_id),
                     str(response))  # TODO
Example #16
0
 def set_base_url(chat_id, url):
     if not chat_id or not url:
         raise Exception('Chat id and url must not be null')
     redis = get_redis()
     redis.set('ms_service_url_' + str(chat_id), str(url))
Example #17
0
 def _record(self, type, value):
     action = RecordedAction(type=type, value=value)
     get_redis().rpush(DB_KEY, pickle.dumps(action))
Example #18
0
 def get_actions():
     raw_actions = get_redis().lrange(DB_KEY, 0, -1)
     return [pickle.loads(raw) for raw in raw_actions]
Example #19
0
 def restart():
     get_redis().delete(DB_KEY)
Example #20
0
 def _retrieve_callback(cls, key) -> Optional[str]:
     redis = get_redis()
     if redis.exists(key):
         return redis.get(key).decode('utf8')
     return None