diff options
Diffstat (limited to 'html.c')
| -rw-r--r-- | html.c | 142 |
1 files changed, 125 insertions, 17 deletions
| @@ -350,7 +350,7 @@ xs_html *html_note(snac *user, const char *summary, | |||
| 350 | const xs_val *mnt_only, const char *redir, | 350 | const xs_val *mnt_only, const char *redir, |
| 351 | const char *in_reply_to, int poll, | 351 | const char *in_reply_to, int poll, |
| 352 | const xs_list *att_files, const xs_list *att_alt_texts, | 352 | const xs_list *att_files, const xs_list *att_alt_texts, |
| 353 | int is_draft) | 353 | int is_draft, const char *published) |
| 354 | /* Yes, this is a FUCKTON of arguments and I'm a bit embarrased */ | 354 | /* Yes, this is a FUCKTON of arguments and I'm a bit embarrased */ |
| 355 | { | 355 | { |
| 356 | xs *action = xs_fmt("%s/admin/note", user->actor); | 356 | xs *action = xs_fmt("%s/admin/note", user->actor); |
| @@ -440,6 +440,36 @@ xs_html *html_note(snac *user, const char *summary, | |||
| 440 | xs_html_attr("name", "is_draft"), | 440 | xs_html_attr("name", "is_draft"), |
| 441 | xs_html_attr(is_draft ? "checked" : "", NULL)))); | 441 | xs_html_attr(is_draft ? "checked" : "", NULL)))); |
| 442 | 442 | ||
| 443 | /* post date and time */ | ||
| 444 | xs *post_date = NULL; | ||
| 445 | xs *post_time = NULL; | ||
| 446 | |||
| 447 | if (xs_is_string(published)) { | ||
| 448 | time_t t = xs_parse_iso_date(published, 0); | ||
| 449 | |||
| 450 | if (t > 0) { | ||
| 451 | post_date = xs_str_time(t, "%Y-%m-%d", 1); | ||
| 452 | post_time = xs_str_time(t, "%H:%M:%S", 1); | ||
| 453 | } | ||
| 454 | } | ||
| 455 | |||
| 456 | if (edit_id == NULL || is_draft || is_scheduled(user, edit_id)) { | ||
| 457 | xs_html_add(form, | ||
| 458 | xs_html_tag("p", | ||
| 459 | xs_html_text(L("Post date and time (empty, right now; in the future, schedule for later):")), | ||
| 460 | xs_html_sctag("br", NULL), | ||
| 461 | xs_html_sctag("input", | ||
| 462 | xs_html_attr("type", "date"), | ||
| 463 | xs_html_attr("value", post_date ? post_date : ""), | ||
| 464 | xs_html_attr("name", "post_date")), | ||
| 465 | xs_html_text(" "), | ||
| 466 | xs_html_sctag("input", | ||
| 467 | xs_html_attr("type", "time"), | ||
| 468 | xs_html_attr("value", post_time ? post_time : ""), | ||
| 469 | xs_html_attr("step", "1"), | ||
| 470 | xs_html_attr("name", "post_time")))); | ||
| 471 | } | ||
| 472 | |||
| 443 | if (edit_id) | 473 | if (edit_id) |
| 444 | xs_html_add(form, | 474 | xs_html_add(form, |
| 445 | xs_html_sctag("input", | 475 | xs_html_sctag("input", |
| @@ -1127,7 +1157,7 @@ xs_html *html_top_controls(snac *user) | |||
| 1127 | NULL, NULL, | 1157 | NULL, NULL, |
| 1128 | xs_stock(XSTYPE_FALSE), "", | 1158 | xs_stock(XSTYPE_FALSE), "", |
| 1129 | xs_stock(XSTYPE_FALSE), NULL, | 1159 | xs_stock(XSTYPE_FALSE), NULL, |
| 1130 | NULL, 1, NULL, NULL, 0), | 1160 | NULL, 1, NULL, NULL, 0, NULL), |
| 1131 | 1161 | ||
| 1132 | /** operations **/ | 1162 | /** operations **/ |
| 1133 | xs_html_tag("details", | 1163 | xs_html_tag("details", |
| @@ -1785,7 +1815,8 @@ xs_html *html_entry_controls(snac *user, const char *actor, | |||
| 1785 | id, NULL, | 1815 | id, NULL, |
| 1786 | xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), | 1816 | xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), |
| 1787 | xs_stock(is_msg_public(msg) ? XSTYPE_FALSE : XSTYPE_TRUE), redir, | 1817 | xs_stock(is_msg_public(msg) ? XSTYPE_FALSE : XSTYPE_TRUE), redir, |
| 1788 | NULL, 0, att_files, att_alt_texts, is_draft(user, id))), | 1818 | NULL, 0, att_files, att_alt_texts, is_draft(user, id), |
| 1819 | xs_dict_get(msg, "published"))), | ||
| 1789 | xs_html_tag("p", NULL)); | 1820 | xs_html_tag("p", NULL)); |
| 1790 | } | 1821 | } |
| 1791 | 1822 | ||
| @@ -1804,7 +1835,7 @@ xs_html *html_entry_controls(snac *user, const char *actor, | |||
| 1804 | NULL, NULL, | 1835 | NULL, NULL, |
| 1805 | xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), | 1836 | xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), |
| 1806 | xs_stock(is_msg_public(msg) ? XSTYPE_FALSE : XSTYPE_TRUE), redir, | 1837 | xs_stock(is_msg_public(msg) ? XSTYPE_FALSE : XSTYPE_TRUE), redir, |
| 1807 | id, 0, NULL, NULL, 0)), | 1838 | id, 0, NULL, NULL, 0, NULL)), |
| 1808 | xs_html_tag("p", NULL)); | 1839 | xs_html_tag("p", NULL)); |
| 1809 | } | 1840 | } |
| 1810 | 1841 | ||
| @@ -2841,6 +2872,18 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, | |||
| 2841 | xs_html_text(L("drafts"))))); | 2872 | xs_html_text(L("drafts"))))); |
| 2842 | } | 2873 | } |
| 2843 | 2874 | ||
| 2875 | { | ||
| 2876 | /* show the list of scheduled posts */ | ||
| 2877 | xs *url = xs_fmt("%s/sched", user->actor); | ||
| 2878 | xs_html_add(lol, | ||
| 2879 | xs_html_tag("li", | ||
| 2880 | xs_html_tag("a", | ||
| 2881 | xs_html_attr("href", url), | ||
| 2882 | xs_html_attr("class", "snac-list-link"), | ||
| 2883 | xs_html_attr("title", L("Scheduled posts")), | ||
| 2884 | xs_html_text(L("scheduled posts"))))); | ||
| 2885 | } | ||
| 2886 | |||
| 2844 | /* the list of followed hashtags */ | 2887 | /* the list of followed hashtags */ |
| 2845 | const char *followed_hashtags = xs_dict_get(user->config, "followed_hashtags"); | 2888 | const char *followed_hashtags = xs_dict_get(user->config, "followed_hashtags"); |
| 2846 | 2889 | ||
| @@ -3141,7 +3184,7 @@ xs_html *html_people_list(snac *user, xs_list *list, const char *header, const c | |||
| 3141 | NULL, actor_id, | 3184 | NULL, actor_id, |
| 3142 | xs_stock(XSTYPE_FALSE), "", | 3185 | xs_stock(XSTYPE_FALSE), "", |
| 3143 | xs_stock(XSTYPE_FALSE), NULL, | 3186 | xs_stock(XSTYPE_FALSE), NULL, |
| 3144 | NULL, 0, NULL, NULL, 0), | 3187 | NULL, 0, NULL, NULL, 0, NULL), |
| 3145 | xs_html_tag("p", NULL)); | 3188 | xs_html_tag("p", NULL)); |
| 3146 | 3189 | ||
| 3147 | xs_html_add(snac_post, snac_controls); | 3190 | xs_html_add(snac_post, snac_controls); |
| @@ -3890,6 +3933,21 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 3890 | } | 3933 | } |
| 3891 | } | 3934 | } |
| 3892 | else | 3935 | else |
| 3936 | if (strcmp(p_path, "sched") == 0) { /** list of scheduled posts **/ | ||
| 3937 | if (!login(&snac, req)) { | ||
| 3938 | *body = xs_dup(uid); | ||
| 3939 | status = HTTP_STATUS_UNAUTHORIZED; | ||
| 3940 | } | ||
| 3941 | else { | ||
| 3942 | xs *list = scheduled_list(&snac); | ||
| 3943 | |||
| 3944 | *body = html_timeline(&snac, list, 0, skip, show, | ||
| 3945 | 0, L("Scheduled posts"), "", 0, error); | ||
| 3946 | *b_size = strlen(*body); | ||
| 3947 | status = HTTP_STATUS_OK; | ||
| 3948 | } | ||
| 3949 | } | ||
| 3950 | else | ||
| 3893 | if (xs_startswith(p_path, "list/")) { /** list timelines **/ | 3951 | if (xs_startswith(p_path, "list/")) { /** list timelines **/ |
| 3894 | if (!login(&snac, req)) { | 3952 | if (!login(&snac, req)) { |
| 3895 | *body = xs_dup(uid); | 3953 | *body = xs_dup(uid); |
| @@ -4186,12 +4244,14 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4186 | snac_debug(&snac, 1, xs_fmt("web action '%s' received", p_path)); | 4244 | snac_debug(&snac, 1, xs_fmt("web action '%s' received", p_path)); |
| 4187 | 4245 | ||
| 4188 | /* post note */ | 4246 | /* post note */ |
| 4189 | const xs_str *content = xs_dict_get(p_vars, "content"); | 4247 | const char *content = xs_dict_get(p_vars, "content"); |
| 4190 | const xs_str *in_reply_to = xs_dict_get(p_vars, "in_reply_to"); | 4248 | const char *in_reply_to = xs_dict_get(p_vars, "in_reply_to"); |
| 4191 | const xs_str *to = xs_dict_get(p_vars, "to"); | 4249 | const char *to = xs_dict_get(p_vars, "to"); |
| 4192 | const xs_str *sensitive = xs_dict_get(p_vars, "sensitive"); | 4250 | const char *sensitive = xs_dict_get(p_vars, "sensitive"); |
| 4193 | const xs_str *summary = xs_dict_get(p_vars, "summary"); | 4251 | const char *summary = xs_dict_get(p_vars, "summary"); |
| 4194 | const xs_str *edit_id = xs_dict_get(p_vars, "edit_id"); | 4252 | const char *edit_id = xs_dict_get(p_vars, "edit_id"); |
| 4253 | const char *post_date = xs_dict_get_def(p_vars, "post_date", ""); | ||
| 4254 | const char *post_time = xs_dict_get_def(p_vars, "post_time", ""); | ||
| 4195 | int priv = !xs_is_null(xs_dict_get(p_vars, "mentioned_only")); | 4255 | int priv = !xs_is_null(xs_dict_get(p_vars, "mentioned_only")); |
| 4196 | int store_as_draft = !xs_is_null(xs_dict_get(p_vars, "is_draft")); | 4256 | int store_as_draft = !xs_is_null(xs_dict_get(p_vars, "is_draft")); |
| 4197 | xs *attach_list = xs_list_new(); | 4257 | xs *attach_list = xs_list_new(); |
| @@ -4279,6 +4339,29 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4279 | msg = xs_dict_set(msg, "summary", xs_is_null(summary) ? "..." : summary); | 4339 | msg = xs_dict_set(msg, "summary", xs_is_null(summary) ? "..." : summary); |
| 4280 | } | 4340 | } |
| 4281 | 4341 | ||
| 4342 | if (xs_is_string(post_date) && *post_date) { | ||
| 4343 | xs *local_pubdate = xs_fmt("%sT%s", post_date, | ||
| 4344 | xs_is_string(post_time) && *post_time ? post_time : "00:00:00"); | ||
| 4345 | |||
| 4346 | time_t t = xs_parse_iso_date(local_pubdate, 1); | ||
| 4347 | |||
| 4348 | if (t != 0) { | ||
| 4349 | xs *iso_date = xs_str_iso_date(t); | ||
| 4350 | msg = xs_dict_set(msg, "published", iso_date); | ||
| 4351 | |||
| 4352 | snac_debug(&snac, 1, xs_fmt("Published date: [%s]", iso_date)); | ||
| 4353 | } | ||
| 4354 | else | ||
| 4355 | snac_log(&snac, xs_fmt("Invalid post date: [%s]", local_pubdate)); | ||
| 4356 | } | ||
| 4357 | |||
| 4358 | /* is the published date from the future? */ | ||
| 4359 | int future_post = 0; | ||
| 4360 | xs *right_now = xs_str_utctime(0, ISO_DATE_SPEC); | ||
| 4361 | |||
| 4362 | if (strcmp(xs_dict_get(msg, "published"), right_now) > 0) | ||
| 4363 | future_post = 1; | ||
| 4364 | |||
| 4282 | if (xs_is_null(edit_id)) { | 4365 | if (xs_is_null(edit_id)) { |
| 4283 | /* new message */ | 4366 | /* new message */ |
| 4284 | const char *id = xs_dict_get(msg, "id"); | 4367 | const char *id = xs_dict_get(msg, "id"); |
| @@ -4286,6 +4369,10 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4286 | if (store_as_draft) { | 4369 | if (store_as_draft) { |
| 4287 | draft_add(&snac, id, msg); | 4370 | draft_add(&snac, id, msg); |
| 4288 | } | 4371 | } |
| 4372 | else | ||
| 4373 | if (future_post) { | ||
| 4374 | schedule_add(&snac, id, msg); | ||
| 4375 | } | ||
| 4289 | else { | 4376 | else { |
| 4290 | c_msg = msg_create(&snac, msg); | 4377 | c_msg = msg_create(&snac, msg); |
| 4291 | timeline_add(&snac, id, msg); | 4378 | timeline_add(&snac, id, msg); |
| @@ -4297,7 +4384,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4297 | 4384 | ||
| 4298 | if (valid_status(object_get(edit_id, &p_msg))) { | 4385 | if (valid_status(object_get(edit_id, &p_msg))) { |
| 4299 | /* copy relevant fields from previous version */ | 4386 | /* copy relevant fields from previous version */ |
| 4300 | char *fields[] = { "id", "context", "url", "published", | 4387 | char *fields[] = { "id", "context", "url", |
| 4301 | "to", "inReplyTo", NULL }; | 4388 | "to", "inReplyTo", NULL }; |
| 4302 | int n; | 4389 | int n; |
| 4303 | 4390 | ||
| @@ -4313,18 +4400,34 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4313 | if (is_draft(&snac, edit_id)) { | 4400 | if (is_draft(&snac, edit_id)) { |
| 4314 | /* message was previously a draft; it's a create activity */ | 4401 | /* message was previously a draft; it's a create activity */ |
| 4315 | 4402 | ||
| 4316 | /* set the published field to now */ | 4403 | /* if the date is from the past, overwrite it with right_now */ |
| 4317 | xs *published = xs_str_utctime(0, ISO_DATE_SPEC); | 4404 | if (strcmp(xs_dict_get(msg, "published"), right_now) < 0) { |
| 4318 | msg = xs_dict_set(msg, "published", published); | 4405 | snac_debug(&snac, 1, xs_fmt("setting draft ancient date to %s", right_now)); |
| 4406 | msg = xs_dict_set(msg, "published", right_now); | ||
| 4407 | } | ||
| 4319 | 4408 | ||
| 4320 | /* overwrite object */ | 4409 | /* overwrite object */ |
| 4321 | object_add_ow(edit_id, msg); | 4410 | object_add_ow(edit_id, msg); |
| 4322 | 4411 | ||
| 4323 | c_msg = msg_create(&snac, msg); | 4412 | if (future_post) { |
| 4324 | timeline_add(&snac, edit_id, msg); | 4413 | schedule_add(&snac, edit_id, msg); |
| 4414 | } | ||
| 4415 | else { | ||
| 4416 | c_msg = msg_create(&snac, msg); | ||
| 4417 | timeline_add(&snac, edit_id, msg); | ||
| 4418 | } | ||
| 4419 | |||
| 4325 | draft_del(&snac, edit_id); | 4420 | draft_del(&snac, edit_id); |
| 4326 | } | 4421 | } |
| 4422 | else | ||
| 4423 | if (is_scheduled(&snac, edit_id)) { | ||
| 4424 | /* editing an scheduled post; just update it */ | ||
| 4425 | schedule_add(&snac, edit_id, msg); | ||
| 4426 | } | ||
| 4327 | else { | 4427 | else { |
| 4428 | /* ignore the (possibly changed) published date */ | ||
| 4429 | msg = xs_dict_set(msg, "published", xs_dict_get(p_msg, "published")); | ||
| 4430 | |||
| 4328 | /* set the updated field */ | 4431 | /* set the updated field */ |
| 4329 | xs *updated = xs_str_utctime(0, ISO_DATE_SPEC); | 4432 | xs *updated = xs_str_utctime(0, ISO_DATE_SPEC); |
| 4330 | msg = xs_dict_set(msg, "updated", updated); | 4433 | msg = xs_dict_set(msg, "updated", updated); |
| @@ -4409,6 +4512,9 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4409 | if (is_draft(&snac, id)) | 4512 | if (is_draft(&snac, id)) |
| 4410 | draft_del(&snac, id); | 4513 | draft_del(&snac, id); |
| 4411 | else | 4514 | else |
| 4515 | if (is_scheduled(&snac, id)) | ||
| 4516 | schedule_del(&snac, id); | ||
| 4517 | else | ||
| 4412 | hide(&snac, id); | 4518 | hide(&snac, id); |
| 4413 | } | 4519 | } |
| 4414 | else | 4520 | else |
| @@ -4504,6 +4610,8 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4504 | 4610 | ||
| 4505 | draft_del(&snac, id); | 4611 | draft_del(&snac, id); |
| 4506 | 4612 | ||
| 4613 | schedule_del(&snac, id); | ||
| 4614 | |||
| 4507 | snac_log(&snac, xs_fmt("deleted entry %s", id)); | 4615 | snac_log(&snac, xs_fmt("deleted entry %s", id)); |
| 4508 | } | 4616 | } |
| 4509 | } | 4617 | } |