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