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")
Esempio n. 2
0
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")
Esempio n. 3
0
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
Esempio n. 4
0
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")
Esempio n. 5
0
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")
Esempio n. 6
0
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)
Esempio n. 7
0
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")
Esempio n. 8
0
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)