Allow more than 1 screenshot.
continuous-integration/drone/push Build is failing Details

* New screenshot naming: branchname-N.extension (the “-N” ist new).
* In JSON file: Array of strings instead of string, “screenshots”
  instead of “screenshot”.
* Old format is still supported.
This commit is contained in:
tastytea 2020-11-15 20:30:42 +01:00
parent 1407954ab9
commit f23a562c1b
Signed by: tastytea
GPG Key ID: CFC39497F1B26E07
7 changed files with 89 additions and 32 deletions

View File

@ -15,12 +15,14 @@
*/
#include "cgi.hpp"
#include "files.hpp"
#include "fs-compat.hpp"
#include "time.hpp"
#include <cgicc/Cgicc.h>
#include <curl/curl.h>
#include <fmt/core.h>
#include <unicode/unistr.h>
#include <algorithm>
@ -39,6 +41,7 @@
namespace FediBlock::cgi
{
using fmt::format;
using std::back_inserter;
using std::getline;
using std::ios;
@ -65,24 +68,25 @@ entry_type parse_formdata()
entry.description = cgi("description");
entry.report_time = time::to_string(system_clock::now());
const auto screenshot = cgi.getFile("screenshot");
if (screenshot != cgi.getFiles().end())
for (const auto &screenshot : cgi.getFiles())
{
constexpr size_t size_limit{1024 * 1024 * 2}; // 2 MiB.
if (screenshot->getDataLength() > size_limit)
constexpr size_t size_limit{1024 * 1024 * 1};
if (screenshot.getDataLength() > size_limit)
{
throw runtime_error{"The screenshot is too big. "
"The limit is 2 MiB."};
throw runtime_error{format("The screenshot “{0:s}” is too big. "
"The limit is {1:.1f} MiB.",
screenshot.getFilename(),
size_limit / 1024 / 1024)};
}
const string filepath{files::get_tmpdir() / screenshot->getFilename()};
const string filepath{files::get_tmpdir() / screenshot.getFilename()};
ofstream file{filepath, ios::binary};
if (!file.good())
{
throw runtime_error{"Could not open temporary file: " + filepath};
}
screenshot->writeToStream(file);
entry.screenshot_filepath = filepath;
screenshot.writeToStream(file);
entry.screenshot_filepaths.push_back(filepath);
}
return entry;

View File

@ -15,12 +15,15 @@
*/
#include "files.hpp"
#include "fs-compat.hpp"
#include "json.hpp"
#include "types.hpp"
#include <fmt/format.h>
#include <fmt/ostream.h> // For compatibility with fmt 4.
#include <sys/types.h>
#include <unistd.h>
#include <algorithm>
#include <cstdint>
@ -29,8 +32,6 @@
#include <sstream>
#include <stdexcept>
#include <string>
#include <sys/types.h>
#include <unistd.h>
namespace FediBlock::files
{
@ -184,11 +185,31 @@ vector<entry_type> read_json_files(const bool cache)
stringstream ss;
ss << file.rdbuf();
auto entry{json::from_json(ss.str())};
if (!entry.screenshot_filepath.empty())
if (!entry.screenshot_filepaths.empty())
{
const fs::path sh_path{entry.screenshot_filepath};
entry.screenshot_filepath = path.stem().string() +=
sh_path.extension();
std::uint8_t counter{0};
for (auto &screenshot : entry.screenshot_filepaths)
{
++counter;
const fs::path sh_path{screenshot};
// clang-format off
const auto compat_path{path.parent_path() /= path.stem()
/= sh_path.extension()};
// clang-format on
if (entry.screenshot_filepaths.size() == 1
&& fs::exists(compat_path))
{
// Compatibility for old entries.
screenshot = path.stem().string() += sh_path.extension();
}
else
{
// clang-format off
screenshot = (path.stem().string() += '-')
+= to_string(counter) += sh_path.extension();
// clang-format on
}
}
}
entries.push_back(entry);
}

View File

@ -109,11 +109,16 @@ void write_html(ostream &out, const vector<entry_type> &entries)
<< "</a></li>\n";
}
out << " </ul>\n";
if (!entry.screenshot_filepath.empty())
if (!entry.screenshot_filepaths.empty())
{
out << " <p><strong>Screenshot:</strong><br>"
<< "<a href=\"" << entry.screenshot_filepath << "\"><img src=\""
<< entry.screenshot_filepath << R"("></a></p>)" << '\n';
out << " <strong>Screenshots:</strong><br>\n"
<< " <ul>\n";
for (const auto &screenshot : entry.screenshot_filepaths)
{
out << " <li><a href=\"" << screenshot << "\">"
<< screenshot << "</a></li>\n";
}
out << " </ul>";
}
out << " </details>\n";
}

