Continuing to chip away at moving ssb.js to C. This time, following.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4096 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
2022-12-31 21:44:48 +00:00
parent a9f6593979
commit 120ed36552
4 changed files with 167 additions and 50 deletions

View File

@ -973,6 +973,129 @@ bool tf_ssb_db_identity_get_private_key(tf_ssb_t* ssb, const char* user, const c
return success;
}
typedef struct _following_t following_t;
typedef struct _following_t
{
char id[k_id_base64_len];
following_t** following;
following_t** blocking;
int following_count;
int blocking_count;
int depth;
} following_t;
static int _following_compare(const void* a, const void* b)
{
const char* ida = a;
const following_t* const* followingb = b;
return strcmp(ida, (*followingb)->id);
}
static void _add_following_entry(following_t*** list, int* count, following_t* add)
{
int index = tf_util_insert_index(add->id, *list, *count, sizeof(following_t*), _following_compare);
if (index >= *count || strcmp(add->id, (*list)[index]->id) == 0)
{
*list = tf_resize_vec(*list, sizeof(**list) * (*count + 1));
if (*count - index)
{
memmove(*list + index + 1, *list + index, sizeof(following_t*) * (*count - index));
}
(*list)[index] = add;
}
}
static following_t* _get_following(tf_ssb_t* ssb, const char* id, following_t*** following, int* following_count, int depth, int max_depth)
{
int index = tf_util_insert_index(id, *following, *following_count, sizeof(following_t*), _following_compare);
following_t* entry = NULL;
if (index < *following_count && strcmp(id, (*following)[index]->id) == 0)
{
entry = (*following)[index];
}
else
{
*following = tf_resize_vec(*following, sizeof(*following) * (*following_count + 1));
if (*following_count - index)
{
memmove(*following + index + 1, *following + index, sizeof(following_t*) * (*following_count - index));
}
entry = tf_malloc(sizeof(following_t));
(*following)[index] = entry;
(*following_count)++;
*entry = (following_t) { 0 };
snprintf(entry->id, sizeof(entry->id), "%s", id);
entry->depth = depth;
if (depth < max_depth)
{
sqlite3* db = tf_ssb_get_db(ssb);
sqlite3_stmt* statement = NULL;
if (sqlite3_prepare(db, "SELECT json_extract(content, '$.contact'), json_extract(content, '$.following'), json_extract(content, '$.blocking') FROM messages WHERE author = ? AND json_extract(content, '$.type') = 'contact' ORDER BY sequence", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
const char* contact = (const char*)sqlite3_column_text(statement, 0);
if (sqlite3_column_type(statement, 1) != SQLITE_NULL)
{
bool is_following = sqlite3_column_int(statement, 1);
following_t* next = _get_following(ssb, contact, following, following_count, depth + 1, max_depth);
if (is_following)
{
_add_following_entry(&entry->following, &entry->following_count, next);
}
}
if (sqlite3_column_type(statement, 2) != SQLITE_NULL)
{
bool is_blocking = sqlite3_column_int(statement, 2);
following_t* next = _get_following(ssb, contact, following, following_count, depth + 1, 0 /* don't dig deeper into blocked users */);
if (is_blocking)
{
_add_following_entry(&entry->blocking, &entry->blocking_count, next);
}
}
}
}
sqlite3_finalize(statement);
}
}
}
return entry;
}
const char** tf_ssb_db_following_deep(tf_ssb_t* ssb, const char** ids, int count, int depth)
{
following_t** following = NULL;
int following_count = 0;
for (int i = 0; i < count; i++)
{
_get_following(ssb, ids[i], &following, &following_count, 0, depth);
}
char** result = tf_malloc(sizeof(char*) * (following_count + 1) + k_id_base64_len * following_count);
char* result_ids = (char*)result + sizeof(char*) * (following_count + 1);
for (int i = 0; i < following_count; i++)
{
result[i] = result_ids + k_id_base64_len * i;
snprintf(result[i], k_id_base64_len, "%s", following[i]->id);
}
result[following_count] = NULL;
for (int i = 0; i < following_count; i++)
{
tf_free(following[i]->following);
tf_free(following[i]->blocking);
tf_free(following[i]);
}
tf_free(following);
return (const char**)result;
}
static void _test_private(sqlite3* db, const uint8_t* private_key)
{
sqlite3_stmt* statement = NULL;