1
0
Fork 0
mirror of https://github.com/fastogt/fastocloud_admin.git synced 2025-03-09 23:38:52 +00:00
fastocloud_admin/app/service/view.py
2020-02-17 03:38:15 -05:00

292 lines
11 KiB
Python

import os
from flask_classy import FlaskView, route
from flask import render_template, redirect, url_for, request, jsonify, Response
from flask_login import login_required, current_user
from bson.objectid import ObjectId
from app import get_runtime_folder
from app.common.service.forms import ServiceSettingsForm, ActivateForm, UploadM3uForm, ServerProviderForm
from pyfastocloud_models.service.entry import ServiceSettings, ProviderPair
from pyfastocloud_models.utils.m3u_parser import M3uParser
from pyfastocloud_models.utils.utils import is_valid_http_url
from app.home.entry import ProviderAdminUser
import pyfastocloud_models.constants as constants
def _get_server_by_id(sid: str):
try:
server = ServiceSettings.objects.get({'_id': ObjectId(sid)})
except ServiceSettings.DoesNotExist:
return None
else:
return server
# routes
class ServiceView(FlaskView):
route_base = "/service/"
def default_logo_url(self):
return url_for('static', filename='images/unknown_channel.png', _external=True)
@login_required
@route('/upload_m3u', methods=['POST', 'GET'])
def upload_m3u(self):
form = UploadM3uForm()
return render_template('service/upload_m3u.html', form=form)
@login_required
@route('/upload_files', methods=['POST'])
def upload_files(self):
form = UploadM3uForm()
server = current_user.get_current_server()
if server and form.validate_on_submit():
stream_type = form.type.data
files = request.files.getlist("files")
for file in files:
m3u_parser = M3uParser()
data = file.read().decode('utf-8')
m3u_parser.load_content(data)
m3u_parser.parse()
streams = []
default_logo_path = self.default_logo_url()
for file in m3u_parser.files:
if stream_type == constants.StreamType.PROXY:
stream = server.make_proxy_stream()
elif stream_type == constants.StreamType.VOD_PROXY:
stream = server.make_proxy_vod()
elif stream_type == constants.StreamType.RELAY:
stream = server.make_relay_stream()
stream.output = [stream.generate_http_link(constants.HlsType.HLS_PULL,
oid=stream.output[0].id)]
elif stream_type == constants.StreamType.ENCODE:
stream = server.make_encode_stream()
stream.output = [stream.generate_http_link(constants.HlsType.HLS_PULL,
oid=stream.output[0].id)]
elif stream_type == constants.StreamType.VOD_RELAY:
stream = server.make_vod_relay_stream()
stream.output = [stream.generate_vod_link(constants.HlsType.HLS_PULL,
oid=stream.output[0].id)]
elif stream_type == constants.StreamType.VOD_ENCODE:
stream = server.make_vod_encode_stream()
stream.output = [stream.generate_vod_link(constants.HlsType.HLS_PULL,
oid=stream.output[0].id)]
elif stream_type == constants.StreamType.COD_RELAY:
stream = server.make_cod_relay_stream()
stream.output = [stream.generate_cod_link(constants.HlsType.HLS_PULL,
oid=stream.output[0].id)]
elif stream_type == constants.StreamType.COD_ENCODE:
stream = server.make_cod_encode_stream()
stream.output = [stream.generate_cod_link(constants.HlsType.HLS_PULL,
oid=stream.output[0].id)]
elif stream_type == constants.StreamType.CATCHUP:
stream = server.make_catchup_stream()
else:
stream = server.make_test_life_stream()
input_url = file['link']
if stream_type == constants.StreamType.PROXY or stream_type == constants.StreamType.VOD_PROXY:
stream.output[0].uri = input_url
else:
stream.input[0].uri = input_url
stream.tvg_logo = default_logo_path
title = file['title']
if len(title) < constants.MAX_STREAM_NAME_LENGTH:
stream.name = title
tvg_id = file['tvg-id']
if len(tvg_id) < constants.MAX_STREAM_TVG_ID_LENGTH:
stream.tvg_id = tvg_id
tvg_name = file['tvg-name']
if len(tvg_name) < constants.MAX_STREAM_NAME_LENGTH:
stream.tvg_name = tvg_name
tvg_group = file['tvg-group']
if len(tvg_group) < constants.MAX_STREAM_GROUP_TITLE_LENGTH:
stream.group = tvg_group
tvg_logo = file['tvg-logo']
if len(tvg_logo) < constants.MAX_URL_LENGTH:
if is_valid_http_url(tvg_logo, timeout=0.1):
stream.tvg_logo = tvg_logo
stream.save()
streams.append(stream)
server.add_streams(streams)
return redirect(url_for('ProviderView:dashboard'))
@login_required
def connect(self):
server = current_user.get_current_server()
if server:
server.connect()
return redirect(url_for('ProviderView:dashboard'))
@login_required
def disconnect(self):
server = current_user.get_current_server()
if server:
server.disconnect()
return redirect(url_for('ProviderView:dashboard'))
@route('/activate', methods=['POST', 'GET'])
@login_required
def activate(self):
form = ActivateForm()
if request.method == 'POST':
server = current_user.get_current_server()
if server:
if form.validate_on_submit():
license = form.license.data
server.activate(license)
return redirect(url_for('ProviderView:dashboard'))
return render_template('service/activate.html', form=form)
@login_required
def sync(self):
server = current_user.get_current_server()
if server:
server.sync()
return redirect(url_for('ProviderView:dashboard'))
@login_required
def stop(self):
server = current_user.get_current_server()
if server:
server.stop(1)
return redirect(url_for('ProviderView:dashboard'))
@login_required
def ping(self):
server = current_user.get_current_server()
if server:
server.ping()
return redirect(url_for('ProviderView:dashboard'))
@login_required
def get_log(self):
server = current_user.get_current_server()
if server:
server.get_log_service()
return redirect(url_for('ProviderView:dashboard'))
@login_required
@route('/playlist/<sid>/master.m3u', methods=['GET'])
def playlist(self, sid):
server = _get_server_by_id(sid)
if server:
return Response(server.generate_playlist(), mimetype='application/x-mpequrl'), 200
return jsonify(status='failed'), 404
@login_required
def view_log(self):
server = current_user.get_current_server()
if server:
path = os.path.join(get_runtime_folder(), str(server.id))
try:
with open(path, "r") as f:
content = f.read()
return content
except OSError as e:
print('Caught exception OSError : {0}'.format(e))
return '''<pre>Not found, please use get log button firstly.</pre>'''
return '''<pre>Not found, please create server firstly.</pre>'''
# broadcast routes
@login_required
def providers(self, sid):
server = _get_server_by_id(sid)
if server:
return render_template('service/providers.html', server=server)
return redirect(url_for('ProviderView:dashboard'))
@login_required
@route('/provider/add/<sid>', methods=['GET', 'POST'])
def provider_add(self, sid):
form = ServerProviderForm()
if request.method == 'POST' and form.validate_on_submit():
email = form.email.data.lower()
provider = ProviderAdminUser.objects(email=email).first()
server = _get_server_by_id(sid)
if server and provider:
admin = ProviderPair(provider.id, form.role.data)
server.add_provider(admin)
provider.add_server(server)
return jsonify(status='ok'), 200
return render_template('service/provider/add.html', form=form)
@login_required
@route('/provider/remove/<sid>', methods=['POST'])
def provider_remove(self, sid):
data = request.get_json()
pid = data['pid']
provider = ProviderAdminUser.objects(id=pid).first()
server = _get_server_by_id(sid)
if provider and server:
server.remove_provider(provider)
provider.remove_server(server)
return jsonify(status='ok'), 200
return jsonify(status='failed'), 404
@login_required
@route('/add', methods=['GET', 'POST'])
def add(self):
form = ServiceSettingsForm(obj=ServiceSettings())
if request.method == 'POST' and form.validate_on_submit():
new_entry = form.make_entry()
admin = ProviderPair(user=current_user.id, role=ProviderPair.Roles.ADMIN)
new_entry.add_provider(admin)
current_user.add_server(new_entry)
return jsonify(status='ok'), 200
return render_template('service/add.html', form=form)
@login_required
@route('/remove', methods=['POST'])
def remove(self):
sid = request.form['sid']
server = _get_server_by_id(sid)
if server:
server.delete()
return jsonify(status='ok'), 200
return jsonify(status='failed'), 404
@login_required
@route('/edit/<sid>', methods=['GET', 'POST'])
def edit(self, sid):
server = _get_server_by_id(sid)
form = ServiceSettingsForm(obj=server)
if request.method == 'POST' and form.validate_on_submit():
server = form.update_entry(server)
server.save()
return jsonify(status='ok'), 200
return render_template('service/edit.html', form=form)
@route('/log/<sid>', methods=['POST'])
def log(self, sid):
# len = request.headers['content-length']
new_file_path = os.path.join(get_runtime_folder(), sid)
with open(new_file_path, 'wb') as f:
data = request.stream.read()
f.write(b'<pre>')
f.write(data)
f.write(b'</pre>')
f.close()
return jsonify(status='ok'), 200