Initial commit
This commit is contained in:
commit
2baf022a0c
25 changed files with 50432 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
venv/
|
||||||
|
*.pyc
|
||||||
|
__pycache__/
|
0
frontend/__init__.py
Normal file
0
frontend/__init__.py
Normal file
3
frontend/admin.py
Normal file
3
frontend/admin.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
6
frontend/apps.py
Normal file
6
frontend/apps.py
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class FrontendConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'frontend'
|
0
frontend/migrations/__init__.py
Normal file
0
frontend/migrations/__init__.py
Normal file
3
frontend/models.py
Normal file
3
frontend/models.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
31
frontend/static.py
Normal file
31
frontend/static.py
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
STATION_URLS = {
|
||||||
|
"orf1": "https://orf1.mdn.ors.at/out/u/orf1/drmqxb/",
|
||||||
|
"orf2": "https://orf2.mdn.ors.at/out/u/orf2/drmqxb/",
|
||||||
|
"orf3": "https://orf3.mdn.ors.at/out/u/orf3/qxb/",
|
||||||
|
"orf2e": "https://orf2e.mdn.ors.at/out/u/orf2e/drmqxb/",
|
||||||
|
"orf2b": "https://orf2b.mdn.ors.at/out/u/orf2b/qxb/",
|
||||||
|
"orf2k": "https://orf2k.mdn.ors.at/out/u/orf2k/qxb/",
|
||||||
|
"orf2n": "https://orf2o.mdn.ors.at/out/u/orf2n/qxb/",
|
||||||
|
"orf2o": "https://orf2o.mdn.ors.at/out/u/orf2n/qxb/",
|
||||||
|
"orf2s": "https://orf2s.mdn.ors.at/out/u/orf2s/qxb/",
|
||||||
|
"orf2stmk": "https://orf2stmk.mdn.ors.at/out/u/orf2stmk/qxb/",
|
||||||
|
"orf2t": "https://orf2s.mdn.ors.at/out/u/orf2s/qxb/",
|
||||||
|
"orf2v": "https://orf2v.mdn.ors.at/out/u/orf2v/qxb/",
|
||||||
|
"orf2w": "https://orf2w.mdn.ors.at/out/u/orf2w/qxb/",
|
||||||
|
}
|
||||||
|
|
||||||
|
STATION_NAMES = {
|
||||||
|
"orf1": "ORF 1 (not working)",
|
||||||
|
"orf2": "ORF 2 (not working)",
|
||||||
|
"orf3": "ORF III",
|
||||||
|
"orf2e": "ORF 2 Europe",
|
||||||
|
"orf2b": "ORF 2 Burgenland",
|
||||||
|
"orf2k": "ORF 2 Kärnten",
|
||||||
|
"orf2n": "ORF 2 Niederösterreich",
|
||||||
|
"orf2o": "ORF 2 Oberösterreich",
|
||||||
|
"orf2s": "ORF 2 Salzburg",
|
||||||
|
"orf2stmk": "ORF 2 Steiermark",
|
||||||
|
"orf2t": "ORF 2 Tirol",
|
||||||
|
"orf2v": "ORF 2 Vorarlberg",
|
||||||
|
"orf2w": "ORF 2 Wien",
|
||||||
|
}
|
0
frontend/templatetags/__init__.py
Normal file
0
frontend/templatetags/__init__.py
Normal file
10
frontend/templatetags/stations.py
Normal file
10
frontend/templatetags/stations.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
from django.template import Library
|
||||||
|
|
||||||
|
from ..static import STATION_URLS
|
||||||
|
|
||||||
|
|
||||||
|
register = Library()
|
||||||
|
|
||||||
|
@register.simple_tag
|
||||||
|
def stationurl(station):
|
||||||
|
return STATION_URLS[station]
|
3
frontend/tests.py
Normal file
3
frontend/tests.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
9
frontend/urls.py
Normal file
9
frontend/urls.py
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
from .views import LiveStationView, StationProxyView, IndexView
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path("station/<slug:station>", LiveStationView.as_view(), name="stationlive"),
|
||||||
|
path("station/<slug:station>/<str:filename>", StationProxyView.as_view(), name="stationproxy"),
|
||||||
|
path("", IndexView.as_view(), name="index"),
|
||||||
|
]
|
44
frontend/views.py
Normal file
44
frontend/views.py
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
from django.views.generic import TemplateView, View
|
||||||
|
from django.http import HttpResponse
|
||||||
|
|
||||||
|
from urllib.request import urlopen
|
||||||
|
|
||||||
|
from .static import STATION_URLS, STATION_NAMES
|
||||||
|
|
||||||
|
|
||||||
|
class LiveStationView(TemplateView):
|
||||||
|
template_name = "frontend/station.html"
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context["station"] = self.kwargs["station"]
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class StationProxyView(View):
|
||||||
|
def get_station(self):
|
||||||
|
return self.kwargs["station"]
|
||||||
|
|
||||||
|
def get_filename(self):
|
||||||
|
return self.kwargs["filename"]
|
||||||
|
|
||||||
|
def download_file(self):
|
||||||
|
url = STATION_URLS[self.get_station()] + self.get_filename()
|
||||||
|
return urlopen(url).read()
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
response = self.download_file()
|
||||||
|
|
||||||
|
if self.get_filename().endswith(".m3u8"):
|
||||||
|
response = response.replace(b"skd", b"https")
|
||||||
|
|
||||||
|
return HttpResponse(response)
|
||||||
|
|
||||||
|
|
||||||
|
class IndexView(TemplateView):
|
||||||
|
template_name = "frontend/index.html"
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context["stations"] = STATION_NAMES
|
||||||
|
return context
|
22
manage.py
Executable file
22
manage.py
Executable file
|
@ -0,0 +1,22 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
"""Django's command-line utility for administrative tasks."""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Run administrative tasks."""
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'orfplayer.settings')
|
||||||
|
try:
|
||||||
|
from django.core.management import execute_from_command_line
|
||||||
|
except ImportError as exc:
|
||||||
|
raise ImportError(
|
||||||
|
"Couldn't import Django. Are you sure it's installed and "
|
||||||
|
"available on your PYTHONPATH environment variable? Did you "
|
||||||
|
"forget to activate a virtual environment?"
|
||||||
|
) from exc
|
||||||
|
execute_from_command_line(sys.argv)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
0
orfplayer/__init__.py
Normal file
0
orfplayer/__init__.py
Normal file
16
orfplayer/asgi.py
Normal file
16
orfplayer/asgi.py
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
"""
|
||||||
|
ASGI config for orfplayer project.
|
||||||
|
|
||||||
|
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/4.0/howto/deployment/asgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'orfplayer.settings')
|
||||||
|
|
||||||
|
application = get_asgi_application()
|
61
orfplayer/settings.py
Normal file
61
orfplayer/settings.py
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
DEBUG = True
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = ["*"]
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
'django.contrib.staticfiles',
|
||||||
|
'frontend',
|
||||||
|
]
|
||||||
|
|
||||||
|
MIDDLEWARE = [
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
]
|
||||||
|
|
||||||
|
ROOT_URLCONF = 'orfplayer.urls'
|
||||||
|
|
||||||
|
TEMPLATES = [
|
||||||
|
{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'DIRS': [BASE_DIR / "templates"],
|
||||||
|
'APP_DIRS': False,
|
||||||
|
'OPTIONS': {
|
||||||
|
'context_processors': [
|
||||||
|
'django.template.context_processors.debug',
|
||||||
|
'django.template.context_processors.request',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
WSGI_APPLICATION = 'orfplayer.wsgi.application'
|
||||||
|
|
||||||
|
DATABASES = {}
|
||||||
|
|
||||||
|
|
||||||
|
# Internationalization
|
||||||
|
# https://docs.djangoproject.com/en/4.0/topics/i18n/
|
||||||
|
|
||||||
|
LANGUAGE_CODE = 'de-at'
|
||||||
|
|
||||||
|
TIME_ZONE = 'Europe/Vienna'
|
||||||
|
|
||||||
|
USE_I18N = True
|
||||||
|
|
||||||
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
# https://docs.djangoproject.com/en/4.0/howto/static-files/
|
||||||
|
|
||||||
|
STATIC_URL = 'static/'
|
||||||
|
|
||||||
|
STATICFILES_DIRS = [
|
||||||
|
BASE_DIR / "static",
|
||||||
|
]
|
5
orfplayer/urls.py
Normal file
5
orfplayer/urls.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
from django.urls import path, include
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path("", include("frontend.urls")),
|
||||||
|
]
|
16
orfplayer/wsgi.py
Normal file
16
orfplayer/wsgi.py
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
"""
|
||||||
|
WSGI config for orfplayer project.
|
||||||
|
|
||||||
|
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/4.0/howto/deployment/wsgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'orfplayer.settings')
|
||||||
|
|
||||||
|
application = get_wsgi_application()
|
2
requirements.txt
Normal file
2
requirements.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
django
|
||||||
|
yt-dlp
|
1431
static/vendor/css/video-js.css
vendored
Normal file
1431
static/vendor/css/video-js.css
vendored
Normal file
File diff suppressed because one or more lines are too long
25674
static/vendor/js/video.js
vendored
Normal file
25674
static/vendor/js/video.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
21613
static/vendor/js/videojs-contrib-hls.js
vendored
Normal file
21613
static/vendor/js/videojs-contrib-hls.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
1455
static/vendor/js/videojs-flash.js
vendored
Normal file
1455
static/vendor/js/videojs-flash.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
5
templates/frontend/index.html
Normal file
5
templates/frontend/index.html
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<ul>
|
||||||
|
{% for stationid, stationname in stations.items %}
|
||||||
|
<li><a href="{% url "stationlive" stationid %}">{{ stationname }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
20
templates/frontend/station.html
Normal file
20
templates/frontend/station.html
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{% load static %}
|
||||||
|
{% load stations %}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<link href="{% static "vendor/css/video-js.css" %}" rel="stylesheet">
|
||||||
|
<script src="{% static "vendor/js/video.js" %}"></script>
|
||||||
|
<script src="{% static "vendor/js/videojs-flash.js" %}"></script>
|
||||||
|
<script src="{% static "vendor/js/videojs-contrib-hls.js" %}"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<video crossOrigin="anonymous" class="video-js vjs-default-skin vjs-big-play-centered" data-setup='{"controls": true, "autoplay": true }'>
|
||||||
|
<source src="{% url "stationproxy" station "manifest_6.m3u8" %}" type="application/x-mpegURL">
|
||||||
|
Your browser does not support HTML5 video.
|
||||||
|
</video>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
Loading…
Reference in a new issue