View File

@ -165,13 +165,17 @@ void write_rss(ostream &out, const vector<entry_type> &entries,
receipt);
}
tmp_item_description += "</ul>";
if (!entry.screenshot_filepath.empty())
if (!entry.screenshot_filepaths.empty())
{
tmp_item_description += "<p><strong>Screenshot:</strong><br>";
tmp_item_description += format("<a href=\"{0:s}{1:s}\">"
"<img src=\"{0:s}{1:s}\" "
"height=\"200\"></a></p>\n",
baseurl, entry.screenshot_filepath);
tmp_item_description += "<p><strong>Screenshots:</strong><br>";
for (const auto &screenshot : entry.screenshot_filepaths)
{
tmp_item_description += format("<a href=\"{0:s}{1:s}\">"
"<img src=\"{0:s}{1:s}\" "
"height=\"200\"></a> ",
baseurl, screenshot);
}
tmp_item_description += "</p>";
}
auto item_description{item.append_child("description")};
item_description.append_child(pugi::node_cdata)

View File

@ -15,6 +15,7 @@
*/
#include "git.hpp"
#include "config.hpp"
#include "files.hpp"
#include "fs-compat.hpp"
@ -153,10 +154,16 @@ void commit(const entry_type &entry)
file << json::to_json(entry);
file.close();
if (!entry.screenshot_filepath.empty())
if (!entry.screenshot_filepaths.empty())
{
const string extension{fs::path(entry.screenshot_filepath).extension()};
fs::copy(entry.screenshot_filepath, basename + extension);
uint8_t counter{0};
for (const auto &screenshot : entry.screenshot_filepaths)
{
++counter;
const string extension{fs::path(screenshot).extension()};
fs::copy(screenshot,
basename + "-" += to_string(counter) += extension);
}
}
// Add files.

View File

@ -15,6 +15,7 @@
*/
#include "json.hpp"
#include "fs-compat.hpp"
#include "types.hpp"
@ -25,13 +26,17 @@ namespace FediBlock::json
string to_json(const entry_type &entry)
{
const string filename{fs::path(entry.screenshot_filepath).filename()};
vector<string> filenames;
for (const auto &screenshot : entry.screenshot_filepaths)
{
filenames.push_back(fs::path(screenshot).filename());
}
// clang-format off
const nlohmann::json json{{"instance", entry.instance},
{"tags", entry.tags},
{"receipts", entry.receipts},
{"description", entry.description},
{"screenshot", filename},
{"screenshots", filenames},
{"report_time", entry.report_time}};
// clang-format on
return json.dump(4);
@ -55,7 +60,18 @@ entry_type from_json(const string_view json_string)
entry.receipts = json[0].at("receipts").get<vector<string>>();
try
{
entry.screenshot_filepath = json[0].at("screenshot").get<string>();
if (json[0].count("screenshot") == 1)
{
// Compatibility for old entries.
entry.screenshot_filepaths.push_back(
json[0].at("screenshot").get<string>());
}
else
{
entry.screenshot_filepaths = json[0]
.at("screenshots")
.get<vector<string>>();
}
}
#if NLOHMANN_JSON_VERSION_MAJOR >= 3
catch (const nlohmann::detail::out_of_range &) // Ignore missing screenshot.

View File

@ -32,7 +32,7 @@ struct entry_type
vector<string> tags;
vector<string> receipts;
string description;
string screenshot_filepath;
vector<string> screenshot_filepaths;
string report_time;
};