WebAPI: Add setComment endpoint

No UI implementation as of now.

Closes #19598.
PR #23031.
This commit is contained in:
HamletDuFromage 2025-08-04 11:52:54 +02:00 committed by GitHub
commit d7b330c069
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 47 additions and 2 deletions

View file

@ -1,5 +1,9 @@
# WebAPI Changelog
## 2.12.1
* [#23031](https://github.com/qbittorrent/qBittorrent/pull/23031)
* Add `torrents/setComment` endpoint with parameters `hashes` and `comment` for setting a new torrent comment
## 2.12.0
* [#22989](https://github.com/qbittorrent/qBittorrent/pull/22989)

View file

@ -236,6 +236,7 @@ BitTorrent::LoadResumeDataResult BitTorrent::BencodeResumeDataStorage::loadTorre
LoadTorrentParams torrentParams;
torrentParams.category = fromLTString(resumeDataRoot.dict_find_string_value("qBt-category"));
torrentParams.name = fromLTString(resumeDataRoot.dict_find_string_value("qBt-name"));
torrentParams.comment = fromLTString(resumeDataRoot.dict_find_string_value("qBt-comment"));
torrentParams.hasFinishedStatus = resumeDataRoot.dict_find_int_value("qBt-seedStatus");
torrentParams.firstLastPiecePriority = resumeDataRoot.dict_find_int_value("qBt-firstLastPiecePriority");
torrentParams.seedingTimeLimit = resumeDataRoot.dict_find_int_value("qBt-seedingTimeLimit", Torrent::USE_GLOBAL_SEEDING_TIME);
@ -437,6 +438,7 @@ void BitTorrent::BencodeResumeDataStorage::Worker::store(const TorrentID &id, co
data["qBt-category"] = resumeData.category.toStdString();
data["qBt-tags"] = setToEntryList(resumeData.tags);
data["qBt-name"] = resumeData.name.toStdString();
data["qBt-comment"] = resumeData.comment.toStdString();
data["qBt-seedStatus"] = resumeData.hasFinishedStatus;
data["qBt-contentLayout"] = Utils::String::fromEnum(resumeData.contentLayout).toStdString();
data["qBt-firstLastPiecePriority"] = resumeData.firstLastPiecePriority;

View file

@ -67,7 +67,7 @@ namespace
{
const QString DB_CONNECTION_NAME = u"ResumeDataStorage"_s;
const int DB_VERSION = 8;
const int DB_VERSION = 9;
const QString DB_TABLE_META = u"meta"_s;
const QString DB_TABLE_TORRENTS = u"torrents"_s;
@ -131,6 +131,7 @@ namespace
const Column DB_COLUMN_NAME = makeColumn(u"name"_s);
const Column DB_COLUMN_CATEGORY = makeColumn(u"category"_s);
const Column DB_COLUMN_TAGS = makeColumn(u"tags"_s);
const Column DB_COLUMN_COMMENT = makeColumn(u"comment"_s);
const Column DB_COLUMN_TARGET_SAVE_PATH = makeColumn(u"target_save_path"_s);
const Column DB_COLUMN_DOWNLOAD_PATH = makeColumn(u"download_path"_s);
const Column DB_COLUMN_CONTENT_LAYOUT = makeColumn(u"content_layout"_s);
@ -461,6 +462,7 @@ void BitTorrent::DBResumeDataStorage::createDB() const
makeColumnDefinition(DB_COLUMN_NAME, u"TEXT"_s),
makeColumnDefinition(DB_COLUMN_CATEGORY, u"TEXT"_s),
makeColumnDefinition(DB_COLUMN_TAGS, u"TEXT"_s),
makeColumnDefinition(DB_COLUMN_COMMENT, u"TEXT"_s),
makeColumnDefinition(DB_COLUMN_TARGET_SAVE_PATH, u"TEXT"_s),
makeColumnDefinition(DB_COLUMN_DOWNLOAD_PATH, u"TEXT"_s),
makeColumnDefinition(DB_COLUMN_CONTENT_LAYOUT, u"TEXT NOT NULL"_s),
@ -578,6 +580,9 @@ void BitTorrent::DBResumeDataStorage::updateDB(const int fromVersion) const
throw RuntimeError(query.lastError().text());
}
if (fromVersion <= 8)
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_COMMENT, u"TEXT"_s);
const QString updateMetaVersionQuery = makeUpdateStatement(DB_TABLE_META, {DB_COLUMN_NAME, DB_COLUMN_VALUE});
if (!query.prepare(updateMetaVersionQuery))
throw RuntimeError(query.lastError().text());
@ -619,6 +624,7 @@ LoadResumeDataResult DBResumeDataStorage::parseQueryResultRow(const QSqlQuery &q
LoadTorrentParams resumeData;
resumeData.name = query.value(DB_COLUMN_NAME.name).toString();
resumeData.category = query.value(DB_COLUMN_CATEGORY.name).toString();
resumeData.comment = query.value(DB_COLUMN_COMMENT.name).toString();
const QString tagsData = query.value(DB_COLUMN_TAGS.name).toString();
if (!tagsData.isEmpty())
{
@ -834,6 +840,7 @@ StoreJob::StoreJob(const TorrentID &torrentID, LoadTorrentParams resumeData)
DB_COLUMN_NAME,
DB_COLUMN_CATEGORY,
DB_COLUMN_TAGS,
DB_COLUMN_COMMENT,
DB_COLUMN_TARGET_SAVE_PATH,
DB_COLUMN_DOWNLOAD_PATH,
DB_COLUMN_CONTENT_LAYOUT,
@ -899,6 +906,7 @@ StoreJob::StoreJob(const TorrentID &torrentID, LoadTorrentParams resumeData)
query.bindValue(DB_COLUMN_CATEGORY.placeholder, m_resumeData.category);
query.bindValue(DB_COLUMN_TAGS.placeholder, (m_resumeData.tags.isEmpty()
? QString() : Utils::String::joinIntoString(m_resumeData.tags, u","_s)));
query.bindValue(DB_COLUMN_COMMENT.placeholder, m_resumeData.comment);
query.bindValue(DB_COLUMN_CONTENT_LAYOUT.placeholder, Utils::String::fromEnum(m_resumeData.contentLayout));
query.bindValue(DB_COLUMN_RATIO_LIMIT.placeholder, static_cast<int>(m_resumeData.ratioLimit * 1000));
query.bindValue(DB_COLUMN_SEEDING_TIME_LIMIT.placeholder, m_resumeData.seedingTimeLimit);

View file

@ -50,6 +50,7 @@ namespace BitTorrent
TagSet tags;
Path savePath;
Path downloadPath;
QString comment;
TorrentContentLayout contentLayout = TorrentContentLayout::Original;
TorrentOperatingMode operatingMode = TorrentOperatingMode::AutoManaged;
bool useAutoTMM = false;

View file

@ -144,6 +144,7 @@ namespace BitTorrent
virtual QDateTime creationDate() const = 0;
virtual QString creator() const = 0;
virtual QString comment() const = 0;
virtual void setComment(const QString &comment) = 0;
virtual bool isPrivate() const = 0;
virtual qlonglong totalSize() const = 0;
virtual qlonglong wantedSize() const = 0;

View file

@ -367,6 +367,9 @@ TorrentImpl::TorrentImpl(SessionImpl *session, const lt::torrent_handle &nativeH
}
}
if (!params.comment.isEmpty())
m_comment = params.comment;
setStopCondition(params.stopCondition);
const auto *extensionData = static_cast<ExtensionData *>(m_ltAddTorrentParams.userdata);
@ -440,6 +443,15 @@ QString TorrentImpl::comment() const
return m_comment;
}
void TorrentImpl::setComment(const QString &comment)
{
if (m_comment != comment)
{
m_comment = comment;
deferredRequestResumeData();
}
}
bool TorrentImpl::isPrivate() const
{
return m_torrentInfo.isPrivate();
@ -2210,6 +2222,7 @@ void TorrentImpl::prepareResumeData(lt::add_torrent_params params)
.tags = m_tags,
.savePath = (!m_useAutoTMM ? m_savePath : Path()),
.downloadPath = (!m_useAutoTMM ? m_downloadPath : Path()),
.comment = m_comment,
.contentLayout = m_contentLayout,
.operatingMode = m_operatingMode,
.useAutoTMM = m_useAutoTMM,

View file

@ -106,6 +106,7 @@ namespace BitTorrent
QDateTime creationDate() const override;
QString creator() const override;
QString comment() const override;
void setComment(const QString &comment) override;
bool isPrivate() const override;
qlonglong totalSize() const override;
qlonglong wantedSize() const override;

View file

@ -1591,6 +1591,19 @@ void TorrentsController::renameAction()
setResult(QString());
}
void TorrentsController::setCommentAction()
{
requireParams({u"hashes"_s, u"comment"_s});
const QStringList hashes {params()[u"hashes"_s].split(u'|')};
const QString comment = params()[u"comment"_s].trimmed();
applyToTorrents(hashes, [&comment](BitTorrent::Torrent *const torrent)
{
torrent->setComment(comment);
});
}
void TorrentsController::setAutoManagementAction()
{
requireParams({u"hashes"_s, u"enable"_s});

View file

@ -71,6 +71,7 @@ private slots:
void recheckAction();
void reannounceAction();
void renameAction();
void setCommentAction();
void setCategoryAction();
void createCategoryAction();
void editCategoryAction();

View file

@ -53,7 +53,7 @@
#include "base/utils/version.h"
#include "api/isessionmanager.h"
inline const Utils::Version<3, 2> API_VERSION {2, 12, 0};
inline const Utils::Version<3, 2> API_VERSION {2, 12, 1};
class APIController;
class AuthController;
@ -200,6 +200,7 @@ private:
{{u"torrents"_s, u"renameFolder"_s}, Http::METHOD_POST},
{{u"torrents"_s, u"setAutoManagement"_s}, Http::METHOD_POST},
{{u"torrents"_s, u"setCategory"_s}, Http::METHOD_POST},
{{u"torrents"_s, u"setComment"_s}, Http::METHOD_POST},
{{u"torrents"_s, u"setDownloadLimit"_s}, Http::METHOD_POST},
{{u"torrents"_s, u"setDownloadPath"_s}, Http::METHOD_POST},
{{u"torrents"_s, u"setForceStart"_s}, Http::METHOD_POST},