Wakotech Blog

ポエム

node.jsをインストールし直す際に苦戦した結果nodebrewを使いました

はるか昔にMac OS Xインストーラから直接インストールしていたNode.js。
バージョン管理が面倒だったり、npmをどうインストールしたかも覚えてないせいでsudoが必要だったり、一部パッケージがうまく動いてくれなかったり、問題ばかり発生していたのでnodeごとインストールし直したのでメモしておきます。
結論からいうとbrewでインストールするのが大変だったのと、バージョン管理出来た方が後々楽そうなのでnodebrewをインストールしました。

まずnodeをアンインストールします。
こちらのStack Overflowを参考にコマンドで削除します。

lsbom -f -l -s -pf /var/db/receipts/org.nodejs.pkg.bom \
| while read i; do
  sudo rm /usr/local/${i}
done
sudo rm -rf /usr/local/lib/node \
     /usr/local/lib/node_modules \
     /var/db/receipts/org.nodejs.*

これでnodeが消えました。
次に、nodebrewを導入します。nodebrewについては公式のgithubの通りに。
hokaccha/nodebrew · GitHub

curlperlも入っているので一行でインストール。PATHも追記しておきましょう。

curl -L git.io/nodebrew | perl - setup
export PATH=$HOME/.nodebrew/current/bin:$PATH

nodeをインストールします。バージョン指定以外にもstableで安定版、latestで最新版を指定できます。今回は安定版(v0.10.33)にしました。
$ nodebrew use (バージョン) で使用バージョンを指定できますが、エイリアスを設定できるので、安定版であるv0.10.33に対してstableとつけておきます。

nodebrew install stable
nodebrew alias stable v0.10.33
nodebrew use stable

パッケージ管理を行うnpmも入っているかと思います。
ためしにいくつかパッケージを入れてみると、パッケージの方にも上記のpathで通っているかと思います。
npmについてはここでは説明しませんが、$ npm install -g (パッケージ名) でインストールすることができます。-gはglobalで、有効にしているnode全体で使えるようになります。-gを指定しないと、現在のディレクトリ以下にインストールされます。
(ここで勘違いをして詰まっていたのですが、expressのインストールはexpress-generator、coffeeのインストールはcoffee-scriptなんですね。ここが原因でpathが通っていないと勘違いしていました……。)

とりあえずyeomanでangularのひな形を作って動かしてみます。

npm install -g yo grunt-cli bower generator-angular
yo angular
grunt server

以前のnpmでうまく動かなかった部分が動きました!というわけで勘違いさえしなければnodebrewですぐ環境が整いました。



……ついでにbrewでインストールしようとした際に失敗したことも書いておきます。
$ brew install node を叩くとビルドで失敗しました。ビルド中にnodeコマンドでcli.jsを実行しているようなのですが、nodeがないので実行できず、エラー……と。
nodeがないと言われても今から入れるんだから当たり前でしょと思い、それ以上の原因も調べてもあまりでてこず(npm導入にnodeのpathが貼られてない問題ばかり)、nodebrewに行き着きました。

8月の終わり(近況報告)

毎日書くとはなんだったのかという感じですが、色々あったのであっという間に8月が終わってしまいました。
とりあえず技術的なことと、そのほかにしたことをまとめておく感じです。

まず今月は一旦rubyから離れてjavascriptを主に触っていました。先月はrailsから離れてrubyをしっかり触ろうという感じだったのですが、やりたいことは一通り終わったので。調べたり本を読んだりで新しいものを実際に書くところまではあまりできませんでしたが、coffeescriptをはじめ、書けそうなときはcoffeeで書くようにはしました。
それと、インターンシップでスタッフとして参加してきました。そちらはハイブリッドアプリの開発だったので、主にMonacaとNifty Cloud Mobile Backendを利用したhtml+jsでの開発のお手伝いという形でした。
OnsenUIというモバイルアプリ向けフレームワークを利用していて、当時は大変でしたが、慣れてきたので今後使っていきたいと思います。angularjsとの親和性も高いようなので。

開発以外では、サークルの旅行で海に行ったり、実家に帰ったり、本をとてもたくさん読んだり、色々な人と飲んだり。山の上にある大学から花火が綺麗に見えるということで、4年目にしてはじめて大学から調布の花火大会を見たりもしました。去年は開発をずっと勉強していて充実していたのですが、今年はやり残すことが無いように自由に過ごせている方かとは思います。

