Cache motd images on disk

This commit is contained in:
fed 2023-03-07 19:57:07 +01:00
parent 40314f3db5
commit d645c7c809

View File

@ -9,30 +9,100 @@
#include <utils/string.hpp> #include <utils/string.hpp>
#include <utils/http.hpp> #include <utils/http.hpp>
#include <utils/concurrency.hpp> #include <utils/concurrency.hpp>
#include <utils/properties.hpp>
#include <utils/io.hpp>
#include <utils/cryptography.hpp>
#define MAX_FEATURED_TABS 8 #define MAX_FEATURED_TABS 8
#define CACHE_MAX_AGE 24h * 5
#define CACHE_FILE_SIGNATURE 'CM2H' // H2MC (H2-MOD Cache)
namespace motd namespace motd
{ {
namespace namespace
{ {
utils::concurrency::container<links_map_t> links; utils::concurrency::container<links_map_t> links;
utils::concurrency::container<nlohmann::json, std::recursive_mutex> marketing; utils::concurrency::container<nlohmann::json, std::recursive_mutex> marketing;
std::unordered_map<std::string, std::string> image_cache; struct cached_file_header
{
std::uint32_t signature;
time_t date_created;
};
std::filesystem::path get_cache_folder()
{
return utils::properties::get_appdata_path() / "cache";
}
std::string get_cached_file_name(const std::string& name)
{
const auto hash = utils::cryptography::sha1::compute(name, true);
return (get_cache_folder() / hash).generic_string();
}
void cache_file(const std::string& name, const std::string& data)
{
std::string buffer;
auto now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
cached_file_header header{};
header.signature = CACHE_FILE_SIGNATURE;
header.date_created = now;
buffer.append(reinterpret_cast<char*>(&header), sizeof(header));
buffer.append(data);
const auto path = get_cached_file_name(name);
utils::io::write_file(path, buffer, false);
}
std::optional<std::string> read_cached_file(const std::string& name)
{
const auto path = get_cached_file_name(name);
if (!utils::io::file_exists(path))
{
return {};
}
auto now = std::chrono::system_clock::now();
auto data = utils::io::read_file(path);
if (data.size() < sizeof(cached_file_header))
{
return {};
}
auto buffer = data.data();
const auto header = reinterpret_cast<cached_file_header*>(buffer);
if (header->signature != CACHE_FILE_SIGNATURE)
{
return {};
}
const auto date = std::chrono::system_clock::from_time_t(header->date_created);
if (now - date >= CACHE_MAX_AGE)
{
utils::io::remove_file(path);
return {};
}
const auto file_data = buffer + sizeof(cached_file_header);
return std::string{file_data, data.size() - sizeof(cached_file_header)};
}
std::optional<std::string> download_image(const std::string& url) std::optional<std::string> download_image(const std::string& url)
{ {
if (image_cache.contains(url)) const auto cached = read_cached_file(url);
if (cached.has_value())
{ {
return {image_cache.at(url)}; return {cached.value()};
} }
const auto res = utils::http::get_data(url); const auto res = utils::http::get_data(url);
if (res.has_value()) if (res.has_value())
{ {
image_cache[url] = res.value(); cache_file(url, res.value());
} }
return res; return res;