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:
parent
f36e338caa
commit
d5945d2ad3
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue