def on_update_alive(sid): if 'type' not in request.args: return json_bad_request_error("ARGUMENT_MISSING", "device type missing") device_type = request.args['type'] if device_type not in ['box', 'sensor', 'mobile']: return json_bad_request_error("INVALID_ARGUMENT", "invalid device type") if 'name' not in request.args: return json_bad_request_error("ARGUMENT_MISSING", "device name missing") device_name = request.args['name'] now = datetime.utcnow().timestamp() if sid not in socketio_sessions: socketio_sessions[sid] = {'sid': sid, 'connect_time': now, 'env': {}} socketio_sessions[sid]['type'] = device_type socketio_sessions[sid]['name'] = device_name socketio_sessions[sid]['connected'] = True socketio_sessions[sid]['alive_time'] = now socketio_sessions[sid]['env']['REMOTE_ADDR'] = request.args.get( 'ip', default='-') info = request.args.get('info') activity_description = info + " " + str( datetime.utcnow()) if info else request.args.get('activity') if activity_description: socketio_sessions[sid]['activity'] = activity_description return json_success("alive state updated")
def on_show_menu(slot): # find target target = get_target(request.args) if not target: return json_bad_request_error('TARGET_MISSING', "target missing") # get parameters if 'visible' not in request.args: return json_bad_request_error('ARGUMENT_MISSING', 'no visibility argument specified') visibleParam = str(request.args.get('visible')).lower() if visibleParam in ['true', '1', 'yes']: visible = True elif visibleParam in ['false', '0', 'no']: visible = False else: return json_bad_request_error('INVALID_ARGUMENT', 'visibility argument invalid') # send command socketio.emit('showmenu', { 'time': datetime.utcnow().timestamp(), 'slot': slot, 'visible': visible }, room=target) return json_success("menu shown")
def on_post_upload_media(): # check if the post request has the file part if 'file' not in request.files: return json_bad_request_error('NO_FILE_SELECTED', 'no file selected') uploaded_file = request.files['file'] # if user does not select a file, the browser also submits an empty part without filename if uploaded_file.filename == '': return json_bad_request_error('FILE_NAME_MISSING', 'file name missing') basename, extension = os.path.splitext(uploaded_file.filename) if not extension: return json_bad_request_error( 'FILE_EXTENSION_NOT_SUPPORTED', 'file extension not supported: ' + uploaded_file.filename) extension = extension[1:].lower() if extension not in ALLOWED_EXTENSIONS: return json_bad_request_error( 'FILE_EXTENSION_NOT_SUPPORTED', 'file extension not supported: ' + uploaded_file.filename) # save file file_name = save_file(uploaded_file) # process file and pass URLs and meta info response = process_media_file(file_name, extension) return jsonify(response), 200
def on_post_change_menu(slot): # find target target = get_target(request.args) if not target: return json_bad_request_error('TARGET_MISSING', "target missing") # send command menu = request.get_json() socketio.emit('changemenu', { 'time': datetime.utcnow().timestamp(), 'slot': slot, 'menu': menu, 'visible': True, 'referencedObjects': find_referenced_items(menu) }, room=target) return json_success("menu changed")
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_send_adjust_volume_command(): now = datetime.utcnow() # find target target = get_target(request.args) if not target: return json_no_command_target_found_error() # get parameters if 'percent' not in request.args: return json_bad_request_error('ARGUMENT_MISSING', 'no volume argument specified') percent = request.args.get('percent') # send command socketio.emit('setvolume', { 'time': now.timestamp(), 'volume': percent }, room=target) return json_success("volume command sent to " + target)
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 save_object(item, user_id): now = get_time_stamp() user_info = get_user_info( user_id ) if user_id else None # user ID may not be set when init object API is used object_type = item.get('type') fields = item['fields'] if 'fields' in item else {} if 'id' not in item: # check authorization if user_info: type_access_level, creatable = select_type_access_info( user_info, object_type) if not creatable: return json_forbidden_error( 'OPERATION_NOT_ALLOWED', 'user is not allowed to create objects of this type') # special checks for user objects if object_type == 'user': email = fields.get('email') if not email: return json_bad_request_error( 'USER_EMAIL_MISSING', 'users require an email to be set') if check_user_exists(email): return json_error_user_already_exists() # adjust and insert object adjust_object_for_insert(item, user_id, now) result = mongo.db.objects.insert_one(item) if result.acknowledged: handle_object_change(item) access_level = select_object_access_level(user_info, item) log.info( f"object with generated ID {item['id']} successfully inserted to database" ) return json_success_update_insert(item, access_level) else: return json_bad_request_error( 'INSERT_FAILED', "object could not be saved to database") else: # check authorization if user_info: previous_object = mongo.db.objects.find_one({'id': item['id']}) if previous_object: if select_object_access_level( user_info, previous_object) < ACCESS_WRITABLE: return json_forbidden_error( 'OPERATION_NOT_ALLOWED', 'user is not allowed to modify this object') else: type_access_level, creatable = select_type_access_info( user_info, object_type) if not creatable: return json_forbidden_error( 'OPERATION_NOT_ALLOWED', 'user is not allowed to create objects of this type') # adjust and update object adjust_object_for_update(item, user_id, now) mongo.db.objects.find_one_and_replace({'id': item['id']}, item, upsert=True) log.info( f"object with preset ID {item['id']} successfully inserted to database" ) handle_object_change(item) access_level = select_object_access_level(user_info, item) return json_success_update_insert(item, access_level)