Add: universal task display

This commit is contained in:
2021-06-04 00:50:07 +02:00
parent 737097fbed
commit 231f06c2e3
9 changed files with 326 additions and 331 deletions

View File

@@ -5,7 +5,9 @@ set(src_files
src/api.cpp
src/worker.hpp
src/worker.cpp
src/tables.hpp)
src/tables.hpp
src/file_status.hpp
src/file_status.cpp)
add_executable(localTubeServer ${src_files})

View File

@@ -7,6 +7,7 @@
#include <filesystem>
#include <fstream>
#include <functional>
#include <exception>
#include <soci/boost-optional.h>
@@ -16,6 +17,8 @@
#include <nlohmann/json.hpp>
#include <spdlog/spdlog.h>
#include "file_status.hpp"
using json = nlohmann::json;
Api::Api(soci::session& sql, httplib::Server& server) : sql(sql)
@@ -116,53 +119,10 @@ void Api::files(httplib::Request const& rq, httplib::Response& rs)
{
try
{
auto data = TaskInfo::getAll(sql);
json res;
// Query incomplete Tasks
soci::rowset<Task> data = (sql.prepare << "SELECT * "
"FROM Tasks "
"WHERE status!=2 "
"ORDER BY id DESC ");
for (auto const& el : data)
{
json current;
current["hash"] = el.hash;
current["status"] = magic_enum::enum_name(el.status);
current["status_id"] = static_cast<int>(el.status);
current["source"] = el.url;
current["name"] = fmt::format("File {}", el.id);
current["audio_only"] = el.audio_only;
current["format"] = el.format.value_or("Source");
res["queue"].push_back(current);
}
// Downloaded
soci::rowset<soci::row> files =
(sql.prepare
<< R"(SELECT Tasks.id, Files.timestamp, Files.hash, audio_only, filename, Files.format
FROM Files,
Tasks
WHERE Tasks.hash == Files.hash
ORDER BY Files.timestamp DESC )");
for (auto const& el : files)
{
json current;
std::time_t time = el.get<int>("timestamp");
current["timestamp"] = fmt::format("{:%Y-%m-%d %H:%M:%S}", *std::localtime(&time));
current["hash"] = el.get<std::string>("hash");
current["audio_only"] = el.get<int>("audio_only");
current["filename"] = el.get<std::string>("filename");
current["format"] = el.get<std::string>("format");
res["files"].push_back(current);
}
res["files"] = data;
rs.set_content(res.dump(), "application/json");
}
@@ -191,14 +151,12 @@ void Api::file(const httplib::Request& rq, httplib::Response& rs)
sql << fmt::format("SELECT * FROM Files WHERE hash='{}';", file), soci::into(dw);
auto fs = std::make_shared<std::ifstream>(dw.local_path, std::ios_base::binary | std::ios::in);
auto fs =
std::make_shared<std::ifstream>(dw.local_path, std::ios_base::binary | std::ios::in);
fs->seekg(0, std::ios_base::end);
auto size = fs->tellg();
fs->seekg(0);
// rs.body.resize(static_cast<size_t>(size));
// fs.read(&rs.body[0], static_cast<std::streamsize>(size));
rs.set_header("Content-Disposition", fmt::format("attachment; filename={};", dw.filename));
rs.set_content_provider(
@@ -207,7 +165,6 @@ void Api::file(const httplib::Request& rq, httplib::Response& rs)
[file = fs](size_t offset, size_t length, httplib::DataSink& sink) mutable {
size_t size = std::min(length, (size_t)1024 * 500);
//spdlog::info("Stream offset {} length {}", offset, length);
std::vector<char> data;
data.resize(size);
@@ -237,54 +194,26 @@ void Api::status(httplib::Request const& rq, httplib::Response& rs)
std::string hash = rq.matches[1];
boost::optional<Task> data;
sql << "SELECT * FROM Tasks WHERE hash=:hash", soci::use(hash, "hash"), soci::into(data);
/*soci::rowset<Task> data = (sql.prepare << "SELECT * "
"FROM Tasks "
"WHERE hash=:hash ",
soci::use(hash, "hash"));*/
json response;
auto& status = response["status"];
if (data)
try
{
auto const& el = data.value();
auto data = TaskInfo::getId(sql, hash);
status["name"] = fmt::format("Task {}", el.hash);
status["source"] = el.url;
status["status"] = magic_enum::enum_name(el.status);
status["status_id"] = static_cast<int>(el.status);
status["timestamp"] = el.timestamp;
status["task_file_type"] =
fmt::format("{}: {}", el.audio_only ? "Audio" : "Video", el.format.value_or("Auto"));
status["id"] = el.hash;
if (el.status == FileStatus::COMPLETE)
if (data)
{
boost::optional<File> file_data;
sql << "SELECT * FROM Files WHERE hash=:hash", soci::use(hash, "hash"),
soci::into(file_data);
response["status"] = data.value();
if (file_data)
{
auto const& file = file_data.value();
auto& file_status = status["file"];
file_status["timestamp"] = file.timestamp;
file_status["name"] = file.filename;
file_status["format"] =
fmt::format("{}: {}", el.audio_only ? "Audio" : "Video", file.format);
}
} else
{
rs.status = 404;
response["error"] = fmt::format("File '{}' not found!", hash);
}
} else
}
catch (std::exception const& e)
{
spdlog::error("[Api Status] Excepion: {}", e.what());
rs.status = 404;
response["error"] = fmt::format("File '{}' not found!", hash);
response["error"] = fmt::format("Exception: {}", e.what());
}
rs.set_content(response.dump(), "application/json");
}

View File

@@ -0,0 +1,76 @@
#include "file_status.hpp"
#include <vector>
#include <soci/boost-optional.h>
#include "tables.hpp"
std::optional<TaskInfo> TaskInfo::getId(soci::session& sql, std::string_view hash)
{
auto hash_str = std::string { hash };
soci::rowset<soci::row> row_data = (sql.prepare << R"(--
SELECT Tasks.hash,
Tasks.status,
Tasks.timestamp AS TaskTimestamp,
Tasks.url,
Files.timestamp AS FileTimestamp,
Files.filename,
Files.format
FROM Tasks LEFT OUTER JOIN Files ON Files.id = Tasks.id
WHERE Tasks.hash = :file_hash ;)",
soci::use(hash_str, "file_hash"));
for (auto const& el : row_data)
{
return fromRow(el);
}
return {};
}
std::vector<TaskInfo> TaskInfo::getAll(soci::session& sql)
{
soci::rowset<soci::row> row_data(sql.prepare << R"(--
SELECT Tasks.hash,
Tasks.status,
Tasks.timestamp AS TaskTimestamp,
Tasks.url,
Files.timestamp AS FileTimestamp,
Files.filename,
Files.format
FROM Tasks LEFT JOIN Files ON Files.id = Tasks.id
ORDER BY TaskTimestamp DESC;")");
std::vector<TaskInfo> data;
for (auto const& el : row_data)
{
data.push_back(fromRow(el));
}
return data;
}
TaskInfo TaskInfo::fromRow(soci::row const& row)
{
TaskInfo status;
auto file_status = row.get<FileStatus>("status");
status.hash = row.get<std::string>("hash");
status.name = fmt::format("Task {}", status.hash);
status.status = magic_enum::enum_name(file_status);
status.timestamp = row.get<int>("TaskTimestamp");
status.url = row.get<std::string>("url");
if (file_status == FileStatus::COMPLETE)
{
status.file = { .timestamp = row.get<int>("FileTimestamp"),
.filename = row.get<std::string>("filename"),
.format = row.get<std::string>("format") };
}
return status;
}

