LoginSignup
17
17

More than 5 years have passed since last update.

angularjs で Twitter クライアントを作成し AWS.S3 で動かす

Last updated at Posted at 2016-01-20

大寒波です。
霜も降り息も白くなり、やっと冬らしくなってきました。
気温が大きく変化する時期は体調を崩しやすくなります。
風邪に気をつけて、外から帰ったら手洗いうがいを怠らないようにしましょう。

AngularJS のお勉強がてら Twitter クライアントでも作ろうと思いました。
やったことを自分の備忘録も兼ねて書いておきます。

やりたいこと

  • Twitter クライアント作る(まずはタイムラインの表示)
    • AngularJS で。
    • yeoman 使いたい。
  • AWS.S3 に配置してスマホで見たい。

んで、出来上がったものはこんなものです。
mytwitter_demo.gif

Twitter アプリ登録

今回作成するアプリは Twitter に OAuth で認証(アクセス)します。
まずは、Twitter の Application Management にて今回作成するアプリを登録します。

twitter_dev.png

※ 諸事情により、上記で登録しているアプリ名(twikurom)とクライアントアプリ名(mytwitter)が異なっていますが気にしないでください。

Callback URL は OAuth の認証URL である https://oauth.io/auth を設定してください。
設定しないとログイン後にアプリに戻ってきません。

OAuth.io アプリ登録

今回は、OAuth のプロバイダ認証を楽にしてくれる OAuth.io サービスを使用します。
Twitter で登録した API Key を設定します。

OAuth_twitter.png

twikurom というアプリを追加していますが、デフォルトで追加されているアプリでも問題ないです。

General タブを開きます。
Public Key は後ほど使用します。
Domains & URLs whitelist に localhost*.amazonaws.com を追加してください。

OAuth_General.png

アプリ作成

開発準備

まずは、ディレクトリの作成と必要なパッケージをインストールします。
yeoman の generator は公式の generator-angular を使用します。

$ mkdir mytwitter; cd mytwitter
$ npm install yo bower grunt-cli -g
$ npm install generator-angular generator-karma --save-dev

ジェネレータをローカルインストールしましたが、他でも使う場合は -g つけてグローバルにインストールしてもいいと思います。

yeoman でプロジェクトを作成します。

$ yo angular

んで、色々聞かれます。

     _-----_
    |       |    .--------------------------.
    |--(o)--|    |    Welcome to Yeoman,    |
   `---------´   |   ladies and gentlemen!  |
    ( _´U`_ )    '--------------------------'
    /___A___\    
     |  ~  |     
   __'.___.'__   
 ´   `  |° ´ Y ` 

Out of the box I include Bootstrap and some AngularJS recommended modules.

? Would you like to use Gulp (experimental) instead of Grunt? No
? Would you like to use Sass (with Compass)? No
? Would you like to include Bootstrap? Yes
? Which modules would you like to include? 
 ◉ angular-animate.js
 ◯ angular-aria.js
❯◉ angular-cookies.js
 ◉ angular-resource.js
 ◯ angular-messages.js
 ◉ angular-route.js
 ◉ angular-sanitize.js
 ◉ angular-touch.js

こんな感じで回答すると、プロジェクトのテンプレートがゔぁーっと作成されます。
途中で package.json を上書きするか聞かれてます(ログ流れちゃって見つけづらいんすけど)。Enter 押すと上書きしちゃうんで気をつけてくださいね。

npm WARN karma-jasmine@0.3.6 requires a peer of jasmine-core@* but none was installed.
npm WARN karma-phantomjs-launcher@0.2.3 requires a peer of karma@>=0.9 but none was installed.
npm WARN karma-phantomjs-launcher@0.2.3 requires a peer of phantomjs@>=1.9 but none was installed.
npm WARN grunt-karma@0.12.1 requires a peer of karma@^0.13.0 || >= 0.14.0-rc.0 but none was installed.

不足しているパッケージがあった場合、追加しましょう。
karma、jasmine-core、phantomjs が足らんと言われているので追加します。

$ npm install karma jasmine-core phantomjs --save-dev

ローカルサーバを起動して確認します。

$ grunt serve

angular.png

おk。
ライブリロードしているので、ソースを変更して保存すると即座に反映されます。すごい。

ビルドしてローカルサーバで確認します。

$ grunt serve:dist

先ほどと同じ画面が表示されますが、distディレクトリに配置したビルド後のアプリが動いています。

dist
├── 404.html
├── favicon.ico
├── fonts
│   ├── glyphicons-halflings-regular.eot
│   ├── glyphicons-halflings-regular.svg
│   ├── glyphicons-halflings-regular.ttf
│   ├── glyphicons-halflings-regular.woff
│   └── glyphicons-halflings-regular.woff2
├── images
│   └── yeoman.8cb970fb.png
├── index.html
├── robots.txt
├── scripts
│   ├── scripts.aa0894ba.js
│   └── vendor.cca3e06b.js
└── styles
    ├── main.16c86e60.css
    └── vendor.2ac5f564.css

Twitterクライアント作成

まずはじめに、OAuth の SDK を bower でインストールします。
bower でインストールしたモジュールは、ビルド時に index.html に挿入されます。便利です。

$ bower install oauth-js --save

main.html を編集してざっくりとしたレイアウトを決めます。

