forked from cory/tildefriends
		
	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:
		
							
								
								
									
										123
									
								
								src/ssb.db.c
									
									
									
									
									
								
							
							
						
						
									
										123
									
								
								src/ssb.db.c
									
									
									
									
									
								
							| @@ -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; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user