command line interface based Twitter client
修訂 | c73b1f92a94573af44b1f954bbd42f1c117b928d (tree) |
---|---|
時間 | 2012-12-19 23:44:47 |
作者 | hylom <hylom@hylo...> |
Commiter | hylom |
update comments
@@ -59,80 +59,52 @@ function authenticate(callback) { | ||
59 | 59 | } |
60 | 60 | |
61 | 61 | /* |
62 | - * ntwitter.Twitterクラスのインスタンスを生成する | |
63 | - * @param {Object} keys アクセスに使用するキー | |
64 | - * @returns 作成されたインスタンス | |
65 | - */ | |
66 | -function createTwitterClient(keys) { | |
67 | - var twitter = new Twitter(keys); | |
68 | - return twitter; | |
69 | -} | |
70 | - | |
71 | -/* | |
72 | - * .accountファイルにアクセストークン情報を書き出す | |
73 | - * @param {Object} twitter ntwitter.Twitterクラスのインスタンス | |
74 | - * @param {Function(err)} callback エラーオブジェクトを返すコールバック関数 | |
75 | - */ | |
76 | -function writeAuthenticationKeys(twitter, callback) { | |
77 | - var keys = { | |
78 | - access_token_key: twitter.options.access_token_key, | |
79 | - access_token_secret: twitter.options.access_token_secret | |
80 | - }; | |
81 | - fs.writeFile(configFile, JSON.stringify(keys, null, 2), 'utf8', callback); | |
82 | -} | |
83 | - | |
84 | -/* | |
85 | - * .accountファイルに保存しておいたアクセストークン情報を読み出す | |
86 | - * @param {Function(err, key)} callback コールバック関数。 | |
87 | - * err引数にはエラーオブジェクトが、 | |
88 | - * keys引数には読み出したアクセストークン情報を格納するオブジェクト | |
89 | - * 格納される | |
90 | - */ | |
91 | -function readAuthenticationKeys(callback) { | |
92 | - fs.readFile(configFile, 'utf8', function (err, data) { | |
93 | - if (err) { | |
94 | - callback(err); | |
95 | - return; | |
96 | - } | |
97 | - var keys = JSON.parse(data); | |
98 | - callback(err, keys); | |
99 | - }); | |
100 | -} | |
101 | - | |
102 | -/* | |
103 | 62 | * 認証を行ってntwitter.Twitterクラスのインスタンスを返す |
104 | 63 | * @param {Function(err, twitter)} callback コールバック関数 |
105 | 64 | * err引数にはエラーオブジェクトが、 |
106 | 65 | * twitter引数には作成されたインスタンスが格納される |
107 | 66 | */ |
108 | -exports.authenticate = function (callback) { | |
67 | +exports.getClient = function (callback) { | |
109 | 68 | var keys = { |
110 | 69 | consumer_key: consumerKey, |
111 | 70 | consumer_secret: consumerSecret |
112 | 71 | }; |
113 | 72 | // ファイルに保存しておいたアクセストークンを読み出す |
114 | - readAuthenticationKeys(function (err, data) { | |
73 | + fs.readFile(configFile, 'utf8', function (err, data) { | |
115 | 74 | // 読み出しに失敗したら認証を実行する |
116 | - if (err || data.access_token_key === undefined | |
117 | - || data.access_token_secret === undefined ) { | |
75 | + if (err) { | |
118 | 76 | authenticate(function (err, token, secret) { |
119 | 77 | if (err) { |
120 | 78 | callback(err); |
79 | + return; | |
121 | 80 | } |
81 | + | |
82 | + // クライアントを作成する | |
122 | 83 | keys.access_token_key = token; |
123 | 84 | keys.access_token_secret = secret; |
124 | - var twitter = createTwitterClient(keys); | |
85 | + var twitter = new Twitter(keys); | |
86 | + | |
125 | 87 | // アクセストークンをファイルに保存しておく |
126 | - writeAuthenticationKeys(twitter, function (err) { | |
88 | + var tokens = { | |
89 | + access_token_key: keys.access_token_key, | |
90 | + access_token_secret: keys.access_token_secret | |
91 | + }; | |
92 | + var jsonString = JSON.stringify(tokens, null, 2); | |
93 | + fs.writeFile(configFile, jsonString, 'utf8', function (err) { | |
94 | + // 処理完了 | |
127 | 95 | callback(err, twitter); |
128 | 96 | }); |
129 | 97 | }); |
130 | 98 | return; |
131 | 99 | } |
132 | 100 | // 読み出しに成功したらその値からクライアントを作成する |
133 | - keys.access_token_key = data.access_token_key; | |
134 | - keys.access_token_secret = data.access_token_secret; | |
135 | - var twitter = createTwitterClient(keys); | |
101 | + var token = JSON.parse(data); | |
102 | + keys.access_token_key = token.access_token_key; | |
103 | + keys.access_token_secret = token.access_token_secret; | |
104 | + var twitter = new Twitter(keys); | |
105 | + | |
106 | + // 処理完了 | |
136 | 107 | callback(null, twitter); |
137 | 108 | }); |
138 | -} | |
109 | +}; | |
110 | + |
@@ -1,8 +1,8 @@ | ||
1 | 1 | #!/usr/local/bin/node |
2 | 2 | |
3 | -var auth = require('./auth'); | |
4 | 3 | var readline = require('readline'); |
5 | 4 | |
5 | +var auth = require('./auth'); | |
6 | 6 | var tweetWriter = require('./tweetwriter'); |
7 | 7 | |
8 | 8 | var rl = null; |
@@ -20,7 +20,7 @@ var mode = { | ||
20 | 20 | } |
21 | 21 | } |
22 | 22 | |
23 | -// タイムラインモードを定義 | |
23 | +// timelineモードを定義 | |
24 | 24 | var timeline = { |
25 | 25 | start: function () { |
26 | 26 | if (rl !== null) { |
@@ -29,6 +29,7 @@ var timeline = { | ||
29 | 29 | } |
30 | 30 | tweetWriter.resume(); |
31 | 31 | process.stdin.once('data', function () { |
32 | + // commandモードに遷移 | |
32 | 33 | mode.start(command); |
33 | 34 | }); |
34 | 35 | process.stdin.resume(); |
@@ -38,7 +39,7 @@ var timeline = { | ||
38 | 39 | } |
39 | 40 | }; |
40 | 41 | |
41 | -// コマンドラインモードを定義 | |
42 | +// commandモードを定義 | |
42 | 43 | var command = { |
43 | 44 | start: function () { |
44 | 45 | rl = readline.createInterface({ |
@@ -61,42 +62,52 @@ var command = { | ||
61 | 62 | exit: function () { |
62 | 63 | }, |
63 | 64 | line: function (data) { |
65 | + // 入力された文字列に応じて処理を切り替える | |
64 | 66 | switch(data) { |
65 | 67 | case 'tweet': |
68 | + // writeMessageモードを開始する | |
66 | 69 | mode.start(writeMessage); |
67 | 70 | break; |
68 | 71 | case 'quit': |
72 | + // アプリケーションを終了する | |
69 | 73 | process.exit(0); |
70 | 74 | case '': |
75 | + // timelineモードに遷移する | |
71 | 76 | mode.start(timeline); |
72 | 77 | break; |
73 | 78 | default: |
79 | + // エラーメッセージを表示してtimelineモードに遷移する | |
74 | 80 | process.stdout.write('invalid command: ' + data + '\n'); |
75 | 81 | mode.start(timeline); |
76 | 82 | break; |
77 | 83 | } |
78 | 84 | }, |
79 | 85 | SIGINT: function () { |
86 | + // Ctrl-Cを受け付けたらtimelineモードに遷移する | |
80 | 87 | mode.start(timeline); |
81 | 88 | } |
82 | 89 | } |
83 | 90 | |
84 | -// tweet入力モードを定義 | |
91 | +// writeMessageモードを定義 | |
85 | 92 | var newMessage = ''; |
86 | 93 | var writeMessage = { |
87 | 94 | start: function () { |
95 | + newMessage = ''; | |
96 | + | |
97 | + // readlineインターフェイスのイベントハンドラの付け替えを行う | |
88 | 98 | rl.removeAllListeners('line'); |
89 | 99 | rl.removeAllListeners('SIGINT'); |
90 | 100 | rl.on('line', this.line); |
91 | 101 | rl.on('SIGINT', this.SIGINT); |
102 | + | |
92 | 103 | rl.setPrompt('tweet> '); |
93 | 104 | process.stdout.write('write tweet message and push Ctrl-C.\n'); |
94 | - newMessage = ''; | |
95 | 105 | rl.prompt(); |
96 | 106 | }, |
97 | 107 | exit: function () { |
98 | 108 | }, |
99 | 109 | line: function (data) { |
110 | + // 入力したメッセージを保存しておく | |
100 | 111 | if (newMessage === '') { |
101 | 112 | newMessage = data; |
102 | 113 | } else { |
@@ -105,10 +116,15 @@ var writeMessage = { | ||
105 | 116 | rl.prompt(); |
106 | 117 | }, |
107 | 118 | SIGINT: function () { |
119 | + // Ctrl-Cを受け付けたらメッセージの入力を終了する | |
108 | 120 | process.stdout.write('\n----\n'); |
109 | 121 | process.stdout.write(newMessage + '\n'); |
110 | 122 | process.stdout.write('----\n'); |
123 | + | |
124 | + // メッセージを表示し、投稿するかどうかを確認する | |
111 | 125 | var message = 'tweet this message? (y:yes/n:no) '; |
126 | + rl.question(message, onAnswer); | |
127 | + | |
112 | 128 | function onAnswer(answer) { |
113 | 129 | if (answer === 'y') { |
114 | 130 | twitter.updateStatus(newMessage, {}, function (err, data) { |
@@ -122,18 +138,23 @@ var writeMessage = { | ||
122 | 138 | rl.question(message, onAnswer); |
123 | 139 | } |
124 | 140 | } |
125 | - rl.question(message, onAnswer); | |
141 | + | |
126 | 142 | } |
127 | 143 | } |
128 | 144 | |
129 | -// User streamによるタイムライン受信を開始 | |
130 | -function startUserStream() { | |
145 | +// ntwitter.Twitterクラスのインスタンスを生成して処理を開始する | |
146 | +auth.getClient(function (err, twit) { | |
147 | + twitter = twit; | |
148 | + | |
149 | + // タイムライン最新20件を取得する | |
131 | 150 | twitter.getHomeTimeline({}, function (err, data) { |
132 | 151 | if (err) { |
133 | 152 | throw err; |
134 | 153 | } |
135 | 154 | tweetWriter.write(data.reverse()); |
136 | 155 | }); |
156 | + | |
157 | + // User streamを使ったタイムライン受信を開始する | |
137 | 158 | twitter.stream('user', {}, function (stream) { |
138 | 159 | stream.on('data', function (data) { |
139 | 160 | tweetWriter.write(data); |
@@ -142,14 +163,6 @@ function startUserStream() { | ||
142 | 163 | console.log(err); |
143 | 164 | }); |
144 | 165 | }); |
145 | -}; | |
146 | - | |
147 | -// ntwitter.Twitterクラスのインスタンスを生成する | |
148 | -auth.authenticate(function (err, twit) { | |
149 | - twitter = twit; | |
150 | - | |
151 | - // User streamを使ったタイムライン受信の開始 | |
152 | - startUserStream(); | |
153 | 166 | |
154 | 167 | // タイムラインモードを開始 |
155 | 168 | mode.start(timeline); |
@@ -1,9 +1,12 @@ | ||
1 | -// tweetの書き込みを行うモジュール | |
1 | +var util = require('util'); | |
2 | 2 | |
3 | 3 | var buffer = []; |
4 | -var util = require('util'); | |
5 | 4 | var writable = false; |
6 | 5 | |
6 | +/* | |
7 | + * tweetをコンソールに出力する | |
8 | + * @param {Object|Array} tweet 出力するtweet、もしくはその配列 | |
9 | + */ | |
7 | 10 | exports.write = function (tweet) { |
8 | 11 | if (util.isArray(tweet)) { |
9 | 12 | tweet.forEach(_write); |
@@ -12,6 +15,25 @@ exports.write = function (tweet) { | ||
12 | 15 | } |
13 | 16 | }; |
14 | 17 | |
18 | +/* | |
19 | + * tweetのコンソールへの出力を再開する | |
20 | + */ | |
21 | +exports.resume = function () { | |
22 | + buffer.forEach(function (data) { | |
23 | + process.stdout.write(data); | |
24 | + }); | |
25 | + buffer = []; | |
26 | + writable = true; | |
27 | +}, | |
28 | + | |
29 | +/* | |
30 | + * tweetのコンソールへの出力を一時停止する | |
31 | + */ | |
32 | +exports.pause = function () { | |
33 | + writable = false; | |
34 | +} | |
35 | + | |
36 | +// tweetを整形して出力する | |
15 | 37 | function _write(tweet) { |
16 | 38 | if (tweet.user === undefined) { |
17 | 39 | return; |
@@ -24,6 +46,8 @@ function _write(tweet) { | ||
24 | 46 | _push('\n'); |
25 | 47 | } |
26 | 48 | |
49 | +// コンソールへの書き出しが許可されていれば文字列を出力し | |
50 | +// 許可されていなければバッファに格納する | |
27 | 51 | function _push(data) { |
28 | 52 | if (writable) { |
29 | 53 | process.stdout.write(data); |
@@ -31,15 +55,3 @@ function _push(data) { | ||
31 | 55 | buffer.push(data); |
32 | 56 | } |
33 | 57 | }; |
34 | - | |
35 | -exports.resume = function () { | |
36 | - buffer.forEach(function (data) { | |
37 | - process.stdout.write(data); | |
38 | - }); | |
39 | - buffer = []; | |
40 | - writable = true; | |
41 | -}, | |
42 | - | |
43 | -exports.pause = function () { | |
44 | - writable = false; | |
45 | -} |