mytwitter/app/scripts/controllers/main.html
<div class="container">
    <h1>My Twitter</h1>

    <div class="row">
        <div class="col-xs-12">
            <button id="connectButton" type="button" class="btn btn-primary">サインイン</button>
            <button id="getTimelineButton" type="button" class="btn btn-info">更新</button>
            <button id="signOut" type="button" class="btn btn-link">サインアウト</button>
        </div>
    </div>
    <hr/>

    <div class="row">
        <div class="col-xs-12" id="results">
            <div class="row well">
                <div class="col-xs-2">
                    <img src="https://pbs.twimg.com/profile_images/679162128750665729/r6ALQmhy_bigger.png" class="img-circle">
                </div>
                <div class="col-xs-10">
                    <small>名前</small>
                    <br> ツィート
                </div>
            </div>
        </div>
    </div>
</div>

grunt serve で動かしてみるとこんな感じ

main.html.png

上記の html に angularjs のディレクティブを記述していきます。

mytwitter/app/scripts/controllers/main.html
<div class="container" ng-controller="MainCtrl">
    <h1>My Twitter</h1>

    <div class="row">
        <div class="col-xs-12">
            <button ng-click="main.connect()" id="connectButton" type="button" class="btn btn-primary">サインイン</button>
            <button ng-click="main.refresh()" id="getTimelineButton" type="button" class="btn btn-info">更新</button>
            <button ng-click="main.signOut()" id="signOut" type="button" class="btn btn-link">サインアウト</button>
        </div>
    </div>
    <hr/>

    <div class="row">
        <div class="col-xs-12" id="results">
            <div class="row well" ng-repeat="tweet in main.tweets">
                <div class="col-xs-2">
                    <img ng-src="{{tweet.user.profile_image_url}}" class="img-circle">
                </div>
                <div class="col-xs-10">
                    <small>{{tweet.user.name}}</small>
                    <br> <span ng-bind-html="tweet.text"></span>
                </div>
            </div>
        </div>
    </div>
</div>

Twitter の認証やデータ取得を行うサービスを作成します。
services.jsscripts 配下に追加します。

mytwitter/app/scripts/services.js
'use strict';

function twitterService($q) {
    var authResult = false;
    return {
        initialize: function() {
            // OAuth.io アプリの公開キー(PublicKey)を設定する。
            OAuth.initialize('xxxxxxxxxxxxxxxxxxxxxxxxxxx', {
                cache: true
            });
            authResult = OAuth.create('twitter');
        },
        isReady: function() {
            return authResult;
        },
        connectTwitter: function() {
            var deferred = $q.defer();
            OAuth.popup('twitter').done(function(result) {
                authResult = result;
                deferred.resolve();
            });
            return deferred.promise;
        },
        clearCache: function() {
            OAuth.clearCache('twitter');
            authResult = false;
        },
        getLatestTweets: function() {
            var deferred = $q.defer(),
                url = '/1.1/statuses/home_timeline.json';

            authResult.get(url)
                .done(function(result) {
                    deferred.resolve(result);
                })
                .fail(function(err) {
                    deferred.reject(err);
                });
            return deferred.promise;
        }
    };
}

angular.module('mytwitterApp.services', [])
    .factory('twitterService', twitterService);

index.html にてサービスの script タグを追加します。

mytwitter/app/index.html
<!-- build:js({.tmp,app}) scripts/scripts.js -->
<script src="scripts/app.js"></script>
<script src="scripts/services.js"></script>
<script src="scripts/controllers/main.js"></script>
<script src="scripts/controllers/about.js"></script>
<!-- endbuild -->

app.js にて、モジュールを追加します。

mytwitter/app/scripts/app.js
angular
  .module('mytwitterApp', [
    'ngAnimate',
    'ngCookies',
    'ngResource',
    'ngRoute',
    'ngSanitize',
    'ngTouch',
    'mytwitterApp.services'
  ])

最後にコントローラを実装します。

mytwitter/app/scripts/controllers/main.js
'use strict';

function MainController(twitterService) {
    var vm = this;

    vm.tweets = [];
    twitterService.initialize();

    vm.refresh = function() {
        twitterService.getLatestTweets().then(function(result) {
            vm.tweets = vm.tweets.concat(result);
        }, function() {
            // error
        });
    };

    vm.connect = function() {
        twitterService.connectTwitter().then(function() {
            if (twitterService.isReady()) {
                vm.refresh();
            } else {
                console.log('unable to connect twitter');
            }
        });
    };

    vm.signOut = function() {
        twitterService.clearCache();
        vm.tweets = [];
    };

    if (twitterService.isReady()) {
        vm.refresh();
    }
}

angular.module('mytwitterApp')
    .controller('MainCtrl', MainController);

初期画面です。
イメージ1.png

サインインボタンを押下すると Twitter 認証ダイアログが開きます。
2016-01-20 10.31.56.png

認証に成功すると元画面にタイムラインが表示されます。
2016-01-20 15.11.41.png

S3

配置

ビルドしておきます。

$ grunt build

AWS の S3 に新しいバケットを作成しましょう。
アップロードメニューから、dist 配下に作成されたファイルをアップロードします。

s3_upload.png

バケットの設定

バケットのプロパティから、静的ウェブサイトホスティングを有効にします。
エントリポイントは index.html を指定し保存します。

アクセス許可 → バケットポリシーの編集 にて、以下を設定します。
バケット名は変更してください。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::aws.bucket.name/*"
        }
    ]
}

静的ウェブサイトホスティングのエンドポイントに設定されている URL にアクセスします。

localhost で実行したものと同様であればOKです。
せっかくだから携帯端末で確認してみましょう。

IMG_2949.jpg

ちょっとレイアウトがごめんなさい。

参考

バージョン情報

  • Chrome: 47.0.2526.106
  • node: v4.2.4
  • npm: 3.5.3
  • yeoman: 1.6.0
    • generator-angular: 0.15.1
    • generator-karma: 1.0.1
  • bower: 1.7.2
  • grunt-cli v0.1.13
  • grunt v0.4.5
17
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
17