Skip to content

Commit 55a9141

Browse files
authored
Merge pull request #1699 from coderdojo-japan/update-connpass-api-from-v1-to-v2
Upgrade `connpass` API: v1 -> v2
2 parents 478c148 + f82ba9b commit 55a9141

File tree

15 files changed

+187
-106
lines changed

15 files changed

+187
-106
lines changed

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ gem 'kramdown-parser-gfm'
3939
gem 'faraday'
4040
gem 'koala'
4141
gem 'lazy_high_charts', '1.5.8'
42+
gem 'connpass_api_v2' # https://github.com/sue445/connpass_api_v2-ruby
4243

4344
# Protect from attacks for Security
4445
gem 'rack-attack'

Gemfile.lock

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ GEM
123123
logger (~> 1.5)
124124
concurrent-ruby (1.3.5)
125125
connection_pool (2.5.3)
126+
connpass_api_v2 (0.1.0)
127+
faraday (>= 2.0.0)
128+
faraday-mashify
126129
crass (1.0.6)
127130
csv (3.3.4)
128131
date (3.4.1)
@@ -144,6 +147,9 @@ GEM
144147
faraday-net_http (>= 2.0, < 3.5)
145148
json
146149
logger
150+
faraday-mashify (1.0.0)
151+
faraday (~> 2.0)
152+
hashie
147153
faraday-multipart (1.1.0)
148154
multipart-post (~> 2.0)
149155
faraday-net_http (3.4.0)
@@ -165,6 +171,7 @@ GEM
165171
globalid (1.2.1)
166172
activesupport (>= 6.1)
167173
hash-deep-merge (0.1.1)
174+
hashie (5.0.0)
168175
i18n (1.14.7)
169176
concurrent-ruby (~> 1.0)
170177
io-console (0.8.0)
@@ -483,6 +490,7 @@ DEPENDENCIES
483490
bootsnap
484491
bootstrap-sass
485492
capybara
493+
connpass_api_v2
486494
csv
487495
dotenv-rails
488496
factory_bot_rails

bin/c-search

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,42 @@
1-
#!/bin/sh
2-
ENVRC_FILE=".envrc"
1+
#!/usr/bin/env ruby
32

4-
if [ ! -f "$ENVRC_FILE" ]; then
5-
echo "$ENVRC_FILE が見つかりません"
6-
exit 1
7-
fi
3+
require 'connpass_api_v2'
4+
require 'uri'
85

9-
source "$ENVRC_FILE"
6+
if ENV['CONNPASS_API_KEY'].nil?
7+
puts('CONNPASS_API_KEY が設定されていません')
8+
exit(1)
9+
end
1010

11-
if [ -z "$FIXIE_URL" ]; then
12-
echo "FIXIE_URL が設定されていません"
13-
exit 1
14-
fi
11+
if ARGV.empty?
12+
puts('Usage: c-search [CONNPASS_EVENT_URL | CONNPASS_EVENT_ID]')
13+
exit(1)
14+
end
1515

