Skip to content

Commit 24066cf

Browse files
authored
Merge pull request #247 from yskkin/statistics
Add custom aggregation units API
2 parents 12c5127 + be6ff2c commit 24066cf

File tree

2 files changed

+211
-0
lines changed

2 files changed

+211
-0
lines changed

lib/line/bot/client.rb

+39
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,45 @@ def update_audience_authority_level(authority_level)
999999
put(endpoint, endpoint_path, body.to_json, credentials)
10001000
end
10011001

1002+
# Get the per-unit statistics of how users interact with push messages and multicast messages.
1003+
#
1004+
# @param unit [String] Case-sensitive name of aggregation unit specified when sending the message.
1005+
# @param from [String] Start date of aggregation period in UTC+9 with `yyyyMMdd` format
1006+
# @param to [String] End date of aggregation period in UTC+9 with `yyyyMMdd` format.
1007+
#
1008+
# @return [Net::HTTPResponse]
1009+
def get_statistics_per_unit(unit:, from:, to:)
1010+
channel_token_required
1011+
1012+
params = {customAggregationUnit: unit, from: from, to: to}
1013+
endpoint_path = "/bot/insight/message/event/aggregation?" + URI.encode_www_form(params)
1014+
get(endpoint, endpoint_path, credentials)
1015+
end
1016+
1017+
# Get the number of aggregation units used this month.
1018+
#
1019+
# @return [Net::HTTPResponse]
1020+
def get_aggregation_info
1021+
channel_token_required
1022+
1023+
endpoint_path = "/bot/message/aggregation/info"
1024+
get(endpoint, endpoint_path, credentials)
1025+
end
1026+
1027+
# Get the name list of units used this month for statistics aggregation.
1028+
#
1029+
# @param limit [Integer] Maximum number of aggregation units per request. Maximum: 100, Default: 100.
1030+
# @param start [String] Value of the continuation token found in the `next` property of the JSON object returned in the response.
1031+
#
1032+
# @return [Net::HTTPResponse]
1033+
def get_aggregation_list(limit: nil, start: nil)
1034+
channel_token_required
1035+
1036+
params = {limit: limit, start: start}.compact
1037+
endpoint_path = "/bot/message/aggregation/list?" + URI.encode_www_form(params)
1038+
get(endpoint, endpoint_path, credentials)
1039+
end
1040+
10021041
# Fetch data, get content of specified URL.
10031042
#
10041043
# @param endpoint_base [String]
+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
require 'spec_helper'
2+
require 'webmock/rspec'
3+
require 'json'
4+
5+
STATISTICS_CONTENT = <<~"EOS"
6+
{
7+
"overview": {
8+
"uniqueImpression": 40,
9+
"uniqueClick": 30,
10+
"uniqueMediaPlayed": 25,
11+
"uniqueMediaPlayed100Percent": null
12+
},
13+
"messages": [
14+
{
15+
"seq": 1,
16+
"impression": 42,
17+
"mediaPlayed": 30,
18+
"mediaPlayed25Percent": null,
19+
"mediaPlayed50Percent": null,
20+
"mediaPlayed75Percent": null,
21+
"mediaPlayed100Percent": null,
22+
"uniqueMediaPlayed": 25,
23+
"uniqueMediaPlayed25Percent": null,
24+
"uniqueMediaPlayed50Percent": null,
25+
"uniqueMediaPlayed75Percent": null,
26+
"uniqueMediaPlayed100Percent": null
27+
}
28+
],
29+
"clicks": [
30+
{
31+
"seq": 1,
32+
"url": "https://developers.line.biz/",
33+
"click": 35,
34+
"uniqueClick": 25,
35+
"uniqueClickOfRequest": null
36+
},
37+
{
38+
"seq": 1,
39+
"url": "https://www.line-community.me/",
40+
"click": 29,
41+
"uniqueClick": null,
42+
"uniqueClickOfRequest": null
43+
}
44+
]
45+
}
46+
EOS
47+
48+
INFO_CONTENT = <<~"EOS"
49+
{
50+
"numOfCustomAggregationUnits": 22
51+
}
52+
EOS
53+
54+
UNIT_CONTENT = <<~"EOS"
55+
{
56+
"customAggregationUnits": [
57+
"test1",
58+
"test2",
59+
"test3"
60+
],
61+
"next": "jxEWCEEP"
62+
}
63+
EOS
64+
65+
NEXT_UNIT_CONTENT = <<~"EOS"
66+
{
67+
"customAggregationUnits": [
68+
"test4",
69+
"test5",
70+
"test6"
71+
]
72+
}
73+
EOS
74+
75+
LIMITED_UNIT_CONTENT = <<~"EOS"
76+
{
77+
"customAggregationUnits": [
78+
"test7",
79+
"test8"
80+
]
81+
}
82+
EOS
83+
84+
describe Line::Bot::Client do
85+
def dummy_config
86+
{
87+
channel_token: 'access token',
88+
}
89+
end
90+
91+
def generate_client
92+
client = Line::Bot::Client.new do |config|
93+
config.channel_token = dummy_config[:channel_token]
94+
end
95+
96+
client
97+
end
98+
99+
it 'gets statistics per unit' do
100+
uri_template = Addressable::Template.new Line::Bot::API::DEFAULT_ENDPOINT + '/bot/insight/message/event/aggregation?customAggregationUnit=test_unit&from=20220101&to=20220131'
101+
stub_request(:get, uri_template).to_return { |request| {body: STATISTICS_CONTENT, status: 200} }
102+
103+
client = generate_client
104+
response = client.get_statistics_per_unit(unit: 'test_unit', from: '20220101', to: '20220131')
105+
106+
expect(response).to be_a(Net::HTTPOK)
107+
result = JSON.parse(response.body)
108+
expect(result).to eq JSON.parse(STATISTICS_CONTENT)
109+
end
110+
111+
it 'gets number of units' do
112+
uri_template = Addressable::Template.new Line::Bot::API::DEFAULT_ENDPOINT + '/bot/message/aggregation/info'
113+
stub_request(:get, uri_template).to_return { |request| {body: INFO_CONTENT, status: 200} }
114+
115+
client = generate_client
116+
response = client.get_aggregation_info
117+
118+
expect(response).to be_a(Net::HTTPOK)
119+
result = JSON.parse(response.body)
120+
expect(result).to eq JSON.parse(INFO_CONTENT)
121+
end
122+
123+
it 'gets unit names' do
124+
uri_template = Addressable::Template.new Line::Bot::API::DEFAULT_ENDPOINT + '/bot/message/aggregation/list'
125+
stub_request(:get, uri_template).to_return { |request| {body: UNIT_CONTENT, status: 200} }
126+
127+
uri_template = Addressable::Template.new Line::Bot::API::DEFAULT_ENDPOINT + '/bot/message/aggregation/list?start={start}'
128+
stub_request(:get, uri_template).to_return { |request| {body: NEXT_UNIT_CONTENT, status: 200} }
129+
130+
client = generate_client
131+
132+
# first page
133+
response = client.get_aggregation_list
134+
135+
expect(response).to be_a(Net::HTTPOK)
136+
result = JSON.parse(response.body)
137+
expect(result['customAggregationUnits']).to eq ["test1", "test2", "test3"]
138+
expect(result['next']).to eq "jxEWCEEP"
139+
140+
# second page
141+
response = client.get_aggregation_list(start: result['next'])
142+
143+
expect(response).to be_a(Net::HTTPOK)
144+
result = JSON.parse(response.body)
145+
expect(result['customAggregationUnits']).to eq ["test4", "test5", "test6"]
146+
expect(result['next']).to be nil
147+
end
148+
149+
it 'gets limited number of unit names' do
150+
# without any other conditions
151+
uri_template = Addressable::Template.new Line::Bot::API::DEFAULT_ENDPOINT + '/bot/message/aggregation/list?limit={limit}'
152+
stub_request(:get, uri_template).to_return { |request| {body: LIMITED_UNIT_CONTENT, status: 200} }
153+
154+
# with other conditions
155+
uri_template = Addressable::Template.new Line::Bot::API::DEFAULT_ENDPOINT + '/bot/message/aggregation/list?limit={limit}&start={start}'
156+
stub_request(:get, uri_template).to_return { |request| {body: LIMITED_UNIT_CONTENT, status: 200} }
157+
158+
client = generate_client
159+
160+
# without any other conditions
161+
response = client.get_aggregation_list(limit: 2)
162+
result = JSON.parse(response.body)
163+
expect(response).to be_a(Net::HTTPOK)
164+
expect(result['customAggregationUnits']).to eq ["test7", "test8"]
165+
166+
# with other conditions
167+
response = client.get_aggregation_list(start: 'foo', limit: 2)
168+
result = JSON.parse(response.body)
169+
expect(response).to be_a(Net::HTTPOK)
170+
expect(result['customAggregationUnits']).to eq ["test7", "test8"]
171+
end
172+
end

0 commit comments

Comments
 (0)