Slon/Api/V1/Statuses: Implement Boosts

Fixes #4
This commit is contained in:
Alec Murphy 2025-03-15 20:28:04 -04:00
parent 57ab5d1d1f
commit 35ff50746c
4 changed files with 357 additions and 122 deletions

View file

@ -1,3 +1,4 @@
U0 (*@slon_api_status_boost_fedi)(JsonObject* status) = NULL;
U0 (*@slon_api_status_create_fedi)(JsonObject* status) = NULL; U0 (*@slon_api_status_create_fedi)(JsonObject* status) = NULL;
U0 (*@slon_api_status_delete_fedi)(JsonObject* status) = NULL; U0 (*@slon_api_status_delete_fedi)(JsonObject* status) = NULL;
@ -62,7 +63,14 @@ U0 @slon_api_v1_statuses_query(SlonHttpSession* session, JsonArray* status_array
for (i = status_array->length - 1; i > -1; i--) { for (i = status_array->length - 1; i > -1; i--) {
status = Json.Clone(status_array->o(i), session->mem_task); status = Json.Clone(status_array->o(i), session->mem_task);
status_id = Str2I64(status->@("id")); status_id = Str2I64(status->@("id"));
status->set("bookmarked", @slon_api_status_is_bookmarked(session, status, account_id), JSON_BOOLEAN);
status->set("favourited", @slon_api_status_is_favourited(session, status, account_id), JSON_BOOLEAN); status->set("favourited", @slon_api_status_is_favourited(session, status, account_id), JSON_BOOLEAN);
if (@slon_api_status_is_reblogged(session, status, account_id)) {
status->set("reblogged", TRUE, JSON_BOOLEAN);
if (status->@("reblog")) {
status->o("reblog")->set("reblogged", TRUE, JSON_BOOLEAN);
}
}
exclude_status = FALSE; exclude_status = FALSE;
if (status->@("deleted")) { if (status->@("deleted")) {
exclude_status = TRUE; exclude_status = TRUE;
@ -82,6 +90,9 @@ U0 @slon_api_v1_statuses_query(SlonHttpSession* session, JsonArray* status_array
if (pinned && !status->@("pinned")) { if (pinned && !status->@("pinned")) {
exclude_status = TRUE; exclude_status = TRUE;
} }
if (exclude_reblogs && status->@("reblogged")) {
exclude_status = TRUE;
}
if (!exclude_status) { if (!exclude_status) {
statuses->append(status); statuses->append(status);
count++; count++;
@ -199,7 +210,14 @@ U0 @slon_api_v1_statuses_get(SlonHttpSession* session)
status = @slon_api_find_status_by_id(id, NULL); status = @slon_api_find_status_by_id(id, NULL);
if (status) { if (status) {
status = Json.Clone(status, session->mem_task); status = Json.Clone(status, session->mem_task);
status->set("bookmarked", @slon_api_status_is_bookmarked(session, status, account_id), JSON_BOOLEAN);
status->set("favourited", @slon_api_status_is_favourited(session, status, account_id), JSON_BOOLEAN); status->set("favourited", @slon_api_status_is_favourited(session, status, account_id), JSON_BOOLEAN);
if (@slon_api_status_is_reblogged(session, status, account_id)) {
status->set("reblogged", TRUE, JSON_BOOLEAN);
if (status->@("reblog")) {
status->o("reblog")->set("reblogged", TRUE, JSON_BOOLEAN);
}
}
session->send(status); session->send(status);
return; return;
} }
@ -223,6 +241,7 @@ U0 @slon_api_v1_statuses_post(SlonHttpSession* session)
U8* id = NULL; U8* id = NULL;
JsonObject* status = NULL; JsonObject* status = NULL;
JsonObject* boost = NULL;
if (session->path_count() > 4) { if (session->path_count() > 4) {
id = session->path(3); id = session->path(3);
@ -266,6 +285,25 @@ U0 @slon_api_v1_statuses_post(SlonHttpSession* session)
return; return;
} }
if (!StrICmp("reblog", verb)) {
status = Json.Clone(status, slon_db_mem_task);
boost = Json.Clone(@slon_api_reblog_status(session, status, account_id), session->mem_task);
boost->set("reblogged", TRUE, JSON_BOOLEAN);
session->send(boost);
if (@slon_api_status_boost_fedi) {
@slon_api_status_boost_fedi(Json.Clone(boost, slon_mem_task));
}
return;
}
if (!StrICmp("unreblog", verb)) {
status = Json.Clone(status, session->mem_task);
@slon_api_unreblog_status(session, status, account_id);
status->set("reblogged", FALSE, JSON_BOOLEAN);
session->send(status);
return;
}
session->status(400); session->status(400);
return; return;
} }

View file

@ -523,6 +523,54 @@ U0 @slon_activitypub_async_create_status_to(JsonObject* status, U8* dest)
Free(fetch_buffer); Free(fetch_buffer);
} }
U0 @slon_activitypub_async_boost_status_to(JsonObject* status, U8* dest)
{
Sleep(1000);
I64 i;
U8 scratch_buffer[2048];
// U8* this_actor = StrNew(status->@("uri"), slon_mem_task);
// StrFind("/statuses/", this_actor)[0] = NULL;
U8* this_actor = db->o("actors")->o(status->o("account")->@("acct"))->@("id");
if (!this_actor) {
AdamLog("slon_activitypub_async_boost_status_to: this_actor is NULL\n");
return;
}
JsonObject* announce_object = Json.CreateObject(slon_mem_task);
announce_object->set("@context", "https://www.w3.org/ns/activitystreams", JSON_STRING);
StrPrint(scratch_buffer, "%s/activity", status->@("uri"));
announce_object->set("id", scratch_buffer, JSON_STRING);
announce_object->set("type", "Announce", JSON_STRING);
announce_object->set("actor", this_actor, JSON_STRING);
announce_object->set("object", status->o("reblog")->@("uri"), JSON_STRING);
announce_object->set("published", status->@("created_at"), JSON_STRING);
announce_object->set("to", Json.Parse("[\"https://www.w3.org/ns/activitystreams#Public\"]", slon_mem_task), JSON_ARRAY);
JsonArray* cc = Json.CreateArray(slon_mem_task);
StrPrint(scratch_buffer, "%s/followers", this_actor);
cc->append(scratch_buffer, JSON_STRING);
announce_object->set("cc", cc, JSON_ARRAY);
U8* fetch_buffer = CAlloc(HTTP_FETCH_BUFFER_SIZE, slon_mem_task);
StrPrint(scratch_buffer, "%s/inbox", dest);
@slon_activitypub_signed_request(scratch_buffer, fetch_buffer, announce_object);
Free(fetch_buffer);
}
U0 @slon_activitypub_async_boost_status(JsonObject* status)
{
I64 i;
JsonArray* followers = db->o("followers")->a(status->o("account")->@("username"));
if (!followers) {
return;
}
for (i = 0; i < followers->length; i++) {
@slon_activitypub_async_boost_status_to(status, followers->@(i));
}
}
U0 @slon_activitypub_async_create_status(JsonObject* status) U0 @slon_activitypub_async_create_status(JsonObject* status)
{ {
I64 i; I64 i;
@ -591,6 +639,11 @@ U0 @slon_activitypub_follow_fedi(JsonObject* follow)
Spawn(&@slon_activitypub_async_follow, follow, "SlonAsyncFollowTask"); Spawn(&@slon_activitypub_async_follow, follow, "SlonAsyncFollowTask");
} }
U0 @slon_activitypub_boost_status_fedi(JsonObject* status)
{
Spawn(&@slon_activitypub_async_boost_status, status, "SlonAsyncBoostTask");
}
U0 @slon_activitypub_create_status_fedi(JsonObject* status) U0 @slon_activitypub_create_status_fedi(JsonObject* status)
{ {
Spawn(&@slon_activitypub_async_create_status, status, "SlonAsyncCreateTask"); Spawn(&@slon_activitypub_async_create_status, status, "SlonAsyncCreateTask");
@ -602,6 +655,7 @@ U0 @slon_activitypub_delete_status_fedi(JsonObject* status)
} }
@slon_api_follow_fedi = &@slon_activitypub_follow_fedi; @slon_api_follow_fedi = &@slon_activitypub_follow_fedi;
@slon_api_status_boost_fedi = &@slon_activitypub_boost_status_fedi;
@slon_api_status_create_fedi = &@slon_activitypub_create_status_fedi; @slon_api_status_create_fedi = &@slon_activitypub_create_status_fedi;
@slon_api_status_delete_fedi = &@slon_activitypub_delete_status_fedi; @slon_api_status_delete_fedi = &@slon_activitypub_delete_status_fedi;

View file

@ -147,6 +147,126 @@ JsonObject* @slon_api_announcement_by_id(U8* id)
return NULL; return NULL;
} }
JsonObject* @slon_api_status_lookup_by_id(U8* id, JsonArray* statuses)
{
if (!id || !statuses) {
return NULL;
}
I64 i;
JsonObject* status;
for (i = 0; i < statuses->length; i++) {
status = statuses->@(i);
if (!status->@("deleted") && status->@("id") && !StrICmp(status->@("id"), id)) {
return status;
}
}
return NULL;
}
JsonObject* @slon_api_status_lookup_by_in_reply_to_id(U8* id, JsonArray* statuses)
{
if (!id || !statuses) {
return NULL;
}
I64 i;
JsonObject* status;
for (i = 0; i < statuses->length; i++) {
status = statuses->@(i);
if (!status->@("deleted") && status->@("in_reply_to_id") && !StrICmp(status->@("in_reply_to_id"), id)) {
return status;
}
}
return NULL;
}
JsonObject* @slon_api_status_lookup_by_uri(U8* uri, JsonArray* statuses)
{
if (!uri || !statuses) {
return NULL;
}
I64 i;
JsonObject* status;
for (i = 0; i < statuses->length; i++) {
status = statuses->@(i);
if (!status->@("deleted") && status->@("uri") && !StrICmp(status->@("uri"), uri)) {
return status;
}
}
return NULL;
}
JsonObject* @slon_api_find_status_by_id(U8* id, U8* account_id = NULL)
{
if (account_id) {
return @slon_api_status_lookup_by_id(id, db->o("statuses")->a(account_id));
}
JsonObject* status = NULL;
JsonKey* key = db->o("statuses")->keys;
while (key) {
status = @slon_api_status_lookup_by_id(id, key->value);
if (status) {
return status;
}
key = key->next;
}
return NULL;
}
JsonObject* @slon_api_find_status_by_uri(U8* uri, U8* account_id = NULL)
{
if (account_id) {
return @slon_api_status_lookup_by_uri(uri, db->o("statuses")->a(account_id));
}
JsonObject* status = NULL;
JsonKey* key = db->o("statuses")->keys;
while (key) {
status = @slon_api_status_lookup_by_uri(uri, key->value);
if (status) {
return status;
}
key = key->next;
}
return NULL;
}
U0 @slon_api_create_status(JsonObject* status, U8* account_id, U8* to_ap_user = NULL)
{
if (!status || !account_id) {
return;
}
if (!db->o("statuses")->a(account_id)) {
db->o("statuses")->set(account_id, Json.CreateArray(slon_mem_task), JSON_ARRAY);
}
db->o("statuses")->a(account_id)->append(status);
@slon_db_save_status_to_disk(status);
@slon_db_instance_increment_status_count;
@slon_db_save_instance_to_disk;
JsonObject* status_item = Json.CreateObject(slon_mem_task);
status_item->set("account_id", account_id, JSON_STRING);
status_item->set("status_id", status->@("id"), JSON_STRING);
// If account_id is a local account, publish to public timeline
JsonObject* acct = @slon_api_account_by_id(account_id);
if (!acct->@("remote_actor") && !StrICmp("public", status->@("visibility"))) {
if (!db->o("timelines")->a("public")) {
db->o("timelines")->set("public", Json.CreateArray(slon_mem_task), JSON_ARRAY);
}
db->o("timelines")->a("public")->append(status_item);
}
// If account_id is a remote account, and we have an ActivityPub user, post to their timeline
if (acct->@("remote_actor") && to_ap_user) {
JsonObject* acct_for_ap_user = @slon_api_account_by_username(to_ap_user);
if (acct_for_ap_user) {
if (!db->o("timelines")->o("home")->a(acct_for_ap_user->@("id"))) {
db->o("timelines")->o("home")->set(acct_for_ap_user->@("id"), Json.CreateArray(slon_mem_task), JSON_ARRAY);
}
db->o("timelines")->o("home")->a(acct_for_ap_user->@("id"))->append(status_item);
}
}
@slon_db_save_timelines_to_disk;
}
Bool @slon_api_status_is_bookmarked(SlonHttpSession* session, JsonObject* status, U8* account_id) Bool @slon_api_status_is_bookmarked(SlonHttpSession* session, JsonObject* status, U8* account_id)
{ {
no_warn session; no_warn session;
@ -183,7 +303,7 @@ U0 @slon_api_bookmark_status(SlonHttpSession* session, JsonObject* status, U8* a
} }
} }
if (!is_already_bookmarked) { if (!is_already_bookmarked) {
bookmark = Json.CreateObject(session->mem_task); bookmark = Json.CreateObject(slon_db_mem_task);
bookmark->set("status_id", status->@("id"), JSON_STRING); bookmark->set("status_id", status->@("id"), JSON_STRING);
bookmark->set("account_id", status->o("account")->@("id"), JSON_STRING); bookmark->set("account_id", status->o("account")->@("id"), JSON_STRING);
bookmarks->append(bookmark); bookmarks->append(bookmark);
@ -229,6 +349,24 @@ Bool @slon_api_status_is_favourited(SlonHttpSession* session, JsonObject* status
return FALSE; return FALSE;
} }
Bool @slon_api_status_is_reblogged(SlonHttpSession* session, JsonObject* status, U8* account_id)
{
no_warn session;
JsonArray* reblogs = db->o("reblogs")->a(account_id);
JsonObject* reblog = NULL;
if (!reblogs) {
return FALSE;
}
I64 i;
for (i = 0; i < reblogs->length; i++) {
reblog = reblogs->o(i);
if (!StrICmp(reblog->@("boost_id"), status->@("id")) || !StrICmp(reblog->@("status_id"), status->@("id"))) {
return TRUE;
}
}
return FALSE;
}
U0 @slon_api_favourite_status(SlonHttpSession* session, JsonObject* status, U8* account_id) U0 @slon_api_favourite_status(SlonHttpSession* session, JsonObject* status, U8* account_id)
{ {
Bool is_already_favourited = FALSE; Bool is_already_favourited = FALSE;
@ -247,7 +385,7 @@ U0 @slon_api_favourite_status(SlonHttpSession* session, JsonObject* status, U8*
} }
} }
if (!is_already_favourited) { if (!is_already_favourited) {
favourite = Json.CreateObject(session->mem_task); favourite = Json.CreateObject(slon_db_mem_task);
favourite->set("status_id", status->@("id"), JSON_STRING); favourite->set("status_id", status->@("id"), JSON_STRING);
favourite->set("account_id", status->o("account")->@("id"), JSON_STRING); favourite->set("account_id", status->o("account")->@("id"), JSON_STRING);
favourites->append(favourite); favourites->append(favourite);
@ -275,6 +413,97 @@ U0 @slon_api_unfavourite_status(SlonHttpSession* session, JsonObject* status, U8
} }
} }
JsonObject* @slon_api_reblog_status(SlonHttpSession* session, JsonObject* status, U8* account_id)
{
Bool is_already_reblogged = FALSE;
JsonArray* reblogs = db->o("reblogs")->a(account_id);
JsonObject* reblog = NULL;
if (!reblogs) {
reblogs = Json.CreateArray(slon_db_mem_task);
db->o("reblogs")->set(account_id, reblogs, JSON_ARRAY);
@slon_db_save_reblogs_to_disk;
}
I64 i;
for (i = 0; i < reblogs->length; i++) {
reblog = reblogs->o(i);
if (!StrICmp(reblog->@("status_id"), status->@("id")) && !StrICmp(reblog->@("account_id"), status->o("account")->@("id"))) {
return @slon_api_find_status_by_id(reblog->@("boost_id"), account_id);
}
}
// Create boost object, which is our reblog status with the original status attached as a "reblog" object
JsonObject* boost = Json.CreateObject(slon_db_mem_task);
U8* boost_id = @slon_api_generate_unique_id(session);
U8* boost_created_at = @slon_api_timestamp_from_cdate(session, Now);
boost->set("id", boost_id, JSON_STRING);
boost->set("in_reply_to_id", NULL, JSON_NULL);
boost->set("in_reply_to_account_id", NULL, JSON_NULL);
boost->set("content", "", JSON_STRING);
boost->set("created_at", boost_created_at, JSON_STRING);
boost->set("visibility", "public", JSON_STRING);
boost->set("uri", status->@("uri"), JSON_STRING);
boost->set("url", status->@("url"), JSON_STRING);
boost->set("account", @slon_api_account_by_id(account_id), JSON_OBJECT);
boost->set("reblogs_count", 0, JSON_NUMBER);
boost->set("favourites_count", 0, JSON_NUMBER);
boost->set("emojis", SLON_EMPTY_JSON_ARRAY, JSON_ARRAY);
boost->set("tags", SLON_EMPTY_JSON_ARRAY, JSON_ARRAY);
boost->set("mentions", SLON_EMPTY_JSON_ARRAY, JSON_ARRAY);
boost->set("media_attachments", SLON_EMPTY_JSON_ARRAY, JSON_ARRAY);
boost->set("replies_count", 0, JSON_NUMBER);
boost->set("spoiler_text", "", JSON_STRING);
boost->set("sensitive", status->@("sensitive"), JSON_BOOLEAN);
boost->set("reblog", status, JSON_OBJECT);
@slon_api_create_status(boost, account_id);
// Create a reblog object which is a lookup to status_id, account_id, boost_id
reblog = Json.CreateObject(slon_db_mem_task);
reblog->set("status_id", status->@("id"), JSON_STRING);
reblog->set("account_id", status->o("account")->@("id"), JSON_STRING);
reblog->set("boost_id", boost->@("id"), JSON_STRING);
reblogs->append(reblog);
@slon_db_save_reblogs_to_disk;
status->set("reblogs_count", status->@("reblogs_count") + 1, JSON_NUMBER);
@slon_db_save_status_to_disk(status);
@slon_free(session, boost_created_at);
@slon_free(session, boost_id);
return boost;
}
U0 @slon_api_unreblog_status(SlonHttpSession* session, JsonObject* status, U8* account_id)
{
no_warn session;
JsonArray* reblogs = db->o("reblogs")->a(account_id);
JsonObject* reblog = NULL;
JsonObject* boost = NULL;
if (!reblogs) {
reblogs = Json.CreateArray(slon_db_mem_task);
db->o("reblogs")->set(account_id, reblogs, JSON_ARRAY);
@slon_db_save_reblogs_to_disk;
}
I64 i;
for (i = 0; i < reblogs->length; i++) {
reblog = reblogs->o(i);
if (!StrICmp(reblog->@("status_id"), status->@("id")) && !StrICmp(reblog->@("account_id"), status->o("account")->@("id"))) {
reblogs->remove(i);
@slon_db_save_reblogs_to_disk;
status->set("reblogs_count", status->@("reblogs_count") - 1, JSON_NUMBER);
@slon_db_save_status_to_disk(status);
boost = @slon_api_find_status_by_id(reblog->@("boost_id"), account_id);
if (boost) {
boost->set("deleted", TRUE, JSON_BOOLEAN);
@slon_db_save_status_to_disk(status);
}
break;
}
}
}
U0 @slon_api_async_upload_to_catbox(SlonCatboxUpload* cb) U0 @slon_api_async_upload_to_catbox(SlonCatboxUpload* cb)
{ {
if (!cb) { if (!cb) {
@ -445,126 +674,6 @@ U0 @slon_api_async_delete_from_catbox(U8* filename)
Free(filename); Free(filename);
} }
JsonObject* @slon_api_status_lookup_by_id(U8* id, JsonArray* statuses)
{
if (!id || !statuses) {
return NULL;
}
I64 i;
JsonObject* status;
for (i = 0; i < statuses->length; i++) {
status = statuses->@(i);
if (!status->@("deleted") && status->@("id") && !StrICmp(status->@("id"), id)) {
return status;
}
}
return NULL;
}
JsonObject* @slon_api_status_lookup_by_in_reply_to_id(U8* id, JsonArray* statuses)
{
if (!id || !statuses) {
return NULL;
}
I64 i;
JsonObject* status;
for (i = 0; i < statuses->length; i++) {
status = statuses->@(i);
if (!status->@("deleted") && status->@("in_reply_to_id") && !StrICmp(status->@("in_reply_to_id"), id)) {
return status;
}
}
return NULL;
}
JsonObject* @slon_api_status_lookup_by_uri(U8* uri, JsonArray* statuses)
{
if (!uri || !statuses) {
return NULL;
}
I64 i;
JsonObject* status;
for (i = 0; i < statuses->length; i++) {
status = statuses->@(i);
if (!status->@("deleted") && status->@("uri") && !StrICmp(status->@("uri"), uri)) {
return status;
}
}
return NULL;
}
JsonObject* @slon_api_find_status_by_id(U8* id, U8* account_id = NULL)
{
if (account_id) {
return @slon_api_status_lookup_by_id(id, db->o("statuses")->a(account_id));
}
JsonObject* status = NULL;
JsonKey* key = db->o("statuses")->keys;
while (key) {
status = @slon_api_status_lookup_by_id(id, key->value);
if (status) {
return status;
}
key = key->next;
}
return NULL;
}
JsonObject* @slon_api_find_status_by_uri(U8* uri, U8* account_id = NULL)
{
if (account_id) {
return @slon_api_status_lookup_by_uri(uri, db->o("statuses")->a(account_id));
}
JsonObject* status = NULL;
JsonKey* key = db->o("statuses")->keys;
while (key) {
status = @slon_api_status_lookup_by_uri(uri, key->value);
if (status) {
return status;
}
key = key->next;
}
return NULL;
}
U0 @slon_api_create_status(JsonObject* status, U8* account_id, U8* to_ap_user = NULL)
{
if (!status || !account_id) {
return;
}
if (!db->o("statuses")->a(account_id)) {
db->o("statuses")->set(account_id, Json.CreateArray(slon_mem_task), JSON_ARRAY);
}
db->o("statuses")->a(account_id)->append(status);
@slon_db_save_status_to_disk(status);
@slon_db_instance_increment_status_count;
@slon_db_save_instance_to_disk;
JsonObject* status_item = Json.CreateObject(slon_mem_task);
status_item->set("account_id", account_id, JSON_STRING);
status_item->set("status_id", status->@("id"), JSON_STRING);
// If account_id is a local account, publish to public timeline
JsonObject* acct = @slon_api_account_by_id(account_id);
if (!acct->@("remote_actor") && !StrICmp("public", status->@("visibility"))) {
if (!db->o("timelines")->a("public")) {
db->o("timelines")->set("public", Json.CreateArray(slon_mem_task), JSON_ARRAY);
}
db->o("timelines")->a("public")->append(status_item);
}
// If account_id is a remote account, and we have an ActivityPub user, post to their timeline
if (acct->@("remote_actor") && to_ap_user) {
JsonObject* acct_for_ap_user = @slon_api_account_by_username(to_ap_user);
if (acct_for_ap_user) {
if (!db->o("timelines")->o("home")->a(acct_for_ap_user->@("id"))) {
db->o("timelines")->o("home")->set(acct_for_ap_user->@("id"), Json.CreateArray(slon_mem_task), JSON_ARRAY);
}
db->o("timelines")->o("home")->a(acct_for_ap_user->@("id"))->append(status_item);
}
}
@slon_db_save_timelines_to_disk;
}
JsonObject* @slon_api_get_timeline_item(JsonObject* timeline_item) JsonObject* @slon_api_get_timeline_item(JsonObject* timeline_item)
{ {
if (!timeline_item) { if (!timeline_item) {

View file

@ -126,6 +126,26 @@ U0 @slon_db_load_favourites_from_disk()
db->set("favourites", favourites, JSON_OBJECT); db->set("favourites", favourites, JSON_OBJECT);
} }
U0 @slon_db_load_reblogs_from_disk()
{
JsonObject* reblogs = Json.CreateObject(slon_db_mem_task);
U8 scratch_buffer[256];
StrPrint(scratch_buffer, "%s/reblogs/*.json", SLON_DB_PATH);
CDirEntry* files = FilesFind(scratch_buffer);
CDirEntry* de = files;
JsonArray* reblog_array = NULL;
while (de) {
reblog_array = Json.ParseFile(de->full_name, slon_db_mem_task);
if (reblog_array) {
StrFind(".json", de->name)[0] = NULL;
reblogs->set(de->name, reblog_array, JSON_ARRAY);
}
de = de->next;
}
DirTreeDel(files);
db->set("reblogs", reblogs, JSON_OBJECT);
}
U0 @slon_db_load_followers_from_disk() U0 @slon_db_load_followers_from_disk()
{ {
JsonObject* followers = Json.CreateObject(slon_db_mem_task); JsonObject* followers = Json.CreateObject(slon_db_mem_task);
@ -341,6 +361,17 @@ U0 @slon_db_save_favourites_to_disk()
} }
} }
U0 @slon_db_save_reblogs_to_disk()
{
U8 scratch_buffer[256];
JsonKey* key = db->o("reblogs")->keys;
while (key) {
StrPrint(scratch_buffer, "%s/reblogs/%s.json", SLON_DB_PATH, key->name);
Json.DumpToFile(scratch_buffer, key->value, slon_db_mem_task);
key = key->next;
}
}
U0 @slon_db_save_followers_to_disk() U0 @slon_db_save_followers_to_disk()
{ {
U8 scratch_buffer[256]; U8 scratch_buffer[256];
@ -429,6 +460,7 @@ U0 @slon_db_save_to_disk()
@slon_db_save_markers_to_disk(); @slon_db_save_markers_to_disk();
@slon_db_save_oauth_to_disk(); @slon_db_save_oauth_to_disk();
@slon_db_save_private_keys_to_disk(); @slon_db_save_private_keys_to_disk();
@slon_db_save_reblogs_to_disk();
@slon_db_save_settings_to_disk(); @slon_db_save_settings_to_disk();
@slon_db_save_statuses_to_disk(); @slon_db_save_statuses_to_disk();
@slon_db_save_timelines_to_disk(); @slon_db_save_timelines_to_disk();
@ -452,6 +484,7 @@ U0 @slon_db_load_from_defaults()
db->set("instance", Json.ParseFile("M:/Slon/Static/defaults/instance.json", slon_db_mem_task), JSON_OBJECT); db->set("instance", Json.ParseFile("M:/Slon/Static/defaults/instance.json", slon_db_mem_task), JSON_OBJECT);
db->set("markers", Json.CreateObject(slon_db_mem_task), JSON_OBJECT); db->set("markers", Json.CreateObject(slon_db_mem_task), JSON_OBJECT);
db->set("media", Json.CreateObject(slon_db_mem_task), JSON_OBJECT); db->set("media", Json.CreateObject(slon_db_mem_task), JSON_OBJECT);
db->set("reblogs", Json.CreateObject(slon_db_mem_task), JSON_OBJECT);
db->set("settings", Json.CreateObject(slon_db_mem_task), JSON_OBJECT); db->set("settings", Json.CreateObject(slon_db_mem_task), JSON_OBJECT);
db->set("statuses", Json.CreateObject(slon_db_mem_task), JSON_OBJECT); db->set("statuses", Json.CreateObject(slon_db_mem_task), JSON_OBJECT);
db->set("timelines", Json.CreateObject(slon_db_mem_task), JSON_OBJECT); db->set("timelines", Json.CreateObject(slon_db_mem_task), JSON_OBJECT);
@ -485,6 +518,7 @@ U0 @slon_db_load_from_disk()
@slon_db_load_markers_from_disk(); @slon_db_load_markers_from_disk();
db->set("media", Json.CreateObject(slon_db_mem_task), JSON_OBJECT); db->set("media", Json.CreateObject(slon_db_mem_task), JSON_OBJECT);
@slon_db_load_oauth_from_disk(); @slon_db_load_oauth_from_disk();
@slon_db_load_reblogs_from_disk();
@slon_db_load_settings_from_disk(); @slon_db_load_settings_from_disk();
@slon_db_load_statuses_from_disk(); @slon_db_load_statuses_from_disk();
@slon_db_load_timelines_from_disk(); @slon_db_load_timelines_from_disk();