Merge received episode actions (bug 997)

Episode actions are now retrieved from the
server and are merged into gPodder's DB. The
first feed update after this release could
lead to a lot of updates, but further updates
should be faster, as only a few actions will
be processed by the server.
This commit is contained in:
Thomas Perl 2010-06-04 19:42:34 +02:00
parent f36e338caa
commit d5945d2ad3
2 changed files with 82 additions and 11 deletions

View File

@ -2459,11 +2459,77 @@ class gPodder(BuilderWidget, dbus.service.Object):
exporter = opml.Exporter(gpodder.subscription_file)
return exporter.write(self.channels)
def find_episode(self, podcast_url, episode_url):
"""Find an episode given its podcast and episode URL
The function will return a PodcastEpisode object if
the episode is found, or None if it's not found.
"""
for podcast in self.channels:
if podcast_url == podcast.url:
for episode in podcast.get_all_episodes():
if episode_url == episode.url:
return episode
return None
def process_received_episode_actions(self, updated_urls):
"""Process/merge episode actions from gpodder.net
This function will merge all changes received from
the server to the local database and update the
status of the affected episodes as necessary.
"""
indicator = ProgressIndicator(_('Merging episode actions'), \
_('Episode actions from gpodder.net are merged.'), \
False, self.get_dialog_parent())
for idx, action in enumerate(self.mygpo_client.get_episode_actions(updated_urls)):
if action.action == 'play':
episode = self.find_episode(action.podcast_url, \
action.episode_url)
if episode is not None:
log('Play action for %s', episode.url, sender=self)
episode.mark(is_played=True)
if action.timestamp > episode.current_position_updated:
log('Updating position for %s', episode.url, sender=self)
episode.current_position = action.position
episode.current_position_updated = action.timestamp
if action.total:
log('Updating total time for %s', episode.url, sender=self)
episode.total_time = action.total
episode.save()
elif action.action == 'delete':
episode = self.find_episode(action.podcast_url, \
action.episode_url)
if episode is not None:
if not episode.was_downloaded(and_exists=True):
# Set the episode to a "deleted" state
log('Marking as deleted: %s', episode.url, sender=self)
episode.delete_from_disk()
episode.save()
indicator.on_message(N_('%d action processed', '%d actions processed', idx) % idx)
gtk.main_iteration(False)
indicator.on_finished()
self.db.commit()
def update_feed_cache_finish_callback(self, updated_urls=None, select_url_afterwards=None):
self.db.commit()
self.updating_feed_cache = False
self.channels = PodcastChannel.load_from_db(self.db, self.config.download_dir)
# Process received episode actions for all updated URLs
self.process_received_episode_actions(updated_urls)
self.channel_list_changed = True
self.update_podcast_list_model(select_url=select_url_afterwards)

View File

@ -209,6 +209,17 @@ class MygPoClient(object):
self._store.remove(rewritten_urls)
return rewritten_urls
def get_episode_actions(self, updated_urls):
for podcast_url in updated_urls:
for action in self._store.load(ReceivedEpisodeAction, \
podcast_url=podcast_url):
yield action
# Remove all episode actions belonging to this URL
self._store.delete(ReceivedEpisodeAction, \
podcast_url=podcast_url)
self._store.commit()
def get_received_actions(self):
"""Returns a list of ReceivedSubscribeAction objects
@ -413,8 +424,6 @@ class MygPoClient(object):
action.started, action.position, action.total)
try:
save_since = True
# Load the "since" value from the database
since_o = self._store.get(SinceValue, host=self.host, \
device_id=self.device_id, \
@ -426,29 +435,25 @@ class MygPoClient(object):
# Step 1: Download Episode actions
try:
changes = self._client.download_episode_actions(since_o.since, \
device_id=self.device_id)
changes = self._client.download_episode_actions(since_o.since)
received_actions = [convert_from_api(a) for a in changes.actions]
log('Received %d episode actions', len(received_actions), \
sender=self)
self._store.save(received_actions)
# Save the "since" value for later use
self._store.update(since_o, since=changes.since)
except Exception, e:
log('Exception while polling for episodes.', sender=self, traceback=True)
save_since = False
# Step 2: Upload Episode actions
# Convert actions to the mygpoclient format for uploading
episode_actions = [convert_to_api(a) for a in actions]
# Upload the episodes and retrieve the new "since" value
since = self._client.upload_episode_actions(episode_actions)
if save_since:
# Update the "since" value of the episodes
self._store.update(since_o, since=since)
# Upload the episode actions
self._client.upload_episode_actions(episode_actions)
# Actions have been uploaded to the server - remove them
self._store.remove(actions)