2023-11-01 21:11:11 +00:00
|
|
|
// This file Copyright © Mnemosyne LLC.
|
2022-02-07 16:25:02 +00:00
|
|
|
// It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
|
2022-01-20 18:27:56 +00:00
|
|
|
// or any future license endorsed by Mnemosyne LLC.
|
|
|
|
// License text can be found in the licenses/ folder.
|
2022-01-13 02:13:58 +00:00
|
|
|
|
|
|
|
#include <memory>
|
2009-04-09 18:55:47 +00:00
|
|
|
|
|
|
|
#include <QDir>
|
|
|
|
#include <QFileSystemWatcher>
|
2009-10-06 00:27:26 +00:00
|
|
|
#include <QTimer>
|
2009-04-09 18:55:47 +00:00
|
|
|
|
|
|
|
#include <libtransmission/transmission.h>
|
|
|
|
|
2021-12-25 23:48:40 +00:00
|
|
|
#include <libtransmission/torrent-metainfo.h>
|
|
|
|
|
2015-06-10 21:27:11 +00:00
|
|
|
#include "Prefs.h"
|
|
|
|
#include "TorrentModel.h"
|
|
|
|
#include "WatchDir.h"
|
2009-04-09 18:55:47 +00:00
|
|
|
|
|
|
|
/***
|
|
|
|
****
|
|
|
|
***/
|
|
|
|
|
2021-08-15 09:41:48 +00:00
|
|
|
WatchDir::WatchDir(TorrentModel const& model)
|
2023-07-18 15:20:17 +00:00
|
|
|
: model_{ model }
|
2009-04-09 18:55:47 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
|
|
****
|
|
|
|
***/
|
|
|
|
|
2022-04-12 06:56:09 +00:00
|
|
|
WatchDir::AddResult WatchDir::metainfoTest(QString const& filename) const
|
2009-04-09 18:55:47 +00:00
|
|
|
{
|
2021-12-25 23:48:40 +00:00
|
|
|
auto metainfo = tr_torrent_metainfo();
|
2023-04-23 01:25:55 +00:00
|
|
|
if (!metainfo.parse_torrent_file(filename.toUtf8().constData()))
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2022-04-12 06:56:09 +00:00
|
|
|
return AddResult::Error;
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
if (model_.hasTorrent(TorrentHash{ metainfo.info_hash() }))
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
2022-04-12 06:56:09 +00:00
|
|
|
return AddResult::Duplicate;
|
2017-04-19 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2022-04-12 06:56:09 +00:00
|
|
|
return AddResult::Success;
|
2009-04-09 18:55:47 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
void WatchDir::onTimeout()
|
2009-04-09 18:55:47 +00:00
|
|
|
{
|
2020-05-20 01:32:51 +00:00
|
|
|
auto* t = qobject_cast<QTimer*>(sender());
|
2013-09-14 22:45:04 +00:00
|
|
|
|
2022-04-12 06:56:09 +00:00
|
|
|
if (auto const filename = t->objectName(); metainfoTest(filename) == AddResult::Success)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
emit torrentFileAdded(filename);
|
|
|
|
}
|
2013-09-14 22:45:04 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
t->deleteLater();
|
2009-04-09 18:55:47 +00:00
|
|
|
}
|
|
|
|
|
2020-05-27 21:53:12 +00:00
|
|
|
void WatchDir::setPath(QString const& path, bool is_enabled)
|
2009-04-09 18:55:47 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
// clear out any remnants of the previous watcher, if any
|
2020-05-27 21:53:12 +00:00
|
|
|
watch_dir_files_.clear();
|
2020-07-29 23:21:11 +00:00
|
|
|
watcher_.reset();
|
2009-04-09 18:55:47 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
// maybe create a new watcher
|
2020-05-27 21:53:12 +00:00
|
|
|
if (is_enabled)
|
2013-09-14 22:45:04 +00:00
|
|
|
{
|
2020-07-29 23:21:11 +00:00
|
|
|
watcher_ = std::make_unique<QFileSystemWatcher>(QStringList{ path });
|
2020-10-31 18:56:12 +00:00
|
|
|
connect(watcher_.get(), &QFileSystemWatcher::directoryChanged, this, &WatchDir::watcherActivated);
|
2022-03-21 14:15:48 +00:00
|
|
|
// trigger the watchdir for torrent files in there already
|
2021-08-15 09:41:48 +00:00
|
|
|
QTimer::singleShot(0, this, SLOT(rescanAllWatchedDirectories()));
|
2009-04-09 18:55:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
void WatchDir::watcherActivated(QString const& path)
|
2009-04-09 18:55:47 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
// get the list of files currently in the watch directory
|
2023-10-25 01:14:37 +00:00
|
|
|
auto const dir = QDir{ path };
|
|
|
|
auto const files = dir.entryList(QDir::Readable | QDir::Files);
|
2013-09-14 22:45:04 +00:00
|
|
|
|
2022-03-21 14:15:48 +00:00
|
|
|
// try to add any new files which end in torrent
|
2020-05-29 17:40:07 +00:00
|
|
|
auto const torrent_suffix = QStringLiteral(".torrent");
|
2023-10-25 01:14:37 +00:00
|
|
|
for (auto const& name : files)
|
2013-09-14 22:45:04 +00:00
|
|
|
{
|
2023-10-25 01:14:37 +00:00
|
|
|
if (!name.endsWith(torrent_suffix, Qt::CaseInsensitive) || (watch_dir_files_.count(name) != 0U))
|
2013-09-14 22:45:04 +00:00
|
|
|
{
|
2023-10-25 01:14:37 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto const filename = dir.absoluteFilePath(name);
|
|
|
|
switch (metainfoTest(filename))
|
|
|
|
{
|
|
|
|
case AddResult::Success:
|
|
|
|
emit torrentFileAdded(filename);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AddResult::Duplicate:
|
|
|
|
break;
|
2017-04-19 12:04:45 +00:00
|
|
|
|
2023-10-25 01:14:37 +00:00
|
|
|
case AddResult::Error:
|
2013-09-14 22:45:04 +00:00
|
|
|
{
|
2023-10-25 01:14:37 +00:00
|
|
|
// give the torrent a few seconds to finish downloading
|
|
|
|
auto* t = new QTimer(this);
|
|
|
|
t->setObjectName(dir.absoluteFilePath(name));
|
|
|
|
t->setSingleShot(true);
|
|
|
|
connect(t, &QTimer::timeout, this, &WatchDir::onTimeout);
|
|
|
|
t->start(5000);
|
2009-04-09 18:55:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
// update our file list so that we can use it
|
|
|
|
// for comparison the next time around
|
2023-10-25 01:14:37 +00:00
|
|
|
watch_dir_files_ = { std::begin(files), std::end(files) };
|
2009-04-09 18:55:47 +00:00
|
|
|
}
|
2014-12-11 22:21:24 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
void WatchDir::rescanAllWatchedDirectories()
|
2014-12-11 22:21:24 +00:00
|
|
|
{
|
2020-07-29 23:21:11 +00:00
|
|
|
if (!watcher_)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2014-12-11 22:21:24 +00:00
|
|
|
|
2020-07-29 23:21:11 +00:00
|
|
|
for (auto const& path : watcher_->directories())
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
watcherActivated(path);
|
|
|
|
}
|
2014-12-11 22:21:24 +00:00
|
|
|
}
|