def send(self, to_addr): conversation_key = self.conversation_key message_url = 'http://go.vumi.org/api/v1/go/http_api/' + conversation_key + '/messages.json' payload = { "to_addr": to_addr, "content": self.content, } if not app.debug: r = requests.put(message_url, auth=(ACCOUNT_KEY, ACCESS_TOKEN), data=json.dumps(payload)) logger.debug(message_url) logger.debug("Status Code: " + str(r.status_code)) try: tmp = json.loads(r.text) logger.debug(json.dumps(tmp, indent=4)) except Exception: logger.debug(r.text) pass if not r.status_code == 200: logger.error("HTTP error encountered while trying to send message through VumiGo API.") return r.text else: logger.debug("MESSAGE SENT \n" + json.dumps(payload, indent=4)) return
def on_model_change(self, form, model, is_created): # send SMS notifications before saving message to database msg = VumiMessage({"content": model.content}) count_tot = 0 model.user = current_user try: with app.open_instance_resource('notification_list.json', mode='r') as f: try: notification_list = json.loads(f.read()) except ValueError: # start with clean list, if the file does not yet contain a list notification_list = [] pass for number in notification_list: logger.debug("sending update to: " + number) msg.send(number) count_tot += 1 model.notes = "Update sent to " + str(count_tot) + " user(s)." except Exception: tmp = "Error sending update broadcast via SMS." logger.exception(tmp) model.notes = tmp return
def event(): """ """ logger.debug("EVENT endpoint called") tmp = request.get_json() logger.debug(json.dumps(tmp, indent=4)) return make_response("OK")
def message(): """ Handle incoming USSD messages, passed as HTTP requests via the vumi HTTP API. """ logger.debug("MESSAGE endpoint called") # TODO: filter out service messages, such as "content": "state: wait_ussrc" if request.method == 'POST': tmp = request.get_json() msg = VumiMessage(tmp) if msg.content == "state: wait_ussrc": logger.debug("End of session message received.") else: logger.debug(msg) try: user_id = msg.from_addr # user's cellphone number content = msg.content # selected menu item, if any mark_online(user_id) selected_item = None try: selected_item = int(content) except (ValueError, TypeError): pass reply_content = generate_output(user_id, selected_item) if app.debug: logger.debug(reply_content) else: msg.reply(reply_content) except Exception as e: logger.exception(e) pass return make_response("OK")
def send_reply(self, content, session_event="resume", user=None): conversation_key = self.conversation_key message_url = 'http://go.vumi.org/api/v1/go/http_api/' + conversation_key + '/messages.json' payload = { "in_reply_to": self.message_id, "content": content, "session_event": session_event, } # log response to db if this is a reply to an SMS query if hasattr(self, 'query_id'): rsp = Response() rsp.query_id = self.query_id rsp.content = content if user: rsp.user = user db.session.add(rsp) db.session.commit() if not app.debug: r = requests.put(message_url, auth=(ACCOUNT_KEY, ACCESS_TOKEN), data=json.dumps(payload)) logger.debug("Response Status Code: " + str(r.status_code)) try: tmp = json.loads(r.text) logger.debug(json.dumps(tmp, indent=4)) except Exception: logger.debug(r.text) pass if not r.status_code == 200: logger.error("HTTP error encountered while trying to send message through VumiGo API.") return r.text else: logger.debug("REPLY \n" + json.dumps(payload, indent=4)) return
def toggle_star(): """ Star / unstar a query. """ logger.debug("TOGGLE STAR endpoint called") query_id = request.form['query_id'] # toggle starred value qry = Query.query.get(query_id) qry.starred = not qry.starred db.session.add(qry) db.session.commit() return redirect('/admin/queryview/', code=302)
def update_status(): """ Update a query status. """ logger.debug("UPDATE STATUS endpoint called") query_id = request.form['query_id'] status = request.form['status'] # toggle starred value qry = Query.query.get(query_id) qry.status = status db.session.add(qry) db.session.commit() return redirect('/admin/queryview/', code=302)
def note(): """ Save a note related to a query. """ logger.debug("NOTE endpoint called") user = current_user content = request.form['content'] query_id = request.form['query_id'] # save note tmp = Note() tmp.user = user tmp.content = content tmp.query_id = query_id db.session.add(tmp) db.session.commit() return redirect('/admin/queryview/', code=302)
def response(): """ Send SMS response to an SMS query. """ logger.debug("RESPONSE endpoint called") user = current_user content = request.form['content'] query_id = request.form['query_id'] # send reply msg = VumiMessage({'query_id': query_id}) msg.send_reply(content, session_event=None, user=user) # update query status qry = Query.query.get(query_id) qry.status = "in_progress" db.session.add(qry) db.session.commit() return redirect('/admin/queryview/', code=302)
def message(): """ Handle incoming messages, passed as HTTP requests via the vumi HTTP API. """ logger.debug("MESSAGE endpoint called") try: tmp = request.get_json() msg = VumiMessage(tmp) if hasattr(msg, 'content') and msg.content == "state: wait_ussrc": logger.debug("End of session message received.") else: logger.debug(msg.msg_type + " message received.") if msg.msg_type == "ussd": user_id = msg.from_addr # user's cellphone number content = msg.content # selected menu item, if any mark_online(user_id) selected_item = None try: selected_item = int(content) except (ValueError, TypeError): pass logger.debug(selected_item) reply_content = generate_output(user_id, selected_item) if "Your number has been added to the list." in reply_content: update_notification_list(msg.from_addr, "add") msg.send_reply(reply_content) elif msg.msg_type == "sms": msg.save_query() tmp = "Thank you for submitting your query. It will be attended to as soon as possible." msg.send_reply(tmp) else: logger.error("Incorrect message type encountered.") except Exception as e: logger.exception(e) raise return make_response("OK")
def generate_output(user_id, selected_item=None): """ Find the relevant menu to display, based on user input and saved session info. """ # retrieve user's session, if available previous_menu = get_user_menu(user_id) logger.debug("PREVIOUS MENU: " + str(previous_menu)) # handle 'back' links if previous_menu and selected_item == 0: if len(previous_menu) == 1: previous_menu = None else: previous_menu = previous_menu[0:-1] selected_item = None sub_menu = menu selected_endpoint = None try: # select user's previous menu if previous_menu: try: for i in previous_menu: sub_menu = sub_menu['content'][int(i)] except Exception: logger.error("Could not retrieve previous menu: " + str(previous_menu)) previous_menu = None pass # select the given option if selected_item: index = selected_item - 1 try: if type(sub_menu['content'][index]) == dict: sub_menu = sub_menu['content'][index] if previous_menu: previous_menu += str(index) else: previous_menu = str(index) else: selected_endpoint = index except TypeError: # This is not a new menu, but an endpoint logger.debug("endpoint") pass except IndexError: # The selected option is not available logger.debug("out of bounds") pass except Exception: previous_menu = None pass # save user's menu to the session mark_menu(user_id, previous_menu) # return the menu's string representation str_out = serialize_options(sub_menu, selected_endpoint) # track user activity in mixpanel heading = str_out.split('\n')[0] if not heading: heading = "unknown" mp.people_set(user_id, { '$first_name': user_id, 'last_seen' : str(datetime.datetime.utcnow()), 'previous_menu': heading, }) mp.track(user_id, heading) return str_out
def generate_output(user_id, selected_item=None): """ Find the relevant menu to display, based on user input and saved session info. """ # retrieve user's session, if available previous_menu = get_user_menu(user_id) logger.debug("PREVIOUS MENU: " + str(previous_menu)) # handle 'back' links if previous_menu and selected_item == 0: if len(previous_menu) == 1: previous_menu = None else: previous_menu = previous_menu[0:-1] selected_item = None sub_menu = menu selected_endpoint = None try: # select user's previous menu if previous_menu: try: for i in previous_menu: sub_menu = sub_menu['content'][int(i)] except Exception: logger.error("Could not retrieve previous menu: " + str(previous_menu)) previous_menu = None pass # select the given option if selected_item: index = selected_item - 1 try: if type(sub_menu['content'][index]) == dict: sub_menu = sub_menu['content'][index] if previous_menu: previous_menu += str(index) else: previous_menu = str(index) else: selected_endpoint = index except TypeError: # This is not a new menu, but an endpoint logger.debug("endpoint") pass except IndexError: # The selected option is not available logger.debug("out of bounds") pass except Exception: previous_menu = None pass # save user's menu to the session mark_menu(user_id, previous_menu) # return the menu's string representation str_out = serialize_options(sub_menu, selected_endpoint) return str_out