diff options
Diffstat (limited to 'data.c')
| -rw-r--r-- | data.c | 121 |
1 files changed, 120 insertions, 1 deletions
| @@ -336,6 +336,35 @@ int user_persist(snac *snac, int publish) | |||
| 336 | xs *bfn = xs_fmt("%s.bak", fn); | 336 | xs *bfn = xs_fmt("%s.bak", fn); |
| 337 | FILE *f; | 337 | FILE *f; |
| 338 | 338 | ||
| 339 | if (publish) { | ||
| 340 | /* check if any of the relevant fields have really changed */ | ||
| 341 | if ((f = fopen(fn, "r")) != NULL) { | ||
| 342 | xs *old = xs_json_load(f); | ||
| 343 | fclose(f); | ||
| 344 | |||
| 345 | if (old != NULL) { | ||
| 346 | int nw = 0; | ||
| 347 | const char *fields[] = { "header", "avatar", "name", "bio", "metadata", NULL }; | ||
| 348 | |||
| 349 | for (int n = 0; fields[n]; n++) { | ||
| 350 | const char *of = xs_dict_get(old, fields[n]); | ||
| 351 | const char *nf = xs_dict_get(snac->config, fields[n]); | ||
| 352 | |||
| 353 | if (of == NULL && nf == NULL) | ||
| 354 | continue; | ||
| 355 | |||
| 356 | if (xs_type(of) != XSTYPE_STRING || xs_type(nf) != XSTYPE_STRING || strcmp(of, nf)) { | ||
| 357 | nw = 1; | ||
| 358 | break; | ||
| 359 | } | ||
| 360 | } | ||
| 361 | |||
| 362 | if (!nw) | ||
| 363 | publish = 0; | ||
| 364 | } | ||
| 365 | } | ||
| 366 | } | ||
| 367 | |||
| 339 | rename(fn, bfn); | 368 | rename(fn, bfn); |
| 340 | 369 | ||
| 341 | if ((f = fopen(fn, "w")) != NULL) { | 370 | if ((f = fopen(fn, "w")) != NULL) { |
| @@ -799,7 +828,7 @@ int _object_add(const char *id, const xs_dict *obj, int ow) | |||
| 799 | fclose(f); | 828 | fclose(f); |
| 800 | 829 | ||
| 801 | /* does this object has a parent? */ | 830 | /* does this object has a parent? */ |
| 802 | const char *in_reply_to = xs_dict_get(obj, "inReplyTo"); | 831 | const char *in_reply_to = get_in_reply_to(obj); |
| 803 | 832 | ||
| 804 | if (!xs_is_null(in_reply_to) && *in_reply_to) { | 833 | if (!xs_is_null(in_reply_to) && *in_reply_to) { |
| 805 | /* update the children index of the parent */ | 834 | /* update the children index of the parent */ |
| @@ -1176,6 +1205,96 @@ xs_list *follower_list(snac *snac) | |||
| 1176 | } | 1205 | } |
| 1177 | 1206 | ||
| 1178 | 1207 | ||
| 1208 | /** pending followers **/ | ||
| 1209 | |||
| 1210 | int pending_add(snac *user, const char *actor, const xs_dict *msg) | ||
| 1211 | /* stores the follow message for later confirmation */ | ||
| 1212 | { | ||
| 1213 | xs *dir = xs_fmt("%s/pending", user->basedir); | ||
| 1214 | xs *md5 = xs_md5_hex(actor, strlen(actor)); | ||
| 1215 | xs *fn = xs_fmt("%s/%s.json", dir, md5); | ||
| 1216 | FILE *f; | ||
| 1217 | |||
| 1218 | mkdirx(dir); | ||
| 1219 | |||
| 1220 | if ((f = fopen(fn, "w")) == NULL) | ||
| 1221 | return -1; | ||
| 1222 | |||
| 1223 | xs_json_dump(msg, 4, f); | ||
| 1224 | fclose(f); | ||
| 1225 | |||
| 1226 | return 0; | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | |||
| 1230 | int pending_check(snac *user, const char *actor) | ||
| 1231 | /* checks if there is a pending follow confirmation for the actor */ | ||
| 1232 | { | ||
| 1233 | xs *md5 = xs_md5_hex(actor, strlen(actor)); | ||
| 1234 | xs *fn = xs_fmt("%s/pending/%s.json", user->basedir, md5); | ||
| 1235 | |||
| 1236 | return mtime(fn) != 0; | ||
| 1237 | } | ||
| 1238 | |||
| 1239 | |||
| 1240 | xs_dict *pending_get(snac *user, const char *actor) | ||
| 1241 | /* returns the pending follow confirmation for the actor */ | ||
| 1242 | { | ||
| 1243 | xs *md5 = xs_md5_hex(actor, strlen(actor)); | ||
| 1244 | xs *fn = xs_fmt("%s/pending/%s.json", user->basedir, md5); | ||
| 1245 | xs_dict *msg = NULL; | ||
| 1246 | FILE *f; | ||
| 1247 | |||
| 1248 | if ((f = fopen(fn, "r")) != NULL) { | ||
| 1249 | msg = xs_json_load(f); | ||
| 1250 | fclose(f); | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | return msg; | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | |||
| 1257 | void pending_del(snac *user, const char *actor) | ||
| 1258 | /* deletes a pending follow confirmation for the actor */ | ||
| 1259 | { | ||
| 1260 | xs *md5 = xs_md5_hex(actor, strlen(actor)); | ||
| 1261 | xs *fn = xs_fmt("%s/pending/%s.json", user->basedir, md5); | ||
| 1262 | |||
| 1263 | unlink(fn); | ||
| 1264 | } | ||
| 1265 | |||
| 1266 | |||
| 1267 | xs_list *pending_list(snac *user) | ||
| 1268 | /* returns a list of pending follow confirmations */ | ||
| 1269 | { | ||
| 1270 | xs *spec = xs_fmt("%s/pending/""*.json", user->basedir); | ||
| 1271 | xs *l = xs_glob(spec, 0, 0); | ||
| 1272 | xs_list *r = xs_list_new(); | ||
| 1273 | const char *v; | ||
| 1274 | |||
| 1275 | xs_list_foreach(l, v) { | ||
| 1276 | FILE *f; | ||
| 1277 | xs *msg = NULL; | ||
| 1278 | |||
| 1279 | if ((f = fopen(v, "r")) == NULL) | ||
| 1280 | continue; | ||
| 1281 | |||
| 1282 | msg = xs_json_load(f); | ||
| 1283 | fclose(f); | ||
| 1284 | |||
| 1285 | if (msg == NULL) | ||
| 1286 | continue; | ||
| 1287 | |||
| 1288 | const char *actor = xs_dict_get(msg, "actor"); | ||
| 1289 | |||
| 1290 | if (xs_type(actor) == XSTYPE_STRING) | ||
| 1291 | r = xs_list_append(r, actor); | ||
| 1292 | } | ||
| 1293 | |||
| 1294 | return r; | ||
| 1295 | } | ||
| 1296 | |||
| 1297 | |||
| 1179 | /** timeline **/ | 1298 | /** timeline **/ |
| 1180 | 1299 | ||
| 1181 | double timeline_mtime(snac *snac) | 1300 | double timeline_mtime(snac *snac) |