今後としてはcoffeescriptが好きになってきたので、それを踏まえてnode.jsやangularjs、yeomanやbower等でのweb開発をやっていくとともに、ruby on railsでのAPI開発で実際にモバイル向けアプリを開発していこうと思います。
インターン中のお話にもあった某サービスのAPIを使ったマッシュアップの開発も余裕があればしたいと思います、が、まずはTwitter関連で作りたいものがあるのでそれを……という感じです。

夏休み、まだ半分近く残っているので、色々楽しんでいきたいと思います。厳しい暑さもどうにかなってきて、夏が苦手な僕にも多少過ごしやすい気候になってきたので、自由に充実した時間を過ごそうと思います。

TwitterでリプライやRTが来たときにYOで通知してくれるのを実装しました

毎日何かしらはやってはいるんですが、記事にできるような区切りがつかないのでなかなか難しいものでした。
今回は、Twitterの通知を独自実装するのに際して、とりあえずYOで通知してくれるようにと思い実装しました。
YOはフレンドとして登録した特定の相手にYOとだけ送る事ができるハイコンテクスト(?)なサービスです。yoserverisdownなどのサービスもあり当初は盛り上がっていたのですが、最近では下火、ですが、APIを公開しているため、使ってみる事にしました。

http://dev.justyo.co/でログインし、YOを送る側のアカウント(アプリケーション)を登録し、APIキーを取得します。
あとはでapi_tokenとusernameを指定してPOSTするだけです。

require 'net/http'
require 'uri'

uri = URI.parse('http://api.justyo.co/yo/')
params = {api_token: API_TOKEN, username: USERNAME}
Net::HTTP.post_form(uri, params)

という形でYOすることができたので、TwitterのStreamingAPIと組み合わせて、YO通知を実装します。
@clientはhttp://yutaszk23.hatenadiary.jp/entry/2014/06/05/142337の通りに宣言されたStreamingAPI用のClientとします。

require 'twitter'
require 'net/http'
require 'uri'
require 'yaml'

def justyo
  uri = URI.parse('http://api.justyo.co/yo/')
  puts Net::HTTP.post_form(uri, {api_token: @YO_TOKEN, username: @YO_USERNAME})
end

def stream
  @client.user do |status|
    if status.is_a?(Twitter::Tweet)
      # reply判定
      if status.in_reply_to_screen_name == @user_screen_name
        justyo
      end

      # RT判定
      if status.retweeted_status.user.screen_name == @user_screen_name
        justyo
      end
    end

    # favorite判定
    if status.is_a?(Twitter::Streaming::Event) && status.name == :favorite
      justyo
    end
  end
end

@YO_TOKEN = YOUR_API_TOKEN
@YO_USERNAME = YOUR_YO_NAME

stream

これでこのプログラムが動いている間は(手元のPC上でOK)通知がYOで来るので、是非試してみてください。永続化したければPCを付けっぱなしにするかサーバで動かすか、で。
これで通知のないTwitterクライアントでも大まかな通知を受け取る事が出来るようになりました(公式併用すればいいのですが)。
これからはPush通知で詳細な内容を通知されるようにしたいのですが、ネイティブ側をいじらなければならないので厳しそうです……まずはAndroidからがんばってみます。

夏休みが開始したので毎日記事を書くことを心がけます

8月になりました。私は夏休みです。
毎日記事を書けるように新しいことに取り組んでいきたいです。

途中まで書いてまだ終わっていないこと
Windowsへの環境構築、カスタマイズ(minttyがうまくいかなくて中断)
rubyでのTwitterリマインダーbot開発(進めていますが寄り道してrubyで遊んでばかり)
・冷蔵庫管理アプリ(ハイブリッドアプリでのjsをしっかり理解したらがんばります。あとネイティブpush通知部分)
ruby単体でActiveRecord+Migrationを使用してのDB管理(作りながらbotに応用して使ってます)

