Slon/Api/V1/Polls: Implement Polls

Fixes #8
This commit is contained in:
Alec Murphy 2025-03-16 19:21:44 -04:00
parent 9a2a68ef93
commit 966be78422
8 changed files with 347 additions and 0 deletions

View file

@ -950,6 +950,14 @@ U0 @slon_activitypub_users_inbox(SlonHttpSession* session, U8* user)
JsonArray* statuses = NULL;
JsonObject* status = NULL;
JsonObject* poll = NULL;
JsonArray* poll_options = NULL;
JsonObject* poll_option = NULL;
I64 votes_count = 0;
JsonArray* ap_poll_options = NULL;
JsonObject* ap_poll_option = NULL;
JsonObject* request_object = NULL;
U8* status_id = NULL;
@ -1101,6 +1109,39 @@ U0 @slon_activitypub_users_inbox(SlonHttpSession* session, U8* user)
request_object = Json.Clone(request_json, slon_mem_task);
}
if (!StrICmp("update", request_json->@("type"))) {
if (request_json->o("object") && !StrICmp("question", request_json->o("object")->@("type"))) {
status_id = StrFind("/", StrFind("/statuses/", request_json->o("object")->@("id")) + 1) + 1;
status = @slon_api_find_status_by_id(status_id, @slon_api_account_by_remote_actor(request_json->@("actor")));
if (status) {
// Update local copy of poll with latest vote counts
poll = status->o("poll");
poll_options = poll->a("options");
if (request_json->o("object")->a("anyOf")) {
ap_poll_options = request_json->o("object")->a("anyOf");
}
if (request_json->o("object")->a("oneOf")) {
ap_poll_options = request_json->o("object")->a("oneOf");
}
if (ap_poll_options) {
for (i = 0; i < ap_poll_options->length; i++) {
ap_poll_option = ap_poll_options->@(i);
for (j = 0; j < poll_options->length; j++) {
poll_option = poll_options->o(j);
if (!StrICmp(ap_poll_option->@("name"), poll_option->@("title"))) {
poll_option->set("votes_count", ap_poll_option->o("replies")->@("totalItems"), JSON_NUMBER);
votes_count += ap_poll_option->o("replies")->@("totalItems");
}
}
}
@slon_db_save_status_to_disk(status);
}
}
}
request_object = Json.Clone(request_json, slon_mem_task);
}
if (request_object) {
JsonObject* o = Json.CreateObject(slon_mem_task);
o->set("actor_for_key_id", session->actor_for_key_id, JSON_STRING);

View file

@ -179,6 +179,22 @@ JsonObject* @slon_api_status_lookup_by_in_reply_to_id(U8* id, JsonArray* statuse
return NULL;
}
JsonObject* @slon_api_status_lookup_by_poll_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->@("poll") && !StrICmp(status->o("poll")->@("id"), id)) {
return status;
}
}
return NULL;
}
JsonObject* @slon_api_status_lookup_by_uri(U8* uri, JsonArray* statuses)
{
if (!uri || !statuses) {
@ -212,6 +228,23 @@ JsonObject* @slon_api_find_status_by_id(U8* id, U8* account_id = NULL)
return NULL;
}
JsonObject* @slon_api_find_status_by_poll_id(U8* id, U8* account_id = NULL)
{
if (account_id) {
return @slon_api_status_lookup_by_poll_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_poll_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) {
@ -285,6 +318,24 @@ Bool @slon_api_status_is_bookmarked(SlonHttpSession* session, JsonObject* status
return FALSE;
}
JsonArray* @slon_api_status_poll_choices(SlonHttpSession* session, JsonObject* status, U8* account_id)
{
no_warn session;
JsonArray* votes = db->o("votes")->a(account_id);
JsonObject* vote = NULL;
if (!votes) {
return NULL;
}
I64 i;
for (i = 0; i < votes->length; i++) {
vote = votes->o(i);
if (!StrICmp(vote->@("status_id"), status->@("id")) && !StrICmp(vote->@("account_id"), account_id)) {
return vote->a("choices");
}
}
return NULL;
}
U0 @slon_api_bookmark_status(SlonHttpSession* session, JsonObject* status, U8* account_id)
{
Bool is_already_bookmarked = FALSE;