mirror of
git://git.psyced.org/git/psyced
synced 2024-08-15 03:25:10 +00:00
user channel improvements: /add, /remove & /privacy cmds, html output for multiple channels in /surf
place/threads: better _notify msgs & error handling, improved html & json generation, TODO: use signatures here as well place/userthreads: added /add, /remove & /privacy cmds person: (un)subscribe to user channel when a user uses the /add & /remove commands, autojoin to #friends & #follow after friendship is established, added _channels data to qDescription user: htDescription: generate html from _channels data http: TODO: fix web examine cmd so it's not executed twice
This commit is contained in:
parent
af95219a9e
commit
f24d662c3c
7 changed files with 500 additions and 183 deletions
|
@ -73,6 +73,12 @@ private volatile mapping _sigs = ([
|
||||||
"_request_ni": ({ "_request_nick_local", 0, "_nick_local", "_INTERNAL_stuss" }),
|
"_request_ni": ({ "_request_nick_local", 0, "_nick_local", "_INTERNAL_stuss" }),
|
||||||
"_request_public": ({ "_request_public", 0, "_flag_public" }),
|
"_request_public": ({ "_request_public", 0, "_flag_public" }),
|
||||||
"_request_pub": ({ "_request_public", 0, "_flag_public" }),
|
"_request_pub": ({ "_request_public", 0, "_flag_public" }),
|
||||||
|
#ifdef _flag_enable_module_microblogging
|
||||||
|
"_request_add": ({ "_request_add", 0, "_person" }),
|
||||||
|
"_request_remove": ({ "_request_remove", 0, "_person" }),
|
||||||
|
"_request_priv": ({ "_request_privacy", 0, "_privacy" }),
|
||||||
|
"_request_privacy": ({ "_request_privacy", 0, "_privacy" }),
|
||||||
|
#endif
|
||||||
#ifdef EXPERIMENTAL
|
#ifdef EXPERIMENTAL
|
||||||
// stuff to play around with
|
// stuff to play around with
|
||||||
"_request_pset": ({ "_request_set", 0, "_key", "_value" }),
|
"_request_pset": ({ "_request_set", 0, "_key", "_value" }),
|
||||||
|
|
|
@ -467,6 +467,16 @@ qDescription(source, vars, profile, itsme) {
|
||||||
if (v("fname"))
|
if (v("fname"))
|
||||||
dv["_name_first"] = v("fname");
|
dv["_name_first"] = v("fname");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _flag_enable_module_microblogging
|
||||||
|
mapping channels = ([ ]);
|
||||||
|
foreach (string c : v("channels")) {
|
||||||
|
object p = find_place(c);
|
||||||
|
unless (objectp(p) && (p->isPublic() || (source && p->qMember(source))) /*&& p->numEntries() > 0*/) continue;
|
||||||
|
channels += ([ p->qChannel(): p->entries(10)]);
|
||||||
|
}
|
||||||
|
dv["_channels"] = make_json(channels);
|
||||||
|
#endif
|
||||||
// PT(("sending: %O\n", dv))
|
// PT(("sending: %O\n", dv))
|
||||||
return dv;
|
return dv;
|
||||||
}
|
}
|
||||||
|
@ -2042,6 +2052,14 @@ case "_request_friendship_implied":
|
||||||
insert_member(source);
|
insert_member(source);
|
||||||
else
|
else
|
||||||
insert_member(source, parse_uniform(source, 1)[URoot]);
|
insert_member(source, parse_uniform(source, 1)[URoot]);
|
||||||
|
|
||||||
|
#ifdef _flag_enable_module_microblogging
|
||||||
|
string uni = psyc_name(ME);
|
||||||
|
sendmsg(source, "_notice_place_enter_automatic_subscription_follow",
|
||||||
|
"Following [_nick_place]", (["_nick": MYNICK, "_nick_place": uni + "#follow" ]));
|
||||||
|
sendmsg(source, "_notice_place_enter_automatic_subscription_follow",
|
||||||
|
"Following [_nick_place]", (["_nick": MYNICK, "_nick_place": uni + "#friends" ]));
|
||||||
|
#endif
|
||||||
showFriends();
|
showFriends();
|
||||||
// fall thru
|
// fall thru
|
||||||
// all other cases describe established friendships,
|
// all other cases describe established friendships,
|
||||||
|
@ -2179,6 +2197,31 @@ case "_status_person_present":
|
||||||
source, display, logged_on))
|
source, display, logged_on))
|
||||||
return logged_on && display; // what about availability?
|
return logged_on && display; // what about availability?
|
||||||
#endif // _flag_disable_module_presence
|
#endif // _flag_disable_module_presence
|
||||||
|
#ifdef _flag_enable_module_microblogging
|
||||||
|
case "_notice_place_enter_automatic_subscription_follow":
|
||||||
|
case "_notice_place_leave_automatic_subscription_follow":
|
||||||
|
string src = objectp(source) ? psyc_name(source) : source;
|
||||||
|
string nick = objectp(source) ? source->qNameLower() : source;
|
||||||
|
string nick_place = vars["_nick_place"];
|
||||||
|
if (qFriend(source) || qSubscription(src, 1) || qSubscription("~"+nick, 1)) {
|
||||||
|
P3((">>> %O: %O subscribed me to %O\n", ME, source, nick_place))
|
||||||
|
subscribe(abbrev("_notice_place_enter", mc) ?
|
||||||
|
SUBSCRIBE_TEMPORARY : SUBSCRIBE_NOT, nick_place);
|
||||||
|
} else if (member(places, find_place(nick_place)) &&
|
||||||
|
(sscanf(nick_place, src+"#%s", t) || sscanf(nick_place, "~"+nick+"#%s", t))) {
|
||||||
|
placeRequest(nick_place,
|
||||||
|
#ifdef SPEC
|
||||||
|
"_request_context_leave",
|
||||||
|
#else
|
||||||
|
"_request_leave",
|
||||||
|
#endif
|
||||||
|
1);
|
||||||
|
} else {
|
||||||
|
P3((">>> %O: got a %O from %O, but he is not a friend or not already following him.\n",
|
||||||
|
ME, mc, source, nick_place))
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
#endif
|
||||||
case "_notice_mail":
|
case "_notice_mail":
|
||||||
// on request by y0shi.. remember mail notifications
|
// on request by y0shi.. remember mail notifications
|
||||||
// even when offline
|
// even when offline
|
||||||
|
@ -2605,7 +2648,7 @@ quit(immediate, variant) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (immediate == 1 || (immediate && find_call_out(#'quit) != -1)) {
|
if (immediate == 1 || (immediate && find_call_out(#'quit) != -1)) { //'
|
||||||
rc = save();
|
rc = save();
|
||||||
if (sizeof(places)) {
|
if (sizeof(places)) {
|
||||||
P2(("%O stayin' alive because of places %O"
|
P2(("%O stayin' alive because of places %O"
|
||||||
|
@ -2718,7 +2761,7 @@ quit(immediate, variant) {
|
||||||
// return if there are some services/clients left
|
// return if there are some services/clients left
|
||||||
if (sizeof(v("locations"))) return rc;
|
if (sizeof(v("locations"))) return rc;
|
||||||
vDel("scheme");
|
vDel("scheme");
|
||||||
call_out(#'quit, 20, 1, variant);
|
call_out(#'quit, 20, 1, variant); //'
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2921,17 +2964,31 @@ static qFriends() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _flag_enable_module_microblogging
|
#ifdef _flag_enable_module_microblogging
|
||||||
qFriend(object snicker) {
|
qFriend(person) {
|
||||||
P3((">> qFriend(%O)\n", snicker))
|
P3((">> qFriend(%O)\n", person))
|
||||||
return member(friends, snicker);
|
if (IS_NEWBIE) return 0;
|
||||||
|
if (objectp(person)) person = person->qNameLower();
|
||||||
|
return member(ppl, person) && ppl[person][PPL_NOTIFY] >= PPL_NOTIFY_FRIEND;
|
||||||
}
|
}
|
||||||
|
|
||||||
qFollower(object snicker) {
|
qFollower(person) {
|
||||||
P3((">> qFollower(%O)\n", snicker))
|
P3((">> qFollower(%O)\n", person))
|
||||||
|
if (IS_NEWBIE) return 0;
|
||||||
foreach (string c : v("channels")) {
|
foreach (string c : v("channels")) {
|
||||||
object p = find_place(c);
|
object p = find_place(c);
|
||||||
P3((">>> c: %O, p: %O\n", c, p))
|
P3((">>> c: %O, p: %O\n", c, p))
|
||||||
if (p && p->qMember(snicker)) return 1;
|
if (p && p->qMember(person)) return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
qSubscription(target, without_channel) {
|
||||||
|
P3((">> qSubscription(%O, %O)\n", target, without_channel))
|
||||||
|
if (IS_NEWBIE) return 0;
|
||||||
|
unless (without_channel) return member(v("subscriptions"), target);
|
||||||
|
string c;
|
||||||
|
foreach (string t : v("subscriptions")) {
|
||||||
|
if (sscanf(t, target + "#%s", c)) return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3039,7 +3096,7 @@ void reset(int again) {
|
||||||
#if 0
|
#if 0
|
||||||
} else {
|
} else {
|
||||||
P3(("RESET: quitting %O\n", ME))
|
P3(("RESET: quitting %O\n", ME))
|
||||||
if (find_call_out(#'quit) == -1) quit();
|
if (find_call_out(#'quit) == -1) quit(); //'
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
} else { // hmm.. why do we still use reset(0) for this?
|
} else { // hmm.. why do we still use reset(0) for this?
|
||||||
|
|
|
@ -44,26 +44,36 @@ cmd(a, args, b, source, vars) {
|
||||||
P3((">> threads:cmd(%O, %O, %O, %O, %O)", a, args, b, source, vars))
|
P3((">> threads:cmd(%O, %O, %O, %O, %O)", a, args, b, source, vars))
|
||||||
// TODO: multiline-sachen irgendwie
|
// TODO: multiline-sachen irgendwie
|
||||||
mapping entry;
|
mapping entry;
|
||||||
|
array(mapping) entries;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
int id;
|
||||||
int num_entries;
|
int num_entries;
|
||||||
//unless (source) source = previous_object();
|
//unless (source) source = previous_object();
|
||||||
switch (a) {
|
switch (a) {
|
||||||
case "entries":
|
case "entries":
|
||||||
num_entries = sizeof(args) >= 2 ? to_int(args[1]) : DEFAULT_BACKLOG;
|
num_entries = sizeof(args) >= 2 ? to_int(args[1]) : DEFAULT_BACKLOG;
|
||||||
// _thread[<5..]
|
// _thread[<5..]
|
||||||
foreach( entry : _thread[<num_entries..] ) {
|
//foreach( entry : _thread[<num_entries..] ) {
|
||||||
sendmsg(source, "_list_thread_item",
|
entries = ({ });
|
||||||
"#[_number] - [_author][_sep][_thread]: [_text] ([_comments])",
|
for (i = sizeof(_thread) - 1; i >= 0; i--) {
|
||||||
([
|
unless (entry = _thread[i]) continue;
|
||||||
|
entries =
|
||||||
|
({ ([
|
||||||
"_sep" : strlen(entry["thread"]) ? " - " : "",
|
"_sep" : strlen(entry["thread"]) ? " - " : "",
|
||||||
"_thread" : entry["thread"],
|
"_thread" : entry["thread"],
|
||||||
"_text" : entry["text"],
|
"_text" : entry["text"],
|
||||||
"_author" : entry["author"],
|
"_author" : entry["author"],
|
||||||
"_date" : entry["date"],
|
"_date" : entry["date"],
|
||||||
"_comments": sizeof(entry["comments"]),
|
"_comments": sizeof(entry["comments"]),
|
||||||
"_number" : i++,
|
"_id" : i,
|
||||||
"_nick_place" : MYNICK ]) );
|
"_nick_place" : MYNICK,
|
||||||
|
]) }) + entries;
|
||||||
|
if (sizeof(entries) == num_entries) break;
|
||||||
}
|
}
|
||||||
|
foreach(entry : entries)
|
||||||
|
sendmsg(source, "_list_thread_entry",
|
||||||
|
"#[_id] - [_author][_sep][_thread]: [_text] ([_comments])",
|
||||||
|
entry);
|
||||||
return 1;
|
return 1;
|
||||||
case "entry":
|
case "entry":
|
||||||
unless (sizeof(args) > 1){
|
unless (sizeof(args) > 1){
|
||||||
|
@ -71,10 +81,18 @@ cmd(a, args, b, source, vars) {
|
||||||
"Usage: /entry <threadid>", ([ ]));
|
"Usage: /entry <threadid>", ([ ]));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int n = to_int(args[1]);
|
id = to_int(args[1]);
|
||||||
entry = _thread[n];
|
if (id >= 0 && id < sizeof(_thread))
|
||||||
sendmsg(source, "_list_thread_item",
|
entry = _thread[id];
|
||||||
"#[_number] [_author][_sep][_thread]: [_text] ([_comments])",
|
|
||||||
|
unless (entry) {
|
||||||
|
sendmsg(source, "_error_thread_invalid_entry",
|
||||||
|
"#[_id]: no such entry", (["_id": id]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendmsg(source, "_list_thread_entry",
|
||||||
|
"#[_id] [_author][_sep][_thread]: [_text] ([_comments])",
|
||||||
([
|
([
|
||||||
"_sep" : strlen(entry["thread"]) ? " - " : "",
|
"_sep" : strlen(entry["thread"]) ? " - " : "",
|
||||||
"_thread" : entry["thread"],
|
"_thread" : entry["thread"],
|
||||||
|
@ -82,7 +100,7 @@ cmd(a, args, b, source, vars) {
|
||||||
"_author" : entry["author"],
|
"_author" : entry["author"],
|
||||||
"_date" : entry["date"],
|
"_date" : entry["date"],
|
||||||
"_comments": sizeof(entry["comments"]),
|
"_comments": sizeof(entry["comments"]),
|
||||||
"_number" : n,
|
"_id" : id,
|
||||||
"_nick_place" : MYNICK ]) );
|
"_nick_place" : MYNICK ]) );
|
||||||
|
|
||||||
if (entry["comments"]) {
|
if (entry["comments"]) {
|
||||||
|
@ -92,6 +110,7 @@ cmd(a, args, b, source, vars) {
|
||||||
([
|
([
|
||||||
"_nick" : item["nick"],
|
"_nick" : item["nick"],
|
||||||
"_text" : item["text"],
|
"_text" : item["text"],
|
||||||
|
"_date": item["date"],
|
||||||
"_nick_place" : MYNICK ]) );
|
"_nick_place" : MYNICK ]) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,28 +121,38 @@ cmd(a, args, b, source, vars) {
|
||||||
"Usage: /thread <threadid> <title>", ([ ]));
|
"Usage: /thread <threadid> <title>", ([ ]));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return setSubject(to_int(args[1]), ARGS(2));
|
id = to_int(args[1]);
|
||||||
|
unless (setSubject(id, ARGS(2)))
|
||||||
|
sendmsg(source, "_error_thread_invalid_entry",
|
||||||
|
"#[_id]: no such entry", (["_id": id]));
|
||||||
|
|
||||||
|
return 1;
|
||||||
case "comment":
|
case "comment":
|
||||||
unless (sizeof(args) >= 2) {
|
unless (sizeof(args) >= 2) {
|
||||||
sendmsg(source, "_warning_usage_reply",
|
sendmsg(source, "_warning_usage_reply",
|
||||||
"Usage: /comment <threadid> <text>", ([ ]));
|
"Usage: /comment <threadid> <text>", ([ ]));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return addComment(ARGS(2), SNICKER, to_int(args[1]));
|
id = to_int(args[1]);
|
||||||
|
unless (addComment(ARGS(2), SNICKER, id))
|
||||||
|
sendmsg(source, "_error_thread_invalid_entry",
|
||||||
|
"#[_id]: no such entry", (["_id": id]));
|
||||||
|
return 1;
|
||||||
case "blog":
|
case "blog":
|
||||||
case "submit":
|
case "submit":
|
||||||
case "addentry":
|
case "addentry":
|
||||||
unless (canPost(SNICKER)) return;
|
unless (canPost(SNICKER)) return 0;
|
||||||
unless (sizeof(args) >= 1) {
|
unless (sizeof(args) >= 1) {
|
||||||
sendmsg(source, "_warning_usage_submit",
|
sendmsg(source, "_warning_usage_submit",
|
||||||
"Usage: /submit <text>", ([ ]));
|
"Usage: /submit <text>", ([ ]));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return addEntry(ARGS(1), SNICKER);
|
addEntry(ARGS(1), SNICKER);
|
||||||
|
return 1;
|
||||||
// TODO: append fuer multiline-sachen
|
// TODO: append fuer multiline-sachen
|
||||||
#if 0
|
#if 0
|
||||||
case "iterator":
|
case "iterator":
|
||||||
unless (canPost(SNICKER)) return;
|
unless (canPost(SNICKER)) return 0;
|
||||||
sendmsg(source, "_notice_thread_iterator",
|
sendmsg(source, "_notice_thread_iterator",
|
||||||
"[_iterator] blog entries have been requested "
|
"[_iterator] blog entries have been requested "
|
||||||
"since creation.", ([
|
"since creation.", ([
|
||||||
|
@ -133,19 +162,18 @@ cmd(a, args, b, source, vars) {
|
||||||
]) );
|
]) );
|
||||||
return 1;
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
|
case "unblog":
|
||||||
case "deblog":
|
case "deblog":
|
||||||
case "delentry":
|
case "delentry":
|
||||||
unless (canPost(SNICKER)) return;
|
unless (canPost(SNICKER)) return 0;
|
||||||
// ist das ein typecheck ob args ein int is?
|
id = to_int(args[1]);
|
||||||
if (sizeof(regexp( ({ args[1] }) , "^[0-9][0-9]*$"))) {
|
if (delEntry(id, source, vars)) {
|
||||||
unless (delEntry(to_int(args[1]), source, vars)) {
|
sendmsg(source, "_notice_thread_entry_removed",
|
||||||
sendmsg(source,"_error_invalid_thread_item",
|
"Entry #[_id] has been removed.",
|
||||||
"There is no such thread item.", ([ ]));
|
([ "_id" : id ]) );
|
||||||
} else {
|
} else {
|
||||||
sendmsg(source, "_notice_thread_item_removed",
|
sendmsg(source, "_error_thread_invalid_entry",
|
||||||
"Thread item [_number] has been removed.",
|
"#[_id]: no such entry", (["_id": id]));
|
||||||
([ "_number" : ARGS(1) ]) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -192,12 +220,12 @@ allEntries(source) {
|
||||||
unless (sizeof(entries)) return 1;
|
unless (sizeof(entries)) return 1;
|
||||||
|
|
||||||
foreach (ar : entries) {
|
foreach (ar : entries) {
|
||||||
sendmsg(source, "_message_", "([_number]) \"[_topic]\", [_author]", ([ // ??
|
sendmsg(source, "_message_", "([_id]) \"[_topic]\", [_author]", ([ // ??
|
||||||
"_topic" : ar["topic"],
|
"_topic" : ar["topic"],
|
||||||
"_text" : ar["text"],
|
"_text" : ar["text"],
|
||||||
"_author" : ar["author"],
|
"_author" : ar["author"],
|
||||||
"_date" : ar["date"],
|
"_date" : ar["date"],
|
||||||
"_number" : i++,
|
"_id" : i++,
|
||||||
"_nick_place" : MYNICK ]) );
|
"_nick_place" : MYNICK ]) );
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -224,13 +252,9 @@ _notice_thread
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
setSubject(num, thread) {
|
setSubject(id, thread) {
|
||||||
mapping* entries;
|
unless (_thread && id >= 0 && id <= sizeof(_thread) && _thread[id]) return 0;
|
||||||
|
_thread[id]["thread"] = thread;
|
||||||
entries = _thread || ({ });
|
|
||||||
// TODO: das hier muss sicherer
|
|
||||||
entries[num]["thread"] = thread;
|
|
||||||
_thread = entries;
|
|
||||||
save();
|
save();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -238,63 +262,70 @@ setSubject(num, thread) {
|
||||||
// TODO: topic uebergeben
|
// TODO: topic uebergeben
|
||||||
addEntry(text, unick, thread) {
|
addEntry(text, unick, thread) {
|
||||||
mapping* entries;
|
mapping* entries;
|
||||||
mapping newentry = ([ "text" : text,
|
mapping newentry = ([
|
||||||
|
"text" : text,
|
||||||
"author" : unick,
|
"author" : unick,
|
||||||
"date" : isotime(ctime(), 1),
|
"date" : time(),
|
||||||
"thread" : thread || "",
|
"thread" : thread || "",
|
||||||
]);
|
]);
|
||||||
entries = _thread || ({ });
|
entries = _thread || ({ });
|
||||||
entries += ({ newentry });
|
entries += ({ newentry });
|
||||||
|
int id = sizeof(entries) - 1;
|
||||||
_thread = entries;
|
_thread = entries;
|
||||||
save();
|
save();
|
||||||
castmsg(ME, "_notice_thread_item",
|
castmsg(ME, "_notice_thread_entry",
|
||||||
"[_nick] adds an entry in \"[_thread]\" of [_nick_place].", ([
|
thread ?
|
||||||
"_entry" : text,
|
"[_nick] adds an entry in [_nick_place] (#[_id]): \"[_thread]\":\n[_entry]" :
|
||||||
"_thread" : thread,
|
"[_nick] adds an entry in [_nick_place] (#[_id]):\n[_entry]",
|
||||||
"_nick" : unick,
|
([
|
||||||
]) );
|
"_entry": text,
|
||||||
|
"_id": id,
|
||||||
|
"_thread": thread,
|
||||||
|
"_nick": unick,
|
||||||
|
]));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
addComment(text, unick, entry_id) {
|
addComment(text, unick, id) {
|
||||||
mapping entry;
|
mapping entry;
|
||||||
|
unless (_thread && id >= 0 && id <= sizeof(_thread) && _thread[id]) return 0;
|
||||||
|
|
||||||
if (sizeof(_thread) > entry_id) {
|
entry = _thread[id];
|
||||||
entry = _thread[entry_id];
|
|
||||||
unless (entry["comments"]) {
|
unless (entry["comments"]) {
|
||||||
entry["comments"] = ({ });
|
entry["comments"] = ({ });
|
||||||
}
|
}
|
||||||
entry["comments"] += ({ (["text" : text, "nick" : unick ]) });
|
int date = time();
|
||||||
|
entry["comments"] += ({ (["text" : text, "nick" : unick, "date": date ]) });
|
||||||
// vSet("entries", entries);
|
// vSet("entries", entries);
|
||||||
|
save();
|
||||||
castmsg(ME, "_notice_thread_comment",
|
castmsg(ME, "_notice_thread_comment",
|
||||||
"[_nick] adds a comment in \"[_thread]\" of [_nick_place].", ([
|
entry["thread"] && strlen(entry["thread"]) ?
|
||||||
|
"[_nick] adds a comment to \"[_thread]\" (entry #[_id]) of [_nick_place]:\n[_comment]" :
|
||||||
|
"[_nick] adds a comment to entry #[_id] of [_nick_place]:\n[_comment]",
|
||||||
|
([
|
||||||
"_entry" : entry["text"],
|
"_entry" : entry["text"],
|
||||||
|
"_id" : id,
|
||||||
"_thread" : entry["thread"],
|
"_thread" : entry["thread"],
|
||||||
"_comment" : text,
|
"_comment" : text,
|
||||||
"_nick" : unick,
|
"_nick" : unick,
|
||||||
]) );
|
"_date": date,
|
||||||
save();
|
]));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delEntry(int number, source, vars) {
|
delEntry(int id, source, vars) {
|
||||||
|
unless (_thread && id >= 0 && id <= sizeof(_thread) && _thread[id]) return 0;
|
||||||
|
|
||||||
array(string) entries, authors, a;
|
array(string) entries, authors, a;
|
||||||
string unick;
|
string unick;
|
||||||
int size;
|
|
||||||
|
|
||||||
entries = _thread || ({ });
|
|
||||||
|
|
||||||
unless (size = sizeof(entries)) return 0;
|
|
||||||
if (number >= size) return 0;
|
|
||||||
|
|
||||||
if (canPost(unick = lower_case(SNICKER))) {
|
if (canPost(unick = lower_case(SNICKER))) {
|
||||||
unless (lower_case(entries[number]["author"]) == unick) return 0;
|
unless (lower_case(_thread[id]["author"]) == unick) return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_thread = entries[0..number-1] + entries[number+1..];
|
//_thread = _thread[0..id-1] + _thread[id+1..];
|
||||||
//_thread[number] = 0;
|
// set to 0 instead so entry ids won't change
|
||||||
|
_thread[id] = 0;
|
||||||
save();
|
save();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -438,7 +469,7 @@ rssExport(last) {
|
||||||
"\t<title>"+ _thread[i]["thread"] +"</title>\n"
|
"\t<title>"+ _thread[i]["thread"] +"</title>\n"
|
||||||
"\t<link>http://" + SERVER_HOST + ":33333" + webact + "?comments=" + i + "</link>\n"
|
"\t<link>http://" + SERVER_HOST + ":33333" + webact + "?comments=" + i + "</link>\n"
|
||||||
"\t<description>" + _thread[i]["text"] + "</description>\n"
|
"\t<description>" + _thread[i]["text"] + "</description>\n"
|
||||||
"\t<dc:date>" + _thread[i]["date"] + "</dc:date>\n"
|
"\t<dc:date>" + isotime(ctime(_thread[i]["date"]), 1) + "</dc:date>\n"
|
||||||
"\t<dc:creator>" + _thread[i]["author"] + "</dc:creator>\n");
|
"\t<dc:creator>" + _thread[i]["author"] + "</dc:creator>\n");
|
||||||
write("</item>\n");
|
write("</item>\n");
|
||||||
}
|
}
|
||||||
|
@ -446,7 +477,6 @@ rssExport(last) {
|
||||||
write("</rdf:RDF>\n");
|
write("</rdf:RDF>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
jscriptExport(last) {
|
jscriptExport(last) {
|
||||||
mapping item;
|
mapping item;
|
||||||
string buf = "";
|
string buf = "";
|
||||||
|
@ -460,9 +490,9 @@ jscriptExport(last) {
|
||||||
"}\n\n"
|
"}\n\n"
|
||||||
"document.blogentries = new Array(\n");
|
"document.blogentries = new Array(\n");
|
||||||
foreach (item : _thread[<last..]) {
|
foreach (item : _thread[<last..]) {
|
||||||
buf += "new Entry(\"" + item["thread"] + "\", \""
|
if (item) buf += "new Entry(\"" + item["thread"] + "\", \""
|
||||||
+ item["author"] + "\", \""
|
+ item["author"] + "\", \""
|
||||||
+ item["date"] + "\", \""
|
+ isotime(ctime(item["date"]), 1) + "\", \""
|
||||||
+ item["text"] + "\"),\n";
|
+ item["text"] + "\"),\n";
|
||||||
}
|
}
|
||||||
buf = buf[..<3] + ");";
|
buf = buf[..<3] + ");";
|
||||||
|
@ -482,7 +512,7 @@ displayMain(last) {
|
||||||
write("<table><tr><td class='blogthread'>" + _thread[i]["thread"]
|
write("<table><tr><td class='blogthread'>" + _thread[i]["thread"]
|
||||||
+ "</td>"
|
+ "</td>"
|
||||||
"<td class='blogauthor'>" + _thread[i]["author"] + "</td>"
|
"<td class='blogauthor'>" + _thread[i]["author"] + "</td>"
|
||||||
"<td class='blogdate'>" + _thread[i]["date"] + "</td></tr>"
|
"<td class='blogdate'>" + isotime(ctime(_thread[i]["date"]), 1) + "</td></tr>"
|
||||||
"<tr><td class='blogtext' colspan=3>" + _thread[i]["text"]
|
"<tr><td class='blogtext' colspan=3>" + _thread[i]["text"]
|
||||||
+ "</td></tr>"
|
+ "</td></tr>"
|
||||||
"<tr><td colspan=3 align='right'>");
|
"<tr><td colspan=3 align='right'>");
|
||||||
|
@ -492,22 +522,24 @@ displayMain(last) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
htMain(last) {
|
htmlEntries(array(mapping) entries, int last, int js, string chan, string submit) {
|
||||||
int i;
|
P3((">> threads:htmlentries(%O, %O)\n", entries, last))
|
||||||
int len;
|
|
||||||
string t;
|
string t;
|
||||||
string ht =
|
string ht = "";
|
||||||
"<script type='text/javascript'>"
|
if (js) ht +=
|
||||||
"function toggle(e) { e = document.getElementById(e); e.className = e.className.match('hidden') ? e.className.replace(/ *hidden/, '') : e.className + ' hidden'; }"
|
"<script type='text/javascript'>\n"
|
||||||
"</script>";
|
"function toggle(e) { e = document.getElementById(e); e.className = e.className.match('hidden') ? e.className.replace(/ *hidden/, '') : e.className + ' hidden'; }\n"
|
||||||
|
"</script>\n";
|
||||||
len = sizeof(_thread);
|
string id_prefix = chan ? chan + "-" : "";
|
||||||
if (last > len) last = len;
|
|
||||||
|
|
||||||
|
mapping item;
|
||||||
|
int n = 0;
|
||||||
|
int id;
|
||||||
// reverse order
|
// reverse order
|
||||||
for (i = len-1; i >= len - last; i--) {
|
for (id = sizeof(entries) - 1; id >= 0; id--) {
|
||||||
P3((">>> _thread[%O]: %O\n", i, _thread[i]))
|
P3((">>> entries[%O]: %O\n", id, entries[id]))
|
||||||
mapping item = _thread[i];
|
unless (item = entries[id]) continue;
|
||||||
|
|
||||||
t = htquote(item["text"]);
|
t = htquote(item["text"]);
|
||||||
t = replace(t, "\n", "<br>\n");
|
t = replace(t, "\n", "<br>\n");
|
||||||
t = replace(t, "<", "<");
|
t = replace(t, "<", "<");
|
||||||
|
@ -516,35 +548,70 @@ htMain(last) {
|
||||||
string c = "";
|
string c = "";
|
||||||
if (item["comments"])
|
if (item["comments"])
|
||||||
foreach(mapping comment : item["comments"])
|
foreach(mapping comment : item["comments"])
|
||||||
c += "<div class='comment'><span class='comment-author'>" + comment["nick"] + "</span>: <span class='comment-text'>" + comment["text"] + "</span></div>\n";
|
c += "<div class='comment' title='" + isotime(ctime(comment["date"]), 1) + "'><span class='comment-author'>" + comment["nick"] + "</span>: <span class='comment-text'>" + comment["text"] + "</span></div>\n";
|
||||||
|
|
||||||
ht += "<div class='entry'>\n"
|
ht +=
|
||||||
|
"<div class='entry'>\n"
|
||||||
"<div class='title'>\n"
|
"<div class='title'>\n"
|
||||||
|
"<span class='id'>#" + id + "</span> - \n"
|
||||||
"<span class='author'>" + item["author"] + "</span>\n"
|
"<span class='author'>" + item["author"] + "</span>\n"
|
||||||
|
+ (item["thread"] && strlen(item["thread"]) ? " - " : "") +
|
||||||
"<span class='subject'>" + htquote(item["thread"]) + "</span>\n"
|
"<span class='subject'>" + htquote(item["thread"]) + "</span>\n"
|
||||||
"</div>\n"
|
"</div>\n"
|
||||||
"<div class='body'>\n"
|
"<div class='body'>\n"
|
||||||
"<div class='text'>" + t + "</div>\n"
|
"<div class='text'>" + t + "</div>\n"
|
||||||
"<div id='comments-" + i + "' class='comments hidden'>" + c + "</div>\n"
|
"<div id='comments-" + id_prefix + id + "' class='comments hidden'>" + c +
|
||||||
|
(submit && strlen(submit) ?
|
||||||
|
"<div class='comment-submit'>"
|
||||||
|
"<textarea autocomplete='off'></textarea>"
|
||||||
|
//FIXME: cmd is executed twice, because after a set-cookie it's parsed again
|
||||||
|
"<input type='button' value='Comment' onclick=\"cmd('comment " + id + " '+ this.previousSibling.value, '" + submit + "')\">"
|
||||||
|
"</div>" : "") +
|
||||||
|
"</div>\n"
|
||||||
"</div>\n"
|
"</div>\n"
|
||||||
"<div class='footer'>\n"
|
"<div class='footer'>\n"
|
||||||
"<span class='date'>" + item["date"] + "</span>\n"
|
"<span class='date'>" + isotime(ctime(item["date"]), 1) + "</span>\n"
|
||||||
"<span class='comments-link'>"
|
"<span class='comments-link'>"
|
||||||
"<a onclick=\"toggle('comments-"+i+"')\">" + sizeof(item["comments"]) + " comments</a>"
|
"<a onclick=\"toggle('comments-" + id_prefix + id + "')\">" + sizeof(item["comments"]) + " comments</a>"
|
||||||
"</span>\n"
|
"</span>\n"
|
||||||
"</div>\n"
|
"</div>\n"
|
||||||
"</div>\n";
|
"</div>\n";
|
||||||
|
if (last && ++n >= last) break;
|
||||||
}
|
}
|
||||||
|
P3((">>> ht: %O\n", ht))
|
||||||
return "<div class='threads'>" + ht + "</div>";
|
return "<div class='threads'>" + ht + "</div>";
|
||||||
}
|
}
|
||||||
|
|
||||||
htComments(data) {
|
htMain(int last) {
|
||||||
|
return htmlEntries(_thread, last, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
entries(int last) {
|
||||||
|
array(mapping) entries = ({ });
|
||||||
|
int n = 0;
|
||||||
|
int id;
|
||||||
|
// reverse order
|
||||||
|
for (id = sizeof(_thread) - 1; id >= 0; id--) {
|
||||||
|
P3((">>> _thread[%O]: %O\n", id, _thread[id]))
|
||||||
|
unless (_thread[id]) continue;
|
||||||
|
entries += ({ _thread[id] });
|
||||||
|
if (++n >= last) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonEntries(int last) {
|
||||||
|
return make_json(entries(last));
|
||||||
|
}
|
||||||
|
|
||||||
|
htComments(entry) {
|
||||||
mapping item;
|
mapping item;
|
||||||
string ht = "";
|
string ht = "";
|
||||||
|
|
||||||
write("<b>" + data["author"] + "</b>: " + data["text"] + "<br><br>\n");
|
write("<b>" + entry["author"] + "</b>: " + entry["text"] + "<br><br>\n");
|
||||||
if (data["comments"]) {
|
if (entry["comments"]) {
|
||||||
foreach(item : data["comments"]) {
|
foreach(item : entry["comments"]) {
|
||||||
ht += "<b>" + item["nick"] + "</b>: " + item["text"] + "<br>\n";
|
ht += "<b>" + item["nick"] + "</b>: " + item["text"] + "<br>\n";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -557,8 +624,8 @@ displayMain(last) {
|
||||||
write(htMain(last));
|
write(htMain(last));
|
||||||
}
|
}
|
||||||
|
|
||||||
displayComments(data) {
|
displayComments(entry) {
|
||||||
write(htComments(data));
|
write(htComments(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
nntpget(cmd, args) {
|
nntpget(cmd, args) {
|
||||||
|
@ -573,13 +640,14 @@ case "ARTICLE":
|
||||||
i = to_int(args) - 1;
|
i = to_int(args) - 1;
|
||||||
P2(("i is: %d\n", i))
|
P2(("i is: %d\n", i))
|
||||||
P2(("entries: %O\n", _thread))
|
P2(("entries: %O\n", _thread))
|
||||||
|
unless (_thread && i >= 0 && i <= sizeof(_thread) && _thread[i]) break;
|
||||||
item = _thread[i];
|
item = _thread[i];
|
||||||
write(S("220 %d <%s%d@%s> article\n",
|
write(S("220 %d <%s%d@%s> article\n",
|
||||||
i + 1, MYNICK, i + 1, SERVER_HOST));
|
i + 1, MYNICK, i + 1, SERVER_HOST));
|
||||||
write(S("From: %s\n", item["author"]));
|
write(S("From: %s\n", item["author"]));
|
||||||
write(S("Newsgroups: %s\n", MYNICK));
|
write(S("Newsgroups: %s\n", MYNICK));
|
||||||
write(S("Subject: %s\n", item["thread"]));
|
write(S("Subject: %s\n", item["thread"]));
|
||||||
write(S("Date: %s\n", item["date"]));
|
write(S("Date: %s\n", isotime(ctime(item["date"]), 1)));
|
||||||
write(S("Xref: %s %s:%d\n", SERVER_HOST, MYNICK, i + 1));
|
write(S("Xref: %s %s:%d\n", SERVER_HOST, MYNICK, i + 1));
|
||||||
write(S("Message-ID: <%s$%d@%s>\n", MYNICK, i+1, SERVER_HOST));
|
write(S("Message-ID: <%s$%d@%s>\n", MYNICK, i+1, SERVER_HOST));
|
||||||
write("\n");
|
write("\n");
|
||||||
|
@ -592,11 +660,11 @@ case "GROUP":
|
||||||
break;
|
break;
|
||||||
case "XOVER":
|
case "XOVER":
|
||||||
for (i = 0; i < sizeof(_thread); i++) {
|
for (i = 0; i < sizeof(_thread); i++) {
|
||||||
item = _thread[i];
|
unless(item = _thread[i]) continue;
|
||||||
P2(("item: %O\n", item))
|
P2(("item: %O\n", item))
|
||||||
write(S("%d\t%s\t%s\t%s <%s%d@%s>\t1609\t22\tXref: news.t-online.com\t%s:%d\n",
|
write(S("%d\t%s\t%s\t%s <%s%d@%s>\t1609\t22\tXref: news.t-online.com\t%s:%d\n",
|
||||||
i+1, item["thread"],
|
i+1, item["thread"],
|
||||||
item["author"], item["date"],
|
item["author"], isotime(ctime(item["date"]), 1),
|
||||||
MYNICK, i+1,
|
MYNICK, i+1,
|
||||||
SERVER_HOST, MYNICK, i+1));
|
SERVER_HOST, MYNICK, i+1));
|
||||||
}
|
}
|
||||||
|
@ -633,3 +701,11 @@ displayFooter() {
|
||||||
canPost(snicker) {
|
canPost(snicker) {
|
||||||
return qAide(snicker);
|
return qAide(snicker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mayLog(mc) {
|
||||||
|
return abbrev("_notice_thread", mc) || abbrev("_message", mc);
|
||||||
|
}
|
||||||
|
|
||||||
|
numEntries() {
|
||||||
|
return sizeof(_thread);
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,11 @@
|
||||||
|
|
||||||
#define BLAME "!configuration"
|
#define BLAME "!configuration"
|
||||||
#define DONT_REWRITE_NICKS
|
#define DONT_REWRITE_NICKS
|
||||||
|
#define PLACE_HISTORY
|
||||||
|
#define PLACE_OWNED
|
||||||
|
#define HISTORY_GLIMPSE 12
|
||||||
|
|
||||||
|
#include <uniform.h>
|
||||||
|
|
||||||
inherit NET_PATH "place/threads";
|
inherit NET_PATH "place/threads";
|
||||||
|
|
||||||
|
@ -17,6 +22,7 @@ load(name, keep) {
|
||||||
|
|
||||||
sscanf(name, "~%s#%s", owner, channel);
|
sscanf(name, "~%s#%s", owner, channel);
|
||||||
vSet("owners", ([ owner: 0 ]));
|
vSet("owners", ([ owner: 0 ]));
|
||||||
|
vSet("privacy", "private");
|
||||||
|
|
||||||
vSet("_restrict_invitation", BLAME);
|
vSet("_restrict_invitation", BLAME);
|
||||||
vSet("_filter_conversation", BLAME);
|
vSet("_filter_conversation", BLAME);
|
||||||
|
@ -27,9 +33,11 @@ load(name, keep) {
|
||||||
enter(source, mc, data, vars) {
|
enter(source, mc, data, vars) {
|
||||||
P3((">> userthreads:enter(%O, %O, %O, %O)\n", source, mc, data, vars))
|
P3((">> userthreads:enter(%O, %O, %O, %O)\n", source, mc, data, vars))
|
||||||
object p = summon_person(owner, NET_PATH "user");
|
object p = summon_person(owner, NET_PATH "user");
|
||||||
string src = psyc_name(source);
|
string src = objectp(source) ? psyc_name(source) : source;
|
||||||
|
|
||||||
unless (p && (p == source || qAide(src) || p->qFriend(source) || p->qFollower(source))) {
|
unless (v("privacy") == "public" ||
|
||||||
|
(p && (p == source || qAide(src) || (objectp(source) && qAide(source->qNameLower()))
|
||||||
|
|| p->qFriend(source) || p->qFollower(source)))) {
|
||||||
sendmsg(source, "_error_place_enter_necessary_invitation",
|
sendmsg(source, "_error_place_enter_necessary_invitation",
|
||||||
"[_nick_place] can only be entered upon invitation.",
|
"[_nick_place] can only be entered upon invitation.",
|
||||||
([ "_nick_place" : qName() ]) );
|
([ "_nick_place" : qName() ]) );
|
||||||
|
@ -49,17 +57,90 @@ enter(source, mc, data, vars) {
|
||||||
return ::enter(source, mc, data, vars);
|
return ::enter(source, mc, data, vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd(a, args, b, source, vars) {
|
_request_add(source, mc, data, vars, b) {
|
||||||
P3((">> threads:cmd(%O, %O, %O, %O, %O)", a, args, b, source, vars))
|
P3((">> userthreads:_request_add(%O, %O, %O, %O, %O)\n", source, mc, data, vars, b))
|
||||||
|
unless (vars["_person"]) {
|
||||||
switch (a) {
|
sendmsg(source, "_warning_usage_add", "Usage: /add <person>", ([ ]));
|
||||||
case "add": // or similar
|
return 1;
|
||||||
// add follower to this channel, TODO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ::cmd(a, args, b, source, vars);
|
object p = summon_person(owner, NET_PATH "user");
|
||||||
|
object target = summon_person(vars["_person"], NET_PATH "user");
|
||||||
|
string ni;
|
||||||
|
if (objectp(target)) {
|
||||||
|
ni = target->qName();
|
||||||
|
} else {
|
||||||
|
target = vars["_person"];
|
||||||
|
mixed *u = parse_uniform(target);
|
||||||
|
if (u) ni = u[UNick];
|
||||||
|
}
|
||||||
|
|
||||||
|
unless (ni && p && (p->qFriend(target) || p->qFollower(target))) {
|
||||||
|
sendmsg(source, "_error_add",
|
||||||
|
"Error: [_person] is not a friend or follower.", ([ "_person": vars["_person"]]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
string _mc = "_notice_place_enter_automatic_subscription_follow";
|
||||||
|
sendmsg(target, _mc, "You're now following [_nick_place].", (["_nick_place" : qName()]), source);
|
||||||
|
//insert_member(target, mc, 0, (["_nick": ni]), ni);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_request_remove(source, mc, data, vars, b) {
|
||||||
|
P3((">> userthreads:_request_remove(%O, %O, %O, %O, %O)\n", source, mc, data, vars, b))
|
||||||
|
unless (vars["_person"]) {
|
||||||
|
sendmsg(source, "_warning_usage_remove", "Usage: /remove <person>", ([ ]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
object p = summon_person(owner, NET_PATH "user");
|
||||||
|
object target = summon_person(vars["_person"], NET_PATH "user") || vars["_person"];
|
||||||
|
|
||||||
|
unless (p && (qMember(target) || p->qFriend(target) || p->qFollower(target))) {
|
||||||
|
sendmsg(source, "_error_add",
|
||||||
|
"Can't remove: [_person] is not a friend or follower.", ([ "_person": vars["_person"]]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
string _mc = "_notice_place_leave_automatic_subscription_follow";
|
||||||
|
sendmsg(target, _mc, "You're no longer following [_nick_place].", (["_nick_place" : qName()]), source);
|
||||||
|
remove_member(target);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set privacy: private or public
|
||||||
|
// - private: only friends & invited people can enter (default)
|
||||||
|
// - public: anyone can enter
|
||||||
|
_request_privacy(source, mc, data, vars, b) {
|
||||||
|
P3((">> userthreads:_request_privace(%O, %O, %O, %O, %O)\n", source, mc, data, vars, b))
|
||||||
|
string p = vars["_privacy"];
|
||||||
|
if (p == "public" || p == "private") {
|
||||||
|
vSet("privacy", p);
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
sendmsg(source, "_status_privacy", "Privacy is: [_privacy].", (["_privacy": v("privacy")]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
htMain(int last) {
|
||||||
|
return htmlEntries(_thread, last, 1, channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
canPost(snicker) {
|
canPost(snicker) {
|
||||||
return qOwner(snicker);
|
return qOwner(snicker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isPublic() {
|
||||||
|
return vQuery("privacy") == "public";
|
||||||
|
}
|
||||||
|
|
||||||
|
qChannel() {
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
qHistoryGlimpse() {
|
||||||
|
return HISTORY_GLIMPSE;
|
||||||
|
}
|
||||||
|
|
|
@ -158,7 +158,7 @@ htDescription(anonymous, query, headers, qs, variant, vars) {
|
||||||
#else
|
#else
|
||||||
int doTalk = 0;
|
int doTalk = 0;
|
||||||
|
|
||||||
P3(("htDescription for %O showing %O or %O\n", qs, vars, descvars))
|
P3(("htDescription in %O for %O showing %O or %O\n", ME, qs, vars, descvars))
|
||||||
if (query) sTextPath(query["layout"] || v("layout"),
|
if (query) sTextPath(query["layout"] || v("layout"),
|
||||||
query["lang"] || v("language"), "html");
|
query["lang"] || v("language"), "html");
|
||||||
else sTextPath(v("layout"), v("language"), "html");
|
else sTextPath(v("layout"), v("language"), "html");
|
||||||
|
@ -285,13 +285,53 @@ htDescription(anonymous, query, headers, qs, variant, vars) {
|
||||||
//
|
//
|
||||||
|
|
||||||
# ifdef _flag_enable_module_microblogging
|
# ifdef _flag_enable_module_microblogging
|
||||||
object u = find_place("~" + nick + "#follow"); //TODO
|
mapping channels;
|
||||||
string updates = objectp(u) ? u->htMain(10) : "";
|
string htchannels;
|
||||||
|
if (vars["_channels"] && (channels = parse_json(vars["_channels"]))) {
|
||||||
|
P3((">>> channels: %O\n", channels))
|
||||||
|
htchannels =
|
||||||
|
"<script type='text/javascript'>\n"
|
||||||
|
"function selectTab(parent, id) {"
|
||||||
|
"var tabs = document.getElementById(parent);"
|
||||||
|
"var tab = tabs.firstChild;"
|
||||||
|
"while (tab) {"
|
||||||
|
"tab.className = (tab.id == parent+'-'+id) ? 'selected' : '';"
|
||||||
|
"tab = tab.nextSibling;"
|
||||||
|
"}"
|
||||||
|
"}\n"
|
||||||
|
"function switchTab(id) {"
|
||||||
|
"selectTab('tabs', id);"
|
||||||
|
"selectTab('tab-contents', id);"
|
||||||
|
"}\n"
|
||||||
|
"</script>\n";
|
||||||
|
|
||||||
|
string tabs = "";
|
||||||
|
string contents = "";
|
||||||
|
int first = 1;
|
||||||
|
object threads = clone_object(NET_PATH "place/threads");
|
||||||
|
|
||||||
|
foreach (string channel, array(mapping) entries : channels) {
|
||||||
|
unless (sizeof(entries) > 0) continue;
|
||||||
|
tabs +=
|
||||||
|
"<a id='tabs-" + channel + "' onclick=\"switchTab('" + channel + "')\" "
|
||||||
|
+ (first ? "class='selected'" : "") + ">#" + channel + "</a>\n";
|
||||||
|
contents +=
|
||||||
|
"<div id='tab-contents-" + channel + "' "
|
||||||
|
+ (first ? "class='selected'" : "") + ">" + threads->htmlEntries(entries, 0, first, channel, anonymous ? "" : vars["_identification"] + "#" + channel) + "</div>\n";
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first) htchannels = "";
|
||||||
|
else htchannels +=
|
||||||
|
"<div id='tabs' class='tabs'>\n" + tabs + "</div>\n"
|
||||||
|
"<div id='tab-contents' class='tab-contents'>\n" + contents + "</div>\n";
|
||||||
|
}
|
||||||
# endif
|
# endif
|
||||||
return psyctext(page, vars + ([
|
return psyctext(page, vars + ([
|
||||||
"_FORM_start" : "\
|
"_FORM_start" : "\
|
||||||
<form class=\"Pef\" name=\"Pef\" action=\"\">\n\
|
<form class=\"Pef\" name=\"Pef\" action=\"\">\n\
|
||||||
<input type=hidden name=cmd value=\"\">\n",
|
<input type=\"hidden\" name=\"cmd\" value=\"\">\n\
|
||||||
|
<input type=\"hidden\" name=\"dest\" value=\"\">\n",
|
||||||
"_QUERY_STRING" : qs || "",
|
"_QUERY_STRING" : qs || "",
|
||||||
"_HTML_photo" : foto,
|
"_HTML_photo" : foto,
|
||||||
"_nick_me" : MYNICK,
|
"_nick_me" : MYNICK,
|
||||||
|
@ -299,7 +339,7 @@ htDescription(anonymous, query, headers, qs, variant, vars) {
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
# ifdef _flag_enable_module_microblogging
|
# ifdef _flag_enable_module_microblogging
|
||||||
+ updates
|
+ htchannels
|
||||||
# endif
|
# endif
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2430,6 +2430,14 @@ friend(rm, entity, ni, trustee) {
|
||||||
insert_member(entity);
|
insert_member(entity);
|
||||||
else
|
else
|
||||||
insert_member(entity, parse_uniform(entity, 1)[URoot]);
|
insert_member(entity, parse_uniform(entity, 1)[URoot]);
|
||||||
|
|
||||||
|
#ifdef _flag_enable_module_microblogging
|
||||||
|
string uni = psyc_name(ME);
|
||||||
|
sendmsg(entity, "_notice_place_enter_automatic_subscription_follow",
|
||||||
|
"Following [_nick_place]", (["_nick": MYNICK, "_nick_place": uni + "#follow" ]));
|
||||||
|
sendmsg(entity, "_notice_place_enter_automatic_subscription_follow",
|
||||||
|
"Following [_nick_place]", (["_nick": MYNICK, "_nick_place": uni + "#friends" ]));
|
||||||
|
#endif
|
||||||
// this used to imply a symmetric request for
|
// this used to imply a symmetric request for
|
||||||
// friendship, but we prefer to make it an
|
// friendship, but we prefer to make it an
|
||||||
// informational message instead. the protocol
|
// informational message instead. the protocol
|
||||||
|
@ -3377,13 +3385,16 @@ subscribe(how, arg, quiet) {
|
||||||
// be like implementing HTTPs cookies..
|
// be like implementing HTTPs cookies..
|
||||||
// if (arg = placeRequest(arg, "_request_enter_subscribe"))
|
// if (arg = placeRequest(arg, "_request_enter_subscribe"))
|
||||||
// sups += ([ objectp(arg) ? arg->qName() : arg ]);
|
// sups += ([ objectp(arg) ? arg->qName() : arg ]);
|
||||||
if (placeRequest(arg,
|
if (find_place(arg)) {
|
||||||
|
// don't join to temporarily subscribed places when not online
|
||||||
|
if (ONLINE || how == SUBSCRIBE_PERMANENT)
|
||||||
|
placeRequest(arg,
|
||||||
#ifdef SPEC
|
#ifdef SPEC
|
||||||
"_request_context_enter_subscribe",
|
"_request_context_enter_subscribe",
|
||||||
#else
|
#else
|
||||||
"_request_enter_subscribe",
|
"_request_enter_subscribe",
|
||||||
#endif
|
#endif
|
||||||
0, quiet)) {
|
0, quiet);
|
||||||
sups += ([ arg : how ]);
|
sups += ([ arg : how ]);
|
||||||
} else return 1;
|
} else return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ body.threads,
|
||||||
padding: 4;
|
padding: 4;
|
||||||
border: 1px solid #f33;
|
border: 1px solid #f33;
|
||||||
}
|
}
|
||||||
|
.comment-submit textarea, .comment-submit input,
|
||||||
.Pe form input,select,textarea {
|
.Pe form input,select,textarea {
|
||||||
background: black;
|
background: black;
|
||||||
color: #f33;
|
color: #f33;
|
||||||
|
@ -79,12 +80,17 @@ body.threads,
|
||||||
|
|
||||||
.entry .body {
|
.entry .body {
|
||||||
background: black;
|
background: black;
|
||||||
padding: 5px;
|
padding: 0.4em 0.4em 0 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entry .body .text,
|
||||||
|
.entry .body .comment-submit {
|
||||||
|
padding-bottom: 0.4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry .body .comment {
|
.entry .body .comment {
|
||||||
margin: 0.5em 1em 0;
|
margin: 0.2em 1em;
|
||||||
padding: 2px;
|
padding: 0.2em;
|
||||||
border-top: 1px solid #933;
|
border-top: 1px solid #933;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,9 +98,19 @@ body.threads,
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry .title {
|
.entry .body .comment-submit {
|
||||||
display: none;
|
margin: 0 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.entry .body .comment-submit input,
|
||||||
|
.entry .body .comment-submit textarea {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.entry .body .comment-submit textarea {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entry .title {}
|
||||||
.entry .title .author {}
|
.entry .title .author {}
|
||||||
.entry .title .subject {}
|
.entry .title .subject {}
|
||||||
|
|
||||||
|
@ -114,6 +130,36 @@ body.threads,
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tabs {
|
||||||
|
width: 574px;
|
||||||
|
margin: 22px 44px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
border-bottom: 1px solid #933;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs a {
|
||||||
|
padding: 2px;
|
||||||
|
background: #333;
|
||||||
|
border: 1px solid #933;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs a:hover {
|
||||||
|
background: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs > a.selected {
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.tab-contents > div {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.tab-contents > div.selected {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
.hidden {
|
.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
Loading…
Reference in a new issue