Generic Issue Tracking Mailing List #293

Parent #37Owner #29Flags read, fertileSource hellcore/hellcore.db

Aliases: Generic Issue Tracking Mailing List

61 verbs · 60 properties · 0 children

Verbs

VerbSpecFlagsDefinerLines
msg_full_textthis none thisrxd#29311
txt_typethis none thisrxd#2931
txt_statusthis none thisrxd#2931
txt_assignedthis none thisrxd#2936
receive_messagethis none thisrxd#29327
txt_votethis none thisrxd#29315
txt_logthis none thisrxd#29341
_parse_to _parse_fromthis none thisrxd#29325
add_logthis none thisrxd#29311
_pmsthis none thisrxd#293167
update_votethis none thisrxd#29334
_msg_full_textthis none thisrxd#2939
msg_summary_linethis none thisrxd#29343
extra_headersthis none thisrxd#29315
extra_textthis none thisrxd#29343
msg_summary_line_coloredthis none thisrxd#29320
mailnet_announce mailnet_announce_admins mailnet_announce_playersthis none thisrxd#29325
_@commentthis none thisrxd#29352
_@vote _@yes _@nothis none thisrxd#29338
_@type _@statusthis none thisrxd#29382
_@assignthis none thisrxd#29330
set_message_detailthis none thisrxd#2932
update_votethis none thisrxd#2930
update_type update_status update_assignedthis none thisrxd#29327
add_logthis none thisrxd#2930
update_countsthis none thisrxd#29346
display_top_seqthis none thisrxd#29348
reset_top_countsthis none thisrxd#29347
top_n bottom_nthis none thisrxd#29329
status_msg_seq type_msg_seqthis none thisrxd#29343
assigned_msg_seqthis none thisrxd#29326
minvotes_msg_seq minscore_msg_seqthis none thisrxd#29326
comment_msg_seqthis none thisrxd#29319
parse_message_seqthis none thisrxd#293237
display_top_allfoldersthis none thisrxd#29357
rm_message_seqthis none thisrxd#2935
do_combinethis none thisrxd#29344
_@combinethis none thisrxd#29329
do_retitlethis none thisrxd#2938
_@retitlethis none thisrxd#29327
_@annotatethis none thisrxd#29323
_@attachthis none thisrxd#29320
display_assigned_allfoldersthis none thisrxd#29325
unclosed_msg_seq_filterthis none thisrxd#29322
report_textthis none thisrxd#29311
_add_to_reportthis none thisrxd#2937
titlethis none thisrxd#2931
is_writable_bythis none thisrxd#29318
_@mailban _@mcbainthis none thisrxd#29337
banned_msgthis none thisrxd#2935
pms_oldthis none thisrxd#293237
old_txt_logthis none thisrxd#29326
on_status_change on_assign_change on_type_changethis none thisrxd#2930
add_bottomthis none thisrxd#2936
is_votable_bythis none thisrxd#2931
is_commentable_bythis none thisrxd#2931
comment_extrathis none thisrxd#2933
jdn_msg_seqthis none thisrxd#29319
most_interestingthis none thisrxd#29338
_@commentbanthis none thisrxd#29329
txt_fromthis none thisrxd#2931

Properties

