Skip to content

Commit 40e4dcc

Browse files
committed
ポッドキャストのタイムスタンプ自動リンク機能を修正
- hh:mm:ss形式(00:00:00)のタイムスタンプに対応 - タイムスタンプをYouTubeの時間形式(?t=1h23m45s)に正確に変換 - mm:ss形式も引き続きサポート - テストケースを追加して動作を保証 - エピソード32のタイムスタンプ形式を統一し、欠けていたURLを追加
1 parent b9429da commit 40e4dcc

File tree

4 files changed

+124
-56
lines changed

4 files changed

+124
-56
lines changed

app/controllers/podcasts_controller.rb

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,24 @@ def convert_shownote(content)
4848
return content unless content.match?(Podcast::TIMESTAMP_REGEX)
4949
youtube_id = @episode.content.match(Podcast::YOUTUBE_ID_REGEX)[1]
5050
content.gsub!(Podcast::TIMESTAMP_REGEX) do
51-
t = $1
52-
t = (t.size == '0:00'.size) ? '0' + t : t
53-
t = (t.size == '00:00'.size) ? '00:' + t : t
54-
55-
#t = Time.parse(t).seconds_since_midnight.to_i
56-
# This format should be faster than above:
57-
# ?t=01:23:45
58-
# ?t=01h23m45s
59-
t[2] = 'h'
60-
t[5] = 'm'
61-
t << 's'
62-
"- [#{$1}](https://youtu.be/#{youtube_id}?t=#{t}) &nbsp; "
51+
original_t = $1
52+
parts = original_t.split(':')
53+
54+
# タイムスタンプをh:m:s形式に変換
55+
if parts.size == 3
56+
# 00:00:00 形式
57+
h, m, s = parts
58+
t = "#{h}h#{m}m#{s}s"
59+
elsif parts.size == 2
60+
# 00:00 形式
61+
m, s = parts
62+
t = "#{m}m#{s}s"
63+
else
64+
# それ以外(通常は来ないはず)
65+
t = original_t
66+
end
67+
68+
"- [#{original_t}](https://youtu.be/#{youtube_id}?t=#{t}) &nbsp; "
6369
end
6470
end
6571
end

app/models/podcast.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ class Podcast < ApplicationRecord
22
self.table_name = 'podcasts'
33
DIR_PATH = 'public/podcasts'
44
WDAY2JAPANESE = %w( )
5-
TIMESTAMP_REGEX = /-\s((\d:)?\d{1,}:\d{2})/
5+
TIMESTAMP_REGEX = /-\s((\d{1,2}:)?\d{1,2}:\d{2})/
66
YOUTUBE_ID_REGEX = /watch\?v=((\w)*)/
77

88
validates :title, presence: true

public/podcasts/32.md

Lines changed: 43 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -32,46 +32,46 @@
3232

3333
## Shownote
3434

