回答編集履歴
7
test
CHANGED
@@ -166,7 +166,7 @@
|
|
166
166
|
|
167
167
|
|
168
168
|
|
169
|
-
このプログラムは
|
169
|
+
このプログラムは(一度authorize()関数を実行してTwitter認証が完了していれば)基本的に、**main()を実行する**だけでよいです。(main()以外を実行しても正常に動作しません)
|
170
170
|
|
171
171
|
|
172
172
|
|
6
test
CHANGED
@@ -118,6 +118,8 @@
|
|
118
118
|
|
119
119
|
(try ~ catch文で囲む)
|
120
120
|
|
121
|
+
|
122
|
+
|
121
123
|
---
|
122
124
|
|
123
125
|
|
@@ -160,9 +162,11 @@
|
|
160
162
|
|
161
163
|
|
162
164
|
|
163
|
-
下記のコードでは、putRetweet関数や、putFavorite関数を実行した
|
165
|
+
下記のコードでは、putRetweet関数や、putFavorite関数を直接実行してしまった場合、引数tweetが空かどうかを判定し、空の場合はreturnすることでエラー停止を回避するように修正しました。
|
166
|
+
|
167
|
+
|
168
|
+
|
164
|
-
|
169
|
+
このプログラムは、基本的に、**main()だけを実行する**ようにしてください。(main()以外を実行しても正常に動作しません)
|
165
|
-
|
166
170
|
|
167
171
|
|
168
172
|
|
5
追加
test
CHANGED
@@ -100,6 +100,74 @@
|
|
100
100
|
|
101
101
|
|
102
102
|
|
103
|
+
# 追記2
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
> 該当部分に、コードを追加したところ、新たにエラーが出てしまったので、
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
すでにリツイート済みのツイートに重ねてリツイートしようとしたり、
|
112
|
+
|
113
|
+
すでにいいねが済んでいるツイートに、重ねて「いいね」をしようとしたため、エラーで停止しています。
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
下記コードについて、エラーが発生しても停止せずエラー内容を表示するように修正しました。
|
118
|
+
|
119
|
+
(try ~ catch文で囲む)
|
120
|
+
|
121
|
+
---
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
|
128
|
+
|
129
|
+
> ① 検索ワードをスプレッドシートから取得する
|
130
|
+
|
131
|
+
> ② 検索ワードをTwitterで検索する(たくさん取れてしまうので「直近10分間」の検索を10分毎に行う)
|
132
|
+
|
133
|
+
> ③ ツイートに いいね or RT をする
|
134
|
+
|
135
|
+
> ④ 他に検索ワードがあれば②に戻る
|
136
|
+
|
137
|
+
> の順番通りにコードを並べる必要があるのかと思い
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
実際のところ、順番通りに並べる必要はありません。
|
142
|
+
|
143
|
+
呼び出し元より後ろにある関数であっても、**自動的に探して認識してくれます。**
|
144
|
+
|
145
|
+
今回のエラーの原因は、上述のようにリツイート済みのツイートに重ねてリツイートしようとしたためです。
|
146
|
+
|
147
|
+
|
148
|
+
|
149
|
+
さらに、putRetweet関数や、putFavorite関数を直接実行されようとしたのではないでしょうか。
|
150
|
+
|
151
|
+
|
152
|
+
|
153
|
+
putRetweet関数や、putFavorite関数は、main()関数から呼び出される専用の関数です。
|
154
|
+
|
155
|
+
|
156
|
+
|
157
|
+
元のコードで、putRetweet関数や、putFavorite関数を直接実行すると、引数tweetが空っぽ(undefined)のため、
|
158
|
+
|
159
|
+
「undefined からプロパティ「id_str」を読み取れません。」というエラーが発生します。
|
160
|
+
|
161
|
+
|
162
|
+
|
163
|
+
下記のコードでは、putRetweet関数や、putFavorite関数を実行したときに、引数tweetが空かどうかを判定し、空の場合はreturnすることでエラー停止を回避するように修正しました。
|
164
|
+
|
165
|
+
|
166
|
+
|
167
|
+
|
168
|
+
|
169
|
+
【回答コード(全体)】
|
170
|
+
|
103
171
|
```js
|
104
172
|
|
105
173
|
//認証用インスタンスの生成
|
@@ -362,11 +430,35 @@
|
|
362
430
|
|
363
431
|
function putFavorite(tweet) {
|
364
432
|
|
433
|
+
// tweetが空っぽ(undefined)の場合はreturn
|
434
|
+
|
435
|
+
if (typeof tweet === "undefined") return;
|
436
|
+
|
365
437
|
var service = twitter.getService();
|
366
438
|
|
367
439
|
var options = { method: 'post' };
|
368
440
|
|
441
|
+
// エラーが発生したら、catchのブロックにジャンプ。
|
442
|
+
|
443
|
+
try {
|
444
|
+
|
369
|
-
service.fetch('https://api.twitter.com/1.1/favorites/create.json?id=' + tweet.id_str, options);
|
445
|
+
service.fetch('https://api.twitter.com/1.1/favorites/create.json?id=' + tweet.id_str, options);
|
446
|
+
|
447
|
+
} catch(e) {
|
448
|
+
|
449
|
+
// メッセージに「"code":139」という文字列が含まれている場合は、内容を表示
|
450
|
+
|
451
|
+
if (e && e.message.indexOf('{"code":139') > -1) {
|
452
|
+
|
453
|
+
Logger.log("このツイートにはすでに「いいね」を押しています。\n[id] "+tweet.id_str +" [username]" + tweet.user.name + "\n[tweet]「"+ tweet.text.slice(0, 40) + "...」");
|
454
|
+
|
455
|
+
} else {
|
456
|
+
|
457
|
+
Logger.log("エラー:" + e.message)
|
458
|
+
|
459
|
+
}
|
460
|
+
|
461
|
+
}
|
370
462
|
|
371
463
|
}
|
372
464
|
|
@@ -378,11 +470,35 @@
|
|
378
470
|
|
379
471
|
function putRetweet(tweet) {
|
380
472
|
|
473
|
+
// tweetが空っぽ(undefined)の場合はreturn
|
474
|
+
|
475
|
+
if (typeof tweet === "undefined") return;
|
476
|
+
|
381
477
|
var service = twitter.getService();
|
382
478
|
|
383
479
|
var options = { method: 'post' };
|
384
480
|
|
481
|
+
// エラーが発生したら、catchのブロックにジャンプ。
|
482
|
+
|
483
|
+
try {
|
484
|
+
|
385
|
-
service.fetch('https://api.twitter.com/1.1/statuses/retweet/' + tweet.id_str +'.json', options);
|
485
|
+
service.fetch('https://api.twitter.com/1.1/statuses/retweet/' + tweet.id_str +'.json', options);
|
486
|
+
|
487
|
+
} catch(e) {
|
488
|
+
|
489
|
+
// メッセージに「"code":327」という文字列が含まれている場合は、内容を表示
|
490
|
+
|
491
|
+
if (e && e.message.indexOf('{"code":327') > -1) {
|
492
|
+
|
493
|
+
Logger.log("このツイートはすでにリツイート済みです。\n[id] "+tweet.id_str +" [username]" + tweet.user.name + "\n[tweet]「"+ tweet.text.slice(0, 40) + "...」");
|
494
|
+
|
495
|
+
} else {
|
496
|
+
|
497
|
+
Logger.log("エラー:" + e.message)
|
498
|
+
|
499
|
+
}
|
500
|
+
|
501
|
+
}
|
386
502
|
|
387
503
|
}
|
388
504
|
|
4
test
CHANGED
@@ -92,7 +92,7 @@
|
|
92
92
|
|
93
93
|
検索ワードを含むツイートが自動でRTされ、C列は最新のlastTweetIdに更新されると思います。
|
94
94
|
|
95
|
-
(D列が空欄だと
|
95
|
+
(※実行時にシート1のD列にも数字を入れる必要があります。D列が空欄だとRTやいいねが実行されません)
|
96
96
|
|
97
97
|
|
98
98
|
|
3
test
CHANGED
@@ -82,7 +82,7 @@
|
|
82
82
|
|
83
83
|
下記のように、putRetweetやputFavoritesを実装する必要があります。
|
84
84
|
|
85
|
-
(下記
|
85
|
+
(下記ソースコードの「以下追加」以降の部分)
|
86
86
|
|
87
87
|
(前の御質問のコメント記載のソースを参考にして修正)
|
88
88
|
|
2
追記
test
CHANGED
@@ -53,3 +53,337 @@
|
|
53
53
|
(なお、上記の画像の場合「Twitter」という単語を含むツイートは世界中で常時つぶやかれているため、
|
54
54
|
|
55
55
|
10秒間隔で実行しても、シート1上のlastTweetIdは実行する度更新されます)
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
----
|
60
|
+
|
61
|
+
# 追記(コメントより)
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
> 20:39:36 お知らせ 実行開始
|
66
|
+
|
67
|
+
> 20:39:37 エラー
|
68
|
+
|
69
|
+
> ReferenceError: 「putRetweet」が定義されていません。
|
70
|
+
|
71
|
+
> main @ コード.gs:94
|
72
|
+
|
73
|
+
>
|
74
|
+
|
75
|
+
> というエラーが出てしまいました。
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
とのことですが、これはメッセージの通り、putRetweetという関数がどこにも定義されていないのにputRetweetを呼び出そうとしたからです。
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
下記のように、putRetweetやputFavoritesを実装する必要があります。
|
84
|
+
|
85
|
+
(下記シースコードの「以下追加」以降の部分)
|
86
|
+
|
87
|
+
(前の御質問のコメント記載のソースを参考にして修正)
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
下記を保存の上、シート1のB列を「RT」、C列を空欄、D列を10等にして実行すると、
|
92
|
+
|
93
|
+
検索ワードを含むツイートが自動でRTされ、C列は最新のlastTweetIdに更新されると思います。
|
94
|
+
|
95
|
+
(D列が空欄だとなにも実行されません)
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
なお、**一定時間内に大量にキーワード検索や、RT・Fav(「いいね」)を実行した場合、API制限がかかってしばらく検索・RT・Favができなく場合があるので、実行する際は注意してください。**
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
```js
|
104
|
+
|
105
|
+
//認証用インスタンスの生成
|
106
|
+
|
107
|
+
var twitter = TwitterWebService.getInstance(
|
108
|
+
|
109
|
+
' ',//API Key
|
110
|
+
|
111
|
+
' '//API secret key
|
112
|
+
|
113
|
+
);
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
// 認証
|
118
|
+
|
119
|
+
function authorize() {
|
120
|
+
|
121
|
+
twitter.authorize();
|
122
|
+
|
123
|
+
}
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
// 認証解除
|
128
|
+
|
129
|
+
function reset() {
|
130
|
+
|
131
|
+
twitter.reset();
|
132
|
+
|
133
|
+
}
|
134
|
+
|
135
|
+
|
136
|
+
|
137
|
+
// 認証後のコールバック
|
138
|
+
|
139
|
+
function authCallback(request) {
|
140
|
+
|
141
|
+
return twitter.authCallback(request);
|
142
|
+
|
143
|
+
}
|
144
|
+
|
145
|
+
|
146
|
+
|
147
|
+
// セルを取得
|
148
|
+
|
149
|
+
var sheetData = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート1"); // 「シート1」はシート名
|
150
|
+
|
151
|
+
|
152
|
+
|
153
|
+
/**
|
154
|
+
|
155
|
+
いいね or RT 機能
|
156
|
+
|
157
|
+
① 検索ワードをスプレッドシートから取得する
|
158
|
+
|
159
|
+
② 検索ワードをTwitterで検索する(たくさん取れてしまうので「直近10分間」の検索を10分毎に行う)
|
160
|
+
|
161
|
+
③ ツイートに いいね or RT をする
|
162
|
+
|
163
|
+
④ 他に検索ワードがあれば②に戻る
|
164
|
+
|
165
|
+
*/
|
166
|
+
|
167
|
+
// ツイートを検索する
|
168
|
+
|
169
|
+
// 【参考】 https://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets
|
170
|
+
|
171
|
+
function findTweets (searchWord, lastTweetId) {
|
172
|
+
|
173
|
+
var service = twitter.getService();
|
174
|
+
|
175
|
+
var query = {
|
176
|
+
|
177
|
+
q: searchWord, // 検索ワード
|
178
|
+
|
179
|
+
lang: 'ja', // 日本語検索
|
180
|
+
|
181
|
+
locale: 'ja', // 日本限定で検索
|
182
|
+
|
183
|
+
result_type: 'recent', // 直近のツイートを検索
|
184
|
+
|
185
|
+
since_id: lastTweetId // これ以前のツイートは見ない
|
186
|
+
|
187
|
+
}
|
188
|
+
|
189
|
+
// 検索の内容を queryStr にまとめていく
|
190
|
+
|
191
|
+
var queryStr = '';
|
192
|
+
|
193
|
+
for (var key in query) {
|
194
|
+
|
195
|
+
// URLに日本語や記号を付けると上手く検索できないことがあるので#も変換する encodeURIComponent をする
|
196
|
+
|
197
|
+
queryStr += key + '=' + encodeURIComponent(query[key]) + '&'
|
198
|
+
|
199
|
+
}
|
200
|
+
|
201
|
+
// &が余計に付いているので削除しておく
|
202
|
+
|
203
|
+
var queryStr = queryStr.slice(0, -1);
|
204
|
+
|
205
|
+
|
206
|
+
|
207
|
+
var response = service.fetch('https://api.twitter.com/1.1/search/tweets.json?' + queryStr);
|
208
|
+
|
209
|
+
var result = JSON.parse(response)
|
210
|
+
|
211
|
+
return result.statuses
|
212
|
+
|
213
|
+
}
|
214
|
+
|
215
|
+
|
216
|
+
|
217
|
+
function main () {
|
218
|
+
|
219
|
+
// ① 検索ワードをスプレッドシートから取得する
|
220
|
+
|
221
|
+
var searchWords = pickUpSearchWords();
|
222
|
+
|
223
|
+
|
224
|
+
|
225
|
+
// searchWordsの中身は
|
226
|
+
|
227
|
+
// [ [ '投稿内容', 'いいね or RT', '最終TweetId', '実行回数'] , [ '投稿内容', 'いいね or RT', '最終TweetId', '実行回数'],....,]
|
228
|
+
|
229
|
+
// という形式になっているので1つずつ見ていく
|
230
|
+
|
231
|
+
for (var i = 0, il = searchWords.length; i < il; i++ ) {
|
232
|
+
|
233
|
+
var searchWord = searchWords[i][0];
|
234
|
+
|
235
|
+
var type = searchWords[i][1];
|
236
|
+
|
237
|
+
var lastTweetId = searchWords[i][2];
|
238
|
+
|
239
|
+
|
240
|
+
|
241
|
+
// !!!!!! 追加 !!!!!!!
|
242
|
+
|
243
|
+
var limit = searchWords[i][3];
|
244
|
+
|
245
|
+
|
246
|
+
|
247
|
+
// ② Twitterで検索する
|
248
|
+
|
249
|
+
var tweetList = findTweets(searchWord, lastTweetId);
|
250
|
+
|
251
|
+
|
252
|
+
|
253
|
+
var count = 0
|
254
|
+
|
255
|
+
// ③ 複数件ツイートを取得されるので for を使って1つずつツイートを取り出し いいね or RT をする
|
256
|
+
|
257
|
+
for (var j = 0, jl = tweetList.length; j < jl; j++ ) {
|
258
|
+
|
259
|
+
var tweet = tweetList[j];
|
260
|
+
|
261
|
+
if (tweet.id_str > lastTweetId) {
|
262
|
+
|
263
|
+
lastTweetId = tweet.id_str;
|
264
|
+
|
265
|
+
}
|
266
|
+
|
267
|
+
|
268
|
+
|
269
|
+
// !!!!!! 追加 !!!!!!!
|
270
|
+
|
271
|
+
if (count == limit) {
|
272
|
+
|
273
|
+
// lastTweetIdを出来るだけ新しくしたい場合は continue;
|
274
|
+
|
275
|
+
// 次回以降の実行で続きのツイートを使いたい場合は break;
|
276
|
+
|
277
|
+
break;
|
278
|
+
|
279
|
+
}
|
280
|
+
|
281
|
+
count++;
|
282
|
+
|
283
|
+
|
284
|
+
|
285
|
+
if (type == 'いいね') {
|
286
|
+
|
287
|
+
putFavorite (tweet);
|
288
|
+
|
289
|
+
} else if (type == 'RT') {
|
290
|
+
|
291
|
+
putRetweet (tweet);
|
292
|
+
|
293
|
+
}
|
294
|
+
|
295
|
+
}
|
296
|
+
|
297
|
+
|
298
|
+
|
299
|
+
// 最新のツイートIDを保存して重複処理をしないようにする
|
300
|
+
|
301
|
+
var titleRow = 1; // 『検索ワード』とか書いている部分の行数
|
302
|
+
|
303
|
+
var lastTweetIdCol = 3; // 『最終TweetId』の列までなので3列目まで
|
304
|
+
|
305
|
+
var updateCell = sheetData.getRange(i + 1 + titleRow, lastTweetIdCol, 1, 1); // i = 0 の時1行目なので+1してる
|
306
|
+
|
307
|
+
updateCell.setValue(lastTweetId);
|
308
|
+
|
309
|
+
}
|
310
|
+
|
311
|
+
}
|
312
|
+
|
313
|
+
|
314
|
+
|
315
|
+
// 検索ワードをスプレッドシートから取得する
|
316
|
+
|
317
|
+
function pickUpSearchWords () {
|
318
|
+
|
319
|
+
var titleRow = 1; // 『検索ワード』とか書いている部分の行数
|
320
|
+
|
321
|
+
var startRow = 1 + titleRow; // 1行目は『検索ワード』とか書いているので2行目から
|
322
|
+
|
323
|
+
var startCol = 1;
|
324
|
+
|
325
|
+
var endRow = sheetData.getLastRow() - titleRow; // 最後の行まで(2行目から始まっているので-1している)
|
326
|
+
|
327
|
+
|
328
|
+
|
329
|
+
// !!!!!! 変更 !!!!!!!
|
330
|
+
|
331
|
+
var endCol = 4; // 『実行回数』の列までなので4列目まで
|
332
|
+
|
333
|
+
|
334
|
+
|
335
|
+
// 一括で取得する
|
336
|
+
|
337
|
+
var cells = sheetData.getRange(startRow, startCol, endRow, endCol).getValues();
|
338
|
+
|
339
|
+
|
340
|
+
|
341
|
+
// cellsの中身は
|
342
|
+
|
343
|
+
// [ [ '投稿内容', 'いいね or RT', '最終TweetId', '実行回数'] , [ '投稿内容', 'いいね or RT', '最終TweetId', '実行回数'] ,....,]
|
344
|
+
|
345
|
+
// という形式になる
|
346
|
+
|
347
|
+
|
348
|
+
|
349
|
+
return cells;
|
350
|
+
|
351
|
+
}
|
352
|
+
|
353
|
+
|
354
|
+
|
355
|
+
// ------------------------------以下追加------------------------------
|
356
|
+
|
357
|
+
|
358
|
+
|
359
|
+
// いいね を付ける
|
360
|
+
|
361
|
+
// 【参考】 https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-favorites-create
|
362
|
+
|
363
|
+
function putFavorite(tweet) {
|
364
|
+
|
365
|
+
var service = twitter.getService();
|
366
|
+
|
367
|
+
var options = { method: 'post' };
|
368
|
+
|
369
|
+
service.fetch('https://api.twitter.com/1.1/favorites/create.json?id=' + tweet.id_str, options);
|
370
|
+
|
371
|
+
}
|
372
|
+
|
373
|
+
|
374
|
+
|
375
|
+
// RT を付ける
|
376
|
+
|
377
|
+
// 【参考】 https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-retweet-id
|
378
|
+
|
379
|
+
function putRetweet(tweet) {
|
380
|
+
|
381
|
+
var service = twitter.getService();
|
382
|
+
|
383
|
+
var options = { method: 'post' };
|
384
|
+
|
385
|
+
service.fetch('https://api.twitter.com/1.1/statuses/retweet/' + tweet.id_str +'.json', options);
|
386
|
+
|
387
|
+
}
|
388
|
+
|
389
|
+
```
|
1
test
CHANGED
@@ -34,7 +34,7 @@
|
|
34
34
|
|
35
35
|
|
36
36
|
|
37
|
-
初回、lastTweetID(C列)を空欄にしてスクリプトを実行すると、
|
37
|
+
初回、lastTweetID(C列)を空欄または0にしてスクリプトを実行すると、
|
38
38
|
|
39
39
|
lastTweetIdは取得したツイートの最大IDに更新されます。
|
40
40
|
|