/* OmnomIRC COPYRIGHT 2010,2011 Netham45 OmnomIRC3 rewrite COPYRIGHT 2013 Nathaniel 'Eeems' van Diepen on behalf of Omnimaga.org This file is part of OmnomIRC. OmnomIRC is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OmnomIRC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OmnomIRC. If not, see . */ (function(window,$,io,undefined){ "use strict"; var $o = window.OmnomIRC = window.$o = function(){ return 'Version: '+version; }, event = function(msg,type){ if(settings.debug){ type=exists(type)?type:'event'; switch(type){ case 'ready':type='document_ready';break; } log('['+type.toUpperCase()+'] '+msg); } }, emit = function(type,data){ if($o.chat.connected()){ socket.emit.apply(socket,arguments); }else{ if(tabs.length > 0){ $o.msg('Disconnected, cannot do anything'); } } }, noop = function(){}, log = function(){ console.log.apply(console,arguments); }, exists = function(object){ return typeof object != 'undefined'; }, prevent = function(e){ e.stopImmediatePropagation(); e.stopPropagation(); e.preventDefault(); return false; }, selectedTab=0, settings = {}, settingsConf = {}, tabs = [], properties = { nick: 'User', sig: '', tabs: tabs, themes: [], origins: [] }, commands = [ { // names cmd: 'names', fn: function(args){ emit('names',{ name: $o.ui.tabs.current().name }); } }, { // me cmd: 'me', help: 'Say something in third person', fn: function(args){ var i,ret=''; for(i=1;i 1){ $o.ui.tabs.remove(args[1]); }else{ $o.ui.tabs.remove(selectedTab); } } }, { // tabs cmd: 'tabs', fn: function(args){ $o.msg('tabs:'); for(var i in tabs){ $o.msg(' ['+i+'] '+tabs[i].name); } } } ], handles = [ { // names on: 'names', fn: function(data){ var tab = $o.ui.tabs.tab(data.room), users = tab.users, i; tab.users = data.names; if($o.ui.tabs.idForName(data.room) == selectedTab){ $o.ui.render.users(); } $(users).each(function(i,v){ if(v != null){ if(tab.users.indexOf(v.trim()) == -1){ emit('echo',{ room: data.room, message: v+' left the room', from: 0, origin: 0 }); runHook('part',[ v, data.room ]); } } }); $(tab.users).each(function(i,v){ if(v != null){ if(users.indexOf(v.trim()) == -1){ runHook('join',[ v, data.room ]); } } }); } }, { // authorized on: 'authorized', fn: function(data){ event('Authorized'); properties.nick = data.nick; for(var i in settings.autojoin){ emit('join',{ name: settings.autojoin[i] }); } runHook('authorized'); } }, { // join on: 'join', fn: function(data){ event('joined '+data.name); var flag = tabs.length == 0; $o.ui.tabs.add(data.name); if(flag){ $o.ui.tabs.select(0); } } }, { // reconnect on: 'reconnect', fn: function(data){ event('reconnected'); properties.connected = true; $o.chat.auth(); runHook('reconnect'); emit('echo',{ room: $o.ui.tabs.current().name, from: 0, origin: 0, message: 'reconnected' }); } }, { // connect on: 'connect', fn: function(data){ event('connected'); properties.connected = true; $o.chat.auth(); runHook('connect'); emit('echo',{ room: $o.ui.tabs.current().name, from: 0, origin: 0, message: 'connected' }); } }, { // disconnect on: 'disconnect', fn: function(data){ event('disconnected'); properties.connected = false; runHook('disconnected'); $o.msg('* disconnected'); } }, { // message on: 'message', fn: function(data){ event('recieved message'); var date = new Date(), string, time = date.getTime(), child, i, msg = function(msg){ string = '[]'; child = $('
  • ').html(string+''+ msg .htmlentities() .replace( /(https?:\/\/(([-\w\.]+)+(:\d+)?(\/([\w/_\.]*(\?\S+)?)?)?))/g, "$1" ) +''); $o.msg({html:child},data.room); }; if(data.from != 0){ msg(' <'+data.from+'> '+data.message); }else{ msg(' * '+data.message); } abbrDate('abbr.date_'+time); if(settings.timestamp == ''){ $('.date_cell').css('visibility','hidden'); }else{ $('.date_cell').css('visibility','visible'); } runHook('message',[ data.message, data.from, data.room, data.origin ]); } } ], hooks = [ { // setting - setting type: 'setting', hook: 'setting', fn: function(name){ return name != 'colour'; } } ], plugins = [], pluginSandbox = { $: window.jQuery, jQuery: window.jQuery, $o: $o }, currentPlugin = 0, Sandbox = function(sandbox){ var i,o = {}; for(i in window){ o[i] = undefined; } o.window = o; for(i in sandbox){ o[i] = sandbox[i]; } if(!exists(o.fragment)){ o.fragment = function(){ return document.createDocumentFragment(); }; } return o; }, runHook = function(name,args){ var i,r=true,hook,fn,sandbox = { jQuery: window.jQuery, $: window.jQuery, $o: window.OmnomIRC, OmnomIRC: window.OmnomIRC }; args=exists(args)?args:[]; for(i in hooks){ hook = hooks[i]; if(hook.hook == name){ r = runInSandbox(hook.fn,sandbox,args,true); } if(r == false){ break; } } return r; }, runInSandbox = function(fn,sandbox,args,isFn){ args = exists(args)?args:[]; sandbox = sandbox instanceof Sandbox?sandbox:new Sandbox(sandbox); var r = false; fn = (fn+'').replace(/\/\/.+?(?=\n|\r|$)|\/\*[\s\S]+?\*\//g,'').replace(/\"/g,'\\"').replace(/\n/g,'').replace(/\r/g,'').replace(/\\n/g,'\\\\n'); if(!exists(isFn) || !isFn){ fn = 'function(){'+fn+'}'; } fn = 'var ret = true;eval("with(this){ret = ('+fn+').apply(this,arguments);}");return ret;'; try{ r = (new Function(fn)).apply(sandbox,args); }catch(e){ event('Sandboxed function failed to run: '+e+"\nFunction that ran: "+fn,'sandbox_error'); } return r; }, version = '3.0', abbrDate = function(selector){ if(settings.timestamp == 'fuzzy'){ $(selector).timeago(); }else{ $(selector).each(function(){ var timestamp = settings.timestamp, i, text='', date = new Date($(this).attr('title')); if(timestamp == 'exact'){ timestamp = 'H:m:s t'; } for(i=0;i9?'':'0')+date.getMinutes();break; case 's':text+=(date.getSeconds()>9?'':'0')+date.getSeconds();break; case 't':text+=(date.getHours()>11)?'pm':'am';break; default:text+=timestamp[i]; } } $(this).text(text); }).timeago('dispose'); } }, origin = function(name){ for(var i in properties.origins){ if(name == properties.origins[i][1]){ return i; } } return 1; }, socket,$i,$s,$h,$cl,$c,$tl,hht; $.extend($o,{ version: function(){ return version; }, register: { theme: function(name){ if(-1==$.inArray(properties.themes,name)){ properties.themes.push(name); runHook('theme',[name]); return true; } return false; }, command: function(name,fn,help){ if(-1==$.inArray(commands,name)){ var o = { cmd: name, fn: fn }; if(exists(help)){ o.help = help; } commands.push(o); return true; } return false; }, plugin: function(name){ if(!exists(plugins[name])){ plugins[name] = { name: name, loaded: false, started: false }; return true; } return false; }, setting: function(name,type,val,validate,values,callback){ if(!exists(settings[name])){ validate = exists(validate)?validate:function(){}; values = exists(values)?values:undefined; callback = exists(callback)?callback:function(){}; settings[name] = val; settingsConf[name] = { validate: validate, callback: callback, type: type, values: values, default: val, name: name } return true; }else{ return false; } }, hook: function(event,fn,type){ type=exists(type)?type:'hook'; hooks.push({ hook: event, fn: fn, type: type }) } }, plugin: { register: function(name){ return $o.register.plugin(name); }, start: function(name){ if(exists(plugins[name])){ var plugin = plugins[name]; if(plugin.started){ $o.plugin.stop(name); } event('Starting plugin '+name); pluginSandbox.$o.hook = function(){ var h = arguments[0], f = arguments[1], fn; if( h == 'start' || h == 'stop'){ fn = function(){ if(arguments[0] == name){ f.apply(this,arguments) } } }else{ fn = f; } $o.hook.apply($o,[h,fn]); }; if(!plugin.loaded){ $.ajax('data/plugins/'+name+'/script.js',{ dataType: 'text', success: function(data){ plugin.script = data; runInSandbox(data,pluginSandbox); plugin.started = true; runHook('start',[name]); } }); }else{ runInSandbox(plugin.script,pluginSandbox); plugin.started = true; } return true; }else{ return false; } }, stop: function(name){ if(exists(plugins[name])){ event('Stopping plugin '+name); runHook('stop',[name]); var i; for(i in hooks){ if(hooks[i].type == 'plugin' && hooks[i].plugin == name){ hooks.spice(i,1); } } }else{ return false; } }, remove: function(name){ if($o.plugin.stop(name)){ plugin[name] = undefined; delete plugin[name]; return true; }else{ return false; } }, dir: function(name){ return 'data/plugins/'+name+'/'; } }, hook: function(event,fn){ $o.register.hook(event,fn); }, ui: { render: { settings: function(){ var name,setting,frag = document.createDocumentFragment(),item; for(name in settings){ setting = $o.get(name,true); switch(setting.type){ case 'select': item = $('') .attr({ type: 'text', id: 'setting_'+name }) .val(setting.val) .change(function(){ $o.set(this.id.substr(8),$(this).val().split(','),false); }); break; case 'boolean': item = $('') .attr({ type: 'checkbox', id: 'setting_'+name }) .change(function(){ $o.set(this.id.substr(8),$(this).is(':checked'),false); }); if(setting.val){ item.attr('checked','checked'); } break; case 'number': case 'string':default: item = $('') .attr({ type: 'text', id: 'setting_'+name }) .val(setting.val) .change(function(){ $o.set(this.id.substr(8),$(this).val(),false); }); } $(frag).append( $('
  • ') .addClass('row') .append( $('') .text(name) .addClass('cell') ) .append( $('') .append(item) .addClass('cell') ) ); } if(settings.debug){ $(frag).append( $('
  • ') .addClass('row') .attr('id','console-log-controls') .append( $('') .text('Debug Log') .addClass('cell') ) .append( $('') .addClass('cell') .append( $('