teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

7

2021/11/23 07:51

投稿

退会済みユーザー
answer CHANGED
@@ -82,7 +82,7 @@
82
82
 
83
83
  下記のコードでは、putRetweet関数や、putFavorite関数を直接実行してしまった場合、引数tweetが空かどうかを判定し、空の場合はreturnすることでエラー停止を回避するように修正しました。
84
84
   
85
- このプログラムは基本的に、**main()だけを実行する**ようにしてくい。(main()以外を実行しても正常に動作しません)
85
+ このプログラムは(一度authorize()関数を実行してTwitter認証が完了していれば)基本的に、**main()を実行する**だけでよです。(main()以外を実行しても正常に動作しません)
86
86
   
87
87
  【回答コード(全体)】
88
88
  ```js

6

2021/11/23 07:51

投稿

退会済みユーザー
answer CHANGED
@@ -58,6 +58,7 @@
58
58
 
59
59
  下記コードについて、エラーが発生しても停止せずエラー内容を表示するように修正しました。
60
60
  (try ~ catch文で囲む)
61
+  
61
62
  ---
62
63
   
63
64
   
@@ -79,8 +80,9 @@
79
80
  元のコードで、putRetweet関数や、putFavorite関数を直接実行すると、引数tweetが空っぽ(undefined)のため、
80
81
  「undefined からプロパティ「id_str」を読み取れません。」というエラーが発生します。
81
82
 
82
- 下記のコードでは、putRetweet関数や、putFavorite関数を実行したときに、引数tweetが空かどうかを判定し、空の場合はreturnすることでエラー停止を回避するように修正しました。
83
+ 下記のコードでは、putRetweet関数や、putFavorite関数を直接実行してしまっ場合、引数tweetが空かどうかを判定し、空の場合はreturnすることでエラー停止を回避するように修正しました。
83
84
   
85
+ このプログラムは、基本的に、**main()だけを実行する**ようにしてください。(main()以外を実行しても正常に動作しません)
84
86
   
85
87
  【回答コード(全体)】
86
88
  ```js

5

追加

2021/11/22 14:37

投稿

退会済みユーザー
answer CHANGED
@@ -49,6 +49,40 @@
49
49
 
50
50
  なお、**一定時間内に大量にキーワード検索や、RT・Fav(「いいね」)を実行した場合、API制限がかかってしばらく検索・RT・Favができなく場合があるので、実行する際は注意してください。**
51
51
 
