diff --git a/django_code/apps/podcast_aggregator/admin.py b/django_code/apps/podcast_aggregator/admin.py index 9479bd9..ecbf68e 100644 --- a/django_code/apps/podcast_aggregator/admin.py +++ b/django_code/apps/podcast_aggregator/admin.py @@ -1,9 +1,13 @@ from django.contrib import admin from import_export.admin import ImportExportModelAdmin from import_export import resources +from django.utils.html import format_html from .models import podcastData # Register your models here. @admin.register(podcastData) class JobAdmin(ImportExportModelAdmin): - list_display = ('podcast_name','podcast_url','enabled') + list_display = ('podcast_name','clickable_links','enabled') + + def clickable_links(self, obj): + return format_html('{}', obj.podcast_url,obj.podcast_url) \ No newline at end of file diff --git a/django_code/apps/random_simpsons/admin.py b/django_code/apps/random_simpsons/admin.py index cdda8d8..1a4bf36 100644 --- a/django_code/apps/random_simpsons/admin.py +++ b/django_code/apps/random_simpsons/admin.py @@ -1,12 +1,13 @@ from django.contrib import admin,messages from django.utils.translation import ngettext -from prompt_toolkit.shortcuts import print_container -from .models import SimpsonsData,simpsons_data_object,urlData -from .utils import mark_episode_watched,unwatch_all_episodes,generate_new_urls_for_episode -from import_export import resources -from import_export.admin import ImportExportModelAdmin +from django.utils.html import format_html from django.utils import timezone from djangoql.admin import DjangoQLSearchMixin +from prompt_toolkit.shortcuts import print_container +from import_export.admin import ImportExportModelAdmin +from import_export import resources +from .models import SimpsonsData,simpsons_data_object,urlData +from .utils import mark_episode_watched,unwatch_all_episodes,generate_new_urls_for_episode # Register your models here. @@ -72,7 +73,9 @@ class EpisodeAdmin(DjangoQLSearchMixin,ImportExportModelAdmin): actions = [make_seen,make_unseen,unseen_betaserie,generate_new_urls] search_fields = ['season', 'episode', 'url', 'seen'] djangoql_completion_enabled_by_default = False - + + def clickable_links(self, obj): + return format_html('{}', obj.url,obj.url) def get_queryset(self, request): diff --git a/django_code/apps/streaming/admin.py b/django_code/apps/streaming/admin.py index ce2f06f..bb77350 100644 --- a/django_code/apps/streaming/admin.py +++ b/django_code/apps/streaming/admin.py @@ -1,7 +1,9 @@ from django.contrib import admin +from django.utils.html import format_html from import_export.admin import ImportExportModelAdmin -from .models import streamingData +from .models import StreamingSiteTestingData,StreamingRedirectData from .utils import full_testing +from urllib.parse import urlsplit, urlunsplit @@ -28,8 +30,63 @@ def check(modeladmin, request, queryset): # messages.SUCCESS, # ) -@admin.register(streamingData) +@admin.action(description="cleaning the url") +def urlcleaning(modeladmin, request, queryset): + for query in queryset: + # Split the URL into components + parsed = urlsplit(query.url) + + # Rebuild using only scheme and netloc, adding a trailing slash at the end + base_url = urlunsplit((parsed.scheme, parsed.netloc, "/", "", "")) + query.url = base_url + query.save(update_fields=["url"]) + print("Cleaning :"+str(base_url)) + + return 0 +@admin.register(StreamingSiteTestingData) class streamingAdmin(ImportExportModelAdmin): - list_display = ['url','result','status'] + list_display = ['clickable_links','result_colored','newstatus'] fields = ['url'] - actions = [check] \ No newline at end of file + actions = [check,urlcleaning] + + def clickable_links(self, obj): + return format_html('{}', obj.url,obj.url) + + def result_colored(self, obj): + colors = { + 'REACHABLE': 'green', + 'VPN REQUIRED': 'yellow', + 'UNREACHABLE': 'red', + } + + return format_html( + '{}', + colors[obj.result], + obj.result, + ) + def newstatus(self, obj): + if obj.status != '200': + return format_html('
{}
', obj.status) + #return obj.status + + +@admin.register(StreamingRedirectData) +class StreamingRedirectAdmin(ImportExportModelAdmin): + list_display = ['name','season','episode','randomViewing','url_example','addedDate','alias'] + #fields = ['name','season','episode','url_example','prefix','infix','suffix','alias','randomViewing','seasonInformation'] + fieldsets = ( + ( + 'Serie', { + 'fields': ('name', 'season', 'episode','randomViewing') + }), + ( + 'url', { + + 'fields': (('prefix','infix','suffix'),'url_example') + }), + ( + 'Information', { + "classes": ["collapse"], + 'fields': ('seasonInformation','alias','betaserieShowId') + }), + ) \ No newline at end of file diff --git a/django_code/apps/streaming/apps.py b/django_code/apps/streaming/apps.py index 85d22eb..7c1d9dd 100644 --- a/django_code/apps/streaming/apps.py +++ b/django_code/apps/streaming/apps.py @@ -4,3 +4,4 @@ from django.apps import AppConfig class StreamingConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'apps.streaming' + label = 'streaming' diff --git a/django_code/apps/streaming/migrations/0003_streamingredirectdata.py b/django_code/apps/streaming/migrations/0003_streamingredirectdata.py new file mode 100644 index 0000000..208d7cc --- /dev/null +++ b/django_code/apps/streaming/migrations/0003_streamingredirectdata.py @@ -0,0 +1,29 @@ +# Generated by Django 4.2.30 on 2026-08-07 13:13 + +import apps.streaming.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('streaming', '0002_streamingdata_result'), + ] + + operations = [ + migrations.CreateModel( + name='StreamingRedirectData', + fields=[ + ('name', models.CharField(help_text='Name of the show', max_length=1000, primary_key=True, serialize=False)), + ('url_example', models.CharField(help_text='https://www.1shows.org/tv/456-the-simpsons?streaming=true&season=18&episode=5', max_length=1000)), + ('prefix', models.CharField(blank=True, help_text='https://www.1shows.org/tv/456-the-simpsons?streaming=true&season=', max_length=1000, null=True)), + ('infix', models.CharField(blank=True, help_text='&episode=', max_length=1000, null=True)), + ('suffix', models.CharField(blank=True, max_length=1000, null=True)), + ('addedDate', models.DateField(auto_now_add=True, null=True, verbose_name='Published')), + ('alias', models.CharField(default=apps.streaming.models.StreamingRedirectData.sanitize, max_length=1000)), + ], + options={ + 'db_table': 'StreamingRedirect', + }, + ), + ] diff --git a/django_code/apps/streaming/migrations/0004_streamingredirectdata_episode_to_watch_and_more.py b/django_code/apps/streaming/migrations/0004_streamingredirectdata_episode_to_watch_and_more.py new file mode 100644 index 0000000..bc762be --- /dev/null +++ b/django_code/apps/streaming/migrations/0004_streamingredirectdata_episode_to_watch_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 4.2.30 on 2026-08-07 14:02 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('streaming', '0003_streamingredirectdata'), + ] + + operations = [ + migrations.AddField( + model_name='streamingredirectdata', + name='episode_to_watch', + field=models.IntegerField(default=1), + ), + migrations.AddField( + model_name='streamingredirectdata', + name='season_to_watch', + field=models.IntegerField(default=1), + ), + migrations.AlterField( + model_name='streamingredirectdata', + name='alias', + field=models.CharField(blank=True, max_length=1000, null=True), + ), + ] diff --git a/django_code/apps/streaming/migrations/0005_streamingredirectdata_hello.py b/django_code/apps/streaming/migrations/0005_streamingredirectdata_hello.py new file mode 100644 index 0000000..7301f8b --- /dev/null +++ b/django_code/apps/streaming/migrations/0005_streamingredirectdata_hello.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.30 on 2026-08-07 14:49 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('streaming', '0004_streamingredirectdata_episode_to_watch_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='streamingredirectdata', + name='hello', + field=models.CharField(blank=True, max_length=1000, null=True), + ), + ] diff --git a/django_code/apps/streaming/migrations/0006_remove_streamingredirectdata_hello_and_more.py b/django_code/apps/streaming/migrations/0006_remove_streamingredirectdata_hello_and_more.py new file mode 100644 index 0000000..2a9df99 --- /dev/null +++ b/django_code/apps/streaming/migrations/0006_remove_streamingredirectdata_hello_and_more.py @@ -0,0 +1,22 @@ +# Generated by Django 4.2.30 on 2026-08-07 14:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('streaming', '0005_streamingredirectdata_hello'), + ] + + operations = [ + migrations.RemoveField( + model_name='streamingredirectdata', + name='hello', + ), + migrations.AddField( + model_name='streamingredirectdata', + name='seasonInformation', + field=models.JSONField(blank=True, max_length=1000, null=True), + ), + ] diff --git a/django_code/apps/streaming/migrations/0007_rename_streamingdata_streamingsitetestingdata_and_more.py b/django_code/apps/streaming/migrations/0007_rename_streamingdata_streamingsitetestingdata_and_more.py new file mode 100644 index 0000000..1581313 --- /dev/null +++ b/django_code/apps/streaming/migrations/0007_rename_streamingdata_streamingsitetestingdata_and_more.py @@ -0,0 +1,22 @@ +# Generated by Django 4.2.30 on 2026-08-07 15:22 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('streaming', '0006_remove_streamingredirectdata_hello_and_more'), + ] + + operations = [ + migrations.RenameModel( + old_name='streamingData', + new_name='StreamingSiteTestingData', + ), + migrations.AlterField( + model_name='streamingredirectdata', + name='seasonInformation', + field=models.JSONField(blank=True, default='', max_length=1000), + ), + ] diff --git a/django_code/apps/streaming/migrations/0008_streamingredirectdata_randomviewing_and_more.py b/django_code/apps/streaming/migrations/0008_streamingredirectdata_randomviewing_and_more.py new file mode 100644 index 0000000..17cd169 --- /dev/null +++ b/django_code/apps/streaming/migrations/0008_streamingredirectdata_randomviewing_and_more.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.30 on 2026-08-07 15:59 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('streaming', '0007_rename_streamingdata_streamingsitetestingdata_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='streamingredirectdata', + name='randomViewing', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='streamingredirectdata', + name='seasonInformation', + field=models.JSONField(blank=True, default=dict), + ), + ] diff --git a/django_code/apps/streaming/migrations/0009_rename_episode_to_watch_streamingredirectdata_episode_and_more.py b/django_code/apps/streaming/migrations/0009_rename_episode_to_watch_streamingredirectdata_episode_and_more.py new file mode 100644 index 0000000..8de3284 --- /dev/null +++ b/django_code/apps/streaming/migrations/0009_rename_episode_to_watch_streamingredirectdata_episode_and_more.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.30 on 2026-08-25 14:06 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('streaming', '0008_streamingredirectdata_randomviewing_and_more'), + ] + + operations = [ + migrations.RenameField( + model_name='streamingredirectdata', + old_name='episode_to_watch', + new_name='episode', + ), + migrations.RenameField( + model_name='streamingredirectdata', + old_name='season_to_watch', + new_name='season', + ), + ] diff --git a/django_code/apps/streaming/migrations/0010_alter_streamingredirectdata_episode.py b/django_code/apps/streaming/migrations/0010_alter_streamingredirectdata_episode.py new file mode 100644 index 0000000..4dc4be3 --- /dev/null +++ b/django_code/apps/streaming/migrations/0010_alter_streamingredirectdata_episode.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.30 on 2026-08-25 14:08 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('streaming', '0009_rename_episode_to_watch_streamingredirectdata_episode_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='streamingredirectdata', + name='episode', + field=models.IntegerField(default=0), + ), + ] diff --git a/django_code/apps/streaming/migrations/0011_streamingredirectdata_betaserieshowid.py b/django_code/apps/streaming/migrations/0011_streamingredirectdata_betaserieshowid.py new file mode 100644 index 0000000..6392400 --- /dev/null +++ b/django_code/apps/streaming/migrations/0011_streamingredirectdata_betaserieshowid.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.30 on 2026-08-25 15:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('streaming', '0010_alter_streamingredirectdata_episode'), + ] + + operations = [ + migrations.AddField( + model_name='streamingredirectdata', + name='betaserieShowId', + field=models.IntegerField(default=0), + ), + ] diff --git a/django_code/apps/streaming/migrations/0012_alter_streamingredirectdata_betaserieshowid.py b/django_code/apps/streaming/migrations/0012_alter_streamingredirectdata_betaserieshowid.py new file mode 100644 index 0000000..b2232ac --- /dev/null +++ b/django_code/apps/streaming/migrations/0012_alter_streamingredirectdata_betaserieshowid.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.30 on 2026-08-25 15:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('streaming', '0011_streamingredirectdata_betaserieshowid'), + ] + + operations = [ + migrations.AlterField( + model_name='streamingredirectdata', + name='betaserieShowId', + field=models.IntegerField(blank=True, null=True), + ), + ] diff --git a/django_code/apps/streaming/models.py b/django_code/apps/streaming/models.py index 640f865..3256e10 100644 --- a/django_code/apps/streaming/models.py +++ b/django_code/apps/streaming/models.py @@ -1,7 +1,10 @@ from django.db import models +from apps.betaserie.utils import betaserieUtils + + # Create your models here. -class streamingData(models.Model): +class StreamingSiteTestingData(models.Model): url = models.CharField(max_length=1000) addedDate = models.DateField('Published', blank=True, null=True, auto_now_add=True) status = models.CharField(max_length=1000, blank=True, null=True) @@ -9,3 +12,48 @@ class streamingData(models.Model): class Meta: db_table = 'streaming' + + + + +class StreamingRedirectData(models.Model): + name = models.CharField(primary_key=True,max_length=1000, help_text="Name of the show") + season = models.IntegerField(null=False,default=1) + episode = models.IntegerField(null=False,default=0) + url_example = models.CharField(max_length=1000, help_text="https://www.1shows.org/tv/456-the-simpsons?streaming=true&season=18&episode=5") + prefix = models.CharField(max_length=1000, help_text="https://www.1shows.org/tv/456-the-simpsons?streaming=true&season=",blank=True, null=True) + infix = models.CharField(max_length=1000, help_text="&episode=",blank=True, null=True) + suffix = models.CharField(max_length=1000, help_text="" ,blank=True, null=True) + addedDate = models.DateField('Published', blank=True, null=True, auto_now_add=True) + alias = models.CharField(max_length=1000, null=True,blank=True) + seasonInformation = models.JSONField(default=dict, blank=True) + betaserieShowId = models.IntegerField(null=True,blank=True) + randomViewing = models.BooleanField(default=False) + + def sanitize(self, name): + return name.replace(" ", "") + + def season_information(self, serie_name): + betaserie = betaserieUtils() + print(serie_name) + print(betaserie.identify_serie(serie_name)) + return betaserie.series_information(betaserie.identify_serie(serie_name))[0] + + def betaserie_show_id(self,serie_name): + betaserie = betaserieUtils() + print(serie_name) + print(betaserie.identify_serie(serie_name)) + return betaserie.identify_serie(serie_name) + + + def save(self, *args, **kwargs): + if not self.seasonInformation : + self.seasonInformation = self.season_information(self.name) + if not self.alias: + self.alias = self.sanitize(self.name) + if not self.betaserieShowId: + self.betaserieShowId = self.betaserie_show_id(self.name) + super().save(*args, **kwargs) + + class Meta: + db_table = 'StreamingRedirect' \ No newline at end of file diff --git a/django_code/apps/streaming/utils.py b/django_code/apps/streaming/utils.py index b873d5f..40f31c4 100644 --- a/django_code/apps/streaming/utils.py +++ b/django_code/apps/streaming/utils.py @@ -35,4 +35,24 @@ def test_website(url_website,bool_proxy=False): except Exception as err: print(f"{type(err).__name__} was raised: {err}") status = "exception not targeted" - return status \ No newline at end of file + return status + + +def randomEpisode(): + return 0,0 + +def followingEpisode(season,episode,seasonInformation): + lastEpisode = False + #check if the episode is the last one of the season + if (episode < seasonInformation[season]['episodes']): + #the current episode is not the + episode += 1 + + #check if the season is the last one + elif((season+1) < (len(seasonInformation)-1)): + season += 1 + episode = 1 + else: + print("You watched the last episode of the serie") + lastEpisode = True + return season,episode,lastEpisode \ No newline at end of file diff --git a/django_code/apps/streaming/views.py b/django_code/apps/streaming/views.py index 91ea44a..1c56fdc 100644 --- a/django_code/apps/streaming/views.py +++ b/django_code/apps/streaming/views.py @@ -1,3 +1,76 @@ -from django.shortcuts import render +from django.http import HttpResponse +from django.shortcuts import redirect +from six import print_ +from .models import StreamingRedirectData +from .utils import randomEpisode,followingEpisode +from apps.betaserie.utils import betaserieUtils + +betaserie = betaserieUtils() + # Create your views here. +def hello(request): + return HttpResponse('