PropertyDefinerFlagsOwnerValue
types#293rc#29{"~1b[1;30mUnknown~1b[0m", "Bug", "Typo", "Idea"}
statuses#293rc#29{"~1b[1;30mSubmitted~1b[0m", "~1b[1m~1b[32mOpen~1b[0m", "~1b[33mWork in progress~1b[0m", "~1b[31mDropped~1b[0m", "~1b[32mResolved~1b[0m"}
extra_text_color#293rc#29"~1b[1;30m"
votecounts#293rc#29
list of 17{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
totalvotes#293rc#29
list of 17{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
totalcomments#293rc#29
list of 17{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
votecounts_top#293rc#29{}
totalvotes_top#293rc#29{}
totalcomments_top#293rc#29{}
help_msg#293rc#29
list of 35{"Welcome to the exciting new world of issue-tracking mail.", "", "New player commands:", " @yes <msg> on <list> @no <msg> on <list>", " @comment <msg> on <list> [with <text>]", " @top [<n>] <list> [by upvotes|totalvotes|comments]", " ", "New prog commands:", " @type <msg> on <list> [is <type>]", " @assign <msg> on <list> [to <who>]", " @status <msg> on <list> [is <type>] ", "", "New message-sequence keywords:", " assigned:<who>|none - assigned to <who>, or to no one", " minvotes:<n> - only with number of votes >= n", " minscore:<n> - only with total score (yes - no) >= n", " type:[not]<type> - only with[out] this type", " status:[not]<status> - only with[out] this status", " comment:<text> - comments matching text", "", "Message-sequence keywords can be used anywhere on the moo where you're ", "used to being able to use them, i.e. @read, @peek, @mail, etc. They ", "can be combined just like (and with) the old ones, so you can do", "'@mail since:1-Jul minscore:5 status:open on *ideas' and it will ", "work.", "", "You can even combine them with themselves. Another example that works:", "'@mail last:100 status:notimpl status:notdrop on *ideas'. Which gives", "you any messages out of the last 100 which are both not implemented ", "and not dropped.", "", "All of the places above where I used '<msg>', you can use message ", "sequences. You can '@assign status:open assigned:none on *bug to me',", "you can '@no 1-$ on *ideas', etc. @yes/@comment/@no do not work", "for more than one message at a time, if you aren't a programmer."}
ok_statuses_for_top#293rc#29{}
default_type#293rc#291
default_status#293rc#291
default_assigned#293rc#29#-1
tell_mailnet#293rc#291
autoassign_statuses#293rc#29{}
postmerge_status#293rc#290
to_report#293rc#29{}
send_reports_to#293rc#29#-1
report_statuses#293rc#29{}
force_show_all#293rc#290
comment_type#293rc#290
notabug_status#293rc#290
banned#293rc#29{}
banned_msg#293rc#29"(USER WAS BANNED FOR THIS POST)"
votecounts_bottom#293rc#29{}
receive_notice#293rc#29{}
aids_statuses#293rc#29{}
display_votes#293rc#291
moderator_notify#37rc#29<clear>
last_msg_date#37r#290
messages_going#37#29<clear>
moderated#37rc#29<clear>
moderator_forward#37rc#29<clear>
writers#37rc#29<clear>
readers#37rc#29<clear>
mail_notify#37r#29<clear>
mail_forward#37r#29{}
expire_period#37r#29<clear>
last_used_time#37r#29<clear>
messages#37#29<clear>
rmm_own_msgs#37rc#291
guests_can_send_here#37rc#29<clear>
messages_kept#37r#29<clear>
registered_email#37#29<clear>
email_validated#37#29<clear>
validation_password#37#29<clear>
barcolor#37rc#29<clear>
hidden_subjects#37rc#29<clear>
hidden_content#37rc#29<clear>
aliases#1r#29{"Generic Issue Tracking Mailing List"}
description#1rc#29<clear>
object_size#1r#29{72404, 1298434536}
hidden_verbs#1rc#29<clear>
phelp_msg#1rc#29<clear>
weight#1rc#29<clear>
owner_verbs#1rc#29<clear>
plural_name#1rc#29<clear>
client_image#1rc#29<clear>
listening#1rc#29<clear>

Ancestry

Ancestors (nearest first): #37 Generic Mail Recipient#1 root

Children: none

Call graph

calls n293_0 #293:msg_full_text n293_6 #293:txt_log n293_0->n293_6 n293_1 #293:txt_type n293_0->n293_1 n293_2 #293:txt_status n293_0->n293_2 n293_3 #293:txt_assigned n293_0->n293_3 n293_5 #293:txt_vote n293_0->n293_5 n20_1 #20:left n293_0->n20_1 n293_60 #293:txt_from n293_0->n293_60 n293_6->n20_1 n38_53 #38:mail_name_for n293_6->n38_53 n20_95 #20:word_wrap n293_6->n20_95 n35_18 #35:abbrev_ctime n293_6->n35_18 n20_59 #20:name_and_number n293_3->n20_59 n20_2 #20:right n293_5->n20_2 n293_4 #293:receive_message n37_14 #37:ok_write n293_4->n37_14 n37_15 #37:parse_message_seq n293_4->n37_15 n293_4->n38_53 n293_16 #293:mailnet_announce n293_4->n293_16 n6_180 #6:systell n293_4->n6_180 n293_16->n6_180 n6_54 #6:check_pref n293_16->n6_54 n37_39 #37:folder_and_message_and_subject n293_16->n37_39 n37_38 #37:folder_and_message n293_16->n37_38 n293_7 #293:_parse_to n20_38 #20:explode n293_7->n20_38 n20_16 #20:literal_object n293_7->n20_16 n48_4 #48:yes_or_no n293_7->n48_4 n293_8 #293:add_log n27_7 #27:tolist n293_8->n27_7 n293_25 #293:update_counts n293_8->n293_25 n293_9 #293:_pms n293_9->n20_38 n48_8 #48:suspend_if_needed n293_9->n48_8 n47_17 #47:assoc n293_9->n47_17 n27_0 #27:add n293_9->n27_0 n27_3 #27:union n293_9->n27_3 n293_10 #293:update_vote n293_10->n27_7 n293_10->n293_25 n293_11 #293:_msg_full_text n293_11->n293_6 n293_11->n293_1 n293_11->n293_2 n293_11->n293_3 n293_11->n293_5 n293_12 #293:msg_summary_line n293_12->n293_2 n293_12->n293_5 n293_12->n20_1 n293_12->n38_53 n293_12->n20_2 n293_12->n35_18 n122_8 #122:strip n293_12->n122_8 n122_9 #122:find n293_12->n122_9 n20_101 #20:smart_abbrev n293_12->n20_101 n20_5 #20:from_list n293_12->n20_5 n293_13 #293:extra_headers n293_13->n293_1 n293_13->n293_2 n293_13->n293_5 n293_13->n20_1 n293_13->n38_53 n293_14 #293:extra_text n293_14->n20_1 n293_14->n38_53 n293_14->n20_95 n293_14->n35_18 n293_14->n6_54 n293_56 #293:comment_extra n293_14->n293_56 n293_15 #293:msg_summary_line_colored n293_15->n293_2 n293_15->n293_5 n293_15->n20_1 n293_15->n38_53 n293_15->n35_18 n293_17 #293:_@comment n293_17->n293_16 n293_17->n48_4 n293_17->n293_8 n293_17->n20_5 n293_17->n37_39 n293_17->n37_38 n293_55 #293:is_commentable_by n293_17->n293_55 n107_43 #107:tell n293_17->n107_43 n27_12 #27:size n293_17->n27_12

Showing 48 of 103 verbs; 55 not shown.

Source

msg_full_text

Spec this none thisFlags rxdOwner #29Definer #293

Referenced by

none

Source

1"Copied from Mail Distribution Center (#46):to_text by Hacker (#36) Sun Aug 24 01:32:08 2008 CDT";
2":to_text(@msg) => message in text form (suitable for printing)";
3txt_log = this:txt_log(args[9]);
4extra_header = ((((((("[ " + this:txt_type(args[5])) + " | ") + this:txt_status(args[6])) + " | ") + this:txt_assigned(args[7])) + " | ") + tostr(this:txt_vote(@args[8]))) + " votes ]";
5if (1)
6return {($su:left(extra_header, 50) + "  ") + ctime(args[1]), ($su:left(($ansi.bold_on + ((args[4] == " ") ? "(no subject)" | args[4])) + $ansi.bold_off, 50) + "  From ") + this:txt_from(args[2]), @args[10..$], @txt_log};
7"Old version:";
8return {"Date:     " + ctime(args[1]), "From:     " + args[2], "To:       " + args[3], @(args[4] == " ") ? {} | {"Subject:  " + args[4]}, extra_header, @args[10..$], @txt_log};
9else
10return {"Date:     " + ctime(args[1]), "From:     " + args[2], "To:       " + args[3], @(args[4] == " ") ? {} | {"Subject:  " + args[4]}, "Type:     " + this:txt_type(args[5]), "Status:   " + this:txt_status(args[6]), "Assigned: " + this:txt_assigned(args[7]), "Votes:    " + tostr(this:txt_vote(@args[8])), @args[10..$], @txt_log};
11endif

txt_type

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1return this.types[args[1]];

txt_status

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1return this.statuses[args[1]];

txt_assigned

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1who = args[1];
2if (valid(who) && is_player(who))
3return tostr("Assigned: ", $su:nn(who));
4else
5return tostr($ansi.dark_gray, "Unassigned", $ansi.reset);
6endif

receive_message

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1"Copied from Generic Mail Recipient (#45):receive_message by Hacker (#36) Sun Aug 24 01:43:41 2008 CDT";
2if (!this:ok_write(caller, caller_perms()))
3return E_PERM;
4else
5m = args[1];
6message = {m[1], m[2], m[3], m[4], this.default_type, this.default_status, this.default_assigned, {{}, {}}, {}, @m[5..$]};
7this.messages = {@this.messages, {new = this:new_message_num(), message}};
8this.last_msg_date = args[1][1];
9this.last_used_time = time();
10fork (0)
11text = "New from " + $mail_agent:mail_name_for(player, 1);
12"text_players = text;";
13"if (player.programmer)";
14"  text_players = \"New from \" + $mail_agent:mail_name_for(#2, 1);";
15"endif";
16newseqnum = length(this.messages);
17seq = {newseqnum, newseqnum + 1};
18this:mailnet_announce(seq, text);
19"this:mailnet_announce_admins(seq, text);";
20"this:mailnet_announce_players(seq, text_players);";
21for msgline in (this.receive_notice)
22msgline = $su:subst(msgline, {{"MSGNUM", tostr(new)}, {"FOLDERNAME", tostr("*", this.name)}});
23player:systell(msgline);
24endfor
25endfork
26return new;
27endif

txt_vote

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1{yes, no} = {length(args[1]), length(args[2])};
2if ((!player.programmer) && (!this.display_votes))
3return tostr(yes + no);
4endif
5if (yes)
6yes_str = ($ansi.green + $su:right(tostr("+", yes), 3)) + $ansi.reset;
7else
8yes_str = "  0";
9endif
10if (no)
11no_str = ($ansi.red + $su:right(tostr("-", no), 3)) + $ansi.reset;
12else
13no_str = "  0";
14endif
15return (yes_str + "/") + no_str;

txt_log

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1log = args[1];
2if (!log)
3return {};
4endif
5txt_log = {""};
6m = "";
7see_ann = player.programmer;
8for x in (log)
9who = $mail_agent:mail_name_for(x[2], 1);
10if (length(x[3]) >= 11)
11if (x[3][1..11] == "commented: ")
12comment = x[3][12..$];
13comment = $su:word_wrap({comment}, 52);
14m = tostr($ansi.dark_gray, "> ", $su:left(who, -12), " ", comment[1]);
15txt_log = {@txt_log, m};
16m = tostr($ansi.dark_gray, "  ", $su:left($time_utils:abbrev_ctime(x[1]), 12), " ", (length(comment) >= 2) ? comment[2] | "");
17txt_log = {@txt_log, m};
18for c in (comment[3..$])
19c = tostr($ansi.dark_gray, c, $ansi.reset);
20txt_log = {@txt_log, "               " + c};
21endfor
22elseif (x[3][1..11] == "annotated: ")
23txt = x[3][12..$];
24txt = $su:word_wrap({txt}, 52);
25if (see_ann)
26m = tostr($ansi.yellow, "> ", $su:left(who, -12), " ", $ansi.yellow, txt[1]);
27txt_log = {@txt_log, m};
28m = tostr($ansi.dark_gray, "  ", $su:left($time_utils:abbrev_ctime(x[1]), 12), $ansi.reset, " ", $ansi.yellow, (length(txt) >= 2) ? txt[2] | "");
29txt_log = {@txt_log, m};
30for line in (txt[3..$])
31line = tostr($ansi.yellow, line, $ansi.reset);
32txt_log = {@txt_log, "               " + line};
33endfor
34endif
35endif
36else
37m = tostr($ansi.dark_gray, "> ", $time_utils:abbrev_ctime(x[1]), "  ", who, " ", x[3], $ansi.reset);
38txt_log = {@txt_log, m};
39endif
40endfor
41return txt_log;

_parse_to _parse_from

Spec this none thisFlags rxdOwner #29Definer #293

Referenced by

none

Source

1"Copied from Mail Distribution Center (#46):_parse_to by Hacker (#36) Sun Aug 24 03:33:04 2008 CDT";
2":_parse_from(string with |'s in it) => object list";
3":_parse_to(string with |'s in it) => object list";
4"  for from:string and to:string items in :parse_message_seq";
5if (verb == "_parse_to")
6match_obj = fail_obj = this;
7match_verb = "match_recipient";
8fail_verb = "match_failed";
9else
10match_obj = $string_utils;
11match_verb = "match_player";
12fail_obj = $command_utils;
13fail_verb = "player_match_failed";
14endif
15plist = {};
16for w in ($string_utils:explode(args[1], "|"))
17if (fail_obj:(fail_verb)(p = match_obj:(match_verb)(w), w))
18p = $string_utils:literal_object(w);
19if ((p == $failed_match) || (!$command_utils:yes_or_no("Continue? ")))
20return "Bad address list:  " + args[1];
21endif
22endif
23plist = setadd(plist, p);
24endfor
25return plist;

add_log

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1{seq, who, text, ?is_comment = 0} = args;
2for index in ($seq_utils:tolist(seq))
3log = this.messages[index][2][9];
4log = {@log, {time(), who, text}};
5this.messages[index][2][9] = log;
6if (is_comment)
7msgnum = this.messages[index][1];
8this:update_counts(msgnum, 1, "totalcomments");
9endif
10yield;
11endfor

_pms

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1"Copied from Generic Issue Tracking Mailing List (#295129):parse_message_seq by Satan (#2) Sun Aug 24 04:27:39 2008 CDT";
2"Copied from Mail Distribution Center (#46):parse_message_seq by Satan (#2) Sun Aug 24 03:25:39 2008 CDT";
3"parse_message_seq(strings,cur[,last_old])";
4"This is the default <message-sequence> parsing routine for those mail commands that refer to sequences of messages (@mail, @read,...) on a folder.";
5"  caller (the folder) is assumed to be a $mail_recipient or a player.";
6"  strings is the <message-sequence> portion of the arg list.";
7"  cur is the number of the player's current message for this folder.";
8"Returns a string error message if the parse fails, otherwise";
9"returns a list {msg_seq, @unused_strings}, where";
10"   msg_seq is a handle understood by caller:display_seq_full/headers(), and ";
11"   unused_strings is the list of remaining uninterpreted strings";
12set_task_perms(caller_perms());
13{strings, ?cur = 0, ?last_old = 0} = args;
14if (!(nummsgs = caller:length_all_msgs()))
15return "%f %<has> no messages.";
16elseif (typeof(strings) != LIST)
17strings = {strings};
18endif
19seq = result = {};
20mode = #0;
21"... changes to 0 if we start seeing message numbers, to 1 if we see masks...";
22keywords = ":from:%from:to:%to:subject:type:status:assigned:body:before:after:since:until:first:last:kept:unkept";
23keyalist = {{1, "from"}, {6, "%from"}, {12, "to"}, {15, "%to"}, {19, "subject"}, {27, "type"}, {32, "status"}, {39, "assigned"}, {48, "body"}, {53, "before"}, {60, "after"}, {66, "since"}, {72, "until"}, {78, "first"}, {84, "last"}, {89, "kept"}, {94, "unkept"}};
24strnum = 0;
25for string in (strings)
26strnum = strnum + 1;
27$command_utils:suspend_if_needed(0);
28if (string && ((c = index(string, ":")) && ((k = index(keywords, ":" + string[1..c - 1])) && (k == rindex(keywords, ":" + string[1..c - 1])))))
29"...we have a mask to apply...";
30keywd = $list_utils:assoc(k, keyalist)[2];
31if (mode == #0)
32seq = {1, nummsgs + 1};
33endif
34mode = 1;
35if (k <= 48)
36"...from, subject, to, body...";
37pattern = string[c + 1..$];
38if (keywd in {"subject", "body", "status", "type"})
39elseif (keywd[1] == "%")
40pattern = $string_utils:explode(pattern, "|");
41else
42pattern = this:((keywd == "to") ? "_parse_to" | "_parse_from")(pattern);
43if (typeof(pattern) == STR)
44return pattern;
45endif
46endif
47seq = this:(keywd + "_msg_seq")(pattern, seq);
48if (typeof(seq) == STR)
49if (strnum == 1)
50return seq;
51else
52seq = {};
53endif
54endif
55elseif (k <= 72)
56"...before, since, after, until...";
57if (typeof(date = this:_parse_date(string[c + 1..$])) != INT)
58return tostr("Bad date `", string, "':  ", date);
59endif
60s = caller:length_date_le((keywd in {"before", "since"}) ? date - 1 | (date + 86399));
61if (keywd in {"before", "until"})
62seq = $seq_utils:remove(seq, s + 1, nummsgs);
63else
64seq = $seq_utils:remove(seq, 1, s);
65endif
66elseif (k <= 63)
67"...first, last...";
68if (n = toint(string[c + 1..$]))
69seq = $seq_utils:(keywd + "n")(seq, n);
70else
71return tostr("Bad number in `", string, "'");
72endif
73else
74"...kept, unkept...";
75if (c < length(string))
76return tostr("Unexpected junk after `", keywd, ":'");
77elseif ((!(seq = caller:(keywd + "_msg_seq")(seq))) && (strnum == 1))
78return tostr("%f %<has> no ", keywd, " messages.");
79endif
80endif
81else
82"...continue building the present sequence...";
83if (mode)
84seq && (result = $seq_utils:union(result, seq));
85seq = {};
86endif
87mode = 0;
88if (!string)
89"...default case for @read: get the current message but skip to the next one if it's not there...";
90if (cur)
91i = min(caller:length_num_le(cur - 1) + 1, nummsgs);
92seq = $seq_utils:add(seq, i, i);
93else
94return "%f %<has> no current message.";
95endif
96elseif ((index(string, "next") == 1) && (!index(string, "-")))
97string[1..4] = "";
98if ((n = string ? toint(string) | 1) <= 0)
99return tostr("Bad number `", string, "'");
100elseif ((i = caller:length_num_le(cur) + 1) <= nummsgs)
101seq = $seq_utils:add(seq, i, min((i + n) - 1, nummsgs));
102else
103return "%f %<has> no next message.";
104endif
105elseif ((index(string, "prev") == 1) && (!index(string, "-")))
106string[1..4] = "";
107if ((n = string ? toint(string) | 1) <= 0)
108return tostr("Bad number `", string, "'");
109elseif (i = caller:length_num_le(cur - 1))
110seq = $seq_utils:add(seq, max(1, (i - n) + 1), i);
111else
112return "%f %<has> no previous message.";
113endif
114elseif (string == "new")
115s = last_old ? caller:length_date_le(last_old) | caller:length_num_le(cur);
116if (s < nummsgs)
117seq = $seq_utils:add(seq, s + 1, nummsgs);
118else
119return "%f %<has> no new messages.";
120endif
121elseif (string == "first")
122seq = $seq_utils:add(seq, 1, 1);
123elseif (n = toint(string) || (((string in {"last", "$"}) && -1) || ((string == "cur") && cur)))
124if (n <= 0)
125seq = $seq_utils:add(seq, max(0, nummsgs + n) + 1, nummsgs);
126elseif (i = caller:exists_num_eq(n))
127seq = $seq_utils:add(seq, i, i);
128else
129return (string == "cur") ? "%f's current message has been removed." | tostr("%f %<has> no message numbered `", string, "'.");
130endif
131elseif (((i = index(string, "..")) > 1) || ((i = index(string, "-")) > 1))
132if ((start = toint(sst = string[1..i - 1])) > 0)
133s = caller:length_num_le(start - 1);
134elseif (sst in {"next", "prev", "cur"})
135s = max(0, caller:length_num_le(cur - (sst != "next")) - (sst == "prev"));
136elseif (sst in {"last", "$"})
137s = nummsgs - 1;
138elseif (sst == "first")
139s = 0;
140else
141return {$seq_utils:union(result, seq), @strings[strnum..$]};
142endif
143j = (string[i] == ".") ? i + 2 | (i + 1);
144if ((end = toint(est = string[j..$])) > 0)
145e = caller:length_num_le(end);
146elseif (est in {"next", "prev", "cur"})
147e = min(nummsgs, caller:length_num_le(cur - (est == "prev")) + (est == "next"));
148elseif (est in {"last", "$"})
149e = nummsgs;
150elseif (est == "first")
151e = 1;
152else
153return {$seq_utils:union(result, seq), @strings[strnum..$]};
154endif
155if (s < e)
156seq = $seq_utils:add(seq, s + 1, e);
157else
158return tostr("%f %<has> no messages in range ", string, ".");
159endif
160elseif (string == "cur")
161return "%f %<has> no current message.";
162else
163return {$seq_utils:union(result, seq), @strings[strnum..$]};
164endif
165endif
166endfor
167return {$seq_utils:union(result, seq)};

update_vote

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1"1 is yes, 2 is no";
2{seq, who, vote} = args;
3othervote = (vote % 2) + 1;
4votes_made = 0;
5for index in ($seq_utils:tolist(seq))
6authortxt = this.messages[index][2][2];
7author = `toobj(authortxt[rindex(authortxt, " ") + 2..$ - 1]) ! ANY => #-1';
8if (author == who)
9who:tell("You can't vote on your own posts.");
10continue;
11endif
12if (this.ok_statuses_for_top && (!(this.messages[index][2][6] in this.ok_statuses_for_top)))
13who:tell("You can't vote on closed issues.");
14continue;
15endif
16votes = this.messages[index][2][8];
17if (who in votes[vote])
18who:tell("You already voted ", (vote == 1) ? "yes" | "no", " on message ", this.messages[index][1], ".");
19continue;
20endif
21dont_count = who in votes[othervote];
22votes[vote] = setadd(votes[vote], who);
23votes[othervote] = setremove(votes[othervote], who);
24this.messages[index][2][8] = votes;
25score = (vote == 1) ? 1 | -1;
26msgnum = this.messages[index][1];
27this:update_counts(msgnum, score, "votecounts");
28if (!dont_count)
29this:update_counts(msgnum, 1, "totalvotes");
30endif
31votes_made = votes_made + 1;
32yield;
33endfor
34return votes_made;

_msg_full_text

Spec this none thisFlags rxdOwner #29Definer #293

Referenced by

none

Source

1"Copied from Generic Issue Tracking Mailing List (#295129):msg_full_text by Hacker (#36) Sun Aug 24 12:21:15 2008 CDT";
2"Copied from Mail Distribution Center (#46):to_text by Hacker (#36) Sun Aug 24 01:32:08 2008 CDT";
3":to_text(@msg) => message in text form (suitable for printing)";
4txt_log = this:txt_log(args[9]);
5if (1)
6return {"Date:     " + ctime(args[1]), ((((((("[ " + this:txt_type(args[5])) + " | ") + this:txt_status(args[6])) + " | ") + this:txt_assigned(args[7])) + " | ") + tostr(this:txt_vote(@args[8]))) + "votes ]", "From:     " + args[2], "To:       " + args[3], @(args[4] == " ") ? {} | {"Subject:  " + args[4]}, @args[10..$], @txt_log};
7else
8return {"Date:     " + ctime(args[1]), "From:     " + args[2], "To:       " + args[3], @(args[4] == " ") ? {} | {"Subject:  " + args[4]}, "Type:     " + this:txt_type(args[5]), "Status:   " + this:txt_status(args[6]), "Assigned: " + this:txt_assigned(args[7]), "Votes:    " + tostr(this:txt_vote(@args[8])), @args[10..$], @txt_log};
9endif

msg_summary_line

Spec this none thisFlags rxdOwner #29Definer #293

Referenced by

Source

1":msg_summary_line(@msg) => date/from/subject as a single string.";
2body = ("" in {@args, ""}) + 1;
3if ((length(args) > body) && (!args[body]))
4body = body + 1;
5endif
6if ((body > length(args)) || (!(subject = args[body])))
7subject = "(no text)";
8endif
9date = $time_utils:abbrev_ctime(args[1]);
10date = ($ansi.brown + date) + $ansi.reset;
11fromtxt = args[2];
12from_obj = fromtxt[rindex(fromtxt, " ") + 2..$ - 1];
13fromtxt = $mail_agent:mail_name_for(toobj(from_obj), 1);
14if (args[4] != " ")
15subject = ($ansi.white + $ansi.bold_on) + args[4];
16else
17subject = $ansi.gray + subject;
18endif
19status = this:txt_status(args[6]);
20if (length($ansi:strip(status)) > 8)
21{statcolors, stattxt} = {$ansi:find(status), $ansi:strip(status)};
22yield;
23stattxt = $su:smart_abbrev(stattxt, 8);
24if (statcolors)
25status = $su:from_list({@statcolors[1..$ - 1], stattxt, statcolors[$]});
26else
27status = stattxt;
28endif
29endif
30asgn = args[7];
31yield;
32if (!(args[6] in this.ok_statuses_for_top))
33asgntxt = valid(asgn) ? tostr("by ", $mail_agent:mail_name_for(asgn, 1)) | tostr($ansi.gray, "by ???", $ansi.default_fg);
34else
35asgntxt = valid(asgn) ? tostr("Asgn: ", $mail_agent:mail_name_for(asgn, 1)) | tostr($ansi.gray, "Unassigned", $ansi.default_fg);
36endif
37yield;
38detailline = tostr($su:left(fromtxt, -14), " ", $su:right(this:txt_vote(@args[8]), 2), " ", $su:left(status, -8), " ", $su:left(asgntxt, -16), " ", $su:right(date, 13));
39if (length(subject) < 40)
40subject = (subject + $ansi.gray) + `" - " + args[11] ! E_RANGE => ""';
41endif
42subjline = $su:left(subject, -62) + $ansi.default_fg;
43return {subjline, detailline};

extra_headers

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1{bar, leftlen, arrows, rightlen, msg} = args;
2typelen = (leftlen - 1) / 2;
3statlen = (leftlen - typelen) - 1;
4asgn = msg[7];
5stattxt = this:txt_status(msg[6]);
6if (!(msg[6] in this.ok_statuses_for_top))
7assigntxt = tostr("Closed by: ", valid(asgn) ? $mail_agent:mail_name_for(asgn, 1) | "???");
8elseif (valid(asgn))
9assigntxt = tostr("Assigned: ", $mail_agent:mail_name_for(asgn, 1));
10else
11assigntxt = tostr(player.ansi ? $ansi.dark_gray | "", "Unassigned", $ansi.reset);
12endif
13line1 = tostr($su:left(" Category", typelen), "|", $su:left(" Status", statlen), arrows, $ansi.yellow, assigntxt, $ansi.reset);
14line2 = tostr($su:left(" " + this:txt_type(msg[5]), typelen), "|", $su:left(" " + stattxt, statlen), arrows, this:txt_vote(@msg[8]), $ansi.yellow, " votes", $ansi.reset);
15return {line1, line2};

extra_text

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1log = args[11];
2if (!log)
3return {};
4endif
5txt_log = {""};
6comment_color = player:check_pref("plaincomments") ? $ansi.reset | $ansi.dark_gray;
7for x in (log)
8who = $mail_agent:mail_name_for(x[2], 1);
9possible_comment = length(x[3]) >= 11;
10color = "";
11if (possible_comment && (x[3][1..11] == "commented: "))
12comment = x[3][12..$];
13color = comment_color;
14elseif (possible_comment && (x[3][1..11] == "annotated: "))
15if (!player.programmer)
16continue;
17endif
18comment = x[3][12..$];
19color = $ansi.yellow;
20elseif (possible_comment && (x[3][1..10] == "attached: "))
21if (!player.programmer)
22comment = "attached object [only visible to admins]";
23else
24comment = x[3];
25endif
26color = $ansi.yellow;
27else
28comment = x[3];
29color = $ansi.cyan;
30endif
31comment = $su:word_wrap({comment}, 52, color);
32if (extra = this:comment_extra(x[2], x[1]))
33comment = {@comment, @$su:word_wrap(extra[2], 52, extra[1])};
34endif
35m = tostr(color, "> ", $su:left(who, 12), $ansi.reset, " ", comment[1]);
36txt_log = {@txt_log, m};
37m = tostr(comment_color, "  ", $su:left($time_utils:abbrev_ctime(x[1]), 12), " ", $ansi.reset, (length(comment) >= 2) ? comment[2] | "");
38txt_log = {@txt_log, m};
39for c in (comment[3..$])
40txt_log = {@txt_log, ("               " + $ansi.reset) + c};
41endfor
42endfor
43return txt_log;

msg_summary_line_colored

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1"Copied from Generic Issue Tracking Mailing List (#295129):msg_summary_line by Hacker (#36) Wed Jul 29 12:22:50 2009 CDT";
2"Copied from Mail Distribution Center (#46):msg_summary_line by Hacker (#36) Sun Aug 24 15:54:51 2008 CDT";
3":msg_summary_line(@msg) => date/from/subject as a single string.";
4body = ("" in {@args, ""}) + 1;
5if ((length(args) > body) && (!args[body]))
6body = body + 1;
7endif
8if ((body > length(args)) || (!(subject = args[body])))
9subject = "(no text)";
10endif
11date = $time_utils:abbrev_ctime(args[1]);
12fromtxt = args[2];
13from_obj = fromtxt[rindex(fromtxt, " ") + 2..$ - 1];
14fromtxt = $mail_agent:mail_name_for(toobj(from_obj), 1);
15if (args[4] != " ")
16subject = args[4];
17endif
18status = this:txt_status(args[6]);
19logs = length(args[9]);
20return tostr(date, "  ", $string_utils:left(fromtxt, -14), "  ", $su:left(status, -9), $ansi.reset, " ", $su:left(this:txt_vote(@args[8]), 2), "  ", subject);

mailnet_announce mailnet_announce_admins mailnet_announce_players

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1net = this.tell_mailnet;
2announce = verb[9..$];
3if (net == 0)
4return;
5endif
6if ((typeof(net) != OBJ) || (!is_a(net, $net)))
7net = $nets.mailnet;
8endif
9{seq, text, ?private = 0} = args;
10if (private)
11net = $nets.prognet;
12endif
13if (typeof(text) != LIST)
14text = {text};
15endif
16net:(announce)(this, tostr("(", this:fms(seq), ") ", text[1]), 1);
17fm = tostr("(", this:fm(seq), ") ");
18for t in (text[2..$])
19net:(announce)(this, fm + t, 1);
20endfor
21if (((is_a(player, $player) && player:check_pref("hints")) && (net == $nets.mailnet)) && (!(net in player.features)))
22fork (2)
23player:systell((($ansi.bold_on + "HINT: ") + $ansi.bold_off) + "Are you using mailnet? Mailnet announces new posts, votes & comments on posts. \"mailnet on\" to use it.");
24endfork
25endif

_@comment

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1{seq, rest} = args;
2verb = verb[2..$];
3comment = "";
4if (!this:is_commentable_by(player))
5player:tell("That list is not commentable by you.");
6return;
7endif
8if (rest)
9if (rest[1] == "with")
10rest = rest[2..$];
11endif
12comment = $su:from_list(rest, " ");
13endif
14if ((seqsz = $seq_utils:size(seq)) > 1)
15if (!player.programmer)
16player:tell("You can only comment on one message at a time.");
17return;
18elseif (!$cu:yes_or_no(tostr("This will affect ", seqsz, " messages. Is that okay?")))
19player:tell("Aborted.");
20return;
21endif
22endif
23"Abusing loop so the comment closed check isn't duplicated.";
24while (1)
25if (!player.programmer)
26seqnum = seq[1];
27if (!(this.messages[seqnum][2][6] in this.ok_statuses_for_top))
28player:tell("That post is closed to comments.");
29return;
30endif
31endif
32if (!comment)
33player:tell($ansi.cyan, "Commenting on ", this:fms(seq), ".", $ansi.reset);
34comment = $command_utils:read("type a one-line comment");
35if (!comment)
36player:tell("Aborted.");
37return;
38endif
39continue;
40endif
41break;
42endwhile
43comment = $su:escape(comment);
44this:add_log(seq, player, "commented: " + comment, 1);
45"if (player.programmer)";
46"  this:mailnet_announce_players(seq, tostr(#2.name, \": \", comment));";
47"else";
48"  this:mailnet_announce_players(seq, tostr(player.name, \": \", comment));";
49"endif";
50"this:mailnet_announce_admins(seq, tostr(player.name, \": \", comment));";
51this:mailnet_announce(seq, tostr(player.name, ": ", comment));
52player:tell($ansi.cyan, "Comment added to ", this:fm(seq), ".", $ansi.reset);

_@vote _@yes _@no

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1{seq, rest} = args;
2verb = verb[2..$];
3provided = "";
4if (rest)
5player:tell("Usage: ", verb, " <msg> on <folder>");
6return;
7endif
8if (!this:is_votable_by(player))
9player:tell("This list is not votable by you.");
10return;
11endif
12if ((seqsz = $seq_utils:size(seq)) > 1)
13if (!player.programmer)
14player:tell("You can only vote on one message at a time.");
15return;
16elseif (!$cu:yes_or_no(tostr("This will affect ", seqsz, " messages. Is that okay?")))
17player:tell("Aborted.");
18return;
19endif
20endif
21"1 is yes, 2 is no.";
22votenum = verb in {"@yes", "@no"};
23if (!votenum)
24player:tell($ansi.cyan, "Voting on ", this:fms(seq), ".", $ansi.reset);
25votestr = $command_utils:read("Vote yes or no:");
26if (!(votenum = votestr in {"y", "ye", "yes", "n", "no"}))
27player:tell($ansi.cyan, "'", votestr, "' is not a valid answer.");
28return;
29else
30player:tell($ansi.cyan, "(Tip: you can use '@yes <msg> on <folder>' or '@no <msg> on <folder>' as a shortcut.)", $ansi.reset);
31votenum = (votenum <= 3) ? 1 | 2;
32endif
33endif
34votestr = {$ansi.green + "+1", $ansi.red + "-1"}[votenum] + $ansi.reset;
35if (this:update_vote(seq, player, votenum))
36this:mailnet_announce(seq, votestr);
37player:tell($ansi.cyan, "Voted ", votestr, $ansi.cyan, " on ", this:fm(seq), ".", $ansi.reset);
38endif

_@type _@status

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1{seq, rest} = args;
2verb = verb[2..$];
3provided = "";
4if (rest)
5if ((rest[1] != "is") || (length(rest) < 2))
6player:tell("Usage: ", verb, " <msg> on <folder> [is <what>]");
7return;
8endif
9provided = $su:from_list(rest[2..$], " ");
10endif
11if (!player.programmer)
12if (verb != "@type")
13raise(E_PERM);
14return;
15endif
16if ($seq_utils:size(seq) > 1)
17player:tell("You can't change the type of more than one post.");
18return;
19endif
20index = seq[1];
21authortxt = this.messages[index][2][2];
22author = `toobj(authortxt[rindex(authortxt, " ") + 2..$ - 1]) ! ANY => #-1';
23if (author != player)
24player:tell("You can't change the type of posts you didn't make.");
25return;
26endif
27if (this.messages[index][2][5] != this.default_status)
28player:tell("That message has already been categorized.");
29return;
30endif
31endif
32action = (verb == "@type") ? "Recategorizing" | "Changing status";
33what = verb[2..$];
34pluralwhat = (what == "type") ? "types" | "statuses";
35prop = this.(pluralwhat);
36updateverb = tostr("update_", what);
37selected = "";
38if (!provided)
39player:tell($ansi.cyan, action, " ", this:fms(seq), ".", $ansi.reset);
40player:tell("Available ", pluralwhat, ":");
41i = 1;
42for i in [1..length(prop)]
43player:tell(tostr(i, " - ", prop[i]));
44endfor
45provided = $command_utils:read("Select a number from the above list.");
46endif
47if ((ti = toint(provided)) && (provided == tostr(ti)))
48if ((ti < 0) || (ti > length(prop)))
49player:tell("Invalid ", what, ".");
50return;
51endif
52selected = prop[ti];
53else
54for ti in [1..length(prop)]
55stripped = $ansi:strip(prop[ti]);
56if ((provided == stripped) || (index(stripped, provided) == 1))
57selected = prop[ti];
58break;
59endif
60endfor
61if (!selected)
62player:tell("Invalid ", what, ".");
63return;
64endif
65endif
66if ((what == "status") && (ti == this.postmerge_status))
67player:tell("Use '@combine <msg> on <list> with <target-msg>' instead of @status.");
68return;
69endif
70if ((seqsz = $seq_utils:size(seq)) > 5)
71if (!$cu:yes_or_no(tostr("This will affect ", seqsz, " messages. Is that okay?")))
72player:tell("Aborted.");
73return;
74endif
75endif
76this:(updateverb)(seq, ti);
77if ((what == "status") && (ti in this.report_statuses))
78this:_add_to_report(seq);
79endif
80this:add_log(seq, player, tostr("changed ", what, ": ", selected));
81this:mailnet_announce(seq, tostr(player.name, " changed ", what, " to ", selected));
82player:tell($ansi.cyan, "Changed ", what, " of ", this:fm(seq), " to ", selected, ".", $ansi.reset);

_@assign

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1{seq, rest} = args;
2verb = verb[2..$];
3provided = "";
4if (rest)
5if ((rest[1] != "to") || (length(rest) < 2))
6player:tell("Usage: ", verb, " <msg> on <folder> [to <player>]");
7return;
8endif
9provided = $su:from_list(rest[2..$], " ");
10endif
11selected = #-1;
12if (!provided)
13player:tell($ansi.cyan, "Assigning ", this:fms(seq), ".", $ansi.reset);
14provided = $cu:read("Type the name of the programmer to assign this to.");
15endif
16ass = $su:match_player(provided);
17if ((!valid(ass)) || (!is_player(ass)))
18player:tell("I don't know who '", provided, "' is.");
19return;
20endif
21if ((seqsz = $seq_utils:size(seq)) > 5)
22if (!$cu:yes_or_no(tostr("This will affect ", seqsz, " messages. Is that okay?")))
23player:tell("Aborted.");
24return;
25endif
26endif
27this:update_assigned(seq, ass);
28this:add_log(seq, player, tostr("assigned to ", ass.name));
29this:mailnet_announce(seq, tostr(player.name, " assigned to ", ass.name), 1);
30player:tell($ansi.cyan, "Assigned ", this:fm(seq), " to ", $su:nn(ass), ".", $ansi.reset);

set_message_detail

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1{message_index, detail_index, value} = args;
2this.messages[message_index][2][detail_index] = value;

update_vote

Spec this none thisFlags rxdOwner #362Definer #293

Referenced by

none

Source

No program (verb defined but unprogrammed).

update_type update_status update_assigned

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1{seq, value} = args;
2index = verb in {"update_type", "update_status", "update_assigned"};
3event_verb = {"on_type_change", "on_status_change", "on_assign_change"}[index];
4detail_index = index + 4;
5if ((verb == "update_assigned") && (value == #199857))
6value = #-1;
7endif
8for s in ($seq_utils:tolist(seq))
9this.messages[s][2][detail_index] = value;
10if (verb == "update_status")
11if (value in this.autoassign_statuses)
12this.messages[s][2][7] = player;
13else
14this.messages[s][2][7] = #-1;
15endif
16if (value in this.aids_statuses)
17fromtxt = this.messages[s][2][2];
18from_obj = fromtxt[rindex(fromtxt, " ") + 2..$ - 1];
19sender = toobj(from_obj);
20if (is_player(sender))
21sender:ingest($drugs.aids, random(10), $drug_vectors.divine);
22endif
23endif
24endif
25`this:(event_verb)(s, detail_index, value) ! ANY => 0';
26yield;
27endfor

add_log

Spec this none thisFlags rxdOwner #362Definer #293

Referenced by

none

Source

No program (verb defined but unprogrammed).

update_counts

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1"msgnum wants to change propname by delta. update the prop, and the top/bottom list for that prop if necessary.";
2{msgnum, delta, propname} = args;
3oldval = `this.(propname)[msgnum] ! E_RANGE => 0';
4newval = oldval + delta;
5this.(propname)[msgnum] = newval;
6topprop = tostr(propname, "_top");
7oldtop = this.(topprop);
8newval = oldval + delta;
9needsort = 0;
10if (!oldtop)
11this.(topprop) = {{msgnum, newval}};
12return;
13elseif (i = $lu:iassoc(msgnum, oldtop))
14newtop = oldtop;
15newtop[i][2] = newval;
16needsort = 1;
17elseif (newval > oldtop[$][2])
18newtop = {@oldtop, {msgnum, newval}};
19needsort = 1;
20endif
21if (needsort)
22newtop = $lu:sort_alist(newtop, 2);
23newtop = $lu:reverse(newtop);
24this.(topprop) = newtop[1..min($, 250)];
25endif
26if (propname != "votecounts")
27return;
28endif
29oldbot = this.votecounts_bottom;
30newval = oldval + delta;
31needsort = 0;
32if (!oldbot)
33this.votecounts_bottom = {{msgnum, newval}};
34return;
35elseif (i = $lu:iassoc(msgnum, oldbot))
36newbot = oldbot;
37newbot[i][2] = newval;
38needsort = 1;
39elseif (newval < oldbot[1][2])
40newbot = {@oldbot, {msgnum, newval}};
41needsort = 1;
42endif
43if (needsort)
44newbot = $lu:sort_alist(newbot, 2);
45this.votecounts_bottom = newbot[1..min($, 250)];
46endif

display_top_seq

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1":display_top_seq([INT n [, STR sortby]]) => show the top n (sorted by sortby) messages on this folder to player. sortby can be upvotes (the default), totalvotes, or comments. n must be in the range 1-50.";
2{?n = 10, ?sortby = "upvotes"} = args;
3toplist = {};
4desc = "";
5if (sortby == "upvotes")
6toplist = this:top_n(n);
7desc = "vote score";
8elseif (sortby == "totalvotes")
9toplist = this:top_n(n, "totalvotes");
10desc = "total votes";
11elseif (sortby == "comments")
12toplist = this:top_n(n, "totalcomments");
13desc = "number of comments";
14elseif (sortby == "worst")
15toplist = this:bottom_n(n, "votecounts");
16desc = "worst score";
17else
18raise(E_INVARG);
19endif
20mcount = 0;
21width = player:linelen() || 79;
22if (!toplist)
23player:tell("There are no top messages by ", desc, " on *", this.name, ".");
24return;
25endif
26if (sortby == "worst")
27player:tell("Worst ", n, " messages on *", this.name, ":");
28else
29player:tell("Top ", n, " messages on *", this.name, ": (by ", desc, ")");
30endif
31for seqnum in ((typeof(toplist[1]) == LIST) ? $lu:slice(toplist) | toplist)
32player:tell();
33x = this.messages[seqnum];
34d = x[2][1];
35summary = this:msg_summary_line(@x[2]);
36if (typeof(summary) != LIST)
37summary = {summary};
38endif
39prefix = tostr($string_utils:right(x[1], 4), ":", "  ");
40player:tell($su:left(prefix + summary[1], -width));
41prefix = $su:space(length(prefix));
42for l in (summary[2..$])
43$cu:sin();
44player:tell($su:left(prefix + l, -width));
45yield;
46endfor
47yield;
48endfor

reset_top_counts

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1votes = [];
2totals = [];
3ccounts = [];
4done = 0;
5for m in (this.messages)
6seq = m[1];
7{yes, no} = m[2][8];
8log = m[2][9];
9vote = length(yes) - length(no);
10if (vote)
11votes[seq] = vote;
12endif
13total = length(yes) + length(no);
14if (total)
15totals[seq] = total;
16endif
17comments = 0;
18for l in (log)
19if ((length(l[3]) > 11) && (l[3][1..11] == "commented: "))
20comments = comments + 1;
21endif
22endfor
23if (comments)
24ccounts[seq] = comments;
25endif
26done = done + 1;
27yield 1;
28endfor
29this.votecounts = votes;
30this.totalvotes = totals;
31this.totalcomments = ccounts;
32for propname in ({"votecounts", "totalvotes", "totalcomments"})
33al = $hu:topN(this.(propname), 250, 1);
34yield;
35al = $lu:sort_alist(al, 2);
36al = $lu:reverse(al);
37yield;
38topprop = tostr(propname, "_top");
39this.(topprop) = al;
40yield;
41endfor
42al = $hu:bottomN(this.votecounts, 250, 1);
43yield;
44al = $lu:sort_alist(al, 2);
45yield;
46this.votecounts_bottom = al;
47return 1;

top_n bottom_n

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1":top_n([INT n [, STR propname]), return the top or bottom n message sequence from this list as determined by propname, defaults to votecounts. (you may also enjoy totalvotes or totalcomments.) n must be in the range 1-50.";
2{?n = 10, ?propname = "votecounts"} = args;
3if ((n > 50) || (n < 1))
4raise(E_INVARG, "n must be in the range 1-50");
5endif
6if (verb == "bottom_n")
7if (propname != "votecounts")
8raise(E_INVARG, "bottom_n is only valid with votecounts");
9endif
10endif
11suffix = (verb == "top_n") ? "_top" | "_bottom";
12propname = tostr(propname, suffix);
13nums = {};
14ok_statuses = this.ok_statuses_for_top;
15for tuple in (this.(propname))
16{msgnum, count} = tuple;
17seqnum = this:exists_num_eq(msgnum);
18if (!seqnum)
19continue;
20endif
21if ((!ok_statuses) || (this.messages[seqnum][2][6] in ok_statuses))
22nums = {@nums, {seqnum, count}};
23if (length(nums) == n)
24return nums;
25endif
26endif
27yield;
28endfor
29return nums;

status_msg_seq type_msg_seq

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1{mask, parsed_arg} = args;
2what = verb[1..index(verb, "_") - 1];
3plural = (what == "type") ? "types" | "statuses";
4prop = this.(plural);
5detail_index = (what in {"type", "status"}) + 4;
6matchvalue = 0;
7realval = "";
8do_not = 0;
9if ((length(parsed_arg) > 3) && (parsed_arg[1..3] == "not"))
10do_not = 1;
11parsed_arg = parsed_arg[4..$];
12endif
13for ti in [1..length(prop)]
14stripped = $ansi:strip(prop[ti]);
15if ((stripped == parsed_arg) || (index(stripped, parsed_arg) == 1))
16realval = prop[ti];
17matchvalue = ti;
18break;
19endif
20endfor
21if (!matchvalue)
22return tostr("Invalid ", what, " '", parsed_arg, "'.");
23endif
24i = 1;
25fseq = {};
26for msg in (caller.messages)
27if ((!mask) || (i < mask[1]))
28elseif ((length(mask) < 2) || (i < mask[2]))
29detail = msg[2][detail_index];
30if (detail == matchvalue)
31if (!do_not)
32fseq = $seq_utils:add(fseq, i, i);
33endif
34elseif (do_not)
35fseq = $seq_utils:add(fseq, i, i);
36endif
37else
38mask = mask[3..$];
39endif
40i = i + 1;
41yield;
42endfor
43return fseq || tostr("%f has no messages with the ", what, " of ", realval, ".");

assigned_msg_seq

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1{mask, parsed_arg} = args;
2who = #-1;
3if ((!parsed_arg) || (parsed_arg in {"none", "no-one", "nothing", "#-1", "nobody"}))
4"leave it as #-1";
5else
6who = $su:match_player(parsed_arg);
7if (!valid(who))
8return tostr("Who is '", parsed_arg, "'?");
9endif
10endif
11i = 1;
12fseq = {};
13for msg in (caller.messages)
14if ((!mask) || (i < mask[1]))
15elseif ((length(mask) < 2) || (i < mask[2]))
16assignee = msg[2][7];
17if (assignee == who)
18fseq = $seq_utils:add(fseq, i, i);
19endif
20else
21mask = mask[3..$];
22endif
23i = i + 1;
24yield;
25endfor
26return fseq || tostr("%f has no messages assigned to ", $su:nn(who), ".");

minvotes_msg_seq minscore_msg_seq

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1{mask, n} = args;
2do_total = verb == "minvotes_msg_seq";
3i = 1;
4fseq = {};
5for msg in (caller.messages)
6if ((!mask) || (i < mask[1]))
7elseif ((length(mask) < 2) || (i < mask[2]))
8{yes, no} = msg[2][8];
9add = 0;
10if (do_total)
11total = length(yes) + length(no);
12add = total >= n;
13else
14score = length(yes) - length(no);
15add = score >= n;
16endif
17if (add)
18fseq = $seq_utils:add(fseq, i, i);
19endif
20else
21mask = mask[3..$];
22endif
23i = i + 1;
24yield;
25endfor
26return fseq || tostr("%f has no messages with a ", verb[1..8], " of ", n, ".");

comment_msg_seq

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1{mask, texttomatch} = args;
2fseq = {};
3i = 1;
4for msg in (caller.messages)
5if ((!mask) || (i < mask[1]))
6elseif ((length(mask) < 2) || (i < mask[2]))
7log = msg[2][9];
8all_comments = $lu:slice(log, 3);
9all_comments = $su:from_list(all_comments);
10if (index(all_comments, texttomatch) != 0)
11fseq = $seq_utils:add(fseq, i, i);
12endif
13else
14mask = mask[3..$];
15endif
16i = i + 1;
17yield;
18endfor
19return fseq || tostr("%f has no messages with comments that have the text '", texttomatch, "'.");

parse_message_seq

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1"Copied from Generic Issue Tracking Mailing List (#295129):parse_message_seq by Seraph (#7195) Sun Jan 10 19:18:00 2010 CST";
2"parse_message_seq(strings,cur[,last_old])";
3"  strings is the <message-sequence> portion of the arg list.";
4"  cur is the number of the player's current message for this folder.";
5"Returns a string error message if the parse fails, otherwise";
6"returns a list {msg_seq, @unused_strings}, where";
7"   msg_seq is a handle understood by caller:display_seq_full/headers(), and ";
8"   unused_strings is the list of remaining uninterpreted strings";
9set_task_perms(caller_perms());
10{strings, ?cur = 0, ?last_old = 0} = args;
11if (!(nummsgs = this:length_all_msgs()))
12return "%f %<has> no messages.";
13elseif (typeof(strings) != LIST)
14strings = {strings};
15endif
16seq = result = {};
17mode = #0;
18orig_strings = strings;
19show_closed = "closed" in strings;
20if (show_closed)
21strings = listdelete(strings, show_closed);
22endif
23do_random = "random" in strings;
24if (do_random)
25strings = listdelete(strings, do_random);
26endif
27"... changes to 0 if we start seeing message numbers, to 1 if we see masks...";
28keywords = ":from:%from:to:%to:subject:body:before:after:since:until:first:last:kept:unkept:minvotes:minscore:type:status:comment:assigned";
29keyalist = {{1, "from"}, {6, "%from"}, {12, "to"}, {15, "%to"}, {19, "subject"}, {27, "body"}, {32, "before"}, {39, "after"}, {45, "since"}, {51, "until"}, {57, "first"}, {63, "last"}, {68, "kept"}, {73, "unkept"}, {80, "minvotes"}, {89, "minscore"}, {98, "type"}, {103, "status"}, {110, "comment"}, {118, "assigned"}};
30strnum = 0;
31for string in (strings)
32strnum = strnum + 1;
33$command_utils:suspend_if_needed(0);
34if (string && ((c = index(string, ":")) && ((k = index(keywords, ":" + string[1..c - 1])) && (k == rindex(keywords, ":" + string[1..c - 1])))))
35"...we have a mask to apply...";
36keywd = $list_utils:assoc(k, keyalist)[2];
37if (mode == #0)
38seq = {1, nummsgs + 1};
39endif
40mode = 1;
41if (k <= 27)
42"...from, subject, to, body...";
43show_closed = 1;
44pattern = string[c + 1..$];
45if (keywd in {"subject", "body"})
46elseif (keywd[1] == "%")
47pattern = $string_utils:explode(pattern, "|");
48else
49pattern = $mail_agent:((keywd == "to") ? "_parse_to" | "_parse_from")(pattern);
50if (typeof(pattern) == STR)
51return pattern;
52endif
53endif
54seq = this:(keywd + "_msg_seq")(pattern, seq);
55if (typeof(seq) == STR)
56if (strnum == 1)
57return seq;
58else
59seq = {};
60endif
61endif
62elseif (k <= 51)
63"...before, since, after, until...";
64show_closed = 1;
65if (typeof(date = $mail_agent:_parse_date(string[c + 1..$])) != INT)
66return tostr("Bad date `", string, "':  ", date);
67endif
68s = this:length_date_le((keywd in {"before", "since"}) ? date - 1 | (date + 86399));
69if (keywd in {"before", "until"})
70seq = $seq_utils:remove(seq, s + 1, nummsgs);
71else
72seq = $seq_utils:remove(seq, 1, s);
73endif
74elseif (k <= 63)
75"...first, last...";
76show_closed = 1;
77if (n = toint(string[c + 1..$]))
78seq = $seq_utils:(keywd + "n")(seq, n);
79else
80return tostr("Bad number in `", string, "'");
81endif
82elseif (k <= 73)
83"...kept, unkept...";
84show_closed = 1;
85if (c < length(string))
86return tostr("Unexpected junk after `", keywd, ":'");
87elseif ((!(seq = this:(keywd + "_msg_seq")(seq))) && (strnum == 1))
88return tostr("%f %<has> no ", keywd, " messages.");
89endif
90elseif (k <= 89)
91"...new: minvotes, minscore...";
92nstr = string[c + 1..$];
93n = toint(nstr);
94if (tostr(n) == nstr)
95seq = this:(keywd + "_msg_seq")(seq, n);
96else
97return tostr("Bad number in `", string, "'");
98endif
99elseif (k <= 118)
100"...new: type, status, comment, assigned.";
101if (keywd in {"status", "comment"})
102show_closed = 1;
103endif
104arg = string[c + 1..$];
105seq = this:(keywd + "_msg_seq")(seq, arg);
106if (typeof(seq) == STR)
107return seq;
108endif
109else
110return "Unknown k value " + tostr(k);
111endif
112else
113"...continue building the present sequence...";
114if (mode)
115if (seq)
116if (!show_closed)
117seq = this:unclosed_msg_seq_filter(seq);
118endif
119result = $seq_utils:union(result, seq);
120seq = {};
121endif
122endif
123mode = 0;
124if (!string)
125"...default case for @read: get the current message but skip to the next one if it's not there...";
126if (cur)
127i = min(this:length_num_le(cur - 1) + 1, nummsgs);
128seq = $seq_utils:add(seq, i, i);
129else
130return "%f %<has> no current message.";
131endif
132elseif ((index(string, "next") == 1) && (!index(string, "-")))
133string[1..4] = "";
134if ((n = string ? toint(string) | 1) <= 0)
135return tostr("Bad number `", string, "'");
136elseif ((i = this:length_num_le(cur) + 1) <= nummsgs)
137seq = $seq_utils:add(seq, i, min((i + n) - 1, nummsgs));
138else
139return "%f %<has> no next message.";
140endif
141elseif ((index(string, "prev") == 1) && (!index(string, "-")))
142string[1..4] = "";
143if ((n = string ? toint(string) | 1) <= 0)
144return tostr("Bad number `", string, "'");
145elseif (i = this:length_num_le(cur - 1))
146seq = $seq_utils:add(seq, max(1, (i - n) + 1), i);
147else
148return "%f %<has> no previous message.";
149endif
150elseif (string == "new")
151s = last_old ? this:length_date_le(last_old) | this:length_num_le(cur);
152if (s < nummsgs)
153seq = $seq_utils:add(seq, s + 1, nummsgs);
154else
155return "%f %<has> no new messages.";
156endif
157elseif (string == "first")
158seq = $seq_utils:add(seq, 1, 1);
159elseif (n = toint(string) || (((string in {"last", "$"}) && -1) || ((string == "cur") && cur)))
160if (n <= 0)
161seq = $seq_utils:add(seq, max(0, nummsgs + n) + 1, nummsgs);
162elseif (i = this:exists_num_eq(n))
163seq = $seq_utils:add(seq, i, i);
164else
165return (string == "cur") ? "%f's current message has been removed." | tostr("%f %<has> no message numbered `", string, "'.");
166endif
167elseif (((i = index(string, "..")) > 1) || ((i = index(string, "-")) > 1))
168if ((start = toint(sst = string[1..i - 1])) > 0)
169s = this:length_num_le(start - 1);
170elseif (sst in {"next", "prev", "cur"})
171s = max(0, this:length_num_le(cur - (sst != "next")) - (sst == "prev"));
172elseif (sst in {"last", "$"})
173s = nummsgs - 1;
174elseif (sst == "first")
175s = 0;
176else
177"final positive outcome #1";
178result = $seq_utils:union(result, seq);
179if (do_random && result)
180rand = $seq_utils:random(result);
181result = {rand, rand + 1};
182endif
183return {result, @strings[strnum..$]};
184endif
185j = (string[i] == ".") ? i + 2 | (i + 1);
186if ((end = toint(est = string[j..$])) > 0)
187e = this:length_num_le(end);
188elseif (est in {"next", "prev", "cur"})
189e = min(nummsgs, this:length_num_le(cur - (est == "prev")) + (est == "next"));
190elseif (est in {"last", "$"})
191e = nummsgs;
192elseif (est == "first")
193e = 1;
194else
195"final positive outcome #2";
196result = $seq_utils:union(result, seq);
197if (do_random && result)
198rand = $seq_utils:random(result);
199result = {rand, rand + 1};
200endif
201return {result, @strings[strnum..$]};
202endif
203if (s < e)
204seq = $seq_utils:add(seq, s + 1, e);
205else
206return tostr("%f %<has> no messages in range ", string, ".");
207endif
208elseif (string == "cur")
209return "%f %<has> no current message.";
210else
211"final positive outcome #3";
212result = $seq_utils:union(result, seq);
213if (do_random && result)
214rand = $seq_utils:random(result);
215result = {rand, rand + 1};
216endif
217return {result, @strings[strnum..$]};
218endif
219endif
220endfor
221if ((mode && seq) && (!show_closed))
222seq = this:unclosed_msg_seq_filter(seq);
223endif
224"final positive outcome #4";
225result = $seq_utils:union(result, seq);
226if (do_random)
227if (!result)
228if (length(orig_strings) == 1)
229result = {1, nummsgs + 1};
230else
231return {result};
232endif
233endif
234rand = $seq_utils:random(result);
235result = {rand, rand + 1};
236endif
237return {result};

display_top_allfolders

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1":display_top_allfolders([INT n [, STR sortby]]) => show the top n (sorted by sortby) messages on all issue-tracking folders to player. sortby can be upvotes (the default), totalvotes, or comments. n must be in the range 1-50.";
2{?n = 10, ?sortby = "upvotes"} = args;
3allseqs = {};
4folders = $ou:leaves($issue_list);
5desc = "";
6top_n_args = {n};
7if (sortby == "upvotes")
8desc = "vote score";
9elseif (sortby == "totalvotes")
10top_n_args = {n, "totalvotes"};
11desc = "total votes";
12elseif (sortby == "comments")
13top_n_args = {n, "totalcomments"};
14desc = "number of comments";
15else
16raise(E_INVARG);
17endif
18for f in (folders)
19topn = f:top_n(@top_n_args);
20for tuple in (topn)
21{seqnum, count} = tuple;
22allseqs = {@allseqs, {f, seqnum, count}};
23endfor
24yield;
25endfor
26allseqs = $lu:sort_alist(allseqs, 3);
27yield;
28allseqs = $lu:reverse(allseqs);
29yield;
30mcount = 0;
31width = player:linelen() || 79;
32player:tell("Top ", n, " messages on issue-tracking lists: (by ", desc, ")");
33for tuple in (allseqs)
34{f, seqnum, count} = tuple;
35x = f.messages[seqnum];
36d = x[2][1];
37summary = f:msg_summary_line(@x[2]);
38if (typeof(summary) != LIST)
39summary = {summary};
40endif
41prefices = {"", ""};
42prefices[1] = $su:right("*" + f.name, -6) + " ";
43prefices[2] = tostr($string_utils:right(x[1], 4), ":", "  ");
44spacefix = $su:space(length(prefices[1]));
45for i in [1..2]
46player:tell($su:left(prefices[i] + summary[i], -width));
47endfor
48for l in (summary[3..$])
49player:tell($su:left(spacefix + l, -width));
50yield;
51endfor
52mcount = mcount + 1;
53if (mcount == n)
54return;
55endif
56yield;
57endfor

rm_message_seq

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1if (!player.programmer)
2return E_PERM;
3else
4return pass(@args);
5endif

do_combine

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1{seq, who, destseqnum} = args;
2postmerge_status = this.postmerge_status;
3target_msg = this.messages[destseqnum];
4{yes, no} = target_msg[2][8];
5{orig_yes, orig_no} = {yes, no};
6newlogs = {};
7now = time();
8authortxt = target_msg[2][2];
9orig_author = `toobj(authortxt[rindex(authortxt, " ") + 2..$ - 1]) ! ANY => #-1';
10for s in ($seq_utils:tolist(seq))
11msg = this.messages[s];
12authortxt = msg[2][2];
13author = `toobj(authortxt[rindex(authortxt, " ") + 2..$ - 1]) ! ANY => #-1';
14player:tell("Merging ", msg[1], " by ", $su:nn(author));
15{myes, mno} = msg[2][8];
16yes = $set_utils:union(yes, myes, valid(author) ? {author} | {});
17yield;
18no = $set_utils:union(no, mno);
19yield;
20player:tell("Total yes votes ", length(yes), " and total no ", length(no));
21if (postmerge_status)
22msg[2][6] = postmerge_status;
23endif
24newlogs = {@newlogs, {now, who, tostr("merged votes from duplicate ", msg[1])}};
25this.messages[s] = msg;
26yield;
27endfor
28yes = setremove(yes, orig_author);
29target_msg[2][8] = {yes, no};
30target_msg[2][9] = {@target_msg[2][9], @newlogs};
31this.messages[destseqnum] = target_msg;
32oldscore = length(orig_yes) - length(orig_no);
33newscore = length(yes) - length(no);
34if (oldscore != newscore)
35change = newscore - oldscore;
36this:update_counts(target_msg[1], change, "votecounts");
37endif
38yield;
39oldcount = length(orig_yes) + length(orig_no);
40newcount = length(yes) + length(no);
41if (oldcount != newcount)
42change = newcount - oldcount;
43this:update_counts(target_msg[1], change, "totalvotes");
44endif

_@combine

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1{seq, rest} = args;
2verb = verb[2..$];
3if (rest)
4if ((rest[1] != "with") || (length(rest) != 2))
5player:tell("Usage: @combine <msg[s]> on <folder> with <msg>");
6return;
7endif
8destmsg_str = rest[2];
9endif
10destmsg = toint(destmsg_str);
11if (tostr(destmsg) != destmsg_str)
12player:tell("Destination message must be a valid message number.");
13return;
14endif
15destseqnum = this:exists_num_eq(destmsg);
16if (!destseqnum)
17player:tell("There is no message numbered ", destmsg, " on *", this.name, ".");
18return;
19endif
20if ((seqsz = $seq_utils:size(seq)) > 1)
21if (!$cu:yes_or_no(tostr("This will affect ", seqsz, " messages. Is that okay?")))
22player:tell("Aborted.");
23return;
24endif
25endif
26this:do_combine(seq, player, destseqnum);
27this:add_log(seq, player, tostr("merged into ", destmsg));
28this:mailnet_announce(seq, tostr("merged into ", destmsg, " by ", player.name));
29player:tell($ansi.cyan, "Merged ", this:fm(seq), " with ", destmsg, ".", $ansi.reset);

do_retitle

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1{seq, who, newsubj} = args;
2if ($seq_utils:size(seq) > 1)
3raise(E_INVARG);
4endif
5s = seq[1];
6oldsubj = this.messages[s][2][4];
7this.messages[s][2][4] = newsubj;
8return oldsubj;

_@retitle

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1{seq, rest} = args;
2verb = verb[2..$];
3newsubj = "";
4if (rest)
5if ((rest[1] != "to") || (length(rest) < 2))
6player:tell("Usage: @retitle <msg> on <folder> [to <text>]");
7return;
8endif
9newsubj = $su:from_list(rest[2..$], " ");
10endif
11if ((seqsz = $seq_utils:size(seq)) > 1)
12player:tell("You can only retitle one message at a time.");
13return;
14endif
15if (!newsubj)
16player:tell($ansi.cyan, "Retitling ", this:fms(seq), ".", $ansi.reset);
17newsubj = $command_utils:read("enter the new subject line");
18endif
19oldsubj = this:do_retitle(seq, player, newsubj);
20if ((!oldsubj) || (oldsubj == "  "))
21oldsubj = "blank";
22else
23oldsubj = ("was: '" + oldsubj) + "'";
24endif
25this:add_log(seq, player, ("changed subject (" + oldsubj) + ")");
26this:mailnet_announce(seq, tostr(player.name, " changed subject (", oldsubj, ")"));
27player:tell($ansi.cyan, this:fm(seq), " retitled.", $ansi.reset);

_@annotate

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1{seq, rest} = args;
2verb = verb[2..$];
3comment = "";
4if (rest)
5if (rest[1] == "with")
6rest = rest[2..$];
7endif
8comment = $su:from_list(rest, " ");
9endif
10if ((seqsz = $seq_utils:size(seq)) > 1)
11if (!$cu:yes_or_no(tostr("This will affect ", seqsz, " messages. Is that okay?")))
12player:tell("Aborted.");
13return;
14endif
15endif
16if (!comment)
17player:tell($ansi.cyan, "Annotating ", this:fms(seq), ".", $ansi.reset);
18comment = $command_utils:read("type a one-line comment");
19endif
20comment = $su:escape(comment);
21this:add_log(seq, player, "annotated: " + comment);
22this:mailnet_announce(seq, tostr($ansi.yellow, player.name, ": ", comment), 1);
23player:tell($ansi.cyan, "Annotation added to ", this:fm(seq), ".", $ansi.reset);

_@attach

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1{what, seq} = args;
2verb = verb[2..$];
3if ((seqsz = $seq_utils:size(seq)) > 1)
4player:tell("You can't attach to multiple messages. Pick one.");
5return;
6endif
7authortxt = this.messages[seq[1]][2][2];
8author = `toobj(authortxt[rindex(authortxt, " ") + 2..$ - 1]) ! ANY => #-1';
9player:tell($ansi.cyan, "[ Attaching to ", this:fms(seq), ": ]", $ansi.reset);
10player:tell($ansi.cyan, "[ Only admins will be able to see this data. ]", $ansi.reset);
11player:tell($ansi.cyan, $ansi.bold_on, "   Object: '", what:name(), "' -- at '", what.location:name(), "'", $ansi.reset);
12if (!$cu:yes_or_no("Attach?"))
13player:tell("Aborted.");
14return;
15endif
16comment = $cu:read("Add an optional comment (one line) or just press enter:");
17text = tostr("attached: ", $su:nn(what), " (parent ", parent(what), ") at ", $su:nn(what.location), @comment ? {" (", comment, ")"} | {});
18this:add_log(seq, player, text);
19this:mailnet_announce(seq, tostr(player.name, " attached an object reference."));
20player:tell($ansi.cyan, "Attached object to ", this:fm(seq), ".", $ansi.reset);

display_assigned_allfolders

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1{?who = player} = args;
2did_one = 0;
3for f in ($ou:leaves($issue_list))
4n = f:length_all_msgs();
5all = {1, n + 1};
6seq = {};
7ok = f.ok_statuses_for_top;
8for i in [1..length(f.messages)]
9if ((f.messages[i][2][7] == who) && (f.messages[i][2][6] in ok))
10seq = $seq_utils:add(seq, i, i);
11endif
12yield;
13endfor
14if (seq)
15player:tell("Active issues on *", f.name, ":");
16f:display_seq_headers(seq, 0, $maxint, 0);
17did_one = 1;
18endif
19yield;
20endfor
21if (!did_one)
22player:tell("You have no active issues on any issue lists.");
23else
24player:tell("--- end of active issues ---");
25endif

unclosed_msg_seq_filter

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1{mask} = args;
2fseq = {};
3open_statuses = this.ok_statuses_for_top;
4if (!open_statuses)
5"this list doesn't have a concept of open/closed";
6return mask;
7endif
8i = 1;
9for msg in (caller.messages)
10if ((!mask) || (i < mask[1]))
11elseif ((length(mask) < 2) || (i < mask[2]))
12status = msg[2][6];
13if (status in open_statuses)
14fseq = $seq_utils:add(fseq, i, i);
15endif
16else
17mask = mask[3..$];
18endif
19i = i + 1;
20yield;
21endfor
22return fseq;

report_text

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1{seqnum} = args;
2msg = this.messages[seqnum][2];
3fromtxt = msg[2];
4status = msg[6];
5assignee = msg[7];
6from_obj = fromtxt[rindex(fromtxt, " ") + 2..$ - 1];
7from = toobj(from_obj).name;
8asgn = valid(assignee) ? assignee.name | "???";
9infoline = tostr(this:fms({seqnum, seqnum + 1}), " from ", from);
10attribution = tostr(this:txt_status(status), " by ", asgn);
11return {attribution, infoline};

_add_to_report

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1{seq} = args;
2to_add = {};
3for s in ($seq_utils:tolist(seq))
4to_add = {@to_add, this:report_text(s)};
5yield;
6endfor
7this.to_report = {@this.to_report, @to_add};

title

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1return "*" + this.name;

is_writable_by

Spec this none thisFlags rxdOwner #29Definer #293

Referenced by

Source

1"Copied from Generic Mail Recipient (#45):is_writable_by by Hacker (#36) Wed Oct 14 05:32:54 2009 CDT";
2who = args[1];
3if (who.wizard)
4return 1;
5elseif (who in this.banned)
6return 0;
7elseif (!this.writers)
8return $perm_utils:controls(who, this);
9elseif (typeof(this.writers) == INT)
10return this.writers;
11else
12for x in (this.writers)
13if (is_a(who, x))
14return 1;
15endif
16endfor
17endif
18return 0;

_@mailban _@mcbain

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1{seq, rest} = args;
2verb = verb[2..$];
3comment = "";
4if (!player.wizard)
5player:tell("Can't do that, get a wiz.");
6return;
7endif
8if (rest)
9comment = $su:from_list(rest, " ");
10endif
11if ((seqsz = $seq_utils:size(seq)) > 1)
12player:tell("You can mailban for one particular message.");
13endif
14index = seq[1];
15msg = this.messages[index];
16authortxt = msg[2][2];
17author = `toobj(authortxt[rindex(authortxt, " ") + 2..$ - 1]) ! ANY => #-1';
18if (author in this.banned)
19player:tell($su:nn(author), " is already banned.");
20endif
21player:systell("Banning the author of ", this:fms(seq), ".");
22player:systell("This will ban ", $su:nn(author), " from ever posting on *", this.name, ".");
23if (!comment)
24player:tell($ansi.cyan, "Ban reason:", $ansi.reset);
25comment = $command_utils:read("type a one-line comment");
26endif
27if (!$cu:yes_or_no(tostr("Really ban ", author.name, "?")))
28player:tell("Aborted.");
29return;
30endif
31this:add_log(seq, player, (($ansi.red + $ansi.bold) + this:banned_msg()) + $ansi.reset, 1);
32if (comment)
33this:add_log(seq, player, "Ban reason: " + comment, 1);
34endif
35this.banned = {@this.banned, author};
36this:mailnet_announce(seq, tostr(player.name, ": ", author.name, " has been permanently banned from *", this.name, "."));
37player:tell($ansi.cyan, author.name, " has been banned from *", this.name, ".", $ansi.reset);

banned_msg

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1if (typeof(m = this.banned_msg) == LIST)
2return m[random($)];
3else
4return m;
5endif

pms_old

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1"Copied from Generic Issue Tracking Mailing List (#295129):parse_message_seq by Seraph (#7195) Sun Jan 10 19:18:00 2010 CST";
2"parse_message_seq(strings,cur[,last_old])";
3"  strings is the <message-sequence> portion of the arg list.";
4"  cur is the number of the player's current message for this folder.";
5"Returns a string error message if the parse fails, otherwise";
6"returns a list {msg_seq, @unused_strings}, where";
7"   msg_seq is a handle understood by caller:display_seq_full/headers(), and ";
8"   unused_strings is the list of remaining uninterpreted strings";
9set_task_perms(caller_perms());
10{strings, ?cur = 0, ?last_old = 0} = args;
11if (!(nummsgs = this:length_all_msgs()))
12return "%f %<has> no messages.";
13elseif (typeof(strings) != LIST)
14strings = {strings};
15endif
16seq = result = {};
17mode = #0;
18orig_strings = strings;
19show_closed = "closed" in strings;
20if (show_closed)
21strings = listdelete(strings, show_closed);
22endif
23do_random = "random" in strings;
24if (do_random)
25strings = listdelete(strings, do_random);
26endif
27"... changes to 0 if we start seeing message numbers, to 1 if we see masks...";
28keywords = ":from:%from:to:%to:subject:body:before:after:since:until:first:last:kept:unkept:minvotes:minscore:type:status:comment:assigned";
29keyalist = {{1, "from"}, {6, "%from"}, {12, "to"}, {15, "%to"}, {19, "subject"}, {27, "body"}, {32, "before"}, {39, "after"}, {45, "since"}, {51, "until"}, {57, "first"}, {63, "last"}, {68, "kept"}, {73, "unkept"}, {80, "minvotes"}, {89, "minscore"}, {98, "type"}, {103, "status"}, {110, "comment"}, {118, "assigned"}};
30strnum = 0;
31for string in (strings)
32strnum = strnum + 1;
33$command_utils:suspend_if_needed(0);
34if (string && ((c = index(string, ":")) && ((k = index(keywords, ":" + string[1..c - 1])) && (k == rindex(keywords, ":" + string[1..c - 1])))))
35"...we have a mask to apply...";
36keywd = $list_utils:assoc(k, keyalist)[2];
37if (mode == #0)
38seq = {1, nummsgs + 1};
39endif
40mode = 1;
41if (k <= 27)
42"...from, subject, to, body...";
43show_closed = 1;
44pattern = string[c + 1..$];
45if (keywd in {"subject", "body"})
46elseif (keywd[1] == "%")
47pattern = $string_utils:explode(pattern, "|");
48else
49pattern = $mail_agent:((keywd == "to") ? "_parse_to" | "_parse_from")(pattern);
50if (typeof(pattern) == STR)
51return pattern;
52endif
53endif
54seq = this:(keywd + "_msg_seq")(pattern, seq);
55if (typeof(seq) == STR)
56if (strnum == 1)
57return seq;
58else
59seq = {};
60endif
61endif
62elseif (k <= 51)
63"...before, since, after, until...";
64show_closed = 1;
65if (typeof(date = $mail_agent:_parse_date(string[c + 1..$])) != INT)
66return tostr("Bad date `", string, "':  ", date);
67endif
68s = this:length_date_le((keywd in {"before", "since"}) ? date - 1 | (date + 86399));
69if (keywd in {"before", "until"})
70seq = $seq_utils:remove(seq, s + 1, nummsgs);
71else
72seq = $seq_utils:remove(seq, 1, s);
73endif
74elseif (k <= 63)
75"...first, last...";
76show_closed = 1;
77if (n = toint(string[c + 1..$]))
78seq = $seq_utils:(keywd + "n")(seq, n);
79else
80return tostr("Bad number in `", string, "'");
81endif
82elseif (k <= 73)
83"...kept, unkept...";
84show_closed = 1;
85if (c < length(string))
86return tostr("Unexpected junk after `", keywd, ":'");
87elseif ((!(seq = this:(keywd + "_msg_seq")(seq))) && (strnum == 1))
88return tostr("%f %<has> no ", keywd, " messages.");
89endif
90elseif (k <= 89)
91"...new: minvotes, minscore...";
92nstr = string[c + 1..$];
93n = toint(nstr);
94if (tostr(n) == nstr)
95seq = this:(keywd + "_msg_seq")(seq, n);
96else
97return tostr("Bad number in `", string, "'");
98endif
99elseif (k <= 118)
100"...new: type, status, comment, assigned.";
101if (keywd in {"status", "comment"})
102show_closed = 1;
103endif
104arg = string[c + 1..$];
105seq = this:(keywd + "_msg_seq")(seq, arg);
106if (typeof(seq) == STR)
107return seq;
108endif
109else
110return "Unknown k value " + tostr(k);
111endif
112else
113"...continue building the present sequence...";
114if (mode)
115if (seq)
116if (!show_closed)
117seq = this:unclosed_msg_seq_filter(seq);
118endif
119result = $seq_utils:union(result, seq);
120seq = {};
121endif
122endif
123mode = 0;
124if (!string)
125"...default case for @read: get the current message but skip to the next one if it's not there...";
126if (cur)
127i = min(this:length_num_le(cur - 1) + 1, nummsgs);
128seq = $seq_utils:add(seq, i, i);
129else
130return "%f %<has> no current message.";
131endif
132elseif ((index(string, "next") == 1) && (!index(string, "-")))
133string[1..4] = "";
134if ((n = string ? toint(string) | 1) <= 0)
135return tostr("Bad number `", string, "'");
136elseif ((i = this:length_num_le(cur) + 1) <= nummsgs)
137seq = $seq_utils:add(seq, i, min((i + n) - 1, nummsgs));
138else
139return "%f %<has> no next message.";
140endif
141elseif ((index(string, "prev") == 1) && (!index(string, "-")))
142string[1..4] = "";
143if ((n = string ? toint(string) | 1) <= 0)
144return tostr("Bad number `", string, "'");
145elseif (i = this:length_num_le(cur - 1))
146seq = $seq_utils:add(seq, max(1, (i - n) + 1), i);
147else
148return "%f %<has> no previous message.";
149endif
150elseif (string == "new")
151s = last_old ? this:length_date_le(last_old) | this:length_num_le(cur);
152if (s < nummsgs)
153seq = $seq_utils:add(seq, s + 1, nummsgs);
154else
155return "%f %<has> no new messages.";
156endif
157elseif (string == "first")
158seq = $seq_utils:add(seq, 1, 1);
159elseif (n = toint(string) || (((string in {"last", "$"}) && -1) || ((string == "cur") && cur)))
160if (n <= 0)
161seq = $seq_utils:add(seq, max(0, nummsgs + n) + 1, nummsgs);
162elseif (i = this:exists_num_eq(n))
163seq = $seq_utils:add(seq, i, i);
164else
165return (string == "cur") ? "%f's current message has been removed." | tostr("%f %<has> no message numbered `", string, "'.");
166endif
167elseif (((i = index(string, "..")) > 1) || ((i = index(string, "-")) > 1))
168if ((start = toint(sst = string[1..i - 1])) > 0)
169s = this:length_num_le(start - 1);
170elseif (sst in {"next", "prev", "cur"})
171s = max(0, this:length_num_le(cur - (sst != "next")) - (sst == "prev"));
172elseif (sst in {"last", "$"})
173s = nummsgs - 1;
174elseif (sst == "first")
175s = 0;
176else
177"final positive outcome #1";
178result = $seq_utils:union(result, seq);
179if (do_random && result)
180rand = $seq_utils:random(result);
181result = {rand, rand + 1};
182endif
183return {result, @strings[strnum..$]};
184endif
185j = (string[i] == ".") ? i + 2 | (i + 1);
186if ((end = toint(est = string[j..$])) > 0)
187e = this:length_num_le(end);
188elseif (est in {"next", "prev", "cur"})
189e = min(nummsgs, this:length_num_le(cur - (est == "prev")) + (est == "next"));
190elseif (est in {"last", "$"})
191e = nummsgs;
192elseif (est == "first")
193e = 1;
194else
195"final positive outcome #2";
196result = $seq_utils:union(result, seq);
197if (do_random && result)
198rand = $seq_utils:random(result);
199result = {rand, rand + 1};
200endif
201return {result, @strings[strnum..$]};
202endif
203if (s < e)
204seq = $seq_utils:add(seq, s + 1, e);
205else
206return tostr("%f %<has> no messages in range ", string, ".");
207endif
208elseif (string == "cur")
209return "%f %<has> no current message.";
210else
211"final positive outcome #3";
212result = $seq_utils:union(result, seq);
213if (do_random && result)
214rand = $seq_utils:random(result);
215result = {rand, rand + 1};
216endif
217return {result, @strings[strnum..$]};
218endif
219endif
220endfor
221if ((mode && seq) && (!show_closed))
222seq = this:unclosed_msg_seq_filter(seq);
223endif
224"final positive outcome #4";
225result = $seq_utils:union(result, seq);
226if (do_random)
227if (!result)
228if (length(orig_strings) == 1)
229result = {1, nummsgs + 1};
230else
231return {result};
232endif
233endif
234rand = $seq_utils:random(result);
235result = {rand, rand + 1};
236endif
237return {result};

old_txt_log

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1"Copied from Generic Issue Tracking Mailing List (#295129):txt_log by Seraph (#7195) Mon Jan 18 14:12:16 2010 CST";
2log = args[1];
3if (!log)
4return {};
5endif
6txt_log = {""};
7m = "";
8for x in (log)
9who = $mail_agent:mail_name_for(x[2], 1);
10if ((length(x[3]) >= 11) && (x[3][1..11] == "commented: "))
11comment = x[3][12..$];
12comment = $su:word_wrap({comment}, 52);
13m = tostr($ansi.dark_gray, "> ", $su:left(who, -12), " ", comment[1]);
14txt_log = {@txt_log, m};
15m = tostr($ansi.dark_gray, "  ", $su:left($time_utils:abbrev_ctime(x[1]), 12), " ", (length(comment) >= 2) ? comment[2] | "");
16txt_log = {@txt_log, m};
17for c in (comment[3..$])
18c = tostr($ansi.dark_gray, c, $ansi.reset);
19txt_log = {@txt_log, "               " + c};
20endfor
21else
22m = tostr($ansi.dark_gray, "> ", $time_utils:abbrev_ctime(x[1]), "  ", who, " ", x[3], $ansi.reset);
23txt_log = {@txt_log, m};
24endif
25endfor
26return txt_log;

on_status_change on_assign_change on_type_change

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

No program (verb defined but unprogrammed).

add_bottom

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1al = $hu:bottomN(this.votecounts, 250);
2yield;
3al = $lu:sort_alist(al, 2);
4yield;
5this.votecounts_bottom = al;
6return 1;

is_votable_by

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1return this:is_writable_by(@args);

is_commentable_by

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1return this:is_writable_by(@args);

comment_extra

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1":comment_extra(OBJ commenter, INT when) => {STR color, LIST of lines to add after the comment}";
2{who, when} = args;
3return {};

jdn_msg_seq

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1{jdn} = args;
2{begin, end} = $tu:jdn_to_interval(jdn);
3msgs = this.messages;
4i = length(msgs);
5matching = {};
6while (i >= 1)
7msg = msgs[i];
8msgtime = msg[2][1];
9if ((msgtime <= end) && (msgtime >= begin))
10matching = {@matching, msg[1]};
11elseif (matching)
12matching = $lu:reverse(matching);
13return $seq_utils:from_sorted_list(matching);
14elseif (msgtime < begin)
15return {};
16endif
17i = i - 1;
18endwhile
19return {};

most_interesting

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1":most_interesting([INT delta from today]) -> most interesting message for today (or a day that is delta days from today)";
2{?delta = 0} = args;
3jdn = $tu:julian_day_number() + delta;
4{begin, end} = $tu:jdn_to_interval(jdn);
5msgs = this.messages;
6i = length(msgs);
7top_detail = 0;
8top_i = 0;
9tried_one = 0;
10while (i >= 1)
11msg = msgs[i];
12msgtime = msg[2][1];
13if ((msgtime <= end) && (msgtime >= begin))
14votes = msg[2][8];
15action = msg[2][9];
16n_yes = length(votes[1]);
17n_no = length(votes[2]);
18n_action = length(action);
19if (n_yes > top_detail)
20top_i = i;
21top_detail = n_yes;
22elseif (n_no > top_detail)
23top_i = i;
24top_detail = n_yes;
25elseif (n_action > top_detail)
26top_i = i;
27top_detail = n_action;
28endif
29tried_one = 1;
30elseif (tried_one)
31return top_i ? msgs[top_i] | {};
32elseif (msgtime < begin)
33return {};
34endif
35yield;
36i = i - 1;
37endwhile
38return {};

_@commentban

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

none

Source

1{seq, rest, author} = args;
2if (author in this.banned)
3player:tell($su:nn(author), " is already banned.");
4return;
5endif
6if ((seqsz = $seq_utils:size(seq)) > 1)
7player:tell("You can mailban for one particular message.");
8endif
9comment = "";
10if (rest)
11comment = $su:from_list(rest, " ");
12endif
13player:systell("Banning ", $su:nn(author), " for a comment in ", this:fms(seq), ".");
14player:systell("This will ban ", $su:nn(author), " from ever posting on *", this.name, ".");
15if (!comment)
16player:tell($ansi.cyan, "Ban reason:", $ansi.reset);
17comment = $command_utils:read("type a one-line comment");
18endif
19if (!$cu:yes_or_no(tostr("Really ban ", author.name, "?")))
20player:tell("Aborted.");
21return;
22endif
23this:add_log(seq, player, (((($ansi.red + $ansi.bold) + "(") + $su:uppercase(author.name)) + " WAS BANNED FOR COMMENTS IN THIS POST)") + $ansi.reset, 1);
24if (comment)
25this:add_log(seq, player, "Commentban reason: " + comment, 1);
26endif
27this.banned = {@this.banned, author};
28this:mailnet_announce(seq, tostr(player.name, ": ", author.name, " has been permanently banned from *", this.name, "."));
29player:tell($ansi.cyan, author.name, " has been banned from *", this.name, ".", $ansi.reset);

txt_from

Spec this none thisFlags rxdOwner #361Definer #293

Referenced by

Source

1return args[1];