LINE BotでMiitomoもどきを作ってみた

LINE Bot流行ってますね
ビジネスアカウントの機能制限版なのに、みなさん嬉しそうでなによりです

ということで流行に便乗してLINE Bot作ってみた

Miitomoもどき
line_bot

Botに話しかけた内容を保存しておいて、他人の発言内容をランダムにチラ見せ

ほぼ拾ったコードのツギハギ
発言の保存するのにDB使ったけど、SSL証明書用意する手間に比べたら楽だよね

ソース

<?php

$json_string = file_get_contents('php://input');
$jsonObj = json_decode($json_string);
$to = $jsonObj->{"result"}[0]->{"content"}->{"from"};
$text = $jsonObj->{"result"}[0]->{"content"}->{"text"};

$url = "https://trialbot-api.line.me/v1/profiles?mids={$to}";
$headers = array(
	'X-Line-ChannelID: xxxx',
    'X-Line-ChannelSecret: xxxx',
    'X-Line-Trusted-User-With-ACL: xxxx'
);

$curl = curl_init($url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$profileJson = curl_exec($curl);

//スタンプとか無視するためにtextに値があることをチェック
if($text != ""){

	$profile = json_decode($profileJson);
	$name = $profile->{"contacts"}[0]->{"displayName"};
	$mid = $profile->{"contacts"}[0]->{"mid"};


	$pdo = new PDO();// DB接続的な何か

	$sql = 'select * from log_line_bot order by id desc limit 50';
	$stmt = $pdo->prepare($sql);
	$stmt->execute();

	$arr_res = array();
	while($row = $stmt -> fetch(PDO::FETCH_ASSOC)) {
		if($row['mid'] != $mid){//自分以外 SQLで絞り込まないのはインデックス面倒だから
			$arr_res[] = $row;
		}
	}

	$sql = 'insert into log_line_bot (mid,name,msg) values (?, ?, ?)';
	$stmt = $pdo->prepare($sql);
	$stmt->execute(array($mid,$name, $text));

	if(count($arr_res) > 0){
		$res = $arr_res[array_rand($arr_res,1)];
		$res_text = "{$res['name']}がさっき「{$res['msg']}」って言ってましたよ";

		$response_format_text = array('contentType'=>1,"toType"=>1,"text"=>$res_text);
		$post_data = array("to"=>array($to),"toChannel"=>"1383378250","eventType"=>"138311608800106203","content"=>$response_format_text);

		$ch = curl_init("https://trialbot-api.line.me/v1/events");
		curl_setopt($ch, CURLOPT_POST, true);
		curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
		curl_setopt($ch, CURLOPT_HTTPHEADER, array(
		    'Content-Type: application/json; charser=UTF-8',
		    'X-Line-ChannelID: xxx',
		    'X-Line-ChannelSecret: xxx',
		    'X-Line-Trusted-User-With-ACL: xxx'
		    ));
		$result = curl_exec($ch);
		curl_close($ch);
	}
}

テーブル定義

create table log_line_bot(
id INT NOT NULL AUTO_INCREMENT,
mid CHAR(64) NOT NULL,
name VARCHAR(255) NOT NULL,
msg VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;

新入社員の皆さんへ

今日から社会人となった新入社員の皆さん、おめでとう

私も15年前、入社式を経験し社会の一員となりました

皆さんよりもほんの少し(15年だけ)先輩の私から、入社式での挨拶代わりに
伝えたいことをここに残します

これから皆さんは、会社の先輩や上司からいろいろ学び成長をしていくでしょうが
どうか目指す先を目の前の先輩や上司にしないでください

皆さんの目指す先は、もっとはるか遠くにあります

今はまだ自分に実力がなかったとしても、隣の先輩がいかに優秀に見えたとしても
自分自身の可能性を信じてください
先輩を目標にしてしまったら、きっとその先輩を超えることは一生できません

自分には世界を変える力があると本気で信じてください

皆さんが新入社員研修を終えて私たちのチームの一員として最初に行う仕事は
「先輩から与えられた課題」でも、「誰にでもできる仕事」でもなく、いつか
皆さん自身が世界を変えるための「最初の1歩」なのです

そして、始めのうちは先輩や上司が先導してくれるであろう歩みを、なるべく早く
自分のものとしてください

そうでなければ、皆さんに待っているのは「先輩の劣化コピー」です

先輩や上司の意見を真正面から否定し、恐れることなく自論を展開できる
ようになってください
ダイバーシティ(多様性)は歓迎すべきもので、私たちのチームは
先輩や上司の意見を否定することを好ましいことであるとの価値観を
もっています。安心してください

そしていつの日か私たちを老害と呼び、自分たちこそが世界を変えることが
できるんだということを示してください

私は皆さんなら、それができると信じています

入社おめでとう

1日の中のトラフィックの変動に合わせてEC2の起動台数を増減させる方法

JAWS-UG Advent Calendar 2013 4日目の投稿です
昨日は@j3tm0t0さんのg2インスタンスを使って宇宙へ行こう!です

11/2の第9回JAWS-UG大阪で発表したときにはManualScalingとして紹介した方法の解説

ゲームに限らず、アクセス数の多いブログやニュースサイトなんかでは、例えばお昼の12時からの1時間のほうが、その前後の1時間に比べて数倍のトラフィックがくることがよくありますよね

1日のピーク値にあわせてサーバを用意しておくというのはイマイチ「クラウド」っぽくありません
そこで、毎日のトラフィックの増減の予想から、指定時間でサーバを起動させる仕組みを作ってみました

なお、指定時刻でサーバを増減させる仕組みを、AWSのドキュメントではScheduled Scalingっていうらしいです。AutoScalingのコマンドで実現可能です。
詳しくはこちら

この公式のScheduled Scalingは、既に運用面も含めてAutoScaling構成になっている環境では簡単に使えるのですが、今回はあえてAutoScalingを使わない方法をご紹介します

今回ご紹介する方法には、コチラのようなメリットがあります

・サーバ減少時にTerminateではなくStop状態でサーバを保存しておける。ログ消えない
・サーバ増加時にはStop状態のサーバをStartさせる。インスタンスの作成時間を短縮
・最新プログラムをサーバへダウンロードするときは前回Stop時からの差分のみなのでわりと高速
・最新プログラムの反映を待ってからELBにサーバを組み込む

ということで、まずは全サーバに次のような起動スクリプトを仕掛けます

#!/bin/bash
#
# Auto associate Elastic IP , rsync and register ELB
#
# chkconfig: 345 98 6
# description: rsync and register ELB
# processname: rsync-elb
#
export JAVA_HOME=/usr/lib/jvm/jre
export EC2_HOME=/opt/aws/apitools/ec2
export AWS_ELB_HOME=/opt/aws/apitools/elb

# 初期化
RSYNC_SERVER=""
ELB_SERVER=""

# 自分のインスタンスIDを取得
INSTANCE_ID=$(/usr/bin/curl http://169.254.169.254/latest/meta-data/instance-id)

# インスタンスIDを元にtagを取得
TAGS=`/opt/aws/apitools/ec2/bin/ec2-describe-tags -O アクセスキー -W シークレットキー --filter "resource-id=${INSTANCE_ID}"  --region ap-northeast-1|/usr/bin/awk '{print $4,$5}'`

# スペース区切りでtagが返ってくるので配列へ
ARR_TAGS=(`echo $TAGS`)

# tagのキーとバリューが交互に入っているのでループ
for i in `seq 1 ${#ARR_TAGS[@]}`
do
  if [[ 'rsync' == ${ARR_TAGS[$i-1]} ]];then
    RSYNC_SERVER=${ARR_TAGS[$i]}
  fi
  if [[ 'elb' == ${ARR_TAGS[$i-1]} ]];then
    ELB_SERVER=${ARR_TAGS[$i]}
  fi
#  キーとバリューが交互なので1つ飛ばす
  i=`expr $i + 1`
done

if [[ $RSYNC_SERVER != "" && $ELB_SERVER != "" ]]; then
#   rsync実行
  /usr/bin/sudo -u ユーザー /usr/bin/rsync -av --update -e "/usr/bin/ssh -i /home/ユーザー/.ssh/秘密鍵 -o \"StrictHostKeyChecking no\"" --include="いろいろ" --exclude="*"  "${RSYNC_SERVER}:/コピー元ディレクトリ"  /コピー先ディレクトリ
  if [ $? -eq 0 ]; then
#   rsync成功 ELB登録
    /opt/aws/apitools/elb/bin/elb-register-instances-with-lb  ${ELB_SERVER} --instances ${INSTANCE_ID} -O アクセスキー -W シークレットキー  --region ap-northeast-1
    if [ $? -eq 0 ]; then
#      ELB登録成功 Apache起動
      /etc/init.d/httpd start
    fi
  else
#   失敗はシャットダウン
    /sbin/shutdown -h now
  fi
else
# 失敗はシャットダウン
  /sbin/shutdown -h now
fi

ttyがない状態でもsudoが使えるように下記の修正


# visudo
コメントアウト
#Defaults    requiretty

そして、次のようなマネージメントコンソールからタグを仕掛けます
scaling

rsync:rsync先のサーバのPublicDNS
elb:elbのLoad Balancer Name

次に指定時間に増減させたいインスタンスIDを指定した起動・停止用スクリプトを作成します

起動用スクリプト

vi /home/ec2-user/EC2-server-start.sh 
------------------------------------------------------------------------------
#!/bin/sh
/opt/aws/bin/ec2-start-instances  -O アクセスキー -W シークレットキー  --region ap-northeast-1 i-XXXXXXXX i-YYYYYYYY
------------------------------------------------------------------------------
chmod +x  EC2-server-start.sh

停止用スクリプト

vi /home/ec2-user/EC2-server-stop.sh
------------------------------------------------------------------------------
#!/bin/sh
# ELB切り離し
elb-deregister-instances-from-lb ELBの名前 --instances  i-XXXXXXXX,i-YYYYYYYY  -O アクセスキー -W シークレットキー   --region ap-northeast-1

# ELB切り離し後、30秒ほど時間を空ける
sleep 30

# インスタンス停止
/opt/aws/bin/ec2-stop-instances -O アクセスキー -W シークレットキー  --region ap-northeast-1 i-XXXXXXXX i-YYYYYYYY
------------------------------------------------------------------------------
chmod +x  EC2-server-stop.sh

最後にお好みの起動・停止時間をcronで設定して終わり

明日は@ar1さんです。

Amazon RDS for PostgreSQL で PostGIS を使う方法

起動直後のRDS(PostgreSQL)では、空間データベース用の関数などが定義されてないので、そのままでは使えない

postgreSQLユーザーの権限不足で定義ファイルのpostgis.sqlやspatial_ref_sys.sqlとか実行できないし、どうしたものかと思っていたけど、以下を実行することで解決

create extension postgis;
create extension postgis_topology;

PostgreSQL 9.1からは、extensions使ってPostGISインストールできるんですね
いつも定義ファイルを自分で実行していたので知らなかった

select postgis_version();
2.1 USE_GEOS=1 USE_PROJ=1 USE_STATS=1

ばっちり使えました

カテゴリー: AWS

新人ソフトウェアエンジニアが知るべき13のこと

今年の新入社員に向けて、つらつらと書いてみた。

 

1.学び続ける覚悟を持とう

日々テクノロジーは進歩している。
エンジニアとして生きていくなら一生学び続ける覚悟が必要だ。

2.基礎を学ぼう

ここでいう基礎とは、TCP/IPやOSのファイルシステムなんかだ
基礎は新しいことを学ぶときに、きっと役に立つ。

3.リファレンスを読もう

googleで検索してblogに書かれたプログラムを無条件に信じてはいけない。
たまたま見たblogの内容が良くない方法(アンチパターン)かもしれない。
信じていいのは公式のリファレンスだけだ。

4.ソースも読もう

リファレンスが不十分だったり理解できないときは、躊躇せずソースを読もう。
たとえばPHPはC言語で書かれているが意外と読めるものだ。
ソースを読んで理解することは一人前になる通過儀礼みたいなものだと覚悟しよう。

5.「動けばいい」とは決して考えないようにしよう

君たちが作るプログラムは、必ず利用者がいる。
利用者に使ってもらえるものを作ろう。「動く」だけでは駄目なんだ。
誰にも観てもらえない映画を作る映画監督になりたいかい?

6.バグに遭遇したら、まずは冷静になろう

よく言われているが、「プログラムは思ったようには動かない。書いたとおりに動く。」は真実だ。
99%は目の前に原因がある。原因が目の前にないことは1%くらいだ。
99:1が決して逆ではないと肝に銘じよう。

7.思想を理解しよう

他人のソースを読むとき処理の内容を追うだけでなく「何故そのように作ったのか」を理解することは大切だ。
計算量を減らして負荷軽減を狙っている/不正な値が入らないようにしている/キャッシュ化することで高速化を狙っている等
コードから学ぶというのは思想を理解することに等しい。

8.良書を探そう

この本いいなと思ったらamazonで検索してみよう。
今は便利な世の中で「この商品を買った人は~」と良書っぽものが芋づる式に見つかる。

9.モチベーションを意識しよう

エンジニアとして学び続けるのは時として大変だ。
行動を起こそうとする源、すなわちモチベーションを意識しよう
朝、鏡を見るときに「自分はなぜエンジニアになったのか?」と問いかけるのもいい
君たちのモチベーションを手っ取り早く上げてくれるはずだ

10.勉強会やコミュニティに参加しよう

会社だけでなく外の風に触れることも時には必要だ。
新しい刺激はモチベーションの維持にもつながる。

11.アウトプットしよう

勉強会でLTをするのでもblogを書くのでもなんでもいい。
なにかをアプトプットするだけで世界は大きく変わる。

12.コミュニティ疲れ・勉強会疲れを感じだたら距離を置こう

「疲れ」の意味がわからないうちは気にしなくていい。
これがそうかな?と思ったら立ち止まろう。もう君は大丈夫だ。
また気が向いたり考え方が変わったら参加してみるといい。

13.趣味や夢中になれるものを持とう

できたら技術以外のものが望ましい。
どんなものであれ君たちの人生を豊かにしてくれる。

CentOSでTimeMachineサーバを作る

Macを何台か買ったのを機に、その辺に余っていたハード使ってTimeMachineサーバを立てたメモ

環境

CentOS6.3(Minimalでインストール)

必要なパッケージを入れる


yum -y update
yum -y install wget cracklib-devel openssl-devel quota-devel libtool automake autoconf db4-devel pam-devel tcp_wrappers-devel libgcrypt-devel avahi-dnsconfd avahi-devel libacl-devel openldap-devel make lynx

nss-mdnsのインストール

avahiで使うので導入する


cd /usr/local/src
wget http://0pointer.de/lennart/projects/nss-mdns/nss-mdns-0.10.tar.gz
tar xzvf nss-mdns-0.10.tar.gz
cd nss-mdns-0.10
./configure
make
make install

vi /etc/nsswitch.conf
hostsの行を下記の用に書き換え
hosts:      files mdns4_minimal [NOTFOUND=return] dns mdns4

netatalkのインストール


cd /usr/local/src
wget http://prdownloads.sourceforge.net/netatalk/netatalk-3.0.2.tar.gz
tar xzvf netatalk-3.0.2.tar.gz
cd netatalk-3.0.2
./configure --with-init-style=redhat-sysv
make
make install

バックアップを取りたいmacごとのアカウントの作成


useradd user1
passwd user1
su user1
mkdir ~/TM
exit

useradd user2
passwd user2
su user2
mkdir ~/TM
exit

以下、必要な台数分繰り返し

netatalkの設定


vi /usr/local/etc/afp.conf

[Global]
; Global server settings
vol preset = default_for_all_vol

[default_for_all_vol]
file perm = 0600
directory perm = 0700

[user1TimeMachine]
path = /home/user1/TM
valid users = user1
time machine = yes
vol size limit = 100000

[user2TimeMachine]
path = /home/user2/TM
valid users = user2
time machine = yes
vol size limit = 100000

以下、必要な台数分繰り返し

iptablesの設定


vi /etc/sysconfig/iptables
-A INPUT -m state --state NEW -m tcp -p tcp --dport 548 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp --dport 548 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp --dport 5353 -j ACCEPT
service iptables restart

netatalkの自動起動


chkconfig netatalk on
service messagebus start
service avahi-daemon start
service netatalk start

これでmac側のTimeMachineのディスク選択に表示されるはず
mac側で見えるようになるまで時間がかかることもあるかも
vol size limitはHDDの容量と相談

EC2 + nginx + php-fpm

yumで何でもかんでも入れられて楽ちん

sudo yum install nginx
sudo yum install mysql-server
sudo yum install php php-fpm php-mbstring php-mysql

nginxの設定

sudo vi /etc/nginx/nginx.conf

        charset utf-8;
        root /var/www/html;
        index index.php;

        location ~ \.php$ {
            root /var/www/html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }

※元々のコメントアウトを使うと「file not found」の洗礼を受ける

php-fpmの設定

sudo vi /etc/php-fpm.d/www.conf

    user = nginx
    group = nginx

起動

sudo /etc/init.d/nginx start
sudo /etc/init.d/php-fpm start
カテゴリー: AWS

Unity NGUIでjavascriptを混在させる

http://www.tasharen.com/forum/index.php?topic=1763.0

nguijs

(画像はリンク先より)

1.NGUIフォルダの外側にpluginというフォルダを作る

2.pluginフォルダの内側にNGUIというフォルダを作る

3.2で作ったフォルダに画像内の赤で示したフォルダを移動させる

これだけで動くようになる

 

なぜこれで動くようになるのか?だけど、unityのコンパイルの順番に由来する。

pluginフォルダ内は他よりも先に読み込まれるので、javascriptで記述したファイルから

C#で記述したNGUIを使えるようになるという原理

Unity NGUI2.3.4で画面アスペクト比を固定する

ウダサンコウボウ:Unity]NGUIで画面サイズに合わせる(NGUI2.2.2対応版)
リンク先は2.2.2対応とのことでしたが、そのままで2.3.4で動きました

NGUI2.3.4では、縦方向基準での調整しか実装されてないのでiPhone5のような縦長の端末だと縦方向に合わせようとする→左右がカットされるという問題が起きてしまいます。
下記のスレッドを読む限り「NGUIに新たなオプションつけたら混乱を招くかもね。補助スクリプト使おうぜ」というニュアンスのようなので、今後のバージョンでも追加されないはず

http://www.tasharen.com/forum/index.php?topic=1933.15

スレッドにも同じコードが投稿されてましたけど


using UnityEngine;
using System.Collections;
 
[ExecuteInEditMode]
public class NGUIUtilScalableUIRoot : MonoBehaviour
{
 public int manualWidth = 640;
 public int manualHeight = 960;
  
 UIRoot uiRoot_;
  
 void Awake()
 {
  uiRoot_ = GetComponent();
 }
  
 void Update ()
 {
  if(!uiRoot_ || manualWidth <= 0 || manualHeight <= 0){ return; }
   
  int h = manualHeight;
  float r = (float)(Screen.height * manualWidth) / (Screen.width * manualHeight); // (Screen.height / manualHeight) / (Screen.width / manualWidth)
  if(r  > 1){ h = (int)(h * r); } // to pretend target height is more high, because screen width is too smaller to show all UI
   
  if(uiRoot_.automatic){ uiRoot_.automatic = false; }
  if(uiRoot_.manualHeight != h){ uiRoot_.manualHeight = h; }
 }
}

このコードをUI Root(2D)あたりに張り付ければOK

リンク先では、カメラの外側も見えてしまうから黒いパネルで隠そうぜ!って感じですが、
背景となる適当な画像を画面サイズの外側の分もデザインして、はみ出る状態で設置することで解決してみた