mirror of
https://github.com/transmission/transmission
synced 2025-02-22 14:10:34 +00:00
support for resuming magnet links (#2702)
* support for resuming magnet links magnet links are now saved as a text file the `Torrents` folder as `.magnet` files.
This commit is contained in:
parent
cc7d1c5f01
commit
943b57979f
8 changed files with 70 additions and 8 deletions
|
@ -181,7 +181,6 @@ std::string tr_magnet_metainfo::magnet() const
|
|||
bool tr_magnet_metainfo::parseMagnet(std::string_view magnet_link, tr_error** error)
|
||||
{
|
||||
magnet_link = tr_strvStrip(magnet_link);
|
||||
|
||||
if (auto const hash = parseHash(magnet_link); hash)
|
||||
{
|
||||
return parseMagnet(tr_strvJoin("magnet:?xt=urn:btih:", tr_sha1_to_string(*hash)));
|
||||
|
|
|
@ -27,6 +27,7 @@ public:
|
|||
{
|
||||
return info_hash_;
|
||||
}
|
||||
|
||||
auto const& name() const
|
||||
{
|
||||
return name_;
|
||||
|
|
|
@ -2041,13 +2041,25 @@ static void sessionLoadTorrents(void* vdata)
|
|||
char const* name = nullptr;
|
||||
while ((name = tr_sys_dir_read_name(odir, nullptr)) != nullptr)
|
||||
{
|
||||
if (!tr_strvEndsWith(name, ".torrent"sv))
|
||||
if (!tr_strvEndsWith(name, ".torrent"sv) && !tr_strvEndsWith(name, ".magnet"sv))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
tr_buildBuf(path, dirname_sv, "/", name);
|
||||
tr_ctorSetMetainfoFromFile(data->ctor, path, nullptr);
|
||||
|
||||
// is a magnet link?
|
||||
if (!tr_ctorSetMetainfoFromFile(data->ctor, path, nullptr))
|
||||
{
|
||||
if (auto buf = std::vector<char>{}; tr_loadFile(buf, path))
|
||||
{
|
||||
tr_ctorSetMetainfoFromMagnetLink(
|
||||
data->ctor,
|
||||
std::string{ std::data(buf), std::size(buf) }.c_str(),
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (tr_torrent* const tor = tr_torrentNew(data->ctor, nullptr); tor != nullptr)
|
||||
{
|
||||
torrents.push_back(tor);
|
||||
|
|
|
@ -127,6 +127,20 @@ bool tr_ctorSaveContents(tr_ctor const* ctor, std::string const& filename, tr_er
|
|||
return tr_saveFile(filename, { std::data(ctor->contents), std::size(ctor->contents) }, error);
|
||||
}
|
||||
|
||||
bool tr_ctorSaveMagnetContents(tr_torrent* tor, std::string const& filename, tr_error** error)
|
||||
{
|
||||
TR_ASSERT(tor != nullptr);
|
||||
TR_ASSERT(!std::empty(filename));
|
||||
|
||||
auto const magnet = tor->magnet();
|
||||
if (std::empty(magnet))
|
||||
{
|
||||
tr_error_set(error, EINVAL, "torrent has no magnetlink to save"sv);
|
||||
return false;
|
||||
}
|
||||
return tr_saveFile(filename, magnet, error);
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
|
|
@ -278,6 +278,9 @@ static bool useNewMetainfo(tr_torrent* tor, tr_incomplete_metadata const* m, tr_
|
|||
return false;
|
||||
}
|
||||
|
||||
// remove .magnet file
|
||||
tr_sys_path_remove(tor->magnetFile().c_str(), nullptr);
|
||||
|
||||
// tor should keep this metainfo
|
||||
tor->setMetainfo(metainfo);
|
||||
|
||||
|
|
|
@ -139,6 +139,11 @@ public:
|
|||
return makeFilename(torrent_dir, name(), infoHashString(), BasenameFormat::Hash, ".torrent");
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string magnetFile(std::string_view torrent_dir) const
|
||||
{
|
||||
return makeFilename(torrent_dir, name(), infoHashString(), BasenameFormat::Hash, ".magnet");
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string resumeFile(std::string_view resume_dir) const
|
||||
{
|
||||
return makeFilename(resume_dir, name(), infoHashString(), BasenameFormat::Hash, ".resume");
|
||||
|
|
|
@ -767,17 +767,31 @@ static void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
|
|||
|
||||
tr_sessionAddTorrent(session, tor);
|
||||
|
||||
// if we don't have a local .torrent file already, assume the torrent is new
|
||||
auto const filename = tor->torrentFile();
|
||||
// if we don't have a local .torrent or .magnet file already, assume the torrent is new
|
||||
auto const filename = tor->hasMetadata() ? tor->torrentFile() : tor->magnetFile();
|
||||
|
||||
bool const is_new_torrent = !tr_sys_path_exists(filename.c_str(), nullptr);
|
||||
if (is_new_torrent)
|
||||
{
|
||||
tr_error* error = nullptr;
|
||||
if (!tr_ctorSaveContents(ctor, filename, &error))
|
||||
if (tor->hasMetadata())
|
||||
{
|
||||
tor->setLocalError(
|
||||
tr_strvJoin("Unable to save torrent file: ", error->message, " ("sv, std::to_string(error->code), ")"sv));
|
||||
if (!tr_ctorSaveContents(ctor, filename, &error))
|
||||
{
|
||||
tor->setLocalError(
|
||||
tr_strvJoin("Unable to save torrent file: ", error->message, " ("sv, std::to_string(error->code), ")"sv));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// magnet link
|
||||
if (!tr_ctorSaveMagnetContents(tor, filename, &error))
|
||||
{
|
||||
tor->setLocalError(
|
||||
tr_strvJoin("Unable to save magnet file: ", error->message, " ("sv, std::to_string(error->code), ")"sv));
|
||||
}
|
||||
}
|
||||
|
||||
tr_error_clear(&error);
|
||||
}
|
||||
|
||||
|
@ -1566,6 +1580,7 @@ static void closeTorrent(void* vtor)
|
|||
if (tor->isDeleting)
|
||||
{
|
||||
tr_torrent_metainfo::removeFile(tor->session->torrent_dir, tor->name(), tor->infoHashString(), ".torrent"sv);
|
||||
tr_torrent_metainfo::removeFile(tor->session->torrent_dir, tor->name(), tor->infoHashString(), ".magnet"sv);
|
||||
tr_torrent_metainfo::removeFile(tor->session->resume_dir, tor->name(), tor->infoHashString(), ".resume"sv);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,8 @@ void tr_ctorInitTorrentWanted(tr_ctor const* ctor, tr_torrent* tor);
|
|||
|
||||
bool tr_ctorSaveContents(tr_ctor const* ctor, std::string const& filename, tr_error** error);
|
||||
|
||||
bool tr_ctorSaveMagnetContents(tr_torrent* tor, std::string const& filename, tr_error** error);
|
||||
|
||||
std::string_view tr_ctorGetContents(tr_ctor const* ctor);
|
||||
|
||||
tr_session* tr_ctorGetSession(tr_ctor const* ctor);
|
||||
|
@ -463,11 +465,21 @@ public:
|
|||
return metainfo_.torrentFile(this->session->torrent_dir);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto magnetFile() const
|
||||
{
|
||||
return metainfo_.magnetFile(this->session->torrent_dir);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto resumeFile() const
|
||||
{
|
||||
return metainfo_.resumeFile(this->session->resume_dir);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto magnet() const
|
||||
{
|
||||
return metainfo_.magnet();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto const& comment() const
|
||||
{
|
||||
return metainfo_.comment();
|
||||
|
@ -763,4 +775,5 @@ tr_peer_id_t const& tr_torrentGetPeerId(tr_torrent* tor);
|
|||
tr_torrent_metainfo&& tr_ctorStealMetainfo(tr_ctor* ctor);
|
||||
|
||||
bool tr_ctorSetMetainfoFromFile(tr_ctor* ctor, std::string const& filename, tr_error** error);
|
||||
bool tr_ctorSetMetainfoFromMagnetLink(tr_ctor* ctor, std::string const& filename, tr_error** error);
|
||||
void tr_ctorSetLabels(tr_ctor* ctor, tr_labels_t&& labels);
|
||||
|
|
Loading…
Reference in a new issue