35-
- 00:00 米国系 IT 企業から CoderDojo へ、233台のノートPC寄贈
36-
- 00:24 配送作業の裏話と、こだわりポイントの紹介
37-
- 01:06 CoderDojo Japan からのお知らせ記事の紹介
38-
- 03:01 過去の寄贈(128台、55台)から233台への規模拡大
39-
- 03:40 配送作業のノウハウ蓄積と、数学的な配分問題
40-
- 04:09 寄贈後のトラブル確認と、英語キーボード配列
41-
- 07:20 制約充足問題として配分を数学的に解いてみる
42-
- 10:20 ダンボール箱の最適化(80サイズで2台ずつ梱包)
43-
- 13:03 偶数台数での配送と、発注する箱数の計算
44-
- 14:08 搬入から搬出までの作業時間の制約
45-
- 16:04 1道場あたりの台数制限(税務上の制約)
46-
- 17:10 土日の30時間で全作業を完了させる計画
47-
- 17:24 配分の公平性をジニ係数で数値化
48-
- 19:30 AI を活用したマッチング(希望機種の振り分け)
49-
- 21:00 マッチ度をなるべく上げていく試み
50-
- 23:52 AI との対話で制約充足問題を解決
51-
- 25:01 AI と遊んでみる回の動画
52-
- 28:27 梱包作業の実際の様子(開封から箱詰めまで)
53-
- 29:02 PC が子供たちに手に届くまで、多くの人が関わっている話
54-
- 31:05 数値化だけでは全てを把握できない話(機種グレードも考慮した例)
55-
- 33:54 ACアダプターなどの対応確認、声かけ確認
56-
- 35:37 指差し確認で間違いを防いで作業する
57-
- 38:40 番号で管理し、最終確認も実施する
58-
- 41:08 233台、すべて初期化していただいた話
59-
- 42:02 梱包の工夫(ACアダプターを上に置かない等)
60-
- 44:13 作業完了後のふりかえり
61-
- 44:55 今後の寄贈プロジェクトへの展望
62-
- 46:02 日本国内での英語版CoderDojoの話
63-
- 46:35 統計情報の英語対応の話 https://coderdojo.jp/stats/english
64-
- 47:00 CASE Shinjuku の日常にも、国際化の流れ
65-
- 49:10 CoderDojo 立ち上げ相談(ロボット工場のある町)
66-
- 54:07 CASE Shinjuku の紹介(1時間500円から利用可能)
67-
- 56:00 多様な利用者層(絵を描く人、DIY、音楽活動)
68-
- 57:52 CoderDojo 青山の「青学つくまなラボ」の話
69-
- 58:00 山崎さんの歌をYouTube配信で使用した話
70-
- 59:14 CASE Shinjuku 利用者と CoderDojo の繋がり
71-
- 1:00:57 CASE Shinjuku の英語アクセスページ
72-
- 1:02:01 CASE Shinjuku の英語インタビュー記事
73-
- 1:04:03 アクセス記事を更新する企画
74-
- 1:07:13 12年前のプレオープン、何もない空間で初めて話した話
75-
- 1:08:35 「私より後に生まれてきた人のために」
76-
- 1:09:22 Pay it forward(恩送り)の考え方
77-
- 1:10:41 エンディング(熱中症に気をつけて)
35+
- 00:00:00 米国系 IT 企業から CoderDojo へ、233台のノートPC寄贈
36+
- 00:00:24 配送作業の裏話と、こだわりポイントの紹介
37+
- 00:01:06 CoderDojo Japan からのお知らせ記事の紹介
38+
- 00:03:01 過去の寄贈(128台、55台)から233台への規模拡大
39+
- 00:03:40 配送作業のノウハウ蓄積と、数学的な配分問題
40+
- 00:04:09 寄贈後のトラブル確認と、英語キーボード配列
41+
- 00:07:20 制約充足問題として配分を数学的に解いてみる
42+
- 00:10:20 ダンボール箱の最適化(80サイズで2台ずつ梱包)
43+
- 00:13:03 偶数台数での配送と、発注する箱数の計算
44+
- 00:14:08 搬入から搬出までの作業時間の制約
45+
- 00:16:04 1道場あたりの台数制限(税務上の制約)
46+
- 00:17:10 土日の30時間で全作業を完了させる計画
47+
- 00:17:24 配分の公平性をジニ係数で数値化
48+
- 00:19:30 AI を活用したマッチング(希望機種の振り分け)
49+
- 00:21:00 マッチ度をなるべく上げていく試み
50+
- 00:23:52 AI との対話で制約充足問題を解決
51+
- 00:25:01 AI と遊んでみる回の動画 https://youtu.be/BYpa1CcYtss?t=1425
52+
- 00:28:27 梱包作業の実際の様子(開封から箱詰めまで)
53+
- 00:29:02 PC が子供たちに手に届くまで、多くの人が関わっている話
54+
- 00:31:05 数値化だけでは全てを把握できない話(機種グレードも考慮した例)
55+
- 00:33:54 ACアダプターなどの対応確認、声かけ確認
56+
- 00:35:37 指差し確認で間違いを防いで作業する
57+
- 00:38:40 番号で管理し、最終確認も実施する
58+
- 00:41:08 233台、すべて初期化していただいた話
59+
- 00:42:02 梱包の工夫(ACアダプターを上に置かない等)
60+
- 00:44:13 作業完了後のふりかえり
61+
- 00:44:55 今後の寄贈プロジェクトへの展望
62+
- 00:46:02 日本国内での英語版CoderDojoの話
63+
- 00:46:35 統計情報の英語対応の話 https://coderdojo.jp/stats/english
64+
- 00:47:00 CASE Shinjuku の日常にも、国際化の流れ
65+
- 00:49:10 CoderDojo 立ち上げ相談(ロボット工場のある町)
66+
- 00:54:07 CASE Shinjuku の紹介(1時間500円から利用可能)
67+
- 00:56:00 多様な利用者層(絵を描く人、DIY、音楽活動)
68+
- 00:57:52 CoderDojo 青山の「青学つくまなラボ」の話
69+
- 00:58:00 山崎さんの歌をYouTube配信で使用した話 https://youtu.be/ZJdlsgMzWrU
70+
- 00:59:14 CASE Shinjuku 利用者と CoderDojo の繋がり
71+
- 01:00:57 CASE Shinjuku の英語アクセスページ https://case-shinjuku.com/english
72+
- 01:02:01 CASE Shinjuku の英語インタビュー記事
73+
- 01:04:03 アクセス記事を更新する企画
74+
- 01:07:13 12年前のプレオープン、何もない空間で初めて話した話
75+
- 01:08:35 「私より後に生まれてきた人のために」
76+
- 01:09:22 Pay it forward(恩送り)の考え方
77+
- 01:10:41 エンディング(熱中症に気をつけて)

