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

View File

@ -15,12 +15,15 @@
*/ */
#include "files.hpp" #include "files.hpp"
#include "fs-compat.hpp" #include "fs-compat.hpp"
#include "json.hpp" #include "json.hpp"
#include "types.hpp" #include "types.hpp"
#include <fmt/format.h> #include <fmt/format.h>
#include <fmt/ostream.h> // For compatibility with fmt 4. #include <fmt/ostream.h> // For compatibility with fmt 4.
#include <sys/types.h>
#include <unistd.h>
#include <algorithm> #include <algorithm>
#include <cstdint> #include <cstdint>
@ -29,8 +32,6 @@
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <sys/types.h>
#include <unistd.h>
namespace FediBlock::files namespace FediBlock::files
{ {
@ -184,11 +185,31 @@ vector<entry_type> read_json_files(const bool cache)
stringstream ss; stringstream ss;
ss << file.rdbuf(); ss << file.rdbuf();
auto entry{json::from_json(ss.str())}; 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}; std::uint8_t counter{0};
entry.screenshot_filepath = path.stem().string() += for (auto &screenshot : entry.screenshot_filepaths)
sh_path.extension(); {
++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); entries.push_back(entry);
} }

View File

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

View File

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

View File

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

View File

@ -15,6 +15,7 @@
*/ */
#include "json.hpp" #include "json.hpp"
#include "fs-compat.hpp" #include "fs-compat.hpp"
#include "types.hpp" #include "types.hpp"
@ -25,13 +26,17 @@ namespace FediBlock::json
string to_json(const entry_type &entry) 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 // clang-format off
const nlohmann::json json{{"instance", entry.instance}, const nlohmann::json json{{"instance", entry.instance},
{"tags", entry.tags}, {"tags", entry.tags},
{"receipts", entry.receipts}, {"receipts", entry.receipts},
{"description", entry.description}, {"description", entry.description},
{"screenshot", filename}, {"screenshots", filenames},
{"report_time", entry.report_time}}; {"report_time", entry.report_time}};
// clang-format on // clang-format on
return json.dump(4); 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>>(); entry.receipts = json[0].at("receipts").get<vector<string>>();
try 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 #if NLOHMANN_JSON_VERSION_MAJOR >= 3
catch (const nlohmann::detail::out_of_range &) // Ignore missing screenshot. catch (const nlohmann::detail::out_of_range &) // Ignore missing screenshot.

View File

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