function _minibar($params) { $watch = $params['watch']; $user = Auth::user(); $widgets = DB::get()->results("SELECT * FROM options WHERE grouping = 'widgets' AND user_id = :user_id", array('user_id' => $user->id)); foreach ($widgets as $widget) { $data = unserialize($widget->value); if ($data['name'] == 'minibar') { $data['rooms'][] = $watch; $widget->value = serialize($data); $widget->update('options', 'id'); Immediate::create()->js("reloadWidgets();addSystem({user_id:{$user->id}, data: 'Added \\'" . addslashes($watch) . "\\' to minibar.', cssclass: 'ok', username: '******', nickname: '{$user->nickname}', status: " . microtime(true) . ", js:''}, '#notices');do_scroll();"); return true; } } $lastwidgetid = DB::get()->val("SELECT MAX(id) FROM options"); if (!$lastwidgetid) { $lastwidgetid = 0; } $lastwidgetid++; $data = array('name' => 'minibar', 'params' => '', 'rooms' => array($watch)); DB::get()->query("INSERT INTO options (name, grouping, value, user_id) VALUES (:name, 'widgets', :value, :user_id);", array('name' => $lastwidgetid, 'value' => serialize($data), 'user_id' => $user->id)); Immediate::create()->js("reloadWidgets();addSystem({user_id:{$user->id}, data: 'Added \\'" . addslashes($watch) . "\\' as minibar widget.', cssclass: 'ok', username: '******', nickname: '{$user->nickname}', status: " . microtime(true) . ", js:''}, '#notices');do_scroll();"); return true; }
function _retreat($params) { $user = $params['user']; $channel = $params['channel']; $inchannels = DB::get()->col('SELECT name FROM channels WHERE user_id = :user_id', array('user_id' => $user->id)); $join = 'office:' . $user->username; $joinalias = $this->_room_alias($join); foreach ($inchannels as $partchan) { DB::get()->query('DELETE FROM channels WHERE name = :name AND user_id = :user_id;', array('name' => $partchan, 'user_id' => $user->id)); if (preg_match('%^search:(?P<criteria>.+)$%i', $partchan, $searchmatches)) { DB::get()->query("DELETE FROM options WHERE name = :name AND grouping = 'searches' AND user_id = :user_id;", array('name' => $searchmatches['criteria'], 'user_id' => $user->id)); } else { if ($partchan != $join) { Status::create()->data("{$user->username} has retreated to <a href=\"#\" onclick=\"joinRoom('" . addslashes($join) . "');return false;\">{$joinalias}</a> from {$partchan}")->type('part')->channel($partchan)->insert(); } } } DB::get()->query('INSERT INTO channels (name, user_id, last) VALUES (:name, :user_id, NOW());', array('name' => $join, 'user_id' => $user->id)); if (!($herald = DB::get()->val("SELECT value FROM options WHERE user_id = :user_id AND name = :name AND grouping = :grouping", array('user_id' => $user->id, 'name' => 'Herald', 'grouping' => 'Identity')))) { $herald = '{$nickname} has joined {$room}'; } $js = ''; $cssclass = ''; $packed = Plugin::call('herald', array('herald' => $herald, 'js' => $js, 'cssclass' => $cssclass)); extract($packed); $herald = str_replace('{$nickname}', $user->nickname, $herald); $herald = str_replace('{$room}', $joinalias, $herald); $msg = htmlspecialchars($herald); Status::create()->data($msg)->type('join')->cssclass($cssclass)->channel($join)->js($js)->insert(); Immediate::create()->laststatus()->js('setRoom("' . addslashes($join) . '");'); return true; }
function _spell($params) { $user = $params['user']; $channel = $params['channel']; $presence = DB::get()->row('SELECT status, data FROM presence WHERE user_id = :user_id AND data <> "" ORDER BY msgtime DESC LIMIT 1', array('user_id' => $user->id)); $data = $presence->data; $words = preg_split('%\\W+%', $data); $words = array_unique($words); $words = array_combine($words, $words); $pspell_link = pspell_new("en"); foreach ($words as $word) { if (!pspell_check($pspell_link, $word)) { $suggestions = pspell_suggest($pspell_link, $word); if (count($suggestions) > 0) { $presence->data = str_replace($word, reset($suggestions), $presence->data); } else { $presence->data = str_replace($word, '<s>' . $word . '</s>', $presence->data); } } } if ($presence->data == $data) { Immediate::ok('No spelling corrections.', $user); } else { include_once "Text/Diff.php"; include_once "Text/Diff/Renderer.php"; include_once "Text/Diff/Renderer/inline.php"; $diff =& new Text_Diff(explode("\n", $data), explode("\n", htmlspecialchars_decode($presence->data))); $renderer =& new Text_Diff_Renderer_inline(); $replacement = $renderer->render($diff); $replacement = addslashes($replacement); $replacement = str_replace("\n", '\\n', $replacement); $js = <<<REPLJS retcon({$presence->status}, '{$replacement}'); REPLJS; Status::create()->user_id($user->id)->js($js)->channel($channel)->cssclass('spell')->insert(); } return true; }
function _externals($params) { $p2 = $params; $p2['user'] = $p2['user']->std(); $p2['chaturl'] = 'http://' . $_SERVER['HTTP_HOST'] . '/'; $body = json_encode($p2); $user = $params['user']; //Immediate::debug(htmlspecialchars(print_r($params,1)));return false; $externals = DB::get()->col("SELECT value FROM options WHERE grouping = 'external'"); foreach ($externals as $url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); // The URL. curl_setopt($ch, CURLOPT_MAXREDIRS, 5); // Maximum number of redirections to follow. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // Follow 302's and the like. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return the data from the stream. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); curl_setopt($ch, CURLOPT_TIMEOUT, 1); curl_setopt($ch, CURLOPT_POST, true); // POST mode. curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array('p' => $body))); // Immediate::create() // ->js("addSystem({user_id:{$user->id}, data: '" . addslashes($body) . "', cssclass: 'error', username: '******', nickname: '{$user->nickname}', status: " . microtime(true) . ", js:''}, '#notices');do_scroll();"); $response = curl_exec($ch); if (curl_errno($ch) !== 0) { Immediate::create()->js("addSystem({user_id:{$user->id}, data: 'External \\'" . addslashes($url) . "\\' failed, with a curl error, " . curl_errno($ch) . ".', cssclass: 'error', username: '******', nickname: '{$user->nickname}', status: " . microtime(true) . ", js:''}, '#notices');do_scroll();"); } elseif (curl_getinfo($ch, CURLINFO_HTTP_CODE) !== 200) { //die('Not 200 response code'); Immediate::create()->js("addSystem({user_id:{$user->id}, data: 'External \\'" . addslashes($url) . "\\' failed, with HTTP error code " . curl_getinfo($ch, CURLINFO_HTTP_CODE) . ".', cssclass: 'error', username: '******', nickname: '{$user->nickname}', status: " . microtime(true) . ", js:''}, '#notices');do_scroll();"); } else { Immediate::debug(htmlspecialchars($response)); //return false; try { $xml = new SimpleXMLElement($response); foreach ($xml->result as $result) { $status = Status::create(); foreach ($result->attributes() as $k => $v) { switch ($k) { case 'append': break; case 'user': $remote_user = DB::get()->val("SELECT id FROM users WHERE username = ?", array($v)); if (!$remote_user) { $remote_user = min(-1, DB::get()->val("SELECT min(id) FROM users") - 1); DB::get()->query("INSERT INTO users (id, username) VALUES (?, ?)", array($remote_user, $v)); DB::get()->query("UPDATE users SET id = ? WHERE username = ?", array($remote_user, $v)); } $status->user_id = $remote_user; break; default: $status->{$k} = $v; break; } } $status->data((string) $result); if (isset($result['append']) && $result['append'] == 'pre') { $status->insert(); } else { $this->statuses[] = $status; } if ($xml['silent'] == 'true') { return true; } } } catch (Exception $e) { Immediate::debug('RESPONSE: ' . htmlspecialchars($response)); } } curl_close($ch); return false; } }
function _response($channel) { $user = Auth::user(); $issearch = false; if (preg_match('%search:(?P<criteria>.+)%i', $channel, $searchmatches)) { $issearch = true; } preg_match('%(?P<roomtype>\\w+):(?P<criteria>.+)%i', $channel, $searchmatches); $searchmatches['roomtype'] = isset($searchmatches['roomtype']) ? $searchmatches['roomtype'] : ''; $searchmatches['criteria'] = isset($searchmatches['criteria']) ? $searchmatches['criteria'] : ''; if (DB::get()->val("SELECT count(*) FROM channels WHERE user_id = :user_id", array('user_id' => Auth::user_id())) == 0) { $join = 'bar'; //$user->username; $allowedchannels = DB::get()->col("SELECT room FROM options WHERE grouping = 'Permissions' AND name = 'allowedchannel' AND user_id = :user_id", array('user_id' => $user->id)); if ($allowedchannels) { $join = reset($allowedchannels); } DB::get()->query("INSERT INTO channels (name, user_id, active) VALUES (:join, :user_id, 1);", array('join' => $join, 'user_id' => Auth::user_id())); if (!($herald = DB::get()->val("SELECT value FROM options WHERE user_id = :user_id AND name = :name AND grouping = :grouping", array('user_id' => Auth::user_id(), 'name' => 'Herald', 'grouping' => 'Identity')))) { $herald = '{$nickname} has joined {$room}'; } $js = ''; $cssclass = ''; $packed = Plugin::call('herald', array('herald' => $herald, 'js' => $js, 'cssclass' => $cssclass)); extract($packed); $herald = str_replace('{$nickname}', $user->nickname, $herald); $herald = str_replace('{$room}', $this->_room_alias($join), $herald); $msg = htmlspecialchars($herald); Status::create()->data($msg)->type('join')->channel($join)->cssclass($cssclass)->js($js)->insert(); } DB::get()->query('UPDATE channels SET active = 0 WHERE user_id = :user_id', array('user_id' => Auth::user_id())); DB::get()->query('UPDATE channels SET active = 1, last = NOW() WHERE name = :channel AND user_id = :user_id', array('channel' => $channel, 'user_id' => Auth::user_id())); $laststatus = Immediate::get_status(); $obj = new StdClass(); $obj->comet_change = false; $obj->status = $laststatus; $obj->reported_status = 0; $obj->chanbar = $this->chanbar(); $obj->channels = DB::get()->col("SELECT name FROM channels WHERE user_id = :user_id ORDER BY name ASC", array('user_id' => Auth::user_id())); $obj->channel = DB::get()->val("SELECT name FROM channels WHERE user_id = :user_id and active = 1", array('user_id' => Auth::user_id())); $obj->jsdate = filemtime(dirname(__FILE__) . '/../../js/sp.js'); switch (strtolower($searchmatches['roomtype'])) { case 'search': $crit = DB::get()->val("SELECT value FROM options WHERE user_id = :user_id AND grouping = 'searches' AND name = :name", array('user_id' => $user->id, 'name' => $searchmatches['criteria'])); $obj->crit = $crit; $sql = ''; $params = array('user_id' => Auth::user_id(), 'crit' => $crit, 'searchchannel' => $obj->channel); $criteria = $this->_get_search_sql($sql, $params, $crit); $obj->updates = DB::get()->results($sql, $params, 'StdClass'); $insert = new stdClass(); $insert->status = 0; $insert->type = 'system'; $insert->channel = ''; $insert->data = 'Search Criteria: ' . $criteria; $insert->msgtime = 0; $insert->user_id = 0; $insert->cssclass = 'searchheader'; $insert->js = ''; $insert->user_to = ''; $insert->received = ''; $obj->updates[] = $insert; break; case 'office': $officeuser = $this->_userstr($searchmatches['criteria']); $qp = array('channel' => $obj->channel, 'user_id' => Auth::user_id()); if ($officeuser->id == $user->id) { $append = "((type = 'direct' AND user_to = :user_id AND presence.user_id <> :user_id) OR (user_to = :user_id) OR (user_to = 0)) AND (type <> 'notice')"; } else { $append = "((type = 'direct' AND user_to = :user_id and presence.user_id = :office_user) OR (user_to = 0)) AND (type <> 'notice')"; $qp['office_user'] = $officeuser->id; } $obj->updates = DB::get()->results("\nSELECT\n\tpresence.*,\n\tusers.username,\n\toptions.value as nickname,\n\tchannels.active as active\nFROM\n\tpresence\nLEFT JOIN\n\tusers\n\tON presence.user_id = users.id\nLEFT JOIN\n\toptions\n\tON options.user_id = users.id AND options.name = 'Nickname' AND options.grouping = 'Identity'\nLEFT JOIN\n\tchannels\n\tON channels.user_id = :user_id \n\tAND channels.name = presence.channel\nWHERE\n\t(channel = :channel OR channel = '')\n\tAND\n\t(\n\t\t{$append}\n\t)\nORDER BY\n\tstatus DESC\nLIMIT 100\n\t\t\t", $qp, 'StdClass'); break; default: $updates = Plugin::call('response', false, $searchmatches['roomtype'], $searchmatches['criteria']); if ($updates) { $obj->updates = $updates; } else { $obj->updates = DB::get()->results("\nSELECT\n\tpresence.*,\n\tusers.username,\n\toptions.value as nickname\nFROM\n\tpresence\nLEFT JOIN\n\tusers\n\tON presence.user_id = users.id\nLEFT JOIN\n\toptions\n\tON options.user_id = users.id AND options.name = 'Nickname' AND options.grouping = 'Identity'\nWHERE\n\t(channel = :channel OR channel = '')\n\tAND\n\t(\n\t\t(user_to = 0)\n\t\tOR\n\t\t(user_to = :user_id and isnull(received))\n\t)\nORDER BY\n\tstatus DESC\nLIMIT 100\n\t\t\t\t\t", array('channel' => $obj->channel, 'user_id' => Auth::user_id()), 'StdClass'); } break; } DB::get()->query('UPDATE presence SET received = msgtime, msgtime = NOW() WHERE isnull(received) AND user_to = :user_id', array('user_id' => Auth::user_id())); foreach ($obj->updates as $k => $v) { $obj->updates[$k]->msgtime = date('Y-m-d H:i:s', strtotime($obj->updates[$k]->msgtime) + intval((string) Option::get('Time', 'Zone Offset')) * 3600); } $obj->updates = array_reverse($obj->updates); $obj->names = DB::get()->results('select channels.name, users.id, username, pingtime, last, active, value as nickname from channels, sessions, users, options where channels.user_id = users.id AND users.id = sessions.user_id and pingtime > now() - 120000 and channels.name = :channel and options.user_id = users.id and options.grouping = "Identity" and options.name="Nickname";', array('channel' => $obj->channel), 'StdClass'); $obj->namebar = $this->namebar(); $obj->namebarmd5 = md5($obj->namebar); $obj->sups = DB::get()->val('SELECT count(*) as ct FROM presence, channels WHERE presence.channel = channels.name AND presence.msgtime > channels.last AND channels.active = 0 AND channels.user_id = :user_id AND presence.user_id <> :user_id AND presence.type <> "status"', array('user_id' => Auth::user_id())); $obj->drawers = DB::get()->results('SELECT * FROM drawers WHERE (channel = :channel OR isnull(channel) OR channel = "") AND user_id = :user_id ORDER BY added DESC;', array('channel' => $obj->channel, 'user_id' => Auth::user_id()), 'StdClass'); $obj->decor = DB::get()->assoc("SELECT name, value FROM options WHERE room = :channel AND grouping = 'decor';", array('channel' => $obj->channel)); $obj = Plugin::call('response_obj', $obj, $searchmatches['roomtype'], $searchmatches['criteria']); Immediate::set_status(); return json_encode($obj); }
function _instant_time($params) { $user = $params['user']; $channel = $params['channel']; $task = $params['task']; $pcode = $this->_project_alias($params['pcode']); $time = $params['time']; $approx = $params['approx']; $notes = $params['notes']; $return = true; if (strpos($time, ':') === 0) { $hours = floatval(substr($time, 1)) / 60; } elseif (strpos($time, ':') > 0) { list($hours, $minutes) = split(':', $time); $hours = intval($hours) + $minutes / 60; } else { $hours = floatval($time); } if (strpos($approx, ':') === 0) { $est = floatval(substr($approx, 1)) / 60; } elseif (strpos($approx, ':') > 0) { $est = (strtotime($approx) - strtotime($time)) / 3600; } elseif (trim($approx) == '') { $est = null; } else { $est = floatval($approx); } extract(Plugin::call('task_filter', array('task' => $task, 'notes' => $notes))); $timerec = array('time' => $hours, 'ondate' => date('Y-m-d'), 'pcode' => $pcode, 'task' => $task, 'notes' => $notes, 'billable' => !(preg_match('%-\\$%', $task) || preg_match('%-\\$%', $notes))); $projects = $this->_get_projects(); if (in_array($timerec['pcode'], $projects)) { $this->_add_time($timerec); $msg = "<span class=\"time\">Added {$hours} hours</span> <span class=\"project\">{$pcode}</span> <span class=\"task\">{$task}</span>"; Immediate::ok($msg, 'ok time time_instant'); } else { Immediate::error('Specified project "' . $timerec['pcode'] . '" does not exist.'); } return $return; }
public static function error($msg) { Immediate::create()->js("addSystem({user_id:0, data: '" . str_replace("\n", '\\n', addslashes($msg)) . "', cssclass: 'error', username: '', nickname: '', status: " . microtime(true) . ", js:''}, '#notices');do_scroll();"); }
function _karma($params) { $user = $params['user']; $channel = $params['channel']; $matches = $params['matches']; $word = trim(strtolower($matches['word']), '"'); $md5w = md5($word); $points = DB::get()->row('select sum(karma) as s, sum(abs(karma)) as b, sum(karma / abs(karma)) as v, std(karma) as d, var_pop(karma) as v from karma where word = ?', array($word)); $lastvote = DB::get()->row('SELECT time_to_sec(timediff(now(),lastvote)) as t, karma FROM karma WHERE word = ? and user_id = ?', array($word, $user->id)); if ($lastvote && $lastvote->t < 30) { Immediate::create()->laststatus()->js("\$('#mainscroller .karma_{$md5w} .inner.active .voters').html('You are voting too fast! Wait " . (30 - $lastvote->t) . " seconds.').effect('highlight', {}, 1500);"); return true; } if ($lastvote && abs($lastvote->karma) > $points->b - abs($lastvote->karma) && $points->v > 2) { Immediate::create()->laststatus()->js("\$('#mainscroller .karma_{$md5w} .inner.active .voters').html('You have voted more than everyone else <em>combined</em>. You win!').effect('highlight', {}, 1500);"); return true; } $kpoints = $points->s; if (DB::get()->val('SELECT count(word) FROM karma WHERE word = ? and user_id = ?', array($word, $user->id)) == 0) { switch ($matches['karma']) { case '++': $kpoints++; $bmsg = 'Added one karma point to "' . htmlspecialchars($matches['word']) . '", totaling ' . $kpoints . ' points.'; DB::get()->query('INSERT INTO karma (word, karma, user_id, direction) VALUES (?, ?, ?, 1)', array($word, 1, $user->id)); break; case '--': $kpoints--; $bmsg = 'Subtracted one karma point from "' . htmlspecialchars($matches['word']) . '", totaling ' . $kpoints . ' points.'; DB::get()->query('INSERT INTO karma (word, karma, user_id, direction) VALUES (?, ?, ?, -1)', array($word, -1, $user->id)); break; case '~~': $kpoints--; $bmsg = 'You didn\'t vote on "' . htmlspecialchars($matches['word']) . '" to begin with. The total is still ' . $kpoints . ' points.'; DB::get()->query('INSERT INTO karma (word, karma, user_id, direction) VALUES (?, ?, ?, 0)', array($word, -1, $user->id)); break; case '??': $bmsg = '"' . htmlspecialchars($matches['word']) . '" has ' . $kpoints . ' karma points -- you have not voted.'; if ($points->b == 0) { return false; } break; } } else { $oldkarma = DB::get()->val('SELECT karma FROM karma WHERE word = ? and user_id = ?', array($word, $user->id)); switch ($matches['karma']) { case '++': $kpoints++; $bmsg = 'Added one karma point to "' . htmlspecialchars($matches['word']) . '", totaling ' . $kpoints . ' points.'; DB::get()->query('UPDATE karma SET karma = karma + 1, lastvote = now(), direction = 1 WHERE word = ? and user_id = ?', array($word, $user->id)); break; case '--': $kpoints--; $bmsg = 'Subtracted one karma point from "' . htmlspecialchars($matches['word']) . '", totaling ' . $kpoints . ' points.'; DB::get()->query('UPDATE karma SET karma = karma - 1, lastvote = now(), direction = -1 WHERE word = ? and user_id = ?', array($word, $user->id)); break; case '~~': $kpoints -= $oldkarma; $bmsg = 'Removing your vote on "' . htmlspecialchars($matches['word']) . '", now totaling ' . $kpoints . ' points.'; DB::get()->query('DELETE FROM karma WHERE word = ? and user_id = ?', array($word, $user->id)); break; case '??': $bmsg = '"' . htmlspecialchars($matches['word']) . '" has ' . $kpoints . ' karma points -- you have already voted (' . $oldkarma . ').'; break; } } $points = DB::get()->row('select sum(karma) as s, sum(karma / abs(karma)) as v, std(karma) as d, var_pop(karma) as v from karma where word = ?', array($word)); $hword = htmlspecialchars($word); $bmsg = '<div class="word">' . $hword . '</div><button class="voteup" onclick="send(\'' . addslashes($hword) . '++\');">++</button><button class="votedown" onclick="send(\'' . addslashes($hword) . '--\');">--</button>'; $bmsg = '<div class="inner">loading</div>'; Status::create()->data($bmsg)->channel($channel)->type('notice')->cssclass('karma karma_' . md5($word))->js('apply_karma("' . $md5w . '", "' . $hword . '");')->insert(); return true; }