diff --git a/app/__init__.py b/app/__init__.py index c569314..f151077 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -3,7 +3,7 @@ import os from omdb import OMDBClient from flask import Flask -from flask_mongoengine import MongoEngine +from flask_pymodm import PyModm from flask_login import LoginManager from flask_mail import Mail from flask_bootstrap import Bootstrap @@ -48,7 +48,7 @@ def init_project(static_folder, *args): app.wsgi_app = ProxyFix(app.wsgi_app) bootstrap = Bootstrap(app) - db = MongoEngine(app) + db = PyModm(app) mail = Mail(app) socketio = SocketIO(app) login_manager = LoginManager(app) diff --git a/app/autofill/entry.py b/app/autofill/entry.py index 2aa3c2c..e8a36ff 100644 --- a/app/autofill/entry.py +++ b/app/autofill/entry.py @@ -1,22 +1,26 @@ -from mongoengine import Document, StringField, ListField +from pymodm import MongoModel, fields import pyfastocloud_models.constants as constants -class M3uParseStreams(Document): - meta = {'allow_inheritance': False, 'collection': 'm3uparse_streams', 'auto_create_index': False} - name = StringField(unique=True, max_length=constants.MAX_STREAM_NAME_LENGTH, - min_length=constants.MIN_STREAM_NAME_LENGTH, - required=True) - tvg_id = ListField(StringField(unique=True), default=[]) - tvg_logo = ListField(StringField(unique=True), default=[]) - group = ListField(StringField(unique=True), default=[]) +class M3uParseStreams(MongoModel): + class Meta: + collection_name = 'm3uparse_streams' + + name = fields.CharField(max_length=constants.MAX_STREAM_NAME_LENGTH, + min_length=constants.MIN_STREAM_NAME_LENGTH, + required=True) + tvg_id = fields.ListField(fields.CharField(), default=[]) + tvg_logo = fields.ListField(fields.CharField(), default=[]) + group = fields.ListField(fields.CharField(), default=[]) -class M3uParseVods(Document): - meta = {'allow_inheritance': False, 'collection': 'm3uparse_vods', 'auto_create_index': False} - name = StringField(unique=True, max_length=constants.MAX_STREAM_NAME_LENGTH, - min_length=constants.MIN_STREAM_NAME_LENGTH, - required=True) - tvg_logo = ListField(StringField(unique=True), default=[]) - group = ListField(StringField(unique=True), default=[]) +class M3uParseVods(MongoModel): + class Meta: + collection_name = 'm3uparse_vods' + + name = fields.CharField(max_length=constants.MAX_STREAM_NAME_LENGTH, + min_length=constants.MIN_STREAM_NAME_LENGTH, + required=True) + tvg_logo = fields.ListField(fields.CharField(), default=[]) + group = fields.ListField(fields.CharField(), default=[]) diff --git a/app/autofill/view.py b/app/autofill/view.py index 5904e5d..abbba6c 100644 --- a/app/autofill/view.py +++ b/app/autofill/view.py @@ -15,11 +15,11 @@ class M3uParseStreamsView(FlaskView): @login_required def show(self): - m3u = M3uParseStreams.objects() + m3u = M3uParseStreams.objects.all() return render_template('autofill/show_streams.html', m3u=m3u) def show_anonim(self): - m3u = M3uParseStreams.objects() + m3u = M3uParseStreams.objects.all() return render_template('autofill/show_streams_anonim.html', m3u=m3u) @route('/search/', methods=['GET']) @@ -82,11 +82,11 @@ class M3uParseVodsView(FlaskView): @login_required def show(self): - m3u = M3uParseVods.objects() + m3u = M3uParseVods.objects.all() return render_template('autofill/show_vods.html', m3u=m3u) def show_anonim(self): - m3u = M3uParseVods.objects() + m3u = M3uParseVods.objects.all() return render_template('autofill/show_vods_anonim.html', m3u=m3u) @route('/search/', methods=['GET']) diff --git a/app/common b/app/common index 1a9515a..1dfd856 160000 --- a/app/common +++ b/app/common @@ -1 +1 @@ -Subproject commit 1a9515a0e359ab708d966dee3a0fb8733c6ba4b9 +Subproject commit 1dfd85657becb2506e9b6ef5ce822c61b9588076 diff --git a/app/config/db_config.py b/app/config/db_config.py index 209c71f..e402f7c 100644 --- a/app/config/db_config.py +++ b/app/config/db_config.py @@ -1,7 +1,3 @@ -MONGO_DBNAME = 'iptv' -MONGO_URI = 'mongodb://localhost:27017/' + MONGO_DBNAME - -MONGODB_SETTINGS = { - 'db': MONGO_DBNAME, - 'host': MONGO_URI -} +MONGODB_DB_NAME = 'iptv' +MONGODB_HOST = 'localhost' +MONGODB_PORT = '27017' diff --git a/app/epg/view.py b/app/epg/view.py index c5ce69e..d04b371 100644 --- a/app/epg/view.py +++ b/app/epg/view.py @@ -23,13 +23,13 @@ class EpgView(FlaskView): @login_required def show(self): - epgs = Epg.objects() + epgs = Epg.objects.all() return render_template('epg/show.html', epgs=epgs) @route('/update_urls', methods=['GET']) @login_required def update_urls(self): - epgs = Epg.objects() + epgs = Epg.objects.all() epg_service_in_directory = app.config.get('EPG_IN_DIRECTORY') result = [] diff --git a/app/home/view.py b/app/home/view.py index 93a38ce..6702277 100644 --- a/app/home/view.py +++ b/app/home/view.py @@ -10,6 +10,25 @@ from app import app, mail, login_manager from app.home.entry import ProviderAdminUser from app.home.forms import ContactForm from app.common.provider.forms import SignupForm, SigninForm +from bson.objectid import ObjectId + + +def _get_provider_by_email(email: str): + try: + provider = ProviderAdminUser.objects.get({'email': email}) + except ProviderAdminUser.DoesNotExist: + return None + else: + return provider + + +def _get_provider_by_id(id: str): + try: + provider = ProviderAdminUser.objects.get({'_id': ObjectId(id)}) + except ProviderAdminUser.DoesNotExist: + return None + else: + return provider def flash_success(text: str): @@ -33,7 +52,7 @@ def post_login(form: SigninForm): return render_template('home/login.html', form=form) email = form.email.data.lower() - check_user = ProviderAdminUser.objects(email=email).first() + check_user = _get_provider_by_email(email) if not check_user: flash_error('User not found.') return render_template('home/login.html', form=form) @@ -42,7 +61,7 @@ def post_login(form: SigninForm): flash_error('User not active.') return render_template('home/login.html', form=form) - if not ProviderAdminUser.check_password_hash(check_user['password'], form.password.data): + if not ProviderAdminUser.check_password_hash(check_user.password, form.password.data): flash_error('Invalid password.') return render_template('home/login.html', form=form) @@ -95,7 +114,7 @@ class HomeView(FlaskView): try: email = self._confirm_link_generator.loads(token, salt=HomeView.SALT_LINK, max_age=HomeView.CONFIRM_LINK_TTL) - confirm_user = ProviderAdminUser.objects(email=email).first() + confirm_user = _get_provider_by_email(email) if confirm_user: confirm_user.status = ProviderAdminUser.Status.ACTIVE confirm_user.save() @@ -140,7 +159,7 @@ class HomeView(FlaskView): flash_error('Invalid email.') return render_template('home/register.html', form=form) - existing_user = ProviderAdminUser.objects(email=email).first() + existing_user = _get_provider_by_email(email) if existing_user: return redirect(url_for('HomeView:signin')) @@ -165,7 +184,7 @@ class HomeView(FlaskView): @login_manager.user_loader def load_user(user_id): - return ProviderAdminUser.objects(pk=user_id).first() + return _get_provider_by_id(user_id) def page_not_found(e): diff --git a/app/provider/view.py b/app/provider/view.py index 7bd7367..0c83e6a 100644 --- a/app/provider/view.py +++ b/app/provider/view.py @@ -65,7 +65,7 @@ class ProviderView(FlaskView): @login_required def remove(self): - servers = ServiceSettings.objects() + servers = ServiceSettings.objects.all() for server in servers: server.remove_provider(current_user) diff --git a/app/service/view.py b/app/service/view.py index 0b87a92..9779ebc 100644 --- a/app/service/view.py +++ b/app/service/view.py @@ -3,6 +3,7 @@ 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 @@ -13,6 +14,15 @@ 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/" @@ -49,28 +59,28 @@ class ServiceView(FlaskView): stream = server.make_proxy_vod() elif stream_type == constants.StreamType.RELAY: stream = server.make_relay_stream() - stream.output.urls[0] = stream.generate_http_link(constants.HlsType.HLS_PULL, - oid=stream.output.urls[0].id) + 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.urls[0] = stream.generate_http_link(constants.HlsType.HLS_PULL, - oid=stream.output.urls[0].id) + 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.urls[0] = stream.generate_vod_link(constants.HlsType.HLS_PULL, - oid=stream.output.urls[0].id) + 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.urls[0] = stream.generate_vod_link(constants.HlsType.HLS_PULL, - oid=stream.output.urls[0].id) + 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.urls[0] = stream.generate_cod_link(constants.HlsType.HLS_PULL, - oid=stream.output.urls[0].id) + 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.urls[0] = stream.generate_cod_link(constants.HlsType.HLS_PULL, - oid=stream.output.urls[0].id) + 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: @@ -78,9 +88,9 @@ class ServiceView(FlaskView): input_url = file['link'] if stream_type == constants.StreamType.PROXY or stream_type == constants.StreamType.VOD_PROXY: - stream.output.urls[0].uri = input_url + stream.output[0].uri = input_url else: - stream.input.urls[0].uri = input_url + stream.input[0].uri = input_url stream.tvg_logo = default_logo_path @@ -171,7 +181,7 @@ class ServiceView(FlaskView): @login_required @route('/playlist//master.m3u', methods=['GET']) def playlist(self, sid): - server = ServiceSettings.objects(id=sid).first() + server = _get_server_by_id(sid) if server: return Response(server.generate_playlist(), mimetype='application/x-mpequrl'), 200 @@ -196,7 +206,7 @@ class ServiceView(FlaskView): @login_required def providers(self, sid): - server = ServiceSettings.objects(id=sid).first() + server = _get_server_by_id(sid) if server: return render_template('service/providers.html', server=server) @@ -209,7 +219,7 @@ class ServiceView(FlaskView): if request.method == 'POST' and form.validate_on_submit(): email = form.email.data.lower() provider = ProviderAdminUser.objects(email=email).first() - server = ServiceSettings.objects(id=sid).first() + server = _get_server_by_id(sid) if server and provider: admin = ProviderPair(provider.id, form.role.data) server.add_provider(admin) @@ -224,7 +234,7 @@ class ServiceView(FlaskView): data = request.get_json() pid = data['pid'] provider = ProviderAdminUser.objects(id=pid).first() - server = ServiceSettings.objects(id=sid).first() + server = _get_server_by_id(sid) if provider and server: server.remove_provider(provider) provider.remove_server(server) @@ -249,7 +259,7 @@ class ServiceView(FlaskView): @route('/remove', methods=['POST']) def remove(self): sid = request.form['sid'] - server = ServiceSettings.objects(id=sid).first() + server = _get_server_by_id(sid) if server: server.delete() return jsonify(status='ok'), 200 @@ -259,7 +269,7 @@ class ServiceView(FlaskView): @login_required @route('/edit/', methods=['GET', 'POST']) def edit(self, sid): - server = ServiceSettings.objects(id=sid).first() + server = _get_server_by_id(sid) form = ServiceSettingsForm(obj=server) if request.method == 'POST' and form.validate_on_submit(): diff --git a/app/stream/view.py b/app/stream/view.py index 95ff47e..f9ced75 100644 --- a/app/stream/view.py +++ b/app/stream/view.py @@ -2,6 +2,7 @@ import os import datetime import re +from bson.objectid import ObjectId from flask_classy import FlaskView, route from flask import render_template, request, jsonify, Response from flask_login import login_required, current_user @@ -15,6 +16,15 @@ from app.common.stream.forms import ProxyStreamForm, EncodeStreamForm, RelayStre from app.common.series.forms import SerialForm +def _get_stream_by_id(sid: str): + try: + stream = IStream.objects.get({'_id': ObjectId(sid)}) + except IStream.DoesNotExist: + return None + else: + return stream + + # routes class StreamView(FlaskView): DEFAULT_PIPELINE_FILENAME_TEMPLATE_1S = '{0}_pipeline.html' @@ -64,7 +74,7 @@ class StreamView(FlaskView): @login_required @route('/play//master.m3u', methods=['GET']) def play(self, sid): - stream = IStream.objects(id=sid).first() + stream = _get_stream_by_id(sid) if stream: return Response(stream.generate_playlist(), mimetype='application/x-mpequrl'), 200 diff --git a/app/subscriber/view.py b/app/subscriber/view.py index 884b8ac..6b4a060 100644 --- a/app/subscriber/view.py +++ b/app/subscriber/view.py @@ -1,19 +1,29 @@ from flask_classy import FlaskView, route from flask import render_template, request, jsonify from flask_login import login_required +from bson.objectid import ObjectId from app.common.subscriber.forms import SignupForm from pyfastocloud_models.subscriber.login.entry import SubscriberUser from pyfastocloud_models.service.entry import ServiceSettings +def _get_subscriber_by_id(sid: str): + try: + subscriber = SubscriberUser.objects.get({'_id': ObjectId(sid)}) + except SubscriberUser.DoesNotExist: + return None + else: + return subscriber + + # routes class SubscriberView(FlaskView): route_base = "/subscriber/" @login_required def show(self): - return render_template('subscriber/show.html', subscribers=SubscriberUser.objects()) + return render_template('subscriber/show.html', subscribers=SubscriberUser.objects.all()) @login_required @route('/add', methods=['GET', 'POST']) @@ -21,7 +31,7 @@ class SubscriberView(FlaskView): form = SignupForm() if request.method == 'POST' and form.validate_on_submit(): new_entry = form.make_entry() - servers = ServiceSettings.objects() + servers = ServiceSettings.objects.all() for server in servers: new_entry.add_server(server) new_entry.save() @@ -32,7 +42,7 @@ class SubscriberView(FlaskView): @login_required @route('/edit/', methods=['GET', 'POST']) def edit(self, sid): - subscriber = SubscriberUser.objects(id=sid).first() + subscriber = _get_subscriber_by_id(sid) form = SignupForm(obj=subscriber) if request.method == 'POST' and form.validate_on_submit(): subscriber = form.update_entry(subscriber) @@ -46,7 +56,7 @@ class SubscriberView(FlaskView): def remove(self): data = request.get_json() sid = data['sid'] - subscriber = SubscriberUser.objects(id=sid).first() + subscriber = _get_subscriber_by_id(sid) if subscriber: subscriber.delete() return jsonify(status='ok'), 200 diff --git a/requirements.txt b/requirements.txt index fc371e1..382794a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,7 @@ flask>=1.0.0 +flask_wtf>=0.14 flask_socketio>=1.0 -flask_mongoengine>=0.8.2 +flask_pymodm>=0.1.2 flask_login>=0.3.0 flask_mail>=0.7.1 flask_bootstrap>=3.3.7.1 diff --git a/scripts/create_provider.py b/scripts/create_provider.py index 6a51164..d0d4537 100755 --- a/scripts/create_provider.py +++ b/scripts/create_provider.py @@ -2,7 +2,7 @@ import argparse import os import sys -from mongoengine import connect +from pymodm import connect sys.path.append(os.path.join(os.path.dirname(__file__), '..')) @@ -22,10 +22,7 @@ if __name__ == '__main__': email = argv.email password = argv.password - mongo = connect(host=argv.mongo_uri) - if not mongo: - sys.exit(1) - + connect(mongodb_uri=argv.mongo_uri) new_user = ProviderAdminUser.make_provider(email=email.lower(), password=password, country=argv.country, language=argv.language) new_user.status = ProviderAdminUser.Status.ACTIVE diff --git a/scripts/import_from_xtream.py b/scripts/import_from_xtream.py index 6bbf366..d8385f1 100755 --- a/scripts/import_from_xtream.py +++ b/scripts/import_from_xtream.py @@ -2,7 +2,7 @@ import argparse import os import sys -from mongoengine import connect +from pymodm import connect import mysql.connector sys.path.append(os.path.join(os.path.dirname(__file__), '..')) diff --git a/scripts/import_resellers_from_xtream.py b/scripts/import_resellers_from_xtream.py index c54ba97..ddd7851 100755 --- a/scripts/import_resellers_from_xtream.py +++ b/scripts/import_resellers_from_xtream.py @@ -2,7 +2,7 @@ import argparse import os import sys -from mongoengine import connect +from pymodm import connect import mysql.connector sys.path.append(os.path.join(os.path.dirname(__file__), '..')) @@ -28,7 +28,7 @@ if __name__ == '__main__': mysql_port = argv.mysql_port server_id = argv.server_id - mongo = connect(host=argv.mongo_uri) + mongo = connect(uri=argv.mongo_uri) if not mongo: sys.exit(1) diff --git a/scripts/import_streams_from_xtream.py b/scripts/import_streams_from_xtream.py index de0da45..5dbf31e 100755 --- a/scripts/import_streams_from_xtream.py +++ b/scripts/import_streams_from_xtream.py @@ -2,7 +2,7 @@ import argparse import os import sys -from mongoengine import connect +from pymodm import connect import mysql.connector sys.path.append(os.path.join(os.path.dirname(__file__), '..')) diff --git a/scripts/import_subscribers_from_xtream.py b/scripts/import_subscribers_from_xtream.py index c004491..a800a42 100755 --- a/scripts/import_subscribers_from_xtream.py +++ b/scripts/import_subscribers_from_xtream.py @@ -2,7 +2,7 @@ import argparse import os import sys -from mongoengine import connect +from pymodm import connect import mysql.connector sys.path.append(os.path.join(os.path.dirname(__file__), '..')) @@ -29,7 +29,7 @@ if __name__ == '__main__': mysql_port = argv.mysql_port server_id = argv.server_id - mongo = connect(host=argv.mongo_uri) + mongo = connect(uri=argv.mongo_uri) if not mongo: sys.exit(1) diff --git a/scripts/migrate/xtream/streams.py b/scripts/migrate/xtream/streams.py index a164356..895b1fd 100755 --- a/scripts/migrate/xtream/streams.py +++ b/scripts/migrate/xtream/streams.py @@ -18,7 +18,7 @@ def import_streams_to_server(db, server: ServiceSettings): if not len(urls): continue - stream.output.urls[0].uri = urls[0] + stream.output[0].uri = urls[0] stream.name = sql_entry['stream_display_name'] tvg_logo = sql_entry['stream_icon'] if len(tvg_logo) < constants.MAX_URL_LENGTH: diff --git a/scripts/parse_json_out.py b/scripts/parse_json_out.py index 14e3b7a..034d129 100644 --- a/scripts/parse_json_out.py +++ b/scripts/parse_json_out.py @@ -11,8 +11,8 @@ if __name__ == '__main__': name = p['name'] icon = p['icon'] group = p['group'] - sid = p['input']['urls'][0]['id'] - input = p['input']['urls'][0]['uri'] + sid = p['input'][0]['id'] + input = p['input'][0]['uri'] f.write('#EXTINF:{0} tvg-id="{1}" tvg-name="" tvg-logo="{3}" group-title="{4}",{2}\n{5}\n'.format( idx, sid, diff --git a/scripts/parse_streams_collection.py b/scripts/parse_streams_collection.py index 4a6a6b2..92aba9d 100755 --- a/scripts/parse_streams_collection.py +++ b/scripts/parse_streams_collection.py @@ -2,7 +2,7 @@ import argparse import os import sys -from mongoengine import connect +from pymodm import connect sys.path.append(os.path.join(os.path.dirname(__file__), '..')) @@ -16,9 +16,9 @@ if __name__ == '__main__': argv = parser.parse_args() - mongo = connect(host=argv.mongo_uri) + mongo = connect(argv.mongo_uri) if mongo: - streams = IStream.objects() + streams = IStream.objects.all() f = open("out.m3u", "w") f.write('#EXTM3U\n') idx = 0 diff --git a/scripts/test_life.py b/scripts/test_life.py index b2f374b..fd39f9c 100755 --- a/scripts/test_life.py +++ b/scripts/test_life.py @@ -2,7 +2,8 @@ import argparse import os import sys -from mongoengine import connect +from pymodm import connect +from bson.objectid import ObjectId sys.path.append(os.path.join(os.path.dirname(__file__), '..')) @@ -12,6 +13,16 @@ from pyfastocloud_models.utils.m3u_parser import M3uParser PROJECT_NAME = 'test_life' + +def _get_server_by_id(sid: str): + try: + server = ServiceSettings.objects.get({'_id': ObjectId(sid)}) + except ServiceSettings.DoesNotExist: + return None + else: + return server + + if __name__ == '__main__': parser = argparse.ArgumentParser(prog=PROJECT_NAME, usage='%(prog)s [options]') parser.add_argument('uri', help='Uri to m3u8 list') @@ -21,13 +32,13 @@ if __name__ == '__main__': mongo = connect(argv.mongo_uri) if mongo: - service_settings = ServiceSettings.objects().first() + service_settings = ServiceSettings.objects.get({}) m3u_parser = M3uParser() m3u_parser.read_m3u(argv.uri) m3u_parser.parse() for file in m3u_parser.files: stream = TestLifeStream.make_stream(service_settings) - stream.input.urls[0].uri = file['link'] + stream.input[0].uri = file['link'] stream.name = '{0}({1})'.format(file['tvg-group'], file['title']) service_settings.streams.append(stream)