Calmery.me

みっかぼうずにならないようがんばる

Gitのコミットメッセージを変更する

commit 48a2a97df5dd5f15241cb0dc6635c66b3a6b6c3f
Author: calmery <contact@calmery.me>
Date:   Sun Dec 18 13:33:08 2016 +0900

    Change layout

commit 9b8c43a562f3a1e095541bdaca4a58c76f6144c2
Author: calmery <ontact@calmery.me>
Date:   Sun Dec 18 12:44:53 2016 +0900

    Merge
$ git rebase -i 9b8c43a562f3a1e095541bdaca4a58c76f6144c2

変更したいコミットの部分の pick を edit に変更する.

pick db3d0e8 Change layout
=>
edit db3d0e8 Change layout

コミットの内容を変更できる.コミットをひとつひとつ変更できるみたい.

$ git commit --amend
$ git rebase --continue
...
$ git commit --amend
$ git rebase --continue

プッシュする.

$ git push -f

ElectronでTwitterのOAuth認証をする

これは Electron Advent Calendar 2016 - Qiita 15 日目の記事です.

はじめに

Electron で Twitter と連携したアプリケーションを作りたいけれど,どうすればアプリケーションから Oauth 認証できるのかということで作りました.
github.com

$ git clone https://github.com/calmery/ElectronAdventCalendar2016.git
$ cd ElectronAdventCalendar2016
$ npm -g install electron-prebuilt
$ npm install
$ electron .
// common.js
// Twitter API Token
consumerKey: 'YOUR_CONSUMER_KEY',
consumerKeySecret: 'YOUR_CONSUMER_KEY_SECRET',

実装

Node.js で Web サーバを立てて,それを Electron から操作するといった感じ.Node.js と Electron の間は socket.io を使ってやり取りを行うようにした.Web サーバには http モジュールと express を使っている.

実際に http モジュールを使い Web サーバを立てるときにポート番号を指定することができるが,自動でポート番号を割り当てることもできる.こちらからポート番号を指定すると,ポート番号が競合してしまったり,他のブラウザなどから開けてしまうので自動で割り当てた方が個人的にはいい気がする.

// ポート番号を指定して実行
server.listen( 3000 );

// ポート番号を指定せずに実行
server.listen();

// ポート番号を取得
server.listen().address().port;

passport を使って認証する

肝心の認証だが passport を使うと簡単にできた.詳しくは Node.js + Express + passport-twitterで認証Webアプリをつくる - Qiita などを参考にすると良さそう.API キーの指定とルーティングをするだけでよかった.

const passport        = require( 'passport' ),
      twitterStrategy = require( 'passport-twitter' ),
      session         = require( 'express-session' );

app.use( passport.initialize() );
app.use( passport.session() );
app.use( session( { secret: 'lectern' } ) );

app.get( '/oauth', passport.authenticate( 'twitter' ) );
app.get( '/callback', passport.authenticate( 'twitter', { 
    successRedirect: '/',
    failureRedirect: '/fail' 
} ) );

passport.serializeUser( function( user, done ){ done( null, user ) } );
passport.deserializeUser( function( user, done ){ done( null, user ) } );

passport.use( new twitterStrategy.Strategy( {
    consumerKey   : 'CONSUMER_KEY',
    consumerSecret: 'CONSUMER_KEY_SECRET',
    callbackURL   : 'http://127.0.0.1:' + port + '/callback'
}, function( token, tokenSecret, profile, done ){
    console.log( token, tokenSecret );
    ...
} ) );

js-yamlトークンを保存する

取得したトークンは js-yaml を使用して保存した.

// common.js
const jsYaml = require( 'js-yaml' );

module.exports = {
    
    getAbsolutePath: function(){
        return path.resolve( path.join.apply( this, [].slice.call( arguments ) ) );
    },
    
    writeFileSync: function( filePath, content ){
        try {
            fs.writeFileSync( this.getAbsolutePath( filePath ), content );
            return true;
        } catch( error ){
            return false;
        }
    },
    
    jsYaml: jsYaml
    
};

// express.js
const common = require( './common' );

common.writeFileSync( 'user.yaml', common.jsYaml.safeDump( {
    access_token: token,
    access_token_secret: tokenSecret
} ) );

こんな YAML ファイルが作られる.

access_token: YOUR_ACCESS_TOKEN
access_token_secret: YOUR_ACCESS_TOKEN_SECRET

