def on_play_scene_json(): # find visitor type visitor_type = get_visitor_type(request.args) visitor_type_id = visitor_type['id'] if visitor_type else None # find target target = get_target(request.args) # find avatar avatars = visitor_type['fields'][ 'avatar'] if visitor_type and 'fields' in visitor_type and 'avatar' in visitor_type[ 'fields'] else [] avatar_id = avatars[0] if avatars else None # execute scene scene = request.get_json() targets = [target] if target else [] now = datetime.utcnow() storyline = str(uuid.uuid4()) errors = execute_scene(now, scene, storyline, { 'individual': 'anyone', 'avatar': avatar_id }, targets) if errors: return json_action_execution_error(errors) else: return json_success("scene played")
def on_trigger_simple_trigger(sensor_name): # find sensor sensor = mongo.db.objects.find_one( { 'type': 'simpletrigger', 'fields.name': sensor_name, 'timestamp-deleted': { '$exists': False } }, {'_id': False}) if not sensor or 'id' not in sensor or 'fields' not in sensor: log.warning(f"sensor {sensor_name} not registered") return json_not_found_error('SENSOR_NOT_REGISTERED', "sensor not registered") sensor_fields = sensor['fields'] # execute effects effect_ids = sensor_fields.get('triggereffects') or [] log.info( f"{len(effect_ids)} effects(s) triggered by simple trigger {sensor_name}" ) errors = execute_effects(datetime.utcnow(), effect_ids, None, None, [], False) if errors: return json_action_execution_error(errors) else: return json_success("sensor triggered successfully")
def on_send_play_story_command(): # find visitor type and target visitor_type = get_visitor_type(request.args) target = get_target(request.args) method = request.args.get('method') # execute story story = request.get_json() errors = execute_story(story, 'anyone', visitor_type, [target] if target else [], method == 'leave') if errors: return json_action_execution_error(errors) else: return json_success( f"story {'stopped' if method == 'leave' else 'started'} successfully" )
def on_shortcut(cbox_name, index): try: index = int(index) except: return json_bad_request_error('INVALID_ARGUMENTS', 'index argument must be numeric') # find cbox by name cbox = find_box(cbox_name) if not cbox or 'fields' not in cbox: return json_not_found_error('CBOX_NOT_FOUND', 'cbox not found') log.debug(f"picked cbox {cbox}") # get body data body = request.get_json() log.info(f"executing shortcut action {index} of {cbox} with {body}") # find shortcut shortcut = cbox.get('fields').get( 'shortcuts')[index] if cbox.get('fields').get('shortcuts') and len( cbox.get('fields').get('shortcuts')) > index else None if not shortcut or 'fields' not in shortcut: return json_not_acceptable_error('INVALID_ITEM', 'invalid shortcut item') log.debug(f"picked shortcut {shortcut}") # execute actions context = body.get('context') if body else {} individual = context.get('individual') if context else None shortcut_fields = shortcut['fields'] actions = shortcut_fields.get('actions') or [] targets = [cbox['id']] errors = schedule_actions(datetime.utcnow(), actions, None, None, {'individual': individual or 'anyone'}, targets) if errors: return json_action_execution_error(errors) else: return json_success("shortcut actions executed")
def on_post_menu_action(menu_id, index): # parse index try: index_list = [int(i) for i in index.split(";")] except: return json_bad_request_error('INVALID_ARGUMENTS', 'arguments must be numeric') # get body data body = request.get_json() log.info(f"executing menu action {index} of {menu_id} with {body}") # find target target = get_target(request.args) if not target: return json_no_command_target_found_error() targets = [target] # find object menu = mongo.db.objects.find_one({'id': menu_id}, {'_id': False}) if not menu or 'fields' not in menu: return json_not_found_error('MENU_NOT_FOUND', 'menu not found') log.debug(f"picked menu {menu}") menu_fields = menu['fields'] # find item item, parent = find_menu_item_and_parent_by_index_list(menu, index_list) if parent and parent.get('type') == 'menuobjectselection': item = parent if not item or 'fields' not in item: return json_not_acceptable_error('INVALID_ITEM', 'invalid menu item') item_fields = item.get('fields') or {} log.debug(f"picked item {item}") # alternative targets defined? # currently not possible and probably a bad idea # if 'target' in menu_fields and menu_fields['target']: # targets = menu_fields['target'] context = body.get('context') or {} if body else {} context['individual'] = context.get('individual') or 'anyone' # find visitor type visitor_type = get_visitor_type(request.args) visitor_type_id = visitor_type['id'] if visitor_type else None # find avatar avatars = visitor_type['fields'][ 'avatar'] if visitor_type and 'fields' in visitor_type and 'avatar' in visitor_type[ 'fields'] else [] avatar_id = avatars[0] if avatars else None context['avatar'] = avatar_id # find subjects if item['type'] == 'menuobjectselection': subject_ids = item_fields.get('items') or [] subject_id = subject_ids[index_list[-1]] context['subjects'] = [ mongo.db.objects.find_one({'id': subject_id}, {'_id': False}) ] # execute actions if item['type'] == 'submenu': header = item_fields.get('header') if header: header_fields = header[0].get('fields') or {} actions = header_fields.get('actions') or [] else: actions = [] else: actions = item_fields.get('actions') or [] additional_actions = menu_fields.get('additionalactions') or [] errors = schedule_actions(datetime.utcnow(), actions + additional_actions, None, None, context, targets) if errors: return json_action_execution_error(errors) else: return json_success("menu actions executed")
def on_answer_interaction(scene_id, index, answer): # validate arguments assert index >= 0 and answer >= 0 # get body data body = request.get_json() log.info(f"got interaction answer {answer} of {scene_id} with {body}") # find target target = get_target(request.args) if not target: return json_no_command_target_found_error() # find scene scene = mongo.db.objects.find_one({'id': scene_id}, {'_id': False}) if not scene or 'fields' not in scene: return json_not_found_error('SCENE_NOT_FOUND', 'scene not found') scene_fields = scene['fields'] if 'actions' not in scene_fields: return json_not_acceptable_error('INVALID_ANSWER', 'invalid answer') log.debug(f"picked scene {scene}") # find action actions = scene_fields['actions'] if not actions or index >= len(actions): return json_not_acceptable_error('INVALID_ANSWER', 'invalid answer') action = actions[index] if not action or 'fields' not in action or 'type' not in action or action[ 'type'] != 'interaction': return json_not_acceptable_error('INVALID_ANSWER', 'invalid answer') log.debug(f"picked action {action}") # find option action_fields = action['fields'] if 'options' not in action_fields: return json_not_acceptable_error('INVALID_ANSWER', 'invalid answer') options = action_fields['options'] if not options or answer >= len(options): return json_not_acceptable_error('INVALID_ANSWER', 'invalid answer') option = options[answer] if not option or 'fields' not in option or 'type' not in option or option[ 'type'] != 'interactioncase': return json_not_acceptable_error('INVALID_ANSWER', 'invalid answer') log.debug(f"picked option {option}") # find visitor type visitor_type = get_visitor_type(request.args) visitor_type_id = visitor_type['id'] if visitor_type else None # find avatar avatars = visitor_type['fields'][ 'avatar'] if visitor_type and 'fields' in visitor_type and 'avatar' in visitor_type[ 'fields'] else [] avatar_id = avatars[0] if avatars else None # execute option context = body.get('context') errors = execute_interaction_option(datetime.utcnow(), option, context, [target]) if errors: return json_action_execution_error(errors) else: return json_success("interaction executed")
def on_trigger_badgesensor(sensor_name, range_index): # find method method = request.args.get('method') signature = request.args.get('signature') # find sensor sensor_info = find_badgesensor_info(sensor_name) if not sensor_info: log.warning(f"sensor {sensor_name} not registered") return json_not_found_error('SENSOR_NOT_REGISTERED', "sensor not registered") if signature and signature != sensor_info.get('signature'): return json_gone_error( 'SENSOR_CONFIGURATION_CHANGED', "sensor configuration has been changed and must be updated") # find beacon range beacon_ranges = sensor_info['ranges'] if range_index >= len(beacon_ranges): log.warning( f"beacon range {range_index} not defined for {sensor_name}") return json_not_found_error('INVALID_BEACON_RANGE', "invalid beacon range") beacon_range = beacon_ranges[range_index] # find individual / visitor type from badge badge = find_badge(request.args) if not badge or 'id' not in badge or 'fields' not in badge: return json_not_found_error('BADGE_NOT_REGISTERED', "badge not registered") badge_fields = badge['fields'] individual = badge['id'] visitor_type_field = badge_fields.get('visitortype') if visitor_type_field: visitor_type_id = visitor_type_field[0] visitor_type = mongo.db.objects.find_one( {'id': visitor_type_id}, {'_id': False}) if visitor_type_id else None else: visitor_type = None # update sensor state now = datetime.utcnow() if method == 'hold': hold_badgesensor_range(sensor_info, range_index, individual, now) return json_success("sensor hold successfully") elif method == 'leave': leave_badgesensor_range(sensor_info, range_index, individual, now) else: enter_badgesensor_range(sensor_info, range_index, individual, now) # find effects sensor_effect_ids = beacon_range.get('effects') or [] badge_effect_ids = badge_fields.get('effects') or [] effect_ids = sensor_effect_ids + badge_effect_ids if not effect_ids: return json_success("sensor triggered without effects") # execute effects log.info( f"{len(effect_ids)} effects(s) on {method} for {individual} of visitor type {visitor_type and visitor_type.get('title')} triggered by badge sensor {sensor_name}" ) errors = execute_effects(now, effect_ids, individual, visitor_type, [], method == 'leave') if errors: return json_action_execution_error(errors) else: return json_success("sensor triggered successfully")