Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/ewanc26/wolfram. Pure C11 AT Protocol SDK: client-side, wire-level implementation (XRPC, OAuth/DPoP
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575/* * cli_feed.c — the `feed` / `get-likes` / `get-reposted-by` / `get-quotes` / * `get-actor-likes` / `get-actor-feeds` / `describe-feed` / * `get-suggested-feeds` / `get-suggestions` / `known-followers` / * `relationships` / `get-profiles` / `unread-count` subcommands, split out * of main.c as their own self-contained concern. */
#include "cli_feed.h"#include "main_internal.h"
#include "wolfram/agent.h"#include "wolfram/feed_typed.h"#include "wolfram/feedgen_typed.h"#include "wolfram/unspecced_typed.h"#include "wolfram/graph_social_typed.h"#include "wolfram/notification_typed.h"#include "wolfram/actor_status_typed.h"#include "wolfram/ageassurance_typed.h"
#include <cJSON.h>#include <stdbool.h>#include <stdio.h>#include <stdlib.h>#include <string.h>
int cmd_feed(int argc, char **argv) { if (argc < 2) { usage_stream(stderr); return 0; } const char *sub = argv[1];
/* wolfram feed get <service> <handle> <password> --feed <generator-uri> * [--limit N] [--cursor C] */ if (strcmp(sub, "get") == 0) { const char *feed = NULL, *cursor = NULL; int limit = 50; const char *pos[3]; int pi = 0; for (int i = 2; i < argc; ++i) { if (strcmp(argv[i], "--feed") == 0 && i + 1 < argc) feed = argv[++i]; else if (strcmp(argv[i], "--limit") == 0 && i + 1 < argc) limit = atoi(argv[++i]); else if (strcmp(argv[i], "--cursor") == 0 && i + 1 < argc) cursor = argv[++i]; else if (pi < 3) pos[pi++] = argv[i]; } if (pi < 3 || !feed) { fprintf( stderr, "error: usage: wolfram feed get <service> <handle> " "<password> --feed <generator-uri> [--limit N] [--cursor C]\n"); return 1; } wf_agent *agent = agent_login_or_err(pos[0], pos[1], pos[2]); if (!agent) return 1; if (g_json) { wf_response res = {0}; wf_status s = wf_agent_get_feed(agent, feed, limit, cursor, &res); return finish_agent_response(agent, s, &res); } wf_agent_feed_view_list list = {0}; wf_status s = wf_agent_get_feed_typed(agent, feed, limit, cursor, &list); if (s != WF_OK) { fprintf(stderr, "error: getFeed failed (status %d)\n", (int)s); wf_agent_feed_view_list_free(&list); wf_agent_free(agent); return 1; } for (size_t i = 0; i < list.item_count; ++i) { const wf_agent_post_view *post = &list.items[i].post; const char *author = post->author.handle ? post->author.handle : (post->author.did ? post->author.did : "?"); const char *text = ""; if (post->record) { cJSON *t = cJSON_GetObjectItemCaseSensitive(post->record, "text"); if (cJSON_IsString(t) && t->valuestring) text = t->valuestring; } printf("%s: %s\n", author, text); } if (list.cursor) printf("cursor: %s\n", list.cursor); if (list.item_count == 0) printf("(empty feed)\n"); wf_agent_feed_view_list_free(&list); wf_agent_free(agent); return 0; }
/* wolfram feed author <service> <handle> <password> --actor <handle-or-did> * [--limit N] [--cursor C] */ if (strcmp(sub, "author") == 0) { const char *actor = NULL, *cursor = NULL; int limit = 50; const char *pos[3]; int pi = 0; for (int i = 2; i < argc; ++i) { if (strcmp(argv[i], "--actor") == 0 && i + 1 < argc) actor = argv[++i]; else if (strcmp(argv[i], "--limit") == 0 && i + 1 < argc) limit = atoi(argv[++i]); else if (strcmp(argv[i], "--cursor") == 0 && i + 1 < argc) cursor = argv[++i]; else if (pi < 3) pos[pi++] = argv[i]; } if (pi < 3 || !actor) { fprintf(stderr, "error: usage: wolfram feed author <service> <handle> " "<password> --actor <handle-or-did> [--limit N] [--cursor " "C]\n"); return 1; } wf_agent *agent = agent_login_or_err(pos[0], pos[1], pos[2]); if (!agent) return 1; if (g_json) { wf_response res = {0}; wf_status s = wf_agent_get_author_feed(agent, actor, limit, cursor, NULL, false, &res); return finish_agent_response(agent, s, &res); } wf_agent_feed_list list = {0}; wf_status s = wf_agent_get_author_feed_typed(agent, actor, limit, cursor, NULL, &list); if (s != WF_OK) { fprintf(stderr, "error: getAuthorFeed failed (status %d)\n", (int)s); wf_agent_feed_list_free(&list); wf_agent_free(agent); return 1; } for (size_t i = 0; i < list.item_count; ++i) { const wf_agent_post_view *post = &list.items[i].post; const char *author = post->author.handle ? post->author.handle : (post->author.did ? post->author.did : "?"); const char *text = ""; if (post->record) { cJSON *t = cJSON_GetObjectItemCaseSensitive(post->record, "text"); if (cJSON_IsString(t) && t->valuestring) text = t->valuestring; } printf("%s: %s\n", author, text); } if (list.cursor) printf("cursor: %s\n", list.cursor); if (list.item_count == 0) printf("(empty feed)\n"); wf_agent_feed_list_free(&list); wf_agent_free(agent); return 0; }
fprintf(stderr, "error: unknown feed subcommand '%s' (try get/author)\n", sub); return 1;}
/* wolfram get-likes <service> <handle> <password> <at-uri> [limit] */int cmd_get_likes(int argc, char **argv) { if (argc < 5) { usage_stream(stderr); return 0; } const char *service = argv[1]; const char *handle = argv[2]; const char *password = argv[3]; const char *at_uri = argv[4]; int limit = (argc >= 6) ? atoi(argv[5]) : 50;
wf_agent *agent = agent_login_or_err(service, handle, password); if (!agent) return 1;
wf_response res = {0}; wf_status s = wf_agent_get_likes(agent, at_uri, limit, NULL, &res); return finish_agent_response(agent, s, &res);}
/* wolfram get-reposted-by <service> <handle> <password> <at-uri> [limit] */int cmd_get_reposted_by(int argc, char **argv) { if (argc < 5) { usage_stream(stderr); return 0; } const char *service = argv[1]; const char *handle = argv[2]; const char *password = argv[3]; const char *at_uri = argv[4]; int limit = (argc >= 6) ? atoi(argv[5]) : 50;
wf_agent *agent = agent_login_or_err(service, handle, password); if (!agent) return 1;
wf_response res = {0}; wf_status s = wf_agent_get_reposted_by(agent, at_uri, limit, NULL, &res); return finish_agent_response(agent, s, &res);}
/* wolfram get-quotes <service> <handle> <password> <at-uri> [limit] */int cmd_get_quotes(int argc, char **argv) { if (argc < 5) { usage_stream(stderr); return 0; } const char *service = argv[1]; const char *handle = argv[2]; const char *password = argv[3]; const char *at_uri = argv[4]; int limit = (argc >= 6) ? atoi(argv[5]) : 50;
wf_agent *agent = agent_login_or_err(service, handle, password); if (!agent) return 1;
wf_response res = {0}; wf_status s = wf_agent_get_quotes(agent, at_uri, limit, NULL, &res); return finish_agent_response(agent, s, &res);}
/* wolfram get-actor-likes <service> <actor> [limit] */int cmd_get_actor_likes(int argc, char **argv) { if (argc < 3) { usage_stream(stderr); return 0; } const char *service = argv[1]; const char *actor = argv[2]; int limit = (argc >= 4) ? atoi(argv[3]) : 50;
wf_agent *agent = wf_agent_new(service); if (!agent) { fprintf(stderr, "error: failed to create agent\n"); return 1; }
wf_response res = {0}; wf_status s = wf_agent_get_actor_likes(agent, actor, limit, NULL, &res); return finish_agent_response(agent, s, &res);}
/* wolfram get-actor-feeds <service> <actor> [limit] */int cmd_get_actor_feeds(int argc, char **argv) { if (argc < 3) { usage_stream(stderr); return 0; } const char *service = argv[1]; const char *actor = argv[2]; int limit = (argc >= 4) ? atoi(argv[3]) : 50;
wf_agent *agent = wf_agent_new(service); if (!agent) { fprintf(stderr, "error: failed to create agent\n"); return 1; }
wf_response res = {0}; wf_status s = wf_agent_get_actor_feeds(agent, actor, limit, NULL, &res); return finish_agent_response(agent, s, &res);}
/* wolfram describe-feed <service> <handle> <password> [--feed <generator-uri>] */int cmd_describe_feed(int argc, char **argv) { const char *feed = NULL; const char *pos[3]; int pi = 0; for (int i = 1; i < argc; ++i) { if (strcmp(argv[i], "--feed") == 0 && i + 1 < argc) feed = argv[++i]; else if (pi < 3) pos[pi++] = argv[i]; } if (pi < 3) { usage_stream(stderr); return 0; }
wf_agent *agent = agent_login_or_err(pos[0], pos[1], pos[2]); if (!agent) return 1;
if (feed) { wf_response res = {0}; wf_status s = wf_agent_get_feed_generator(agent, feed, &res); return finish_agent_response(agent, s, &res); }
wf_response res = {0}; wf_status s = wf_agent_describe_feed_generator(agent, &res); return finish_agent_response(agent, s, &res);}
/* wolfram get-suggested-feeds <service> <handle> <password> */int cmd_get_suggested_feeds(int argc, char **argv) { if (argc < 4) { usage_stream(stderr); return 0; } wf_agent *agent = agent_login_or_err(argv[1], argv[2], argv[3]); if (!agent) return 1;
wf_response res = {0}; wf_status s = wf_agent_get_suggested_feeds(agent, &res); return finish_agent_response(agent, s, &res);}
/* wolfram get-suggestions <service> <handle> <password> [limit] */int cmd_get_suggestions(int argc, char **argv) { if (argc < 4) { usage_stream(stderr); return 0; } int limit = (argc >= 5) ? atoi(argv[4]) : 50;
wf_agent *agent = agent_login_or_err(argv[1], argv[2], argv[3]); if (!agent) return 1;
wf_response res = {0}; wf_status s = wf_agent_get_suggestions(agent, limit, NULL, &res); return finish_agent_response(agent, s, &res);}
/* wolfram known-followers <service> <actor> [limit] */int cmd_known_followers(int argc, char **argv) { if (argc < 3) { usage_stream(stderr); return 0; } const char *service = argv[1]; const char *actor = argv[2]; int limit = (argc >= 4) ? atoi(argv[3]) : 50;
wf_agent *agent = wf_agent_new(service); if (!agent) { fprintf(stderr, "error: failed to create agent\n"); return 1; }
wf_response res = {0}; wf_status s = wf_agent_get_known_followers(agent, actor, limit, NULL, &res); return finish_agent_response(agent, s, &res);}
/* wolfram relationships <service> <actor> <other-did>... */int cmd_relationships(int argc, char **argv) { if (argc < 4) { usage_stream(stderr); return 0; } const char *service = argv[1]; const char *actor = argv[2]; /* argv[3..] are the other DIDs */ int n_others = argc - 3; const char **others = (const char **)(argv + 3);
wf_agent *agent = wf_agent_new(service); if (!agent) { fprintf(stderr, "error: failed to create agent\n"); return 1; }
wf_response res = {0}; wf_status s = wf_agent_get_relationships(agent, actor, others, n_others, &res); return finish_agent_response(agent, s, &res);}
/* wolfram get-profiles <service> <actor>... */int cmd_get_profiles(int argc, char **argv) { if (argc < 3) { usage_stream(stderr); return 0; } const char *service = argv[1]; int n_actors = argc - 2; const char **actors = (const char **)(argv + 2);
wf_agent *agent = wf_agent_new(service); if (!agent) { fprintf(stderr, "error: failed to create agent\n"); return 1; }
wf_response res = {0}; wf_status s = wf_agent_get_profiles(agent, actors, n_actors, 0, NULL, &res); return finish_agent_response(agent, s, &res);}
/* wolfram unread-count <service> <handle> <password> */int cmd_unread_count(int argc, char **argv) { if (argc < 4) { usage_stream(stderr); return 0; } wf_agent *agent = agent_login_or_err(argv[1], argv[2], argv[3]); if (!agent) return 1;
int count = 0; wf_status s = wf_agent_get_unread_count_typed(agent, &count); if (s != WF_OK) { fprintf(stderr, "error: getUnreadCount failed (status %d)\n", (int)s); wf_agent_free(agent); return 1; } printf("%d\n", count); wf_agent_free(agent); return 0;}
/* wolfram get-actor-status <service> <actor> */int cmd_get_actor_status(int argc, char **argv) { if (argc < 3) { usage_stream(stderr); return 0; } const char *service = argv[1]; const char *actor = argv[2];
wf_agent *agent = wf_agent_new(service); if (!agent) { fprintf(stderr, "error: failed to create agent\n"); return 1; }
wf_actor_status_view status = {0}; wf_status s = wf_agent_get_actor_status(agent, actor, &status); if (s != WF_OK) { fprintf(stderr, "error: getActorStatus failed (status %d)\n", (int)s); wf_agent_free(agent); return 1; }
printf("actor: %s\n", actor); printf("status: %s\n", status.status ? status.status : "(none)"); printf("createdAt: %s\n", status.created_at ? status.created_at : "(none)"); if (status.has_duration_minutes) printf("durationMinutes: %lld\n", (long long)status.duration_minutes); printf("isActive: %d\n", status.has_is_active ? status.is_active : 0); printf("isDisabled: %d\n", status.has_is_disabled ? status.is_disabled : 0); printf("expiresAt: %s\n", status.expires_at ? status.expires_at : "(none)"); printf("uri: %s\n", status.uri ? status.uri : "(none)"); printf("cid: %s\n", status.cid ? status.cid : "(none)");
wf_actor_status_view_free(&status); wf_agent_free(agent); return 0;}
/* wolfram get-feed-generators <service> <feed-uri>... */int cmd_get_feed_generators(int argc, char **argv) { if (argc < 3) { usage_stream(stderr); return 0; } const char *service = argv[1]; int n_feeds = argc - 2; const char **feeds = (const char **)(argv + 2);
wf_agent *agent = wf_agent_new(service); if (!agent) { fprintf(stderr, "error: failed to create agent\n"); return 1; }
wf_response res = {0}; wf_status s = wf_agent_get_feed_generators(agent, feeds, n_feeds, &res); return finish_agent_response(agent, s, &res);}
/* wolfram get-suggested-follows-by-actor <service> <actor> */int cmd_get_suggested_follows_by_actor(int argc, char **argv) { if (argc < 3) { usage_stream(stderr); return 0; } const char *service = argv[1]; const char *actor = argv[2];
wf_agent *agent = wf_agent_new(service); if (!agent) { fprintf(stderr, "error: failed to create agent\n"); return 1; }
wf_response res = {0}; wf_status s = wf_agent_get_suggested_follows_by_actor(agent, actor, &res); return finish_agent_response(agent, s, &res);}
/* wolfram age-assurance <service> <handle> <password> * <begin|get-config|get-state> */int cmd_age_assurance(int argc, char **argv) { if (argc < 5) { usage_stream(stderr); return 0; } const char *service = argv[1]; const char *handle = argv[2]; const char *password = argv[3]; const char *sub = argv[4];
wf_agent *agent = agent_login_or_err(service, handle, password); if (!agent) { return 1; }
if (strcmp(sub, "begin") == 0) { wf_ageassurance_begin out = {0}; wf_status s = wf_agent_begin_ageassurance(agent, &out); if (s != WF_OK) { fprintf(stderr, "error: ageAssurance.begin failed (status %d)\n", (int)s); wf_agent_free(agent); return 1; } printf("status: %s\n", out.status ? out.status : "(none)"); printf("access: %s\n", out.access ? out.access : "(none)"); printf("lastInitiatedAt: %s\n", out.last_initiated_at ? out.last_initiated_at : "(none)"); wf_ageassurance_begin_free(&out); } else if (strcmp(sub, "get-config") == 0) { wf_ageassurance_config out = {0}; wf_status s = wf_agent_get_ageassurance_config(agent, &out); if (s != WF_OK) { fprintf(stderr, "error: ageAssurance.getConfig failed (status %d)\n", (int)s); wf_agent_free(agent); return 1; } printf("required: %s\n", out.regions && cJSON_IsTrue(out.regions) ? "true" : "false"); if (out.regions && cJSON_IsArray(out.regions)) { int n = cJSON_GetArraySize(out.regions); printf("regions (%d):\n", n); for (int i = 0; i < n; ++i) { cJSON *r = cJSON_GetArrayItem(out.regions, i); printf(" %s\n", cJSON_IsObject(r) ? "(object)" : "(unknown)"); } } wf_ageassurance_config_free(&out); } else if (strcmp(sub, "get-state") == 0) { wf_ageassurance_state out = {0}; wf_status s = wf_agent_get_ageassurance_state(agent, &out); if (s != WF_OK) { fprintf(stderr, "error: ageAssurance.getState failed (status %d)\n", (int)s); wf_agent_free(agent); return 1; } printf("status: %s\n", out.state.status ? out.state.status : "(none)"); printf("access: %s\n", out.state.access ? out.state.access : "(none)"); printf("lastInitiatedAt: %s\n", out.state.last_initiated_at ? out.state.last_initiated_at : "(none)"); printf("accountCreatedAt: %s\n", out.metadata.account_created_at ? out.metadata.account_created_at : "(none)"); wf_ageassurance_state_free(&out); } else { fprintf(stderr, "error: unknown age-assurance subcommand '%s' (try begin, " "get-config, get-state)\n", sub); wf_agent_free(agent); return 1; }
wf_agent_free(agent); return 0;}