Basic structure of site defined.
--- /dev/null
+[flake8]
+ignore = E203, W503
+max-line-length = 88
--- /dev/null
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+pip-wheel-metadata/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+.python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+#Pipfile.lock
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
--- /dev/null
+"""
+ASGI config for core 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.1/howto/deployment/asgi/
+"""
+
+import os
+
+from django.core.asgi import get_asgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings")
+
+application = get_asgi_application()
--- /dev/null
+"""
+Django settings for core project.
+
+Generated by 'django-admin startproject' using Django 4.1.5.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/4.1/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/4.1/ref/settings/
+"""
+
+import os
+from pathlib import Path
+
+# Build paths inside the project like this: BASE_DIR / 'subdir'.
+BASE_DIR = Path(__file__).resolve().parent.parent
+
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = "django-insecure-!nzce=4gwub(n+!6@lh^vjl+m(*ibo42&gav2kvr@d4!$3ausi"
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+
+if DEBUG:
+ import dotenv
+
+ dotenv.load_dotenv()
+
+ALLOWED_HOSTS = []
+
+
+# Application definition
+
+INSTALLED_APPS = [
+ # Django
+ "django.contrib.admin",
+ "django.contrib.auth",
+ "django.contrib.contenttypes",
+ "django.contrib.sessions",
+ "django.contrib.messages",
+ "django.contrib.staticfiles",
+ # Allauth
+ "django.contrib.sites",
+ "allauth",
+ "allauth.account",
+ "allauth.socialaccount",
+ "allauth.socialaccount.providers.twitch",
+ # Custom
+ "manager",
+]
+
+MIDDLEWARE = [
+ "django.middleware.security.SecurityMiddleware",
+ "django.contrib.sessions.middleware.SessionMiddleware",
+ "django.middleware.common.CommonMiddleware",
+ "django.middleware.csrf.CsrfViewMiddleware",
+ "django.contrib.auth.middleware.AuthenticationMiddleware",
+ "django.contrib.messages.middleware.MessageMiddleware",
+ "django.middleware.clickjacking.XFrameOptionsMiddleware",
+]
+
+ROOT_URLCONF = "core.urls"
+
+TEMPLATES = [
+ {
+ "BACKEND": "django.template.backends.django.DjangoTemplates",
+ "DIRS": [
+ os.path.join(BASE_DIR, "templates"),
+ ],
+ "APP_DIRS": True,
+ "OPTIONS": {
+ "context_processors": [
+ "django.template.context_processors.debug",
+ "django.template.context_processors.request",
+ "django.contrib.auth.context_processors.auth",
+ "django.contrib.messages.context_processors.messages",
+ ],
+ },
+ },
+]
+
+WSGI_APPLICATION = "core.wsgi.application"
+
+
+# Database
+# https://docs.djangoproject.com/en/4.1/ref/settings/#databases
+
+DATABASES = {
+ "default": {
+ "ENGINE": "django.db.backends.sqlite3",
+ "NAME": BASE_DIR / "db.sqlite3",
+ }
+}
+
+
+# Password validation
+# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators
+
+AUTH_PASSWORD_VALIDATORS = [
+ {
+ "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
+ },
+ {
+ "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
+ },
+ {
+ "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
+ },
+ {
+ "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
+ },
+]
+
+
+# Internationalization
+# https://docs.djangoproject.com/en/4.1/topics/i18n/
+
+LANGUAGE_CODE = "en-us"
+
+TIME_ZONE = "UTC"
+
+USE_I18N = True
+
+USE_TZ = True
+
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/4.1/howto/static-files/
+
+STATIC_URL = "static/"
+STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),)
+
+# Default primary key field type
+# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
+
+DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
+
+
+SITE_ID = 1
+
+# Provider specific settings
+SOCIALACCOUNT_PROVIDERS = {
+ "twitch": {
+ "SCOPE": [
+ ],
+ },
+}
+AUTHENTICATION_BACKENDS = [
+ # Needed to login by username in Django admin, regardless of `allauth`
+ "django.contrib.auth.backends.ModelBackend",
+ # `allauth` specific authentication methods, such as login by e-mail
+ "allauth.account.auth_backends.AuthenticationBackend",
+]
+DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
+
+SOCIALACCOUNT_STORE_TOKENS = True
+ACCOUNT_EMAIL_REQUIRED = False
+ACCOUNT_EMAIL_VERIFICATION = "none"
+ACCOUNT_LOGOUT_ON_GET = False
+ACCOUNT_UNIQUE_EMAIL = False
+ACCOUNT_AUTHENTICATED_LOGIN_REDIRECT = True
+SOCIALACCOUNT_DISCONNECT_REDIRECT_URL = "/"
--- /dev/null
+"""core URL Configuration
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+ https://docs.djangoproject.com/en/4.1/topics/http/urls/
+Examples:
+Function views
+ 1. Add an import: from my_app import views
+ 2. Add a URL to urlpatterns: path('', views.home, name='home')
+Class-based views
+ 1. Add an import: from other_app.views import Home
+ 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
+Including another URLconf
+ 1. Import the include() function: from django.urls import include, path
+ 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
+"""
+from django.contrib import admin
+from django.urls import path, include
+from django.views.generic import TemplateView
+
+urlpatterns = [
+ path("admin/", admin.site.urls),
+ path('accounts/', include('allauth.urls')),
+ path('', TemplateView.as_view(template_name="manager/index.html")),
+]
--- /dev/null
+"""
+WSGI config for core 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.1/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings")
+
+application = get_wsgi_application()
--- /dev/null
+#!/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", "core.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()
--- /dev/null
+from django.contrib import admin
+
+# Register your models here.
--- /dev/null
+from django.apps import AppConfig
+
+
+class ManagerConfig(AppConfig):
+ default_auto_field = "django.db.models.BigAutoField"
+ name = "manager"
--- /dev/null
+from django.db import models
+
+
+# Create your models here.
+class Clip(models.Model):
+ id = models.TextField(primary_key=True)
+ url = models.URLField()
+ embed_url = models.URLField()
+ broadcaster_id = models.TextField()
+ broadcaster_name = models.TextField()
+ creator_id = models.TextField()
+ creator_name = models.TextField()
+ video_id = models.TextField()
+ game_id = models.TextField()
+ title = models.TextField()
+ view_count = models.IntegerField()
+ created_at = models.TextField()
+ thumbnail_url = models.TextField()
+ duration = models.FloatField()
+ vod_offset = models.IntegerField()
--- /dev/null
+{% extends 'base.html' %}
+{% block content %}
+<header id="heading">
+ {% if user.is_authenticated %}
+ <h1>Please Input Clip Link</h1>
+ <br />
+ <form>
+ <input type="text">
+ <button>Submit Clip</button>
+ </form>
+ {% else %}
+ <h1>Welcome Friend, please log in</h1>
+ {% endif %}
+</div>
+{% endblock %}
--- /dev/null
+from django.test import TestCase
+
+# Create your tests here.
--- /dev/null
+from django.shortcuts import render
+
+# Create your views here.
--- /dev/null
+* {
+ box-sizing: border-box;
+}
+
+body {
+ margin: 0;
+ font-family: Arial, Helvetica, sans-serif;
+ background: #333;
+ color: #eee;
+}
+
+#heading {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ min-height: 100vh;
+ flex-direction: column;
+}
+
+/* Style the side navigation */
+.sidenav {
+ height: 100%;
+ width: 200px;
+ position: fixed;
+ z-index: 0;
+ top: 0;
+ left: 0;
+ background-color: #111;
+ overflow-x: hidden;
+}
+
+
+/* CSS */
+button.btn {
+ background-color: #111;
+ border-style: none;
+ color: white;
+ cursor: pointer;
+ font-family: "Arial", "Helvetica", "sans-serif";
+ font-size: 16px;
+ padding: 16px;
+ position: absolute;
+ text-align: left;
+}
+
+button.btn:hover,
+button.btn:focus {
+ background-color: #ddd;
+ color: black;
+ padding: 16px;
+ text-decoration: none;
+ display: block;
+
+}
+
+
+
+a.btn {
+ color: white;
+ padding: 16px;
+ text-decoration: none;
+ display: block;
+}
+a:hover.btn {
+ background-color: #ddd;
+ color: black;
+}
+
+.btn-bot {
+ position: absolute;
+ width: 100%;
+ bottom: 0px;
+}
+
+/* Style the content */
+.content {
+ margin-left: 200px;
+ padding-left: 20px;
+}
+
--- /dev/null
+{% load static %}
+{% load socialaccount %}
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ {% if title %}
+ <title>Clip Ranker - {{ title }}</title>
+ {% else %}
+ <title>Clip Ranker</title>
+ {% endif %}
+ <link href="{% static 'main.css' %}" rel="stylesheet" type="text/css" />
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ </head>
+ <body>
+ <div class="sidenav">
+ <a class="btn" href="#">Home</a>
+ {% if user.is_authenticated %}
+ <a class="btn" href="#">Panel</a>
+ {% endif %}
+ {% if user.is_superuser %}
+ <a class="btn" href="{% url 'admin:index' %}">Admin</a>
+ {% endif %}
+ <a class="btn" href="#">About</a>
+ {% if user.is_authenticated %}
+ <form action="{% url 'account_logout' %}" method="post">
+ {% csrf_token %}
+ <button class="btn btn-bot" type="submit">Log out</button>
+ </form>
+ <a class="btn" href="#">{{ user.username }}</a>
+ {% else %}
+ <form action="{% provider_login_url 'twitch' %}" method="post">
+ {% csrf_token %}
+ <button class="btn btn-bot" type="submit">Log in with Twitch</button>
+ </form>
+ {% endif %}
+ </div>
+ <div class="content">
+ {% block content %}{% endblock %}
+ </div>
+ </body>
+</html>