Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix mix command #1261

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions mps_youtube/commands/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from .. import c, config, content, contentquery, g, listview, screen, util
from ..playlist import Playlist, Video
from . import command
from .songlist import paginatesongs, plist
from .songlist import paginatesongs, plist, mixlist

ISO8601_TIMEDUR_EX = re.compile(r'PT((\d{1,3})H)?((\d{1,3})M)?((\d{1,2})S)?')

Expand Down Expand Up @@ -523,11 +523,10 @@ def mix(num):
if item is None:
g.message = util.F('invalid item')
return
item = util.get_pafy(item)
# Mix playlists are made up of 'RD' + video_id
item = g.model[int(num) -1]
try:
plist("RD" + item.videoid)
except OSError:
mixlist(item.ytid)
except KeyError:
g.message = util.F('no mix')


Expand Down
15 changes: 15 additions & 0 deletions mps_youtube/commands/songlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,21 @@ def pl_seg(s, e):
loadmsg = "Retrieving YouTube playlist"
paginatesongs(pl_seg, length=len(ytpl.videos), msg=msg, loadmsg=loadmsg)

def mixlist(video_url):
""" Retrieve YouTube mix from video slug """

util.dbg("%sFetching mix using pafy%s", c.y, c.w)
# No caching here because mixes are different every time they are retrieved
ytpl = pafy.get_mix(video_url)
plitems = util.IterSlicer(ytpl.songs)

def pl_seg(s, e):
return [Video(i["id"], i["title"], i["duration_parsed"]) for i in plitems[s:e]]

msg = "Showing YouTube playlist %s" % (c.y + ytpl.name + c.w)
loadmsg = "Retrieving YouTube playlist"
paginatesongs(pl_seg, length=len(ytpl.songs), msg=msg, loadmsg=loadmsg)


@command(r'(rm|add)\s*(-?\d[-,\d\s]{,250})', 'rm', 'add')
def songlist_rm_add(action, songrange):
Expand Down
43 changes: 42 additions & 1 deletion mps_youtube/pafy.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import yt_dlp
from youtubesearchpython import VideosSearch, ChannelsSearch, PlaylistsSearch, Suggestions, Playlist, playlist_from_channel_id, Comments, Video, Channel, ChannelSearch

from . import playlists


class MyLogger:

Expand Down Expand Up @@ -107,6 +109,45 @@ def get_playlist(playlist_id):
playlist.getNextVideos()
return playlist

def get_mix(video_id):

'''
Get a list of all videos (max 100) in the mix of the specified video_id
'''

# youtubesearchpython gets playlists by parsing the HTML of the
# corresponding page, and this doesn't work for mixes. so, we need to
# enlist the help of yt-dlp instead

# Mix playlist IDs are made up of "RD" + video_id
# In order to see the mix, we need to fetch the first video in the list
playlist_url = "https://www.youtube.com/watch?v=%s&list=RD%s" % (video_id, video_id)

ydl_opts = {
"extract_flat": True,
"playlist_items": "1-100",
"dump_single_json": True,
"logger": MyLogger()
}
playlist_data = {}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
playlist_data = ydl.extract_info(playlist_url)

videos = []
for video_data in playlist_data["entries"]:
video = {}

video["id"] = video_data["id"]
video["title"] = video_data["title"]
video["link"] = "https://www.youtube.com/watch?v=%s" % video_data["id"]
video["duration_parsed"] = video_data["duration"]

videos.append(video)

# NB: We use a playlists.Playlist instead of youtubesearchpython.Playlist
playlist = playlists.Playlist(playlist_data["title"], videos)
return playlist

def get_video_title_suggestions(query):
suggestions = Suggestions(language = 'en', region = 'US')
related_searches = suggestions.get(query)['result']
Expand Down Expand Up @@ -236,4 +277,4 @@ def get_subtitles(ytid, output_dir):
# Download the subtitle
ydl.download([url])
path = f'{outtmpl}.{lang}.vtt'
return path if os.path.isfile(path) else None
return path if os.path.isfile(path) else None