Esempio n. 1
0
 def test_save_empty_logo(self):
     """ Make sure that save_podcast_logo(None) does not fail """
     try:
         CoverArt.save_podcast_logo(None)
     except:
         self.fail('CoverArt.save_podcast_logo(None) should not raise '
                   'an exception')
Esempio n. 2
0
    def _save_logo(self):
        with responses.RequestsMock() as rsps, open(IMG_PATH1, 'rb') as body:
            rsps.add(
                responses.GET, self.URL, status=200, body=body, content_type='image/png'
            )

            CoverArt.save_podcast_logo(self.URL)
Esempio n. 3
0
    def _save_logo(self):
        with responses.RequestsMock() as rsps, open(IMG_PATH1, 'rb') as body:
            rsps.add(
                responses.GET, self.URL, status=200, body=body, content_type='image/png'
            )

            CoverArt.save_podcast_logo(self.URL)
Esempio n. 4
0
    def test_exception_during_fetch(self):
        with responses.RequestsMock() as rsps:
            rsps.add(responses.GET,
                     self.URL,
                     body=requests.exceptions.RequestException(
                         'Fetching URL failed'))

            CoverArt.save_podcast_logo(self.URL)
Esempio n. 5
0
 def test_save_empty_logo(self):
     """ Make sure that save_podcast_logo(None) does not fail """
     try:
         CoverArt.save_podcast_logo(None)
     except:
         self.fail(
             'CoverArt.save_podcast_logo(None) should not raise ' 'an exception'
         )
Esempio n. 6
0
def get_podcast_logo(podcast, feed):
    cover_art = podcast.logo_url
    image = feed.feed.get('image', None)
    if image is not None:
        for key in ('href', 'url'):
            cover_art = getattr(image, key, None)
            if cover_art:
                break

    if podcast.link:
        yturl = youtube.get_real_cover(podcast.link)
        if yturl:
            cover_art = yturl

    if cover_art:
        try:
            image_sha1 = hashlib.sha1(cover_art).hexdigest()
            prefix = CoverArt.get_prefix(image_sha1)

            filename = CoverArt.get_original(prefix, image_sha1)
            dirname = CoverArt.get_dir(filename)

            # get hash of existing file
            if os.path.exists(filename):
                with open(filename) as f:
                    old_hash = file_hash(f).digest()
            else:
                old_hash = ''

            print 'LOGO @', cover_art

            # save new cover art
            with open(filename, 'w') as fp:
                fp.write(urllib2.urlopen(cover_art).read())

            # get hash of new file
            with open(filename) as f:
                new_hash = file_hash(f).digest()

            # remove thumbnails if cover changed
            if old_hash != new_hash:
                thumbnails = CoverArt.get_existing_thumbnails(prefix, filename)
                print 'Removing %d thumbnails' % len(thumbnails)
                for f in thumbnails:
                    os.unlink(f)

            return  cover_art

        except Exception, e:
            if str(e).strip():
                try:
                    print >> sys.stderr, \
                        unicode('cannot save image for podcast %s: %s'
                        % (podcast.get_id(), str(e)), errors='ignore')
                except:
                    print >> sys.stderr, 'cannot save podcast logo'

            return None
Esempio n. 7
0
    def test_exception_during_fetch(self):
        with responses.RequestsMock() as rsps:
            rsps.add(
                responses.GET,
                self.URL,
                body=requests.exceptions.RequestException('Fetching URL failed'),
            )

            CoverArt.save_podcast_logo(self.URL)
Esempio n. 8
0
    def get_logo_url(self, size):
        if self.logo_url:
            filename = hashlib.sha1(self.logo_url).hexdigest()
        else:
            filename = 'podcast-%d.png' % (hash(self.title) % 5, )

        prefix = CoverArt.get_prefix(filename)

        return reverse('logo', args=[size, prefix, filename])
