def setUp(self): self.podcast1 = Podcast(urls=['http://example.com/feed.rss']) self.podcast2 = Podcast(urls=['http://test.org/podcast/']) self.podcast3 = Podcast(urls=['http://test.org/feed/']) self.podcast1.save() self.podcast2.save() self.podcast3.save() self.episode1 = Episode(podcast=self.podcast1.get_id(), urls = ['http://example.com/episode1.mp3']) self.episode2 = Episode(podcast=self.podcast2.get_id(), urls = ['http://example.com/episode1.mp3']) self.episode3 = Episode(podcast=self.podcast3.get_id(), urls = ['http://example.com/media.mp3']) self.episode1.save() self.episode2.save() self.episode3.save() self.podcast2.group_with(self.podcast3, 'My Group', 'Feed1', 'Feed2') self.user = User(username='******') self.user.email = '*****@*****.**' self.user.set_password('secret!') self.user.save()
def episodes_for_slug(podcast_id, episode_slug): """ returns all episodes for the given slug this should normally only return one episode, but there might be multiple due to resolved replication conflicts, etc """ if not podcast_id: raise QueryParameterMissing('podcast_id') if not episode_slug: raise QueryParameterMissing('episode_slug') r = Episode.view('episodes/by_slug', key = [podcast_id, episode_slug], include_docs = True, ) if not r: return [] episodes = r.all() for episode in episodes: if episode.needs_update: incomplete_obj.send_robust(sender=episode) return episodes
def update_episode(entry, podcast): url, mimetype = get_episode_url(entry) if url is None: print 'Ignoring entry' return url = sanitize_url(url, 'episode') if not url: print 'Ignoring entry' return episode = Episode.for_podcast_id_url(podcast.get_id(), url, create=True) md = get_episode_metadata(entry, url, mimetype, podcast.language) changed = False for key, value in md.items(): if getattr(episode, key) != value: setattr(episode, key, value) changed = True if changed: episode.save() print 'Updating Episode: %s' % episode.title.encode('utf-8', 'ignore') return episode
def _decorator(request, id, *args, **kwargs): episode = Episode.for_oldid(id) if episode is None: raise Http404 return f(request, episode, *args, **kwargs)
def _decorator(request, p_slug_id, e_slug_id, *args, **kwargs): episode = Episode.for_slug_id(p_slug_id, e_slug_id) if episode is None: raise Http404 return f(request, episode, *args, **kwargs)
def episodes_for_podcast_uncached(podcast, since=None, until={}, **kwargs): if not podcast: raise QueryParameterMissing('podcast') if kwargs.get('descending', False): since, until = until, since if isinstance(since, datetime): since = since.isoformat() if isinstance(until, datetime): until = until.isoformat() res = Episode.view('episodes/by_podcast', startkey = [podcast.get_id(), since], endkey = [podcast.get_id(), until], include_docs = True, reduce = False, **kwargs ) episodes = list(res) for episode in episodes: if episode.needs_update: incomplete_obj.send_robust(sender=episode) return episodes
def episode_settings(user, url, podcast_url): episode = Episode.for_podcast_url(podcast_url, url) if episode is None: raise Http404 episode_state = episode.get_user_state(user) return episode_state, episode_state
def setUp(self): self.podcast1 = Podcast(urls=['http://example.com/feed.rss']) self.podcast2 = Podcast(urls=['http://test.org/podcast/']) self.podcast1.save() self.podcast2.save() self.episode1 = Episode(podcast=self.podcast1.get_id(), urls = ['http://example.com/episode1.mp3']) self.episode2 = Episode(podcast=self.podcast2.get_id(), urls = ['http://example.com/episode1.mp3']) self.episode1.save() self.episode2.save() self.user = User(username='******') self.user.email = '*****@*****.**' self.user.set_password('secret!') self.user.save()
def _get_existing_slugs(self): """ Episode slugs have to be unique within the Podcast """ from mygpo.core.models import Episode res = Episode.view( "episodes/by_slug", startkey=[self.podcast_id, self.base_slug], endkey=[self.podcast_id, self.base_slug + "ZZZZZ"], wrap_doc=False, ) return [r["key"][1] for r in res]
def episode_slugs_per_podcast(podcast_id, base_slug): if not podcast_id: raise QueryParameterMissing('podcast_id') res = Episode.view('episodes/by_slug', startkey = [podcast_id, base_slug], endkey = [podcast_id, base_slug + 'ZZZZZ'], wrap_doc = False, ) return [r['key'][1] for r in res]
def handle_obj(self, seq, doc, actions): state = EpisodeUserState.wrap(doc) try: episode = Episode.get(state.episode) except ResourceNotFound: episode = None if episode: listeners = episode.listener_count() updated = self.update(episode=episode, listeners=listeners) actions['updated'] += updated else: actions['missing'] += 1
def episodes_for_podcast_current(podcast, limit=None): if not podcast: raise QueryParameterMissing('podcast') res = Episode.view('episodes/by_podcast_current', startkey = podcast.get_id(), endkey = podcast.get_id(), include_docs = True, limit = limit, ) episodes = list(res) for episode in episodes: if episode.needs_update: incomplete_obj.send_robust(sender=episode) return episodes
def episodes_by_id(episode_ids): if episode_ids is None: raise QueryParameterMissing('episode_ids') if not episode_ids: return [] r = Episode.view('episodes/by_id', include_docs = True, keys = episode_ids, ) episodes = list(r) for episode in episodes: if episode.needs_update: incomplete_obj.send_robust(sender=episode) return episodes
def welcome(request): current_site = RequestSite(request) podcasts = get_cache_or_calc('podcast-count', timeout=60*60, calc=lambda: Podcast.count()) users = get_cache_or_calc('user-count', timeout=60*60, calc=lambda: User.count()) episodes = get_cache_or_calc('episode-count', timeout=60*60, calc=lambda: Episode.count()) lang = utils.process_lang_params(request) toplist = PodcastToplist(lang) return render(request, 'home.html', { 'podcast_count': podcasts, 'user_count': users, 'episode_count': episodes, 'url': current_site, 'toplist': toplist, })
def for_ref_urls(cls, user, podcast_url, episode_url): import hashlib cache_key = 'episode-state-%s-%s-%s' % (user._id, hashlib.md5(podcast_url).hexdigest(), hashlib.md5(episode_url).hexdigest()) state = cache.get(cache_key) if state: return state res = cls.view('episode_states/by_ref_urls', key = [user._id, podcast_url, episode_url], limit=1, include_docs=True) if res: state = res.first() state.ref_url = episode_url state.podcast_ref_url = podcast_url cache.set(cache_key, state, 60*60) return state else: episode = Episode.for_podcast_url(podcast_url, episode_url, create=True) return episode.get_user_state(user)
def episode_for_podcast_id_url(podcast_id, episode_url, create=False): if not podcast_id: raise QueryParameterMissing('podcast_id') if not episode_url: raise QueryParameterMissing('episode_url') key = u'episode-podcastid-%s-url-%s' % ( sha1(podcast_id.encode('utf-8')).hexdigest(), sha1(episode_url.encode('utf-8')).hexdigest()) # Disabled as cache invalidation is not working properly # episode = cache.get(key) # if episode: # return episode db = get_main_database() episode = get_single_result(db, 'episodes/by_podcast_url', key = [podcast_id, episode_url], include_docs = True, reduce = False, schema = Episode, ) if episode: if episode.needs_update: incomplete_obj.send_robust(sender=episode) else: cache.set(key, episode) return episode if create: episode = Episode() episode.created_timestamp = get_timestamp(datetime.utcnow()) episode.podcast = podcast_id episode.urls = [episode_url] episode.save() incomplete_obj.send_robust(sender=episode) return episode return None
def test_merge(self): p1 = Podcast() p1.urls = ['http://example.com/podcast1.rss'] p1.save() p2 = Podcast() p2.urls = ['http://example.com/podcast2.rss'] p2.save() e1 = Episode() e1.title = 'Episode 1' e1.podcast = p1.get_id() e1.urls = ['http://example.com/podcast1/e1.mp3'] e1.save() e2 = Episode() e2.title = 'Episode 2' e2.podcast = p1.get_id() e2.urls = ['http://example.com/podcast1/e2.mp3'] e2.save() e3 = Episode() e3.title = 'Episode 3' e3.podcast = p2.get_id() e3.urls = ['http://example.com/podcast2/e2.mp3'] e3.save() e4 = Episode() e4.title = 'Episode 4' e4.podcast = p2.get_id() e4.urls = ['http://example.com/podcast2/e3.mp3'] e4.save() user = User() user.username = '******' user.email = '*****@*****.**' user.set_password('secret') device1 = Device() device1.uid = 'dev1' device2 = Device() device2.uid = 'dev2' user.devices.append(device1) user.devices.append(device2) user.save() p1.subscribe(user, device1) time.sleep(1) p1.unsubscribe(user, device1) time.sleep(1) p1.subscribe(user, device1) p2.subscribe(user, device2) s1 = e1.get_user_state(user) s1.add_actions([EpisodeAction(action='play')]) s1.save() s3 = e3.get_user_state(user) s3.add_actions([EpisodeAction(action='play')]) s3.save() # we need that for later e3_id = e3._id actions = Counter() # decide which episodes to merge groups = [(0, [e1]), (1, [e2, e3]), (2, [e4])] # carry out the merge pm = PodcastMerger([p1, p2], actions, groups) pm.merge() e1 = Episode.get(e1._id) es1 = e1.get_user_state(user) self.assertEqual(len(es1.actions), 1) # check if merged episode's id can still be accessed e3 = Episode.get(e3_id) es3 = e3.get_user_state(user) self.assertEqual(len(es3.actions), 1) p1 = Podcast.get(p1.get_id()) ps1 = p1.get_user_state(user) self.assertEqual(len(ps1.get_subscribed_device_ids()), 2) self.assertEqual(len(list(p1.get_episodes())), 3)
class MergeTests(TestCase): """ Tests merging of two podcasts, their episodes and states """ def setUp(self): self.podcast1 = Podcast(urls=['http://example.com/feed.rss']) self.podcast2 = Podcast(urls=['http://test.org/podcast/']) self.podcast1.save() self.podcast2.save() self.episode1 = Episode(podcast=self.podcast1.get_id(), urls = ['http://example.com/episode1.mp3']) self.episode2 = Episode(podcast=self.podcast2.get_id(), urls = ['http://example.com/episode1.mp3']) self.episode1.save() self.episode2.save() self.user = User(username='******') self.user.email = '*****@*****.**' self.user.set_password('secret!') self.user.save() def test_merge_podcasts(self): # Create additional data that will be merged state1 = episode_state_for_user_episode(self.user, self.episode1) state2 = episode_state_for_user_episode(self.user, self.episode2) action1 = EpisodeAction(action='play', timestamp=datetime.utcnow(), upload_timestamp=get_timestamp(datetime.utcnow())) action2 = EpisodeAction(action='download', timestamp=datetime.utcnow(), upload_timestamp=get_timestamp(datetime.utcnow())) add_episode_actions(state1, [action1]) add_episode_actions(state2, [action2]) # copy of the object episode2 = episode_by_id(self.episode2._id) # decide which episodes to merge groups = [(0, [self.episode1, self.episode2])] counter = Counter() pm = PodcastMerger([self.podcast1, self.podcast2], counter, groups) pm.merge() state1 = episode_state_for_user_episode(self.user, self.episode1) state2 = episode_state_for_user_episode(self.user, episode2) self.assertIn(action1, state1.actions) self.assertIn(action2, state1.actions) self.assertEqual(state2._id, None) def tearDown(self): self.podcast1.delete() self.episode1.delete() #self.podcast2.delete() #self.episode2.delete() self.user.delete()
class MergeTests(TestCase): def setUp(self): self.podcast1 = Podcast(urls=['http://example.com/feed.rss']) self.podcast2 = Podcast(urls=['http://test.org/podcast/']) self.podcast1.save() self.podcast2.save() self.episode1 = Episode(podcast=self.podcast1.get_id(), urls = ['http://example.com/episode1.mp3']) self.episode2 = Episode(podcast=self.podcast2.get_id(), urls = ['http://example.com/episode1.mp3']) self.episode1.save() self.episode2.save() self.user = User(username='******') self.user.email = '*****@*****.**' self.user.set_password('secret!') self.user.save() def test_merge_podcasts(self): state1 = self.episode1.get_user_state(self.user) state2 = self.episode2.get_user_state(self.user) action1 = EpisodeAction(action='play', timestamp=datetime.utcnow()) action2 = EpisodeAction(action='download', timestamp=datetime.utcnow()) state1.add_actions([action1]) state2.add_actions([action2]) state1.save() state2.save() pm = PodcastMerger([self.podcast1, self.podcast2]) pm.merge() state1 = self.episode1.get_user_state(self.user) state2 = self.episode2.get_user_state(self.user) self.assertIn(action1, state1.actions) self.assertIn(action2, state1.actions) def tearDown(self): self.podcast1.delete() self.episode1.delete() try: self.podcast2.delete() self.episode2.delete() except: pass self.user.delete()
class MergeGroupTests(TestCase): """ Tests merging of two podcasts, one of which is part of a group """ def setUp(self): self.podcast1 = Podcast(urls=['http://example.com/feed.rss']) self.podcast2 = Podcast(urls=['http://test.org/podcast/']) self.podcast3 = Podcast(urls=['http://test.org/feed/']) self.podcast1.save() self.podcast2.save() self.podcast3.save() self.episode1 = Episode(podcast=self.podcast1.get_id(), urls = ['http://example.com/episode1.mp3']) self.episode2 = Episode(podcast=self.podcast2.get_id(), urls = ['http://example.com/episode1.mp3']) self.episode3 = Episode(podcast=self.podcast3.get_id(), urls = ['http://example.com/media.mp3']) self.episode1.save() self.episode2.save() self.episode3.save() self.podcast2.group_with(self.podcast3, 'My Group', 'Feed1', 'Feed2') self.user = User(username='******') self.user.email = '*****@*****.**' self.user.set_password('secret!') self.user.save() def test_merge_podcasts(self): podcast1 = podcast_by_id(self.podcast1.get_id()) podcast2 = podcast_by_id(self.podcast2.get_id()) podcast3 = podcast_by_id(self.podcast3.get_id()) # assert that the podcasts are actually grouped self.assertEqual(podcast2._id, podcast3._id) self.assertNotEqual(podcast2.get_id(), podcast2._id) self.assertNotEqual(podcast3.get_id(), podcast3._id) # Create additional data that will be merged state1 = episode_state_for_user_episode(self.user, self.episode1) state2 = episode_state_for_user_episode(self.user, self.episode2) action1 = EpisodeAction(action='play', timestamp=datetime.utcnow(), upload_timestamp=get_timestamp(datetime.utcnow())) action2 = EpisodeAction(action='download', timestamp=datetime.utcnow(), upload_timestamp=get_timestamp(datetime.utcnow())) add_episode_actions(state1, [action1]) add_episode_actions(state2, [action2]) # copy of the object episode2 = episode_by_id(self.episode2._id) # decide which episodes to merge groups = [(0, [self.episode1, self.episode2])] counter = Counter() pm = PodcastMerger([podcast2, podcast1], counter, groups) pm.merge() state1 = episode_state_for_user_episode(self.user, self.episode1) state2 = episode_state_for_user_episode(self.user, episode2) self.assertIn(action1, state1.actions) self.assertIn(action2, state1.actions) self.assertEqual(state2._id, None) episode1 = episode_by_id(self.episode1._id) # episode2 has been merged into episode1, so it must contain its # merged _id self.assertEqual(episode1.merged_ids, [episode2._id]) def tearDown(self): self.podcast2.delete() self.episode1.delete() #self.podcast2.delete() #self.episode2.delete() self.user.delete()
def _episode_wrapper(doc): from mygpo.core.models import Episode return Episode.wrap(doc)
def get_favorites(user): favorites = Episode.view("favorites/episodes_by_user", key=user._id, include_docs=True) return favorites