16-
if [ $# -eq 0 ]
17-
then
18-
echo "Usage: c-search [CONNPASS_EVENT_URL | CONNPASS_EVENT_ID]"
16+
input = ARGV[0]
17+
event_id = nil
18+
if input =~ /^https?:\/\//
19+
# URLからイベントIDを抽出
20+
event_id = URI(input).path[%r{event/(\d+)}, 1]
1921
else
20-
id=$(echo $1 | sed -e 's/[^0-9]//g')
21-
curl -x "$FIXIE_URL" -sL "https://connpass.com/api/v1/event/?event_id=${id}" | jq ".events[].series.id"
22-
fi
22+
event_id = input.gsub(/\D/, '')
23+
end
24+
25+
unless event_id && !event_id.empty?
26+
puts "イベントIDが特定できませんでした: #{input}"
27+
exit 1
28+
end
29+
30+
client = ConnpassApiV2.client(ENV['CONNPASS_API_KEY'])
31+
result = client.get_events(event_id: event_id)
32+
33+
if result.results_returned > 0
34+
event = result.events.first
35+
puts event.fetch('id')
36+
#puts "id: #{event.fetch('id')}"
37+
#puts "title: #{event.fetch('title')}"
38+
#puts "group_id: #{event.fetch('group').fetch('id')}"
39+
#puts "group_name: #{event.fetch('group').fetch('title')}"
40+
else
41+
puts "イベントが見つかりませんでした (event_id: #{event_id})"
42+
end

bin/setup

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ FileUtils.chdir APP_ROOT do
3434
#today = Time.now.in_time_zone('Tokyo').to_date
3535
#from = (today - 90).strftime('%Y%m')
3636
#to = today.prev_month.strftime('%Y%m')
37-
#if ENV['DOORKEEPER_API_TOKEN'] && ENV['FIXIE_URL']
37+
#if ENV['DOORKEEPER_API_TOKEN'] && ENV['CONNPASS_API_KEY']
3838
# system! "bin/rails statistics:aggregation[#{from},#{to}]"
3939
# system! 'bin/rails upcoming_events:aggregation'
4040
#elsif ENV['DOORKEEPER_API_TOKEN']
@@ -43,7 +43,7 @@ FileUtils.chdir APP_ROOT do
4343
# system! 'bin/rails upcoming_events:aggregation[connpass]'
4444
#else
4545
# puts <<~MESSAGE
46-
# 環境変数 DOORKEEPER_API_TOKEN と FIXIE_URL が設定されていないため、
46+
# 環境変数 DOORKEEPER_API_TOKEN と CONNPASS_API_KEY が設定されていないため、
4747
# Doorkeeper API や connpass API を使ったイベント情報の取得をスキップします。
4848
#
4949
# なお API 経由でイベント情報を取得しなくても、rails server は実行可能です。

lib/event_service/client.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ def get(path, params)
1616
def connection_for(endpoint, proxy)
1717
Faraday.new(endpoint, proxy: proxy) do |f|
1818
f.response :logger if self.class.debug
19-
19+
2020
# faraday標準のJSONパーサーを使用
2121
f.response :json, parser_options: { symbolize_names: true }
22-
22+
2323
# faraday標準のエラーハンドリングを使用
2424
f.response :raise_error, include_request: true
2525

lib/event_service/providers/connpass.rb

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
1+
require 'connpass_api_v2'
2+
13
module EventService
24
module Providers
35
class Connpass
4-
ENDPOINT = 'https://connpass.com/api/v1'.freeze
5-
# NOTE: 期間は ym or ymd パラメータで指定(複数指定可能)、未指定時全期間が対象
6-
76
def initialize
8-
@client = EventService::Client.new(ENDPOINT, proxy: ENV['FIXIE_URL'])
7+
@client = ConnpassApiV2.client(ENV['CONNPASS_API_KEY'])
98
end
109

1110
def search(keyword:)
12-
@client.get('event/', { keyword: keyword, count: 100 })
11+
@client.get_events(keyword: keyword, count: 100)
1312
end
1413

1514
# NOTE: yyyymm, yyyymmdd は文字列を要素とする配列(Array[String])で指定
16-
def fetch_events(series_id:, yyyymm: nil, yyyymmdd: nil)
17-
series_id = series_id.join(',') if series_id.is_a?(Array)
15+
def fetch_events(group_id:, yyyymm: nil, yyyymmdd: nil)
16+
group_id = group_id.join(',') if group_id.is_a?(Array)
1817

18+
# API v1 -> v2 でパラメータ名が変更された
19+
# https://connpass.com/about/api/v2/
20+
# e.g. series_id -> group_id
1921
params = {
20-
series_id: series_id,
21-
start: 1,
22-
count: 100
22+
group_id: group_id,
23+
start: 1, # offset → start
24+
count: 100 # limit → count
2325
}
2426

2527
param_period_patern = []
@@ -35,17 +37,22 @@ def fetch_events(series_id:, yyyymm: nil, yyyymmdd: nil)
3537

3638
param_period_patern.each do |param_period|
3739
loop do
38-
# connpass は https://connpass.com/robots.txt を守らない場合は、アクセス制限を施すので、下記の sleep を入れるようにした https://connpass.com/about/api/
39-
sleep 5
40-
part = @client.get('event/', params.merge(param_period))
40+
begin
41+
args = params.merge(param_period).compact
42+
res = @client.get_events(**args)
43+
rescue ConnpassApiV2::Error => e
44+
sleep 5 && retry if e.response&.status == 403
45+
46+
raise e
47+
end
4148

42-
break if part['results_returned'].zero?
49+
break if res.results_returned.zero?
4350

44-
events.push(*part.fetch('events'))
51+
events.push(*res.events)
4552

46-
break if part.size < params[:count]
53+
break if res.events.size < params[:count]
4754

48-
break if params[:start] + params[:count] > part['results_available']
55+
break if params[:start] + params[:count] > res.results_available
4956

5057
params[:start] += params[:count]
5158
end

lib/event_service/providers/doorkeeper.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class Doorkeeper
66

77
def initialize
88
@client = EventService::Client.new(ENDPOINT) do |c|
9-
c.authorization(:Bearer, ENV.fetch('DOORKEEPER_API_TOKEN'))
9+
c.request :authorization, 'Bearer', ENV.fetch('DOORKEEPER_API_TOKEN')
1010
end
1111
@default_since = '2010-07-01'.to_date.beginning_of_day
1212
@default_until = Time.zone.yesterday.end_of_day

lib/statistics/tasks/connpass.rb

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,19 @@ def run
2020
dojo.dojo_event_services.for(:connpass).pluck(:group_id)
2121
end
2222

23-
@client.fetch_events(**@params.merge(series_id: group_ids)).each do |e|
23+
@client.fetch_events(**@params.merge(group_id: group_ids)).each do |e|
2424
dojo_event_service = DojoEventService.find_by(group_id: e.dig('series', 'id').to_s)
2525
next unless dojo_event_service
2626

2727
EventHistory.create!(dojo_id: dojo_event_service.dojo_id,
2828
dojo_name: dojo_event_service.dojo.name,
2929
service_name: dojo_event_service.name,
3030
service_group_id: dojo_event_service.group_id,
31-
event_id: e['event_id'],
32-
event_url: e['event_url'],
33-
participants: e['accepted'],
34-
evented_at: Time.zone.parse(e['started_at']))
31+
event_id: e.fetch('id'),
32+
event_url: e.fetch('event_url'),
33+
participants: e.fetch('accepted'),
34+
evented_at: Time.zone.parse(e.fetch('started_at'))
35+
)
3536
end
3637
end
3738

