File indexing completed on 2024-05-12 16:21:17
0001 // SPDX-FileCopyrightText: 2023 Théophile Gilgien <theophile@gilgien.net> 0002 // 0003 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 0005 #include "playlistimporter.h" 0006 #include "playlistutils.h" 0007 0008 #include "library.h" 0009 #include <qglobal.h> 0010 #include <qsqldatabase.h> 0011 #include <threadeddatabase.h> 0012 0013 #include <KLocalizedString> 0014 0015 PlaylistImporter::PlaylistImporter(QObject* parent) 0016 :QObject(parent) 0017 {} 0018 0019 0020 void PlaylistImporter::importPlaylist(const QString &url) 0021 { 0022 const QString croppedURL = this->cropURL(url).toString(), title = i18n("Unknown"), description = i18n("No description"); 0023 QCoro::connect(Library::instance().database().execute("insert into playlists (title, description) values (?, ?)", title, description), &Library::instance(), [this, croppedURL]() { 0024 QCoro::connect(Library::instance().database().getResults<SingleValue<qint64>>("select * from playlists"), &Library::instance(), [this, croppedURL](auto &&playlists) { 0025 const quint64 playlistId = playlists.back().value; 0026 Q_EMIT Library::instance().playlistsChanged(); 0027 0028 QCoro::connect(YTMusicThread::instance()->fetchPlaylist(croppedURL), this, [this, playlistId](auto &&playlist) { 0029 this->renamePlaylist(playlistId, QString::fromStdString(playlist.title), QString::fromStdString(playlist.author.name)); 0030 0031 for (const auto& track : playlist.tracks) { 0032 if (track.is_available && track.video_id) { 0033 this->addPlaylistEntry(playlistId, track); 0034 } 0035 } 0036 0037 Q_EMIT Library::instance().playlistsChanged(); 0038 Q_EMIT importFinished(); 0039 }); 0040 }); 0041 }); 0042 } 0043 0044 void PlaylistImporter::addPlaylistEntry(qint64 playlistId, const QString &videoId, const QString &title, const QString &artist, const QString &album) 0045 { 0046 QCoro::connect(Library::instance().addSong(videoId, title, artist, album), this, [=, this] { 0047 QCoro::connect(Library::instance().database().execute("insert into playlist_entries (playlist_id, video_id) values (?, ?)", playlistId, videoId), this, [=, this] { 0048 Q_EMIT playlistEntriesChanged(playlistId); 0049 }); 0050 }); 0051 } 0052 0053 void PlaylistImporter::addPlaylistEntry(qint64 playlistId, const playlist::Track &track) 0054 { 0055 const QString videoId = track.video_id.value().c_str(); 0056 const QString title = (!track.title.empty()) ? QString::fromStdString(track.title) : i18n("No title"); 0057 const QString artists = PlaylistUtils::artistsToString(track.artists); 0058 const QString album = (track.album ) ? QString::fromStdString(track.album->name) : i18n("No album"); 0059 this->addPlaylistEntry(playlistId, videoId, title, artists, album); 0060 } 0061 0062 void PlaylistImporter::renamePlaylist(qint64 playlistId, const QString &name, const QString &description) 0063 { 0064 QCoro::connect(Library::instance().database().execute("update playlists set title = ? , description = ? where playlist_id = ?", name, description, playlistId), this, &PlaylistImporter::refreshModel); 0065 } 0066 0067 0068 QStringView PlaylistImporter::cropURL(QStringView srcUrl) 0069 { 0070 // Find entry point 0071 constexpr auto urlFragment = QStringView(u"?list="); 0072 qsizetype urlPos = srcUrl.indexOf(urlFragment); 0073 if (urlPos != -1) { 0074 urlPos += urlFragment.size(); 0075 } else { 0076 urlPos = 0; 0077 } 0078 auto mid = srcUrl.mid(urlPos); 0079 0080 // Find exit point 0081 urlPos = std::min(mid.indexOf(u"?"), mid.indexOf(u"&")); 0082 return mid.mid(0, urlPos); 0083 }