Example #1
0
    def _best_match(self, videos):
        """ Select the best matching video from a list of videos. """
        if const.args.manual:
            log.info(self.raw_song)
            log.info('0. Skip downloading this song.\n')
            # fetch all video links on first page on YouTube
            for i, v in enumerate(videos):
                log.info(u'{0}. {1} {2} {3}'.format(
                    i + 1, v['title'], v['videotime'],
                    "http://youtube.com/watch?v=" + v['link']))
            # let user select the song to download
            result = internals.input_link(videos)
            if result is None:
                return None
        else:
            if not self.meta_tags:
                # if the metadata could not be acquired, take the first result
                # from Youtube because the proper song length is unknown
                result = videos[0]
                log.debug(
                    'Since no metadata found on Spotify, going with the first result'
                )
            else:
                # filter out videos that do not have a similar length to the Spotify song
                duration_tolerance = 10
                max_duration_tolerance = 20
                possible_videos_by_duration = []

                # start with a reasonable duration_tolerance, and increment duration_tolerance
                # until one of the Youtube results falls within the correct duration or
                # the duration_tolerance has reached the max_duration_tolerance
                while len(possible_videos_by_duration) == 0:
                    possible_videos_by_duration = list(
                        filter(
                            lambda x: abs(x['seconds'] - self.meta_tags[
                                'duration']) <= duration_tolerance, videos))
                    duration_tolerance += 1
                    if duration_tolerance > max_duration_tolerance:
                        log.error("{0} by {1} was not found.\n".format(
                            self.meta_tags['name'],
                            self.meta_tags['artists'][0]['name']))
                        return None

                result = possible_videos_by_duration[0]

        if result:
            url = "http://youtube.com/watch?v={0}".format(result['link'])
        else:
            url = None

        return url
Example #2
0
def feed_playlist(username):
    """ Fetch user playlists when using the -u option. """
    playlists = spotify.user_playlists(username)
    links = []
    check = 1

    while True:
        for playlist in playlists['items']:
            # in rare cases, playlists may not be found, so playlists['next']
            # is None. Skip these. Also see Issue #91.
            if playlist['name'] is not None:
                log.info(u'{0:>5}. {1:<30}  ({2} tracks)'.format(
                    check, playlist['name'], playlist['tracks']['total']))
                log.debug(playlist['external_urls']['spotify'])
                links.append(playlist)
                check += 1
        if playlists['next']:
            playlists = spotify.next(playlists)
        else:
            break

    playlist = internals.input_link(links)
    write_playlist(playlist['owner']['id'], playlist['id'])
Example #3
0
def write_user_playlist(username, text_file=None):
    links = get_playlists(username=username)
    playlist = internals.input_link(links)
    return write_playlist(playlist, text_file)
Example #4
0
def generate_youtube_url(raw_song, meta_tags, tries_remaining=5):
    """ Search for the song on YouTube and generate a URL to its video. """
    # prevents an infinite loop but allows for a few retries
    if tries_remaining == 0:
        log.debug('No tries left. I quit.')
        return

    query = {'part': 'snippet', 'maxResults': 50, 'type': 'video'}

    if args.music_videos_only:
        query['videoCategoryId'] = '10'

    if meta_tags is None:
        song = raw_song
        query['q'] = song
    else:
        song = generate_songname(meta_tags)
        query['q'] = song
    log.debug('Query: {0}'.format(query))

    data = pafy.call_gdata('search', query)
    query2 = {
        'part': 'contentDetails,snippet,statistics',
        'maxResults': 50,
        'id': ','.join(i['id']['videoId'] for i in data['items'])
    }
    log.debug('Query2: {0}'.format(query2))

    vdata = pafy.call_gdata('videos', query2)

    videos = []
    for x in vdata['items']:
        duration_s = pafy.playlist.parseISO8591(
            x['contentDetails']['duration'])
        youtubedetails = {
            'link': x['id'],
            'title': x['snippet']['title'],
            'videotime': internals.videotime_from_seconds(duration_s),
            'seconds': duration_s
        }
        videos.append(youtubedetails)
        if meta_tags is None:
            break

    if not videos:
        return None

    log.debug(pprint.pformat(videos))

    if args.manual:
        log.info(song)
        log.info('0. Skip downloading this song.\n')
        # fetch all video links on first page on YouTube
        for i, v in enumerate(videos):
            log.info(u'{0}. {1} {2} {3}'.format(
                i + 1, v['title'], v['videotime'],
                "http://youtube.com/watch?v=" + v['link']))
        # let user select the song to download
        result = internals.input_link(videos)
        if result is None:
            return None
    else:
        if meta_tags is None:
            # if the metadata could not be acquired, take the first result
            # from Youtube because the proper song length is unknown
            result = videos[0]
            log.debug(
                'Since no metadata found on Spotify, going with the first result'
            )
        else:
            # filter out videos that do not have a similar length to the Spotify song
            duration_tolerance = 10
            max_duration_tolerance = 20
            possible_videos_by_duration = list()
            '''
            start with a reasonable duration_tolerance, and increment duration_tolerance
            until one of the Youtube results falls within the correct duration or
            the duration_tolerance has reached the max_duration_tolerance
            '''
            while len(possible_videos_by_duration) == 0:
                possible_videos_by_duration = list(
                    filter(
                        lambda x: abs(x['seconds'] - (int(meta_tags[
                            'duration_ms']) / 1000)) <= duration_tolerance,
                        videos))
                duration_tolerance += 1
                if duration_tolerance > max_duration_tolerance:
                    log.error("{0} by {1} was not found.\n".format(
                        meta_tags['name'], meta_tags['artists'][0]['name']))
                    return None

            result = possible_videos_by_duration[0]

    if result:
        url = "http://youtube.com/watch?v=" + result['link']
    else:
        url = None

    return url
