Podcasts: alle Folgen an einem Tag (Archiv, Kurs) zählen als selten, nicht als täglich
Some checks failed
Test / e2e (push) Waiting to run
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Has been cancelled

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mrwnslz 2026-10-19 17:29:39 +02:00
parent ba3c6ff905
commit 2cb5dc4c04
3 changed files with 15 additions and 5 deletions

View file

@ -40,7 +40,7 @@ Diese Woche (the last 7 days), Diesen Monat (30 days), then the months — after
Kino feed. In „Folgen“ (sort „Nach Zeitraum, seltene zuerst“, the default) and „Neu“
the podcasts that seldom come go first within a group: `interval_days` of each feed
in `/podcasts/state/`, the mean gap between its newest 10 episodes (one episode: its
age, at least 30 days; kept an hour). Heard is a filter chip, not an order.
age, at least 30 days, the same when all came on one day; kept an hour). Heard is a filter chip, not an order.
### Shared code: `static/js/folders.js` (diora-web, every platform)

View file

@ -810,6 +810,14 @@ class EpisodeListTests(TestCase):
self.assertAlmostEqual(feeds[self.fa.id]['interval_days'], (_at(1, 3) - _at(1, 1)).total_seconds() / 86400 / 2, places=1)
self.assertAlmostEqual(feeds[self.fb.id]['interval_days'], (_at(1, 5) - _at(1, 4)).total_seconds() / 86400, places=1)
def test_a_whole_archive_at_once_counts_as_seldom(self):
f = PodcastFeed.objects.create(user=self.user, rss_url='https://example.org/c', title='Archiv')
for k in range(5):
PodcastEpisode.objects.create(feed=f, guid=f'c{k}', title=f'C{k}', audio_url=f'https://example.org/c{k}.mp3',
pub_date=_at(1, 1) + timedelta(minutes=k))
feeds = {x['id']: x for x in self.client.get('/podcasts/state/').json()['feeds']}
self.assertGreater(feeds[f.id]['interval_days'], 30)
def test_all_newest_first_without_date_last(self):
data = self.get()
self.assertEqual([e['id'] for e in data['episodes']],

View file

@ -816,7 +816,7 @@ INTERVAL_SINGLE_DAYS = 30
def _intervals(user):
"""How often each feed brings an episode, in days: the mean gap between its newest
INTERVAL_EPISODES. One episode only: its age, at least INTERVAL_SINGLE_DAYS. The lists
INTERVAL_EPISODES. One episode only (or all on one day): its age, at least INTERVAL_SINGLE_DAYS. The lists
put the seldom ones first within a day or week (after Kino's feed; feeds.js does the
same for blogs). One query (the newest episodes per feed by a window), kept an hour."""
key = f'podcasts:intervals:{user.id}'
@ -835,10 +835,12 @@ def _intervals(user):
now = timezone.now()
out = {}
for feed_id, ds in dates.items():
if len(ds) == 1:
days = max((now - ds[0]).total_seconds() / 86400, INTERVAL_SINGLE_DAYS)
span = (max(ds) - min(ds)).total_seconds() / 86400
if len(ds) == 1 or span < 1:
# One episode, or all of them at once (an archive, a course): no rhythm to go by.
days = max((now - max(ds)).total_seconds() / 86400, INTERVAL_SINGLE_DAYS)
else:
days = (max(ds) - min(ds)).total_seconds() / 86400 / (len(ds) - 1)
days = span / (len(ds) - 1)
out[feed_id] = round(days, 2)
cache.set(key, out, 3600)
return out