Open ghost opened 4 years ago
I'm not fonol, but I wrote this new YouTube quick import thing, which automatically copies the youtube title and channel name into the new note. If fonol approves of this feature, I can have a look at the feasibility of doing this.
@p4nix Sure, sounds like a useful feature!
so i managed to do it over the last couple days - just to test the concept - and it worked (similar to how the url dialogue works), however i used youtube-dl library to parse the playlist's videos' ids, so i am not sure you would want to integrate that (because of DMCA issues).
from aqt.qt import *
import aqt.editor
import aqt
import functools
import re
from ..notes import *
import random
from aqt.utils import showInfo
import youtube_dl
from ..index.fts_index import Worker
import utility.text
import utility.misc
from ..youtube_dl import YoutubeDL
import utility.misc
YOUTUBE_URL_REGEX = re.compile(r"^(http|https):\/\/(?:www\.)?youtube\.com\/(?:watch|playlist)\?(?:&.*)*((?:v=([^&\s]*)(?:&.*)*&list=(?P<ListID>[^&\s]*)|(?:list=(?P<ListID1>[^&\s])*)(?:&.*)*&v=([^&\s]*)|(?:list=(?P<ListID2>[^#\&\?]*))))(?:&.*)*(?:\#.*)*")
class YoutubePlayListDialog(QDialog):
"""Fetches the url"""
def __init__(self, parent):
QDialog.__init__(self, parent, Qt.WindowSystemMenuHint | Qt.WindowTitleHint | Qt.WindowCloseButtonHint)
self.chosen_url = None
self.parent = parent
self.videos = None
self.setup_ui()
self.setWindowTitle("Youtube Playlist Input")
self.threadPool = QThreadPool()
def setup_ui(self):
self.vbox = QVBoxLayout()
self.vbox.addWidget(QLabel("This will import the Playlist videos."))
self.vbox.addSpacing(10)
self.vbox.addWidget(QLabel("URL:"))
self.input = QLineEdit()
self.input.setMinimumWidth(300)
self.vbox.addWidget(self.input)
self.vbox.addSpacing(15)
hbox_bot = QHBoxLayout()
self.accept_btn = QPushButton("Fetch")
self.accept_btn.setShortcut("Ctrl+Return")
self.accept_btn.clicked.connect(self.accept_clicked)
self.reject_btn = QPushButton("Cancel")
self.reject_btn.clicked.connect(self.reject)
hbox_bot.addStretch(1)
hbox_bot.addWidget(self.accept_btn)
hbox_bot.addWidget(self.reject_btn)
self.vbox.addLayout(hbox_bot)
self.setLayout(self.vbox)
def _is_youtube_playlist(self, url: str) -> bool:
return url is not None and (YOUTUBE_URL_REGEX.match(url).group("ListID") or \
YOUTUBE_URL_REGEX.match(url).group("ListID1") or \
YOUTUBE_URL_REGEX.match(url).group("ListID2")) is not None
def accept_clicked(self):
self.chosen_url = self.input.text()
if self._is_youtube_playlist(self.chosen_url):
worker = Worker(self._load_yt_playlistvids,self.chosen_url)
worker.signals = WorkerSignals()
worker.signals.result.connect(self._success)
worker.stamp = utility.misc.get_milisec_stamp()
self.threadPool.start(worker)
def _success(self, vids: tuple,nothing):
self.videos = vids
self.accept()
def _load_yt_playlistvids(self, playlist: str):
ydl_opts = {
'ignoreerrors' : True,
'quiet' : True,
'yesplaylist' : True,
}
result = ()
with YoutubeDL(ydl_opts) as ydl:
playlist_dict = ydl.extract_info(playlist, download=False)
for video in playlist_dict['entries']:
video_details = {}
if not video:
# TODO add to logger
print('ERROR: Unable to get info. Continuing...')
continue
video_details["source"] = f'https://www.youtube.com/watch?v={video.get("id")}'
video_details["title"] = video.get("title")
result = result + (video_details,)
return result
class WorkerSignals(QObject):
finished = pyqtSignal()
error = pyqtSignal(tuple)
result = pyqtSignal(tuple,object)
Thanks for the code. To be honest, I would prefer a solution without that external library. This add-on is already quite bloated, so I don't really like including just another library just for an edge-usecase. I could imagine using YouTube's data API, which has the advantage of being 100% safe and legal and would eliminate the need to include any additional libraries. However, you need an API key, and I am also not really a fan of solutions that require external setup of any kind to be usable.
Perhaps going with a user-configurable YouTube API key would be the way? - and would also allow to extend the Quick YT dialog with a search function, as I envisioned in the beginning. But this would add to the complexity again... And there is so much on the list next to studying already anyway ^^
It would be really awesome to batch load MIT's OCW courses -as well as my university courses as they shift towards e-learning thanks to the pandemic- and incrementally watch them since I use them as supplement material to my university's courses. I assume others would find it particularly appealing too due to the now wide availability of free Youtube courses packed in playlist formats.