やりたいこと
・wakolab.jpのデザインリニューアル、モバイル対応。全体的なjsの修正
Twitterのツイートを簡易解析してライフログ
・↑を応用して睡眠時間ベースや予定ベース、もしくはbotへの起床時間コマンドによる時間自動設定の目覚ましアプリの開発
Scala本(去年買った)
Android本(去年(ry
・生活に関連するものをまとめてPush通知実装

軽い目標としてはこんな感じです。夏の帰省ではテキストを持ち帰らなくても実家でコードが書けそうなので捗りそうです。おそらく気温も低くて過ごしやすいので。



それと、今日は卒業演習の中間発表を見てきました
前期は特に研究が多かったようで、作るものがはっきり決まっている人も多く、興味深いものもたくさんあったので、最終が非常に楽しみです。
デザイン系の人のスライドを見る機会もあまりなかったので、フォントやらレイアウトやら色使いやらとても参考になりました。きれいなスライドっていいですね。
自分がものをある程度作れるようになるにつれて、どのように作られるのかを考えると以前より楽しめるようになってきたと感じます。こういう部分でもプログラミングを勉強してきてよかったなと思います。
僕は卒業論文も制作もないので、自由に好きなことを研究できる身なので、自由にrubyやらtwitterやらで遊んでいますが、卒業までにはruby+twitter+スマホで生活を便利にできるようにしたいなと思ってます。
とりあえず次はruby関連で書くと思います。

Windowsの画面分割を快適に行う「WinSplit Revolution」を導入しました | Windowsカスタマイズその①

Windowsで開発環境をいい加減整えようと思ったので、シリーズ化して記事にしたいと思います。Macだとまとまった記事がたくさんあるんですがWindowsだと少ないので。
とりあえず仮想マシンXubuntuを入れるとかVagrantでCentOS7を使ってみようだとか思ったのですが、そもそもそれ以前に画面分割が標準のエアロスナップの2分割しかないのが色々不便だなーと思ったのでまずは画面分割から。
次回以降で、WindowsUnixライクなコマンドを使うためのMintty、VagrantでのCentOS複数マシン間での作業状態の共有あたりについてやっていきたいと思います。

まず今回導入したのは、画面分割を快適にするWinSplit Revolutionというものです。公式がアクセスできなかったためこちらからダウンロードしました。
Hotkeys settingsからキー操作の設定を、Layout settingsから画面サイズの設定をできます。画面分割操作は左上から右下まで9種類のコマンドに対して、それぞれ複数のサイズを割り当てることができます。
たとえば、右端(Right)に対して、25%と33%と50%を割り当て、キーボードショートカットのRight操作を行うたびに設定されたサイズで切り替わります。自分はテンキーがないので画面位置になぞらえCtrl+Alt+LをRightにあてました。
ある程度デフォルトでサイズがそろっているので、テンキーがあればそのまま、なければホットキー設定を変えるだけですぐに使えます。さらに、標準のエアロスナップに対して上書きをしないのも使いやすいポイントだと思います(Aqua Snapはエアロスナップ上書きな上に複数画面非対応で使いにくかったので)。
あとは使っているうちに画面サイズにあわせて必要な画面分割サイズを追加していくだけでだいぶ使いやすくなります。特にHD以上の高解像度の場合は2分割だけだと持て余してしまう部分もあるので。
自分の場合はメインディスプレイがWQHDなので、標準の33%(66%)、50%に加えて25%(75%)、20%(80%)を追加しました。他にも右下にターミナルを配置したりする都合でカスタマイズしようと思いますが、簡単にカスタマイズしやすいので使いやすそうです(最悪、自分で引き延ばせばいいですし)。

まずは画面分割環境が整ったので、次は開発環境を整えていきたいと思います。

update_name実装したらすごく攻撃されるので怖い

リマインダーbotのついでにTwitterのupdate_nameを実装してみたのですが(古い)、攻撃しようとしてくる人が多いので少し困ったところ、というか心配です。
"#{}"で対処できているはずだとは思うんですが、怖いので、この書き方はまずいというのがありましたら指摘して頂きたいです。
@clientはstreaming用、@rest_clientはrest用で認証して接続してあり、@user_screen_nameは自身のスクリーンネームを取得済みとします。

require 'twitter'

def stream
  regexp_name = /^@#{@user_screen_name}\supdate_name\s(.+)$/
  @client.user do |status|
    if status.is_a?(Twitter::Tweet)
      if status.in_reply_to_screen_name == @user_screen_name
        if status.text.match(regexp_name)
          update_name($1, status.user)
        end
      end
    end
  end
end

def update_name(updated_name, user)
  ng_regexp = /NGワード集/
  before_name = @rest_client.user.name
  begin
    if updated_name.match(ng_regexp)
      @rest_client.update("@#{user.screen_name} NGワードが含まれています")
    else
      @rest_client.update_profile(name: updated_name)
      notice = "#{user.name}(@#{user.screen_name})により改名されました: #{before_name} => #{updated_name}"
      puts notice
      @rest_client.update(notice)
    end
  rescue
    puts 'update_name denied.'
    notice = "@#{user.screen_name} 失敗しました: #{updated_name}"
    if notice.length < 140
      @rest_client.update("@#{user.screen_name} 失敗しました: #{updated_name}")
    else
      @rest_client.update("@#{user.screen_name} 失敗しました")
    end
  end
end

stream

Streamingで拾った中で該当するものがあればupdate_name処理をする、という形です。現状だと絵文字やダブルクォートがツイートはされるがスクリーンネームには反映されなかったり、同一人物からの連続した投稿が許されていたり、単純にツイート数が多くてうるさくなるという問題もあるのでそれらはこれからなおしていきます……。
ので、とりあえずはセキュリティ的に危険があればそれは早く対処したいという感じです(今は停止していますが)。皆様よろしくお願い致します。

さくらVPS(CentOS 6.5/1GB)でTerrariaのマルチサーバーを立てるのにとても大変だったお話

ついこの間SteamでTerrariaがセールだったため、友人達と数人で購入しました。VPSを借りていますがサイト公開くらいにしか使っていなかったのでどうせならとマルチサーバーを立ててみることに。
最初はここを参考にしていたのですが、ここにあいてあるTDSMはバージョンの都合で対応してないようで……なのでtshockの最新版を探して直接wgetすることにしました。
色々探した結果英語ですがここが一番わかりやすかったです。が英語なので簡単に概要と手順を説明します。

今回マルチサーバーを立てるのにはTShockというものを使用します。TShockにはTerrariaServer.exeが標準で入っているのでそれを起動すればマルチサーバーが立ちます。
しかしCentOSでは.exeは起動しないので、monoというものが必要だそうです。monoでは.NET製のexeファイルを動かすことができるそうです(全てを動かせる訳ではないみたい?)。
上記のページの通りにコマンドを打てばmonoもTShockも入ります。権限がなかったため $ echo ':CLR:M::MZ::/usr/local/bin/mono:' > /proc/sys/fs/binfmt_misc/register は動かせなかったのですが、これは.exeをmonoに関連づけるものらしいので、TerrariaServer.exeを起動するときに毎回monoをかませば問題ありません。

マルチサーバーを立てようとする際にsudoでコマンドを叩いたのですが、sudoだとPATHを張ったはずのmonoコマンドが見つからない……と思って調べてみると、sudoでは元のユーザのPATHが引き継がれないそうです。なのでこちらを参考に$ sudo visudo コマンドで設定ファイルを書き換えましょう。
これでmonoは動いてマルチサーバーが起動します。新たにワールドを作る際はコマンドに従って作成、既存ワールドを使う場合はtcpコマンド等でアップロードし、/Terraria/Worlds以下に配置しましょう。
ワールドを選択すればロードがはじまってワールドが起動する……のですが、足場がロードされていないため落ち続けてしまいます(正確には少しずつロードされているようですが)。
「Help, my map does not show up! Players just fall endlessly!」の項にあるようにLD_LIBRARY_PATHを宣言しても動きませんでした。原因はさきほどのPATH同様LD_LIBRARY_PATHがsudoに渡されていなかったためでした。
こちらの場合はvisudoに追記してもだめなようなので、コマンドを実行する際にenv LD_LIBRARY_PATH=/opt/mono/libと指定するしかないようです。もしくは、aliasを書いておくか。
$ sudo env LD_LIBRARY_PATH=/opt/mono/lib mono TerrariaServer.exe
このコマンドで正しく動くようになります。

他にはtshockのwikiを参考にconfig.jsonを書き換えたりコマンドを打って設定できるようです。また、大きいワールドの場合ロード時間がだいぶかかってしまうので注意が必要です(自分の環境ではLargeで20分程かかりました)。
起動時こそCPU使用率が100%になりますが、起動してしまえばそこまででもないので、最安の1GBプランでもどうにかなりそうだといいです(メモリは結構食われていますが)。
身内向けという感じではありますが、興味のある方はIPアドレスをお伝えしますのでご連絡ください。