昔、UNIXの
talkコマンドっておもしろいなぁって思ってたら
IRCってのをみつけて、
ネットワークってスゴいって思った。そっから
ICQってのが出てきて、
MSN Messanger
に感動し、
Skypeに傾倒して、結局今はもっぱら
Google Talkを使ってる。
ただ、アプリ版のGoogle Talkはグループチャット機能がなく、ガジェット版はテキスト
のコピー&ペーストができない、、、しかたなくチームで作業する時とかは別途でSkype
を立ち上げたりしてたのが、
PartyChatというグループチャットのゲートウェイ的な
サービスを
見つけて、なるほどーと思った。
PartyChatは十分素敵に使えるんだけれど、なんかもっと簡単にならないかなぁと思って
車輪の再発明してみた。(Special Thanks to
techwalla 汗)
- gtgchat@gmail.comをGoogle Talk(もしくはJabberクライアント)に登録するとすぐラウンジ(lounge)に入り、そこでたむろっている人がいれば話すことができる。
- 自分の名前を変更したい場合は「name hoge」と入力するとhogeさんになれる。
- 「room (好きな部屋の名前)」と入力すると自動的に部屋をつくってそこへ移動でき、同じ名前の部屋に移動した人がいればその中だけで会話ができる。
- また、「room」とだけ打つと部屋の一覧が表示され、部屋の名前の先頭に#(半角シャープ)をつけると一覧にでてこない秘密の部屋(例: room #秘密の部屋)ができるので、内緒話ができる。
- 「exit」と話しかけると部屋から出る、すなわち終了。
こんだけ。ソースとAmazon EC2上に立ち上げている手順は下記の通り。
ほぼこの用途にしか使わないサーバなので、グループを作成してファイアウォール
の設定(72.14.253.125はtalk.google.comのIP)。
# ec2-add-group gtgchat -d "Google Talk GroupChat Server"
GROUP gtgchat Google Talk GroupChat Server
# ec2-authorize gtgchat -s 72.14.253.125/32 -p 5222-5222
GROUP gtgchat
PERMISSION gtgchat ALLOWS tcp 5222 5222 FROM CIDR 72.14.253.125/32
# もちろん管理用のポートも開けとく
前回作ったAMIで立ち上げる。
# ec2-run-instances -k gsg-keypair -g gtgchat -d "cp /usr/share/zoneinfo/Japan /etc/localtime" ami-eb7c9982
RESERVATION r-******* ************ gtgchat
INSTANCE i-****** ami-eb7c9982 pending gsg-keypair 0 m1.small 2008-05-04T18:44:08+0000 us-east-1a
# 立ち上がったサーバでphpのインストール
USE='cli pcre unicode xml mhash' emerge php
あとは
class.jabber.phpをとってきて、下記のソースで起動させるだけ(実際にはdaemontoolsで立ち上げてる)。
<?php
require("class.jabber.php");
define('ME','junji.shiokawa@gmail.com'); // 管理者のメアド(最初に認証を済ませておく必要がある)
define('USER','/mnt/supervise/gtgchat/gtgchat.user'); // データの保存ファイル名
$j = new Jabber();
$j->server = 'gmail.com';
$j->connect_server = 'talk.google.com';
$j->port = 5222;
$j->username = 'gtgchat'; // 使用するユーザ名
$j->password = '******'; // パスワード
$j->resource = 'fork'; // リソース名(適当)
$j->log_filename = 'php://stdout';
$j->enable_logging = true;
$j->Connect();
$j->SendAuth();
$j->RosterUpdate();
$j->SendPresence();
chat(ME,'up');
while(1){
if($j->connected == FALSE){
$j->Disconnect();
exit;
}
$j->CruiseControl(300);
}
function Handler_message_chat($p) {
global $j;
$e = email($j->GetInfoFromMessageFrom($p));
$b = body($j->GetInfoFromMessageBody($p));
$c = explode(' ',$b);
if ( $e == ME && $b == "kill" ) {
//管理者がkillと入力すると落とせる
chat($e,'ok');
$j->Disconnect();
exit;
}elseif( $b == 'exit' ) {
room($e,'');
chat($e,'ok');
}elseif( $b == 'help' ) {
// helpと入力すると使い方を表示
chat($e,help());
}elseif( $c[0] == 'name' ) {
if($c[1]){
name($e,$c[1]);
chat($e,'ok');
}else{
$u=rooms();
chat($e,$u[$e]['name'].': '. $e);
}
}elseif( $c[0] == 'room' ) {
if($c[1]){
$u=room($e,$c[1]);
$r=array();
array_push($r,$u[$e]['name']);
foreach($u as $k => $v){
if($v['room'] == $c[1] && $k != $e){
array_push($r,$v['name']);
}
}
if(count($r)){
sort($r);
chat($e,'['.$c[1].'] '.implode(', ',$r));
}else{
chat($e,'new');
}
}else{
$u=rooms();
$a=array();
foreach($u as $k => $v){
if(substr($v['room'],0,1)=='#'){
if($u[$e]!=$v['room']){
continue;
}
}
if($v['room']){
$a[$v['room']]=1;
}
}
if(count($a)){
$m='';
ksort($a);
foreach($a as $k => $v){
if($u[$e]['room'] == $k){
$m.="*[$k] ";
}else{
$m.="[$k] ";
}
$r=array();
foreach($u as $uk => $uv){
if($uv['room'] == $k){
array_push($r,$uv['name']);
}
}
if(count($r)){
sort($r);
$m.=implode(', ',$r) ."\n";
}
}
chat($e,$m);
}else{
chat($e,'no rooms');
}
}
}else{
if($b){
$u=rooms();
foreach($u as $k => $v){
if($u[$e]['room'] && $u[$e]['room'] == $u[$k]['room'] && $k!=$e){
chat($k,$u[$e]['name'].': '.$b);
}
}
}
}
}
function Handler_presence_subscribe($p) {
global $j;
$f = $j->GetInfoFromPresenceFrom($p);
$j->SubscriptionAcceptRequest($f);
$j->RosterUpdate();
name(email($f),email($f));
room(email($f),'lounge');
}
function Handler_presence_unavailable($p) {
global $j;
room(email($j->GetInfoFromPresenceFrom($p)),'');
}
function Handler_message_error($p) {
room(email($p['message']['@']['from']),'');
}
function chat($e,$m) {
global $j;
$j->SendMessage($e, "chat", NULL, array("body" =>$m));
}
function email($f) {
return strtolower(array_shift(explode('/',$f)));
}
function body ($b) {
return trim(mb_convert_kana($b,'KVas','UTF-8'));
}
function room($e,$r) {
$u = unserialize(file_get_contents(USER));
if($u[$e]['room'] && $u[$e]['room'] != $r){
foreach($u as $k => $v){
if($u[$e]['room'] == $u[$k]['room'] && $k!=$e){
chat($k,'['.$u[$e]['room'].'] - '. $u[$e]['name']);
}
}
}
if(! $u[$e]['name']) {
$n1=explode('@',$e);
$n2=explode('.',$n1[0]);
if($n2[0]){
$u[$e]['name']=$n2[0];
}else{
$u[$e]['name']=$n1[0];
}
}
if($r){
$u[$e]['room']=$r;
}else{
unset($u[$e]['room']);
}
if($u[$e]['room']){
foreach($u as $k => $v){
if($u[$e]['room'] == $u[$k]['room'] && $k!=$e){
chat($k,'['.$u[$e]['room'].'] + '. $u[$e]['name']);
}
}
}
file_put_contents(USER,serialize($u));
return $u;
}
function rooms() {
return unserialize(file_get_contents(USER));
}
function name($e,$a) {
$u = unserialize(file_get_contents(USER));
if( strstr($a,'@')) {
$n1=explode('@',$e);
$n2=explode('.',$n1[0]);
if($n2[0]){
$a=$n2[0];
}else{
$a=$n1[0];
}
}
$u[$e]['name']=$a;
file_put_contents(USER,serialize($u));
return $u;
}
function help() {
return "room [name] ... no param lists room and with [name] goto room. [#name] is secret room.
name [nickname] ... set nickname to [nickname].
exit ... leave chat.
";
}
?>
0 コメント:
Post a Comment