@@ -2,23 +2,24 @@ require 'rss'
22require 'net/http'
33require 'json'
44
5+ PR_TIMES_FEED = 'https://prtimes.jp/companyrdf.php?company_id=38935' . freeze
6+ DOJO_NEWS_FEED = 'https://news.coderdojo.jp/feed/' . freeze
7+ TEST_NEWS_FEED = Rails . root . join ( 'spec' , 'fixtures' , 'sample_news.rss' ) . freeze
8+
59NEWS_YAML_PATH = 'db/news.yml' . freeze
6- NEWS_LOG_PATH = 'log/news.log' . freeze
10+ NEWS_LOGS_PATH = 'log/news.log' . freeze
11+ TASK_LOGGER = ActiveSupport ::BroadcastLogger . new (
12+ ActiveSupport ::Logger . new ( NEWS_LOGS_PATH ) ,
13+ ActiveSupport ::Logger . new ( STDOUT )
14+ )
715
816namespace :news do
917 desc "RSS フィードを取得し、#{ NEWS_YAML_PATH } に保存"
1018 task fetch : :environment do
1119 # ロガー設定(ファイル+コンソール出力)
12- console = ActiveSupport ::Logger . new ( STDOUT )
13- logger_file = ActiveSupport ::Logger . new ( NEWS_LOG_PATH )
14- logger = ActiveSupport ::BroadcastLogger . new ( logger_file , console )
15-
16- logger . info ( '==== START news:fetch ====' )
20+ TASK_LOGGER . info ( '==== START news:fetch ====' )
1721
1822 # 本番/開発環境では実フィード、それ以外(テスト環境など)ではテスト用フィード
19- DOJO_NEWS_FEED = 'https://news.coderdojo.jp/feed/'
20- PR_TIMES_FEED = 'https://prtimes.jp/companyrdf.php?company_id=38935'
21- TEST_NEWS_FEED = Rails . root . join ( 'spec' , 'fixtures' , 'sample_news.rss' )
2223 RSS_FEED_LIST = ( Rails . env . test? || Rails . env . staging? ) ?
2324 [ TEST_NEWS_FEED ] :
2425 [ DOJO_NEWS_FEED , PR_TIMES_FEED ]
@@ -96,31 +97,66 @@ namespace :news do
9697 f . write ( formatted_items . to_yaml )
9798 end
9899
99- logger . info "✅ Wrote #{ merged_items . size } items to #{ NEWS_YAML_PATH } (#{ created_items . size } new, #{ updated_items . size } updated)"
100- logger . info "==== END news:fetch ===="
101- logger . info ""
100+ TASK_LOGGER . info "✅ Wrote #{ merged_items . size } items to #{ NEWS_YAML_PATH } (#{ created_items . size } new, #{ updated_items . size } updated)"
101+ TASK_LOGGER . info "==== END news:fetch ===="
102+ TASK_LOGGER . info ""
102103 end
103104
104105 desc "news.yml をリセットし、すべてのフィードから全記事を取得"
105106 task 'fetch:reset' => :environment do
106107 # ロガー設定(ファイル+コンソール出力)
107- console = ActiveSupport ::Logger . new ( STDOUT )
108- logger_file = ActiveSupport ::Logger . new ( NEWS_LOG_PATH )
109- logger = ActiveSupport ::BroadcastLogger . new ( logger_file , console )
110-
111- logger . info ( '==== START news:fetch:reset ====' )
108+ TASK_LOGGER . info ( '==== START news:fetch:reset ====' )
112109
113110 # 1. news.yml を空にする
114111 File . write ( NEWS_YAML_PATH , [ ] . to_yaml )
115- logger . info ( "📄 news.yml をリセットしました" )
112+ TASK_LOGGER . info ( "📄 news.yml をリセットしました" )
116113
117114 # 2. WordPress REST API からすべての投稿を取得
118- dojo_news_items = fetch_all_wordpress_posts ( logger )
119- logger . info ( "📰 news.coderdojo.jp から #{ dojo_news_items . size } 件を取得" )
115+ dojo_news_items = [ ]
116+ page = 1
117+ per_page = 100
118+
119+ loop do
120+ uri = URI ( "https://news.coderdojo.jp/wp-json/wp/v2/posts" )
121+ uri . query = URI . encode_www_form ( page : page , per_page : per_page , status : 'publish' )
122+
123+ response = Net ::HTTP . get_response ( uri )
124+ break unless response . is_a? ( Net ::HTTPSuccess )
125+
126+ posts = JSON . parse ( response . body )
127+ break if posts . empty?
128+
129+ posts . each do |post |
130+ dojo_news_items << {
131+ 'url' => post [ 'link' ] ,
132+ 'title' => post [ 'title' ] [ 'rendered' ] ,
133+ 'published_at' => Time . parse ( post [ 'date_gmt' ] + ' UTC' ) . iso8601
134+ }
135+ end
136+
137+ TASK_LOGGER . info ( "📄 WordPress API: ページ #{ page } から #{ posts . size } 件取得" )
138+ page += 1
139+ end
140+ TASK_LOGGER . info ( "📰 news.coderdojo.jp から #{ dojo_news_items . size } 件を取得" )
120141
121142 # 3. PR TIMES RSS フィードからすべてのプレスリリースを取得
122- prtimes_items = fetch_prtimes_feed ( logger )
123- logger . info ( "📢 PR TIMES から #{ prtimes_items . size } 件を取得" )
143+ prtimes_items = [ ]
144+ feed = RSS ::Parser . parse ( 'https://prtimes.jp/companyrdf.php?company_id=38935' , false )
145+ feed . items . each do |item |
146+ published_at = if item . respond_to? ( :dc_date ) && item . dc_date
147+ item . dc_date . iso8601
148+ else
149+ raise "PR TIMES feed: dc:date not found for item: #{ item . link } "
150+ end
151+
152+ prtimes_items << {
153+ 'url' => item . link ,
154+ 'title' => item . title ,
155+ 'published_at' => published_at
156+ }
157+ end
158+ TASK_LOGGER . info ( "📢 PR TIMES RSS: #{ prtimes_items . size } 件取得" )
159+ TASK_LOGGER . info ( "📢 PR TIMES から #{ prtimes_items . size } 件を取得" )
124160
125161 # 4. すべてのアイテムをマージし、ID を付与
126162 all_items = ( dojo_news_items + prtimes_items ) . sort_by { |item |
@@ -133,7 +169,7 @@ namespace :news do
133169 end
134170
135171 # 最新順にソート
136- sorted_items = all_items . sort_by { |item |
172+ sorted_items = all_items . sort_by { |item |
137173 Time . parse ( item [ 'published_at' ] )
138174 } . reverse
139175
@@ -151,78 +187,15 @@ namespace :news do
151187 f . write ( formatted_items . to_yaml )
152188 end
153189
154- logger . info ( "✅ 合計 #{ sorted_items . size } 件を news.yml に保存しました" )
155- logger . info ( "📌 次は 'bundle exec rails news:upsert' でデータベースに反映してください" )
156- logger . info ( "==== END news:fetch:reset ====" )
190+ TASK_LOGGER . info ( "✅ 合計 #{ sorted_items . size } 件を news.yml に保存しました" )
191+ TASK_LOGGER . info ( "📌 次は 'bundle exec rails news:upsert' でデータベースに反映してください" )
192+ TASK_LOGGER . info ( "==== END news:fetch:reset ====" )
157193 end
158194
159- # WordPress REST API からすべての投稿を取得
160- def fetch_all_wordpress_posts ( logger )
161- items = [ ]
162- page = 1
163- per_page = 100
164-
165- loop do
166- uri = URI ( "https://news.coderdojo.jp/wp-json/wp/v2/posts" )
167- uri . query = URI . encode_www_form ( page : page , per_page : per_page , status : 'publish' )
168-
169- response = Net ::HTTP . get_response ( uri )
170- break unless response . is_a? ( Net ::HTTPSuccess )
171-
172- posts = JSON . parse ( response . body )
173- break if posts . empty?
174-
175- posts . each do |post |
176- items << {
177- 'url' => post [ 'link' ] ,
178- 'title' => post [ 'title' ] [ 'rendered' ] ,
179- 'published_at' => Time . parse ( post [ 'date_gmt' ] + ' UTC' ) . iso8601
180- }
181- end
182-
183- logger . info ( "📄 WordPress API: ページ #{ page } から #{ posts . size } 件取得" )
184- page += 1
185- end
186-
187- items
188- end
189-
190- # PR TIMES RSS フィードから全記事を取得
191- def fetch_prtimes_feed ( logger )
192- items = [ ]
193-
194- begin
195- feed = RSS ::Parser . parse ( 'https://prtimes.jp/companyrdf.php?company_id=38935' , false )
196-
197- feed . items . each do |item |
198- published_at = if item . respond_to? ( :dc_date ) && item . dc_date
199- item . dc_date . iso8601
200- else
201- raise "PR TIMES feed: dc:date not found for item: #{ item . link } "
202- end
203-
204- items << {
205- 'url' => item . link ,
206- 'title' => item . title ,
207- 'published_at' => published_at
208- }
209- end
210-
211- logger . info ( "📢 PR TIMES RSS: #{ items . size } 件取得" )
212- rescue => e
213- logger . error ( "❌ PR TIMES フィード取得エラー: #{ e . message } " )
214- end
215-
216- items
217- end
218195
219196 desc "#{ NEWS_YAML_PATH } からデータベースに upsert"
220197 task upsert : :environment do
221- console = ActiveSupport ::Logger . new ( STDOUT )
222- logger_file = ActiveSupport ::Logger . new ( NEWS_LOG_PATH )
223- logger = ActiveSupport ::BroadcastLogger . new ( logger_file , console )
224-
225- logger . info "==== START news:upsert ===="
198+ TASK_LOGGER . info "==== START news:upsert ===="
226199
227200 news_items = YAML . safe_load File . read ( NEWS_YAML_PATH )
228201 created_count = 0
@@ -244,13 +217,13 @@ namespace :news do
244217 created_count += 1 if is_new_record
245218 updated_count += 1 unless is_new_record
246219
247- logger . info "[News] #{ news . published_at . to_date } #{ news . title } (#{ status } )"
220+ TASK_LOGGER . info "[News] #{ news . published_at . to_date } #{ news . title } (#{ status } )"
248221 end
249222 end
250223 end
251224
252- logger . info "Upserted #{ created_count + updated_count } items (#{ created_count } new, #{ updated_count } updated)."
253- logger . info "==== END news:upsert ===="
254- logger . info ""
225+ TASK_LOGGER . info "Upserted #{ created_count + updated_count } items (#{ created_count } new, #{ updated_count } updated)."
226+ TASK_LOGGER . info "==== END news:upsert ===="
227+ TASK_LOGGER . info ""
255228 end
256229end
0 commit comments