def test_file_upload_without_login(): with pytest.raises(CapeException): cc = CapeClient(API_URL) fh = open("/tmp/cape_api.txt", "w") fh.write(document_text) fh.close() cc.add_document("Cape API Documentation", file_path="/tmp/cape_api.txt")
def add_paraphrase(message, channel, bot, slack_client): if bot['slack_key'] not in previous_replies or previous_replies[bot['slack_key']] is None: slack_client.api_call("chat.postMessage", channel=channel, text="Please ask a question or create a new saved reply so that I know what to add a paraphrase to.", as_user=True) return try: question = message.split(".add-paraphrase")[1] reply_id = previous_replies[bot['slack_key']] cape_admin_token = bot['cape_admin_token'] admin_client = CapeClient(API_BASE, admin_token=cape_admin_token) admin_client.add_paraphrase_question(reply_id, question) slack_client.api_call("chat.postMessage", channel=channel, text="Thanks, I'll remember that!", as_user=True) except CapeException as e: slack_client.api_call("chat.postMessage", channel=channel, text=e.message, as_user=True)
def explain(channel, bot, slack_client): if bot['slack_key'] not in previous_answers: return previous = previous_answers[bot['slack_key']][last_answer[bot['slack_key']]] if previous['sourceType'] == 'document': slack_client.api_call("chat.postMessage", channel=channel, text="I found that in the document '%s'" % previous['sourceId'], as_user=True) else: try: cape_admin_token = bot['cape_admin_token'] admin_client = CapeClient(API_BASE, admin_token=cape_admin_token) saved_reply = admin_client.get_saved_replies(saved_reply_ids=[previous['sourceId']])['items'][0] slack_client.api_call("chat.postMessage", channel=channel, text="I thought you asked: %s" % saved_reply['canonicalQuestion'], as_user=True) except CapeException as e: slack_client.api_call("chat.postMessage", channel=channel, text=e.message, as_user=True)
def create_demo_user(api_url): log('Creating demo user') client = CapeClient(api_url) new_user_parameters = { 'userId': cape_frontend_settings.DEMO_USER_LOGIN, 'password': cape_frontend_settings.DEMO_USER_PASSWORD, 'token': cape_frontend_settings.DEMO_USER_TOKEN, 'superAdminToken': cape_frontend_settings.BACKEND_SUPER_ADMIN_TOKEN, } url = 'user/create-user?' for k, v in new_user_parameters.items(): url += "%s=%s&" % (k, v) response = client._raw_api_call(url) assert response.status_code == 200, "Could not create demo user" client.login(cape_frontend_settings.DEMO_USER_LOGIN, cape_frontend_settings.DEMO_USER_PASSWORD) log(f'Demo user created with token {cape_frontend_settings.DEMO_USER_TOKEN}' )
def add_saved_reply(message, channel, bot, slack_client): try: message = message.split(".add-saved-reply")[1] question, answer = message.split('|', 1) except Exception as e: slack_client.api_call("chat.postMessage", channel=channel, text="Sorry, I didn't understand that. The usage for .add-saved-reply is: .add-saved-reply question | answer", as_user=True) print("Add saved reply failed: ", e, "Message: ", message) return try: cape_admin_token = bot['cape_admin_token'] admin_client = CapeClient(API_BASE, admin_token=cape_admin_token) reply_id = admin_client.add_saved_reply(question, answer)['replyId'] previous_replies[bot['slack_key']] = reply_id slack_client.api_call("chat.postMessage", channel=channel, text="Thanks, I'll remember that!", as_user=True) except CapeException as e: slack_client.api_call("chat.postMessage", channel=channel, text=e.message, as_user=True)
def wait_for_backend(): if not cape_frontend_settings.WAIT_FOR_BACKENDS: return demo_user_created = not cape_frontend_settings.CREATE_DEMO_ACCOUNT_ON_INIT num_backends = len(cape_frontend_settings.BACKENDS_API_URL) backends_left = set(cape_frontend_settings.BACKENDS_API_URL) while backends_left: log(f"Frontend waiting for backends to initialize {len(backends_left)}/{num_backends}" ) current_url = backends_left.pop() try: reachable = requests.get(current_url[:-4], timeout=1).status_code == 200 except Exception: reachable = False if not reachable: log(f'Could not reach backend {current_url}, retrying ...') backends_left.add(current_url) time.sleep(1) continue if not demo_user_created: create_demo_user(current_url) client = CapeClient(current_url) client.login(cape_frontend_settings.DEMO_USER_LOGIN, cape_frontend_settings.DEMO_USER_PASSWORD) client.answer( question="How many people were present ?", text= "Yesterday at the demonstration, 500 people assisted the event.") log("All backends started")
def test_emails(email_cape_client: CapeClient): # # Testing Bob->Cape Error->Bob # user_token = email_cape_client.get_user_token() question = 'What colour is the sky ?' cape_email = f"{user_token}@{TEST_RECEIVE_EMAIL_DOMAIN}" bob_email = f"bob@{TEST_SEND_EMAIL_DOMAIN}" alice_email = f"alice@{TEST_SEND_EMAIL_DOMAIN}" answer = "The sky is blue." random_key = str(uuid4()) bob_email_content = f"Hello {random_key},\n{question}\nRegards,\nBob" alice_answer = f"Hello {random_key},\n {answer} \nRegards,\nAlice" bob_email_subject = "Test sky colour" # First attempt we get an error for not setting forward email _mailgun_send(email_from=bob_email, email_to=cape_email, email_subject=bob_email_subject, email_text=bob_email_content) time.sleep(MAILGUN_WAIT_PERIOD) sent_body_plain = _mailgun_get_last_email(cape_email)['body-plain'] assert random_key in sent_body_plain assert question in sent_body_plain error_response = _mailgun_get_last_email(bob_email)['body-plain'] assert 'Sorry, this Cape AI account has not yet been configured for email access. \nPlease contact your Cape administrator to set this up.' in error_response assert email_cape_client.get_profile()['forwardEmail'] is None assert email_cape_client.set_forward_email(alice_email) assert email_cape_client.get_profile()['forwardEmail'] == alice_email assert email_cape_client.get_profile()['forwardEmailVerified'] == False time.sleep(MAILGUN_WAIT_PERIOD) verification_token_text = _mailgun_get_last_email(alice_email)['body-plain'] verification_token = verification_token_text.split("verifiedEmailToken=")[1].split("\n")[0] email_cape_client._raw_api_call('user/verify-forward-email', {"verifiedEmailToken":verification_token}) assert email_cape_client.get_profile()['forwardEmailVerified'] == True time.sleep(60) # we wait for the forwardEmailVerified attribute to be propagated across nodes # # Testing Bob->Cape Suggestions->Alice->Cape New Saved Reply->Bob # _mailgun_send(email_from=bob_email, email_to=cape_email, email_subject=bob_email_subject, email_text=bob_email_content) time.sleep(MAILGUN_WAIT_PERIOD) sent_body_plain = _mailgun_get_last_email(cape_email)['body-plain'] reply = _mailgun_get_last_email(alice_email) suggestions: str = reply['body-plain'] assert random_key in sent_body_plain assert question in sent_body_plain assert random_key in suggestions assert """==Cape AI Suggestions==""" in suggestions # mailgun's plain-text version adds line breaks when encountering our <b> tags around the answer suggestions = suggestions.replace("\n", "") assert suggestions.index("sky is blue") < suggestions.index("colour is red") < suggestions.index("like pizzas") # Alice replies with the answer test_sender = reply['Sender'].replace('thecape.ai', TEST_RECEIVE_EMAIL_DOMAIN) _mailgun_send(email_from=alice_email, email_to=test_sender, email_subject="Re: " + bob_email_subject, email_text=alice_answer) time.sleep(MAILGUN_WAIT_PERIOD) alice_response = _mailgun_get_last_email(test_sender)['body-plain'] assert answer in alice_response bob_response = _mailgun_get_last_email(bob_email)['body-plain'] assert answer in bob_response assert random_key in bob_response # # Testing Bob->Cape Saved Reply->Bob # random_key = str(uuid4()) bob_email_content = f"Hello {random_key},\n{question}\nRegards,\nBob" _mailgun_send(email_from=bob_email, email_to=cape_email, email_subject=bob_email_subject, email_text=bob_email_content) time.sleep(MAILGUN_WAIT_PERIOD) sent_body_plain = _mailgun_get_last_email(cape_email)['body-plain'] bob_response = _mailgun_get_last_email(bob_email)['body-plain'] assert answer in bob_response assert random_key in sent_body_plain assert question in sent_body_plain assert random_key in bob_response
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import os import time from bots import bots from slackclient import SlackClient from cape.client import CapeClient, CapeException READ_WEBSOCKET_DELAY = 1 # Delay in seconds between reading from firehose API_BASE='https://responder.thecape.ai/api' cc = CapeClient(API_BASE) previous_answers = {} last_answer = {} previous_replies = {} def handle_question(question, channel, bot, slack_client): cape_token = bot['cape_token'] answers = cc.answer(question, cape_token, number_of_items=5) if len(answers) > 0: print(question, answers[0]['answerText']) previous_answers[bot['slack_key']] = answers last_answer[bot['slack_key']] = 0 if answers[0]['sourceType'] == 'saved_reply': previous_replies[bot['slack_key']] = answers[0]['sourceId'] else:
# -*- coding: utf-8 -*- """ Created on Fri Oct 16 12:41:46 2020 @author: Carl """ from flask import Flask, render_template, jsonify, request from cape.client import CapeClient from settings import USERNAME, PASSWORD app = Flask(__name__) _CAPE_CLIENT = CapeClient() _CAPE_CLIENT.login(USERNAME, PASSWORD) _LAST_DOC_ID = None _ANSWER_TOKEN = _CAPE_CLIENT.get_user_token() @app.route('/') def index(): return render_template('index.html') @app.route('/add_document', methods=['POST']) def add_document(): global _LAST_DOC_ID doc_text = request.form.get('doc', "") _LAST_DOC_ID = _CAPE_CLIENT.upload_document(title='ctrl_f_doc', text=doc_text,
def cc(): client = CapeClient(API_URL) client.login('testuser', 'testpass') yield client client.logout()
def test_login(): cc = CapeClient(API_URL) assert cc.logged_in() == False cc.login('blo', 'bla') assert cc.logged_in() == True
def test_get_token_without_login(): with pytest.raises(CapeException): cc = CapeClient(API_URL) cc.get_user_token()
def test_failed_login(): with pytest.raises(CapeException): cc = CapeClient(UNLUCKY_API_URL) cc.login('invalid', 'invalid')
this parsing function returns None unless a message is directed at the Bot, based on its ID. """ output_list = slack_rtm_output if output_list and len(output_list) > 0: for output in output_list: at_bot = "<@%s>" % BOT_ID if output and 'text' in output and at_bot in output[ 'text'] and 'channel' in output: # return text after the @ mention, whitespace removed return output['text'].split(at_bot)[1].strip(), \ output['channel'] return None, None if __name__ == "__main__": slack_client = SlackClient(SLACK_KEY) cape_client = CapeClient() if slack_client.rtm_connect(): print("Connected") else: print("Failed to connect") sys.exit() while True: message, channel = parse_slack_output(slack_client.rtm_read()) if message and channel: handle_question(message, channel, slack_client, cape_client) time.sleep(READ_WEBSOCKET_DELAY)
def test_text_upload_without_login(): with pytest.raises(CapeException): cc = CapeClient(API_URL) cc.add_document("Cape API Documentation", document_text, origin='cape_api.txt')
return try: # Create a new saved reply cape_client.add_saved_reply(question, answer) slack_client.api_call("chat.postMessage", channel=channel, text="Thanks, I'll remember that!", as_user=True) except CapeException as e: # Inform the user of any errors encountered when adding their saved reply slack_client.api_call("chat.postMessage", channel=channel, text=e.message, as_user=True) if __name__ == "__main__": slack_client = SlackClient(SLACK_KEY) cape_client = CapeClient(admin_token=CAPE_ADMIN_TOKEN) if slack_client.rtm_connect(): print("Connected") else: print("Failed to connect") sys.exit() while True: message, channel = parse_slack_output(slack_client.rtm_read()) if message and channel: if message.lower().startswith(".add-saved-reply"): add_saved_reply(message, channel, slack_client, cape_client) else: handle_question(message, channel, slack_client, cape_client) time.sleep(READ_WEBSOCKET_DELAY)