Add basic spotify page
It currently doesn't handle pagination, or caching
This commit is contained in:
parent
9f2b2a81c9
commit
ace30f4dbd
11 changed files with 1100 additions and 0 deletions
9
static/src/scss/_spotify.scss
Normal file
9
static/src/scss/_spotify.scss
Normal file
|
@ -0,0 +1,9 @@
|
|||
body.page-spotifyplaylistpage {
|
||||
table {
|
||||
img {
|
||||
min-width: 55px;
|
||||
width: 55px;
|
||||
height: 55px;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@
|
|||
@import "blocks";
|
||||
@import "shareon";
|
||||
@import "search";
|
||||
@import "spotify";
|
||||
|
||||
html,
|
||||
body {
|
||||
|
|
|
@ -9,6 +9,7 @@ env = environ.Env(
|
|||
DEBUG=(bool, False),
|
||||
BASE_HOSTNAME=(str, "example.com"),
|
||||
UNSPLASH_CLIENT_ID=(str, ""),
|
||||
SPOTIFY_PROXY_HOST=(str, ""),
|
||||
)
|
||||
|
||||
# Read local secrets
|
||||
|
@ -30,6 +31,7 @@ INSTALLED_APPS = [
|
|||
"website.blog",
|
||||
"website.images",
|
||||
"website.contact",
|
||||
"website.spotify",
|
||||
"website.contrib.code_block",
|
||||
"website.contrib.mermaid_block",
|
||||
"website.contrib.unsplash",
|
||||
|
@ -178,6 +180,7 @@ WAGTAILEMBEDS_FINDERS = [
|
|||
]
|
||||
|
||||
UNSPLASH_CLIENT_ID = env("UNSPLASH_CLIENT_ID")
|
||||
SPOTIFY_PROXY_HOST = env("SPOTIFY_PROXY_HOST")
|
||||
|
||||
|
||||
if DEBUG:
|
||||
|
|
0
website/spotify/__init__.py
Normal file
0
website/spotify/__init__.py
Normal file
16
website/spotify/client.py
Normal file
16
website/spotify/client.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
import requests
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
def is_valid_playlist(playlist_id: str) -> bool:
|
||||
return requests.get(
|
||||
f"https://{settings.SPOTIFY_PROXY_HOST}/v1/playlists/{playlist_id}"
|
||||
).ok
|
||||
|
||||
|
||||
def get_playlist(playlist_id: str) -> dict:
|
||||
response = requests.get(
|
||||
f"https://{settings.SPOTIFY_PROXY_HOST}/v1/playlists/{playlist_id}"
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
989
website/spotify/migrations/0001_initial.py
Normal file
989
website/spotify/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,989 @@
|
|||
# Generated by Django 4.0.6 on 2022-08-17 20:20
|
||||
|
||||
import django.db.models.deletion
|
||||
import wagtail.blocks
|
||||
import wagtail.embeds.blocks
|
||||
import wagtail.fields
|
||||
import wagtail.images.blocks
|
||||
from django.db import migrations, models
|
||||
|
||||
import website.spotify.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
("unsplash", "0002_unsplashphoto_created_and_more"),
|
||||
("wagtailcore", "0069_log_entry_jsonfield"),
|
||||
("images", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="SpotifyPlaylistPage",
|
||||
fields=[
|
||||
(
|
||||
"page_ptr",
|
||||
models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="wagtailcore.page",
|
||||
),
|
||||
),
|
||||
("subtitle", models.CharField(blank=True, max_length=255)),
|
||||
(
|
||||
"body",
|
||||
wagtail.fields.StreamField(
|
||||
[
|
||||
("embed", wagtail.embeds.blocks.EmbedBlock()),
|
||||
(
|
||||
"rich_text",
|
||||
wagtail.blocks.RichTextBlock(
|
||||
features=[
|
||||
"h2",
|
||||
"h3",
|
||||
"h4",
|
||||
"h5",
|
||||
"h6",
|
||||
"bold",
|
||||
"italic",
|
||||
"ol",
|
||||
"ul",
|
||||
"link",
|
||||
"document-link",
|
||||
"code",
|
||||
"strikethrough",
|
||||
"snippet-link",
|
||||
"snippet-embed",
|
||||
]
|
||||
),
|
||||
),
|
||||
(
|
||||
"lorem",
|
||||
wagtail.blocks.StructBlock(
|
||||
[
|
||||
(
|
||||
"paragraphs",
|
||||
wagtail.blocks.IntegerBlock(min_value=1),
|
||||
)
|
||||
]
|
||||
),
|
||||
),
|
||||
("html", wagtail.blocks.RawHTMLBlock()),
|
||||
(
|
||||
"image",
|
||||
wagtail.blocks.StructBlock(
|
||||
[
|
||||
(
|
||||
"image",
|
||||
wagtail.images.blocks.ImageChooserBlock(),
|
||||
),
|
||||
(
|
||||
"caption",
|
||||
wagtail.blocks.RichTextBlock(
|
||||
features=[
|
||||
"bold",
|
||||
"italic",
|
||||
"link",
|
||||
"document-link",
|
||||
"code",
|
||||
"strikethrough",
|
||||
"snippet-link",
|
||||
]
|
||||
),
|
||||
),
|
||||
]
|
||||
),
|
||||
),
|
||||
(
|
||||
"code",
|
||||
wagtail.blocks.StructBlock(
|
||||
[
|
||||
(
|
||||
"language",
|
||||
wagtail.blocks.ChoiceBlock(
|
||||
choices=[
|
||||
("ABAP", "ABAP"),
|
||||
("ABNF", "ABNF"),
|
||||
("ADL", "ADL"),
|
||||
("AMDGPU", "AMDGPU"),
|
||||
(
|
||||
"ANSYS parametric design language",
|
||||
"ANSYS parametric design language",
|
||||
),
|
||||
("ANTLR", "ANTLR"),
|
||||
(
|
||||
"ANTLR With ActionScript Target",
|
||||
"ANTLR With ActionScript Target",
|
||||
),
|
||||
(
|
||||
"ANTLR With C# Target",
|
||||
"ANTLR With C# Target",
|
||||
),
|
||||
(
|
||||
"ANTLR With CPP Target",
|
||||
"ANTLR With CPP Target",
|
||||
),
|
||||
(
|
||||
"ANTLR With Java Target",
|
||||
"ANTLR With Java Target",
|
||||
),
|
||||
(
|
||||
"ANTLR With ObjectiveC Target",
|
||||
"ANTLR With ObjectiveC Target",
|
||||
),
|
||||
(
|
||||
"ANTLR With Perl Target",
|
||||
"ANTLR With Perl Target",
|
||||
),
|
||||
(
|
||||
"ANTLR With Python Target",
|
||||
"ANTLR With Python Target",
|
||||
),
|
||||
(
|
||||
"ANTLR With Ruby Target",
|
||||
"ANTLR With Ruby Target",
|
||||
),
|
||||
("APL", "APL"),
|
||||
("ASCII armored", "ASCII armored"),
|
||||
("ActionScript", "ActionScript"),
|
||||
(
|
||||
"ActionScript 3",
|
||||
"ActionScript 3",
|
||||
),
|
||||
("Ada", "Ada"),
|
||||
("Agda", "Agda"),
|
||||
("Aheui", "Aheui"),
|
||||
("Alloy", "Alloy"),
|
||||
("AmbientTalk", "AmbientTalk"),
|
||||
("Ampl", "Ampl"),
|
||||
("Angular2", "Angular2"),
|
||||
("ApacheConf", "ApacheConf"),
|
||||
("AppleScript", "AppleScript"),
|
||||
("Arduino", "Arduino"),
|
||||
("Arrow", "Arrow"),
|
||||
("AspectJ", "AspectJ"),
|
||||
("Asymptote", "Asymptote"),
|
||||
("Augeas", "Augeas"),
|
||||
("AutoIt", "AutoIt"),
|
||||
("Awk", "Awk"),
|
||||
("BARE", "BARE"),
|
||||
("BBC Basic", "BBC Basic"),
|
||||
("BBCode", "BBCode"),
|
||||
("BC", "BC"),
|
||||
("BNF", "BNF"),
|
||||
("BST", "BST"),
|
||||
("BUGS", "BUGS"),
|
||||
("Base Makefile", "Base Makefile"),
|
||||
("Bash", "Bash"),
|
||||
("Bash Session", "Bash Session"),
|
||||
("Batchfile", "Batchfile"),
|
||||
("Bdd", "Bdd"),
|
||||
("Befunge", "Befunge"),
|
||||
("Berry", "Berry"),
|
||||
("BibTeX", "BibTeX"),
|
||||
("BlitzBasic", "BlitzBasic"),
|
||||
("BlitzMax", "BlitzMax"),
|
||||
("Boa", "Boa"),
|
||||
("Boo", "Boo"),
|
||||
("Boogie", "Boogie"),
|
||||
("Brainfuck", "Brainfuck"),
|
||||
("C", "C"),
|
||||
("C#", "C#"),
|
||||
("C++", "C++"),
|
||||
("CAmkES", "CAmkES"),
|
||||
("CBM BASIC V2", "CBM BASIC V2"),
|
||||
("CDDL", "CDDL"),
|
||||
("CFEngine3", "CFEngine3"),
|
||||
("CMake", "CMake"),
|
||||
("COBOL", "COBOL"),
|
||||
("COBOLFree", "COBOLFree"),
|
||||
("CPSA", "CPSA"),
|
||||
("CSS", "CSS"),
|
||||
(
|
||||
"CSS+Django/Jinja",
|
||||
"CSS+Django/Jinja",
|
||||
),
|
||||
(
|
||||
"CSS+Genshi Text",
|
||||
"CSS+Genshi Text",
|
||||
),
|
||||
("CSS+Lasso", "CSS+Lasso"),
|
||||
("CSS+Mako", "CSS+Mako"),
|
||||
("CSS+Myghty", "CSS+Myghty"),
|
||||
("CSS+PHP", "CSS+PHP"),
|
||||
("CSS+Ruby", "CSS+Ruby"),
|
||||
("CSS+Smarty", "CSS+Smarty"),
|
||||
("CSS+UL4", "CSS+UL4"),
|
||||
(
|
||||
"CSS+mozpreproc",
|
||||
"CSS+mozpreproc",
|
||||
),
|
||||
("CUDA", "CUDA"),
|
||||
("Cap'n Proto", "Cap'n Proto"),
|
||||
("CapDL", "CapDL"),
|
||||
("Ceylon", "Ceylon"),
|
||||
("ChaiScript", "ChaiScript"),
|
||||
("Chapel", "Chapel"),
|
||||
("Charmci", "Charmci"),
|
||||
("Cheetah", "Cheetah"),
|
||||
("Cirru", "Cirru"),
|
||||
("Clay", "Clay"),
|
||||
("Clean", "Clean"),
|
||||
("Clojure", "Clojure"),
|
||||
("ClojureScript", "ClojureScript"),
|
||||
("CoffeeScript", "CoffeeScript"),
|
||||
(
|
||||
"Coldfusion CFC",
|
||||
"Coldfusion CFC",
|
||||
),
|
||||
(
|
||||
"Coldfusion HTML",
|
||||
"Coldfusion HTML",
|
||||
),
|
||||
("Common Lisp", "Common Lisp"),
|
||||
(
|
||||
"Component Pascal",
|
||||
"Component Pascal",
|
||||
),
|
||||
("Coq", "Coq"),
|
||||
("Crmsh", "Crmsh"),
|
||||
("Croc", "Croc"),
|
||||
("Cryptol", "Cryptol"),
|
||||
("Crystal", "Crystal"),
|
||||
(
|
||||
"Csound Document",
|
||||
"Csound Document",
|
||||
),
|
||||
(
|
||||
"Csound Orchestra",
|
||||
"Csound Orchestra",
|
||||
),
|
||||
("Csound Score", "Csound Score"),
|
||||
("Cypher", "Cypher"),
|
||||
("Cython", "Cython"),
|
||||
("D", "D"),
|
||||
("DASM16", "DASM16"),
|
||||
("DTD", "DTD"),
|
||||
("Darcs Patch", "Darcs Patch"),
|
||||
("Dart", "Dart"),
|
||||
(
|
||||
"Debian Control file",
|
||||
"Debian Control file",
|
||||
),
|
||||
(
|
||||
"Debian Sourcelist",
|
||||
"Debian Sourcelist",
|
||||
),
|
||||
("Delphi", "Delphi"),
|
||||
("Devicetree", "Devicetree"),
|
||||
("Diff", "Diff"),
|
||||
("Django/Jinja", "Django/Jinja"),
|
||||
("Docker", "Docker"),
|
||||
("Duel", "Duel"),
|
||||
("Dylan", "Dylan"),
|
||||
("Dylan session", "Dylan session"),
|
||||
("DylanLID", "DylanLID"),
|
||||
("E-mail", "E-mail"),
|
||||
("EBNF", "EBNF"),
|
||||
("ECL", "ECL"),
|
||||
("ERB", "ERB"),
|
||||
("Earl Grey", "Earl Grey"),
|
||||
("Easytrieve", "Easytrieve"),
|
||||
("Eiffel", "Eiffel"),
|
||||
("Elixir", "Elixir"),
|
||||
(
|
||||
"Elixir iex session",
|
||||
"Elixir iex session",
|
||||
),
|
||||
("Elm", "Elm"),
|
||||
("Elpi", "Elpi"),
|
||||
("EmacsLisp", "EmacsLisp"),
|
||||
(
|
||||
"Embedded Ragel",
|
||||
"Embedded Ragel",
|
||||
),
|
||||
("Erlang", "Erlang"),
|
||||
(
|
||||
"Erlang erl session",
|
||||
"Erlang erl session",
|
||||
),
|
||||
("Evoque", "Evoque"),
|
||||
("Ezhil", "Ezhil"),
|
||||
("F#", "F#"),
|
||||
("FStar", "FStar"),
|
||||
("Factor", "Factor"),
|
||||
("Fancy", "Fancy"),
|
||||
("Fantom", "Fantom"),
|
||||
("Felix", "Felix"),
|
||||
("Fennel", "Fennel"),
|
||||
("Fish", "Fish"),
|
||||
("Flatline", "Flatline"),
|
||||
("FloScript", "FloScript"),
|
||||
("Forth", "Forth"),
|
||||
("Fortran", "Fortran"),
|
||||
("FortranFixed", "FortranFixed"),
|
||||
("FoxPro", "FoxPro"),
|
||||
("Freefem", "Freefem"),
|
||||
("Futhark", "Futhark"),
|
||||
("GAP", "GAP"),
|
||||
("GAS", "GAS"),
|
||||
("GDScript", "GDScript"),
|
||||
("GLSL", "GLSL"),
|
||||
("GSQL", "GSQL"),
|
||||
("Genshi", "Genshi"),
|
||||
("Genshi Text", "Genshi Text"),
|
||||
(
|
||||
"Gettext Catalog",
|
||||
"Gettext Catalog",
|
||||
),
|
||||
("Gherkin", "Gherkin"),
|
||||
("Gnuplot", "Gnuplot"),
|
||||
("Go", "Go"),
|
||||
("Golo", "Golo"),
|
||||
("GoodData-CL", "GoodData-CL"),
|
||||
("Gosu", "Gosu"),
|
||||
("Gosu Template", "Gosu Template"),
|
||||
("Graphviz", "Graphviz"),
|
||||
("Groff", "Groff"),
|
||||
("Groovy", "Groovy"),
|
||||
("HLSL", "HLSL"),
|
||||
("HSAIL", "HSAIL"),
|
||||
("HTML", "HTML"),
|
||||
(
|
||||
"HTML + Angular2",
|
||||
"HTML + Angular2",
|
||||
),
|
||||
("HTML+Cheetah", "HTML+Cheetah"),
|
||||
(
|
||||
"HTML+Django/Jinja",
|
||||
"HTML+Django/Jinja",
|
||||
),
|
||||
("HTML+Evoque", "HTML+Evoque"),
|
||||
("HTML+Genshi", "HTML+Genshi"),
|
||||
(
|
||||
"HTML+Handlebars",
|
||||
"HTML+Handlebars",
|
||||
),
|
||||
("HTML+Lasso", "HTML+Lasso"),
|
||||
("HTML+Mako", "HTML+Mako"),
|
||||
("HTML+Myghty", "HTML+Myghty"),
|
||||
("HTML+PHP", "HTML+PHP"),
|
||||
("HTML+Smarty", "HTML+Smarty"),
|
||||
("HTML+Twig", "HTML+Twig"),
|
||||
("HTML+UL4", "HTML+UL4"),
|
||||
("HTML+Velocity", "HTML+Velocity"),
|
||||
("HTTP", "HTTP"),
|
||||
("Haml", "Haml"),
|
||||
("Handlebars", "Handlebars"),
|
||||
("Haskell", "Haskell"),
|
||||
("Haxe", "Haxe"),
|
||||
("Hexdump", "Hexdump"),
|
||||
("Hspec", "Hspec"),
|
||||
("Hxml", "Hxml"),
|
||||
("Hy", "Hy"),
|
||||
("Hybris", "Hybris"),
|
||||
("IDL", "IDL"),
|
||||
("INI", "INI"),
|
||||
("IRC logs", "IRC logs"),
|
||||
("Icon", "Icon"),
|
||||
("Idris", "Idris"),
|
||||
("Igor", "Igor"),
|
||||
("Inform 6", "Inform 6"),
|
||||
(
|
||||
"Inform 6 template",
|
||||
"Inform 6 template",
|
||||
),
|
||||
("Inform 7", "Inform 7"),
|
||||
("Io", "Io"),
|
||||
("Ioke", "Ioke"),
|
||||
("Isabelle", "Isabelle"),
|
||||
("J", "J"),
|
||||
("JAGS", "JAGS"),
|
||||
("JCL", "JCL"),
|
||||
("JSGF", "JSGF"),
|
||||
("JSLT", "JSLT"),
|
||||
("JSON", "JSON"),
|
||||
("JSON-LD", "JSON-LD"),
|
||||
(
|
||||
"JSONBareObject",
|
||||
"JSONBareObject",
|
||||
),
|
||||
("Jasmin", "Jasmin"),
|
||||
("Java", "Java"),
|
||||
(
|
||||
"Java Server Page",
|
||||
"Java Server Page",
|
||||
),
|
||||
("JavaScript", "JavaScript"),
|
||||
(
|
||||
"JavaScript+Cheetah",
|
||||
"JavaScript+Cheetah",
|
||||
),
|
||||
(
|
||||
"JavaScript+Django/Jinja",
|
||||
"JavaScript+Django/Jinja",
|
||||
),
|
||||
(
|
||||
"JavaScript+Genshi Text",
|
||||
"JavaScript+Genshi Text",
|
||||
),
|
||||
(
|
||||
"JavaScript+Lasso",
|
||||
"JavaScript+Lasso",
|
||||
),
|
||||
(
|
||||
"JavaScript+Mako",
|
||||
"JavaScript+Mako",
|
||||
),
|
||||
(
|
||||
"JavaScript+Myghty",
|
||||
"JavaScript+Myghty",
|
||||
),
|
||||
(
|
||||
"JavaScript+PHP",
|
||||
"JavaScript+PHP",
|
||||
),
|
||||
(
|
||||
"JavaScript+Ruby",
|
||||
"JavaScript+Ruby",
|
||||
),
|
||||
(
|
||||
"JavaScript+Smarty",
|
||||
"JavaScript+Smarty",
|
||||
),
|
||||
(
|
||||
"Javascript+UL4",
|
||||
"Javascript+UL4",
|
||||
),
|
||||
(
|
||||
"Javascript+mozpreproc",
|
||||
"Javascript+mozpreproc",
|
||||
),
|
||||
("Julia", "Julia"),
|
||||
("Julia console", "Julia console"),
|
||||
("Juttle", "Juttle"),
|
||||
("K", "K"),
|
||||
("Kal", "Kal"),
|
||||
("Kconfig", "Kconfig"),
|
||||
("Kernel log", "Kernel log"),
|
||||
("Koka", "Koka"),
|
||||
("Kotlin", "Kotlin"),
|
||||
("Kuin", "Kuin"),
|
||||
("LLVM", "LLVM"),
|
||||
("LLVM-MIR", "LLVM-MIR"),
|
||||
("LLVM-MIR Body", "LLVM-MIR Body"),
|
||||
("LSL", "LSL"),
|
||||
("Lasso", "Lasso"),
|
||||
("Lean", "Lean"),
|
||||
("LessCss", "LessCss"),
|
||||
(
|
||||
"Lighttpd configuration file",
|
||||
"Lighttpd configuration file",
|
||||
),
|
||||
("LilyPond", "LilyPond"),
|
||||
("Limbo", "Limbo"),
|
||||
("Literate Agda", "Literate Agda"),
|
||||
(
|
||||
"Literate Cryptol",
|
||||
"Literate Cryptol",
|
||||
),
|
||||
(
|
||||
"Literate Haskell",
|
||||
"Literate Haskell",
|
||||
),
|
||||
(
|
||||
"Literate Idris",
|
||||
"Literate Idris",
|
||||
),
|
||||
("LiveScript", "LiveScript"),
|
||||
("Logos", "Logos"),
|
||||
("Logtalk", "Logtalk"),
|
||||
("Lua", "Lua"),
|
||||
("MAQL", "MAQL"),
|
||||
("MCFunction", "MCFunction"),
|
||||
("MIME", "MIME"),
|
||||
("MOOCode", "MOOCode"),
|
||||
("MQL", "MQL"),
|
||||
("MSDOS Session", "MSDOS Session"),
|
||||
("MXML", "MXML"),
|
||||
("Macaulay2", "Macaulay2"),
|
||||
("Makefile", "Makefile"),
|
||||
("Mako", "Mako"),
|
||||
("Markdown", "Markdown"),
|
||||
("Mask", "Mask"),
|
||||
("Mason", "Mason"),
|
||||
("Mathematica", "Mathematica"),
|
||||
("Matlab", "Matlab"),
|
||||
(
|
||||
"Matlab session",
|
||||
"Matlab session",
|
||||
),
|
||||
("Maxima", "Maxima"),
|
||||
("Meson", "Meson"),
|
||||
("MiniD", "MiniD"),
|
||||
("MiniScript", "MiniScript"),
|
||||
("Modelica", "Modelica"),
|
||||
("Modula-2", "Modula-2"),
|
||||
(
|
||||
"MoinMoin/Trac Wiki markup",
|
||||
"MoinMoin/Trac Wiki markup",
|
||||
),
|
||||
("Monkey", "Monkey"),
|
||||
("Monte", "Monte"),
|
||||
("MoonScript", "MoonScript"),
|
||||
("Mosel", "Mosel"),
|
||||
("Mscgen", "Mscgen"),
|
||||
("MuPAD", "MuPAD"),
|
||||
("MySQL", "MySQL"),
|
||||
("Myghty", "Myghty"),
|
||||
("NASM", "NASM"),
|
||||
("NCL", "NCL"),
|
||||
("NSIS", "NSIS"),
|
||||
("Nemerle", "Nemerle"),
|
||||
("NestedText", "NestedText"),
|
||||
("NewLisp", "NewLisp"),
|
||||
("Newspeak", "Newspeak"),
|
||||
(
|
||||
"Nginx configuration file",
|
||||
"Nginx configuration file",
|
||||
),
|
||||
("Nimrod", "Nimrod"),
|
||||
("Nit", "Nit"),
|
||||
("Nix", "Nix"),
|
||||
(
|
||||
"Node.js REPL console session",
|
||||
"Node.js REPL console session",
|
||||
),
|
||||
("Notmuch", "Notmuch"),
|
||||
("NuSMV", "NuSMV"),
|
||||
("NumPy", "NumPy"),
|
||||
("OCaml", "OCaml"),
|
||||
("ODIN", "ODIN"),
|
||||
(
|
||||
"OMG Interface Definition Language",
|
||||
"OMG Interface Definition Language",
|
||||
),
|
||||
("Objective-C", "Objective-C"),
|
||||
("Objective-C++", "Objective-C++"),
|
||||
("Objective-J", "Objective-J"),
|
||||
("Octave", "Octave"),
|
||||
("Ooc", "Ooc"),
|
||||
("Opa", "Opa"),
|
||||
("OpenEdge ABL", "OpenEdge ABL"),
|
||||
("PEG", "PEG"),
|
||||
("PHP", "PHP"),
|
||||
("PL/pgSQL", "PL/pgSQL"),
|
||||
("POVRay", "POVRay"),
|
||||
("PacmanConf", "PacmanConf"),
|
||||
("Pan", "Pan"),
|
||||
("ParaSail", "ParaSail"),
|
||||
("Pawn", "Pawn"),
|
||||
("Perl", "Perl"),
|
||||
("Perl6", "Perl6"),
|
||||
("Pig", "Pig"),
|
||||
("Pike", "Pike"),
|
||||
("PkgConfig", "PkgConfig"),
|
||||
("Pointless", "Pointless"),
|
||||
("Pony", "Pony"),
|
||||
("PostScript", "PostScript"),
|
||||
(
|
||||
"PostgreSQL SQL dialect",
|
||||
"PostgreSQL SQL dialect",
|
||||
),
|
||||
(
|
||||
"PostgreSQL console (psql)",
|
||||
"PostgreSQL console (psql)",
|
||||
),
|
||||
("PowerShell", "PowerShell"),
|
||||
(
|
||||
"PowerShell Session",
|
||||
"PowerShell Session",
|
||||
),
|
||||
("Praat", "Praat"),
|
||||
("Procfile", "Procfile"),
|
||||
("Prolog", "Prolog"),
|
||||
("PromQL", "PromQL"),
|
||||
("Properties", "Properties"),
|
||||
(
|
||||
"Protocol Buffer",
|
||||
"Protocol Buffer",
|
||||
),
|
||||
(
|
||||
"PsySH console session for PHP",
|
||||
"PsySH console session for PHP",
|
||||
),
|
||||
("Pug", "Pug"),
|
||||
("Puppet", "Puppet"),
|
||||
("PyPy Log", "PyPy Log"),
|
||||
("Python", "Python"),
|
||||
("Python 2.x", "Python 2.x"),
|
||||
(
|
||||
"Python 2.x Traceback",
|
||||
"Python 2.x Traceback",
|
||||
),
|
||||
(
|
||||
"Python Traceback",
|
||||
"Python Traceback",
|
||||
),
|
||||
(
|
||||
"Python console session",
|
||||
"Python console session",
|
||||
),
|
||||
("Python+UL4", "Python+UL4"),
|
||||
("Q", "Q"),
|
||||
("QBasic", "QBasic"),
|
||||
("QML", "QML"),
|
||||
("QVTO", "QVTO"),
|
||||
("Qlik", "Qlik"),
|
||||
("RConsole", "RConsole"),
|
||||
("REBOL", "REBOL"),
|
||||
("RHTML", "RHTML"),
|
||||
("RPMSpec", "RPMSpec"),
|
||||
("RQL", "RQL"),
|
||||
("RSL", "RSL"),
|
||||
("Racket", "Racket"),
|
||||
("Ragel", "Ragel"),
|
||||
(
|
||||
"Ragel in C Host",
|
||||
"Ragel in C Host",
|
||||
),
|
||||
(
|
||||
"Ragel in CPP Host",
|
||||
"Ragel in CPP Host",
|
||||
),
|
||||
(
|
||||
"Ragel in D Host",
|
||||
"Ragel in D Host",
|
||||
),
|
||||
(
|
||||
"Ragel in Java Host",
|
||||
"Ragel in Java Host",
|
||||
),
|
||||
(
|
||||
"Ragel in Objective C Host",
|
||||
"Ragel in Objective C Host",
|
||||
),
|
||||
(
|
||||
"Ragel in Ruby Host",
|
||||
"Ragel in Ruby Host",
|
||||
),
|
||||
(
|
||||
"Raw token data",
|
||||
"Raw token data",
|
||||
),
|
||||
("Rd", "Rd"),
|
||||
("ReasonML", "ReasonML"),
|
||||
("Red", "Red"),
|
||||
("Redcode", "Redcode"),
|
||||
(
|
||||
"Relax-NG Compact",
|
||||
"Relax-NG Compact",
|
||||
),
|
||||
(
|
||||
"ResourceBundle",
|
||||
"ResourceBundle",
|
||||
),
|
||||
("Rexx", "Rexx"),
|
||||
("Ride", "Ride"),
|
||||
("Rita", "Rita"),
|
||||
(
|
||||
"Roboconf Graph",
|
||||
"Roboconf Graph",
|
||||
),
|
||||
(
|
||||
"Roboconf Instances",
|
||||
"Roboconf Instances",
|
||||
),
|
||||
(
|
||||
"RobotFramework",
|
||||
"RobotFramework",
|
||||
),
|
||||
("Ruby", "Ruby"),
|
||||
(
|
||||
"Ruby irb session",
|
||||
"Ruby irb session",
|
||||
),
|
||||
("Rust", "Rust"),
|
||||
("S", "S"),
|
||||
("SARL", "SARL"),
|
||||
("SAS", "SAS"),
|
||||
("SCSS", "SCSS"),
|
||||
("SNBT", "SNBT"),
|
||||
("SPARQL", "SPARQL"),
|
||||
("SQL", "SQL"),
|
||||
("SWIG", "SWIG"),
|
||||
("Sass", "Sass"),
|
||||
("Savi", "Savi"),
|
||||
("Scala", "Scala"),
|
||||
(
|
||||
"Scalate Server Page",
|
||||
"Scalate Server Page",
|
||||
),
|
||||
("Scaml", "Scaml"),
|
||||
("Scheme", "Scheme"),
|
||||
("Scilab", "Scilab"),
|
||||
("Sed", "Sed"),
|
||||
("ShExC", "ShExC"),
|
||||
("Shen", "Shen"),
|
||||
("Sieve", "Sieve"),
|
||||
("Silver", "Silver"),
|
||||
("Singularity", "Singularity"),
|
||||
("Slash", "Slash"),
|
||||
("Slim", "Slim"),
|
||||
("Slurm", "Slurm"),
|
||||
("Smali", "Smali"),
|
||||
("Smalltalk", "Smalltalk"),
|
||||
(
|
||||
"SmartGameFormat",
|
||||
"SmartGameFormat",
|
||||
),
|
||||
("Smarty", "Smarty"),
|
||||
("Smithy", "Smithy"),
|
||||
("Snobol", "Snobol"),
|
||||
("Snowball", "Snowball"),
|
||||
("Solidity", "Solidity"),
|
||||
("Sophia", "Sophia"),
|
||||
("SourcePawn", "SourcePawn"),
|
||||
("Spice", "Spice"),
|
||||
("SquidConf", "SquidConf"),
|
||||
("Srcinfo", "Srcinfo"),
|
||||
("Stan", "Stan"),
|
||||
("Standard ML", "Standard ML"),
|
||||
("Stata", "Stata"),
|
||||
("SuperCollider", "SuperCollider"),
|
||||
("Swift", "Swift"),
|
||||
("TADS 3", "TADS 3"),
|
||||
("TAP", "TAP"),
|
||||
("TASM", "TASM"),
|
||||
("TOML", "TOML"),
|
||||
("Tal", "Tal"),
|
||||
("Tcl", "Tcl"),
|
||||
("Tcsh", "Tcsh"),
|
||||
("Tcsh Session", "Tcsh Session"),
|
||||
("TeX", "TeX"),
|
||||
("Tea", "Tea"),
|
||||
(
|
||||
"Tera Term macro",
|
||||
"Tera Term macro",
|
||||
),
|
||||
("Termcap", "Termcap"),
|
||||
("Terminfo", "Terminfo"),
|
||||
("Terraform", "Terraform"),
|
||||
("Text only", "Text only"),
|
||||
("Text output", "Text output"),
|
||||
("ThingsDB", "ThingsDB"),
|
||||
("Thrift", "Thrift"),
|
||||
("Todotxt", "Todotxt"),
|
||||
("TrafficScript", "TrafficScript"),
|
||||
("Transact-SQL", "Transact-SQL"),
|
||||
("Treetop", "Treetop"),
|
||||
("Turtle", "Turtle"),
|
||||
("Twig", "Twig"),
|
||||
("TypeScript", "TypeScript"),
|
||||
("TypoScript", "TypoScript"),
|
||||
(
|
||||
"TypoScriptCssData",
|
||||
"TypoScriptCssData",
|
||||
),
|
||||
(
|
||||
"TypoScriptHtmlData",
|
||||
"TypoScriptHtmlData",
|
||||
),
|
||||
(
|
||||
"Typographic Number Theory",
|
||||
"Typographic Number Theory",
|
||||
),
|
||||
("UL4", "UL4"),
|
||||
("USD", "USD"),
|
||||
("Unicon", "Unicon"),
|
||||
(
|
||||
"Unix/Linux config files",
|
||||
"Unix/Linux config files",
|
||||
),
|
||||
("UrbiScript", "UrbiScript"),
|
||||
("VB.net", "VB.net"),
|
||||
("VBScript", "VBScript"),
|
||||
("VCL", "VCL"),
|
||||
("VCLSnippets", "VCLSnippets"),
|
||||
("VCTreeStatus", "VCTreeStatus"),
|
||||
("VGL", "VGL"),
|
||||
("Vala", "Vala"),
|
||||
("Velocity", "Velocity"),
|
||||
("VimL", "VimL"),
|
||||
("WDiff", "WDiff"),
|
||||
("Web IDL", "Web IDL"),
|
||||
("WebAssembly", "WebAssembly"),
|
||||
("Whiley", "Whiley"),
|
||||
("X10", "X10"),
|
||||
("XML", "XML"),
|
||||
("XML+Cheetah", "XML+Cheetah"),
|
||||
(
|
||||
"XML+Django/Jinja",
|
||||
"XML+Django/Jinja",
|
||||
),
|
||||
("XML+Evoque", "XML+Evoque"),
|
||||
("XML+Lasso", "XML+Lasso"),
|
||||
("XML+Mako", "XML+Mako"),
|
||||
("XML+Myghty", "XML+Myghty"),
|
||||
("XML+PHP", "XML+PHP"),
|
||||
("XML+Ruby", "XML+Ruby"),
|
||||
("XML+Smarty", "XML+Smarty"),
|
||||
("XML+UL4", "XML+UL4"),
|
||||
("XML+Velocity", "XML+Velocity"),
|
||||
("XQuery", "XQuery"),
|
||||
("XSLT", "XSLT"),
|
||||
(
|
||||
"XUL+mozpreproc",
|
||||
"XUL+mozpreproc",
|
||||
),
|
||||
("Xorg", "Xorg"),
|
||||
("Xtend", "Xtend"),
|
||||
("YAML", "YAML"),
|
||||
("YAML+Jinja", "YAML+Jinja"),
|
||||
("YANG", "YANG"),
|
||||
("Zeek", "Zeek"),
|
||||
("Zephir", "Zephir"),
|
||||
("Zig", "Zig"),
|
||||
("aspx-cs", "aspx-cs"),
|
||||
("aspx-vb", "aspx-vb"),
|
||||
("autohotkey", "autohotkey"),
|
||||
("c-objdump", "c-objdump"),
|
||||
("cADL", "cADL"),
|
||||
(
|
||||
"ca65 assembler",
|
||||
"ca65 assembler",
|
||||
),
|
||||
("cfstatement", "cfstatement"),
|
||||
("cplint", "cplint"),
|
||||
("cpp-objdump", "cpp-objdump"),
|
||||
("d-objdump", "d-objdump"),
|
||||
("dg", "dg"),
|
||||
("eC", "eC"),
|
||||
("execline", "execline"),
|
||||
("g-code", "g-code"),
|
||||
("liquid", "liquid"),
|
||||
(
|
||||
"mozhashpreproc",
|
||||
"mozhashpreproc",
|
||||
),
|
||||
(
|
||||
"mozpercentpreproc",
|
||||
"mozpercentpreproc",
|
||||
),
|
||||
("nesC", "nesC"),
|
||||
("objdump", "objdump"),
|
||||
("objdump-nasm", "objdump-nasm"),
|
||||
(
|
||||
"reStructuredText",
|
||||
"reStructuredText",
|
||||
),
|
||||
("reg", "reg"),
|
||||
("scdoc", "scdoc"),
|
||||
("sqlite3con", "sqlite3con"),
|
||||
("systemverilog", "systemverilog"),
|
||||
("teal", "teal"),
|
||||
("tiddler", "tiddler"),
|
||||
("ucode", "ucode"),
|
||||
("verilog", "verilog"),
|
||||
("vhdl", "vhdl"),
|
||||
("xtlang", "xtlang"),
|
||||
]
|
||||
),
|
||||
),
|
||||
("source", wagtail.blocks.TextBlock()),
|
||||
]
|
||||
),
|
||||
),
|
||||
(
|
||||
"tangent",
|
||||
wagtail.blocks.StructBlock(
|
||||
[
|
||||
(
|
||||
"name",
|
||||
wagtail.blocks.CharBlock(max_length=64),
|
||||
),
|
||||
(
|
||||
"content",
|
||||
wagtail.blocks.RichTextBlock(
|
||||
features=[
|
||||
"bold",
|
||||
"italic",
|
||||
"ol",
|
||||
"ul",
|
||||
"link",
|
||||
"document-link",
|
||||
"code",
|
||||
"strikethrough",
|
||||
"snippet-link",
|
||||
]
|
||||
),
|
||||
),
|
||||
]
|
||||
),
|
||||
),
|
||||
(
|
||||
"mermaid",
|
||||
wagtail.blocks.StructBlock(
|
||||
[
|
||||
("source", wagtail.blocks.TextBlock()),
|
||||
(
|
||||
"caption",
|
||||
wagtail.blocks.RichTextBlock(
|
||||
features=[
|
||||
"bold",
|
||||
"italic",
|
||||
"link",
|
||||
"document-link",
|
||||
"code",
|
||||
"strikethrough",
|
||||
"snippet-link",
|
||||
]
|
||||
),
|
||||
),
|
||||
]
|
||||
),
|
||||
),
|
||||
],
|
||||
blank=True,
|
||||
use_json_field=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"spotify_playlist_id",
|
||||
models.CharField(
|
||||
max_length=32,
|
||||
unique=True,
|
||||
validators=[website.spotify.models.validate_playlist_id],
|
||||
),
|
||||
),
|
||||
(
|
||||
"hero_image",
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to="images.customimage",
|
||||
),
|
||||
),
|
||||
(
|
||||
"hero_unsplash_photo",
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to="unsplash.unsplashphoto",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"abstract": False,
|
||||
},
|
||||
bases=("wagtailcore.page",),
|
||||
),
|
||||
]
|
0
website/spotify/migrations/__init__.py
Normal file
0
website/spotify/migrations/__init__.py
Normal file
38
website/spotify/models.py
Normal file
38
website/spotify/models.py
Normal file
|
@ -0,0 +1,38 @@
|
|||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.http.request import HttpRequest
|
||||
from wagtail.admin.panels import FieldPanel
|
||||
|
||||
from website.common.models import BaseContentPage
|
||||
|
||||
from . import client
|
||||
|
||||
|
||||
def validate_playlist_id(playlist_id: str) -> None:
|
||||
if not client.is_valid_playlist(playlist_id):
|
||||
raise ValidationError("Unknown playlist id")
|
||||
|
||||
|
||||
class SpotifyPlaylistPage(BaseContentPage):
|
||||
subpage_types: list = []
|
||||
|
||||
spotify_playlist_id = models.CharField(
|
||||
max_length=32, unique=True, validators=[validate_playlist_id]
|
||||
)
|
||||
|
||||
content_panels = BaseContentPage.content_panels + [
|
||||
FieldPanel("spotify_playlist_id")
|
||||
]
|
||||
|
||||
@property
|
||||
def table_of_contents(self) -> list:
|
||||
return []
|
||||
|
||||
@property
|
||||
def reading_time(self) -> int:
|
||||
return 0
|
||||
|
||||
def get_context(self, request: HttpRequest) -> dict:
|
||||
context = super().get_context(request)
|
||||
context["playlist"] = client.get_playlist(self.spotify_playlist_id)
|
||||
return context
|
17
website/spotify/templates/spotify/spotify-item.html
Normal file
17
website/spotify/templates/spotify/spotify-item.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
{% with url=track.external_urls.spotify %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{ url }}">
|
||||
<img src="{{ track.album.images.0.url }}" decoding="async" loading="lazy" referrerpolicy="no-referrer" class="image"/>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{% if track.preview_url %}
|
||||
<a href="{{ track.preview_url }}"><i class="fas fa-play"></i></a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td><a href="{{ url }}">{{ track.name }}</a></td>
|
||||
<td>{% for artist in track.artists %}{% if not forloop.first %}, {% endif %}{{ artist.name }}{% endfor %}</td>
|
||||
<td>{{ track.album.name }}</td>
|
||||
</tr>
|
||||
{% endwith %}
|
3
website/spotify/templates/spotify/spotify-items.html
Normal file
3
website/spotify/templates/spotify/spotify-items.html
Normal file
|
@ -0,0 +1,3 @@
|
|||
{% for track in tracks %}
|
||||
{% include "spotify/spotify-item.html" with track=track.track %}
|
||||
{% endfor %}
|
24
website/spotify/templates/spotify/spotify_playlist_page.html
Normal file
24
website/spotify/templates/spotify/spotify_playlist_page.html
Normal file
|
@ -0,0 +1,24 @@
|
|||
{% extends "common/content_page.html" %}
|
||||
|
||||
{% block post_content %}
|
||||
<section class="container content">
|
||||
<h3>{{ playlist.name }}</h3>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th>Track</th>
|
||||
<th>Artist</th>
|
||||
<th>Album</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% include "spotify/spotify-items.html" with tracks=playlist.tracks.items %}
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
<section class="container">
|
||||
<a href="{{ playlist.external_urls.spotify }}"><i class="fab fa-spotify"></i> View on Spotify</a>
|
||||
</section>
|
||||
{% endblock %}
|
Loading…
Reference in a new issue