@@ -4,146 +4,43 @@ require 'connpass_api_v2'
44require 'uri'
55require 'net/http'
66require 'json'
7- require 'timeout'
87
9- if ENV [ 'CONNPASS_API_KEY' ] . nil?
10- puts ( 'CONNPASS_API_KEY が設定されていません' )
11- exit ( 1 )
12- end
8+ HOW_TO_USE_MESSAGE = <<~MESSAGE
9+ Usage: c-search [CONNPASS_URL | CONNPASS_EVENT_ID]
10+ 例: c-search https://coderdojoaoyama.connpass.com/
11+ 例: c-search https://coderdojoaoyama.connpass.com/event/356972/
12+ 例: c-search 356972
13+ MESSAGE
1314
14- if ARGV . empty?
15- puts ( 'Usage: c-search [CONNPASS_URL | CONNPASS_EVENT_ID]' )
16- puts ( ' 例: c-search https://coderdojoaoyama.connpass.com/' )
17- puts ( ' 例: c-search https://coderdojoaoyama.connpass.com/event/356972/' )
18- puts ( ' 例: c-search 356972' )
19- exit ( 1 )
15+ if ARGV . empty? || ARGV [ 0 ] . end_with? ( 'event' , 'event/' )
16+ puts HOW_TO_USE_MESSAGE
17+ exit 1
2018end
2119
22- input = ARGV [ 0 ]
23-
24- # URLのバリデーションとタイプ判定
25- def validate_and_classify_url ( input )
26- # 数字のみの場合はイベントID
27- return { type : :event_id , value : input . gsub ( /\D / , '' ) } if input !~ /^https?:\/ \/ /
20+ input = ARGV [ 0 ]
21+ api_key = ENV [ 'CONNPASS_API_KEY' ]
2822
29- begin
30- uri = URI . parse ( input )
31-
32- # HTTPSのみ許可(セキュリティ対策)
33- unless uri . scheme == 'https'
34- return { type : :error , message : "HTTPSのURLを指定してください: #{ input } " }
35- end
36-
37- # Connpassドメインのみ許可(SSRF対策)
38- unless uri . host &.end_with? ( '.connpass.com' )
39- return { type : :error , message : "Connpass のURLを指定してください: #{ input } " }
40- end
41-
42- # イベントURLの場合
43- if uri . path =~ %r{/event/(\d +)/?}
44- return { type : :event_url , event_id : $1 }
45- end
46-
47- # グループURLの場合
48- if uri . path == '/' || uri . path . empty?
49- subdomain = uri . host . split ( '.' ) . first
50- return { type : :group_url , subdomain : subdomain }
51- end
52-
53- return { type : :error , message : "認識できないURLパターンです: #{ input } " }
54- rescue URI ::InvalidURIError => e
55- return { type : :error , message : "無効なURLです: #{ input } " }
56- end
57- end
23+ # 数字のみ、またはイベントURLの場合
24+ if input =~ /\A (\d +)$/ or input =~ /event\/ (\d +)/
25+ event_id = $1
26+ client = ConnpassApiV2 . client ( api_key )
27+ result = client . get_events ( event_id : event_id )
28+ puts result . events . first [ 'group' ] [ 'id' ]
5829
59- # グループ情報を取得する関数(リダイレクト対応)
60- def fetch_group_by_subdomain ( subdomain , api_key , limit = 5 )
61- return { success : false , message : "リダイレクトが多すぎます" } if limit <= 0
62-
63- uri = URI ( 'https://connpass.com/api/v2/groups/' )
30+ # グループURLの場合
31+ elsif input =~ /\A https:\/ \/ ([\w -]+)\. connpass\. com/
32+ subdomain = $1
33+ uri = URI ( 'https://connpass.com/api/v2/groups/' )
6434 uri . query = URI . encode_www_form ( subdomain : subdomain , count : 1 )
65-
66- req = Net ::HTTP ::Get . new ( uri )
35+
36+ req = Net ::HTTP ::Get . new ( uri )
6737 req [ 'X-Api-Key' ] = api_key
68-
69- begin
70- res = Net ::HTTP . start ( uri . hostname , uri . port , use_ssl : true ,
71- open_timeout : 5 , read_timeout : 5 ) do |http |
72- http . request ( req )
73- end
74-
75- case res
76- when Net ::HTTPSuccess
77- data = JSON . parse ( res . body )
78- return { success : false , message : "Invalid API response" } unless data . is_a? ( Hash )
79-
80- if data [ 'results_returned' ] && data [ 'results_returned' ] > 0
81- groups = data [ 'groups' ]
82- return { success : false , message : "Invalid API response: missing groups" } unless groups &.any?
83-
84- group = groups . first
85- group_id = group &.dig ( 'id' )
86- return { success : false , message : "Invalid API response: missing group ID" } unless group_id
87-
88- return { success : true , group_id : group_id }
89- else
90- return { success : false , message : "グループが見つかりませんでした (subdomain: #{ subdomain } )" }
91- end
92- when Net ::HTTPRedirection # 301, 302などのリダイレクト
93- location = res [ 'location' ]
94- if location
95- # 新しいURIでリトライ
96- new_uri = URI . join ( uri , location )
97- # リダイレクト先のURIから新しいsubdomainを抽出
98- new_subdomain = new_uri . host &.split ( '.' ) &.first
99- return { success : false , message : "Invalid redirect URL" } unless new_subdomain
100- return fetch_group_by_subdomain ( new_subdomain , api_key , limit - 1 )
101- else
102- return { success : false , message : "リダイレクト先が不明です" }
103- end
104- when Net ::HTTPNotFound
105- return { success : false , message : "グループが見つかりませんでした (subdomain: #{ subdomain } )" }
106- else
107- return { success : false , message : "APIエラー: #{ res . code } #{ res . message } " }
108- end
109- rescue Timeout ::Error
110- return { success : false , message : "APIへの接続がタイムアウトしました" }
111- rescue => e
112- return { success : false , message : "エラーが発生しました: #{ e . message } " }
113- end
114- end
11538
116- # メイン処理
117- result = validate_and_classify_url ( input )
39+ response = Net ::HTTP . start ( uri . hostname , uri . port , use_ssl : true ) { it . request req }
40+ result = JSON . parse ( response . body )
41+ puts result [ 'groups' ] . first [ 'id' ]
11842
119- case result [ :type ]
120- when :error
121- puts result [ :message ]
43+ else
44+ puts HOW_TO_USE_MESSAGE
12245 exit 1
123-
124- when :event_id , :event_url
125- # イベントIDまたはイベントURLの場合(既存の処理)
126- event_id = result [ :type ] == :event_id ? result [ :value ] : result [ :event_id ]
127-
128- client = ConnpassApiV2 . client ( ENV [ 'CONNPASS_API_KEY' ] )
129- api_result = client . get_events ( event_id : event_id )
130-
131- if api_result . results_returned > 0
132- event = api_result . events . first
133- puts event . fetch ( 'group' ) . fetch ( 'id' )
134- else
135- puts "イベントが見つかりませんでした (event_id: #{ event_id } )"
136- exit 1
137- end
138-
139- when :group_url
140- # グループURLの場合(新規処理)
141- group_result = fetch_group_by_subdomain ( result [ :subdomain ] , ENV [ 'CONNPASS_API_KEY' ] )
142-
143- if group_result [ :success ]
144- puts group_result [ :group_id ]
145- else
146- puts group_result [ :message ]
147- exit 1
148- end
14946end
0 commit comments