52
+ # 追記2
53
+
54
+ > 該当部分に、コードを追加したところ、新たにエラーが出てしまったので、
55
+
56
+ すでにリツイート済みのツイートに重ねてリツイートしようとしたり、
57
+ すでにいいねが済んでいるツイートに、重ねて「いいね」をしようとしたため、エラーで停止しています。
58
+
59
+ 下記コードについて、エラーが発生しても停止せずエラー内容を表示するように修正しました。
60
+ (try ~ catch文で囲む)
61
+ ---
62
+  
63
+  
64
+
65
+ > ① 検索ワードをスプレッドシートから取得する
66
+ > ② 検索ワードをTwitterで検索する(たくさん取れてしまうので「直近10分間」の検索を10分毎に行う)
67
+ > ③ ツイートに いいね or RT をする
68
+ > ④ 他に検索ワードがあれば②に戻る
69
+ > の順番通りにコードを並べる必要があるのかと思い
70
+
71
+ 実際のところ、順番通りに並べる必要はありません。
72
+ 呼び出し元より後ろにある関数であっても、**自動的に探して認識してくれます。**
73
+ 今回のエラーの原因は、上述のようにリツイート済みのツイートに重ねてリツイートしようとしたためです。
74
+
75
+ さらに、putRetweet関数や、putFavorite関数を直接実行されようとしたのではないでしょうか。
76
+
77
+ putRetweet関数や、putFavorite関数は、main()関数から呼び出される専用の関数です。
78
+
79
+ 元のコードで、putRetweet関数や、putFavorite関数を直接実行すると、引数tweetが空っぽ(undefined)のため、
80
+ 「undefined からプロパティ「id_str」を読み取れません。」というエラーが発生します。
81
+
82
+ 下記のコードでは、putRetweet関数や、putFavorite関数を実行したときに、引数tweetが空かどうかを判定し、空の場合はreturnすることでエラー停止を回避するように修正しました。
83
+  
84
+  
85
+ 【回答コード(全体)】
52
86
  ```js
53
87
  //認証用インスタンスの生成
54
88
  var twitter = TwitterWebService.getInstance(
@@ -180,16 +214,40 @@
180
214
  // いいね を付ける
181
215
  // 【参考】 https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-favorites-create
182
216
  function putFavorite(tweet) {
217
+ // tweetが空っぽ(undefined)の場合はreturn
218
+ if (typeof tweet === "undefined") return;
183
219
  var service = twitter.getService();
184
220
  var options = { method: 'post' };
221
+ // エラーが発生したら、catchのブロックにジャンプ。
222
+ try {
185
- service.fetch('https://api.twitter.com/1.1/favorites/create.json?id=' + tweet.id_str, options);
223
+ service.fetch('https://api.twitter.com/1.1/favorites/create.json?id=' + tweet.id_str, options);
224
+ } catch(e) {
225
+ // メッセージに「"code":139」という文字列が含まれている場合は、内容を表示
226
+ if (e && e.message.indexOf('{"code":139') > -1) {
227
+ Logger.log("このツイートにはすでに「いいね」を押しています。\n[id] "+tweet.id_str +" [username]" + tweet.user.name + "\n[tweet]「"+ tweet.text.slice(0, 40) + "...」");
228
+ } else {
229
+ Logger.log("エラー:" + e.message)
230
+ }
231
+ }
186
232
  }
187
233
 
188
234
  // RT を付ける
189
235
  // 【参考】 https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-retweet-id
190
236
  function putRetweet(tweet) {
237
+ // tweetが空っぽ(undefined)の場合はreturn
238
+ if (typeof tweet === "undefined") return;
191
239
  var service = twitter.getService();
192
240
  var options = { method: 'post' };
241
+ // エラーが発生したら、catchのブロックにジャンプ。
242
+ try {
193
- service.fetch('https://api.twitter.com/1.1/statuses/retweet/' + tweet.id_str +'.json', options);
243
+ service.fetch('https://api.twitter.com/1.1/statuses/retweet/' + tweet.id_str +'.json', options);
244
+ } catch(e) {
245
+ // メッセージに「"code":327」という文字列が含まれている場合は、内容を表示
246
+ if (e && e.message.indexOf('{"code":327') > -1) {
247
+ Logger.log("このツイートはすでにリツイート済みです。\n[id] "+tweet.id_str +" [username]" + tweet.user.name + "\n[tweet]「"+ tweet.text.slice(0, 40) + "...」");
248
+ } else {
249
+ Logger.log("エラー:" + e.message)
250
+ }
251
+ }
194
252
  }
195
253
  ```

4

2021/11/22 14:34

投稿

退会済みユーザー
answer CHANGED
@@ -45,7 +45,7 @@
45
45
 
46
46
  下記を保存の上、シート1のB列を「RT」、C列を空欄、D列を10等にして実行すると、
47
47
  検索ワードを含むツイートが自動でRTされ、C列は最新のlastTweetIdに更新されると思います。
48
- (D列が空欄だとなにも実行されません)
48
+ ※実行時にシート1のD列にも数字を入れる必要あります。D列が空欄だとRTやいいねが実行されません)
49
49
 
50
50
  なお、**一定時間内に大量にキーワード検索や、RT・Fav(「いいね」)を実行した場合、API制限がかかってしばらく検索・RT・Favができなく場合があるので、実行する際は注意してください。**
51
51
 

3

2021/11/21 17:38

投稿

退会済みユーザー
answer CHANGED
@@ -40,7 +40,7 @@
40
40
  とのことですが、これはメッセージの通り、putRetweetという関数がどこにも定義されていないのにputRetweetを呼び出そうとしたからです。
41
41
 
42
42
  下記のように、putRetweetやputFavoritesを実装する必要があります。
43
- (下記ースコードの「以下追加」以降の部分)
43
+ (下記ースコードの「以下追加」以降の部分)
44
44
  (前の御質問のコメント記載のソースを参考にして修正)
45
45
 
46
46
  下記を保存の上、シート1のB列を「RT」、C列を空欄、D列を10等にして実行すると、

2

追記

2021/11/21 17:34

投稿

退会済みユーザー
answer CHANGED
@@ -25,4 +25,171 @@
25
25
  一定時間経過しないと、APIでは当該ツイート(直近で取得したtweetIdより後のツイート)が取得できないことがあります。
