Compare commits
No commits in common. "c7ce34b0da0002fcbc234a53e88fde2ffb4d33a0" and "270200cac31e06e766a0396fb97919be12517bd0" have entirely different histories.
c7ce34b0da
...
270200cac3
9 changed files with 7 additions and 220 deletions
|
|
@ -1,23 +0,0 @@
|
||||||
# Generated by Django 5.1.5 on 2025-02-13 15:09
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("item", "0010_week_break_notice_week_is_break"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="week",
|
|
||||||
name="use_hue",
|
|
||||||
field=models.BooleanField(default=False),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="week",
|
|
||||||
name="break_notice",
|
|
||||||
field=models.TextField(blank=True, default=""),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import urllib.parse
|
|
||||||
from django.utils.timezone import datetime, timedelta
|
from django.utils.timezone import datetime, timedelta
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
import json
|
import json
|
||||||
|
|
@ -12,8 +11,6 @@ from django.db.models.functions import ExtractWeek, ExtractYear
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.timesince import timesince
|
from django.utils.timesince import timesince
|
||||||
|
|
||||||
import ox
|
|
||||||
|
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
@ -30,6 +27,7 @@ class Item(models.Model):
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
modified = models.DateTimeField(auto_now=True)
|
modified = models.DateTimeField(auto_now=True)
|
||||||
|
|
||||||
|
|
||||||
title = models.CharField(max_length=1024)
|
title = models.CharField(max_length=1024)
|
||||||
url = models.CharField(max_length=1024, unique=True)
|
url = models.CharField(max_length=1024, unique=True)
|
||||||
description = models.TextField(default="", blank=True, editable=False)
|
description = models.TextField(default="", blank=True, editable=False)
|
||||||
|
|
@ -42,10 +40,6 @@ class Item(models.Model):
|
||||||
#if self.url and not self.data.get("url") == self.url:
|
#if self.url and not self.data.get("url") == self.url:
|
||||||
if self.url:
|
if self.url:
|
||||||
self.update_data()
|
self.update_data()
|
||||||
if self.use_hue:
|
|
||||||
if "hue" in self.data:
|
|
||||||
del self.data["hue"]
|
|
||||||
self.get_hue()
|
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
@ -110,14 +104,6 @@ class Item(models.Model):
|
||||||
d = '%s-W%s' % (self.get_year(), self.get_week())
|
d = '%s-W%s' % (self.get_year(), self.get_week())
|
||||||
return datetime.strptime(d + '-1', "%Y-W%W-%w").strftime('%Y-%m-%d')
|
return datetime.strptime(d + '-1', "%Y-W%W-%w").strftime('%Y-%m-%d')
|
||||||
|
|
||||||
@property
|
|
||||||
def use_hue(self):
|
|
||||||
monday = self.get_monday()
|
|
||||||
week = Week.objects.filter(monday=monday).first()
|
|
||||||
if week:
|
|
||||||
return week.use_hue
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse('item', kwargs={'id': self.id})
|
return reverse('item', kwargs={'id': self.id})
|
||||||
|
|
||||||
|
|
@ -126,8 +112,6 @@ class Item(models.Model):
|
||||||
|
|
||||||
def update_data(self):
|
def update_data(self):
|
||||||
self.data.update(self.parse_url())
|
self.data.update(self.parse_url())
|
||||||
if "hue" in self.data:
|
|
||||||
del self.data["hue"]
|
|
||||||
|
|
||||||
def parse_url(self):
|
def parse_url(self):
|
||||||
content = requests.get(self.url).text
|
content = requests.get(self.url).text
|
||||||
|
|
@ -149,84 +133,6 @@ class Item(models.Model):
|
||||||
data["thumbnail"] = data["thumbnail"].replace('/512p', '/1024p')
|
data["thumbnail"] = data["thumbnail"].replace('/512p', '/1024p')
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def get_hue(self, update=False):
|
|
||||||
if "hue" in self.data:
|
|
||||||
return self.data["hue"]
|
|
||||||
if update:
|
|
||||||
self.save()
|
|
||||||
return self.data.get("hue")
|
|
||||||
|
|
||||||
hue = None
|
|
||||||
parts = self.url.split('/')
|
|
||||||
url = '/'.join(parts[:3]) + '/api/'
|
|
||||||
if parts[4] == 'edits':
|
|
||||||
edit = urllib.parse.unquote(parts[5]).replace('_', ' ')
|
|
||||||
request = {
|
|
||||||
"action": "getEdit",
|
|
||||||
"data": {
|
|
||||||
"id": edit,
|
|
||||||
"keys": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
response = requests.post(url, json=request).json()
|
|
||||||
clips = response["data"]["clips"]
|
|
||||||
if clips:
|
|
||||||
hue = clips[int(len(clips)/2)]['hue']
|
|
||||||
else:
|
|
||||||
item = parts[4]
|
|
||||||
parts = parts[5:]
|
|
||||||
if parts and parts[0] in ("editor", "player"):
|
|
||||||
parts = parts[1:]
|
|
||||||
args = {}
|
|
||||||
if parts and "?" in parts[-1]:
|
|
||||||
part, arguments = parts[-1].split('?')
|
|
||||||
parts[-1] = part
|
|
||||||
args = dict(
|
|
||||||
kv.split('=', 1)
|
|
||||||
for kv in urllib.parse.unquote(arguments).split("&")
|
|
||||||
)
|
|
||||||
if ',' in parts[0]:
|
|
||||||
start, end = [ox.parse_timecode(p) for p in parts[0].split(',')]
|
|
||||||
request = {
|
|
||||||
"action": "findClips",
|
|
||||||
"data": {
|
|
||||||
"query": {
|
|
||||||
"conditions": [
|
|
||||||
{"key": "out", "value": start, "operator": ">"},
|
|
||||||
{"key": "in", "value": end, "operator": "<"},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"itemsQuery": {
|
|
||||||
"conditions": [{"key": "id", "value": item, "operator": "=="}]
|
|
||||||
},
|
|
||||||
"keys": ["id", "in", "out", "hue"],
|
|
||||||
"range": [0, 5000],
|
|
||||||
"sort": [
|
|
||||||
{"key": "in", "operator": "+"},
|
|
||||||
{"key": "out", "operator": "+"},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
response = requests.post(url, json=request).json()
|
|
||||||
items = response["data"]["items"]
|
|
||||||
if items:
|
|
||||||
hue = items[int(len(items)/2)]["hue"]
|
|
||||||
else:
|
|
||||||
annotation = '%s/%s' % (item, parts[0])
|
|
||||||
request = {
|
|
||||||
"action": "getAnnotation",
|
|
||||||
"data": {
|
|
||||||
"id": annotation,
|
|
||||||
"keys": ["hue"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
response = requests.post(url, json=request).json()
|
|
||||||
hue = response["data"]["hue"]
|
|
||||||
|
|
||||||
if hue is not None:
|
|
||||||
self.data["hue"] = hue
|
|
||||||
return hue
|
|
||||||
|
|
||||||
|
|
||||||
class Comment(models.Model):
|
class Comment(models.Model):
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
@ -292,30 +198,8 @@ class Week(models.Model):
|
||||||
title = models.CharField(max_length=2048, blank=True, default="")
|
title = models.CharField(max_length=2048, blank=True, default="")
|
||||||
byline = models.CharField(max_length=2048, blank=True, default="")
|
byline = models.CharField(max_length=2048, blank=True, default="")
|
||||||
published = models.DateTimeField(null=True, default=None, blank=True, editable=False)
|
published = models.DateTimeField(null=True, default=None, blank=True, editable=False)
|
||||||
use_hue = models.BooleanField(default=False)
|
|
||||||
is_break = models.BooleanField(default=False)
|
is_break = models.BooleanField(default=False)
|
||||||
break_notice = models.TextField(default="", blank=True)
|
break_notice = models.TextField(default="", blank=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s (%s)" % (self.title, self.monday)
|
return "%s (%s)" % (self.title, self.monday)
|
||||||
|
|
||||||
def items(self):
|
|
||||||
from datetime import date
|
|
||||||
monday = timezone.make_aware(datetime.combine(self.monday, datetime.min.time()), timezone.get_default_timezone())
|
|
||||||
monday += timedelta(days=7)
|
|
||||||
items, _ = Item.public(monday)
|
|
||||||
return items.order_by('published')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def background(self):
|
|
||||||
if self.use_hue:
|
|
||||||
colors = []
|
|
||||||
for item in self.items():
|
|
||||||
color = item.get_hue(update=True)
|
|
||||||
if color:
|
|
||||||
if not colors:
|
|
||||||
colors.append(f'hsl({color}, 100%, 15%, 0.8)')
|
|
||||||
else:
|
|
||||||
colors.append(f'hsl({color}, 60%, 15%, 0.8)')
|
|
||||||
return 'linear-gradient(to bottom, %s)' % ', '.join(colors)
|
|
||||||
return ''
|
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,6 @@ def archive(request, year=None, month=None, day=None, week=None):
|
||||||
if extra:
|
if extra:
|
||||||
context['week_title'] = extra.title
|
context['week_title'] = extra.title
|
||||||
context['week_byline'] = extra.byline
|
context['week_byline'] = extra.byline
|
||||||
context['week_background'] = extra.background
|
|
||||||
elif week:
|
elif week:
|
||||||
week = int(week)
|
week = int(week)
|
||||||
year = int(year)
|
year = int(year)
|
||||||
|
|
|
||||||
|
|
@ -92,23 +92,23 @@ def add_email(email):
|
||||||
|
|
||||||
def delete_bounced_emails():
|
def delete_bounced_emails():
|
||||||
url = settings.LISTMONK_API + 'bounces'
|
url = settings.LISTMONK_API + 'bounces'
|
||||||
auth = get_auth(headers)
|
auth = (settings.LISTMONK_USER, settings.LISTMONK_PASSWORD)
|
||||||
r = requests.get(url + '?per_page=10000', headers=headers, auth=auth).json()
|
r = requests.get(url + '?per_page=10000', auth=auth).json()
|
||||||
ids = [sub['subscriber_id'] for sub in r['data']['results']]
|
ids = [sub['subscriber_id'] for sub in r['data']['results']]
|
||||||
url = settings.LISTMONK_API + 'subscribers'
|
url = settings.LISTMONK_API + 'subscribers'
|
||||||
for id in ids:
|
for id in ids:
|
||||||
r = requests.delete(url + '?id=%s' % id, headers=headers, auth=auth).json()
|
r = requests.delete(url + '?id=%s' % id, auth=auth).json()
|
||||||
if not r.get("data"):
|
if not r.get("data"):
|
||||||
print(id)
|
print(id)
|
||||||
|
|
||||||
|
|
||||||
def delete_blacklisted_emails():
|
def delete_blacklisted_emails():
|
||||||
url = settings.LISTMONK_API + 'subscribers'
|
url = settings.LISTMONK_API + 'subscribers'
|
||||||
auth = get_auth(headers)
|
auth = (settings.LISTMONK_USER, settings.LISTMONK_PASSWORD)
|
||||||
r = requests.get(url + '?per_page=10000', headers=headers, auth=auth).json()
|
r = requests.get(url + '?per_page=10000', auth=auth).json()
|
||||||
ids = [u['id'] for u in r['data']['results'] if u['status'] == 'blocklisted']
|
ids = [u['id'] for u in r['data']['results'] if u['status'] == 'blocklisted']
|
||||||
for id in ids:
|
for id in ids:
|
||||||
r = requests.delete(url + '?id=%s' % id, headers=headers, auth=auth).json()
|
r = requests.delete(url + '?id=%s' % id, auth=auth).json()
|
||||||
if not r.get("data"):
|
if not r.get("data"):
|
||||||
print(id)
|
print(id)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,6 @@
|
||||||
--title: rgb(240, 240, 240);
|
--title: rgb(240, 240, 240);
|
||||||
}
|
}
|
||||||
|
|
||||||
html, body {
|
|
||||||
overscroll-behavior: none;
|
|
||||||
background-color: var(--bg);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "wrong font";
|
font-family: "wrong font";
|
||||||
src: url("https://files.pad.ma/ttf/wrongfont.woff") format("woff");
|
src: url("https://files.pad.ma/ttf/wrongfont.woff") format("woff");
|
||||||
|
|
|
||||||
|
|
@ -190,15 +190,6 @@ async function loadEdit(id, args) {
|
||||||
previous = annotation
|
previous = annotation
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (window.useHue && data.edit.clips && data.edit.clips.length) {
|
|
||||||
const color1 = data.edit.clips[0].hue
|
|
||||||
const color2 = data.edit.clips[parseInt(data.edit.clips.length/2)].hue
|
|
||||||
const color3 = data.edit.clips[data.edit.clips.length-1].hue
|
|
||||||
document.documentElement.style.setProperty('--color1', `hsl(${color1}, 100%, 15%, 0.8)`);
|
|
||||||
document.documentElement.style.setProperty('--color2', `hsl(${color2}, 60%, 15%, 0.8)`);
|
|
||||||
document.documentElement.style.setProperty('--color3', `hsl(${color3}, 60%, 15%, 0.8)`);
|
|
||||||
}
|
|
||||||
|
|
||||||
var value = []
|
var value = []
|
||||||
pandora.layerKeys.forEach(layer => {
|
pandora.layerKeys.forEach(layer => {
|
||||||
if (!data.layers[layer]) {
|
if (!data.layers[layer]) {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ async function loadData(id, args) {
|
||||||
"date",
|
"date",
|
||||||
"source",
|
"source",
|
||||||
"summary",
|
"summary",
|
||||||
"hue",
|
|
||||||
"streams",
|
"streams",
|
||||||
"duration",
|
"duration",
|
||||||
"durations",
|
"durations",
|
||||||
|
|
@ -31,8 +30,6 @@ async function loadData(id, args) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data.item = response['data']
|
data.item = response['data']
|
||||||
|
|
||||||
|
|
||||||
if (data.item.rightslevel > pandora.site.capabilities.canPlayClips['guest']) {
|
if (data.item.rightslevel > pandora.site.capabilities.canPlayClips['guest']) {
|
||||||
return {
|
return {
|
||||||
site: data.site,
|
site: data.site,
|
||||||
|
|
@ -82,35 +79,6 @@ async function loadData(id, args) {
|
||||||
data['in'] = data.annotation['in']
|
data['in'] = data.annotation['in']
|
||||||
data.out = data.annotation['out']
|
data.out = data.annotation['out']
|
||||||
}
|
}
|
||||||
if (window.useHue) {
|
|
||||||
var clips = await pandoraAPI('findClips', {
|
|
||||||
"query": {
|
|
||||||
"conditions": [
|
|
||||||
{"key": "out", "value": data["in"], "operator": ">"},
|
|
||||||
{"key": "in", "value": data["out"], "operator": "<"},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"itemsQuery": {
|
|
||||||
"conditions": [{"key": "id", "value": data.id.split('/')[0], "operator": "=="}]
|
|
||||||
},
|
|
||||||
"keys":["id", "in", "out", "hue"],
|
|
||||||
"range": [0, 5000],
|
|
||||||
"sort": [
|
|
||||||
{"key": "in", "operator": "+"},
|
|
||||||
{"key": "out", "operator": "+"},
|
|
||||||
]
|
|
||||||
})
|
|
||||||
clips = clips.data?.items
|
|
||||||
if (clips && clips.length) {
|
|
||||||
const color1 = clips[0].hue
|
|
||||||
const color2 = clips[parseInt(clips.length/2)].hue
|
|
||||||
const color3 = clips[clips.length-1].hue
|
|
||||||
document.documentElement.style.setProperty('--color1', `hsl(${color1}, 100%, 15%, 0.8)`);
|
|
||||||
document.documentElement.style.setProperty('--color2', `hsl(${color2}, 60%, 15%, 0.8)`);
|
|
||||||
document.documentElement.style.setProperty('--color3', `hsl(${color3}, 60%, 15%, 0.8)`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
data.layers = {}
|
data.layers = {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,6 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block head %}
|
{% block head %}
|
||||||
<title>{{ settings.SITENAME }}</title>
|
<title>{{ settings.SITENAME }}</title>
|
||||||
{% if week_background %}
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
background: {{ week_background }};
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script>
|
|
||||||
window.useHue = true;
|
|
||||||
</script>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="index archive">
|
<div class="index archive">
|
||||||
|
|
|
||||||
|
|
@ -13,22 +13,6 @@
|
||||||
<meta property="og:url" content="{{ url }}"/>
|
<meta property="og:url" content="{{ url }}"/>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<meta property="og:site_name" content="{{ settings.SITENAME }}"/>
|
<meta property="og:site_name" content="{{ settings.SITENAME }}"/>
|
||||||
{% if item.use_hue %}
|
|
||||||
<style>
|
|
||||||
:root {
|
|
||||||
--color1: var(--bg);
|
|
||||||
--color2: var(--bg);
|
|
||||||
--color3: var(--bg);
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
background: linear-gradient(to bottom, var(--color1), var(--color2), var(--color3));
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script>
|
|
||||||
window.useHue = true;
|
|
||||||
</script>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue