Skip to content

Commit

Permalink
Add WebAPI for downloading torrent metadata
Browse files Browse the repository at this point in the history
Signed-off-by: Thomas Piccirello <thomas@piccirello.com>
  • Loading branch information
Piccirello committed Dec 14, 2024
1 parent 7ddc6c8 commit 773b344
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/base/bittorrent/torrentdescriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,22 @@ catch (const lt::system_error &err)
return nonstd::make_unexpected(QString::fromLocal8Bit(err.what()));
}

nonstd::expected<QByteArray, QString> BitTorrent::TorrentDescriptor::saveToBuffer() const
try
{
const lt::entry torrentEntry = lt::write_torrent_file(m_ltAddTorrentParams);
// usually torrent size should be smaller than 1 MB,
// however there are >100 MB v2/hybrid torrent files out in the wild
QByteArray buffer;
buffer.reserve(1024 * 1024);
lt::bencode(std::back_inserter(buffer), torrentEntry);
return buffer;
}
catch (const lt::system_error &err)
{
return nonstd::make_unexpected(QString::fromLocal8Bit(err.what()));
}

BitTorrent::TorrentDescriptor::TorrentDescriptor(lt::add_torrent_params ltAddTorrentParams)
: m_ltAddTorrentParams {std::move(ltAddTorrentParams)}
{
Expand Down
1 change: 1 addition & 0 deletions src/base/bittorrent/torrentdescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ namespace BitTorrent
static nonstd::expected<TorrentDescriptor, QString> loadFromFile(const Path &path) noexcept;
static nonstd::expected<TorrentDescriptor, QString> parse(const QString &str) noexcept;
nonstd::expected<void, QString> saveToFile(const Path &path) const;
nonstd::expected<QByteArray, QString> saveToBuffer() const;

const lt::add_torrent_params &ltAddTorrentParams() const;

Expand Down
37 changes: 37 additions & 0 deletions src/webui/api/torrentscontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1895,6 +1895,43 @@ void TorrentsController::parseMetadataAction()
setResult(result);
}

void TorrentsController::saveMetadataAction()
{
requireParams({u"source"_s});

const QString sourceParam = params()[u"source"_s].trimmed();
if (sourceParam.isEmpty())
throw APIError(APIErrorType::BadParams, tr("Must specify URI or hash"));

const QString source = QUrl::fromPercentEncoding(sourceParam.toLatin1());

BitTorrent::InfoHash infoHash;
if (const auto sourceTorrentDescr = BitTorrent::TorrentDescriptor::parse(source))
infoHash = sourceTorrentDescr.value().infoHash();
else if (const auto cachedInfoHash = m_torrentSourceCache.get(source))
infoHash = cachedInfoHash.value();

if (infoHash != BitTorrent::InfoHash {})
{
if (const auto torrentDescr = m_torrentMetadataCache.get(infoHash))
{
const nonstd::expected<QByteArray, QString> result = torrentDescr.value().saveToBuffer();
if (!result)
throw APIError(APIErrorType::Conflict, tr("Unable to export torrent metadata. Error: %1").arg(result.error()));

setResult(result.value(), u"application/x-bittorrent"_s, (infoHash.toTorrentID().toString() + u".torrent"));
}
else
{
throw APIError(APIErrorType::Conflict, tr("Metadata is not yet available"));
}
}
else
{
throw APIError(APIErrorType::NotFound);
}
}

void TorrentsController::onDownloadFinished(const Net::DownloadResult &result)
{
const QString source = result.url;
Expand Down
1 change: 1 addition & 0 deletions src/webui/api/torrentscontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ private slots:
void setSSLParametersAction();
void fetchMetadataAction();
void parseMetadataAction();
void saveMetadataAction();

private:
void onDownloadFinished(const Net::DownloadResult &result);
Expand Down

0 comments on commit 773b344

Please sign in to comment.