Clementine-audio-player-Mac.../src/internet/dropboxservice.cpp

199 lines
5.8 KiB
C++
Raw Normal View History

2012-11-29 18:19:41 +01:00
#include "dropboxservice.h"
2012-11-29 20:18:08 +01:00
#include <QFileInfo>
2012-11-29 18:48:49 +01:00
#include <qjson/parser.h>
2012-11-29 20:18:08 +01:00
#include "core/application.h"
#include "core/logging.h"
#include "core/network.h"
2012-11-29 20:18:08 +01:00
#include "core/player.h"
#include "core/utilities.h"
2012-11-29 20:18:08 +01:00
#include "core/waitforsignal.h"
2012-11-29 18:19:41 +01:00
#include "internet/dropboxauthenticator.h"
2012-11-29 20:18:08 +01:00
#include "internet/dropboxurlhandler.h"
#include "library/librarybackend.h"
using Utilities::ParseRFC822DateTime;
2012-11-29 18:19:41 +01:00
const char* DropboxService::kServiceName = "Dropbox";
const char* DropboxService::kSettingsGroup = "Dropbox";
namespace {
static const char* kServiceId = "dropbox";
static const char* kMetadataEndpoint =
"https://api.dropbox.com/1/metadata/dropbox/";
2012-11-29 20:18:08 +01:00
static const char* kMediaEndpoint =
"https://api.dropbox.com/1/media/dropbox/";
2012-11-29 18:19:41 +01:00
} // namespace
DropboxService::DropboxService(Application* app, InternetModel* parent)
: CloudFileService(
app, parent,
kServiceName, kServiceId,
QIcon(":/providers/dropbox.png"),
SettingsDialog::Page_Dropbox),
network_(new NetworkAccessManager(this)) {
QSettings settings;
settings.beginGroup(kSettingsGroup);
access_token_ = settings.value("access_token").toString();
access_token_secret_ = settings.value("access_token_secret").toString();
2012-11-29 20:18:08 +01:00
app->player()->RegisterUrlHandler(new DropboxUrlHandler(this, this));
2012-11-29 18:19:41 +01:00
}
bool DropboxService::has_credentials() const {
return !access_token_.isEmpty();
}
void DropboxService::Connect() {
if (has_credentials()) {
RequestFileList("");
2012-11-29 18:19:41 +01:00
} else {
ShowSettingsDialog();
}
}
void DropboxService::AuthenticationFinished(DropboxAuthenticator* authenticator) {
authenticator->deleteLater();
access_token_ = authenticator->access_token();
access_token_secret_ = authenticator->access_token_secret();
2012-11-29 18:19:41 +01:00
QSettings settings;
settings.beginGroup(kSettingsGroup);
settings.setValue("access_token", access_token_);
settings.setValue("access_token_secret", access_token_secret_);
2012-11-29 18:19:41 +01:00
settings.setValue("name", authenticator->name());
emit Connected();
RequestFileList("");
}
QByteArray DropboxService::GenerateAuthorisationHeader() {
return DropboxAuthenticator::GenerateAuthorisationHeader(
access_token_,
access_token_secret_);
}
void DropboxService::RequestFileList(const QString& path) {
QUrl url(QString(kMetadataEndpoint) + path);
QNetworkRequest request(url);
request.setRawHeader("Authorization", GenerateAuthorisationHeader());
QNetworkReply* reply = network_->get(request);
NewClosure(reply, SIGNAL(finished()),
this, SLOT(RequestFileListFinished(QNetworkReply*)), reply);
}
2012-11-29 18:48:49 +01:00
namespace {
bool IsSupportedMimeType(const QString& mime_type) {
return mime_type == "audio/ogg" ||
mime_type == "audio/mpeg";
}
} // namespace
void DropboxService::RequestFileListFinished(QNetworkReply* reply) {
reply->deleteLater();
2012-11-29 18:48:49 +01:00
QJson::Parser parser;
QVariantMap response = parser.parse(reply).toMap();
QVariantList contents = response["contents"].toList();
foreach (const QVariant& c, contents) {
QVariantMap item = c.toMap();
const bool directory = item["is_dir"].toBool();
if (directory) {
RequestFileList(item["path"].toString());
} else {
2012-11-29 20:18:08 +01:00
QUrl url;
url.setScheme("dropbox");
url.setPath(item["path"].toString());
MaybeAddFileToDatabase(url, item);
2012-11-29 18:48:49 +01:00
}
}
2012-11-29 18:19:41 +01:00
}
2012-11-29 20:18:08 +01:00
void DropboxService::MaybeAddFileToDatabase(
const QUrl& url, const QVariantMap& file) {
if (!IsSupportedMimeType(file["mime_type"].toString())) {
return;
}
Song song = library_backend_->GetSongByUrl(url);
if (song.is_valid()) {
return;
}
QNetworkReply* reply = FetchContentUrl(url);
NewClosure(reply, SIGNAL(finished()),
this, SLOT(FetchContentUrlFinished(QNetworkReply*, QVariantMap)),
reply, file);
}
2012-11-29 20:18:08 +01:00
QNetworkReply* DropboxService::FetchContentUrl(const QUrl& url) {
QUrl request_url(QString(kMediaEndpoint) + url.path());
QNetworkRequest request(request_url);
request.setRawHeader("Authorization", GenerateAuthorisationHeader());
return network_->post(request, QByteArray());
}
void DropboxService::FetchContentUrlFinished(
QNetworkReply* reply, const QVariantMap& data) {
reply->deleteLater();
QJson::Parser parser;
QVariantMap response = parser.parse(reply).toMap();
QFileInfo info(data["path"].toString());
TagReaderClient::ReplyType* tag_reply = app_->tag_reader_client()->ReadCloudFile(
response["url"].toUrl(),
info.fileName(),
data["bytes"].toInt(),
data["mime_type"].toString(),
QString::null);
NewClosure(tag_reply, SIGNAL(Finished(bool)),
this, SLOT(ReadTagsFinished(TagReaderClient::ReplyType*,QVariantMap)),
tag_reply, data);
2012-11-29 20:18:08 +01:00
}
void DropboxService::ReadTagsFinished(
TagReaderClient::ReplyType* reply, const QVariantMap& file) {
qLog(Debug) << reply->message().DebugString().c_str();
const auto& message = reply->message().read_cloud_file_response();
if (!message.has_metadata() ||
!message.metadata().filesize()) {
qLog(Debug) << "Failed to tag:" << file["path"].toString();
return;
}
Song song;
song.InitFromProtobuf(message.metadata());
song.set_directory_id(0);
song.set_etag(file["rev"].toString());
song.set_mtime(ParseRFC822DateTime(file["modified"].toString()).toTime_t());
QUrl url;
url.setScheme("dropbox");
url.setPath(file["path"].toString());
song.set_url(url);
if (song.title().isEmpty()) {
QFileInfo info(file["path"].toString());
song.set_title(info.fileName());
}
qLog(Debug) << "Adding song to db:" << song.title();
library_backend_->AddOrUpdateSongs(SongList() << song);
2012-11-29 20:18:08 +01:00
}
QUrl DropboxService::GetStreamingUrlFromSongId(const QUrl& url) {
QNetworkReply* reply = FetchContentUrl(url);
WaitForSignal(reply, SIGNAL(finished()));
QJson::Parser parser;
QVariantMap response = parser.parse(reply).toMap();
return response["url"].toUrl();
}