Пример #1
0
    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()
Пример #2
0
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
Пример #3
0
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
Пример #4
0
    def _decorator(request, id, *args, **kwargs):
        episode = Episode.for_oldid(id)

        if episode is None:
            raise Http404

        return f(request, episode, *args, **kwargs)
Пример #5
0
    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)
Пример #6
0
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
Пример #7
0
    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
Пример #8
0
    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()
Пример #9
0
    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]
Пример #10
0
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]
Пример #11
0
    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
Пример #12
0
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
Пример #13
0
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
Пример #14
0
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,
    })
Пример #15
0
    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)
Пример #16
0
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
Пример #17
0
    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)
Пример #18
0
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()
Пример #19
0
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()
Пример #20
0
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()
Пример #21
0
    def _episode_wrapper(doc):
        from mygpo.core.models import Episode

        return Episode.wrap(doc)
Пример #22
0
def get_favorites(user):
    favorites = Episode.view("favorites/episodes_by_user", key=user._id, include_docs=True)
    return favorites