Skip to content

Commit

Permalink
added stub for caching figurine images
Browse files Browse the repository at this point in the history
  • Loading branch information
g3gg0 committed Aug 12, 2024
1 parent 8fa739c commit 4a66c22
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 6 deletions.
8 changes: 8 additions & 0 deletions include/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ typedef struct
char *datadirfull;
char *wwwdirfull;
char *firmwaredirfull;
char *cachedirfull;

char *overlayUniqueId;
uint8_t overlayNumber;
Expand Down Expand Up @@ -248,6 +249,7 @@ typedef struct
char *configdir;
char *contentdir;
char *firmwaredir;
char *cachedir;
char *librarydir;
char *datadir;
char *wwwdir;
Expand Down Expand Up @@ -300,6 +302,11 @@ typedef struct
char *filename;
} settings_pcap_t;

typedef struct
{
bool cache_images;
} settings_tonie_json_t;

typedef struct
{
uint32_t configVersion;
Expand All @@ -318,6 +325,7 @@ typedef struct
settings_log_t log;
settings_rtnl_t rtnl;
settings_pcap_t pcap;
settings_tonie_json_t tonie_json;
} settings_t;

typedef enum
Expand Down
18 changes: 13 additions & 5 deletions src/settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,10 @@ static void option_map_init(uint8_t settingsId)
OPTION_INTERNAL_STRING("core.configdir", &settings->core.configdir, CONFIG_BASE_PATH, "Configuration dir", LEVEL_EXPERT)
OPTION_STRING("core.contentdir", &settings->core.contentdir, "default", "Content dir", "Directory for placing cloud content", LEVEL_DETAIL)
OPTION_STRING("core.librarydir", &settings->core.librarydir, "library", "Library dir", "Directory of the audio library", LEVEL_DETAIL)
OPTION_STRING("core.datadir", &settings->core.datadir, "data", "Data dir", "Base directory for 'contentdir', 'firmwaredir' and 'wwwdir' when they are relative", LEVEL_EXPERT)
OPTION_STRING("core.datadir", &settings->core.datadir, "data", "Data dir", "Base directory for 'contentdir', 'firmwaredir', 'cachedir' and 'wwwdir' when they are relative", LEVEL_EXPERT)
OPTION_INTERNAL_STRING("core.wwwdir", &settings->core.wwwdir, "www", "WWW dir", LEVEL_NONE)
OPTION_STRING("core.firmwaredir", &settings->core.firmwaredir, "firmware", "Firmware dir", "Directory to upload original firmware", LEVEL_DETAIL)
OPTION_STRING("core.cachedir", &settings->core.cachedir, "cache", "Cache dir", "Directory where to cache files downloaded from internet", LEVEL_DETAIL)
OPTION_STRING("core.sslkeylogfile", &settings->core.sslkeylogfile, "", "SSL-key logfile", "SSL/TLS key log filename", LEVEL_EXPERT)