View File

@@ -0,0 +1,46 @@
#pragma once
#include <optional>
#include <string>
#include <nlohmann/json.hpp>
#include <soci/session.h>
using json = nlohmann::json;
struct FileInfo
{
int64_t timestamp;
std::string filename;
std::string format;
};
struct TaskInfo
{
std::string name;
std::string hash;
std::string status;
std::string url;
int64_t timestamp;
std::optional<FileInfo> file;
static std::optional<TaskInfo> getId(soci::session& sql, std::string_view hash);
static std::vector<TaskInfo> getAll(soci::session& sql);
static TaskInfo fromRow(soci::row const& row);
};
inline void to_json(json& j, const TaskInfo& p)
{
j = json { { "name", p.name },
{ "source", p.url },
{ "status", p.status },
{ "timestamp", p.timestamp },
{ "hash", p.hash } };
if(p.file)
{
j["file"]["timestamp"] = p.file.value().timestamp;
j["file"]["filename"] = p.file.value().filename;
j["file"]["format"] = p.file.value().format;
}
}

View File

@@ -65,7 +65,7 @@ int main()
File::create_table(sql);
}
Worker worker(sql);
//Worker worker(sql);
httplib::Server srv;
srv.set_mount_point("/", "www/");
@@ -75,5 +75,7 @@ int main()
Api api(sql, srv);
spdlog::info("Listing on 0.0.0.0 Port 80");
srv.listen("0.0.0.0", 80);
srv.listen("0.0.0.0", 8888);
}