def test_edit_asset(self): with db.conn(settings['database']) as conn: assets_helper.create(conn, asset_x) with Browser() as browser: browser.visit('http://localhost:8080') wait_for_and_do(browser, '.edit-asset-button', lambda btn: btn.click()) sleep(1) wait_for_and_do(browser, 'input[name="duration"]', lambda field: field.fill('333')) sleep(1) # wait for new-asset panel animation wait_for_and_do(browser, '#add-form', lambda form: form.click()) sleep(1) wait_for_and_do(browser, '#save-asset', lambda btn: btn.click()) sleep(3) # backend need time to process request with db.conn(settings['database']) as conn: assets = assets_helper.read(conn) self.assertEqual(len(assets), 1) asset = assets[0] self.assertEqual(asset['duration'], u'333')
def test_rm_asset(self): with db.conn(settings['database']) as conn: assets_helper.create(conn, asset_x) with Browser() as browser: browser.visit('http://localhost:8080') wait_for_and_do(browser, '.delete-asset-button', lambda btn: btn.click()) wait_for_and_do(browser, '.confirm-delete', lambda btn: btn.click()) sleep(3) # backend need time to process request with db.conn(settings['database']) as conn: assets = assets_helper.read(conn) self.assertEqual(len(assets), 0)
def test_enable_asset(self): with db.conn(settings['database']) as conn: assets_helper.create(conn, asset_x) with Browser() as browser: browser.visit('http://localhost:8080') wait_for_and_do(browser, 'span[class="on"]', lambda btn: btn.click()) sleep(3) # backend need time to process request with db.conn(settings['database']) as conn: assets = assets_helper.read(conn) self.assertEqual(len(assets), 1) asset = assets[0] self.assertEqual(asset['is_enabled'], 1)
def test_add_asset_streaming(self): with Browser() as browser: browser.visit(main_page_url) wait_for_and_do(browser, '#add-asset-button', lambda btn: btn.click()) sleep(1) wait_for_and_do(browser, 'input[name="uri"]', lambda field: field.fill('rtmp://localhost:1935/app/video.flv')) sleep(1) wait_for_and_do(browser, '#add-form', lambda form: form.click()) sleep(1) wait_for_and_do(browser, '#save-asset', lambda btn: btn.click()) sleep(10) # backend need time to process request with db.conn(settings['database']) as conn: assets = assets_helper.read(conn) self.assertEqual(len(assets), 1) asset = assets[0] self.assertEqual(asset['name'], u'rtmp://localhost:1935/app/video.flv') self.assertEqual(asset['uri'], u'rtmp://localhost:1935/app/video.flv') self.assertEqual(asset['mimetype'], u'streaming') self.assertEqual(asset['duration'], settings['default_streaming_duration'])
def test_add_asset_url(self): with Browser() as browser: browser.visit('http://localhost:8080') wait_for_and_do(browser, '#add-asset-button', lambda btn: btn.click()) sleep(1) wait_for_and_do(browser, 'input[name="uri"]', lambda field: field.fill('http://example.com')) wait_for_and_do(browser, 'input[name="duration"]', lambda field: field.fill('30')) sleep(1) wait_for_and_do(browser, '#add-form', lambda form: form.click()) sleep(1) wait_for_and_do(browser, '#save-asset', lambda btn: btn.click()) sleep(3) # backend need time to process request with db.conn(settings['database']) as conn: assets = assets_helper.read(conn) self.assertEqual(len(assets), 1) asset = assets[0] self.assertEqual(asset['name'], u'http://example.com') self.assertEqual(asset['uri'], u'http://example.com') self.assertEqual(asset['mimetype'], u'webpage') self.assertEqual(asset['duration'], u'30')
def get(self, asset_id): with db.conn(settings['database']) as conn: asset = assets_helper.read(conn, asset_id) if isinstance(asset, list): raise Exception('Invalid asset ID provided') if path.isfile(asset['uri']): filename = asset['name'] with open(asset['uri'], 'rb') as f: content = f.read() mimetype = guess_type(filename)[0] if not mimetype: mimetype = 'application/octet-stream' result = { 'type': 'file', 'filename': filename, 'content': b64encode(content), 'mimetype': mimetype } else: result = { 'type': 'url', 'url': asset['uri'] } return result
def test_add_two_assets_upload(self): video_file = '/tmp/video.flv' image_file = '/tmp/image.png' with Browser() as browser: browser.visit(main_page_url) browser.find_by_id('add-asset-button').click() sleep(1) wait_for_and_do(browser, 'a[href="#tab-file_upload"]', lambda tab: tab.click()) wait_for_and_do(browser, 'input[name="file_upload"]', lambda input: input.fill(image_file)) wait_for_and_do(browser, 'input[name="file_upload"]', lambda input: input.fill(video_file)) sleep(3) # backend need time to process request with db.conn(settings['database']) as conn: assets = assets_helper.read(conn) self.assertEqual(len(assets), 2) self.assertEqual(assets[0]['name'], u'image.png') self.assertEqual(assets[0]['mimetype'], u'image') self.assertEqual(assets[0]['duration'], settings['default_duration']) self.assertEqual(assets[1]['name'], u'video.flv') self.assertEqual(assets[1]['mimetype'], u'video') self.assertEqual(assets[1]['duration'], u'54')
def test_add_asset_video_upload(self): video_file = '/tmp/video.mov' with Browser() as browser: browser.visit('http://localhost:8080') browser.find_by_id('add-asset-button').click() sleep(1) wait_for_and_do(browser, 'a[href="#tab-file_upload"]', lambda tab: tab.click()) wait_for_and_do(browser, 'input[name="file_upload"]', lambda input: input.fill(video_file)) sleep(1) # wait for new-asset panel animation wait_for_and_do(browser, '#add-form', lambda form: form.click()) sleep(1) wait_for_and_do(browser, '#save-asset', lambda btn: btn.click()) sleep(3) # backend need time to process request with db.conn(settings['database']) as conn: assets = assets_helper.read(conn) self.assertEqual(len(assets), 1) asset = assets[0] self.assertEqual(asset['name'], u'video.mov') self.assertEqual(asset['mimetype'], u'video') self.assertEqual(asset['duration'], u'33')
def test_disable_asset(self): with db.conn(settings['database']) as conn: _asset_x = asset_x.copy() _asset_x['is_enabled'] = 1 assets_helper.create(conn, _asset_x) with Browser() as browser: browser.visit(main_page_url) wait_for_and_do(browser, 'span[class="off"]', lambda btn: btn.click()) sleep(3) # backend need time to process request with db.conn(settings['database']) as conn: assets = assets_helper.read(conn) self.assertEqual(len(assets), 1) asset = assets[0] self.assertEqual(asset['is_enabled'], 0)
def delete(self, asset_id): with db.conn(settings['database']) as conn: asset = assets_helper.read(conn, asset_id) try: if asset['uri'].startswith(settings['assetdir']): remove(asset['uri']) except OSError: pass assets_helper.delete(conn, asset_id) return '', 204 # return an OK with no content
def setup(): global HOME, arch, db_conn HOME = getenv('HOME', '/home/pi') arch = machine() signal(SIGUSR1, sigusr1) load_settings() db_conn = db.conn(settings['database']) sh.mkdir(SCREENLY_HTML, p=True) html_templates.black_page(BLACK_PAGE)
def post(self): asset = prepare_asset_v1_2(request) if url_fails(asset['uri']): raise Exception("Could not retrieve file. Check the asset URL.") with db.conn(settings['database']) as conn: assets = assets_helper.read(conn) ids_of_active_assets = [x['asset_id'] for x in assets if x['is_active']] asset = assets_helper.create(conn, asset) if asset['is_active']: ids_of_active_assets.insert(asset['play_order'], asset['asset_id']) assets_helper.save_ordering(conn, ids_of_active_assets) return assets_helper.read(conn, asset['asset_id']), 201
def get(self): collector = ZmqCollector.get_instance() publisher = ZmqPublisher.get_instance() publisher.send_to_viewer('current_asset_id') collector_result = collector.recv_json(2000) current_asset_id = collector_result.get('current_asset_id') if not current_asset_id: return [] with db.conn(settings['database']) as conn: return assets_helper.read(conn, current_asset_id)
def test_reorder_asset(self): with db.conn(settings['database']) as conn: _asset_x = asset_x.copy() _asset_x['is_enabled'] = 1 assets_helper.create(conn, _asset_x) assets_helper.create(conn, asset_y) with Browser() as browser: browser.visit('http://localhost:8080') asset_x_for_drag = browser.find_by_id(asset_x['asset_id']) sleep(1) asset_y_to_reorder = browser.find_by_id(asset_y['asset_id']) asset_x_for_drag.drag_and_drop(asset_y_to_reorder) sleep(3) # backend need time to process request with db.conn(settings['database']) as conn: x = assets_helper.read(conn, asset_x['asset_id']) y = assets_helper.read(conn, asset_y['asset_id']) self.assertEqual(x['play_order'], 0) self.assertEqual(y['play_order'], 1)
def put(self, asset_id): asset = prepare_asset_v1_2(request, asset_id) with db.conn(settings['database']) as conn: assets = assets_helper.read(conn) ids_of_active_assets = [x['asset_id'] for x in assets if x['is_active']] asset = assets_helper.update(conn, asset_id, asset) try: ids_of_active_assets.remove(asset['asset_id']) except ValueError: pass if asset['is_active']: ids_of_active_assets.insert(asset['play_order'], asset['asset_id']) assets_helper.save_ordering(conn, ids_of_active_assets) return assets_helper.read(conn, asset_id)
def get(self): with db.conn(settings['database']) as conn: assets = assets_helper.read(conn) return assets
@app.route('/static_with_mime/<string:path>') @auth_basic def static_with_mime(path): mimetype = request.args['mime'] if 'mime' in request.args else 'auto' return send_from_directory(directory='static', filename=path, mimetype=mimetype) if __name__ == "__main__": # Make sure the asset folder exist. If not, create it if not path.isdir(settings['assetdir']): mkdir(settings['assetdir']) # Create config dir if it doesn't exist if not path.isdir(settings.get_configdir()): makedirs(settings.get_configdir()) with db.conn(settings['database']) as conn: with db.cursor(conn) as cursor: cursor.execute(queries.exists_table) if cursor.fetchone() is None: cursor.execute(assets_helper.create_assets_table) config = { 'bind': '{}:{}'.format(LISTEN, PORT), 'threads': 2, 'timeout': 20 } class GunicornApplication(Application): def init(self, parser, opts, args): return config
def playlist_order(): with db.conn(settings['database']) as conn: assets_helper.save_ordering(conn, request.POST.get('ids', '').split(','))
def setUp(self): self.old_db_path = settings.settings['database'] viewer.db_conn = db.conn(':memory:') with db.commit(viewer.db_conn) as cursor: cursor.execute(assets_helper.create_assets_table)
def setUp(self): self.assertEmpty = functools.partial(self.assertEqual, []) self.conn = db.conn(':memory:') with db.commit(self.conn) as cursor: cursor.execute(assets_helper.create_assets_table)
def post(self): asset = prepare_asset(request, unique_name=True) if url_fails(asset['uri']): raise Exception("Could not retrieve file. Check the asset URL.") with db.conn(settings['database']) as conn: return assets_helper.create(conn, asset), 201
def post(self): asset = prepare_asset(request) if url_fails(asset['uri']): raise Exception("Could not retrieve file. Check the asset URL.") with db.conn(settings['database']) as conn: return assets_helper.create(conn, asset), 201
def get(self, asset_id): with db.conn(settings['database']) as conn: return assets_helper.read(conn, asset_id)
def put(self, asset_id): with db.conn(settings['database']) as conn: return assets_helper.update(conn, asset_id, prepare_asset(request))
def api_assets(): with db.conn(settings['database']) as conn: assets = assets_helper.read(conn) return make_json_response(assets)
def static_with_mime(path): mimetype = request.args['mime'] if 'mime' in request.args else 'auto' return send_from_directory(directory='static', filename=path, mimetype=mimetype) if __name__ == "__main__": # Make sure the asset folder exist. If not, create it if not path.isdir(settings['assetdir']): mkdir(settings['assetdir']) # Create config dir if it doesn't exist if not path.isdir(settings.get_configdir()): makedirs(settings.get_configdir()) with db.conn(settings['database']) as conn: with db.cursor(conn) as cursor: cursor.execute(queries.exists_table) if cursor.fetchone() is None: cursor.execute(assets_helper.create_assets_table) config = { 'bind': '{}:{}'.format(LISTEN, PORT), 'threads': 2, 'timeout': 20 } class GunicornApplication(Application): def init(self, parser, opts, args): return config
def prepare_asset_v1_2(request_environ, asset_id=None, unique_name=False): data = json.loads(request_environ.data) def get(key): val = data.get(key, '') if isinstance(val, unicode): return val.strip() elif isinstance(val, basestring): return val.strip().decode('utf-8') else: return val if not all([get('name'), get('uri'), get('mimetype'), str(get('is_enabled')), get('start_date'), get('end_date')]): raise Exception( "Not enough information provided. Please specify 'name', 'uri', 'mimetype', 'is_enabled', 'start_date' and 'end_date'.") name = get('name') if unique_name: with db.conn(settings['database']) as conn: names = assets_helper.get_names_of_assets(conn) if name in names: i = 1 while True: new_name = '%s-%i' % (name, i) if new_name in names: i += 1 else: name = new_name break asset = { 'name': name, 'mimetype': get('mimetype'), 'is_enabled': get('is_enabled'), 'nocache': get('nocache') } uri = get('uri') if uri.startswith('/'): if not path.isfile(uri): raise Exception("Invalid file path. Failed to add asset.") else: if not validate_url(uri): raise Exception("Invalid URL. Failed to add asset.") if not asset_id: asset['asset_id'] = uuid.uuid4().hex if uri.startswith('/'): rename(uri, path.join(settings['assetdir'], asset['asset_id'])) uri = path.join(settings['assetdir'], asset['asset_id']) if 'youtube_asset' in asset['mimetype']: uri, asset['name'], asset['duration'] = download_video_from_youtube(uri, asset['asset_id']) asset['mimetype'] = 'video' asset['is_processing'] = 1 asset['uri'] = uri if "video" in asset['mimetype']: if get('duration') == 'N/A' or int(get('duration')) == 0: asset['duration'] = int(get_video_duration(uri).total_seconds()) elif get('duration'): # Crashes if it's not an int. We want that. asset['duration'] = int(get('duration')) else: asset['duration'] = 10 asset['play_order'] = get('play_order') if get('play_order') else 0 asset['skip_asset_check'] = int(get('skip_asset_check')) if int(get('skip_asset_check')) else 0 # parse date via python-dateutil and remove timezone info asset['start_date'] = date_parser.parse(get('start_date')).replace(tzinfo=None) asset['end_date'] = date_parser.parse(get('end_date')).replace(tzinfo=None) return asset
def post(self): with db.conn(settings['database']) as conn: assets_helper.save_ordering(conn, request.form.get('ids', '').split(','))
def prepare_asset_v1_2(request_environ, asset_id=None, unique_name=False): data = json.loads(request_environ.data) def get(key): val = data.get(key, '') if isinstance(val, unicode): return val.strip() elif isinstance(val, basestring): return val.strip().decode('utf-8') else: return val if not all([ get('name'), get('uri'), get('mimetype'), str(get('is_enabled')), get('start_date'), get('end_date') ]): raise Exception( "Not enough information provided. Please specify 'name', 'uri', 'mimetype', 'is_enabled', 'start_date' and 'end_date'." ) name = get('name') if unique_name: with db.conn(settings['database']) as conn: names = assets_helper.get_names_of_assets(conn) if name in names: i = 1 while True: new_name = '%s-%i' % (name, i) if new_name in names: i += 1 else: name = new_name break asset = { 'name': name, 'mimetype': get('mimetype'), 'is_enabled': get('is_enabled'), 'nocache': get('nocache') } uri = get('uri') if uri.startswith('/'): if not path.isfile(uri): raise Exception("Invalid file path. Failed to add asset.") else: if not validate_url(uri): raise Exception("Invalid URL. Failed to add asset.") if not asset_id: asset['asset_id'] = uuid.uuid4().hex if uri.startswith('/'): rename(uri, path.join(settings['assetdir'], asset['asset_id'])) uri = path.join(settings['assetdir'], asset['asset_id']) if 'youtube_asset' in asset['mimetype']: uri, asset['name'], asset['duration'] = download_video_from_youtube( uri, asset['asset_id']) asset['mimetype'] = 'video' asset['is_processing'] = 1 asset['uri'] = uri if "video" in asset['mimetype']: if get('duration') == 'N/A' or int(get('duration')) == 0: asset['duration'] = int(get_video_duration(uri).total_seconds()) elif get('duration'): # Crashes if it's not an int. We want that. asset['duration'] = int(get('duration')) else: asset['duration'] = 10 asset['play_order'] = get('play_order') if get('play_order') else 0 asset['skip_asset_check'] = int(get('skip_asset_check')) if int( get('skip_asset_check')) else 0 # parse date via python-dateutil and remove timezone info asset['start_date'] = date_parser.parse( get('start_date')).replace(tzinfo=None) asset['end_date'] = date_parser.parse(get('end_date')).replace(tzinfo=None) return asset
def setUp(self): with db.conn(settings['database']) as conn: assets = assets_helper.read(conn) for asset in assets: assets_helper.delete(conn, asset['asset_id'])