121 lines
3.9 KiB
Python
121 lines
3.9 KiB
Python
"""
|
|
The Feed model describes a podcast of anything that can be parsed by :mod:`feedparser`.
|
|
Most of the heavy lifting is done via :mod:`feedparser`, we just download the
|
|
podcast files.
|
|
"""
|
|
|
|
from django.db import models
|
|
import datetime, time
|
|
import feedparser
|
|
|
|
from archive import Archive
|
|
|
|
# What mime types should be downloaded from the podcast XML
|
|
_audio_type_mime_types = [
|
|
u'audio/mpeg'
|
|
]
|
|
|
|
_audio_type_mime_types_string = "\n".join(_audio_type_mime_types)
|
|
|
|
class Feed(models.Model):
|
|
"""
|
|
.. data:: url
|
|
|
|
String representation of The URL from which the podcast
|
|
file should be downloaded.
|
|
|
|
.. data:: name
|
|
|
|
Human-readable string for this podcast. This is set by the user, not by
|
|
the XML podcast name. Is the name for the folder in which this podcast
|
|
is stored.
|
|
|
|
.. data:: max_episodes
|
|
|
|
Integer for how many fields should be stored at a time. A value of ``0``
|
|
(or ``< 0``) indicates that all episodes should be stored. A positive
|
|
value controls how many episodes are stored at a time.
|
|
|
|
.. data:: current_episodes
|
|
|
|
Integer for how many episodes are currently stored locally. This will
|
|
be deprecated, as it can be calculated.
|
|
|
|
.. data:: last_episode
|
|
|
|
DateTime object for the date of the most recent file downloaded. This
|
|
should not be modified by anything outside this model.
|
|
|
|
.. data:: parent_archive
|
|
|
|
Reference to the :class:`Archive` this podcast belongs to. Informs the
|
|
feed where it should store its files at.
|
|
"""
|
|
|
|
url = models.URLField()
|
|
name = models.CharField(max_length = 64)
|
|
max_episodes = models.IntegerField(default = 0) # Default store everything
|
|
current_episodes = models.IntegerField(default = 0)
|
|
last_episode = models.DateTimeField(default = datetime.datetime(1970, 1, 1))
|
|
parent_archive = models.ForeignKey(Archive)
|
|
|
|
class Meta:
|
|
app_label = 'archiver'
|
|
|
|
def _get_episode_time(episode):
|
|
"""
|
|
Get a datetime.datetime object of a podcast episode's published time.
|
|
Expects a specific element from feed_object.entries.
|
|
"""
|
|
t = time.mktime(episode.published_parsed)
|
|
return datetime.datetime.fromtimestamp(t)
|
|
|
|
def _calculate_new_episodes(feed_object):
|
|
"""
|
|
Calculate how many new episodes there are of a podcast (and consequently
|
|
how many we need to remove).
|
|
"""
|
|
num_episodes = 0
|
|
|
|
#feed_object.entries starts at the most recent
|
|
for episode in feed_object.entries:
|
|
if _get_episode_time(episode) > last_episode:
|
|
num_episodes += 1
|
|
|
|
#Don't set ourselves up to download any more than max_episodes
|
|
if num_episodes > max_episodes and max_episodes > 0:
|
|
return num_episodes
|
|
|
|
return num_episodes
|
|
|
|
def _download_podcast(feed_object, num_episodes = -1):
|
|
"""
|
|
Update this podcast with episodes from the server copy. The feed_object is a reference to a
|
|
feedparser object so we don't have to redownload a feed multiple times.
|
|
"""
|
|
|
|
num_episodes = _calculate_new_episodes()
|
|
|
|
#feedparser-specific way of building the list
|
|
new_episodes = feed_object.entries[:num_episodes]
|
|
|
|
for episode in new_episodes:
|
|
episode_audio_links = [link for link in episodes['links']
|
|
if link['type'] in _audio_type_mime_types_string]
|
|
|
|
print episode_audio_links
|
|
|
|
|
|
def sync_podcast(dry_run = False, forbid_delete = False):
|
|
"""
|
|
Update the podcast with episodes from the server copy.
|
|
|
|
:param dry_run: Calculate what would have been downloaded or deleted, but do not actually do either.
|
|
:param forbid_delete: Run, and only download new episodes. Ignores the :data:`max_episodes` field for this podcast.
|
|
|
|
.. todo::
|
|
Actually write this method...
|
|
|
|
"""
|
|
pass
|