lib/statistics/tasks/doorkeeper.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ def initialize(dojos, period)
1818
def run
1919
@dojos.each do |dojo|
2020
dojo.dojo_event_services.for(:doorkeeper).each do |dojo_event_service|
21-
@client.fetch_events(**@params.merge(group_id: dojo_event_service.group_id)).each do |e|
21+
events = @client.fetch_events(**@params.merge(group_id: dojo_event_service.group_id))
22+
(events || []).compact.each do |e|
2223
next unless e['group'].to_s == dojo_event_service.group_id
2324

2425
EventHistory.create!(dojo_id: dojo.id,

lib/upcoming_events/tasks/connpass.rb

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,25 @@ def run
1111
group_ids = @dojos.flat_map do |dojo|
1212
dojo.dojo_event_services.for(:connpass).pluck(:group_id)
1313
end
14-
15-
@client.fetch_events(**@params.merge(series_id: group_ids)).each do |e|
16-
dojo_event_service = DojoEventService.find_by(group_id: e.dig('series', 'id').to_s)
14+
15+
events = @client.fetch_events(**@params.merge(group_id: group_ids))
16+
puts "[connpass] Fetched events: #{events.size}"
17+
events.each do |e|
18+
puts "[connpass] event_id: #{e.fetch('id')}, title: #{e.fetch('title')}"
19+
dojo_event_service = DojoEventService.find_by(group_id: e.dig('group', 'id').to_s)
1720
next unless dojo_event_service
18-
19-
record = dojo_event_service.upcoming_events.find_or_initialize_by(event_id: e['event_id'])
21+
22+
record = dojo_event_service.upcoming_events.find_or_initialize_by(event_id: e.fetch('id'))
2023
record.update!(service_name: dojo_event_service.name,
21-
event_title: e['title'],
22-
event_url: e['event_url'],
23-
event_at: Time.zone.parse(e['started_at']),
24-
event_end_at: Time.zone.parse(e['ended_at']),
25-
participants: e['accepted'],
26-
event_update_at: Time.zone.parse(e['updated_at']),
27-
address: e['address'],
28-
place: e['place'],
29-
limit: e['limit'])
24+
event_title: e.fetch('title'),
25+
event_url: e.fetch('url'),
26+
event_at: Time.zone.parse(e.fetch('started_at')),
27+
event_end_at: Time.zone.parse(e.fetch('ended_at')),
28+
participants: e.fetch('accepted'),
29+
event_update_at: Time.zone.parse(e.fetch('updated_at')),
30+
address: e.fetch('address'),
31+
place: e.fetch('place'),
32+
limit: e.fetch('limit'))
3033
end
3134
end
3235

lib/upcoming_events/tasks/doorkeeper.rb

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,23 @@ def initialize(dojos, period)
1010
def run
1111
@dojos.each do |dojo|
1212
dojo.dojo_event_services.for(:doorkeeper).each do |dojo_event_service|
13-
@client.fetch_events(**@params.merge(group_id: dojo_event_service.group_id)).each do |e|
14-
next unless e['group'].to_s == dojo_event_service.group_id
13+
events = @client.fetch_events(**@params.merge(group_id: dojo_event_service.group_id))
14+
puts "[Doorkeeper] dojo_id: #{dojo.id}, group_id: #{dojo_event_service.group_id}, fetched events: #{events&.size || 0}"
15+
(events || []).compact.each do |e|
16+
puts "[Doorkeeper] event_id: #{e.fetch('id')}, title: #{e.fetch('title')}"
17+
next unless e.fetch('group').to_s == dojo_event_service.group_id
1518

