summaryrefslogtreecommitdiff
path: root/src/feeds.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-11-27 14:35:54 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-11-27 14:35:54 +0200
commit6e8924cb5e95466cbdbe6c237365a8383c35b26b (patch)
treed5ced984200555684bc1f3843b4de45ae9dca725 /src/feeds.c
parent54f063e859f8e7eb5c3a825763ed4c85d30ef5b5 (diff)
Feeds: Separate timestamps for posting and discovery
The discovery time is needed for knowing how long the entry can be retained in the history.
Diffstat (limited to 'src/feeds.c')
-rw-r--r--src/feeds.c34
1 files changed, 22 insertions, 12 deletions
diff --git a/src/feeds.c b/src/feeds.c
index 26d8c04f..3340d201 100644
--- a/src/feeds.c
+++ b/src/feeds.c
@@ -43,7 +43,8 @@ iDeclareType(FeedJob)
43iDefineTypeConstruction(FeedEntry) 43iDefineTypeConstruction(FeedEntry)
44 44
45void init_FeedEntry(iFeedEntry *d) { 45void init_FeedEntry(iFeedEntry *d) {
46 iZap(d->timestamp); 46 iZap(d->posted);
47 iZap(d->discovered);
47 init_String(&d->url); 48 init_String(&d->url);
48 init_String(&d->title); 49 init_String(&d->title);
49 d->bookmarkId = 0; 50 d->bookmarkId = 0;
@@ -135,6 +136,8 @@ static void parseResult_FeedJob_(iFeedJob *d) {
135 /* TODO: Should tell the user if the request failed. */ 136 /* TODO: Should tell the user if the request failed. */
136 if (isSuccess_GmStatusCode(status_GmRequest(d->request))) { 137 if (isSuccess_GmStatusCode(status_GmRequest(d->request))) {
137 iBeginCollect(); 138 iBeginCollect();
139 iTime now;
140 initCurrent_Time(&now);
138 iRegExp *linkPattern = 141 iRegExp *linkPattern =
139 new_RegExp("^=>\\s*([^\\s]+)\\s+" 142 new_RegExp("^=>\\s*([^\\s]+)\\s+"
140 "([0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9])" 143 "([0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9])"
@@ -153,6 +156,7 @@ static void parseResult_FeedJob_(iFeedJob *d) {
153 const iRangecc date = capturedRange_RegExpMatch(&m, 2); 156 const iRangecc date = capturedRange_RegExpMatch(&m, 2);
154 const iRangecc title = capturedRange_RegExpMatch(&m, 3); 157 const iRangecc title = capturedRange_RegExpMatch(&m, 3);
155 iFeedEntry * entry = new_FeedEntry(); 158 iFeedEntry * entry = new_FeedEntry();
159 entry->discovered = now;
156 entry->bookmarkId = d->bookmarkId; 160 entry->bookmarkId = d->bookmarkId;
157 setRange_String(&entry->url, url); 161 setRange_String(&entry->url, url);
158 set_String(&entry->url, absoluteUrl_String(url_GmRequest(d->request), &entry->url)); 162 set_String(&entry->url, absoluteUrl_String(url_GmRequest(d->request), &entry->url));
@@ -161,7 +165,7 @@ static void parseResult_FeedJob_(iFeedJob *d) {
161 int year, month, day; 165 int year, month, day;
162 sscanf(date.start, "%04d-%02d-%02d", &year, &month, &day); 166 sscanf(date.start, "%04d-%02d-%02d", &year, &month, &day);
163 init_Time( 167 init_Time(
164 &entry->timestamp, 168 &entry->posted,
165 &(iDate){ 169 &(iDate){
166 .year = year, .month = month, .day = day, .hour = 12 /* noon UTC */ }); 170 .year = year, .month = month, .day = day, .hour = 12 /* noon UTC */ });
167 pushBack_PtrArray(&d->results, entry); 171 pushBack_PtrArray(&d->results, entry);
@@ -185,15 +189,15 @@ static iBool updateEntries_Feeds_(iFeeds *d, iPtrArray *incoming) {
185 iBool changed = iFalse; 189 iBool changed = iFalse;
186 iDate newDate; 190 iDate newDate;
187 iDate oldDate; 191 iDate oldDate;
188 init_Date(&newDate, &entry->timestamp); 192 init_Date(&newDate, &entry->posted);
189 init_Date(&oldDate, &existing->timestamp); 193 init_Date(&oldDate, &existing->posted);
190 if (!equalCase_String(&existing->title, &entry->title) || 194 if (!equalCase_String(&existing->title, &entry->title) ||
191 (newDate.year != oldDate.year || newDate.month != oldDate.month || 195 (newDate.year != oldDate.year || newDate.month != oldDate.month ||
192 newDate.day != oldDate.day)) { 196 newDate.day != oldDate.day)) {
193 changed = iTrue; 197 changed = iTrue;
194 } 198 }
195 set_String(&existing->title, &entry->title); 199 set_String(&existing->title, &entry->title);
196 existing->timestamp = entry->timestamp; 200 existing->posted = entry->posted;
197 delete_FeedEntry(entry); 201 delete_FeedEntry(entry);
198 if (changed) { 202 if (changed) {
199 /* TODO: better to use a new flag for read feed entries? */ 203 /* TODO: better to use a new flag for read feed entries? */
@@ -321,9 +325,10 @@ static void save_Feeds_(iFeeds *d) {
321 writeData_File(f, "# Entries\n", 10); 325 writeData_File(f, "# Entries\n", 10);
322 iConstForEach(Array, i, &d->entries.values) { 326 iConstForEach(Array, i, &d->entries.values) {
323 const iFeedEntry *entry = *(const iFeedEntry **) i.value; 327 const iFeedEntry *entry = *(const iFeedEntry **) i.value;
324 format_String(str, "%x\n%llu\n%s\n%s\n", 328 format_String(str, "%x\n%llu\n%llu\n%s\n%s\n",
325 entry->bookmarkId, 329 entry->bookmarkId,
326 integralSeconds_Time(&entry->timestamp), 330 integralSeconds_Time(&entry->posted),
331 integralSeconds_Time(&entry->discovered),
327 cstr_String(&entry->url), 332 cstr_String(&entry->url),
328 cstr_String(&entry->title)); 333 cstr_String(&entry->title));
329 write_File(f, utf8_String(str)); 334 write_File(f, utf8_String(str));
@@ -385,7 +390,11 @@ static void load_Feeds_(iFeeds *d) {
385 case 2: { 390 case 2: {
386 const uint32_t feedId = strtoul(line.start, NULL, 16); 391 const uint32_t feedId = strtoul(line.start, NULL, 16);
387 if (!nextSplit_Rangecc(range_Block(src), "\n", &line)) break; 392 if (!nextSplit_Rangecc(range_Block(src), "\n", &line)) break;
388 const unsigned long long ts = strtoull(line.start, NULL, 10); 393 const unsigned long long posted = strtoull(line.start, NULL, 10);
394 if (posted == 0) break;
395 if (!nextSplit_Rangecc(range_Block(src), "\n", &line)) break;
396 const unsigned long long discovered = strtoull(line.start, NULL, 10);
397 if (discovered == 0) break;
389 if (!nextSplit_Rangecc(range_Block(src), "\n", &line)) break; 398 if (!nextSplit_Rangecc(range_Block(src), "\n", &line)) break;
390 const iRangecc urlRange = line; 399 const iRangecc urlRange = line;
391 if (!nextSplit_Rangecc(range_Block(src), "\n", &line)) break; 400 if (!nextSplit_Rangecc(range_Block(src), "\n", &line)) break;
@@ -396,8 +405,9 @@ static void load_Feeds_(iFeeds *d) {
396 const iFeedHashNode *node = (iFeedHashNode *) value_Hash(feeds, feedId); 405 const iFeedHashNode *node = (iFeedHashNode *) value_Hash(feeds, feedId);
397 if (node) { 406 if (node) {
398 iFeedEntry *entry = new_FeedEntry(); 407 iFeedEntry *entry = new_FeedEntry();
399 entry->bookmarkId = node->bookmarkId; 408 entry->bookmarkId = node->bookmarkId;
400 entry->timestamp.ts.tv_sec = ts; 409 entry->posted.ts.tv_sec = posted;
410 entry->discovered.ts.tv_sec = discovered;
401 set_String(&entry->url, url); 411 set_String(&entry->url, url);
402 set_String(&entry->title, title); 412 set_String(&entry->title, title);
403 insert_SortedArray(&d->entries, &entry); 413 insert_SortedArray(&d->entries, &entry);
@@ -475,7 +485,7 @@ void removeEntries_Feeds(uint32_t feedBookmarkId) {
475 485
476static int cmpTimeDescending_FeedEntryPtr_(const void *a, const void *b) { 486static int cmpTimeDescending_FeedEntryPtr_(const void *a, const void *b) {
477 const iFeedEntry * const *e1 = a, * const *e2 = b; 487 const iFeedEntry * const *e1 = a, * const *e2 = b;
478 return -cmp_Time(&(*e1)->timestamp, &(*e2)->timestamp); 488 return -cmp_Time(&(*e1)->posted, &(*e2)->posted);
479} 489}
480 490
481const iPtrArray *listEntries_Feeds(void) { 491const iPtrArray *listEntries_Feeds(void) {
@@ -519,7 +529,7 @@ const iString *entryListPage_Feeds(void) {
519 iConstForEach(PtrArray, i, listEntries_Feeds()) { 529 iConstForEach(PtrArray, i, listEntries_Feeds()) {
520 const iFeedEntry *entry = i.ptr; 530 const iFeedEntry *entry = i.ptr;
521 iDate entryDate; 531 iDate entryDate;
522 init_Date(&entryDate, &entry->timestamp); 532 init_Date(&entryDate, &entry->posted);
523 if (on.year != entryDate.year || on.month != entryDate.month || on.day != entryDate.day) { 533 if (on.year != entryDate.year || on.month != entryDate.month || on.day != entryDate.day) {
524 appendFormat_String( 534 appendFormat_String(
525 src, "## %s\n", cstrCollect_String(format_Date(&entryDate, "%Y-%m-%d"))); 535 src, "## %s\n", cstrCollect_String(format_Date(&entryDate, "%Y-%m-%d")));