#kiwi a img { border:none; }
#kiwi .format_span a { color: inherit; background-color: inherit; text-decoration: inherit; font-style: inherit; font-weight: inherit;}
+#kiwi h1,
+#kiwi h2,
+#kiwi h3 {
+ margin-top: 22px;
+ margin-bottom: 11px;
+}
+#kiwi h4,
+#kiwi h5,
+#kiwi h6 {
+ margin-top: 11px;
+ margin-bottom: 11px;
+}
+#kiwi h1 { font-size: 46px; }
+#kiwi h2 { font-size: 40px; }
+#kiwi h3 { font-size: 34px; }
+#kiwi h4 { font-size: 28px; }
+#kiwi h5 { font-size: 22px; }
+#kiwi h6 { font-size: 16px; }
+
/**
* Main layout blocks
display: inline-block;
}
-#kiwi .settings_container h1 {
- margin-top: 22px;
- margin-bottom: 11px;
- font-size: 46px;
-}
-
-#kiwi .settings_container h2 {
- margin-top: 22px;
- margin-bottom: 11px;
- font-size: 40px;
-}
-
-#kiwi .settings_container h3 {
- margin-top: 22px;
- margin-bottom: 11px;
- font-size: 34px;
-}
-
-#kiwi .settings_container h4 {
- margin-top: 11px;
- margin-bottom: 11px;
- font-size: 28px;
-}
-
-#kiwi .settings_container h5 {
- margin-top: 11px;
- margin-bottom: 11px;
- font-size: 22px;
-}
-
-#kiwi .settings_container h6 {
- margin-top: 11px;
- margin-bottom: 11px;
- font-size: 16px;
-}
-
#kiwi .settings_container label {
cursor: pointer;
}
-#kiwi .settings_container input,
-#kiwi .settings_container select,
-#kiwi .settings_container textarea {
- width: 100%;
+#kiwi_ form label { display: block; }
+#kiwi form input,
+#kiwi form select,
+#kiwi form textarea {
+ /*width: 100%;
+ box-sizing: border-box;*/
}
-#kiwi .settings_container input[size],
-#kiwi .settings_container select[size],
-#kiwi .settings_container textarea[size] {
+#kiwi form input[size],
+#kiwi form select[size],
+#kiwi form textarea[size] {
width: auto;
}
-#kiwi .settings_container input[type="file"],
-#kiwi .settings_container input[type="image"],
-#kiwi .settings_container input[type="submit"],
-#kiwi .settings_container input[type="reset"],
-#kiwi .settings_container input[type="button"] {
+#kiwi form input[type="file"],
+#kiwi form input[type="image"],
+#kiwi form input[type="submit"],
+#kiwi form input[type="reset"],
+#kiwi form input[type="button"] {
width: auto;
}
-#kiwi .settings_container input[type="radio"] {
+#kiwi form input[type="radio"] {
width: auto;
cursor: pointer;
margin-top: 2px;
}
-#kiwi .settings_container input[type="checkbox"] {
+#kiwi form input[type="checkbox"] {
width: auto;
cursor: pointer;
margin-top: 3px;
}
-#kiwi .settings_container .radio,
-#kiwi .settings_container .checkbox {
+#kiwi form .radio,
+#kiwi form .checkbox {
margin-bottom: 10px;
padding-left: 20px;
}
-#kiwi .settings_container .radio:last-child,
-#kiwi .settings_container .checkbox:last-child {
+#kiwi form .radio:last-child,
+#kiwi form .checkbox:last-child {
margin-bottom: 0;
}
-#kiwi .settings_container .radio input[type="radio"],
-#kiwi .settings_container .checkbox input[type="checkbox"] {
+#kiwi form .radio input[type="radio"],
+#kiwi form .checkbox input[type="checkbox"] {
float: left;
margin-left: -20px;
}
-#kiwi .settings_container .radio+.radio,
-#kiwi .settings_container .checkbox+.checkbox {
+#kiwi form .radio+.radio,
+#kiwi form .checkbox+.checkbox {
margin-top: -7px;
}
width: 75px;
}
-#kiwi .settings_container .control-group {
+#kiwi .control-group {
margin: 0 0 20px 20px;
}
-#kiwi .settings_container .control-group:last-child {
+#kiwi .control-group:last-child {
margin-bottom: 0;
}
}
+#kiwi .schannel_info {}
+#kiwi .channel_info label { display: block; }
+#kiwi .channel_info .channel_url {
+ display: none;
+}
+#kiwi .channel_info .remove-ban { cursor: pointer; }
+
+
padding:10px; left: 0px;
background: #1B1B1B; color:#eeeeee;
}
-#kiwi.theme_relaxed .controlbox .nickchange input { padding:0.3em 0.5em; margin-left: 0.5em; }
+#kiwi.theme_relaxed .controlbox .nickchange input { padding:0.3em 0.5em; margin-left: 0.5em; width: 165px; }
#kiwi.theme_relaxed .controlbox .nickchange button { padding:0.5em; margin: 0 0.5em 0 1em; }
#kiwi.theme_mini .messages .msg { border-bottom: 1px solid #DEDEDE; padding: 5px; font-family:arial; font-size:0.9em; }
#kiwi.theme_mini .messages .msg .time { display:none; }
-#kiwi.theme_mini .messages .msg .nick { display:block; font-family:Arial; text-transform:capitalize; }
+#kiwi.theme_mini .messages .msg .nick { display:block; font-family:Arial; text-tranform:capitalize; }
#kiwi.theme_mini .messages .msg .text { display:block; white-space:pre-wrap; word-wrap:break-word; font-family:arial; }
#kiwi.theme_mini .messages .msg.action .nick { }
var funcs = {\r
kiwi: 'kiwi', raw: 'raw', kick: 'kick', topic: 'topic',\r
part: 'part', join: 'join', action: 'action', ctcp: 'ctcp',\r
- notice: 'notice', msg: 'privmsg', changeNick: 'changeNick'\r
+ notice: 'notice', msg: 'privmsg', changeNick: 'changeNick',\r
+ channelInfo: 'channelInfo', mode: 'mode'\r
};\r
\r
// Proxy each gateway method\r
</script>\r
\r
\r
+ <script type="text/html" id="tmpl_channel_info">\r
+ <div class="channel_info">\r
+ <h6><%= channel_name %></h6>\r
+ <b class="channel_url"><a href=""></a></b>\r
+\r
+ <div class="control-group">\r
+ <form class="channel_info_modes">\r
+ <label>\r
+ <input type="checkbox" name="channel_mute" class="channel-mode" data-mode="m" />\r
+ Moderated chat\r
+ </label>\r
+ <label>\r
+ <input type="checkbox" name="channel_invite" class="channel-mode" data-mode="i" />\r
+ Invite only\r
+ </label>\r
+ <label>\r
+ <input type="checkbox" name="channel_topic" class="channel-mode" data-mode="t" />\r
+ Only operators can change the topic\r
+ </label>\r
+ <label>\r
+ <input type="checkbox" name="channel_external_messages" class="channel-mode" data-mode="n" />\r
+ Block messages from outside this channel\r
+ </label>\r
+ <label>\r
+ Password\r
+ <input type="text" name="channel_key" class="channel-mode" data-mode="k" />\r
+ </label>\r
+ </form>\r
+ </div>\r
+\r
+ <div class="control-group">\r
+ <form class="channel_banlist">\r
+ <button class="show_banlist">Show banlist</button>\r
+ <table>\r
+ <thead>\r
+ <tr>\r
+ <td>Bank Mask</td>\r
+ <td>Added By</td>\r
+ <td>Date Added</td>\r
+ <td></td>\r
+ </tr>\r
+ </thead>\r
+ <tbody>\r
+ </tbody>\r
+ </table>\r
+ </form>\r
+ </div>\r
+ </div>\r
+ </script>\r
+\r
+\r
<script type="text/html" id="tmpl_userbox">\r
<div class="userbox">\r
<a class="close_menu if_op op"><i class="icon-star"></i><%= op %></a>\r
\r
<script type="text/html" id="tmpl_applet_settings">\r
<div class="settings_container">\r
- <section>\r
- <h6>Theme</h6>\r
- <div class="control-group">\r
- <div class="thumbnails">\r
- <a class="thumbnail" data-setting="theme" data-value="relaxed" href="#">\r
- <div class="thumbnail_wrapper"><div class="theme_color" style="background-color: #e7e7e7;"></div></div>\r
- <div class="caption"><u>Relaxed</u></div>\r
- </a>\r
- <a class="thumbnail" data-setting="theme" data-value="mini" href="#">\r
- <div class="thumbnail_wrapper"><div class="theme_color" style="background-color: #fff;"></div></div>\r
- <div class="caption"><u>Mini</u></div>\r
- </a>\r
- <a class="thumbnail" data-setting="theme" data-value="cli" href="#">\r
- <div class="thumbnail_wrapper"><div class="theme_color" style="background-color: #222;"></div></div>\r
- <div class="caption"><u>CLI</u></div>\r
- </a>\r
- <a class="thumbnail" data-setting="theme" data-value="basic" href="#">\r
- <div class="thumbnail_wrapper"><div class="theme_color" style="background-color: #e7e7e7;"></div></div>\r
- <div class="caption"><u>Basic</u></div>\r
- </a>\r
+ <form>\r
+ <section>\r
+ <h6>Theme</h6>\r
+ <div class="control-group">\r
+ <div class="thumbnails">\r
+ <a class="thumbnail" data-setting="theme" data-value="relaxed" href="#">\r
+ <div class="thumbnail_wrapper"><div class="theme_color" style="background-color: #e7e7e7;"></div></div>\r
+ <div class="caption"><u>Relaxed</u></div>\r
+ </a>\r
+ <a class="thumbnail" data-setting="theme" data-value="mini" href="#">\r
+ <div class="thumbnail_wrapper"><div class="theme_color" style="background-color: #fff;"></div></div>\r
+ <div class="caption"><u>Mini</u></div>\r
+ </a>\r
+ <a class="thumbnail" data-setting="theme" data-value="cli" href="#">\r
+ <div class="thumbnail_wrapper"><div class="theme_color" style="background-color: #222;"></div></div>\r
+ <div class="caption"><u>CLI</u></div>\r
+ </a>\r
+ <a class="thumbnail" data-setting="theme" data-value="basic" href="#">\r
+ <div class="thumbnail_wrapper"><div class="theme_color" style="background-color: #e7e7e7;"></div></div>\r
+ <div class="caption"><u>Basic</u></div>\r
+ </a>\r
+ </div>\r
</div>\r
- </div>\r
- </section>\r
-\r
- <section>\r
- <h6>Channels</h6>\r
- <div class="control-group">\r
- <div class="radio">\r
- <label>\r
- <input type="radio" name="channel_list_style" data-setting="channel_list_style" value="tabs">\r
- <%= tabs %>\r
- </label>\r
- </div>\r
- <div class="radio">\r
- <label>\r
- <input type="radio" name="channel_list_style" data-setting="channel_list_style" value="list">\r
- <%= list %><small class="text-muted">(<%= large_amounts_of_chans %>)</small>\r
- </label>\r
+ </section>\r
+\r
+ <section>\r
+ <h6>Channels</h6>\r
+ <div class="control-group">\r
+ <div class="radio">\r
+ <label>\r
+ <input type="radio" name="channel_list_style" data-setting="channel_list_style" value="tabs">\r
+ <%= tabs %>\r
+ </label>\r
+ </div>\r
+ <div class="radio">\r
+ <label>\r
+ <input type="radio" name="channel_list_style" data-setting="channel_list_style" value="list">\r
+ <%= list %><small class="text-muted">(<%= large_amounts_of_chans %>)</small>\r
+ </label>\r
+ </div>\r
</div>\r
- </div>\r
- </section>\r
-\r
- <section>\r
- <h6>Chat window</h6>\r
- <div class="control-group">\r
- <div class="checkbox">\r
+ </section>\r
+\r
+ <section>\r
+ <h6>Chat window</h6>\r
+ <div class="control-group">\r
+ <div class="checkbox">\r
+ <label>\r
+ <input data-setting="show_joins_parts" type="checkbox">\r
+ <%= join_part %>\r
+ </label>\r
+ </div>\r
+ <div class="checkbox">\r
+ <label>\r
+ <input data-setting="show_timestamps" type="checkbox">\r
+ <%= timestamps %>\r
+ </label>\r
+ </div>\r
+ <div class="checkbox">\r
+ <label>\r
+ <input data-setting="mute_sounds" type="checkbox">\r
+ <%= mute %>\r
+ </label>\r
+ </div>\r
+ <div class="checkbox">\r
+ <label>\r
+ <input data-setting="show_emoticons" type="checkbox">\r
+ <%= emoticons %>\r
+ </label>\r
+ </div>\r
<label>\r
- <input data-setting="show_joins_parts" type="checkbox">\r
- <%= join_part %>\r
+ <input data-setting="scrollback" class="input-small" type="text" size="4" pattern="\d*">\r
+ <span><%= scroll_history %></span>\r
</label>\r
</div>\r
- <div class="checkbox">\r
- <label>\r
- <input data-setting="show_timestamps" type="checkbox">\r
- <%= timestamps %>\r
- </label>\r
+ </section>\r
+\r
+ <section class="language">\r
+ <h6>Language</h6>\r
+ <div class="control-group">\r
+ <select data-setting="locale">\r
+ <% _.forEach(languages, function(lang) { %>\r
+ <option value="<%= lang.tag %>"><%= lang.language %></li>\r
+ <% }); %>\r
+ </select>\r
+ <br>\r
+ <small><%= locale_restart_needed %></small>\r
</div>\r
- <div class="checkbox">\r
- <label>\r
- <input data-setting="mute_sounds" type="checkbox">\r
- <%= mute %>\r
- </label>\r
+ </section>\r
+\r
+ <section class="protocol_handler">\r
+ <h6><%= default_client %></h6>\r
+ <div class="control-group">\r
+ <button class="register_protocol"><%= make_default %></button>\r
+ <br>\r
+ <small><%= default_note %></small>\r
</div>\r
- <div class="checkbox">\r
- <label>\r
- <input data-setting="show_emoticons" type="checkbox">\r
- <%= emoticons %>\r
- </label>\r
- </div>\r
- <label>\r
- <input data-setting="scrollback" class="input-small" type="text" size="4" pattern="\d*">\r
- <span><%= scroll_history %></span>\r
- </label>\r
- </div>\r
- </section>\r
-\r
- <section class="language">\r
- <h6>Language</h6>\r
- <div class="control-group">\r
- <select data-setting="locale">\r
- <% _.forEach(languages, function(lang) { %>\r
- <option value="<%= lang.tag %>"><%= lang.language %></li>\r
- <% }); %>\r
- </select>\r
- <br>\r
- <small><%= locale_restart_needed %></small>\r
- </div>\r
- </section>\r
-\r
- <section class="protocol_handler">\r
- <h6><%= default_client %></h6>\r
- <div class="control-group">\r
- <button class="register_protocol"><%= make_default %></button>\r
- <br>\r
- <small><%= default_note %></small>\r
- </div>\r
- </section>\r
-\r
- <section class="notification_enabler">\r
- <h6><%= html5_notifications %></h6>\r
- <div class="control-group">\r
- <button class="enable_notifications"><%= enable_notifications %></button>\r
- </div>\r
- </section>\r
+ </section>\r
\r
+ <section class="notification_enabler">\r
+ <h6><%= html5_notifications %></h6>\r
+ <div class="control-group">\r
+ <button class="enable_notifications"><%= enable_notifications %></button>\r
+ </div>\r
+ </section>\r
+ </form>\r
</div>\r
</script>\r
\r
'/voice': '/quote mode $channel +v $1+',\r
'/devoice': '/quote mode $channel -v $1+',\r
'/k': '/kick $channel $1+',\r
+ '/ban': '/quote mode $channel +b $1+',\r
+ '/unban': '/quote mode $channel -b $1+',\r
\r
// Misc aliases\r
'/slap': '/me slaps $1 around a bit with a large trout'\r
\r
controlbox.on('command:encoding', encodingCommand);\r
\r
+ controlbox.on('command:info', function(ev) {\r
+ var active_panel = _kiwi.app.panels().active;\r
+\r
+ if (!active_panel.isChannel())\r
+ return;\r
+\r
+ new _kiwi.model.ChannelInfo({channel: _kiwi.app.panels().active});\r
+ });\r
+\r
controlbox.on('command:css', function (ev) {\r
var queryString = '?reload=' + new Date().getTime();\r
$('link[rel="stylesheet"]').each(function () {\r
this.addMsg('', 'Window cleared');\r
\r
this.view.render();\r
+ },\r
+\r
+\r
+ setMode: function(mode_string) {\r
+ this.get('network').gateway.mode(this.get('name'), mode_string);\r
}\r
});\r
--- /dev/null
+_kiwi.model.ChannelInfo = Backbone.Model.extend({
+ initialize: function () {
+ this.view = new _kiwi.view.ChannelInfo({"model": this});
+ }
+});
\ No newline at end of file
this.sendData(connection_id, data, callback);\r
};\r
\r
+ /**\r
+ * Retrieves channel information\r
+ */\r
+ this.channelInfo = function (connection_id, channel, callback) {\r
+ var data = {\r
+ method: 'channel_info',\r
+ args: {\r
+ channel: channel\r
+ }\r
+ };\r
+\r
+ this.sendData(connection_id, data, callback);\r
+ };\r
+\r
/**\r
* Leaves a channel\r
* @param {String} channel The channel to part\r
this.sendData(connection_id, data, callback);\r
};\r
\r
+ /**\r
+ * Sets a mode for a target\r
+ */\r
+ this.mode = function (connection_id, target, mode_string, callback) {\r
+ data = {\r
+ method: 'raw',\r
+ args: {\r
+ data: 'MODE ' + target + ' ' + mode_string\r
+ }\r
+ };\r
+\r
+ this.sendData(connection_id, data, callback);\r
+ };\r
+\r
+\r
/**\r
* Sends ENCODING change request to server.\r
* @param {String} new_encoding The new proposed encode\r
this.gateway.on('topicsetby', onTopicSetBy, this);
this.gateway.on('userlist', onUserlist, this);
this.gateway.on('userlist_end', onUserlistEnd, this);
+ this.gateway.on('banlist', onBanlist, this);
this.gateway.on('mode', onMode, this);
this.gateway.on('whois', onWhois, this);
this.gateway.on('whowas', onWhowas, this);
this.gateway.on('list_start', onListStart, this);
this.gateway.on('irc_error', onIrcError, this);
this.gateway.on('unknown_command', onUnknownCommand, this);
+ this.gateway.on('channel_info', onChannelInfo, this);
},
// Check if we have the panel already. If not, create it
channel = that.panels.getByName(channel_name);
if (!channel) {
- channel = new _kiwi.model.Channel({name: channel_name});
+ channel = new _kiwi.model.Channel({name: channel_name, network: that});
that.panels.add(channel);
}
var c, members, user;
c = this.panels.getByName(event.channel);
if (!c) {
- c = new _kiwi.model.Channel({name: event.channel});
+ c = new _kiwi.model.Channel({name: event.channel, network: this});
this.panels.add(c);
}
// If a panel isn't found for this PM, create one
panel = this.panels.getByName(event.nick);
if (!panel) {
- panel = new _kiwi.model.Channel({name: event.nick});
+ panel = new _kiwi.model.Channel({name: event.nick, network: this});
this.panels.add(panel);
}
+ function onChannelInfo(event) {
+ var channel = this.panels.getByName(event.channel);
+ if (!channel) return;
+
+ if (event.url) {
+ channel.set('info_url', event.url);
+ } else if (event.modes) {
+ channel.set('info_modes', event.modes);
+ }
+ }
+
+
+
function onUserlist(event) {
var channel;
channel = this.panels.getByName(event.channel);
+ function onBanlist(event) {
+ console.log('banlist', event);
+ var channel = this.panels.getByName(event.channel);
+ if (!channel)
+ return;
+
+ channel.set('banlist', event.bans || []);
+ }
+
+
+
function onMode(event) {
var channel, i, prefixes, members, member, find_prefix;
--- /dev/null
+// var f = new _kiwi.model.ChannelInfo({channel: _kiwi.app.panels().active});
+
+_kiwi.view.ChannelInfo = Backbone.View.extend({
+ events: {
+ 'click .show_banlist': 'updateBanlist',
+ 'change .channel-mode': 'onModeChange',
+ 'click .remove-ban': 'onRemoveBanClick'
+ },
+
+
+ initialize: function () {
+ var that = this,
+ network,
+ channel = this.model.get('channel'),
+ text = {
+ channel_name: channel.get('name')
+ };
+
+ this.$el = $(_.template($('#tmpl_channel_info').html().trim(), text));
+
+ // Create the menu box this view will sit inside
+ this.menu = new _kiwi.view.MenuBox();
+ this.menu.addItem('channel_info', this.$el);
+ this.menu.$el.appendTo(channel.view.$container);
+ this.menu.show();
+
+ // Menu box will call this destroy on closing
+ this.$el.dispose = _.bind(this.dispose, this);
+
+ // Display the info we have, then listen for further changes
+ this.updateInfo(channel);
+ channel.on('change:info_modes change:info_url change:banlist', this.updateInfo, this);
+
+ // Request the latest info for ths channel from the network
+ channel.get('network').gateway.channelInfo(channel.get('name'));
+ },
+
+
+ render: function () {
+ },
+
+
+ onModeChange: function(event) {
+ var $this = $(event.currentTarget),
+ channel = this.model.get('channel'),
+ mode = $this.data('mode'),
+ mode_string = '';
+
+ if ($this.attr('type') == 'checkbox') {
+ mode_string = $this.is(':checked') ? '+' : '-';
+ mode_string += mode;
+ channel.setMode(mode_string);
+
+ return;
+ }
+
+ if ($this.attr('type') == 'text') {
+ mode_string = $this.val() ?
+ '+' + mode + ' ' + $this.val() :
+ '-' + mode;
+
+ channel.setMode(mode_string);
+
+ return;
+ }
+ },
+
+
+ onRemoveBanClick: function (event) {
+ event.preventDefault();
+ event.stopPropagation();
+
+ var $this = $(event.currentTarget),
+ $tr = $this.parents('tr:first'),
+ ban = $tr.data('ban');
+
+ if (!ban)
+ return;
+
+ var channel = this.model.get('channel');
+ channel.setMode('-b ' + ban.banned);
+
+ $tr.remove();
+ },
+
+
+ updateInfo: function (channel, new_val) {
+ var that = this,
+ modes, url, banlist;
+
+ modes = channel.get('info_modes');
+ if (modes) {
+ _.each(modes, function(mode, idx) {
+ mode.mode = mode.mode.toLowerCase();
+
+ if (mode.mode == '+k') {
+ that.$el.find('[name="channel_key"]').val(mode.param);
+ } else if (mode.mode == '+m') {
+ that.$el.find('[name="channel_mute"]').attr('checked', 'checked');
+ } else if (mode.mode == '+i') {
+ that.$el.find('[name="channel_invite"]').attr('checked', 'checked');
+ } else if (mode.mode == '+n') {
+ that.$el.find('[name="channel_external_messages"]').attr('checked', 'checked');
+ } else if (mode.mode == '+t') {
+ that.$el.find('[name="channel_topic"]').attr('checked', 'checked');
+ }
+ });
+ }
+
+ url = channel.get('info_url');
+ if (url) {
+ this.$el.find('.channel_url a')
+ .text(url)
+ .attr('href', url);
+
+ this.$el.find('.channel_url').slideDown();
+ }
+
+ banlist = channel.get('banlist');
+ if (banlist && banlist.length) {
+ var $table = this.$el.find('.channel_banlist table tbody');
+
+ $table.empty();
+ _.each(banlist, function(ban) {
+ var $tr = $('<tr></tr>').data('ban', ban);
+
+ $('<td></td>').text(ban.banned).appendTo($tr);
+ $('<td></td>').text(ban.banned_by.split(/[!@]/)[0]).appendTo($tr);
+ $('<td></td>').text(formatDate(new Date(parseInt(ban.banned_at, 10) * 1000))).appendTo($tr);
+ $('<td><i class="icon-remove remove-ban"></i></td>').appendTo($tr);
+
+ $table.append($tr);
+ });
+ }
+ },
+
+
+ updateBanlist: function (event) {
+ event.preventDefault();
+
+ var channel = this.model.get('channel'),
+ network = channel.get('network');
+
+ network.gateway.raw('MODE ' + channel.get('name') + ' +b');
+ },
+
+
+ dispose: function () {
+ this.model.get('channel').off('change:info_modes change:info_url change:banlist', this.updateInfo, this);
+
+ this.$el.remove();
+ }
+});
\ No newline at end of file
addItem: function(item_name, $item) {
- $item = $($item);
if ($item.is('a')) $item.addClass('icon-chevron-right');
this._items[item_name] = $item;
},
irc_connection.write('PRIVMSG ' + args.target + ' :' + block, cb);\r
});\r
},\r
- \r
+\r
\r
CTCP: function (args, irc_connection, callback) {\r
if ((args.target) && (args.type)) {\r
},\r
\r
\r
+ CHANNEL_INFO: function (args, irc_connection, callback) {\r
+ if (args.channel) {\r
+ irc_connection.write('MODE ' + args.channel, callback);\r
+ }\r
+ },\r
+\r
+\r
PART: function (args, irc_connection, callback) {\r
if (args.channel) {\r
_.each(args.channel.split(","), function (chan) {\r
'src/models/panel.js',
'src/models/member.js',
'src/models/memberlist.js',
- 'src/models/network.js'
+ 'src/models/network.js',
+ 'src/models/channelinfo.js'
],
[
'src/views/statusmessage.js',
'src/views/tabs.js',
'src/views/topicbar.js',
- 'src/views/userbox.js'
+ 'src/views/userbox.js',
+ 'src/views/channelinfo.js'
]
]);
} else {
banlist: onBanList,
banlist_end: onBanListEnd,
topicsetby: onTopicSetBy,
- mode: onMode
+ mode: onMode,
+ info: onChannelInfo
};
EventBinder.bindIrcEvents('channel ' + this.name, this.irc_events, this, irc_connection);
};
}
+function onChannelInfo(event) {
+ // Channel info event may contain 1 of several types of info,
+ // including creation time, modes. So just pipe the event
+ // right through to the client
+ this.irc_connection.clientEvent('channel_info', event);
+}
+
+
function onBanList(event) {
this.ban_list_buffer.push(event);
}
function onBanListEnd(event) {
- var that = this;
- this.ban_list_buffer.forEach(function (ban) {
- that.irc_connection.clientEvent('banlist', ban);
+ this.irc_connection.clientEvent('banlist', {
+ channel: this.name,
+ bans: this.ban_list_buffer
});
+
this.ban_list_buffer = [];
}
'321': 'RPL_LISTSTART',
'322': 'RPL_LIST',
'323': 'RPL_LISTEND',
+ '324': 'RPL_CHANNELMODEIS',
+ '328': 'RPL_CHANNEL_URL',
+ '329': 'RPL_CREATIONTIME',
'330': 'RPL_WHOISACCOUNT',
'331': 'RPL_NOTOPIC',
'332': 'RPL_TOPIC',
});
},
+ 'RPL_CHANNELMODEIS': function (command) {
+ var channel = command.params[1],
+ modes = parseModeList.call(this, command.params[2], command.params.slice(3));
+
+ this.irc_connection.emit('channel ' + channel + ' info', {
+ channel: channel,
+ modes: modes
+ });
+ },
+
+ 'RPL_CREATIONTIME': function (command) {
+ var channel = command.params[1];
+
+ this.irc_connection.emit('channel ' + channel + ' info', {
+ channel: channel,
+ created_at: parseInt(command.params[2], 10)
+ });
+ },
+
+ 'RPL_CHANNEL_URL': function (command) {
+ var channel = command.params[1];
+
+ this.irc_connection.emit('channel ' + channel + ' info', {
+ channel: channel,
+ url: command.trailing
+ });
+ },
+
'RPL_MOTD': function (command) {
this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' motd', {
motd: command.trailing + '\n'
},
'MODE': function (command) {
- var chanmodes = this.irc_connection.options.CHANMODES || [],
- prefixes = this.irc_connection.options.PREFIX || [],
- always_param = (chanmodes[0] || '').concat((chanmodes[1] || '')),
- modes = [],
- has_param, i, j, add, event, time;
+ var modes = [], event, time;
// Check if we have a server-time
time = getServerTime.call(this, command);
- prefixes = _.reduce(prefixes, function (list, prefix) {
- list.push(prefix.mode);
- return list;
- }, []);
- always_param = always_param.split('').concat(prefixes);
-
- has_param = function (mode, add) {
- if (_.find(always_param, function (m) {
- return m === mode;
- })) {
- return true;
- } else if (add && _.find((chanmodes[2] || '').split(''), function (m) {
- return m === mode;
- })) {
- return true;
- } else {
- return false;
- }
- };
-
- if (!command.params[1]) {
- command.params[1] = command.trailing;
- }
-
- j = 0;
- for (i = 0; i < command.params[1].length; i++) {
- switch (command.params[1][i]) {
- case '+':
- add = true;
- break;
- case '-':
- add = false;
- break;
- default:
- if (has_param(command.params[1][i], add)) {
- modes.push({mode: (add ? '+' : '-') + command.params[1][i], param: command.params[2 + j]});
- j++;
- } else {
- modes.push({mode: (add ? '+' : '-') + command.params[1][i], param: null});
- }
- }
- }
-
+ // Get a JSON representation of the modes
+ modes = parseModeList.call(this, command.params[1] || command.trailing, command.params.slice(2));
event = (_.contains(this.irc_connection.options.CHANTYPES, command.params[0][0]) ? 'channel ' : 'user ') + command.params[0] + ' mode';
this.irc_connection.emit(event, {
}
+/**
+ * Convert a mode string such as '+k pass', or '-i' to a readable
+ * format.
+ * [ { mode: '+k', param: 'pass' } ]
+ * [ { mode: '-i', param: null } ]
+ */
+function parseModeList(mode_string, mode_params) {
+ var chanmodes = this.irc_connection.options.CHANMODES || [],
+ prefixes = this.irc_connection.options.PREFIX || [],
+ always_param = (chanmodes[0] || '').concat((chanmodes[1] || '')),
+ modes = [],
+ has_param, i, j, add;
+
+ prefixes = _.reduce(prefixes, function (list, prefix) {
+ list.push(prefix.mode);
+ return list;
+ }, []);
+ always_param = always_param.split('').concat(prefixes);
+
+ has_param = function (mode, add) {
+ if (_.find(always_param, function (m) {
+ return m === mode;
+ })) {
+ return true;
+ } else if (add && _.find((chanmodes[2] || '').split(''), function (m) {
+ return m === mode;
+ })) {
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+ j = 0;
+ for (i = 0; i < mode_string.length; i++) {
+ switch (mode_string[i]) {
+ case '+':
+ add = true;
+ break;
+ case '-':
+ add = false;
+ break;
+ default:
+ if (has_param(mode_string[i], add)) {
+ modes.push({mode: (add ? '+' : '-') + mode_string[i], param: mode_params[j]});
+ j++;
+ } else {
+ modes.push({mode: (add ? '+' : '-') + mode_string[i], param: null});
+ }
+ }
+ }
+
+ return modes;
+}
+
+
function getServerTime(command) {
var time;