new object $channel_ui: $user_interfaces;
var $channel_ui active_channels = #[];
var $channel_ui channel_creation = 1;
var $channel_ui channel_dict = #[];
var $channel_ui credits = ["Chuck and Brad"];
var $has_commands local = \
#[["@desc-c?hannel", [["@desc-c?hannel", "* as *", "@desc-c?hannel <any> as <any>", 'describe_channel_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]],\
["@join-lock-channel|@jlc",\
[["@join-lock-channel|@jlc", "* with|to *", "@join-lock-channel|@jlc <any> with|to <any>", 'channel_add_lock_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]],\
["@leave-lock-channel|@llc",\
[["@leave-lock-channel|@llc", "* with|to *", "@leave-lock-channel|@llc <any> with|to <any>", 'channel_add_lock_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]],\
["@use-lock-channel|@ulc",\
[["@use-lock-channel|@ulc", "* with|to *", "@use-lock-channel|@ulc <any> with|to <any>", 'channel_add_lock_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]],\
["@add-channel-manager|@acm",\
[["@add-channel-manager|@acm", "* to *", "@add-channel-manager|@acm <user> to <any>", 'channel_add_manager, #[[1, ['user, []]], [3, ['any, []]]]]]],\
["@del-channel-manager|@dcm",\
[["@del-channel-manager|@dcm", "* from *", "@del-channel-manager|@dcm <user> from <any>", 'channel_del_manager, #[[1, ['user, []]], [3, ['any, []]]]]]],\
["@add-ch?annel|@addcom",\
[["@add-ch?annel|@addcom", "*", "@add-ch?annel|@addcom <any>", 'addcom_cmd, #[[1, ['any, []]]]]]],\
["@del-ch?annel|@delcom",\
[["@del-ch?annel|@delcom", "*", "@del-ch?annel|@delcom <any>", 'delcom_cmd, #[[1, ['any, []]]]]]],\
["@purge-channel",\
[["@purge-channel", "*", "@purge-channel <any>", 'channel_purge_cmd, #[[1, ['any, []]]]]]],\
["@ch?annels",\
[["@ch?annels", "*", "@ch?annels <any:+f?ull +d?etailed>", 'channels_cmd, #[[1, ['any_opt, ["f?ull", "d?etailed"]]]]]]]];
var $has_commands remote = #[];
var $has_commands shortcuts = #[];
var $root created_on = 838251646;
var $root flags = ['variables, 'methods, 'code, 'command_cache, 'fertile, 'core];
var $root inited = 1;
var $root managed = [$channel_ui];
var $root manager = $channel_ui;
var $root trusted_by = [$channel_db];
public method ._broadcast() {
arg channel, message;
var q;
if (!(caller() in [$channel_ui, $user, $sys]))
throw(~perm, "You are not allowed to call $channel_ui._broadcast() directly");
for q in ($user_db.connected())
q.channel_msg(channel, message);
};
private method ._del_active_channel() {
arg key;
active_channels = active_channels.del(key);
};
public method ._del_channel_dict() {
arg key;
channel_dict = channel_dict.del(key);
};
public method .active_channels() {
return active_channels;
};
protected method .addcom_cmd() {
arg cmdstr, cmd, args;
var elements, db, channel, lowerchannel, msg;
(> .perms(caller(), 'command) <);
elements = args.explode("=");
if ((elements.length()) != 2) {
return "Syntax: @addcom <alias>=<channel_name>";
} else if (channel_dict.contains(elements[1])) {
return "You are already using that alias for a channel.";
} else {
channel = tosym(elements[2]);
lowerchannel = tosym((elements[2]).lowercase());
db = (| $channel_db.search(lowerchannel) |) || 0;
if (type(db) == 'list) {
if ((type(db[3]) == 'frob) && ((!((db[3]).try(sender()))) && (!($sys.is_system(sender())))))
return ("Sorry, channel " + (db[1])) + " is join-locked.";
msg = (("Channel " + (elements[2])) + " added with alias ") + (elements[1]);
} else if (.can_create_channel()) {
db = [channel, 0, 0, 0, sender(), [sender()], 0, 0];
$channel_db.insert(lowerchannel, db);
msg = (("Channel " + (elements[2])) + " created with alias ") + (elements[1]);
} else {
return "Sorry, that channel doesn't exist, and you are not authorized to create new channels.";
}
}
$channel_db.value_changed(lowerchannel, db.replace(2, (db[2]) + 1));
channel_dict = channel_dict.add(elements[1], db[1]);
.channel_on(db[1]);
return msg;
};
public method .broadcast() {
arg channel, msg;
var q, spammer_name, message;
(> .perms(sender()) <);
// is this really a command?. If so, do the command.
catch any {
switch (msg) {
case "who":
if ((channel in ($channel_db.system_channels())) && (!($sys.is_system(sender()))))
return "Sorry, that's a listen only channel.";
return .channel_members(channel);
case "off":
.channel_off(channel);
return;
case "on":
.channel_on(channel);
return;
}
} with {
return (traceback()[1])[2];
}
if ((channel in ($channel_db.system_channels())) && (channel != 'All))
return "Sorry, that's a listen only channel.";
if (!(active_channels.contains(channel)))
return "You must be on a channel to send a message to it.";
// check for poses, thinking, etc.
spammer_name = .name();
switch (msg[1]) {
case ":":
message = (spammer_name + " ") + (msg.subrange(2));
case "%":
message = ((spammer_name + " . o O ( ") + (msg.subrange(2))) + " )";
case "!":
(> .channel_moderator_ok() <);
message = msg.subrange(2);
default:
message = (spammer_name + ": ") + msg;
}
._broadcast(channel, message);
};
public method .can_create_channel() {
if ((sender().has_ancestor($user)) && (($channel_ui.channel_creation()) || ($sys.is_system(sender()))))
return 1;
else
return 0;
};
protected method .channel_add_lock_cmd() {
arg cmdstr, cmd, this, prep, str;
var channel, db, lock, mode, modestr;
(> .perms(caller(), 'command) <);
if ((cmd[2]) == "j") {
mode = 3;
modestr = "join";
} else if ((cmd[2]) == "l") {
mode = 4;
modestr = "leave";
} else {
mode = 8;
modestr = "use";
}
channel = tosym(this.lowercase());
db = (| $channel_db.search(channel) |) || 0;
if (type(db) == 'list) {
if ((!(sender() in (db[6]))) && (!($sys.is_system(sender())))) {
return "Sorry, you're not on the manager list for that channel.";
} else if ((str.length()) == 0) {
$channel_db.value_changed(channel, db.replace(mode, 0));
return ((("You un-" + modestr) + "lock channel ") + (db[1])) + ".";
} else {
catch ~objnf, ~parse {
lock = $lock_parser.parse(str, sender());
$channel_db.value_changed(channel, db.replace(mode, lock));
return ((((("You " + modestr) + "lock channel ") + (db[1])) + " with ") + (lock.lock_name('thing))) + ".";
} with {
switch (error()) {
case ~objnf:
return "Object not found in lock string.";
case ~parse:
return "Invalid lock string.";
}
}
}
} else {
return "Channel not found, nothing locked.";
}
};
public method .channel_add_manager() {
arg cmdstr, cmd, user, prep, channel;
var db, channel;
channel = (| tosym(channel.lowercase()) |) || 0;
if (channel == 0)
return "@add-channel-manager|@acm <user> to <channel>";
db = (| $channel_db.search(channel) |) || 0;
if (db == 0)
return "That channel does not exist.";
if ((sender() != (db[5])) && (!($sys.is_system(sender()))))
return "You are not the channel owner.";
if (user in (db[6]))
return ((user.name()) + " is already a manager of channel ") + (db[1]);
$channel_db.value_changed(channel, db.replace(6, [@db[6], user]));
return "Manager added.";
};
public method .channel_alias() {
arg ch_alias;
return (| channel_dict[ch_alias] |) || "";
};
public method .channel_command() {
arg cmd, args, opts, detailed, full;
var ch, syn, cmd;
syn = ("Syntax: " + cmd) + " <channel> <command>";
if (listlen(args) < 2)
return [syn, "Where <command> is one of: WHO, OFF, ON, or INFO"];
[ch, cmd, @args] = args;
switch (cmd) {
case "who":
if ((ch in ($channel_db.system_channels())) && (!($sys.is_system(this()))))
return "Sorry, that's a listen only channel.";
return .channel_members(ch, full);
case "off":
.channel_off(ch);
return;
case "on":
.channel_on(ch);
return;
case "info":
return;
default:
return ("Unknown @channel command: " + cmd) + ", should be: WHO, OFF, ON or INFO";
}
};
public method .channel_creation() {
return channel_creation;
};
public method .channel_del_manager() {
arg cmdstr, cmd, user, prep, channel;
var db, channel;
channel = (| tosym(channel.lowercase()) |) || 0;
if (channel == 0)
return "@add-channel-manager|@acm <user> from <channel>";
db = (| $channel_db.search(channel) |) || 0;
if (db == 0)
return "That channel does not exist.";
if ((sender() != (db[5])) && (!($sys.is_system(sender()))))
return "You are not the channel owner.";
if (!(user in (db[6])))
return ((user.name()) + " is not a manager of channel ") + (db[1]);
$channel_db.value_changed(channel, db.replace(6, (db[6]).del(user)));
return "Manager deleted.";
};
public method .channel_dict() {
return channel_dict;
};
public method .channel_member() {
arg channel;
return channel in dict_values(channel_dict || #[]);
};
public method .channel_members() {
arg channel, @full;
var q, members, name, who, line;
members = [];
[(full ?= 0)] = full;
if (full) {
line = ("All members of channel " + channel) + " ('*'=listening, '!'=not connected):";
who = $user_db.user_dbrefs();
} else {
line = ("Connected members of channel " + channel) + " ('*'=listening):";
who = $user_db.connected();
}
for q in (who) {
if (!valid(q))
continue;
if (q.channel_member(channel)) {
if (q.connected())
name = " " + (q.name());
else
name = "!" + (q.name());
if (q.listen_channel(channel))
members += ["*" + name];
else
members += [" " + name];
}
}
return ([line] + ((members.vcolumnize(4, (.linelen()) - 4)).prefix(" "))) + ["---"];
};
public method .channel_moderator_ok() {
(> .check_mojo() <);
return 1;
};
public method .channel_msg() {
arg channel, msg;
(caller() == definer()) || (> .perms(sender(), 'system) <);
if ((channel == 'All) || (active_channels.contains(channel)))
.tell((("<" + channel) + "> ") + msg);
};
protected method .channel_off() {
arg channel;
if (active_channels.contains(channel)) {
if (channel in ($channel_db.system_channels()))
.tell(("<" + channel) + "> You have left this channel.");
else
.broadcast(channel, ":has left this channel.");
active_channels = active_channels.del(channel);
} else {
.tell("You are not on this channel.");
}
};
protected method .channel_on() {
arg channel;
if (!(active_channels.contains(channel))) {
active_channels = active_channels.add(channel, 1);
if (channel in ($channel_db.system_channels()))
.tell(("<" + channel) + "> You have joined this channel");
else
.broadcast(channel, ":has joined this channel.");
} else {
.tell("You are already on this channel.");
}
};
public method .channel_purge_cmd() {
arg cmdstr, cmd, channel;
var db, channel, connected, u;
channel = (| tosym(channel.lowercase()) |) || 0;
if (channel == 0)
return "@purge-channel <channel>";
db = (| $channel_db.search(channel) |) || 0;
if (db == 0)
return "That channel does not exist.";
if ((sender() != (db[5])) && (!($sys.is_system(sender()))))
return "You are not the channel owner.";
$channel_db.remove(channel);
connected = $user_db.connected();
for u in ((((($user_db.database()).to_dict()).to_list()).slice(2)).compress()) {
if ((u in connected) && (((u.channel_dict()).invert()).contains(db[1])))
u.tell((("<" + (db[1])) + "> Channel deleted by ") + (sender().name()));
(| u._del_active_channel(db[1]) |);
(| u._del_channel_dict(((u.channel_dict()).invert())[db[1]]) |);
pause();
}
return "Channel deleted.";
};
protected method .channels_cmd() {
arg cmdstr, cmd, args;
var opts, f, d, cur_channels, cd_keys, cd_values, i, alias, db, active, msg, match_with, match_pattern, tmp, form, add, o;
(> .perms(caller(), 'command) <);
[args, opts] = args;
o = opts.slice(1);
if ((f = (| "f?ull" in o |)))
f = (opts[f])[3];
if ((d = (| "d?etailed" in o |)))
d = (opts[d])[3];
if (listlen(args) > 1) {
catch any {
cmd = (| ($channel_db.search(args[1]))[1] |);
return .channel_members(cmd, f);
} with {
return (traceback()[1])[2];
}
}
cd_keys = channel_dict.keys();
cd_values = channel_dict.values();
cur_channels = f ? ((($channel_db.database()).values()).slice(1)) : cd_values;
if (args) {
match_with = (| .get_setting("match-with", $programmer) |) || 'match_pattern;
match_pattern = (| (args[1])[1] |) || ((| .get_setting("match-default", $programmer) |) || "*");
cur_channels = filter f in (cur_channels) where ((f.to_string()).(match_with)(match_pattern) != 0);
}
if (!cur_channels)
return "No channels found.";
msg = [];
add = [];
for i in (cur_channels) {
alias = (| cd_keys[i in cd_values] |) || "";
db = (| $channel_db.search(tostr(i)) |);
if (type(db) == 'list) {
msg += [[(active_channels.contains(i)) ? "*" : " ", alias, tostr(db[1]), (db[7]) || "<no description>"]];
form = "%26r: %50l";
if (d) {
tmp = [form.format("Number of users", tostr(db[2])), form.format("Owner", (db[5]).name()), form.format("Managers", ((db[6]).mmap('namef, 'name)).to_english())];
if (db[3])
tmp += [form.format("Join Lock", (db[3]).lock_name())];
if (db[4])
tmp += [form.format("Leave Lock", (db[4]).lock_name())];
if (db[8])
tmp += [form.format("Use Lock", (db[8]).lock_name())];
add += [tmp];
}
} else {
msg += [[(active_channels.contains(i)) ? "*" : " ", alias, "", "Channel not in database!"]];
}
refresh();
}
msg = (msg.transpose()).tabulate([["", ""], ["Alias", "-----"], ["Channel", "-------"], ["Description", "-----------"]]);
if (d)
msg = [msg[1], msg[2], @map i in [3 .. msg.length()] to ([msg[i]] + (add[i - 2])).sum()];
return [@msg, " -----"];
};
protected method .delcom_cmd() {
arg cmdstr, cmd, args;
var db, channel, del_from_db, msg, dict_var;
(> .perms(caller(), 'command) <);
del_from_db = 1;
msg = ("Channel alias " + args) + " deleted.";
if (!args)
return ("Syntax: " + cmd) + " <channel>";
dict_var = channel_dict[args];
channel = (| (((channel_dict[args]).to_string()).lowercase()).to_symbol() |) || 0;
if (type(channel) == 'symbol) {
db = (| $channel_db.search(channel) |) || 0;
if (type(db) == 'list) {
if ((type(db[4]) == 'frob) && ((!((db[4]).try(sender()))) && (!($sys.is_system(sender())))))
return "Channel leave locked, you can't leave it!";
} else {
del_from_db = 0;
msg = ("That channel does not seem to be in the channel database. Channel alias " + args) + " deleted.";
}
} else {
return "You do not have that channel alias defined.";
}
if (del_from_db)
$channel_db.value_changed(channel, db.replace(2, (db[2]) - 1));
if (active_channels.contains(dict_var))
.channel_off(dict_var);
channel_dict = channel_dict.del(args);
return msg;
};
protected method .describe_channel_cmd() {
arg cmdstr, cmd, channel, prep, desc;
var db, channel;
(> .perms(caller(), 'command) <);
channel = (| tosym(channel.lowercase()) |) || 0;
if (channel == 0)
return "@desc-ch?annel <channel> as <description>";
db = (| $channel_db.search(channel) |) || 0;
if (db == 0)
return "That channel does not exist.";
if ((!(sender() in (db[6]))) && (!($sys.is_system(sender()))))
return "You are not a manager for channel " + (db[1]);
$channel_db.value_changed(channel, db.replace(7, desc));
return "Description updated.";
};
protected method .init_channel_ui() {
channel_dict = #[];
active_channels = #[];
};
public method .listen_channel() {
arg channel;
if (active_channels.contains(channel))
return 1;
return 0;
};
public method .uninit_channel_ui() {
var c, channel, db;
for c in (.channel_dict()) {
if ((| active_channels[c[2]] |) || 0)
.channel_off(c[2]);
channel = (| tosym(((c[2]).to_string()).lowercase()) |) || 0;
if (type(channel) == 'symbol) {
db = (| $channel_db.search(channel) |) || 0;
if (type(db) == 'list)
$channel_db.value_changed(channel, db.replace(2, (db[2]) - 1));
}
}
active_channels = #[];
channel_dict = #[];
};