hmml_to_html.c: Cache the quotes
Also link to insofaras' quote site
This commit is contained in:
parent
5f21a9544d
commit
ec556a8e3b
|
@ -465,7 +465,8 @@ function handleKey(key) {
|
||||||
case "o": {
|
case "o": {
|
||||||
if(focusedElement)
|
if(focusedElement)
|
||||||
{
|
{
|
||||||
if(focusedElement.parentNode.classList.contains("references_container"))
|
if(focusedElement.parentNode.classList.contains("references_container") ||
|
||||||
|
focusedElement.parentNode.classList.contains("quotes_container"))
|
||||||
{
|
{
|
||||||
var url = focusedElement.getAttribute("href");
|
var url = focusedElement.getAttribute("href");
|
||||||
window.open(url, "_blank");
|
window.open(url, "_blank");
|
||||||
|
|
|
@ -19,6 +19,8 @@ typedef unsigned int bool;
|
||||||
#include <getopt.h> // NOTE(matt): getopts
|
#include <getopt.h> // NOTE(matt): getopts
|
||||||
//#include "config.h" // TODO(matt): Implement config.h
|
//#include "config.h" // TODO(matt): Implement config.h
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#define Kilobytes(Bytes) Bytes << 10
|
#define Kilobytes(Bytes) Bytes << 10
|
||||||
#define Megabytes(Bytes) Bytes << 20
|
#define Megabytes(Bytes) Bytes << 20
|
||||||
|
@ -823,40 +825,11 @@ CurlIntoBuffer(char *InPtr, size_t CharLength, size_t Chars, char **OutputPtr)
|
||||||
return Length;
|
return Length;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
int
|
int
|
||||||
BuildQuote(quote_info *Info, char *Speaker, int ID)
|
SearchQuotes(buffer QuoteStaging, int CacheSize, quote_info *Info, int ID)
|
||||||
{
|
{
|
||||||
char QuotesURL[256];
|
|
||||||
CopyString(QuotesURL, "https://dev.abaines.me.uk/quotes/%s.raw", Speaker);
|
|
||||||
|
|
||||||
buffer QuoteStaging;
|
|
||||||
QuoteStaging.ID = "QuoteStaging";
|
|
||||||
QuoteStaging.Size = Kilobytes(256);
|
|
||||||
if(!(QuoteStaging.Location = malloc(QuoteStaging.Size)))
|
|
||||||
{
|
|
||||||
perror("malloc");
|
|
||||||
}
|
|
||||||
QuoteStaging.Ptr = QuoteStaging.Location;
|
QuoteStaging.Ptr = QuoteStaging.Location;
|
||||||
|
while(QuoteStaging.Ptr - QuoteStaging.Location < CacheSize)
|
||||||
CURL *curl = curl_easy_init();
|
|
||||||
if(curl) {
|
|
||||||
CURLcode res;
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &QuoteStaging.Ptr);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlIntoBuffer);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, QuotesURL);
|
|
||||||
if((res = curl_easy_perform(curl)))
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s", curl_easy_strerror(res));
|
|
||||||
}
|
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(matt): Search the quote store in reverse
|
|
||||||
QuoteStaging.Ptr = QuoteStaging.Location;
|
|
||||||
|
|
||||||
while(*QuoteStaging.Ptr)
|
|
||||||
{
|
{
|
||||||
char InID[4] = { 0 };
|
char InID[4] = { 0 };
|
||||||
char InTime[16] = { 0 };
|
char InTime[16] = { 0 };
|
||||||
|
@ -900,11 +873,87 @@ BuildQuote(quote_info *Info, char *Speaker, int ID)
|
||||||
++QuoteStaging.Ptr;
|
++QuoteStaging.Ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeBuffer(&QuoteStaging);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
BuildQuote(quote_info *Info, char *Speaker, int ID, char *CacheDir)
|
||||||
|
{
|
||||||
|
// TODO(matt): Rebuild cache option
|
||||||
|
|
||||||
|
char QuoteCacheDir[255];
|
||||||
|
CopyString(QuoteCacheDir, "%s/quotes", CacheDir);
|
||||||
|
char QuoteCachePath[255];
|
||||||
|
CopyString(QuoteCachePath, "%s/%s", QuoteCacheDir, Speaker);
|
||||||
|
FILE *QuoteCache;
|
||||||
|
|
||||||
|
while(!(QuoteCache = fopen(QuoteCachePath, "a+")))
|
||||||
|
{
|
||||||
|
char StagingDirectory[255];
|
||||||
|
CopyString(StagingDirectory, QuoteCacheDir);
|
||||||
|
while(mkdir(StagingDirectory, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1)
|
||||||
|
{
|
||||||
|
int i = StringLength(StagingDirectory);
|
||||||
|
while(StagingDirectory[i] != '/')
|
||||||
|
{
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
StagingDirectory[i] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(QuoteCache, 0, SEEK_END);
|
||||||
|
int FileSize = ftell(QuoteCache);
|
||||||
|
fseek(QuoteCache, 0, SEEK_SET);
|
||||||
|
|
||||||
|
buffer QuoteStaging;
|
||||||
|
QuoteStaging.ID = "QuoteStaging";
|
||||||
|
QuoteStaging.Size = Kilobytes(256);
|
||||||
|
if(!(QuoteStaging.Location = malloc(QuoteStaging.Size)))
|
||||||
|
{
|
||||||
|
perror("malloc");
|
||||||
|
}
|
||||||
|
QuoteStaging.Ptr = QuoteStaging.Location;
|
||||||
|
|
||||||
|
fread(QuoteStaging.Location, FileSize, 1, QuoteCache);
|
||||||
|
fclose(QuoteCache);
|
||||||
|
|
||||||
|
if(SearchQuotes(QuoteStaging, FileSize, Info, ID) == 1)
|
||||||
|
{
|
||||||
|
char QuotesURL[256];
|
||||||
|
CopyString(QuotesURL, "https://dev.abaines.me.uk/quotes/%s.raw", Speaker);
|
||||||
|
|
||||||
|
CURL *curl = curl_easy_init();
|
||||||
|
if(curl) {
|
||||||
|
CURLcode res;
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &QuoteStaging.Ptr);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlIntoBuffer);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, QuotesURL);
|
||||||
|
if((res = curl_easy_perform(curl)))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s", curl_easy_strerror(res));
|
||||||
|
}
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!(QuoteCache = fopen(QuoteCachePath, "w")))
|
||||||
|
{
|
||||||
|
perror(QuoteCachePath);
|
||||||
|
}
|
||||||
|
fwrite(QuoteStaging.Location, QuoteStaging.Ptr - QuoteStaging.Location, 1, QuoteCache);
|
||||||
|
fclose(QuoteCache);
|
||||||
|
|
||||||
|
int CacheSize = QuoteStaging.Ptr - QuoteStaging.Location;
|
||||||
|
QuoteStaging.Ptr = QuoteStaging.Location;
|
||||||
|
if(SearchQuotes(QuoteStaging, CacheSize, Info, ID) == 1)
|
||||||
|
{
|
||||||
|
FreeBuffer(&QuoteStaging);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GenerateTopicColours(buffer *Colour, char *Topic, char *TopicsDir)
|
GenerateTopicColours(buffer *Colour, char *Topic, char *TopicsDir)
|
||||||
{
|
{
|
||||||
|
@ -1308,6 +1357,16 @@ main(int ArgC, char **Args)
|
||||||
bool DefaultForceIntegration = FALSE;
|
bool DefaultForceIntegration = FALSE;
|
||||||
bool ForceIntegration = DefaultForceIntegration;
|
bool ForceIntegration = DefaultForceIntegration;
|
||||||
|
|
||||||
|
char CacheDir[255] = { 0 };
|
||||||
|
if(getenv("XDG_CACHE_HOME"))
|
||||||
|
{
|
||||||
|
CopyString(CacheDir, "%s/cinera", getenv("XDG_CACHE_HOME"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CopyString(CacheDir, "%s/.cache/cinera", getenv("HOME"));
|
||||||
|
}
|
||||||
|
|
||||||
if(ArgC < 2)
|
if(ArgC < 2)
|
||||||
{
|
{
|
||||||
PrintUsage(Args[0], DefaultCSSDir, DefaultImagesDir, DefaultJSDir, DefaultDefaultMedium, DefaultOutLocation, DefaultTemplateLocation);
|
PrintUsage(Args[0], DefaultCSSDir, DefaultImagesDir, DefaultJSDir, DefaultDefaultMedium, DefaultOutLocation, DefaultTemplateLocation);
|
||||||
|
@ -2084,7 +2143,10 @@ main(int ArgC, char **Args)
|
||||||
|
|
||||||
HasQuote = TRUE;
|
HasQuote = TRUE;
|
||||||
|
|
||||||
if(BuildQuote(&QuoteInfo, Anno->quote.author ? Anno->quote.author : HMML.metadata.stream_username ? HMML.metadata.stream_username : HMML.metadata.member, Anno->quote.id) == 1)
|
if(BuildQuote(&QuoteInfo,
|
||||||
|
Anno->quote.author ? Anno->quote.author : HMML.metadata.stream_username ? HMML.metadata.stream_username : HMML.metadata.member,
|
||||||
|
Anno->quote.id,
|
||||||
|
CacheDir) == 1)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s:%d: Quote #%s %d not found. Unlucky!\n",
|
fprintf(stderr, "%s:%d: Quote #%s %d not found. Unlucky!\n",
|
||||||
Args[FileIndex],
|
Args[FileIndex],
|
||||||
|
@ -2098,22 +2160,26 @@ main(int ArgC, char **Args)
|
||||||
}
|
}
|
||||||
|
|
||||||
CopyStringToBuffer(&QuoteMenu,
|
CopyStringToBuffer(&QuoteMenu,
|
||||||
" <span data-id=\"&#%d;\" class=\"ref\">\n"
|
" <a target=\"_blank\" class=\"ref\" href=\"https://dev.abaines.me.uk/quotes/%s/%d\">\n"
|
||||||
" <span class=\"ref_content\">\n"
|
" <span data-id=\"&#%d;\">\n"
|
||||||
" <div class=\"source\">Quote %d</div>\n"
|
" <span class=\"ref_content\">\n"
|
||||||
" <div class=\"ref_title\">",
|
" <div class=\"source\">Quote %d</div>\n"
|
||||||
|
" <div class=\"ref_title\">",
|
||||||
|
Anno->quote.author ? Anno->quote.author : HMML.metadata.stream_username ? HMML.metadata.stream_username : HMML.metadata.member,
|
||||||
|
Anno->quote.id,
|
||||||
QuoteIdentifier,
|
QuoteIdentifier,
|
||||||
Anno->quote.id);
|
Anno->quote.id);
|
||||||
|
|
||||||
CopyStringToBufferCSVSafe(&QuoteMenu, QuoteInfo.Text);
|
CopyStringToBufferCSVSafe(&QuoteMenu, QuoteInfo.Text);
|
||||||
|
|
||||||
CopyStringToBuffer(&QuoteMenu, "</div>\n"
|
CopyStringToBuffer(&QuoteMenu, "</div>\n"
|
||||||
" <div class=\"quote_byline\">—%s, %s</div>\n"
|
" <div class=\"quote_byline\">—%s, %s</div>\n"
|
||||||
|
" </span>\n"
|
||||||
|
" <div class=\"ref_indices\">\n"
|
||||||
|
" <span data-timestamp=\"%d\" class=\"timecode\"><span class=\"ref_index\">[&#%d;]</span><span class=\"time\">%s</span></span>\n"
|
||||||
|
" </div>\n"
|
||||||
" </span>\n"
|
" </span>\n"
|
||||||
" <div class=\"ref_indices\">\n"
|
" </a>\n",
|
||||||
" <span data-timestamp=\"%d\" class=\"timecode\"><span class=\"ref_index\">[&#%d;]</span><span class=\"time\">%s</span></span>\n"
|
|
||||||
" </div>\n"
|
|
||||||
" </span>\n",
|
|
||||||
Anno->quote.author ? Anno->quote.author : HMML.metadata.stream_username ? HMML.metadata.stream_username : HMML.metadata.member,
|
Anno->quote.author ? Anno->quote.author : HMML.metadata.stream_username ? HMML.metadata.stream_username : HMML.metadata.member,
|
||||||
QuoteInfo.Date,
|
QuoteInfo.Date,
|
||||||
TimecodeToSeconds(Anno->time),
|
TimecodeToSeconds(Anno->time),
|
||||||
|
@ -2531,34 +2597,66 @@ main(int ArgC, char **Args)
|
||||||
" <span style=\"width: auto\" class=\"help_key unavailable\">Enter</span> <span class=\"help_text unavailable\">Jump to timecode</span><br>\n");
|
" <span style=\"width: auto\" class=\"help_key unavailable\">Enter</span> <span class=\"help_text unavailable\">Jump to timecode</span><br>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(HasReferenceMenu)
|
if(HasQuoteMenu)
|
||||||
{
|
{
|
||||||
CopyStringToBuffer(&Menus,
|
CopyStringToBuffer(&Menus,
|
||||||
" <h2>References ");
|
" <h2>Quotes");
|
||||||
if(HasCreditsMenu)
|
if(HasReferenceMenu)
|
||||||
{
|
{
|
||||||
CopyStringToBuffer(&Menus, "and Credits Menus</h2>\n");
|
CopyStringToBuffer(&Menus, ", References ");
|
||||||
|
if(HasCreditsMenu)
|
||||||
|
{
|
||||||
|
CopyStringToBuffer(&Menus, "and Credits Menus</h2>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CopyStringToBuffer(&Menus, "<span class=\"unavailable\">and Credits</span> Menus</h2>");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CopyStringToBuffer(&Menus, "<span class=\"unavailable\">and Credits</span> Menus</h2>\n");
|
CopyStringToBuffer(&Menus, "<span class=\"unavailable\">, References ");
|
||||||
|
if(HasCreditsMenu)
|
||||||
|
{
|
||||||
|
CopyStringToBuffer(&Menus, "</span>and Credits Menus</h2>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CopyStringToBuffer(&Menus, "and Credits</span> Menus</h2>");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CopyStringToBuffer(&Menus,
|
CopyStringToBuffer(&Menus,
|
||||||
" <h2><span class=\"unavailable\">References");
|
" <h2><span class=\"unavailable\">Quotes");
|
||||||
if(HasCreditsMenu)
|
if(HasReferenceMenu)
|
||||||
{
|
{
|
||||||
CopyStringToBuffer(&Menus, " and</span> Credits Menus</h2>\n");
|
CopyStringToBuffer(&Menus, ", </span>References ");
|
||||||
|
if(HasCreditsMenu)
|
||||||
|
{
|
||||||
|
CopyStringToBuffer(&Menus, "and Credits Menus</h2>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CopyStringToBuffer(&Menus, "<span class=\"unavailable\">and Credits</span> Menus</h2>");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CopyStringToBuffer(&Menus, " and Credits Menus</span></h2>\n");
|
CopyStringToBuffer(&Menus, ", References ");
|
||||||
|
if(HasCreditsMenu)
|
||||||
|
{
|
||||||
|
CopyStringToBuffer(&Menus, "</span>and Credits Menus</h2>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CopyStringToBuffer(&Menus, "and Credits Menus</h2></span>");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(HasReferenceMenu || HasCreditsMenu)
|
if(HasQuoteMenu || HasReferenceMenu || HasCreditsMenu)
|
||||||
{
|
{
|
||||||
CopyStringToBuffer(&Menus,
|
CopyStringToBuffer(&Menus,
|
||||||
" <span class=\"help_key\">o</span> <span class=\"help_text\">Open URL (in new tab)</span>\n");
|
" <span class=\"help_key\">o</span> <span class=\"help_text\">Open URL (in new tab)</span>\n");
|
||||||
|
|
Loading…
Reference in New Issue