Example #5
0
def generate_youtube_url(raw_song, meta_tags, tries_remaining=5):
    """ Search for the song on YouTube and generate a URL to its video. """
    # prevents an infinite loop but allows for a few retries
    if tries_remaining == 0:
        log.debug('No tries left. I quit.')
        return

    if meta_tags is None:
        song = raw_song
        search_url = internals.generate_search_url(song, viewsort=False)
    else:
        song = generate_songname(meta_tags)
        search_url = internals.generate_search_url(song, viewsort=True)
    log.debug('Opening URL: {0}'.format(search_url))

    item = urllib.request.urlopen(search_url).read()
    items_parse = BeautifulSoup(item, "html.parser")

    videos = []
    for x in items_parse.find_all(
            'div', {'class': 'yt-lockup-dismissable yt-uix-tile'}):

        if not is_video(x):
            continue

        y = x.find('div', class_='yt-lockup-content')
        link = y.find('a')['href']
        title = y.find('a')['title']

        try:
            videotime = x.find('span', class_="video-time").get_text()
        except AttributeError:
            log.debug('Could not find video duration on YouTube, retrying..')
            return generate_youtube_url(raw_song, meta_tags,
                                        tries_remaining - 1)

        youtubedetails = {
            'link': link,
            'title': title,
            'videotime': videotime,
            'seconds': internals.get_sec(videotime)
        }
        videos.append(youtubedetails)
        if meta_tags is None:
            break

    if not videos:
        return None

    log.debug(pprint.pformat(videos))

    if args.manual:
        log.info(song)
        log.info('0. Skip downloading this song.\n')
        # fetch all video links on first page on YouTube
        for i, v in enumerate(videos):
            log.info(u'{0}. {1} {2} {3}'.format(
                i + 1, v['title'], v['videotime'],
                "http://youtube.com" + v['link']))
        # let user select the song to download
        result = internals.input_link(videos)
        if result is None:
            return None
    else:
        if meta_tags is None:
            # if the metadata could not be acquired, take the first result
            # from Youtube because the proper song length is unknown
            result = videos[0]
            log.debug(
                'Since no metadata found on Spotify, going with the first result'
            )
        else:
            # filter out videos that do not have a similar length to the Spotify song
            duration_tolerance = 10
            max_duration_tolerance = 20
            possible_videos_by_duration = list()
            '''
            start with a reasonable duration_tolerance, and increment duration_tolerance
            until one of the Youtube results falls within the correct duration or
            the duration_tolerance has reached the max_duration_tolerance
            '''
            while len(possible_videos_by_duration) == 0:
                possible_videos_by_duration = list(
                    filter(
                        lambda x: abs(x['seconds'] - (int(meta_tags[
                            'duration_ms']) / 1000)) <= duration_tolerance,
                        videos))
                duration_tolerance += 1
                if duration_tolerance > max_duration_tolerance:
                    log.error("{0} by {1} was not found.\n".format(
                        meta_tags['name'], meta_tags['artists'][0]['name']))
                    return None

            result = possible_videos_by_duration[0]

    if result:
        full_link = u'http://youtube.com{0}'.format(result['link'])
    else:
        full_link = None

    log.debug('Best matching video link: {}'.format(full_link))
    return full_link