26
26
 
27
27
  (なお、上記の画像の場合「Twitter」という単語を含むツイートは世界中で常時つぶやかれているため、
28
- 10秒間隔で実行しても、シート1上のlastTweetIdは実行する度更新されます)
28
+ 10秒間隔で実行しても、シート1上のlastTweetIdは実行する度更新されます)
29
+
30
+ ----
31
+ # 追記(コメントより)
32
+
33
+ > 20:39:36 お知らせ 実行開始
34
+ > 20:39:37 エラー
35
+ > ReferenceError: 「putRetweet」が定義されていません。
36
+ > main @ コード.gs:94
37
+ >
38
+ > というエラーが出てしまいました。
39
+
40
+ とのことですが、これはメッセージの通り、putRetweetという関数がどこにも定義されていないのにputRetweetを呼び出そうとしたからです。
41
+
42
+ 下記のように、putRetweetやputFavoritesを実装する必要があります。
43
+ (下記シースコードの「以下追加」以降の部分)
44
+ (前の御質問のコメント記載のソースを参考にして修正)
45
+
46
+ 下記を保存の上、シート1のB列を「RT」、C列を空欄、D列を10等にして実行すると、
47
+ 検索ワードを含むツイートが自動でRTされ、C列は最新のlastTweetIdに更新されると思います。
48
+ (D列が空欄だとなにも実行されません)
49
+
50
+ なお、**一定時間内に大量にキーワード検索や、RT・Fav(「いいね」)を実行した場合、API制限がかかってしばらく検索・RT・Favができなく場合があるので、実行する際は注意してください。**
51
+
52
+ ```js
53
+ //認証用インスタンスの生成
54
+ var twitter = TwitterWebService.getInstance(
55
+ '         ',//API Key
56
+ '         '//API secret key
57
+ );
58
+
59
+ // 認証
60
+ function authorize() {
61
+ twitter.authorize();
62
+ }
63
+
64
+ // 認証解除
65
+ function reset() {
66
+ twitter.reset();
67
+ }
68
+
69
+ // 認証後のコールバック
70
+ function authCallback(request) {
71
+ return twitter.authCallback(request);
72
+ }
73
+
74
+ // セルを取得
75
+ var sheetData = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート1"); // 「シート1」はシート名
76
+
77
+ /**
78
+ いいね or RT 機能
79
+ ① 検索ワードをスプレッドシートから取得する
80
+ ② 検索ワードをTwitterで検索する(たくさん取れてしまうので「直近10分間」の検索を10分毎に行う)
81
+ ③ ツイートに いいね or RT をする
82
+ ④ 他に検索ワードがあれば②に戻る
83
+ */
84
+ // ツイートを検索する
85
+ // 【参考】 https://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets
86
+ function findTweets (searchWord, lastTweetId) {
87
+ var service = twitter.getService();
88
+ var query = {
89
+ q: searchWord, // 検索ワード
90
+ lang: 'ja', // 日本語検索
91
+ locale: 'ja', // 日本限定で検索
92
+ result_type: 'recent', // 直近のツイートを検索
93
+ since_id: lastTweetId // これ以前のツイートは見ない
94
+ }
95
+ // 検索の内容を queryStr にまとめていく
96
+ var queryStr = '';
97
+ for (var key in query) {
98
+ // URLに日本語や記号を付けると上手く検索できないことがあるので#も変換する encodeURIComponent をする
99
+ queryStr += key + '=' + encodeURIComponent(query[key]) + '&'
100
+ }
101
+ // &が余計に付いているので削除しておく
102
+ var queryStr = queryStr.slice(0, -1);
103
+
104
+ var response = service.fetch('https://api.twitter.com/1.1/search/tweets.json?' + queryStr);
105
+ var result = JSON.parse(response)
106
+ return result.statuses
107
+ }
108
+
109
+ function main () {
110
+ // ① 検索ワードをスプレッドシートから取得する
111
+ var searchWords = pickUpSearchWords();
112
+
113
+ // searchWordsの中身は
114
+ // [ [ '投稿内容', 'いいね or RT', '最終TweetId', '実行回数'] , [ '投稿内容', 'いいね or RT', '最終TweetId', '実行回数'],....,]
115
+ // という形式になっているので1つずつ見ていく
116
+ for (var i = 0, il = searchWords.length; i < il; i++ ) {
117
+ var searchWord = searchWords[i][0];
118
+ var type = searchWords[i][1];
119
+ var lastTweetId = searchWords[i][2];
120
+
121
+ // !!!!!! 追加 !!!!!!!
122
+ var limit = searchWords[i][3];
123
+
124
+ // ② Twitterで検索する
125
+ var tweetList = findTweets(searchWord, lastTweetId);
126
+
127
+ var count = 0
128
+ // ③ 複数件ツイートを取得されるので for を使って1つずつツイートを取り出し いいね or RT をする
129
+ for (var j = 0, jl = tweetList.length; j < jl; j++ ) {
130
+ var tweet = tweetList[j];
131
+ if (tweet.id_str > lastTweetId) {
132
+ lastTweetId = tweet.id_str;
133
+ }
134
+
135
+ // !!!!!! 追加 !!!!!!!
136
+ if (count == limit) {
137
+ // lastTweetIdを出来るだけ新しくしたい場合は continue;
138
+ // 次回以降の実行で続きのツイートを使いたい場合は break;
139
+ break;
140
+ }
141
+ count++;
142
+
143
+ if (type == 'いいね') {
144
+ putFavorite (tweet);
145
+ } else if (type == 'RT') {
146
+ putRetweet (tweet);
147
+ }
148
+ }
149
+
150
+ // 最新のツイートIDを保存して重複処理をしないようにする
151
+ var titleRow = 1; // 『検索ワード』とか書いている部分の行数
152
+ var lastTweetIdCol = 3; // 『最終TweetId』の列までなので3列目まで
153
+ var updateCell = sheetData.getRange(i + 1 + titleRow, lastTweetIdCol, 1, 1); // i = 0 の時1行目なので+1してる
154
+ updateCell.setValue(lastTweetId);
155
+ }
156
+ }
157
+
158
+ // 検索ワードをスプレッドシートから取得する
159
+ function pickUpSearchWords () {
160
+ var titleRow = 1; // 『検索ワード』とか書いている部分の行数
161
+ var startRow = 1 + titleRow; // 1行目は『検索ワード』とか書いているので2行目から
162
+ var startCol = 1;
163
+ var endRow = sheetData.getLastRow() - titleRow; // 最後の行まで(2行目から始まっているので-1している)
164
+
165
+ // !!!!!! 変更 !!!!!!!
166
+ var endCol = 4; // 『実行回数』の列までなので4列目まで
167
+
168
+ // 一括で取得する
169
+ var cells = sheetData.getRange(startRow, startCol, endRow, endCol).getValues();
170
+
171
+ // cellsの中身は
172
+ // [ [ '投稿内容', 'いいね or RT', '最終TweetId', '実行回数'] , [ '投稿内容', 'いいね or RT', '最終TweetId', '実行回数'] ,....,]
173
+ // という形式になる
174
+
175
+ return cells;
176
+ }
177
+
178
+ // ------------------------------以下追加------------------------------
179
+
180
+ // いいね を付ける
181
+ // 【参考】 https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-favorites-create
182
+ function putFavorite(tweet) {
183
+ var service = twitter.getService();
184
+ var options = { method: 'post' };
185
+ service.fetch('https://api.twitter.com/1.1/favorites/create.json?id=' + tweet.id_str, options);
186
+ }
187
+
188
+ // RT を付ける
189
+ // 【参考】 https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-retweet-id
190
+ function putRetweet(tweet) {
191
+ var service = twitter.getService();
192
+ var options = { method: 'post' };
193
+ service.fetch('https://api.twitter.com/1.1/statuses/retweet/' + tweet.id_str +'.json', options);
194
+ }
195
+ ```

1

2021/11/21 17:33

投稿

退会済みユーザー
answer CHANGED
@@ -16,7 +16,7 @@
16
16
 
17
17
  (その背景として、シート1上の検索ワードが、それほど頻繁につぶやかれている単語ではない、ということが考えられます)
18
18
 
19
- 初回、lastTweetID(C列)を空欄にしてスクリプトを実行すると、
19
+ 初回、lastTweetID(C列)を空欄または0にしてスクリプトを実行すると、
20
20
  lastTweetIdは取得したツイートの最大IDに更新されます。
21
21
 
22
22
  ただし、Twitter APIのデータ反映にはタイムラグがあります。