spec/features/podcasts_spec.rb

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,67 @@
3636
click_link target, match: :first
3737
expect(page).to have_http_status(:success)
3838
end
39+
40+
scenario 'Show note timestamps are converted to YouTube links' do
41+
@podcast = create(:podcast)
42+
allow(@podcast).to receive(:exist?) { true }
43+
allow(@podcast).to receive(:content) {
44+
<<~CONTENT
45+
タイトル
46+
収録日: 2019/05/10
47+
48+
YouTubeリンク: https://www.youtube.com/watch?v=Dd9IYiF0R6E
49+
50+
## Shownote
51+
52+
- 00:00:00 米国系 IT 企業から CoderDojo へ、233台のノートPC寄贈
53+
- 00:25:01 AI と遊んでみる回の動画 https://youtu.be/BYpa1CcYtss?t=1425
54+
- 00:59:14 CASE Shinjuku 利用者と CoderDojo の繋がり
55+
- 01:00:57 CASE Shinjuku の英語アクセスページ https://case-shinjuku.com/english
56+
CONTENT
57+
}
58+
allow(Podcast).to receive(:find_by).with(id: @podcast.id.to_s) { @podcast }
59+
60+
visit "/podcasts/#{@podcast.id}"
61+
expect(page).to have_http_status(:success)
62+
63+
# タイムスタンプがYouTubeリンクに変換されているか確認
64+
expect(page).to have_link '00:00:00', href: 'https://youtu.be/Dd9IYiF0R6E?t=00h00m00s'
65+
expect(page).to have_link '00:25:01', href: 'https://youtu.be/Dd9IYiF0R6E?t=00h25m01s'
66+
expect(page).to have_link '00:59:14', href: 'https://youtu.be/Dd9IYiF0R6E?t=00h59m14s'
67+
expect(page).to have_link '01:00:57', href: 'https://youtu.be/Dd9IYiF0R6E?t=01h00m57s'
68+
69+
# 既存のURL付きタイムスタンプはそのまま表示されること
70+
expect(page).to have_content 'AI と遊んでみる回の動画 https://youtu.be/BYpa1CcYtss?t=1425'
71+
expect(page).to have_content 'CASE Shinjuku の英語アクセスページ https://case-shinjuku.com/english'
72+
end
73+
74+
scenario 'Show note timestamps with mm:ss format are converted to YouTube links' do
75+
@podcast = create(:podcast)
76+
allow(@podcast).to receive(:exist?) { true }
77+
allow(@podcast).to receive(:content) {
78+
<<~CONTENT
79+
タイトル
80+
収録日: 2019/05/10
81+
82+
YouTubeリンク: https://www.youtube.com/watch?v=test123
83+
84+
## Shownote
85+
86+
- 00:30 オープニング
87+
- 05:45 メインテーマ
88+
- 59:59 エンディング
89+
CONTENT
90+
}
91+
allow(Podcast).to receive(:find_by).with(id: @podcast.id.to_s) { @podcast }
92+
93+
visit "/podcasts/#{@podcast.id}"
94+
expect(page).to have_http_status(:success)
95+
96+
# mm:ss形式のタイムスタンプもYouTubeリンクに変換されているか確認
97+
expect(page).to have_link '00:30', href: 'https://youtu.be/test123?t=00m30s'
98+
expect(page).to have_link '05:45', href: 'https://youtu.be/test123?t=05m45s'
99+
expect(page).to have_link '59:59', href: 'https://youtu.be/test123?t=59m59s'
100+
end
39101
end
40102
end

0 commit comments

Comments
 (0)