Esempio n. 9
0
def _save_podcast_logo(cover_art):
    if not cover_art:
        return

    try:
        image_sha1 = hashlib.sha1(cover_art.encode('utf-8')).hexdigest()
        prefix = CoverArt.get_prefix(image_sha1)

        filename = CoverArt.get_original(prefix, image_sha1)
        dirname = CoverArt.get_dir(filename)

        # get hash of existing file
        if os.path.exists(filename):
            with open(filename) as f:
                old_hash = file_hash(f).digest()
        else:
            old_hash = ''

        logger.info('Logo %s', cover_art)

        # save new cover art
        with open(filename, 'wb') as fp:
            fp.write(urllib.request.urlopen(cover_art).read())

        # get hash of new file
        with open(filename) as f:
            new_hash = file_hash(f).digest()

        # remove thumbnails if cover changed
        if old_hash != new_hash:
            thumbnails = CoverArt.get_existing_thumbnails(prefix, filename)
            logger.info('Removing %d thumbnails', len(thumbnails))
            for f in thumbnails:
                os.unlink(f)

        return cover_art

    except (urllib.error.HTTPError, urllib.error.URLError, ValueError,
            http.client.BadStatusLine, socket.error, IOError) as e:
        logger.warn('Exception while updating podcast logo: %s', str(e))
Esempio n. 10
0
    def test_new_logo(self):
        with responses.RequestsMock() as rsps, open(
                IMG_PATH1,
                'rb') as body1, open(IMG_PATH1,
                                     'rb') as body2, open(IMG_PATH2,
                                                          'rb') as body3:
            rsps.add(
                responses.GET,
                self.URL,
                status=200,
                body=body1,
                content_type='image/png',
            )
            rsps.add(
                responses.GET,
                self.URL,
                status=200,
                body=body2,
                content_type='image/png',
            )
            rsps.add(
                responses.GET,
                self.URL,
                status=200,
                body=body3,
                content_type='image/png',
            )

            logo_url = get_logo_url(self.podcast, 32)

            # first request
            CoverArt.save_podcast_logo(self.URL)
            response1 = self._fetch_cover(self.podcast)

            # stayed the same
            CoverArt.save_podcast_logo(self.URL)
            response2 = self._fetch_cover(self.podcast)

            self.assertEqual(list(response1.streaming_content),
                             list(response2.streaming_content))

            # changed
            CoverArt.save_podcast_logo(self.URL)
            response3 = self._fetch_cover(self.podcast)

            self.assertNotEqual(list(response2.streaming_content),
                                list(response3.streaming_content))
Esempio n. 11
0
    def test_new_logo(self):
        with responses.RequestsMock() as rsps, open(IMG_PATH1, 'rb') as body1, open(
            IMG_PATH1, 'rb'
        ) as body2, open(IMG_PATH2, 'rb') as body3:
            rsps.add(
                responses.GET,
                self.URL,
                status=200,
                body=body1,
                content_type='image/png',
            )
            rsps.add(
                responses.GET,
                self.URL,
                status=200,
                body=body2,
                content_type='image/png',
            )
            rsps.add(
                responses.GET,
                self.URL,
                status=200,
                body=body3,
                content_type='image/png',
            )

            logo_url = get_logo_url(self.podcast, 32)

            # first request
            CoverArt.save_podcast_logo(self.URL)
            response1 = self._fetch_cover(self.podcast)

            # stayed the same
            CoverArt.save_podcast_logo(self.URL)
            response2 = self._fetch_cover(self.podcast)

            self.assertEqual(
                list(response1.streaming_content), list(response2.streaming_content)
            )

            # changed
            CoverArt.save_podcast_logo(self.URL)
            response3 = self._fetch_cover(self.podcast)

            self.assertNotEqual(
                list(response2.streaming_content), list(response3.streaming_content)
            )
Esempio n. 12
0
import re

from django.urls import path
from django.conf import settings
from django.views.generic.base import TemplateView, RedirectView
from django.views.static import serve

from mygpo.web.logo import CoverArt

from . import views