16-
record = dojo_event_service.upcoming_events.find_or_initialize_by(event_id: e['id'])
19+
record = dojo_event_service.upcoming_events.find_or_initialize_by(event_id: e.fetch('id'))
1720
record.update!(service_name: dojo_event_service.name,
18-
event_title: e['title'],
19-
event_url: e['public_url'],
20-
participants: e['participants'],
21-
event_at: Time.zone.parse(e['starts_at']),
22-
event_end_at: Time.zone.parse(e['ends_at']),
23-
event_update_at: Time.zone.parse(e['updated_at']),
24-
address: e['address'],
25-
place: e['venue_name'],
26-
limit: e['ticket_limit'])
21+
event_title: e.fetch('title'),
22+
event_url: e.fetch('public_url'),
23+
participants: e.fetch('participants'),
24+
event_at: Time.zone.parse(e.fetch('starts_at')),
25+
event_end_at: Time.zone.parse(e.fetch('ends_at')),
26+
event_update_at: Time.zone.parse(e.fetch('updated_at')),
27+
address: e.fetch('address'),
28+
place: e.fetch('venue_name'),
29+
limit: e.fetch('ticket_limit'))
2730
end
2831
end
2932
end

spec/lib/event_service/providers/connpass_spec.rb

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,40 +8,28 @@
88
subject { described_class.new.search(keyword: 'coderdojo') }
99

1010
it do
11-
expect(subject).to be_instance_of(Hash)
12-
expect(subject['results_returned']).to eq 1
13-
expect(subject['events'].size).to eq 1
14-
expect(subject['events'].first['event_id']).to eq 12345
15-
expect(subject['events'].first['series']['url']).to eq 'https://coderdojo-okutama.connpass.com/'
16-
expect(subject['events'].first['series']['id']).to eq 9876
11+
expect(subject).to be_a(ConnpassApiV2::Response)
12+
expect(subject.results_returned).to eq 100
13+
expect(subject.events).to be_a(Array)
1714
end
1815
end
1916

2017
describe '#fetch_events' do
21-
context 'when a single series_id is given' do
22-
subject { described_class.new.fetch_events(series_id: 9876) }
18+
context 'when a single group_id is given' do
19+
subject { described_class.new.fetch_events(group_id: 9876) }
2320

2421
it do
25-
expect(subject).to be_instance_of(Array)
26-
expect(subject.size).to eq 1
27-
expect(subject.first['event_id']).to eq 12345
28-
expect(subject.first['series']['url']).to eq 'https://coderdojo-okutama.connpass.com/'
29-
expect(subject.first['series']['id']).to eq 9876
22+
expect(subject).to be_a(Array)
23+
expect(subject.size).to eq 4
3024
end
3125
end
3226

33-
context 'when multiple series_ids are given' do
34-
subject { described_class.new.fetch_events(series_id: [9876, 9877]) }
27+
context 'when multiple group_ids are given' do
28+
subject { described_class.new.fetch_events(group_id: [9876, 9877]) }
3529

3630
it do
37-
expect(subject).to be_instance_of(Array)
38-
expect(subject.size).to eq 2
39-
expect(subject.first['event_id']).to eq 12345
40-
expect(subject.first['series']['url']).to eq 'https://coderdojo-okutama.connpass.com/'
41-
expect(subject.first['series']['id']).to eq 9876
42-
expect(subject.second['event_id']).to eq 12346 # assuming the second event has id 12346
43-
expect(subject.second['series']['url']).to eq 'https://coderdojo-okutama2.connpass.com/'
44-
expect(subject.second['series']['id']).to eq 9877
31+
expect(subject).to be_a(Array)
32+
expect(subject.size).to eq 5
4533
end
4634
end
4735
end

spec/lib/statistics/aggregation_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
subject { Statistics::Aggregation.new(from: Time.zone.today.prev_month.strftime('%Y%m')).run }
3333

3434
it do
35-
expect{ subject }.to change{ EventHistory.count }.from(0).to(3)
35+
expect{ subject }.to change{ EventHistory.count }.from(0).to(2)
3636
end
3737
end
3838

spec/rails_helper.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# This file is copied to spec/ when you run 'rails generate rspec:install'
22
ENV['RAILS_ENV'] ||= 'test'
3+
ENV['CONNPASS_API_KEY'] = 'DUMMY_CONNPASS_API_KEY'
34
require File.expand_path('../../config/environment', __FILE__)
45
# Prevent database truncation if the environment is production
56
abort("The Rails environment is running in production mode!") if Rails.env.production?

0 commit comments

Comments
 (0)