diff --git a/.gitignore b/.gitignore index 56a7f43..a667458 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ +.vscode/ +__pycache__/ db.sqlite3 videos/ channel_archiver/yt-dlp-archive.txt -channel_archiver/UnusualVideos* +channel_archiver/UnusualVideos* \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 834369a..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "[python]": { - "editor.defaultFormatter": "ms-python.python" - }, - "python.formatting.provider": "none" -} \ No newline at end of file diff --git a/api/README.md b/api/README.md new file mode 100644 index 0000000..eded595 --- /dev/null +++ b/api/README.md @@ -0,0 +1,24 @@ +# VideoAPI + +## Search +`GET /api/?param=value` + +### Parameters +| Param | Value | +|-|-| +| `q` | The search query string. | +| `limit` | A limit on the number of objects to be returned. Default is 6. | + +### Response +``` +[ + { + "id": 1, + "name": "Video 1" + }, + {...} +] +``` + +### Examples +> `GET /api/?q=foo&limit=3` will return the first 3 videos with "foo" in their name. diff --git a/api/__init__.py b/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/api/urls.py b/api/urls.py new file mode 100644 index 0000000..ad6ea78 --- /dev/null +++ b/api/urls.py @@ -0,0 +1,7 @@ +from django.urls import path, include +from . import views + +urlpatterns = [ + path('search/', views.searchAPI), + path('', include('sage_stream.api.urls')), +] \ No newline at end of file diff --git a/api/views.py b/api/views.py new file mode 100644 index 0000000..200f5db --- /dev/null +++ b/api/views.py @@ -0,0 +1,17 @@ +from django.db.models import Q +from rest_framework.response import Response +from rest_framework.decorators import api_view +from core.models import Video +from core.serializers import VideoSerializer + +@api_view(['GET']) +def searchAPI(request): + q = request.GET.get('q', '') + l = request.GET.get('limit', '6') + try: + l = int(l) + videos = Video.objects.filter(Q(id__contains=q) | Q(name__contains=q))[:l] + except: + videos = Video.objects.filter(Q(id__contains=q) | Q(name__contains=q)) + serializer = VideoSerializer(videos, many=True) + return Response(serializer.data) diff --git a/core/__pycache__/__init__.cpython-38.pyc b/core/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index 79d0b5f..0000000 Binary files a/core/__pycache__/__init__.cpython-38.pyc and /dev/null differ diff --git a/core/__pycache__/admin.cpython-38.pyc b/core/__pycache__/admin.cpython-38.pyc deleted file mode 100644 index 8f8ad87..0000000 Binary files a/core/__pycache__/admin.cpython-38.pyc and /dev/null differ diff --git a/core/__pycache__/apps.cpython-38.pyc b/core/__pycache__/apps.cpython-38.pyc deleted file mode 100644 index 1939d17..0000000 Binary files a/core/__pycache__/apps.cpython-38.pyc and /dev/null differ diff --git a/core/__pycache__/models.cpython-38.pyc b/core/__pycache__/models.cpython-38.pyc deleted file mode 100644 index 2f41b94..0000000 Binary files a/core/__pycache__/models.cpython-38.pyc and /dev/null differ diff --git a/core/__pycache__/urls.cpython-38.pyc b/core/__pycache__/urls.cpython-38.pyc deleted file mode 100644 index 835d60f..0000000 Binary files a/core/__pycache__/urls.cpython-38.pyc and /dev/null differ diff --git a/core/__pycache__/views.cpython-38.pyc b/core/__pycache__/views.cpython-38.pyc deleted file mode 100644 index 1437c5f..0000000 Binary files a/core/__pycache__/views.cpython-38.pyc and /dev/null differ diff --git a/core/admin.py b/core/admin.py index 63d2e8a..ddce0fa 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,6 +1,4 @@ from django.contrib import admin - - from .models import Video @admin.register(Video) diff --git a/core/migrations/__pycache__/0001_initial.cpython-38.pyc b/core/migrations/__pycache__/0001_initial.cpython-38.pyc deleted file mode 100644 index 0c1200a..0000000 Binary files a/core/migrations/__pycache__/0001_initial.cpython-38.pyc and /dev/null differ diff --git a/core/migrations/__pycache__/0002_video_thumbnail_alter_video_created_at.cpython-38.pyc b/core/migrations/__pycache__/0002_video_thumbnail_alter_video_created_at.cpython-38.pyc deleted file mode 100644 index 3f6408b..0000000 Binary files a/core/migrations/__pycache__/0002_video_thumbnail_alter_video_created_at.cpython-38.pyc and /dev/null differ diff --git a/core/migrations/__pycache__/0003_alter_video_file_alter_video_thumbnail.cpython-38.pyc b/core/migrations/__pycache__/0003_alter_video_file_alter_video_thumbnail.cpython-38.pyc deleted file mode 100644 index 2554846..0000000 Binary files a/core/migrations/__pycache__/0003_alter_video_file_alter_video_thumbnail.cpython-38.pyc and /dev/null differ diff --git a/core/migrations/__pycache__/__init__.cpython-38.pyc b/core/migrations/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index ffc280f..0000000 Binary files a/core/migrations/__pycache__/__init__.cpython-38.pyc and /dev/null differ diff --git a/core/serializers.py b/core/serializers.py new file mode 100644 index 0000000..5452b30 --- /dev/null +++ b/core/serializers.py @@ -0,0 +1,7 @@ +from rest_framework import serializers +from .models import Video + +class VideoSerializer(serializers.ModelSerializer): + class Meta: + model = Video + fields = ['id', 'name'] \ No newline at end of file diff --git a/core/templates/base.html b/core/templates/base.html index c81382d..18ba5dd 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -12,8 +12,7 @@ - +
@@ -51,12 +50,18 @@
+
- + aria-label="Search" + autocomplete="off" + id="search"> +
+
@@ -123,5 +129,6 @@ + diff --git a/core/urls.py b/core/urls.py index b3b572f..6cec69f 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,11 +1,10 @@ from django.urls import path from . import views - urlpatterns = [ path('', views.core, name='core'), path('status/', views.status, name='status'), path('about/', views.about, name='about'), path('random/', views.random, name='random'), path('view/', views.view, name='view'), - ] +] diff --git a/core/views.py b/core/views.py index 0e43982..3800c1e 100644 --- a/core/views.py +++ b/core/views.py @@ -1,9 +1,6 @@ from django.shortcuts import render -from django.contrib.auth.decorators import login_required -from django.http import HttpResponse from django.shortcuts import redirect from core.models import Video -import random # Create your views here. @@ -11,10 +8,9 @@ def core(request): videos = Video.objects.all() return render(request, 'base.html', {'videos': videos[::-1]}) - def random(request): videos = Video.objects.all().order_by("?") - ran = videos.first(); + ran = videos.first() return redirect('/view/'+str(ran.id)) def status(request): diff --git a/ragnarok/__pycache__/__init__.cpython-38.pyc b/ragnarok/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index 6600f0e..0000000 Binary files a/ragnarok/__pycache__/__init__.cpython-38.pyc and /dev/null differ diff --git a/ragnarok/__pycache__/settings.cpython-38.pyc b/ragnarok/__pycache__/settings.cpython-38.pyc deleted file mode 100644 index d64f6da..0000000 Binary files a/ragnarok/__pycache__/settings.cpython-38.pyc and /dev/null differ diff --git a/ragnarok/__pycache__/urls.cpython-38.pyc b/ragnarok/__pycache__/urls.cpython-38.pyc deleted file mode 100644 index 8307fc3..0000000 Binary files a/ragnarok/__pycache__/urls.cpython-38.pyc and /dev/null differ diff --git a/ragnarok/__pycache__/wsgi.cpython-38.pyc b/ragnarok/__pycache__/wsgi.cpython-38.pyc deleted file mode 100644 index ca63f3b..0000000 Binary files a/ragnarok/__pycache__/wsgi.cpython-38.pyc and /dev/null differ diff --git a/ragnarok/urls.py b/ragnarok/urls.py index accda0b..56cedde 100644 --- a/ragnarok/urls.py +++ b/ragnarok/urls.py @@ -22,9 +22,7 @@ urlpatterns = [ path('admin/', admin.site.urls), path('auth/', include('django.contrib.auth.urls')), path('', include('core.urls')), - path('/', include('core.urls')), - path('status/', include('core.urls')), - path('api/', include('sage_stream.api.urls')), + path('api/', include('api.urls')), ] if settings.DEBUG: diff --git a/static/dist/js/searchsuggestions.js b/static/dist/js/searchsuggestions.js new file mode 100644 index 0000000..d6a923c --- /dev/null +++ b/static/dist/js/searchsuggestions.js @@ -0,0 +1,38 @@ +const searchinput = document.querySelector("#search"); +const searchsuggestions = document.querySelector("#searchdropdown"); +const li = (c) => document.createElement("li").appendChild(c); +searchinput.addEventListener("input", (e) => { + q(e.target.value).then((d) => { + if (d.length < 1) searchsuggestions.replaceChildren(nothing()); + else searchsuggestions.replaceChildren(...suggestions(d)); + }) +}); +async function q(s) { + if (s.length > 0) { + try { + const response = await fetch("/api/search/?q=" + s); + const result = await response.json(); + return result; + } catch(error) { + console.log("Error: " + error); + } + } + return []; +} +function nothing() { + const span = document.createElement("span"); + span.setAttribute("class", "dropdown-item-text"); + span.insertAdjacentText("afterbegin", "Nothing"); + return li(span); +} +function suggestions(d) { + const items = []; + for (const vid of d) { + const a = document.createElement("a"); + a.setAttribute("class", "dropdown-item") + a.setAttribute("href", "/view/" + vid.id); + a.insertAdjacentText("afterbegin", vid.name + " " + vid.id); + items.push(li(a)); + } + return items; +}