urlpatterns = [
    path("", views.home, name="home"),
    path(
        "logo/<int:size>/<str:prefix>/<str:filename>", CoverArt.as_view(), name="logo"
    ),
    # Media files are also served in production mode. For performance, these
    # files should be served by a reverse proxy in practice
    path(
        "%s<path:path>" % settings.MEDIA_URL.lstrip("/"),
        serve,
        name="media",
        kwargs=dict(document_root=settings.MEDIA_ROOT),
    ),
    path("tags/", views.mytags, name="tags"),
    path(
        "online-help",
        RedirectView.as_view(
            url="http://gpoddernet.readthedocs.org/en/latest/user/index.html",
            permanent=False,
Esempio n. 13
0
    def _update_podcast(self, podcast, parsed, episode_updater, update_result):
        """ updates a podcast according to new parser results """

        # we need that later to decide if we can "bump" a category
        prev_latest_episode_timestamp = podcast.latest_episode_timestamp

        # will later be used to see whether the index is outdated
        old_index_fields = get_index_fields(podcast)

        podcast.title = parsed.get('title') or podcast.title
        podcast.description = parsed.get('description') or podcast.description
        podcast.subtitle = parsed.get('subtitle') or podcast.subtitle
        podcast.link = parsed.get('link') or podcast.link
        podcast.logo_url = parsed.get('logo') or podcast.logo_url

        podcast.author = to_maxlength(Podcast, 'author',
                                      parsed.get('author') or podcast.author)

        podcast.language = to_maxlength(
            Podcast, 'language',
            parsed.get('language') or podcast.language)

        podcast.content_types = (','.join(parsed.get('content_types'))
                                 or podcast.content_types)

        # podcast.tags['feed'] = parsed.tags or podcast.tags.get('feed', [])

        podcast.common_episode_title = to_maxlength(
            Podcast,
            'common_episode_title',
            parsed.get('common_title') or podcast.common_episode_title,
        )

        podcast.new_location = parsed.get(
            'new_location') or podcast.new_location
        podcast.flattr_url = to_maxlength(
            Podcast, 'flattr_url',
            parsed.get('flattr') or podcast.flattr_url)
        podcast.hub = parsed.get('hub') or podcast.hub
        podcast.license = parsed.get('license') or podcast.license
        podcast.max_episode_order = episode_updater.max_episode_order

        podcast.add_missing_urls(parsed.get('urls', []))

        if podcast.new_location:
            try:
                new_podcast = Podcast.objects.get(
                    urls__url=podcast.new_location)

                if new_podcast != podcast:
                    self._mark_outdated(podcast,
                                        'redirected to different podcast',
                                        episode_updater)
                    return
            except Podcast.DoesNotExist:
                podcast.set_url(podcast.new_location)

        # latest episode timestamp
        episodes = Episode.objects.filter(
            podcast=podcast, released__isnull=False).order_by('released')

        # Determine update interval

        # Update interval is based on intervals between episodes
        podcast.update_interval = episode_updater.get_update_interval(episodes)

        # factor is increased / decreased depending on whether the latest
        # update has returned episodes
        if update_result.episodes_added == 0:  # no episodes, incr factor
            newfactor = podcast.update_interval_factor * 1.2
            podcast.update_interval_factor = min(1000,
                                                 newfactor)  # never above 1000
        elif update_result.episodes_added > 1:  # new episodes, decr factor
            newfactor = podcast.update_interval_factor / 1.2
            podcast.update_interval_factor = max(1, newfactor)  # never below 1

        latest_episode = episodes.last()
        if latest_episode:
            podcast.latest_episode_timestamp = latest_episode.released

        # podcast.episode_count is not update here on purpose. It is, instead,
        # continuously updated when creating new episodes in
        # EpisodeManager.get_or_create_for_url

        self._update_categories(podcast, prev_latest_episode_timestamp)

        # try to download the logo and reset logo_url to None on http errors
        found = CoverArt.save_podcast_logo(podcast.logo_url)
        if not found:
            podcast.logo_url = None

        # check if search index should be considered out of date
        new_index_fields = get_index_fields(podcast)
        if list(old_index_fields.items()) != list(new_index_fields.items()):
            podcast.search_index_uptodate = False

        # The podcast is always saved (not just when there are changes) because
        # we need to record the last update
        logger.info('Saving podcast.')
        podcast.last_update = datetime.utcnow()
        podcast.save()

        try:
            subscribe_at_hub(podcast)
        except SubscriptionError as se:
            logger.warn('subscribing to hub failed: %s', str(se))

        self.assign_slug(podcast)
        episode_updater.assign_missing_episode_slugs()
        update_related_podcasts.delay(podcast.pk)
Esempio n. 14
0
from django.conf.urls import url
from django.views.generic.base import TemplateView, RedirectView

from mygpo.web.logo import CoverArt

from . import views


urlpatterns = [

    url(r'^$',
        views.home,
        name='home'),

    url(r'^logo/(?P<size>\d+)/(?P<prefix>.{3})/(?P<filename>[^/]*)$',
        CoverArt.as_view(),
        name='logo'),

    url(r'^tags/',
        views.mytags,
        name='tags'),

    url(r'^online-help',
        RedirectView.as_view(
            url='http://gpoddernet.readthedocs.org/en/latest/user/index.html',
            permanent=False,
        ),
        name='help'),

    url(r'^developer/',
        TemplateView.as_view(template_name='developer.html')),
Esempio n. 15
0
File: urls.py Progetto: Korvox/mygpo
from django.conf.urls import *
from django.contrib.auth.views import logout
from django.views.generic.base import TemplateView, RedirectView

from mygpo.web.logo import CoverArt


urlpatterns = patterns('mygpo.web.views',
 url(r'^$',                                                       'home',          name='home'),
 url(r'^logo/(?P<size>\d+)/(?P<prefix>.{3})/(?P<filename>[^/]*)$', CoverArt.as_view(), name='logo'),
 url(r'^tags/',                                                   'mytags',        name='tags'),

 url(r'^online-help',
     RedirectView.as_view(
        url='http://gpoddernet.readthedocs.org/en/latest/user/index.html',
        permanent=False,
     ),
     name='help'),

 url(r'^developer/',
     TemplateView.as_view(template_name='developer.html')),

 url(r'^contribute/',
     TemplateView.as_view(template_name='contribute.html'),
     name='contribute'),

 url(r'^privacy/',
     TemplateView.as_view(template_name='privacy_policy.html'),
     name='privacy-policy'),

)
Esempio n. 16
0
from django.views.generic.base import TemplateView, RedirectView
from django.views.static import serve

from mygpo.web.logo import CoverArt

from . import views


urlpatterns = [

    path('',
        views.home,
        name='home'),

    path('logo/<int:size>/<str:prefix>/<str:filename>',
        CoverArt.as_view(),
        name='logo'),

    # Media files are also served in production mode. For performance, these
    # files should be served by a reverse proxy in practice
    path('%s<path:path>' % settings.MEDIA_URL.lstrip('/'),
        serve,
        name='media',
        kwargs=dict(document_root=settings.MEDIA_ROOT)
    ),

    path('tags/',
        views.mytags,
        name='tags'),

    path('online-help',
Esempio n. 17
0
import re

from django.urls import path
from django.conf import settings
from django.views.generic.base import TemplateView, RedirectView
from django.views.static import serve

from mygpo.web.logo import CoverArt

from . import views


urlpatterns = [
    path('', views.home, name='home'),
    path(
        'logo/<int:size>/<str:prefix>/<str:filename>', CoverArt.as_view(), name='logo'
    ),
    # Media files are also served in production mode. For performance, these
    # files should be served by a reverse proxy in practice
    path(
        '%s<path:path>' % settings.MEDIA_URL.lstrip('/'),
        serve,
        name='media',
        kwargs=dict(document_root=settings.MEDIA_ROOT),
    ),
    path('tags/', views.mytags, name='tags'),
    path(
        'online-help',
        RedirectView.as_view(
            url='http://gpoddernet.readthedocs.org/en/latest/user/index.html',
            permanent=False,