OPTION_TREE_DESC("core.server_cert", "HTTPS server certificates", LEVEL_EXPERT)
Expand Down Expand Up @@ -151,6 +152,7 @@ static void option_map_init(uint8_t settingsId)
OPTION_INTERNAL_STRING("internal.datadirfull", &settings->internal.datadirfull, "", "Directory where data is placed (absolute)", LEVEL_NONE)
OPTION_INTERNAL_STRING("internal.wwwdirfull", &settings->internal.wwwdirfull, "", "Directory where web content is placed (absolute)", LEVEL_NONE)
OPTION_INTERNAL_STRING("internal.firmwaredirfull", &settings->internal.firmwaredirfull, "", "Directory where firmwares are placed (absolute)", LEVEL_NONE)
OPTION_INTERNAL_STRING("internal.cachedirfull", &settings->internal.cachedirfull, "", "Directory where cached files are placed (absolute)", LEVEL_NONE)
OPTION_INTERNAL_STRING("internal.overlayUniqueId", &settings->internal.overlayUniqueId, "", "Unique Id of the overlay", LEVEL_NONE)
OPTION_INTERNAL_UNSIGNED("internal.overlayNumber", &settings->internal.overlayNumber, 0, 0, MAX_OVERLAYS, "Id of the overlay", LEVEL_NONE)
OPTION_INTERNAL_STRING("internal.assign_unknown", &settings->internal.assign_unknown, "", "TAF file to assign to the next unknown tag", LEVEL_NONE)
Expand Down Expand Up @@ -227,7 +229,7 @@ static void option_map_init(uint8_t settingsId)
OPTION_BOOL("encode.ffmpeg_stream_restart", &settings->encode.ffmpeg_stream_restart, FALSE, "Stream force restart", "If a stream is continued by the box, a new file is forced. This has the cost of a slower restart, but does not play the old buffered content and deletes the previous stream data on the box.", LEVEL_EXPERT)
OPTION_BOOL("encode.ffmpeg_sweep_startup_buffer", &settings->encode.ffmpeg_sweep_startup_buffer, TRUE, "Sweep stream prebuffer", "Webradio streams often send several seconds as a buffer immediately. This may contain ads and will add up if you disalbe 'Stream force restart'.", LEVEL_EXPERT)
OPTION_UNSIGNED("encode.ffmpeg_sweep_delay_ms", &settings->encode.ffmpeg_sweep_delay_ms, 2000, 0, 10000, "Sweep delay ms", "Wait x ms until sweeping is stopped and stream is started. Delays stream start, but may increase success.", LEVEL_EXPERT)
OPTION_UNSIGNED("encode.stream_max_size", &settings->encode.stream_max_size, 1024 * 1024 * 40 * 6 -1, 1024 * 1024 - 1, INT32_MAX, "Max stream filesize", "The box may create an empty file this length for each stream. So if you have 10 streaming tonies you use, the box may block 10*240MB. The only downside is, that the box will stop after the file is full and you'll need to replace the tag onto the box. Must not be a multiply of 4096, Default: 251.658.239, so 240MB, which means around 6h.", LEVEL_EXPERT)
OPTION_UNSIGNED("encode.stream_max_size", &settings->encode.stream_max_size, 1024 * 1024 * 40 * 6 - 1, 1024 * 1024 - 1, INT32_MAX, "Max stream filesize", "The box may create an empty file this length for each stream. So if you have 10 streaming tonies you use, the box may block 10*240MB. The only downside is, that the box will stop after the file is full and you'll need to replace the tag onto the box. Must not be a multiply of 4096, Default: 251.658.239, so 240MB, which means around 6h.", LEVEL_EXPERT)

OPTION_TREE_DESC("toniebox", "Toniebox", LEVEL_BASIC)
OPTION_BOOL("toniebox.api_access", &settings->toniebox.api_access, TRUE, "API access", "Grant access to the API (default value for new boxes)", LEVEL_EXPERT)
Expand Down Expand Up @@ -261,6 +263,9 @@ static void option_map_init(uint8_t settingsId)
OPTION_TREE_DESC("hass", "Home Assistant", LEVEL_DETAIL)
OPTION_STRING("hass.name", &settings->hass.name, "teddyCloud - Server", "Home Assistant name", "Home Assistant name", LEVEL_DETAIL)
OPTION_STRING("hass.id", &settings->hass.id, "teddyCloud_Server", "Unique ID", "Unique ID to identify this device", LEVEL_DETAIL)

OPTION_TREE_DESC("tonie_json", "Tonie JSON", LEVEL_DETAIL)
OPTION_BOOL("tonie_json.cache_images", &settings->tonie_json.cache_images, FALSE, "Cache images", "Download and cache figurine images", LEVEL_DETAIL)
OPTION_END()

settings_size = sizeof(option_map_array) / sizeof(option_map_array[0]) - 1;
Expand Down Expand Up @@ -424,7 +429,7 @@ uint8_t get_overlay_id(const char *overlay_unique_id)

