diff options
Diffstat (limited to 'activitypub.c')
| -rw-r--r-- | activitypub.c | 241 |
1 files changed, 124 insertions, 117 deletions
diff --git a/activitypub.c b/activitypub.c index 9951f39..d35a909 100644 --- a/activitypub.c +++ b/activitypub.c | |||
| @@ -486,6 +486,109 @@ void process_tags(snac *snac, const char *content, xs_str **n_content, xs_list * | |||
| 486 | } | 486 | } |
| 487 | 487 | ||
| 488 | 488 | ||
| 489 | void notify(snac *snac, const char *type, const char *utype, const char *actor, const xs_dict *msg) | ||
| 490 | /* notifies the user of relevant events */ | ||
| 491 | { | ||
| 492 | if (strcmp(type, "Create") == 0) { | ||
| 493 | /* only notify of notes specifically for us */ | ||
| 494 | xs *rcpts = recipient_list(snac, msg, 0); | ||
| 495 | |||
| 496 | if (xs_list_in(rcpts, snac->actor) == -1) | ||
| 497 | return; | ||
| 498 | } | ||
| 499 | |||
| 500 | if (strcmp(type, "Undo") == 0 && strcmp(utype, "Follow") != 0) | ||
| 501 | return; | ||
| 502 | |||
| 503 | /* get the object id */ | ||
| 504 | const char *objid = xs_dict_get(msg, "object"); | ||
| 505 | |||
| 506 | if (xs_type(objid) == XSTYPE_DICT) | ||
| 507 | objid = xs_dict_get(objid, "id"); | ||
| 508 | else | ||
| 509 | objid = xs_dict_get(msg, "id"); | ||
| 510 | |||
| 511 | if (strcmp(type, "Like") == 0 || strcmp(type, "Announce") == 0) { | ||
| 512 | /* if it's not an admiration about something by us, done */ | ||
| 513 | if (xs_is_null(objid) || !xs_startswith(objid, snac->actor)) | ||
| 514 | return; | ||
| 515 | } | ||
| 516 | |||
| 517 | /* user will love to know about this! */ | ||
| 518 | |||
| 519 | /* prepare message body */ | ||
| 520 | xs *body = xs_fmt("User : @%s@%s\n", | ||
| 521 | xs_dict_get(snac->config, "uid"), | ||
| 522 | xs_dict_get(srv_config, "host") | ||
| 523 | ); | ||
| 524 | |||
| 525 | if (strcmp(utype, "(null)") != 0) { | ||
| 526 | xs *s1 = xs_fmt("Type : %s + %s\n", type, utype); | ||
| 527 | body = xs_str_cat(body, s1); | ||
| 528 | } | ||
| 529 | else { | ||
| 530 | xs *s1 = xs_fmt("Type : %s\n", type); | ||
| 531 | body = xs_str_cat(body, s1); | ||
| 532 | } | ||
| 533 | |||
| 534 | { | ||
| 535 | xs *s1 = xs_fmt("Actor : %s\n", actor); | ||
| 536 | body = xs_str_cat(body, s1); | ||
| 537 | } | ||
| 538 | |||
| 539 | if (objid != NULL) { | ||
| 540 | xs *s1 = xs_fmt("Object: %s\n", objid); | ||
| 541 | body = xs_str_cat(body, s1); | ||
| 542 | } | ||
| 543 | |||
| 544 | /* email */ | ||
| 545 | |||
| 546 | const char *email = "[disabled by admin]"; | ||
| 547 | |||
| 548 | if (xs_type(xs_dict_get(srv_config, "disable_email_notifications")) != XSTYPE_TRUE) { | ||
| 549 | email = xs_dict_get(snac->config_o, "email"); | ||
| 550 | if (xs_is_null(email)) { | ||
| 551 | email = xs_dict_get(snac->config, "email"); | ||
| 552 | |||
| 553 | if (xs_is_null(email)) | ||
| 554 | email = "[empty]"; | ||
| 555 | } | ||
| 556 | } | ||
| 557 | |||
| 558 | if (*email != '\0' && *email != '[') { | ||
| 559 | snac_debug(snac, 1, xs_fmt("email notify %s %s %s", type, utype, actor)); | ||
| 560 | |||
| 561 | xs *subject = xs_fmt("snac notify for @%s@%s", | ||
| 562 | xs_dict_get(snac->config, "uid"), xs_dict_get(srv_config, "host")); | ||
| 563 | xs *from = xs_fmt("snac-daemon <snac-daemon@%s>", xs_dict_get(srv_config, "host")); | ||
| 564 | xs *header = xs_fmt( | ||
| 565 | "From: %s\n" | ||
| 566 | "To: %s\n" | ||
| 567 | "Subject: %s\n" | ||
| 568 | "\n", | ||
| 569 | from, email, subject); | ||
| 570 | |||
| 571 | xs *email_body = xs_fmt("%s%s", header, body); | ||
| 572 | |||
| 573 | enqueue_email(email_body, 0); | ||
| 574 | } | ||
| 575 | |||
| 576 | /* telegram */ | ||
| 577 | |||
| 578 | char *bot = xs_dict_get(snac->config, "telegram_bot"); | ||
| 579 | char *chat_id = xs_dict_get(snac->config, "telegram_chat_id"); | ||
| 580 | |||
| 581 | if (!xs_is_null(bot) && !xs_is_null(chat_id) && *bot && *chat_id) | ||
| 582 | enqueue_telegram(body, bot, chat_id); | ||
| 583 | |||
| 584 | /* finally, store it in the notification folder */ | ||
| 585 | if (strcmp(type, "Follow") == 0) | ||
| 586 | objid = xs_dict_get(msg, "id"); | ||
| 587 | |||
| 588 | notify_add(snac, type, utype, actor, objid); | ||
| 589 | } | ||
| 590 | |||
| 591 | |||
| 489 | /** messages **/ | 592 | /** messages **/ |
| 490 | 593 | ||
| 491 | xs_dict *msg_base(snac *snac, const char *type, const char *id, | 594 | xs_dict *msg_base(snac *snac, const char *type, const char *id, |
| @@ -1070,6 +1173,8 @@ int update_question(snac *user, const char *id) | |||
| 1070 | if (strcmp(now, end_time) >= 0) { | 1173 | if (strcmp(now, end_time) >= 0) { |
| 1071 | xs *et = xs_dup(end_time); | 1174 | xs *et = xs_dup(end_time); |
| 1072 | msg = xs_dict_set(msg, "closed", et); | 1175 | msg = xs_dict_set(msg, "closed", et); |
| 1176 | |||
| 1177 | notify(user, "Update", "Question", user->actor, msg); | ||
| 1073 | } | 1178 | } |
| 1074 | } | 1179 | } |
| 1075 | 1180 | ||
| @@ -1093,107 +1198,6 @@ int update_question(snac *user, const char *id) | |||
| 1093 | } | 1198 | } |
| 1094 | 1199 | ||
| 1095 | 1200 | ||
| 1096 | void notify(snac *snac, xs_str *type, xs_str *utype, xs_str *actor, xs_dict *msg) | ||
| 1097 | /* notifies the user of relevant events */ | ||
| 1098 | { | ||
| 1099 | if (strcmp(type, "Create") == 0) { | ||
| 1100 | /* only notify of notes specifically for us */ | ||
| 1101 | xs *rcpts = recipient_list(snac, msg, 0); | ||
| 1102 | |||
| 1103 | if (xs_list_in(rcpts, snac->actor) == -1) | ||
| 1104 | return; | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | if (strcmp(type, "Undo") == 0 && strcmp(utype, "Follow") != 0) | ||
| 1108 | return; | ||
| 1109 | |||
| 1110 | /* get the object id */ | ||
| 1111 | const char *objid = xs_dict_get(msg, "object"); | ||
| 1112 | |||
| 1113 | if (xs_type(objid) == XSTYPE_DICT) | ||
| 1114 | objid = xs_dict_get(objid, "id"); | ||
| 1115 | |||
| 1116 | if (strcmp(type, "Like") == 0 || strcmp(type, "Announce") == 0) { | ||
| 1117 | /* if it's not an admiration about something by us, done */ | ||
| 1118 | if (xs_is_null(objid) || !xs_startswith(objid, snac->actor)) | ||
| 1119 | return; | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | /* user will love to know about this! */ | ||
| 1123 | |||
| 1124 | /* prepare message body */ | ||
| 1125 | xs *body = xs_fmt("User : @%s@%s\n", | ||
| 1126 | xs_dict_get(snac->config, "uid"), | ||
| 1127 | xs_dict_get(srv_config, "host") | ||
| 1128 | ); | ||
| 1129 | |||
| 1130 | if (strcmp(utype, "(null)") != 0) { | ||
| 1131 | xs *s1 = xs_fmt("Type : %s + %s\n", type, utype); | ||
| 1132 | body = xs_str_cat(body, s1); | ||
| 1133 | } | ||
| 1134 | else { | ||
| 1135 | xs *s1 = xs_fmt("Type : %s\n", type); | ||
| 1136 | body = xs_str_cat(body, s1); | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | { | ||
| 1140 | xs *s1 = xs_fmt("Actor : %s\n", actor); | ||
| 1141 | body = xs_str_cat(body, s1); | ||
| 1142 | } | ||
| 1143 | |||
| 1144 | if (objid != NULL) { | ||
| 1145 | xs *s1 = xs_fmt("Object: %s\n", objid); | ||
| 1146 | body = xs_str_cat(body, s1); | ||
| 1147 | } | ||
| 1148 | |||
| 1149 | /* email */ | ||
| 1150 | |||
| 1151 | const char *email = "[disabled by admin]"; | ||
| 1152 | |||
| 1153 | if (xs_type(xs_dict_get(srv_config, "disable_email_notifications")) != XSTYPE_TRUE) { | ||
| 1154 | email = xs_dict_get(snac->config_o, "email"); | ||
| 1155 | if (xs_is_null(email)) { | ||
| 1156 | email = xs_dict_get(snac->config, "email"); | ||
| 1157 | |||
| 1158 | if (xs_is_null(email)) | ||
| 1159 | email = "[empty]"; | ||
| 1160 | } | ||
| 1161 | } | ||
| 1162 | |||
| 1163 | if (*email != '\0' && *email != '[') { | ||
| 1164 | snac_debug(snac, 1, xs_fmt("email notify %s %s %s", type, utype, actor)); | ||
| 1165 | |||
| 1166 | xs *subject = xs_fmt("snac notify for @%s@%s", | ||
| 1167 | xs_dict_get(snac->config, "uid"), xs_dict_get(srv_config, "host")); | ||
| 1168 | xs *from = xs_fmt("snac-daemon <snac-daemon@%s>", xs_dict_get(srv_config, "host")); | ||
| 1169 | xs *header = xs_fmt( | ||
| 1170 | "From: %s\n" | ||
| 1171 | "To: %s\n" | ||
| 1172 | "Subject: %s\n" | ||
| 1173 | "\n", | ||
| 1174 | from, email, subject); | ||
| 1175 | |||
| 1176 | xs *email_body = xs_fmt("%s%s", header, body); | ||
| 1177 | |||
| 1178 | enqueue_email(email_body, 0); | ||
| 1179 | } | ||
| 1180 | |||
| 1181 | /* telegram */ | ||
| 1182 | |||
| 1183 | char *bot = xs_dict_get(snac->config, "telegram_bot"); | ||
| 1184 | char *chat_id = xs_dict_get(snac->config, "telegram_chat_id"); | ||
| 1185 | |||
| 1186 | if (!xs_is_null(bot) && !xs_is_null(chat_id) && *bot && *chat_id) | ||
| 1187 | enqueue_telegram(body, bot, chat_id); | ||
| 1188 | |||
| 1189 | /* finally, store it in the notification folder */ | ||
| 1190 | if (strcmp(type, "Follow") == 0) | ||
| 1191 | objid = xs_dict_get(msg, "id"); | ||
| 1192 | |||
| 1193 | notify_add(snac, type, utype, actor, objid); | ||
| 1194 | } | ||
| 1195 | |||
| 1196 | |||
| 1197 | /** queues **/ | 1201 | /** queues **/ |
| 1198 | 1202 | ||
| 1199 | int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | 1203 | int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) |
| @@ -1270,7 +1274,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 1270 | return 1; | 1274 | return 1; |
| 1271 | } | 1275 | } |
| 1272 | 1276 | ||
| 1273 | if (strcmp(type, "Follow") == 0) { | 1277 | if (strcmp(type, "Follow") == 0) { /** **/ |
| 1274 | if (!follower_check(snac, actor)) { | 1278 | if (!follower_check(snac, actor)) { |
| 1275 | xs *f_msg = xs_dup(msg); | 1279 | xs *f_msg = xs_dup(msg); |
| 1276 | xs *reply = msg_accept(snac, f_msg, actor); | 1280 | xs *reply = msg_accept(snac, f_msg, actor); |
| @@ -1294,8 +1298,8 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 1294 | snac_log(snac, xs_fmt("repeated 'Follow' from %s", actor)); | 1298 | snac_log(snac, xs_fmt("repeated 'Follow' from %s", actor)); |
| 1295 | } | 1299 | } |
| 1296 | else | 1300 | else |
| 1297 | if (strcmp(type, "Undo") == 0) { | 1301 | if (strcmp(type, "Undo") == 0) { /** **/ |
| 1298 | if (strcmp(utype, "Follow") == 0) { | 1302 | if (strcmp(utype, "Follow") == 0) { /** **/ |
| 1299 | if (valid_status(follower_del(snac, actor))) { | 1303 | if (valid_status(follower_del(snac, actor))) { |
| 1300 | snac_log(snac, xs_fmt("no longer following us %s", actor)); | 1304 | snac_log(snac, xs_fmt("no longer following us %s", actor)); |
| 1301 | do_notify = 1; | 1305 | do_notify = 1; |
| @@ -1307,11 +1311,11 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 1307 | snac_debug(snac, 1, xs_fmt("ignored 'Undo' for object type '%s'", utype)); | 1311 | snac_debug(snac, 1, xs_fmt("ignored 'Undo' for object type '%s'", utype)); |
| 1308 | } | 1312 | } |
| 1309 | else | 1313 | else |
| 1310 | if (strcmp(type, "Create") == 0) { | 1314 | if (strcmp(type, "Create") == 0) { /** **/ |
| 1311 | if (is_muted(snac, actor)) | 1315 | if (is_muted(snac, actor)) |
| 1312 | snac_log(snac, xs_fmt("ignored 'Create' + '%s' from muted actor %s", utype, actor)); | 1316 | snac_log(snac, xs_fmt("ignored 'Create' + '%s' from muted actor %s", utype, actor)); |
| 1313 | 1317 | ||
| 1314 | if (strcmp(utype, "Note") == 0) { | 1318 | if (strcmp(utype, "Note") == 0) { /** **/ |
| 1315 | char *id = xs_dict_get(object, "id"); | 1319 | char *id = xs_dict_get(object, "id"); |
| 1316 | char *in_reply_to = xs_dict_get(object, "inReplyTo"); | 1320 | char *in_reply_to = xs_dict_get(object, "inReplyTo"); |
| 1317 | xs *wrk = NULL; | 1321 | xs *wrk = NULL; |
| @@ -1330,7 +1334,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 1330 | update_question(snac, in_reply_to); | 1334 | update_question(snac, in_reply_to); |
| 1331 | } | 1335 | } |
| 1332 | else | 1336 | else |
| 1333 | if (strcmp(utype, "Question") == 0) { | 1337 | if (strcmp(utype, "Question") == 0) { /** **/ |
| 1334 | char *id = xs_dict_get(object, "id"); | 1338 | char *id = xs_dict_get(object, "id"); |
| 1335 | 1339 | ||
| 1336 | if (timeline_add(snac, id, object)) | 1340 | if (timeline_add(snac, id, object)) |
| @@ -1340,8 +1344,8 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 1340 | snac_debug(snac, 1, xs_fmt("ignored 'Create' for object type '%s'", utype)); | 1344 | snac_debug(snac, 1, xs_fmt("ignored 'Create' for object type '%s'", utype)); |
| 1341 | } | 1345 | } |
| 1342 | else | 1346 | else |
| 1343 | if (strcmp(type, "Accept") == 0) { | 1347 | if (strcmp(type, "Accept") == 0) { /** **/ |
| 1344 | if (strcmp(utype, "Follow") == 0) { | 1348 | if (strcmp(utype, "Follow") == 0) { /** **/ |
| 1345 | if (following_check(snac, actor)) { | 1349 | if (following_check(snac, actor)) { |
| 1346 | following_add(snac, actor, msg); | 1350 | following_add(snac, actor, msg); |
| 1347 | snac_log(snac, xs_fmt("confirmed follow from %s", actor)); | 1351 | snac_log(snac, xs_fmt("confirmed follow from %s", actor)); |
| @@ -1353,7 +1357,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 1353 | snac_debug(snac, 1, xs_fmt("ignored 'Accept' for object type '%s'", utype)); | 1357 | snac_debug(snac, 1, xs_fmt("ignored 'Accept' for object type '%s'", utype)); |
| 1354 | } | 1358 | } |
| 1355 | else | 1359 | else |
| 1356 | if (strcmp(type, "Like") == 0) { | 1360 | if (strcmp(type, "Like") == 0) { /** **/ |
| 1357 | if (xs_type(object) == XSTYPE_DICT) | 1361 | if (xs_type(object) == XSTYPE_DICT) |
| 1358 | object = xs_dict_get(object, "id"); | 1362 | object = xs_dict_get(object, "id"); |
| 1359 | 1363 | ||
| @@ -1362,7 +1366,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 1362 | do_notify = 1; | 1366 | do_notify = 1; |
| 1363 | } | 1367 | } |
| 1364 | else | 1368 | else |
| 1365 | if (strcmp(type, "Announce") == 0) { | 1369 | if (strcmp(type, "Announce") == 0) { /** **/ |
| 1366 | xs *a_msg = NULL; | 1370 | xs *a_msg = NULL; |
| 1367 | xs *wrk = NULL; | 1371 | xs *wrk = NULL; |
| 1368 | 1372 | ||
| @@ -1393,7 +1397,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 1393 | snac_log(snac, xs_fmt("error requesting 'Announce' object %s", object)); | 1397 | snac_log(snac, xs_fmt("error requesting 'Announce' object %s", object)); |
| 1394 | } | 1398 | } |
| 1395 | else | 1399 | else |
| 1396 | if (strcmp(type, "Update") == 0) { | 1400 | if (strcmp(type, "Update") == 0) { /** **/ |
| 1397 | if (strcmp(utype, "Person") == 0) { | 1401 | if (strcmp(utype, "Person") == 0) { |
| 1398 | actor_add(actor, xs_dict_get(msg, "object")); | 1402 | actor_add(actor, xs_dict_get(msg, "object")); |
| 1399 | timeline_touch(snac); | 1403 | timeline_touch(snac); |
| @@ -1401,7 +1405,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 1401 | snac_log(snac, xs_fmt("updated actor %s", actor)); | 1405 | snac_log(snac, xs_fmt("updated actor %s", actor)); |
| 1402 | } | 1406 | } |
| 1403 | else | 1407 | else |
| 1404 | if (strcmp(utype, "Note") == 0) { | 1408 | if (strcmp(utype, "Note") == 0) { /** **/ |
| 1405 | const char *id = xs_dict_get(object, "id"); | 1409 | const char *id = xs_dict_get(object, "id"); |
| 1406 | 1410 | ||
| 1407 | object_add_ow(id, object); | 1411 | object_add_ow(id, object); |
| @@ -1410,7 +1414,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 1410 | snac_log(snac, xs_fmt("updated post %s", id)); | 1414 | snac_log(snac, xs_fmt("updated post %s", id)); |
| 1411 | } | 1415 | } |
| 1412 | else | 1416 | else |
| 1413 | if (strcmp(utype, "Question") == 0) { | 1417 | if (strcmp(utype, "Question") == 0) { /** **/ |
| 1414 | const char *id = xs_dict_get(object, "id"); | 1418 | const char *id = xs_dict_get(object, "id"); |
| 1415 | const char *closed = xs_dict_get(object, "closed"); | 1419 | const char *closed = xs_dict_get(object, "closed"); |
| 1416 | 1420 | ||
| @@ -1418,12 +1422,15 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 1418 | timeline_touch(snac); | 1422 | timeline_touch(snac); |
| 1419 | 1423 | ||
| 1420 | snac_log(snac, xs_fmt("%s poll %s", closed == NULL ? "updated" : "closed", id)); | 1424 | snac_log(snac, xs_fmt("%s poll %s", closed == NULL ? "updated" : "closed", id)); |
| 1425 | |||
| 1426 | if (closed != NULL) | ||
| 1427 | do_notify = 1; | ||
| 1421 | } | 1428 | } |
| 1422 | else | 1429 | else |
| 1423 | snac_log(snac, xs_fmt("ignored 'Update' for object type '%s'", utype)); | 1430 | snac_log(snac, xs_fmt("ignored 'Update' for object type '%s'", utype)); |
| 1424 | } | 1431 | } |
| 1425 | else | 1432 | else |
| 1426 | if (strcmp(type, "Delete") == 0) { | 1433 | if (strcmp(type, "Delete") == 0) { /** **/ |
| 1427 | if (xs_type(object) == XSTYPE_DICT) | 1434 | if (xs_type(object) == XSTYPE_DICT) |
| 1428 | object = xs_dict_get(object, "id"); | 1435 | object = xs_dict_get(object, "id"); |
| 1429 | 1436 | ||
| @@ -1433,11 +1440,11 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 1433 | snac_debug(snac, 1, xs_fmt("ignored 'Delete' for unknown object %s", object)); | 1440 | snac_debug(snac, 1, xs_fmt("ignored 'Delete' for unknown object %s", object)); |
| 1434 | } | 1441 | } |
| 1435 | else | 1442 | else |
| 1436 | if (strcmp(type, "Pong") == 0) { | 1443 | if (strcmp(type, "Pong") == 0) { /** **/ |
| 1437 | snac_log(snac, xs_fmt("'Pong' received from %s", actor)); | 1444 | snac_log(snac, xs_fmt("'Pong' received from %s", actor)); |
| 1438 | } | 1445 | } |
| 1439 | else | 1446 | else |
| 1440 | if (strcmp(type, "Ping") == 0) { | 1447 | if (strcmp(type, "Ping") == 0) { /** **/ |
| 1441 | snac_log(snac, xs_fmt("'Ping' requested from %s", actor)); | 1448 | snac_log(snac, xs_fmt("'Ping' requested from %s", actor)); |
| 1442 | 1449 | ||
| 1443 | xs *rsp = msg_pong(snac, actor, xs_dict_get(msg, "id")); | 1450 | xs *rsp = msg_pong(snac, actor, xs_dict_get(msg, "id")); |