forked from cory/tildefriends
ssb: Add a get_contacts command to enumerate follows, blocks, and friends.
This commit is contained in:
99
src/main.c
99
src/main.c
@ -152,6 +152,7 @@ static int _tf_command_store_blob(const char* file, int argc, char* argv[]);
|
||||
static int _tf_command_get_sequence(const char* file, int argc, char* argv[]);
|
||||
static int _tf_command_get_identity(const char* file, int argc, char* argv[]);
|
||||
static int _tf_command_get_profile(const char* file, int argc, char* argv[]);
|
||||
static int _tf_command_get_contacts(const char* file, int argc, char* argv[]);
|
||||
static int _tf_command_test(const char* file, int argc, char* argv[]);
|
||||
static int _tf_command_verify(const char* file, int argc, char* argv[]);
|
||||
static int _tf_command_usage(const char* file);
|
||||
@ -173,6 +174,7 @@ const command_t k_commands[] = {
|
||||
{ "get_sequence", _tf_command_get_sequence, "Get the last sequence number for a feed." },
|
||||
{ "get_identity", _tf_command_get_identity, "Get the server account identity." },
|
||||
{ "get_profile", _tf_command_get_profile, "Get profile information for the given identity." },
|
||||
{ "get_contacts", _tf_command_get_contacts, "Get information about followed, blocked, and friend identities." },
|
||||
{ "has_blob", _tf_command_has_blob, "Check whether a blob is in the blob store." },
|
||||
{ "store_blob", _tf_command_store_blob, "Write a file to the blob store." },
|
||||
{ "verify", _tf_command_verify, "Verify a feed." },
|
||||
@ -944,7 +946,7 @@ static int _tf_command_get_profile(const char* file, int argc, char* argv[])
|
||||
tf_printf("\n%s get_profile [options]\n\n", file);
|
||||
tf_printf("options:\n");
|
||||
tf_printf(" -d, --db-path db_path SQLite database path (default: %s).\n", default_db_path);
|
||||
tf_printf(" -i, --identity identity Account from which to get latest sequence number.\n");
|
||||
tf_printf(" -i, --identity identity Account for which to get profile information.\n");
|
||||
tf_printf(" -h, --help Show this usage information.\n");
|
||||
tf_free((void*)default_db_path);
|
||||
return EXIT_FAILURE;
|
||||
@ -961,6 +963,101 @@ static int _tf_command_get_profile(const char* file, int argc, char* argv[])
|
||||
return profile != NULL;
|
||||
}
|
||||
|
||||
static int _tf_command_get_contacts(const char* file, int argc, char* argv[])
|
||||
{
|
||||
const char* default_db_path = _get_db_path();
|
||||
const char* db_path = default_db_path;
|
||||
const char* identity = NULL;
|
||||
bool show_usage = false;
|
||||
|
||||
while (!show_usage)
|
||||
{
|
||||
static const struct option k_options[] = {
|
||||
{ "db-path", required_argument, NULL, 'd' },
|
||||
{ "id", required_argument, NULL, 'i' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ 0 },
|
||||
};
|
||||
int c = getopt_long(argc, argv, "d:i:h", k_options, NULL);
|
||||
if (c == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '?':
|
||||
case 'h':
|
||||
default:
|
||||
show_usage = true;
|
||||
break;
|
||||
case 'd':
|
||||
db_path = optarg;
|
||||
break;
|
||||
case 'i':
|
||||
identity = optarg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (show_usage || !identity)
|
||||
{
|
||||
tf_printf("\n%s get_contacts [options]\n\n", file);
|
||||
tf_printf("options:\n");
|
||||
tf_printf(" -d, --db-path db_path SQLite database path (default: %s).\n", default_db_path);
|
||||
tf_printf(" -i, --identity identity Account from which to get contact information.\n");
|
||||
tf_printf(" -h, --help Show this usage information.\n");
|
||||
tf_free((void*)default_db_path);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
tf_ssb_t* ssb = tf_ssb_create(NULL, NULL, db_path, NULL);
|
||||
JSContext* context = tf_ssb_get_context(ssb);
|
||||
JSValue contacts = JS_NewObject(context);
|
||||
JSValue follows = JS_NewObject(context);
|
||||
JSValue blocks = JS_NewObject(context);
|
||||
JSValue friends = JS_NewObject(context);
|
||||
tf_ssb_following_t* following = tf_ssb_db_following_deep(ssb, &identity, 1, 1, true);
|
||||
tf_ssb_following_t* following2 = tf_ssb_db_following_deep(ssb, &identity, 1, 2, false);
|
||||
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
||||
for (int i = 0; *following[i].id; i++)
|
||||
{
|
||||
if (following[i].followed_by_count)
|
||||
{
|
||||
const char* name = tf_ssb_db_get_profile_name(db, following[i].id);
|
||||
JS_SetPropertyStr(context, follows, following[i].id, name ? JS_NewString(context, name) : JS_NULL);
|
||||
tf_free((void*)name);
|
||||
}
|
||||
if (following[i].blocked_by_count)
|
||||
{
|
||||
const char* name = tf_ssb_db_get_profile_name(db, following[i].id);
|
||||
JS_SetPropertyStr(context, blocks, following[i].id, name ? JS_NewString(context, name) : JS_NULL);
|
||||
tf_free((void*)name);
|
||||
}
|
||||
}
|
||||
for (int i = 0; *following2[i].id; i++)
|
||||
{
|
||||
const char* name = tf_ssb_db_get_profile_name(db, following2[i].id);
|
||||
JS_SetPropertyStr(context, friends, following2[i].id, name ? JS_NewString(context, name) : JS_NULL);
|
||||
tf_free((void*)name);
|
||||
}
|
||||
tf_ssb_release_db_reader(ssb, db);
|
||||
JS_SetPropertyStr(context, contacts, "follows", follows);
|
||||
JS_SetPropertyStr(context, contacts, "blocks", blocks);
|
||||
JS_SetPropertyStr(context, contacts, "friends", friends);
|
||||
tf_free(following2);
|
||||
tf_free(following);
|
||||
JSValue json = JS_JSONStringify(context, contacts, JS_NULL, JS_NewInt32(context, 2));
|
||||
const char* json_str = JS_ToCString(context, json);
|
||||
tf_printf("%s\n", json_str);
|
||||
JS_FreeCString(context, json_str);
|
||||
JS_FreeValue(context, json);
|
||||
JS_FreeValue(context, contacts);
|
||||
tf_ssb_destroy(ssb);
|
||||
tf_free((void*)default_db_path);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int _tf_command_verify(const char* file, int argc, char* argv[])
|
||||
{
|
||||
const char* identity = NULL;
|
||||
|
Reference in New Issue
Block a user