void settings_resolve_dir(char **resolvedPath, char *path, char *basePath)
{
if(!resolvedPath || !*resolvedPath || !path)
if (!resolvedPath || !*resolvedPath || !path)
{
return;
}
Expand All @@ -435,7 +440,7 @@ void settings_resolve_dir(char **resolvedPath, char *path, char *basePath)
}
else
{
if(!basePath)
if (!basePath)
{
return;
}
Expand All @@ -462,6 +467,7 @@ static void settings_generate_internal_dirs(settings_t *settings)
free(settings->internal.datadirfull);
free(settings->internal.wwwdirfull);
free(settings->internal.firmwaredirfull);
free(settings->internal.cachedirfull);

settings->internal.basedirfull = osAllocMem(256);
settings->internal.certdirfull = osAllocMem(256);
Expand All @@ -472,6 +478,7 @@ static void settings_generate_internal_dirs(settings_t *settings)
settings->internal.datadirfull = osAllocMem(256);
settings->internal.wwwdirfull = osAllocMem(256);
settings->internal.firmwaredirfull = osAllocMem(256);
settings->internal.cachedirfull = osAllocMem(256);

char *tmpPath = osAllocMem(256);
settings_resolve_dir(&settings->internal.basedirfull, settings->internal.basedir, settings->internal.cwd);
Expand All @@ -482,6 +489,7 @@ static void settings_generate_internal_dirs(settings_t *settings)

settings_resolve_dir(&settings->internal.wwwdirfull, settings->core.wwwdir, settings->internal.datadirfull);
settings_resolve_dir(&settings->internal.firmwaredirfull, settings->core.firmwaredir, settings->internal.datadirfull);
settings_resolve_dir(&settings->internal.cachedirfull, settings->core.cachedir, settings->internal.datadirfull);

settings_resolve_dir(&tmpPath, settings->core.contentdir, "content");
settings_resolve_dir(&settings->internal.contentdirrel, tmpPath, settings->core.datadir);
Expand Down Expand Up @@ -525,7 +533,7 @@ void settings_changed_id(uint8_t settingsId)

static void settings_deinit_ovl(uint8_t overlayNumber)
{
if(overlayNumber >= MAX_OVERLAYS)
if (overlayNumber >= MAX_OVERLAYS)
{
return;
}
Expand Down
83 changes: 82 additions & 1 deletion src/toniesJson.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "cloud_request.h"
#include "server_helpers.h"
#include "mutex_manager.h"
#include "hash/sha256.h" // for sha256Update, sha256Final, sha256Init

#define TONIES_JSON_CACHED 1
#if TONIES_JSON_CACHED == 1
Expand Down Expand Up @@ -367,7 +368,87 @@ void tonies_readJson(char *source, toniesJson_item_t **retCache, size_t *retCoun
osFreeMem(releaseString);
item->language = tonies_jsonGetString(tonieJson, "language");
item->category = tonies_jsonGetString(tonieJson, "category");
item->picture = tonies_jsonGetString(tonieJson, "pic");

char *pic_link = tonies_jsonGetString(tonieJson, "pic");

if (osStrlen(pic_link) > 0 && settings_get_bool("tonie_json.cache_images"))
{
const char *cachePath = get_settings()->internal.cachedirfull;
if (cachePath == NULL || !fsDirExists(cachePath))
{
char message[128];
osSnprintf(message, sizeof(message), "core.cachedirfull not set to a valid path: '%s'", cachePath);
TRACE_ERROR("%s\r\n", message);
}
else
{
uint8_t sha256_calc[32];
char sha256_calc_str[65];

/* hash the image URL */
Sha256Context ctx;
sha256Init(&ctx);
sha256Update(&ctx, pic_link, strlen(pic_link));
sha256Final(&ctx, sha256_calc);

for (int pos = 0; pos < 32; pos++)
{
osSprintf(&sha256_calc_str[2 * pos], "%02X", sha256_calc[pos]);
}

/* Find the file extension from the URL */
const char *ext_pos = strrchr(pic_link, '.');
char *extension = strdup("jpg");

if (ext_pos && !osStrchr(ext_pos, '/'))
{
osFreeMem(extension);
extension = strdup(&ext_pos[1]);

/* Remove optional HTTP GET parameters */
char *query_param = osStrchr(extension, '?');
if (query_param)
{
*query_param = '\0';
}
}
char *cached_filename = custom_asprintf("%s/%s.%s", cachePath, sha256_calc_str, extension);
char *cached_url = custom_asprintf("%s/cache/%s", settings_get_string("core.host_url"), sha256_calc_str);

osFreeMem(extension);

TRACE_INFO("Original URL: '%s'\r\n", pic_link);
TRACE_INFO("Cache filename would be: '%s'\r\n", cached_filename);
TRACE_INFO("Cache URL would be: '%s'\r\n", cached_url);

/* check if it is already cached */
if (fsFileExists(cached_filename))
{
TRACE_INFO("File exists, not downloading\r\n");
osFreeMem(pic_link);
pic_link = strdup(cached_url);
}
else
{
/* if not, try to download and cache the file */
TRACE_INFO("Download file from original URL -> not implemented yet\r\n");

/*
fsFile = fsOpenFile(cached_filename, FS_FILE_MODE_WRITE);
if (fsFile != NULL)
{
fsWriteFile(fsFile, " ", 1);
fsCloseFile(fsFile);
osFreeMem(pic_link);
pic_link = strdup(cached_url);
}
*/
}
osFreeMem(cached_filename);
osFreeMem(cached_url);
}
}
item->picture = pic_link;
}
cJSON_Delete(toniesJson);
}
Expand Down

0 comments on commit 4a66c22

Please sign in to comment.