Hello streaming view!

') + + +def streamingRedirect(request,alias): + streaming_object = StreamingRedirectData.objects.filter(alias=alias) + + episode = streaming_object.values('episode')[0]['episode'] + season = streaming_object.values('season')[0]['season'] + seasonInformation = streaming_object.values('seasonInformation')[0]['seasonInformation'] + + url_prefix = streaming_object.values('prefix')[0]['prefix'] + url_infix = streaming_object.values('infix')[0]['infix'] + url_suffix = streaming_object.values('suffix')[0]['suffix'] or '' + + betaserieShowId = streaming_object.values('betaserieShowId')[0]['betaserieShowId'] + + print(url_prefix) + + print(season) + print(episode) + + + print(seasonInformation) + + value = str(streaming_object.values('url_example')) + print(value) + + url_example = str(streaming_object.values('url_example')[0]['url_example']) + print(url_example) + + randomViewing =str(streaming_object.values('randomViewing')[0]['randomViewing']) + print(randomViewing) + + if (randomViewing == False): + print('show set to random') + season,episode = randomEpisode() + else: + print('show set to following episode') + season,episode,lastEpisode = followingEpisode(season,episode,seasonInformation) + if (lastEpisode): + return HttpResponse('

You already watched the last episode of the serie!

') + + print(season) + print(episode) + + + url_generated = str(url_prefix)+str(season)+str(url_infix)+str(episode)+str(url_suffix) + print(url_generated) + + + #append the data into the model + StreamingRedirectData.objects.filter(alias=alias).update(season=season,episode=episode) + + #### mark as view in betaserie + + #mark episode as seen in betaserie + episode_number = "S"+str(season)+"E"+str(episode) + + episode_id = betaserie.identify_episode(betaserieShowId,episode_number) + + betaserie.mark_episodes_watched(episode_id) + + + return redirect(str(url_generated)) \ No newline at end of file diff --git a/django_code/core/settings.py b/django_code/core/settings.py index 7ff2b56..ca97e09 100644 --- a/django_code/core/settings.py +++ b/django_code/core/settings.py @@ -163,6 +163,7 @@ DATABASES = { 'HOST': os.environ.get('DB_HOST'), 'PORT': os.environ.get('DB_PORT'), }, + } DATABASE_ROUTERS = ['core.routers.ProjectDatabaseRouter'] #DATABASE_ROUTERS = [] diff --git a/django_code/core/urls.py b/django_code/core/urls.py index 25d64ce..fbfaefd 100644 --- a/django_code/core/urls.py +++ b/django_code/core/urls.py @@ -27,6 +27,7 @@ from apps.stash_management import apps as stashapp from apps.stash_management import views as stashview from apps.website_redirection import views as website_redirectionapp from apps.podcast_aggregator import views as podcast_views +from apps.streaming import views as streaming_views urlpatterns = [ @@ -93,4 +94,9 @@ urlpatterns = [ ################### cloudmanager ################### path('podcast/', podcast_views.execute_podcast), + ################### streaming ################### + path('streaming/', streaming_views.hello), + path('streaming/go/', streaming_views.streamingRedirect), + + ] diff --git a/infra/production/entrypoint.sh b/infra/production/entrypoint.sh index f501c9e..828b5c1 100644 --- a/infra/production/entrypoint.sh +++ b/infra/production/entrypoint.sh @@ -9,6 +9,7 @@ python django_code/manage.py makemigrations telegram python django_code/manage.py makemigrations podcast python django_code/manage.py makemigrations streaming + python django_code/manage.py migrate python django_code/manage.py migrate --database=cloudmanager_db python django_code/manage.py migrate --database=simpsons_db @@ -19,5 +20,6 @@ python django_code/manage.py migrate --database=podcast_db python django_code/manage.py migrate --database=streaming_db + python django_code/manage.py runserver "0.0.0.0:8000" diff --git a/requirements.txt b/requirements.txt index 6bd0bf5..137d398 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,4 +19,3 @@ bitwarden_sdk xmltodict whitenoise djangoql -python-json-logger