ちなみにアプリケーションを立ち上げたとき,このアクセストークンを保存したファイルが無ければ認証ページにリダイレクトするようにしている.

app.get( '/', function( request, response ){
    if( common.exists( 'user.yaml' ) ) 
        response.sendFile( common.getAbsolutePath( 'public/index.html' ) );
    else 
        response.redirect( '/oauth' );
} )

TwitterAPI を使う

Twitter API の呼び出しは関数にまとめた.

// twitter.js
module.exports.getClient = function(){

    const config = common.yamlLoader( 'user.yaml' );

    const client = new twitter( {
        consumer_key       : common.consumerKey,
        consumer_secret    : common.consumerKeySecret,
        access_token_key   : config.access_token,
        access_token_secret: config.access_token_secret
    } );

    return {

        getUserTweet: function( condition ){
            return new Promise( function( resolve, reject ){
                client.get( 'statuses/user_timeline', makeOption( condition ), function( error, tweet, response ){
                    if( error === null ) 
                        resolve( tweet );
                    else 
                        reject( error );
                } );
            } );
        },
        ...
// index.js
io.sockets.on( 'connection', function( socket ){
    
    client = twitter.getClient()
    
    const emit = function( key, content ){
        io.sockets.to( socket.id ).emit( key, content );
    };
    
    const emitError = function( content ){
        emit( 'error', content );
    };
    
    socket.on( 'getUserTweet', function( user_id ){
        client.getUserTweet( user_id ).then( function( tweet ){
            emit( 'userTweet', tweet );
        }, emitError );
    } );
    
} );

ツイートを表示する

Electron 側での表示はこんな感じ.

<script src="/socket.io/socket.io.js"></script>
<script src="resources/preload.js"></script>
<script src="resources/index.js"></script>
// preload.js
var socket = io()

socket.on( 'error', function( error ){
    console.log( error )
} )

// index.js
socket.emit( 'getUserTweet', 'calmeryme' )

socket.on( 'userTweet', function( tweet ){
    
    for( var i=0; i<tweet.length; i++ )
        document.body.innerHTML += tweet[i].text + '<br><br>'
    
} )

指定したユーザのツイートを表示できた.
f:id:calmery:20161214211134p:plain

まとめ

Electron を使って Oauth 認証し,ユーザのツイートを取得することができた.Web の知識だけで簡単にアプリケーションを作ることができるのは本当にありがたい.Electron 万歳.あとは electron-packager を使って配布できる形式にすればいい.パッケージ化したアプリケーションの容量が大きくなってしまうことが難点だがよりアプリケーションっぽくなる.30分で出来る、JavaScript (Electron) でデスクトップアプリを作って配布するまで - Qiita が参考になった.もうほんとライブラリさまさまなので感謝しかない><

JPHACKS AwardDay(やっぱり東京は凄かった)

JPHACKS AwardDay に参加してきました.賞は何も取れなかった!残念すぎる…
終結果は JPHACKS 2016 最終審査結果を公開しました | JPHACKS | 全国6都市で開催する、日本最大級の学生向けハックイベント で見ることができる.他の作品が凄すぎる…

プレゼンの様子は JPHACKS | FRESH!(フレッシュ) - 生放送がログイン不要・高画質で見放題 で見ることができる.2時間47分辺りの,キュートなくまモンの姿を見ていただきたい(恥ずかしい)

ちょっと未来に生きすぎた.いい感じに写真も撮っていただいた.好きと言ってもらえたのがせめてもの救い.IMG_2450
落ち着いて考えるとお花とお話なんて頭おかしい.でも逆にそれが受けたのかなと思ったり思わなかったり.

ちなみに AwardDay の前日,ポケモン買いました.発売日に買えたので良かった.というか,オシャマリ可愛すぎませんか?

Givery の村上さんの勧めで Mashup Award にも申し込んだ.学生部門のオンライン選考で 部門賞決勝審査 に出ることができた.ただ当日は誰も行くことができなかった.残念すぎる…講義がなければ行きたかった.

ほとんど見ているだけになってしまったけど楽しかった.JPHACKS には来年も絶対出るし AwardDay 出たいし賞も取りたい.頑張る.
JPHACKS2016で作ったものまとめ - Calmery.me
IMG_3238
JP HACKS | Flickr