|
|
|
|
#ifndef _TR_TORRENT_HPP_
|
|
|
|
|
#define _TR_TORRENT_HPP_
|
|
|
|
|
|
|
|
|
|
#include <boost/filesystem.hpp>
|
|
|
|
|
#include <http.hpp>
|
|
|
|
|
#include <libtorrent/sha1_hash.hpp>
|
|
|
|
|
#include <util.hpp>
|
|
|
|
|
|
|
|
|
|
namespace tr {
|
|
|
|
|
|
|
|
|
|
namespace torrent {
|
|
|
|
|
template <class torrent_t>
|
|
|
|
|
static nlohmann::json to_json(torrent_t torrent) {
|
|
|
|
|
const auto status = torrent.status(
|
|
|
|
|
torrent.query_name |
|
|
|
|
|
torrent.query_save_path);
|
|
|
|
|
return {{"info_hash", util::sha1::string(torrent.info_hash())},
|
|
|
|
|
{"paused", status.paused},
|
|
|
|
|
{"seeding", status.is_seeding},
|
|
|
|
|
{"state", status.state},
|
|
|
|
|
{"priority", status.priority},
|
|
|
|
|
{"up_limit", torrent.upload_limit()},
|
|
|
|
|
{"down_limit", torrent.download_limit()},
|
|
|
|
|
{"name", status.name}};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace session {
|
|
|
|
|
namespace torrents {
|
|
|
|
|
namespace id {
|
|
|
|
|
template <class torrent_session, class request, class response>
|
|
|
|
|
void get(torrent_session &session, response resp, request req) {
|
|
|
|
|
auto http_response = http::response();
|
|
|
|
|
const auto respond = [&](http::status status) {
|
|
|
|
|
const auto response_code = http::code(status);
|
|
|
|
|
http_response.set_body({{"code", response_code.first}, {"status", response_code.second}});
|
|
|
|
|
http_response.set_status(response_code.first);
|
|
|
|
|
*resp << http_response;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (!session.is_valid()) {
|
|
|
|
|
return respond(http::service_unavailable);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto hash = req->path.substr(18, req->path.size() - 18); //TODO hacky
|
|
|
|
|
const auto torrent = session.find_torrent(util::sha1::info_hash(hash));
|
|
|
|
|
|
|
|
|
|
if (!torrent.is_valid()) {
|
|
|
|
|
return respond(http::bad_request);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
http_response.set_body(torrent::to_json(torrent));
|
|
|
|
|
http_response.set_status(http::ok);
|
|
|
|
|
*resp << http_response;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <class torrent_session, class request, class response>
|
|
|
|
|
void patch(torrent_session &session, response resp, request req) {
|
|
|
|
|
auto http_response = http::response();
|
|
|
|
|
const auto respond = [&](http::status status) {
|
|
|
|
|
const auto response_code = http::code(status);
|
|
|
|
|
http_response.set_body({{"code", response_code.first}, {"status", response_code.second}});
|
|
|
|
|
http_response.set_status(response_code.first);
|
|
|
|
|
*resp << http_response;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (!session.is_valid()) {
|
|
|
|
|
return respond(http::service_unavailable);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto hash = req->path.substr(18, req->path.size() - 18);
|
|
|
|
|
|
|
|
|
|
#ifndef _TR_TESTING_
|
|
|
|
|
auto torrent = session.find_torrent(util::sha1::info_hash(hash));
|
|
|
|
|
#else
|
|
|
|
|
auto &torrent = session.find_torrent(util::sha1::info_hash(hash));
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (!torrent.is_valid()) {
|
|
|
|
|
return respond(http::bad_request);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto request_object = util::json::parse(req->content);
|
|
|
|
|
|
|
|
|
|
if (request_object.is_null()) {
|
|
|
|
|
return respond(http::bad_request);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!request_object.is_object()) {
|
|
|
|
|
return respond(http::bad_request);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto paused_field = request_object.find("paused") != request_object.end();
|
|
|
|
|
auto up_limit_field = request_object.find("up_limit") != request_object.end();
|
|
|
|
|
auto down_limit_field = request_object.find("down_limit") != request_object.end();
|
|
|
|
|
|
|
|
|
|
if (paused_field) {
|
|
|
|
|
bool paused = false;
|
|
|
|
|
const auto obj = request_object.at("paused");
|
|
|
|
|
if (obj.is_boolean())
|
|
|
|
|
paused = request_object.at("paused");
|
|
|
|
|
else if (obj.is_string()) {
|
|
|
|
|
std::string p = obj;
|
|
|
|
|
paused = (p == "true");
|
|
|
|
|
} else {
|
|
|
|
|
return respond(http::bad_request);
|
|
|
|
|
}
|
|
|
|
|
if (torrent.status().paused != paused) {
|
|
|
|
|
if (paused)
|
|
|
|
|
torrent.pause();
|
|
|
|
|
else {
|
|
|
|
|
torrent.resume();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (up_limit_field) {
|
|
|
|
|
int up_limit = 0;
|
|
|
|
|
auto obj = request_object.at("up_limit");
|
|
|
|
|
if (obj.is_string()) {
|
|
|
|
|
std::string i = obj;
|
|
|
|
|
up_limit = std::stoi(i);
|
|
|
|
|
} else if (obj.is_number()) {
|
|
|
|
|
up_limit = obj;
|
|
|
|
|
} else {
|
|
|
|
|
return respond(http::bad_request);
|
|
|
|
|
}
|
|
|
|
|
torrent.set_upload_limit(up_limit);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (down_limit_field) {
|
|
|
|
|
int down_limit = 0;
|
|
|
|
|
auto obj = request_object.at("down_limit");
|
|
|
|
|
if (obj.is_string()) {
|
|
|
|
|
std::string i = obj;
|
|
|
|
|
down_limit = std::stoi(i);
|
|
|
|
|
} else if (obj.is_number()) {
|
|
|
|
|
down_limit = obj;
|
|
|
|
|
} else {
|
|
|
|
|
return respond(http::bad_request);
|
|
|
|
|
}
|
|
|
|
|
torrent.set_download_limit(down_limit);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (down_limit_field || up_limit_field || paused_field) {
|
|
|
|
|
return respond(http::bad_request);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
respond(http::accepted);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|