Spaces:
Running
Running
Upload 99 files
Browse files- CloudStorage/__init__.py +0 -0
- CloudStorage/__pycache__/__init__.cpython-311.pyc +0 -0
- CloudStorage/__pycache__/__init__.cpython-312.pyc +0 -0
- CloudStorage/__pycache__/__init__.cpython-313.pyc +0 -0
- CloudStorage/__pycache__/__init__.cpython-39.pyc +0 -0
- CloudStorage/__pycache__/settings.cpython-311.pyc +0 -0
- CloudStorage/__pycache__/settings.cpython-312.pyc +0 -0
- CloudStorage/__pycache__/settings.cpython-313.pyc +0 -0
- CloudStorage/__pycache__/settings.cpython-39.pyc +0 -0
- CloudStorage/__pycache__/urls.cpython-311.pyc +0 -0
- CloudStorage/__pycache__/urls.cpython-312.pyc +0 -0
- CloudStorage/__pycache__/urls.cpython-39.pyc +0 -0
- CloudStorage/__pycache__/wsgi.cpython-311.pyc +0 -0
- CloudStorage/__pycache__/wsgi.cpython-312.pyc +0 -0
- CloudStorage/__pycache__/wsgi.cpython-39.pyc +0 -0
- CloudStorage/asgi.py +16 -0
- CloudStorage/settings.py +145 -0
- CloudStorage/urls.py +24 -0
- CloudStorage/wsgi.py +16 -0
- home/__pycache__/__init__.cpython-312.pyc +0 -0
- home/__pycache__/__init__.cpython-313.pyc +0 -0
- home/__pycache__/admin.cpython-312.pyc +0 -0
- home/__pycache__/apps.cpython-312.pyc +0 -0
- home/__pycache__/apps.cpython-313.pyc +0 -0
- home/__pycache__/models.cpython-312.pyc +0 -0
- home/__pycache__/urls.cpython-312.pyc +0 -0
- home/__pycache__/views.cpython-312.pyc +0 -0
- home/migrations/0011_movies_backdrop.py +18 -0
- home/migrations/__pycache__/0001_initial.cpython-312.pyc +0 -0
- home/migrations/__pycache__/0002_rename_data_userdata.cpython-312.pyc +0 -0
- home/migrations/__pycache__/0003_userdata_ip.cpython-312.pyc +0 -0
- home/migrations/__pycache__/0004_ip_address_remove_userdata_ip.cpython-312.pyc +0 -0
- home/migrations/__pycache__/0005_remove_userdata_files.cpython-312.pyc +0 -0
- home/migrations/__pycache__/0006_movies.cpython-312.pyc +0 -0
- home/migrations/__pycache__/0007_movies_uploaded.cpython-312.pyc +0 -0
- home/migrations/__pycache__/0008_movies_casts_movies_country_movies_duration_and_more.cpython-312.pyc +0 -0
- home/migrations/__pycache__/0009_movies_imdbid.cpython-312.pyc +0 -0
- home/migrations/__pycache__/0010_alter_movies_casts_alter_movies_country_and_more.cpython-312.pyc +0 -0
- home/migrations/__pycache__/0011_movies_backdrop.cpython-312.pyc +0 -0
- home/migrations/__pycache__/__init__.cpython-312.pyc +0 -0
- home/models.py +1 -0
- home/movies.json +0 -0
- home/urls.py +23 -21
- home/views.py +482 -327
- templates/godMode.html +77 -77
- templates/movie.html +51 -72
- templates/movieDetail.html +199 -156
CloudStorage/__init__.py
ADDED
File without changes
|
CloudStorage/__pycache__/__init__.cpython-311.pyc
ADDED
Binary file (177 Bytes). View file
|
|
CloudStorage/__pycache__/__init__.cpython-312.pyc
ADDED
Binary file (144 Bytes). View file
|
|
CloudStorage/__pycache__/__init__.cpython-313.pyc
ADDED
Binary file (144 Bytes). View file
|
|
CloudStorage/__pycache__/__init__.cpython-39.pyc
ADDED
Binary file (156 Bytes). View file
|
|
CloudStorage/__pycache__/settings.cpython-311.pyc
ADDED
Binary file (3.1 kB). View file
|
|
CloudStorage/__pycache__/settings.cpython-312.pyc
ADDED
Binary file (3.01 kB). View file
|
|
CloudStorage/__pycache__/settings.cpython-313.pyc
ADDED
Binary file (3.01 kB). View file
|
|
CloudStorage/__pycache__/settings.cpython-39.pyc
ADDED
Binary file (2.88 kB). View file
|
|
CloudStorage/__pycache__/urls.cpython-311.pyc
ADDED
Binary file (1.41 kB). View file
|
|
CloudStorage/__pycache__/urls.cpython-312.pyc
ADDED
Binary file (1.31 kB). View file
|
|
CloudStorage/__pycache__/urls.cpython-39.pyc
ADDED
Binary file (1.08 kB). View file
|
|
CloudStorage/__pycache__/wsgi.cpython-311.pyc
ADDED
Binary file (709 Bytes). View file
|
|
CloudStorage/__pycache__/wsgi.cpython-312.pyc
ADDED
Binary file (642 Bytes). View file
|
|
CloudStorage/__pycache__/wsgi.cpython-39.pyc
ADDED
Binary file (569 Bytes). View file
|
|
CloudStorage/asgi.py
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
ASGI config for CloudStorage project.
|
3 |
+
|
4 |
+
It exposes the ASGI callable as a module-level variable named ``application``.
|
5 |
+
|
6 |
+
For more information on this file, see
|
7 |
+
https://docs.djangoproject.com/en/4.0/howto/deployment/asgi/
|
8 |
+
"""
|
9 |
+
|
10 |
+
import os
|
11 |
+
|
12 |
+
from django.core.asgi import get_asgi_application
|
13 |
+
|
14 |
+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CloudStorage.settings')
|
15 |
+
|
16 |
+
application = get_asgi_application()
|
CloudStorage/settings.py
ADDED
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Django settings for CloudStorage project.
|
3 |
+
|
4 |
+
Generated by 'django-admin startproject' using Django 4.0.4.
|
5 |
+
|
6 |
+
For more information on this file, see
|
7 |
+
https://docs.djangoproject.com/en/4.0/topics/settings/
|
8 |
+
|
9 |
+
For the full list of settings and their values, see
|
10 |
+
https://docs.djangoproject.com/en/4.0/ref/settings/
|
11 |
+
"""
|
12 |
+
|
13 |
+
from pathlib import Path
|
14 |
+
import os
|
15 |
+
|
16 |
+
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
17 |
+
BASE_DIR = Path(__file__).resolve().parent.parent
|
18 |
+
|
19 |
+
|
20 |
+
# Quick-start development settings - unsuitable for production
|
21 |
+
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
|
22 |
+
|
23 |
+
# SECURITY WARNING: keep the secret key used in production secret!
|
24 |
+
SECRET_KEY = 'django-insecure-f221fh+#lk4ul5x@gk7bm2x5f&+u3uhu+t-(bri%t(uh!z6gf#'
|
25 |
+
|
26 |
+
# SECURITY WARNING: don't run with debug turned on in production!
|
27 |
+
DEBUG = True
|
28 |
+
X_FRAME_OPTIONS = 'ALLOWALL'
|
29 |
+
|
30 |
+
ALLOWED_HOSTS = ['127.0.0.1', 'thejagstudio-cloudstorage.hf.space']
|
31 |
+
CORS_ALLOWED_ORIGINS = [
|
32 |
+
'https://thejagstudio-cloudstorage.hf.space',
|
33 |
+
'https://huggingface.co'
|
34 |
+
]
|
35 |
+
CORS_ALLOW_ALL_ORIGINS = True
|
36 |
+
|
37 |
+
|
38 |
+
# Application definition
|
39 |
+
|
40 |
+
INSTALLED_APPS = [
|
41 |
+
'django.contrib.admin',
|
42 |
+
'django.contrib.auth',
|
43 |
+
'django.contrib.contenttypes',
|
44 |
+
'django.contrib.sessions',
|
45 |
+
'django.contrib.messages',
|
46 |
+
'django.contrib.staticfiles',
|
47 |
+
'home',
|
48 |
+
'corsheaders'
|
49 |
+
]
|
50 |
+
|
51 |
+
MIDDLEWARE = [
|
52 |
+
'django.middleware.security.SecurityMiddleware',
|
53 |
+
'django.contrib.sessions.middleware.SessionMiddleware',
|
54 |
+
'django.middleware.common.CommonMiddleware',
|
55 |
+
'django.middleware.csrf.CsrfViewMiddleware',
|
56 |
+
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
57 |
+
'django.contrib.messages.middleware.MessageMiddleware',
|
58 |
+
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
59 |
+
]
|
60 |
+
|
61 |
+
ROOT_URLCONF = 'CloudStorage.urls'
|
62 |
+
|
63 |
+
TEMPLATES = [
|
64 |
+
{
|
65 |
+
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
66 |
+
'DIRS': ['templates'],
|
67 |
+
'APP_DIRS': True,
|
68 |
+
'OPTIONS': {
|
69 |
+
'context_processors': [
|
70 |
+
'django.template.context_processors.debug',
|
71 |
+
'django.template.context_processors.request',
|
72 |
+
'django.contrib.auth.context_processors.auth',
|
73 |
+
'django.contrib.messages.context_processors.messages',
|
74 |
+
],
|
75 |
+
},
|
76 |
+
},
|
77 |
+
]
|
78 |
+
|
79 |
+
WSGI_APPLICATION = 'CloudStorage.wsgi.application'
|
80 |
+
|
81 |
+
|
82 |
+
# Database
|
83 |
+
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
|
84 |
+
|
85 |
+
DATABASES = {
|
86 |
+
'default': {
|
87 |
+
'ENGINE': 'django.db.backends.postgresql',
|
88 |
+
'NAME': 'postgres',
|
89 |
+
'USER': 'postgres.ptkwerplskfglvudefxq',
|
90 |
+
'PORT': 5432,
|
91 |
+
'PASSWORD': 'KBIPUBbDVDdiftJf',
|
92 |
+
'HOST': 'aws-0-us-east-2.pooler.supabase.com',
|
93 |
+
}
|
94 |
+
}
|
95 |
+
# DATABASES = {
|
96 |
+
# 'default': {
|
97 |
+
# 'ENGINE': 'django.db.backends.sqlite3',
|
98 |
+
# 'NAME': BASE_DIR / 'db.sqlite3',
|
99 |
+
# }
|
100 |
+
# }
|
101 |
+
|
102 |
+
|
103 |
+
# Password validation
|
104 |
+
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
|
105 |
+
|
106 |
+
AUTH_PASSWORD_VALIDATORS = [
|
107 |
+
{
|
108 |
+
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
109 |
+
},
|
110 |
+
{
|
111 |
+
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
112 |
+
},
|
113 |
+
{
|
114 |
+
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
115 |
+
},
|
116 |
+
{
|
117 |
+
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
118 |
+
},
|
119 |
+
]
|
120 |
+
|
121 |
+
|
122 |
+
# Internationalization
|
123 |
+
# https://docs.djangoproject.com/en/4.0/topics/i18n/
|
124 |
+
|
125 |
+
LANGUAGE_CODE = 'en-us'
|
126 |
+
|
127 |
+
TIME_ZONE = 'UTC'
|
128 |
+
|
129 |
+
USE_I18N = True
|
130 |
+
|
131 |
+
USE_TZ = True
|
132 |
+
|
133 |
+
|
134 |
+
# Static files (CSS, JavaScript, Images)
|
135 |
+
# https://docs.djangoproject.com/en/4.0/howto/static-files/
|
136 |
+
|
137 |
+
STATIC_URL = '/static/'
|
138 |
+
STATICFILES_DIRS = [
|
139 |
+
BASE_DIR / "static",
|
140 |
+
]
|
141 |
+
|
142 |
+
# Default primary key field type
|
143 |
+
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
|
144 |
+
|
145 |
+
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
CloudStorage/urls.py
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""CloudStorage URL Configuration
|
2 |
+
|
3 |
+
The `urlpatterns` list routes URLs to views. For more information please see:
|
4 |
+
https://docs.djangoproject.com/en/4.0/topics/http/urls/
|
5 |
+
Examples:
|
6 |
+
Function views
|
7 |
+
1. Add an import: from my_app import views
|
8 |
+
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
9 |
+
Class-based views
|
10 |
+
1. Add an import: from other_app.views import Home
|
11 |
+
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
12 |
+
Including another URLconf
|
13 |
+
1. Import the include() function: from django.urls import include, path
|
14 |
+
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
15 |
+
"""
|
16 |
+
from django.contrib import admin
|
17 |
+
from django.urls import path, include
|
18 |
+
from django.conf import settings
|
19 |
+
from django.conf.urls.static import static
|
20 |
+
|
21 |
+
urlpatterns = [
|
22 |
+
path('admin/', admin.site.urls),
|
23 |
+
path('', include('home.urls')),
|
24 |
+
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
CloudStorage/wsgi.py
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
WSGI config for CloudStorage project.
|
3 |
+
|
4 |
+
It exposes the WSGI callable as a module-level variable named ``application``.
|
5 |
+
|
6 |
+
For more information on this file, see
|
7 |
+
https://docs.djangoproject.com/en/4.0/howto/deployment/wsgi/
|
8 |
+
"""
|
9 |
+
|
10 |
+
import os
|
11 |
+
|
12 |
+
from django.core.wsgi import get_wsgi_application
|
13 |
+
|
14 |
+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CloudStorage.settings')
|
15 |
+
|
16 |
+
application = get_wsgi_application()
|
home/__pycache__/__init__.cpython-312.pyc
ADDED
Binary file (136 Bytes). View file
|
|
home/__pycache__/__init__.cpython-313.pyc
ADDED
Binary file (136 Bytes). View file
|
|
home/__pycache__/admin.cpython-312.pyc
ADDED
Binary file (609 Bytes). View file
|
|
home/__pycache__/apps.cpython-312.pyc
ADDED
Binary file (438 Bytes). View file
|
|
home/__pycache__/apps.cpython-313.pyc
ADDED
Binary file (496 Bytes). View file
|
|
home/__pycache__/models.cpython-312.pyc
ADDED
Binary file (2.35 kB). View file
|
|
home/__pycache__/urls.cpython-312.pyc
ADDED
Binary file (1.78 kB). View file
|
|
home/__pycache__/views.cpython-312.pyc
ADDED
Binary file (30 kB). View file
|
|
home/migrations/0011_movies_backdrop.py
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Generated by Django 5.0.2 on 2025-06-06 17:07
|
2 |
+
|
3 |
+
from django.db import migrations, models
|
4 |
+
|
5 |
+
|
6 |
+
class Migration(migrations.Migration):
|
7 |
+
|
8 |
+
dependencies = [
|
9 |
+
("home", "0010_alter_movies_casts_alter_movies_country_and_more"),
|
10 |
+
]
|
11 |
+
|
12 |
+
operations = [
|
13 |
+
migrations.AddField(
|
14 |
+
model_name="movies",
|
15 |
+
name="backdrop",
|
16 |
+
field=models.CharField(default="", max_length=1000, null=True),
|
17 |
+
),
|
18 |
+
]
|
home/migrations/__pycache__/0001_initial.cpython-312.pyc
ADDED
Binary file (1.4 kB). View file
|
|
home/migrations/__pycache__/0002_rename_data_userdata.cpython-312.pyc
ADDED
Binary file (774 Bytes). View file
|
|
home/migrations/__pycache__/0003_userdata_ip.cpython-312.pyc
ADDED
Binary file (732 Bytes). View file
|
|
home/migrations/__pycache__/0004_ip_address_remove_userdata_ip.cpython-312.pyc
ADDED
Binary file (1.01 kB). View file
|
|
home/migrations/__pycache__/0005_remove_userdata_files.cpython-312.pyc
ADDED
Binary file (629 Bytes). View file
|
|
home/migrations/__pycache__/0006_movies.cpython-312.pyc
ADDED
Binary file (1.1 kB). View file
|
|
home/migrations/__pycache__/0007_movies_uploaded.cpython-312.pyc
ADDED
Binary file (705 Bytes). View file
|
|
home/migrations/__pycache__/0008_movies_casts_movies_country_movies_duration_and_more.cpython-312.pyc
ADDED
Binary file (1.79 kB). View file
|
|
home/migrations/__pycache__/0009_movies_imdbid.cpython-312.pyc
ADDED
Binary file (766 Bytes). View file
|
|
home/migrations/__pycache__/0010_alter_movies_casts_alter_movies_country_and_more.cpython-312.pyc
ADDED
Binary file (2.64 kB). View file
|
|
home/migrations/__pycache__/0011_movies_backdrop.cpython-312.pyc
ADDED
Binary file (780 Bytes). View file
|
|
home/migrations/__pycache__/__init__.cpython-312.pyc
ADDED
Binary file (147 Bytes). View file
|
|
home/models.py
CHANGED
@@ -14,6 +14,7 @@ class ip_address(models.Model):
|
|
14 |
class movies(models.Model):
|
15 |
movie = models.CharField(max_length=1000, null=True)
|
16 |
poster = models.CharField(max_length=1000, default="", null=True)
|
|
|
17 |
trailer = models.CharField(max_length=1000, default="", null=True)
|
18 |
description = models.CharField(max_length=1000, default="", null=True)
|
19 |
Released = models.CharField(max_length=1000, default="", null=True)
|
|
|
14 |
class movies(models.Model):
|
15 |
movie = models.CharField(max_length=1000, null=True)
|
16 |
poster = models.CharField(max_length=1000, default="", null=True)
|
17 |
+
backdrop = models.CharField(max_length=1000, default="", null=True)
|
18 |
trailer = models.CharField(max_length=1000, default="", null=True)
|
19 |
description = models.CharField(max_length=1000, default="", null=True)
|
20 |
Released = models.CharField(max_length=1000, default="", null=True)
|
home/movies.json
ADDED
The diff for this file is too large to render.
See raw diff
|
|
home/urls.py
CHANGED
@@ -1,21 +1,23 @@
|
|
1 |
-
from django.urls import path, re_path
|
2 |
-
from . import views
|
3 |
-
|
4 |
-
urlpatterns = [
|
5 |
-
path('', views.index, name="index"),
|
6 |
-
path('login/', views.user_login, name="user_login"),
|
7 |
-
path('signup/', views.sign_up, name="sign_up"),
|
8 |
-
path('logout/', views.user_logout, name="user_logout"),
|
9 |
-
path('upload/', views.upload, name="upload"),
|
10 |
-
path('uploader/', views.uploader, name="uploader"),
|
11 |
-
path('uploaderAI/', views.uploaderAI, name="uploaderAI"),
|
12 |
-
path('list/', views.list, name="list"),
|
13 |
-
path('list/<str:id>/', views.folder_list, name="folder_list"),
|
14 |
-
path('deleteFile/', views.deleteFile, name="deleteFile"),
|
15 |
-
path('renameFile/', views.renameFile, name="renameFile"),
|
16 |
-
path('ip/', views.ipGetter, name="ipGetter"),
|
17 |
-
path('godmode/', views.godMode, name="godMode"),
|
18 |
-
path('movieDownloader/', views.movieDownloader, name="movieDownloader"),
|
19 |
-
path('movie/', views.movie, name="movie"),
|
20 |
-
path('movie/<str:id>', views.movieDetail, name="movieDetail"),
|
21 |
-
|
|
|
|
|
|
1 |
+
from django.urls import path, re_path
|
2 |
+
from . import views
|
3 |
+
|
4 |
+
urlpatterns = [
|
5 |
+
path('', views.index, name="index"),
|
6 |
+
path('login/', views.user_login, name="user_login"),
|
7 |
+
path('signup/', views.sign_up, name="sign_up"),
|
8 |
+
path('logout/', views.user_logout, name="user_logout"),
|
9 |
+
path('upload/', views.upload, name="upload"),
|
10 |
+
path('uploader/', views.uploader, name="uploader"),
|
11 |
+
path('uploaderAI/', views.uploaderAI, name="uploaderAI"),
|
12 |
+
path('list/', views.list, name="list"),
|
13 |
+
path('list/<str:id>/', views.folder_list, name="folder_list"),
|
14 |
+
path('deleteFile/', views.deleteFile, name="deleteFile"),
|
15 |
+
path('renameFile/', views.renameFile, name="renameFile"),
|
16 |
+
path('ip/', views.ipGetter, name="ipGetter"),
|
17 |
+
path('godmode/', views.godMode, name="godMode"),
|
18 |
+
path('movieDownloader/', views.movieDownloader, name="movieDownloader"),
|
19 |
+
path('movie/', views.movie, name="movie"),
|
20 |
+
path('movie/<str:id>', views.movieDetail, name="movieDetail"),
|
21 |
+
path('movieLoader/', views.movieLoader, name="movieLoader"),
|
22 |
+
path('movieInputer/', views.movieInputer, name="movieInputer"),
|
23 |
+
]
|
home/views.py
CHANGED
@@ -1,327 +1,482 @@
|
|
1 |
-
from django.shortcuts import render, redirect, HttpResponse
|
2 |
-
from django.contrib.auth import authenticate, login, logout
|
3 |
-
from django.contrib import messages
|
4 |
-
from django.contrib.auth.decorators import login_required
|
5 |
-
from django.contrib.auth.models import User
|
6 |
-
import json
|
7 |
-
from .models import Userdata, ip_address, movies
|
8 |
-
import threading
|
9 |
-
from django.conf import settings
|
10 |
-
from django.views.decorators.csrf import csrf_exempt, csrf_protect
|
11 |
-
from django.core.mail import send_mail
|
12 |
-
import os
|
13 |
-
from pydrive.auth import GoogleAuth
|
14 |
-
from pydrive.drive import GoogleDrive
|
15 |
-
import requests
|
16 |
-
import geocoder
|
17 |
-
import folium
|
18 |
-
from oauth2client import client
|
19 |
-
import time
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
file1
|
35 |
-
file1.
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
context
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from django.shortcuts import render, redirect, HttpResponse
|
2 |
+
from django.contrib.auth import authenticate, login, logout
|
3 |
+
from django.contrib import messages
|
4 |
+
from django.contrib.auth.decorators import login_required
|
5 |
+
from django.contrib.auth.models import User
|
6 |
+
import json
|
7 |
+
from .models import Userdata, ip_address, movies
|
8 |
+
import threading
|
9 |
+
from django.conf import settings
|
10 |
+
from django.views.decorators.csrf import csrf_exempt, csrf_protect
|
11 |
+
from django.core.mail import send_mail
|
12 |
+
import os
|
13 |
+
from pydrive.auth import GoogleAuth
|
14 |
+
from pydrive.drive import GoogleDrive
|
15 |
+
import requests
|
16 |
+
import geocoder
|
17 |
+
import folium
|
18 |
+
from oauth2client import client
|
19 |
+
import time
|
20 |
+
from urllib.parse import urlparse, parse_qs
|
21 |
+
|
22 |
+
gauth = GoogleAuth()
|
23 |
+
content = '{"access_token": "ya29.a0AXooCgtLK5HzYMtRs4R9J7FRZSGR3i5jUkeMeVhGjorlrgq_BupFi8d9upA2skYC5FofxUqo23Nivk_P_Hy8eRn0DWM3deSKoiWMhA3lsy05JVakD0vd2fPRaFOXfRV20jAEGt6ql9yy_0up3Y9z8u9yXZ28IUxRRZAHaCgYKASQSARISFQHGX2MipVyGD4fFFZJWXGvyd-sJnQ0171", "client_id": "895306463817-h14aujg3ohgptue5safg2d81530qs4c3.apps.googleusercontent.com", "client_secret": "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", "refresh_token": "1//0gsu0CorccmScCgYIARAAGBASNwF-L9IrF-TDYDXR_MTQGAGGf4fY4BBBSBUipsz_7c0B6HjmRYZV3uxPVU4CAJjqWoWBm0T4pxA", "token_expiry": "2024-05-25T11:14:56Z", "token_uri": "https://oauth2.googleapis.com/token", "user_agent": null, "revoke_uri": "https://oauth2.googleapis.com/revoke", "id_token": null, "id_token_jwt": null, "token_response": {"access_token": "ya29.a0AXooCgtLK5HzYMtRs4R9J7FRZSGR3i5jUkeMeVhGjorlrgq_BupFi8d9upA2skYC5FofxUqo23Nivk_P_Hy8eRn0DWM3deSKoiWMhA3lsy05JVakD0vd2fPRaFOXfRV20jAEGt6ql9yy_0up3Y9z8u9yXZ28IUxRRZAHaCgYKASQSARISFQHGX2MipVyGD4fFFZJWXGvyd-sJnQ0171", "expires_in": 3599, "refresh_token": "1//0gsu0CorccmScCgYIARAAGBASNwF-L9IrF-TDYDXR_MTQGAGGf4fY4BBBSBUipsz_7c0B6HjmRYZV3uxPVU4CAJjqWoWBm0T4pxA", "scope": "https://www.googleapis.com/auth/drive", "token_type": "Bearer"}, "scopes": ["https://www.googleapis.com/auth/drive"], "token_info_uri": "https://oauth2.googleapis.com/tokeninfo", "invalid": false, "_class": "OAuth2Credentials", "_module": "oauth2client.client"}'
|
24 |
+
gauth.credentials = client.Credentials.new_from_json(content)
|
25 |
+
if gauth.access_token_expired:
|
26 |
+
# Refresh them if expired
|
27 |
+
gauth.Refresh()
|
28 |
+
else:
|
29 |
+
gauth.Authorize()
|
30 |
+
DRIVE = GoogleDrive(gauth)
|
31 |
+
|
32 |
+
|
33 |
+
def GoogleDriveUpload(filename, folder, file):
|
34 |
+
file1 = DRIVE.CreateFile({"title": filename, "parents": [{"id": folder}]})
|
35 |
+
file1.content = file
|
36 |
+
file1.Upload()
|
37 |
+
|
38 |
+
|
39 |
+
@csrf_exempt
|
40 |
+
def index(request):
|
41 |
+
context = {"user": request.user}
|
42 |
+
return render(request, "index.html", context=context)
|
43 |
+
|
44 |
+
|
45 |
+
@csrf_exempt
|
46 |
+
def movie(request):
|
47 |
+
all_movies = movies.objects.all()
|
48 |
+
context = {"movies": all_movies.values()}
|
49 |
+
return render(request, "movie.html", context=context)
|
50 |
+
|
51 |
+
|
52 |
+
@csrf_exempt
|
53 |
+
def movieDetail(request, id):
|
54 |
+
|
55 |
+
# Try to get movie from database
|
56 |
+
movie = movies.objects.filter(tmdbId=id).first()
|
57 |
+
|
58 |
+
# If not found or description is empty, fetch from API and save/update
|
59 |
+
if not movie or not movie.description:
|
60 |
+
url = f"https://api.themoviedb.org/3/movie/{id}?append_to_response=images,reviews,similar,recommendations,credits"
|
61 |
+
headers = {"Authorization": "Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI2MmY0Njg4NDE4ODI2MDNjODc1Y2EwZDMyMzE1NzkyZSIsInN1YiI6IjYyMDBlNmFmMWZkMzZmMDA2NmI5OTczNSIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.mt_t8wqYYl5b8AlDy5npgiF7sbb8ZaDh_XPauDgMt8I", "accept": "application/json"}
|
62 |
+
response = requests.get(url, headers=headers)
|
63 |
+
data = response.json()
|
64 |
+
|
65 |
+
# Prepare fields for model
|
66 |
+
movie_data = {"movie": data.get("title", ""), "poster": data.get("poster_path", ""), "backdrop": data.get("backdrop_path", ""), "trailer": "", "description": data.get("overview", ""), "Released": data.get("release_date", ""), "Genre": ", ".join([g["name"] for g in data.get("genres", [])]), "Casts": ", ".join([c["name"] for c in data.get("credits", {}).get("cast", [])[:5]]), "Duration": str(data.get("runtime", "")), "Country": ", ".join([c["name"] for c in data.get("production_countries", [])]), "Production": ", ".join([c["name"] for c in data.get("production_companies", [])]), "tmdbId": str(data.get("id", "")), "imdbId": data.get("imdb_id", ""), "uploaded": False} # You can extract trailer info from data['videos'] if needed
|
67 |
+
|
68 |
+
if movie:
|
69 |
+
# Update existing movie
|
70 |
+
for key, value in movie_data.items():
|
71 |
+
setattr(movie, key, value)
|
72 |
+
movie.save()
|
73 |
+
else:
|
74 |
+
# Create new movie
|
75 |
+
movie = movies.objects.create(**movie_data)
|
76 |
+
|
77 |
+
# Prepare data for template
|
78 |
+
data = {
|
79 |
+
"movie": movie.movie,
|
80 |
+
"poster": movie.poster,
|
81 |
+
"backdrop": movie.backdrop,
|
82 |
+
"trailer": movie.trailer,
|
83 |
+
"description": movie.description,
|
84 |
+
"Released": movie.Released,
|
85 |
+
"Genre": movie.Genre,
|
86 |
+
"Casts": movie.Casts,
|
87 |
+
"Duration": movie.Duration,
|
88 |
+
"Country": movie.Country,
|
89 |
+
"Production": movie.Production,
|
90 |
+
"tmdbId": movie.tmdbId,
|
91 |
+
"imdbId": movie.imdbId,
|
92 |
+
"torrentLink": movie.torrentLink,
|
93 |
+
"driveLink": movie.driveLink,
|
94 |
+
"uploaded": movie.uploaded,
|
95 |
+
}
|
96 |
+
|
97 |
+
# If driveLink exists, try to get watchLink
|
98 |
+
if movie.driveLink:
|
99 |
+
try:
|
100 |
+
url = "https://drive.google.com/get_video_info?docid=" + movie.driveLink + "&drive_originator_app=303"
|
101 |
+
headers = {"accept": "application/json"}
|
102 |
+
response = requests.get(url, headers=headers)
|
103 |
+
urlData = response.text
|
104 |
+
parsed_url = urlparse("https://drive.google.com/?" + urlData)
|
105 |
+
urlData = json.loads(parse_qs(parsed_url.query)["player_response"][0])
|
106 |
+
data["watchLink"] = urlData
|
107 |
+
except Exception as e:
|
108 |
+
print(e)
|
109 |
+
|
110 |
+
context = {"data": data}
|
111 |
+
return render(request, "movieDetail.html", context=context)
|
112 |
+
|
113 |
+
|
114 |
+
@csrf_exempt
|
115 |
+
def user_login(request):
|
116 |
+
if request.method == "POST":
|
117 |
+
username = request.POST["username"]
|
118 |
+
password = request.POST["password"]
|
119 |
+
user = authenticate(request, username=username, password=password)
|
120 |
+
if user is not None:
|
121 |
+
login(request, user)
|
122 |
+
messages.success(request, ("You have been logged in!"))
|
123 |
+
# print('logged in')
|
124 |
+
return redirect("index")
|
125 |
+
else:
|
126 |
+
messages.success(request, ("Error logging in - please try again."))
|
127 |
+
# print('error logging in')
|
128 |
+
return render(request, "login.html")
|
129 |
+
return render(request, "login.html")
|
130 |
+
|
131 |
+
|
132 |
+
@csrf_exempt
|
133 |
+
def sign_up(request):
|
134 |
+
if request.method == "POST":
|
135 |
+
name = request.POST["name"]
|
136 |
+
email = request.POST["email"]
|
137 |
+
password = request.POST["password"]
|
138 |
+
password2 = request.POST["password1"]
|
139 |
+
user = authenticate(request, email=email, password=password)
|
140 |
+
if user is not None and password == password2:
|
141 |
+
login(request, user)
|
142 |
+
messages.success(request, ("You have been logged in!"))
|
143 |
+
# print('logged in')
|
144 |
+
return redirect("index")
|
145 |
+
elif user is None and password == password2:
|
146 |
+
user = User.objects.create_user(username=email, email=email, password=password, first_name=name)
|
147 |
+
user.save()
|
148 |
+
messages.success(request, ("Created new user!"))
|
149 |
+
login(request, user)
|
150 |
+
folder = "1lrtX-7QPLD4vQl6Dkf65ue4aqgSTl1fZ"
|
151 |
+
new_folder = DRIVE.CreateFile({"title": name, "mimeType": "application/vnd.google-apps.folder", "parents": [{"id": folder}]})
|
152 |
+
new_folder.Upload()
|
153 |
+
new_folder.InsertPermission({"type": "user", "value": email, "role": "writer"})
|
154 |
+
dataObj = Userdata(user_id=request.user, folder=new_folder["id"])
|
155 |
+
dataObj.save()
|
156 |
+
# print('new user created')
|
157 |
+
return redirect("index")
|
158 |
+
else:
|
159 |
+
pass
|
160 |
+
return render(request, "signup.html")
|
161 |
+
|
162 |
+
|
163 |
+
@csrf_exempt
|
164 |
+
@login_required
|
165 |
+
def user_logout(request):
|
166 |
+
logout(request)
|
167 |
+
messages.success(request, ("You have been logged out!"))
|
168 |
+
# print('logged out')
|
169 |
+
return redirect("index")
|
170 |
+
|
171 |
+
|
172 |
+
@csrf_exempt
|
173 |
+
@login_required
|
174 |
+
def upload(request):
|
175 |
+
return render(request, "upload.html")
|
176 |
+
|
177 |
+
|
178 |
+
@csrf_exempt
|
179 |
+
@login_required
|
180 |
+
def uploader(request):
|
181 |
+
global gauth
|
182 |
+
if gauth.access_token_expired:
|
183 |
+
# Refresh them if expired
|
184 |
+
gauth.Refresh()
|
185 |
+
if request.method == "POST":
|
186 |
+
folder = "files/"
|
187 |
+
file = request.FILES["file"]
|
188 |
+
title = request.POST["title"]
|
189 |
+
if title == "":
|
190 |
+
title = file.name
|
191 |
+
if file.name == "":
|
192 |
+
return redirect("/upload/")
|
193 |
+
folder_id = Userdata.objects.get(user_id=request.user).folder
|
194 |
+
thread = threading.Thread(target=GoogleDriveUpload, args=(title, folder_id, file))
|
195 |
+
thread.start()
|
196 |
+
thread.join()
|
197 |
+
return redirect("/upload/")
|
198 |
+
|
199 |
+
|
200 |
+
@csrf_exempt
|
201 |
+
def uploaderAI(request):
|
202 |
+
global gauth
|
203 |
+
if gauth.access_token_expired:
|
204 |
+
# Refresh them if expired
|
205 |
+
gauth.Refresh()
|
206 |
+
if request.method == "POST":
|
207 |
+
try:
|
208 |
+
file = request.FILES["file"]
|
209 |
+
title = request.POST["title"]
|
210 |
+
prompt = request.POST["prompt"]
|
211 |
+
if title == "":
|
212 |
+
title = file.name
|
213 |
+
folder_id = "1Hxpc5aT4xl9Nz1QUQJirJcnaT9J1QrzR"
|
214 |
+
file1 = DRIVE.CreateFile({"title": title, "description": prompt, "parents": [{"id": folder_id}]})
|
215 |
+
file1.content = file
|
216 |
+
file1.Upload()
|
217 |
+
return HttpResponse(json.dumps({"status": "success"}), content_type="application/json")
|
218 |
+
except Exception as e:
|
219 |
+
return HttpResponse(json.dumps({"status": "error", "error": str(e)}), content_type="application/json")
|
220 |
+
|
221 |
+
|
222 |
+
@csrf_exempt
|
223 |
+
@login_required
|
224 |
+
def list(request):
|
225 |
+
global gauth
|
226 |
+
if gauth.access_token_expired:
|
227 |
+
# Refresh them if expired
|
228 |
+
gauth.Refresh()
|
229 |
+
files = []
|
230 |
+
folders = []
|
231 |
+
folder_id = Userdata.objects.get(user_id=request.user).folder
|
232 |
+
list_files = DRIVE.ListFile({"q": "'%s' in parents and trashed=false" % folder_id}).GetList()
|
233 |
+
for file in list_files:
|
234 |
+
if file["title"] != "Deleted" and file["title"] != "DeletedFile" and file["mimeType"] != "application/vnd.google-apps.folder":
|
235 |
+
files.append([file["title"], file["embedLink"], file["id"], file["iconLink"].replace("/16/", "/32/"), file["webContentLink"]])
|
236 |
+
elif file["mimeType"] == "application/vnd.google-apps.folder":
|
237 |
+
folders.append([file["title"], "/list/" + file["id"][::-1]])
|
238 |
+
else:
|
239 |
+
pass
|
240 |
+
context = {"files": files, "folders": folders, "back": False}
|
241 |
+
return render(request, "list.html", context=context)
|
242 |
+
|
243 |
+
|
244 |
+
@csrf_exempt
|
245 |
+
@login_required
|
246 |
+
def folder_list(request, id):
|
247 |
+
global gauth
|
248 |
+
if gauth.access_token_expired:
|
249 |
+
# Refresh them if expired
|
250 |
+
gauth.Refresh()
|
251 |
+
files = []
|
252 |
+
folders = []
|
253 |
+
folder_id = id[::-1] # Userdata.objects.get(user_id=request.user).folder
|
254 |
+
list_files = DRIVE.ListFile({"q": "'%s' in parents and trashed=false" % folder_id}).GetList()
|
255 |
+
for file in list_files:
|
256 |
+
if file["title"] != "Deleted" and file["mimeType"] != "application/vnd.google-apps.folder":
|
257 |
+
files.append([file["title"], file["embedLink"], file["id"], file["iconLink"].replace("/16/", "/32/"), file["webContentLink"]])
|
258 |
+
elif file["mimeType"] == "application/vnd.google-apps.folder":
|
259 |
+
folders.append([file["title"], "/list/" + file["id"][::-1]])
|
260 |
+
else:
|
261 |
+
pass
|
262 |
+
context = {"files": files, "folders": folders, "back": True}
|
263 |
+
return render(request, "list.html", context=context)
|
264 |
+
|
265 |
+
|
266 |
+
@csrf_exempt
|
267 |
+
@login_required
|
268 |
+
def deleteFile(request):
|
269 |
+
global gauth
|
270 |
+
if gauth.access_token_expired:
|
271 |
+
# Refresh them if expired
|
272 |
+
gauth.Refresh()
|
273 |
+
if request.method == "POST":
|
274 |
+
file_id = json.loads(request.body)["file_id"]
|
275 |
+
file = DRIVE.CreateFile({"id": file_id})
|
276 |
+
file.Trash()
|
277 |
+
return HttpResponse(json.dumps({"status": "success"}), content_type="application/json")
|
278 |
+
|
279 |
+
|
280 |
+
@csrf_exempt
|
281 |
+
@login_required
|
282 |
+
def renameFile(request):
|
283 |
+
global gauth
|
284 |
+
if gauth.access_token_expired:
|
285 |
+
# Refresh them if expired
|
286 |
+
gauth.Refresh()
|
287 |
+
if request.method == "POST":
|
288 |
+
data = json.loads(request.body)
|
289 |
+
file_id = data["file_id"]
|
290 |
+
new_name = data["new_name"]
|
291 |
+
file = DRIVE.CreateFile({"id": file_id})
|
292 |
+
file.FetchMetadata(fields="title")
|
293 |
+
file["title"] = new_name
|
294 |
+
file.Upload()
|
295 |
+
return HttpResponse(json.dumps({"status": "success"}), content_type="application/json")
|
296 |
+
|
297 |
+
|
298 |
+
def torrentDownloader(link):
|
299 |
+
import libtorrent as lt
|
300 |
+
|
301 |
+
ses = lt.session()
|
302 |
+
ses.listen_on(6881, 6891)
|
303 |
+
params = {"save_path": "/tmp/", "storage_mode": lt.storage_mode_t(2)}
|
304 |
+
handle = lt.add_magnet_uri(ses, link, params)
|
305 |
+
ses.start_dht()
|
306 |
+
while not handle.has_metadata():
|
307 |
+
time.sleep(1)
|
308 |
+
while handle.status().state != lt.torrent_status.seeding:
|
309 |
+
s = handle.status()
|
310 |
+
state_str = ["queued", "checking", "downloading metadata", "downloading", "finished", "seeding", "allocating"]
|
311 |
+
print("%.2f%% complete (down: %.1f kb/s up: %.1f kB/s peers: %d) %s " % (s.progress * 100, s.download_rate / 1000, s.upload_rate / 1000, s.num_peers, state_str[s.state]))
|
312 |
+
time.sleep(5)
|
313 |
+
with open("/tmp/" + handle.file_name, "rb") as f:
|
314 |
+
file = f.read()
|
315 |
+
file1 = DRIVE.CreateFile({"title": handle.file_name, "parents": [{"id": "1l6oqVFu-Ys025p7PKjIY0Nwgdr08MwlB"}]})
|
316 |
+
file1.content = file
|
317 |
+
file1.Upload()
|
318 |
+
|
319 |
+
print("Uploaded torrent file to drive from link: ", torrent_file.file_name)
|
320 |
+
|
321 |
+
|
322 |
+
@csrf_exempt
|
323 |
+
def movieDownloader(request):
|
324 |
+
if request.method == "POST":
|
325 |
+
data = json.loads(request.body)
|
326 |
+
movie = data["movie"]
|
327 |
+
tmdbId = data["tmdbId"]
|
328 |
+
torrentLink = data["torrentLink"]
|
329 |
+
t1 = threading.Thread(target=torrentDownloader, args=(torrentLink,))
|
330 |
+
t1.start()
|
331 |
+
return HttpResponse(json.dumps({"status": "success"}), content_type="application/json")
|
332 |
+
|
333 |
+
|
334 |
+
def ipGetter(request):
|
335 |
+
ip = request.GET.get("ip", "")
|
336 |
+
ipIn = ip_address.objects.filter(ip=ip).first()
|
337 |
+
if ipIn is None:
|
338 |
+
new_entry = ip_address(ip=ip)
|
339 |
+
new_entry.save()
|
340 |
+
return HttpResponse(json.dumps({"status": "success"}), content_type="application/json")
|
341 |
+
|
342 |
+
|
343 |
+
@login_required
|
344 |
+
def godMode(request):
|
345 |
+
if request.user.is_superuser:
|
346 |
+
ips = ip_address.objects.all()
|
347 |
+
ipF = ips[0].ip
|
348 |
+
g = geocoder.ip(ipF)
|
349 |
+
myAddress = g.latlng
|
350 |
+
my_map1 = folium.Map(location=myAddress, zoom_start=12)
|
351 |
+
for ip in ips:
|
352 |
+
g = geocoder.ip(ip.ip)
|
353 |
+
myAddress = g.latlng
|
354 |
+
folium.Marker(myAddress).add_to(my_map1)
|
355 |
+
my_map1.save("templates/godMode.html")
|
356 |
+
return render(request, "godMode.html")
|
357 |
+
|
358 |
+
|
359 |
+
def movieLoader(request):
|
360 |
+
mainFolderId = "1l6oqVFu-Ys025p7PKjIY0Nwgdr08MwlB"
|
361 |
+
|
362 |
+
# get all files recursively from the main folder
|
363 |
+
def get_all_files(folder_id):
|
364 |
+
files = []
|
365 |
+
list_files = DRIVE.ListFile({"q": f"'{folder_id}' in parents and trashed=false"}).GetList()
|
366 |
+
for file in list_files:
|
367 |
+
if file["mimeType"] == "application/vnd.google-apps.folder":
|
368 |
+
files.extend(get_all_files(file["id"]))
|
369 |
+
else:
|
370 |
+
files.append(file)
|
371 |
+
print(f"Found file: {file['title']} with ID: {file['id']}")
|
372 |
+
return files
|
373 |
+
|
374 |
+
all_files = get_all_files(mainFolderId)
|
375 |
+
with open("home/movies.json", "w") as f:
|
376 |
+
f.write(
|
377 |
+
json.dumps(
|
378 |
+
[
|
379 |
+
{
|
380 |
+
"movie": file["title"],
|
381 |
+
"id": file["id"],
|
382 |
+
"driveLink": file["embedLink"],
|
383 |
+
}
|
384 |
+
for file in all_files
|
385 |
+
if file["mimeType"] != "application/vnd.google-apps.folder"
|
386 |
+
],
|
387 |
+
indent=4,
|
388 |
+
)
|
389 |
+
)
|
390 |
+
return HttpResponse(json.dumps({"status": "success"}), content_type="application/json")
|
391 |
+
|
392 |
+
|
393 |
+
def movieInputer(request):
|
394 |
+
with open("home/movies.json", "r") as f:
|
395 |
+
movies_data = json.load(f)
|
396 |
+
|
397 |
+
def search_movie_by_tmdb_id(name):
|
398 |
+
url = f"https://api.themoviedb.org/3/search/movie?query={name}&include_adult=false&language=en-US&page=1"
|
399 |
+
headers = {"accept": "application/json", "Authorization": "Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI2MmY0Njg4NDE4ODI2MDNjODc1Y2EwZDMyMzE1NzkyZSIsInN1YiI6IjYyMDBlNmFmMWZkMzZmMDA2NmI5OTczNSIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.mt_t8wqYYl5b8AlDy5npgiF7sbb8ZaDh_XPauDgMt8I"}
|
400 |
+
response = requests.get(url, headers=headers)
|
401 |
+
if response.status_code == 200:
|
402 |
+
return response.json()
|
403 |
+
else:
|
404 |
+
print(f"Error fetching data for TMDB ID {name}: {response.status_code}")
|
405 |
+
return None
|
406 |
+
restart = False
|
407 |
+
for movie_data in movies_data:
|
408 |
+
if "mp4" in movie_data["movie"]:
|
409 |
+
|
410 |
+
movie = movies.objects.filter(driveLink=movie_data["id"]).first()
|
411 |
+
if movie is None:
|
412 |
+
if restart:
|
413 |
+
name = movie_data["movie"].replace(".mp4", "")
|
414 |
+
queryName = name.split(".1080p")[0].strip()
|
415 |
+
queryName = queryName.replace(".", " ").replace("(", "").replace(")", "").replace("-", " ").replace("_", " ").replace("'", "").replace(":", "").replace(";", "").replace(" ", " ").replace(" ", " ")
|
416 |
+
print("searching for movie:", queryName)
|
417 |
+
search_result = []
|
418 |
+
max_attempts = 10
|
419 |
+
i = 0
|
420 |
+
while len(search_result) == 0 and i < max_attempts:
|
421 |
+
search_result = search_movie_by_tmdb_id(queryName)["results"]
|
422 |
+
if len(search_result) == 0:
|
423 |
+
queryName = " ".join(queryName.split(" ")[:-2])
|
424 |
+
i += 1
|
425 |
+
if len(search_result) > 0:
|
426 |
+
search_result = search_result[0]
|
427 |
+
# Check if movie exists, update if so, else create
|
428 |
+
movie_obj = movies.objects.filter(driveLink=movie_data["id"]).first()
|
429 |
+
movie_fields = {
|
430 |
+
"movie": search_result["title"],
|
431 |
+
"poster": search_result["poster_path"],
|
432 |
+
"backdrop": search_result["backdrop_path"],
|
433 |
+
"trailer": "",
|
434 |
+
"description": search_result["overview"],
|
435 |
+
"Released": search_result["release_date"],
|
436 |
+
"Genre": ", ".join([g["name"] for g in search_result.get("genres", [])]),
|
437 |
+
"Casts": ", ".join([c["name"] for c in search_result.get("credits", {}).get("cast", [])[:5]]),
|
438 |
+
"Duration": str(search_result.get("runtime", "")),
|
439 |
+
"Country": ", ".join([c["name"] for c in search_result.get("production_countries", [])]),
|
440 |
+
"Production": ", ".join([c["name"] for c in search_result.get("production_companies", [])]),
|
441 |
+
"tmdbId": str(search_result["id"]),
|
442 |
+
"imdbId": search_result.get("imdb_id", ""),
|
443 |
+
"torrentLink": "",
|
444 |
+
"driveLink": movie_data["id"],
|
445 |
+
"uploaded": False,
|
446 |
+
}
|
447 |
+
if movie_obj:
|
448 |
+
for key, value in movie_fields.items():
|
449 |
+
setattr(movie_obj, key, value)
|
450 |
+
movie_obj.save()
|
451 |
+
print(f"Updated movie: {movie_obj.movie} with TMDB ID: {movie_obj.tmdbId}")
|
452 |
+
else:
|
453 |
+
movies.objects.create(**movie_fields)
|
454 |
+
print(f"Added movie: {movie_fields['movie']} with TMDB ID: {movie_fields['tmdbId']}")
|
455 |
+
else:
|
456 |
+
# now just add rest of the movies
|
457 |
+
name = movie_data["movie"].replace(".mp4", "")
|
458 |
+
queryName = name.split(".1080p")[0].strip()
|
459 |
+
queryName = queryName.replace(".", " ").replace("(", "").replace(")", "").replace("-", " ").replace("_", " ").replace("'", "").replace(":", "").replace(";", "").replace(" ", " ").replace(" ", " ")
|
460 |
+
movie =movies()
|
461 |
+
movie.movie = queryName
|
462 |
+
movie.driveLink = movie_data["id"]
|
463 |
+
movie.poster = ""
|
464 |
+
movie.backdrop = ""
|
465 |
+
movie.trailer = ""
|
466 |
+
movie.description = ""
|
467 |
+
movie.Released = ""
|
468 |
+
movie.Genre = ""
|
469 |
+
movie.Casts = ""
|
470 |
+
movie.Duration = ""
|
471 |
+
movie.Country = ""
|
472 |
+
movie.Production = ""
|
473 |
+
movie.tmdbId = ""
|
474 |
+
movie.imdbId = ""
|
475 |
+
movie.torrentLink = ""
|
476 |
+
movie.uploaded = True
|
477 |
+
movie.save()
|
478 |
+
print(f"Added movie: {movie.movie} with TMDB ID: {movie.tmdbId}")
|
479 |
+
|
480 |
+
|
481 |
+
|
482 |
+
return HttpResponse(json.dumps({"status": "success"}), content_type="application/json")
|
templates/godMode.html
CHANGED
@@ -1,78 +1,78 @@
|
|
1 |
-
<!DOCTYPE html>
|
2 |
-
<html>
|
3 |
-
<head>
|
4 |
-
|
5 |
-
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
|
6 |
-
|
7 |
-
<script>
|
8 |
-
L_NO_TOUCH = false;
|
9 |
-
L_DISABLE_3D = false;
|
10 |
-
</script>
|
11 |
-
|
12 |
-
<style>html, body {width: 100%;height: 100%;margin: 0;padding: 0;}</style>
|
13 |
-
<style>#map {position:absolute;top:0;bottom:0;right:0;left:0;}</style>
|
14 |
-
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/leaflet.js"></script>
|
15 |
-
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
16 |
-
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
|
17 |
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.js"></script>
|
18 |
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/leaflet.css"/>
|
19 |
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"/>
|
20 |
-
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"/>
|
21 |
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/[email protected]/css/all.min.css"/>
|
22 |
-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css"/>
|
23 |
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/python-visualization/folium/folium/templates/leaflet.awesome.rotate.min.css"/>
|
24 |
-
|
25 |
-
<meta name="viewport" content="width=device-width,
|
26 |
-
initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
27 |
-
<style>
|
28 |
-
#map_f83a88f12360719b8d5108477e64fbcf {
|
29 |
-
position: relative;
|
30 |
-
width: 100.0%;
|
31 |
-
height: 100.0%;
|
32 |
-
left: 0.0%;
|
33 |
-
top: 0.0%;
|
34 |
-
}
|
35 |
-
.leaflet-container { font-size: 1rem; }
|
36 |
-
</style>
|
37 |
-
|
38 |
-
</head>
|
39 |
-
<body>
|
40 |
-
|
41 |
-
|
42 |
-
<div class="folium-map" id="map_f83a88f12360719b8d5108477e64fbcf" ></div>
|
43 |
-
|
44 |
-
</body>
|
45 |
-
<script>
|
46 |
-
|
47 |
-
|
48 |
-
var map_f83a88f12360719b8d5108477e64fbcf = L.map(
|
49 |
-
"map_f83a88f12360719b8d5108477e64fbcf",
|
50 |
-
{
|
51 |
-
center: [22.2916, 70.7932],
|
52 |
-
crs: L.CRS.EPSG3857,
|
53 |
-
zoom: 12,
|
54 |
-
zoomControl: true,
|
55 |
-
preferCanvas: false,
|
56 |
-
}
|
57 |
-
);
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
var tile_layer_a2e3a495395fce5ac855e71111a3d95c = L.tileLayer(
|
64 |
-
"https://tile.openstreetmap.org/{z}/{x}/{y}.png",
|
65 |
-
{"attribution": "\u0026copy; \u003ca href=\"https://www.openstreetmap.org/copyright\"\u003eOpenStreetMap\u003c/a\u003e contributors", "detectRetina": false, "maxNativeZoom": 19, "maxZoom": 19, "minZoom": 0, "noWrap": false, "opacity": 1, "subdomains": "abc", "tms": false}
|
66 |
-
);
|
67 |
-
|
68 |
-
|
69 |
-
tile_layer_a2e3a495395fce5ac855e71111a3d95c.addTo(map_f83a88f12360719b8d5108477e64fbcf);
|
70 |
-
|
71 |
-
|
72 |
-
var marker_42ec10f3bb57a07b25f279b217982f24 = L.marker(
|
73 |
-
[22.2916, 70.7932],
|
74 |
-
{}
|
75 |
-
).addTo(map_f83a88f12360719b8d5108477e64fbcf);
|
76 |
-
|
77 |
-
</script>
|
78 |
</html>
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html>
|
3 |
+
<head>
|
4 |
+
|
5 |
+
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
|
6 |
+
|
7 |
+
<script>
|
8 |
+
L_NO_TOUCH = false;
|
9 |
+
L_DISABLE_3D = false;
|
10 |
+
</script>
|
11 |
+
|
12 |
+
<style>html, body {width: 100%;height: 100%;margin: 0;padding: 0;}</style>
|
13 |
+
<style>#map {position:absolute;top:0;bottom:0;right:0;left:0;}</style>
|
14 |
+
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/leaflet.js"></script>
|
15 |
+
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
16 |
+
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
|
17 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.js"></script>
|
18 |
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/leaflet.css"/>
|
19 |
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"/>
|
20 |
+
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"/>
|
21 |
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/[email protected]/css/all.min.css"/>
|
22 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css"/>
|
23 |
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/python-visualization/folium/folium/templates/leaflet.awesome.rotate.min.css"/>
|
24 |
+
|
25 |
+
<meta name="viewport" content="width=device-width,
|
26 |
+
initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
27 |
+
<style>
|
28 |
+
#map_f83a88f12360719b8d5108477e64fbcf {
|
29 |
+
position: relative;
|
30 |
+
width: 100.0%;
|
31 |
+
height: 100.0%;
|
32 |
+
left: 0.0%;
|
33 |
+
top: 0.0%;
|
34 |
+
}
|
35 |
+
.leaflet-container { font-size: 1rem; }
|
36 |
+
</style>
|
37 |
+
|
38 |
+
</head>
|
39 |
+
<body>
|
40 |
+
|
41 |
+
|
42 |
+
<div class="folium-map" id="map_f83a88f12360719b8d5108477e64fbcf" ></div>
|
43 |
+
|
44 |
+
</body>
|
45 |
+
<script>
|
46 |
+
|
47 |
+
|
48 |
+
var map_f83a88f12360719b8d5108477e64fbcf = L.map(
|
49 |
+
"map_f83a88f12360719b8d5108477e64fbcf",
|
50 |
+
{
|
51 |
+
center: [22.2916, 70.7932],
|
52 |
+
crs: L.CRS.EPSG3857,
|
53 |
+
zoom: 12,
|
54 |
+
zoomControl: true,
|
55 |
+
preferCanvas: false,
|
56 |
+
}
|
57 |
+
);
|
58 |
+
|
59 |
+
|
60 |
+
|
61 |
+
|
62 |
+
|
63 |
+
var tile_layer_a2e3a495395fce5ac855e71111a3d95c = L.tileLayer(
|
64 |
+
"https://tile.openstreetmap.org/{z}/{x}/{y}.png",
|
65 |
+
{"attribution": "\u0026copy; \u003ca href=\"https://www.openstreetmap.org/copyright\"\u003eOpenStreetMap\u003c/a\u003e contributors", "detectRetina": false, "maxNativeZoom": 19, "maxZoom": 19, "minZoom": 0, "noWrap": false, "opacity": 1, "subdomains": "abc", "tms": false}
|
66 |
+
);
|
67 |
+
|
68 |
+
|
69 |
+
tile_layer_a2e3a495395fce5ac855e71111a3d95c.addTo(map_f83a88f12360719b8d5108477e64fbcf);
|
70 |
+
|
71 |
+
|
72 |
+
var marker_42ec10f3bb57a07b25f279b217982f24 = L.marker(
|
73 |
+
[22.2916, 70.7932],
|
74 |
+
{}
|
75 |
+
).addTo(map_f83a88f12360719b8d5108477e64fbcf);
|
76 |
+
|
77 |
+
</script>
|
78 |
</html>
|
templates/movie.html
CHANGED
@@ -69,16 +69,45 @@
|
|
69 |
</div>
|
70 |
<!-- buttons - end -->
|
71 |
</header>
|
72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
{% for movie in movies %}
|
74 |
-
<
|
75 |
-
<
|
76 |
-
|
77 |
-
|
78 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
{% endfor %}
|
80 |
</div>
|
81 |
-
<button class="demo-btn">Click Me</button>
|
82 |
</div>
|
83 |
<script>
|
84 |
function inB(event) {
|
@@ -93,75 +122,25 @@
|
|
93 |
ass[i].classList.add("hidden");
|
94 |
}
|
95 |
}
|
96 |
-
</script>
|
97 |
-
|
98 |
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
99 |
-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" integrity="sha512-SnH5WK+bZxgPHs44uWIX+LLJAJ9/2PkPKZ5QiAj6Ta86w+fsb2TkcmfRyVX3pBnMFcV7oQPJkl9QevSCWr3W6A==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
100 |
-
<!-- <script src="https://getcssscan.com/js/solid.min.js"></script>
|
101 |
-
<script src="https://getcssscan.com/js/lity.min.js"></script> -->
|
102 |
-
<!--!-->
|
103 |
-
<!-- <script src="https://getcssscan.com/js/jquery.countdown.min.js"></script> -->
|
104 |
-
<script>
|
105 |
-
const minWidthToRunDemo = 1024;
|
106 |
-
|
107 |
-
function canRunDemo() {
|
108 |
-
return window.innerWidth >= minWidthToRunDemo;
|
109 |
-
}
|
110 |
-
|
111 |
-
function loadDemoScript() {
|
112 |
-
const demo_script = document.querySelector("#cssscan-demo-script");
|
113 |
-
const demo_loading_warning = document.querySelector(".loading-demo");
|
114 |
-
|
115 |
-
if (!demo_script) {
|
116 |
-
const script = document.createElement("script");
|
117 |
-
script.setAttribute("src", "demo-build/main.js");
|
118 |
-
script.id = "cssscan-demo-script";
|
119 |
-
document.body.appendChild(script);
|
120 |
-
|
121 |
-
script.onload = () => {
|
122 |
-
script.dataset.loaded = true;
|
123 |
-
if (demo_loading_warning && demo_loading_warning.style.display !== "") {
|
124 |
-
window.cssScanReady();
|
125 |
-
try {
|
126 |
-
demo_loading_warning.remove();
|
127 |
-
} catch (e) {}
|
128 |
-
}
|
129 |
-
};
|
130 |
-
}
|
131 |
-
}
|
132 |
-
|
133 |
-
if (canRunDemo()) {
|
134 |
-
loadDemoScript();
|
135 |
-
}
|
136 |
-
|
137 |
-
window.onresize = function (e) {
|
138 |
-
const demo_script = document.querySelector("#cssscan-demo-script");
|
139 |
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
const demo_loading_warning = document.querySelector(".loading-demo");
|
151 |
-
|
152 |
-
if (demo_script && !demo_script.dataset.loaded) {
|
153 |
-
if (demo_loading_warning && demo_loading_warning.style.display === "") {
|
154 |
-
demo_loading_warning.style.display = "inline-block";
|
155 |
-
}
|
156 |
-
} else if (demo_script && demo_script.dataset.loaded) {
|
157 |
-
try {
|
158 |
-
demo_loading_warning.remove();
|
159 |
-
} catch (e) {}
|
160 |
}
|
161 |
});
|
162 |
}
|
|
|
|
|
|
|
|
|
|
|
163 |
</script>
|
164 |
-
<script src="{% static 'demo.js' %}"></script>
|
165 |
-
<!-- <script src="https://getcssscan.com/demo-build/main.js" id="cssscan-demo-script" data-loaded="true"></script> -->
|
166 |
</body>
|
167 |
</html>
|
|
|
69 |
</div>
|
70 |
<!-- buttons - end -->
|
71 |
</header>
|
72 |
+
|
73 |
+
<!-- Add search bar here, above movies grid -->
|
74 |
+
<div class="flex justify-start px-20 mb-6">
|
75 |
+
<div id="searchBarContainer" class="flex w-full max-w-xl">
|
76 |
+
<input
|
77 |
+
id="movieSearchInput"
|
78 |
+
type="text"
|
79 |
+
placeholder="Search movies..."
|
80 |
+
class="w-full px-4 py-2 border border-gray-300 rounded-l-lg focus:outline-none focus:ring-2 focus:ring-indigo-400"
|
81 |
+
oninput="filterMovies()"
|
82 |
+
/>
|
83 |
+
<button type="button" onclick="clearSearch()" class="px-4 py-2 bg-indigo-500 text-white rounded-r-lg hover:bg-indigo-600 transition">Clear</button>
|
84 |
+
</div>
|
85 |
+
</div>
|
86 |
+
<div class="grid-cols-6 grid gap-5 px-20" id="movieGrid">
|
87 |
{% for movie in movies %}
|
88 |
+
<div onclick="location.href='/movie/{{movie.tmdbId}}'" class="movie-card bg-white rounded-xl shadow-lg overflow-hidden flex flex-col hover:scale-105 transition-transform duration-300 group" data-title="{{movie.movie|lower}}">
|
89 |
+
<div class="relative">
|
90 |
+
<img class="w-full h-64 object-cover group-hover:opacity-80 transition" src="https://image.tmdb.org/t/p/w600_and_h900_bestv2/{{movie.poster}}" alt="{{movie.movie}} poster" />
|
91 |
+
<a href="{{movie.trailer}}" target="_blank" class="absolute bottom-2 right-2 bg-indigo-600 text-white px-3 py-1 rounded-full text-xs font-semibold shadow hover:bg-indigo-700 transition">Trailer</a>
|
92 |
+
</div>
|
93 |
+
<div class="p-4 flex flex-col flex-1">
|
94 |
+
<h2 class="text-lg font-bold mb-1 truncate" title="{{movie.movie}}">{{movie.movie}}</h2>
|
95 |
+
<p class="text-sm text-gray-500 mb-2">{{movie.Released}} • {{movie.Duration}}</p>
|
96 |
+
<p class="text-sm text-gray-700 mb-3 line-clamp-3">{{movie.description}}</p>
|
97 |
+
<div class="flex flex-wrap gap-2 mt-auto">
|
98 |
+
{% if movie.torrentLink %}
|
99 |
+
<a href="{{movie.torrentLink}}" target="_blank" class="bg-green-500 text-white text-xs px-3 py-1 rounded hover:bg-green-600 transition">Torrent</a>
|
100 |
+
{% endif %}
|
101 |
+
{% if movie.driveLink %}
|
102 |
+
<a href="{{movie.driveLink}}" target="_blank" class="bg-blue-500 text-white text-xs px-3 py-1 rounded hover:bg-blue-600 transition">Drive</a>
|
103 |
+
{% endif %}
|
104 |
+
<a href="https://www.imdb.com/title/{{movie.imdbId}}" target="_blank" class="bg-yellow-500 text-white text-xs px-3 py-1 rounded hover:bg-yellow-600 transition">IMDb</a>
|
105 |
+
<a href="{{movie.tmdbId}}" class="bg-indigo-500 text-white text-xs px-3 py-1 rounded hover:bg-indigo-600 transition">Details</a>
|
106 |
+
</div>
|
107 |
+
</div>
|
108 |
+
</div>
|
109 |
{% endfor %}
|
110 |
</div>
|
|
|
111 |
</div>
|
112 |
<script>
|
113 |
function inB(event) {
|
|
|
122 |
ass[i].classList.add("hidden");
|
123 |
}
|
124 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
|
126 |
+
// Filter movies client-side
|
127 |
+
function filterMovies() {
|
128 |
+
const query = document.getElementById('movieSearchInput').value.trim().toLowerCase();
|
129 |
+
const cards = document.querySelectorAll('.movie-card');
|
130 |
+
cards.forEach(card => {
|
131 |
+
const title = card.getAttribute('data-title');
|
132 |
+
if (title.includes(query)) {
|
133 |
+
card.style.display = '';
|
134 |
+
} else {
|
135 |
+
card.style.display = 'none';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
136 |
}
|
137 |
});
|
138 |
}
|
139 |
+
|
140 |
+
function clearSearch() {
|
141 |
+
document.getElementById('movieSearchInput').value = '';
|
142 |
+
filterMovies();
|
143 |
+
}
|
144 |
</script>
|
|
|
|
|
145 |
</body>
|
146 |
</html>
|
templates/movieDetail.html
CHANGED
@@ -1,156 +1,199 @@
|
|
1 |
-
<!DOCTYPE html>
|
2 |
-
<html lang="en">
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
<
|
31 |
-
|
32 |
-
|
33 |
-
<
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
</
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
|
4 |
+
<head>
|
5 |
+
<meta charset="UTF-8" />
|
6 |
+
<title>{{data.title}}</title>
|
7 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
8 |
+
</head>
|
9 |
+
|
10 |
+
<body>
|
11 |
+
<div class="bg-white relative overflow-x-hidden h-full min-h-screen">
|
12 |
+
<div id="previewContainer"
|
13 |
+
class="bg-white origin-center absolute flex flex-col scale-0 top-0 left-0 h-full w-full transition-all duration-500 z-50">
|
14 |
+
<svg onclick="preview('{{ file.2 }}')" width="32" height="32"
|
15 |
+
class="top-5 right-20 fixed top-0 bg-red-500 p-1 hover:scale-110 transition-all cursor-pointer z-50 rounded-full"
|
16 |
+
viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
17 |
+
<path fill-rule="evenodd"
|
18 |
+
d="M11.293 3.293a1 1 0 1 1 1.414 1.414L9.414 8l3.293 3.293a1 1 0 0 1-1.414 1.414L8 9.414l-3.293 3.293a1 1 0 0 1-1.414-1.414L6.586 8 3.293 4.707a1 1 0 0 1 1.414-1.414L8 6.586z" />
|
19 |
+
</svg>
|
20 |
+
|
21 |
+
<iframe id="previewIframe" src="" frameborder="0" seamless="" draggable="false" loading="lazy"
|
22 |
+
decoding="async" data-nimg="1"
|
23 |
+
class="fixed top-0 h-[100vh] w-full z-10 rounded-sm object-cover object-center"
|
24 |
+
style="color: transparent"></iframe>
|
25 |
+
</div>
|
26 |
+
<header class="h-20 flex m-4 justify-between items-center mb-4">
|
27 |
+
<!-- logo - start -->
|
28 |
+
<a href="/" class="my-5 inline-flex items-center text-black-800 text-2xl md:text-3xl font-bold gap-2.5"
|
29 |
+
aria-label="logo">
|
30 |
+
<svg class="w-[10%] text-indigo-500" id="outputsvg" xmlns="http://www.w3.org/2000/svg"
|
31 |
+
style="transform: none; transform-origin: 50% 50%; cursor: move; transition: none 0s ease 0s"
|
32 |
+
viewBox="0 0 3500 3500">
|
33 |
+
<g id="l5TLm6F9JGem8YOQ8A41YML" fill="rgb(100,103,241)" style="transform: none">
|
34 |
+
<g>
|
35 |
+
<path id="pulsHdoRs"
|
36 |
+
d="M1455 3470 c-164 -30 -323 -83 -480 -160 -487 -242 -829 -689 -935 -1226 -28 -139 -37 -389 -21 -534 64 -550 390 -1040 879 -1319 170 -98 440 -186 642 -211 203 -24 460 -7 658 45 609 160 1093 651 1246 1263 120 479 34 978 -238 1387 -258 387 -641 646 -1101 745 -149 33 -495 38 -650 10z m488 -574 c37 -7 70 -15 72 -18 3 -3 -39 -24 -92 -48 -214 -94 -369 -196 -520 -343 -336 -327 -433 -761 -242 -1084 19 -31 67 -89 107 -130 40 -40 70 -73 67 -73 -15 0 -143 54 -225 95 -221 111 -505 336 -517 410 -9 55 17 270 43 362 121 418 441 719 869 818 117 28 326 33 438 11z m360 -132 c271 -152 315 -279 149 -436 -70 -67 -94 -78 -165 -78 -46 0 -61 6 -127 51 -90 62 -156 92 -258 121 -65 17 -95 20 -187 15 -153 -7 -269 -48 -381 -133 -27 -21 -44 -31 -38 -23 110 147 205 237 364 343 100 67 296 166 395 199 l70 24 55 -23 c30 -12 85 -39 123 -60z m-1463 -1370 c262 -187 520 -287 807 -314 125 -12 210 -3 313 31 81 26 86 29 188 96 128 86 196 84 296 -8 59 -54 106 -135 106 -183 -1 -41 -30 -104 -66 -139 -47 -47 -187 -136 -271 -172 -299 -129 -612 -133 -916 -10 -250 102 -488 336 -599 590 -42 96 -74 194 -83 254 l-7 44 73 -64 c41 -36 112 -92 159 -125z">
|
37 |
+
</path>
|
38 |
+
</g>
|
39 |
+
</g>
|
40 |
+
</svg>
|
41 |
+
Cloud Storage
|
42 |
+
</a>
|
43 |
+
<!-- logo - end -->
|
44 |
+
|
45 |
+
<!-- nav - start -->
|
46 |
+
<nav class="hidden lg:flex gap-12">
|
47 |
+
<a href="/"
|
48 |
+
class="text-gray-600 hover:text-indigo-500 active:text-indigo-700 text-lg font-semibold transition duration-100">Home</a>
|
49 |
+
<a href="/list"
|
50 |
+
class="text-gray-600 hover:text-indigo-500 active:text-indigo-700 text-lg font-semibold transition duration-100">List</a>
|
51 |
+
<a href="/upload"
|
52 |
+
class="text-gray-600 hover:text-indigo-500 active:text-indigo-700 text-lg font-semibold transition duration-100">Upload</a>
|
53 |
+
<a href="/movie" class="text-indigo-500 text-lg font-semibold">Movie</a>
|
54 |
+
<a href="/logout"
|
55 |
+
class="text-gray-600 hover:text-indigo-500 active:text-indigo-700 text-lg font-semibold transition duration-100">Logout</a>
|
56 |
+
</nav>
|
57 |
+
<!-- nav - end -->
|
58 |
+
|
59 |
+
<!-- buttons - start -->
|
60 |
+
<div id="nav" onmouseout="outB()" onmouseover="inB()"
|
61 |
+
class="overflow-visible z-10 mt-[150px] grid grid-cols-1 grid-rows-5">
|
62 |
+
<button type="button"
|
63 |
+
class="shadow-xl inline-flex items-center lg:hidden bg-gray-200 hover:bg-gray-300 focus-visible:ring ring-indigo-300 text-gray-500 active:text-gray-700 text-sm md:text-base font-semibold rounded-lg gap-2 px-2.5 py-2">
|
64 |
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" viewBox="0 0 20 20" fill="currentColor">
|
65 |
+
<path fill-rule="evenodd"
|
66 |
+
d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h6a1 1 0 110 2H4a1 1 0 01-1-1zM3 15a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z"
|
67 |
+
clip-rule="evenodd" />
|
68 |
+
</svg>
|
69 |
+
Menu
|
70 |
+
</button>
|
71 |
+
<a href="../"
|
72 |
+
class="mt-2 hidden bg-white rounded-t-lg px-2 text-gray-600 hover:text-indigo-500 active:text-indigo-700 text-lg font-semibold transition duration-100">Home</a>
|
73 |
+
<a href="../list"
|
74 |
+
class="shadow-xl hidden bg-white px-2 text-gray-600 hover:text-indigo-500 active:text-indigo-700 text-lg font-semibold transition duration-100">List</a>
|
75 |
+
<a href="../upload"
|
76 |
+
class="shadow-xl hidden bg-white px-2 text-gray-600 hover:text-indigo-500 active:text-indigo-700 text-lg font-semibold transition duration-100">Upload</a>
|
77 |
+
<a href="../movie"
|
78 |
+
class="shadow-xl hidden bg-white px-2 text-indigo-500 hover:text-indigo-500 active:text-indigo-700 text-lg font-semibold transition duration-100">Movie</a>
|
79 |
+
<a href="../logout"
|
80 |
+
class="shadow-xl hidden bg-white px-2 text-gray-600 hover:text-indigo-500 active:text-indigo-700 text-lg font-semibold transition duration-100 rounded-b-lg">Logout</a>
|
81 |
+
</div>
|
82 |
+
<!-- buttons - end -->
|
83 |
+
</header>
|
84 |
+
<section class="relative bg-gradient-to-b from-[#f8fafc] to-[#e0e7ef] min-h-[90vh] py-12 px-0 md:px-0">
|
85 |
+
<div class="absolute top-0 inset-0 z-0">
|
86 |
+
<img src="https://media.themoviedb.org/t/p/w1920_and_h800_multi_faces/{{data.backdrop}}" alt="Backdrop"
|
87 |
+
class="w-full h-full object-cover opacity-20 scale-100" />
|
88 |
+
<div class="absolute inset-0 bg-gradient-to-b from-white/60 to-white/75 backdrop-blur-md"></div>
|
89 |
+
</div>
|
90 |
+
<div
|
91 |
+
class="relative z-10 max-w-6xl mx-auto flex flex-col md:flex-row gap-10 items-start bg-white/80 rounded-2xl shadow-2xl p-8 backdrop-blur-md">
|
92 |
+
<!-- Poster & Trailer -->
|
93 |
+
<div class="flex flex-col items-center gap-6 w-full md:w-1/3">
|
94 |
+
<div class="relative group w-full">
|
95 |
+
<img src="https://media.themoviedb.org/t/p/w300_and_h450_bestv2/{{data.poster}}" alt="Poster"
|
96 |
+
class="rounded-xl border-4 border-gray-200 shadow-lg w-full max-w-xs mx-auto object-cover" />
|
97 |
+
{% if data.trailer %}
|
98 |
+
<a href="{{ data.trailer }}" target="_blank"
|
99 |
+
class="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity bg-white/70 rounded-xl">
|
100 |
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-20 w-20 text-indigo-600 drop-shadow-lg"
|
101 |
+
fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
102 |
+
<circle cx="12" cy="12" r="10" fill="rgba(99,102,241,0.15)" />
|
103 |
+
<polygon points="10 8 16 12 10 16 10 8" fill="#6366f1" />
|
104 |
+
</svg>
|
105 |
+
</a>
|
106 |
+
{% endif %}
|
107 |
+
</div>
|
108 |
+
{% if data.torrentLink %}
|
109 |
+
<a href="{{ data.torrentLink }}" target="_blank"
|
110 |
+
class="w-full text-center bg-indigo-500 hover:bg-indigo-600 text-white font-semibold py-2 rounded-lg shadow transition">Download
|
111 |
+
Torrent</a>
|
112 |
+
{% endif %}
|
113 |
+
{% if data.driveLink %}
|
114 |
+
<a href="{{ data.driveLink }}" target="_blank"
|
115 |
+
class="w-full text-center bg-green-500 hover:bg-green-600 text-white font-semibold py-2 rounded-lg shadow transition">Watch
|
116 |
+
on Drive</a>
|
117 |
+
{% endif %}
|
118 |
+
</div>
|
119 |
+
<!-- Movie Details -->
|
120 |
+
<div class="flex-1 flex flex-col gap-6">
|
121 |
+
<div>
|
122 |
+
<h1 class="text-4xl font-extrabold text-gray-900 mb-2 tracking-tight">{{ data.movie }}</h1>
|
123 |
+
<div
|
124 |
+
class="flex flex-wrap whitespace-wrap items-center gap-3 text-gray-700 text-base font-medium">
|
125 |
+
{% if data.Released %}
|
126 |
+
<span class="bg-indigo-100 text-indigo-700 px-3 py-1 rounded-full">{{data.Released}}</span>
|
127 |
+
<span>•</span>
|
128 |
+
{% endif %}
|
129 |
+
{% if data.Duration %}
|
130 |
+
<span class="bg-gray-200 text-gray-700 px-3 py-1 rounded-full">{{ data.Duration }}
|
131 |
+
min</span>
|
132 |
+
<span>•</span>
|
133 |
+
{% endif %}
|
134 |
+
{% if data.Country %}
|
135 |
+
<span class="bg-gray-200 text-gray-700 px-3 py-1 rounded-full">{{ data.Country}}</span>
|
136 |
+
<span>•</span>
|
137 |
+
{% endif %}
|
138 |
+
{% if data.Production %}
|
139 |
+
<span class="text-gray-700">{{ data.Production}}</span>
|
140 |
+
{% endif %}
|
141 |
+
</div>
|
142 |
+
<div class="flex flex-wrap gap-2 mt-3">
|
143 |
+
<span class="bg-indigo-200 text-indigo-800 px-2 py-1 rounded text-xs font-semibold">
|
144 |
+
{{ data.Genre }}
|
145 |
+
</span>
|
146 |
+
</div>
|
147 |
+
</div>
|
148 |
+
<div>
|
149 |
+
<h2 class="text-xl font-semibold text-gray-900 mb-1">Plot Summary</h2>
|
150 |
+
<p class="text-gray-800 text-base leading-relaxed">{{ data.description }}
|
151 |
+
</p>
|
152 |
+
</div>
|
153 |
+
<div class="flex flex-wrap gap-4 mt-4">
|
154 |
+
{% if data.imdbId %}
|
155 |
+
<a href="https://www.imdb.com/title/{{ data.imdbId }}" target="_blank"
|
156 |
+
class="flex items-center gap-2 bg-yellow-400 hover:bg-yellow-500 text-black font-bold px-4 py-2 rounded transition">
|
157 |
+
|
158 |
+
IMDb
|
159 |
+
</a>
|
160 |
+
{% endif %}
|
161 |
+
{% if data.tmdbId %}
|
162 |
+
<a href="https://www.themoviedb.org/movie/{{ data.tmdbId }}" target="_blank"
|
163 |
+
class="flex items-center gap-2 bg-cyan-400 hover:bg-cyan-500 text-white font-bold px-4 py-2 rounded transition">
|
164 |
+
|
165 |
+
TMDB
|
166 |
+
</a>
|
167 |
+
{% endif %}
|
168 |
+
</div>
|
169 |
+
</div>
|
170 |
+
</div>
|
171 |
+
<!-- Optional: Video Player -->
|
172 |
+
{% if data.driveLink %}
|
173 |
+
<div class="relative z-20 max-w-6xl mx-auto mt-12 rounded-xl overflow-hidden shadow-2xl">
|
174 |
+
<iframe src="https://drive.google.com/file/d/{{ data.driveLink }}/preview" class="w-full h-[400px] bg-gray-100" allowfullscreen></iframe>
|
175 |
+
</div>
|
176 |
+
{% endif %}
|
177 |
+
</section>
|
178 |
+
</div>
|
179 |
+
<script>
|
180 |
+
function inB(event) {
|
181 |
+
ass = document.getElementById("nav").getElementsByTagName("a");
|
182 |
+
for (let i = 0; i < ass.length; i++) {
|
183 |
+
ass[i].classList.remove("hidden");
|
184 |
+
}
|
185 |
+
}
|
186 |
+
function outB(event) {
|
187 |
+
ass = document.getElementById("nav").getElementsByTagName("a");
|
188 |
+
for (let i = 0; i < ass.length; i++) {
|
189 |
+
ass[i].classList.add("hidden");
|
190 |
+
}
|
191 |
+
}
|
192 |
+
function openMovie(id) {
|
193 |
+
let videoLink = "https://drive.google.com/uc?export=download&id=" + id;
|
194 |
+
document.getElementById("moviePlayer").src = videoLink;
|
195 |
+
}
|
196 |
+
</script>
|
197 |
+
</body>
|
198 |
+
|
199 |
+
</html>
|