Skip to content

Commit 354a3f5

Browse files
author
Hyunje Jun
authored
Merge pull request #23 from line/get-member-ids-api
Implement "Group/Room Member IDs" API
2 parents 0e2e825 + 57fafe4 commit 354a3f5

File tree

5 files changed

+162
-7
lines changed

5 files changed

+162
-7
lines changed

docs/pages/api-reference/client.md

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ class Client {
1515
replyMessage(replyToken: string, messages: Message | Message[]): Promise<{}>
1616
multicast(to: string[], messages: Message | Message[]): Promise<{}>
1717
getProfile(userId: string): Promise<Profile>
18+
getGroupMemberProfile(groupId: string, userId: string): Promise<Profile>
19+
getRoomMemberProfile(roomId: string, userId: string): Promise<Profile>
20+
getGroupMemberIds(groupId: string): Promise<string[]>
21+
getRoomMemberIds(roomId: string): Promise<string[]>
1822
getMessageContent(messageId: string): Promise<ReadableStream>
1923
leaveGroup(groupId: string): Promise<{}>
2024
leaveRoom(roomId: string): Promise<{}>
@@ -23,7 +27,7 @@ class Client {
2327

2428
`Message` is a valid message object. About message object structure, please
2529
refer to [Send message object](https://devdocs.line.me/en/#send-message-object)
26-
of the official document.
30+
of the official documentation.
2731

2832
`ClientConfig` type is like below, except that it also allows fields
2933
from [MiddlewareConfig](./middleware.md) too.
@@ -39,7 +43,7 @@ type ClientConfig = {
3943
For a parameter `messages: messages: Message | Message[]`, you can provide a
4044
message object or an array of message objects. Both will work, but please beware
4145
that there can be a limit on the number of the messages to be sent
42-
simultaneously. About the API detail, please refer to [the official document](https://devdocs.line.me/en/#messaging-api).
46+
simultaneously. About the API detail, please refer to [the official documentation](https://devdocs.line.me/en/#messaging-api).
4347
4448
For functions returning `Promise`, there will be errors thrown if something
4549
goes wrong, such as HTTP errors or parsing errors. You can catch them with the
@@ -65,7 +69,7 @@ It corresponds to the [Reply message](https://devdocs.line.me/en/#reply-message)
6569
6670
The first argument is a reply token, which is retrieved from a webhook event
6771
object. For the list of replyable events, please refer to [Webhook event object](https://devdocs.line.me/en/#webhook-event-object)
68-
of the official document. The second argument is the same with one in `pushMessage()`.
72+
of the official documentation. The second argument is the same with one in `pushMessage()`.
6973
7074
``` js
7175
client.replyMessage(event.replyToken, {
@@ -100,6 +104,64 @@ client.getProfile('user_id').then((profile) => {
100104
});
101105
```
102106

107+
### `getGroupMemberProfile(groupId: string, userId: string): Promise<Profile>`
108+
109+
It corresponds to the [Group/Room Member Profile](https://devdocs.line.me/en/#get-group-room-member-profile) API.
110+
111+
*FYI: This feature is only available for LINE@ Approved accounts or official accounts.*
112+
113+
The arguments are a group ID and an ID of a user in the group. Please refer to
114+
the official documentation for the difference between this API and `getProfile()`.
115+
116+
``` js
117+
client.getGroupMemberProfile('group_id', 'user_id').then((profile) => {
118+
console.log(profile);
119+
})
120+
```
121+
122+
### `getRoomMemberProfile(roomId: string, userId: string): Promise<Profile>`
123+
124+
It corresponds to the [Group/Room Member Profile](https://devdocs.line.me/en/#get-group-room-member-profile) API.
125+
126+
*FYI: This feature is only available for LINE@ Approved accounts or official accounts.*
127+
128+
The arguments are a room ID and an ID of a user in the room. Please refer to the
129+
official documentation for the difference between this API and `getProfile()`.
130+
131+
``` js
132+
client.getRoomMemberProfile('room_id', 'user_id').then((profile) => {
133+
console.log(profile);
134+
})
135+
```
136+
137+
### `getGroupMemberIds(groupId: string): Promise<string[]>`
138+
139+
It corresponds to the [Group/Room Member IDs](https://devdocs.line.me/en/#get-group-room-member-ids) API.
140+
141+
*FYI: This feature is only available for LINE@ Approved accounts or official accounts.*
142+
143+
The argument is a group ID and the method returns a promise of an array of user IDs.
144+
145+
``` js
146+
client.getGroupMemberIds('group_id').then((ids) => {
147+
ids.forEach((id) => console.log(id));
148+
})
149+
```
150+
151+
### `getRoomMemberIds(roomId: string): Promise<string[]>`
152+
153+
It corresponds to the [Group/Room Member IDs](https://devdocs.line.me/en/#get-group-room-member-ids) API.
154+
155+
*FYI: This feature is only available for LINE@ Approved accounts or official accounts.*
156+
157+
The argument is a room ID and the method returns a promise of an array of user IDs.
158+
159+
``` js
160+
client.getRoomMemberIds('room_id').then((ids) => {
161+
ids.forEach((id) => console.log(id));
162+
})
163+
```
164+
103165
### `getMessageContent(messageId: string): Promise<ReadableStream>`
104166

105167
It corresponds to the [Content](https://devdocs.line.me/en/#content) API.

lib/client.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,32 @@ export default class Client {
4646
return this.get(URL.roomMemberProfile(roomId, userId));
4747
}
4848

49+
public getGroupMemberIds(groupId: string): Promise<string[]> {
50+
const load = (start?: string): Promise<string[]> =>
51+
this.get(URL.groupMemberIds(groupId, start))
52+
.then((res: { memberIds: string[], next?: string }) => {
53+
if (!res.next) {
54+
return res.memberIds;
55+
}
56+
57+
return load(res.next).then((extraIds) => res.memberIds.concat(extraIds));
58+
});
59+
return load();
60+
}
61+
62+
public getRoomMemberIds(roomId: string): Promise<string[]> {
63+
const load = (start?: string): Promise<string[]> =>
64+
this.get(URL.roomMemberIds(roomId, start))
65+
.then((res: { memberIds: string[], next?: string }) => {
66+
if (!res.next) {
67+
return res.memberIds;
68+
}
69+
70+
return load(res.next).then((extraIds) => res.memberIds.concat(extraIds));
71+
});
72+
return load();
73+
}
74+
4975
public getMessageContent(messageId: string): Promise<NodeJS.ReadableStream> {
5076
return this.stream(URL.content(messageId));
5177
}

lib/urls.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,33 @@
1+
import * as qs from "querystring";
2+
13
const baseURL: string = process.env.API_BASE_URL || "https://api.line.me/v2/bot/";
24

3-
const apiURL = (path: string) => baseURL + path;
5+
const apiURL = (path: string, query?: object) =>
6+
baseURL + path + (query ? `?${qs.stringify(query)}` : "");
47

58
export const reply: string = apiURL("message/reply");
9+
610
export const push: string = apiURL("message/push");
11+
712
export const multicast: string = apiURL("message/multicast");
8-
export const content = (messageId: string) => apiURL(`message/${messageId}/content`);
13+
14+
export const content = (messageId: string) =>
15+
apiURL(`message/${messageId}/content`);
16+
917
export const profile = (userId: string) => apiURL(`profile/${userId}`);
10-
export const groupMemberProfile = (groupId: string, userId: string) => apiURL(`group/${groupId}/member/${userId}`);
11-
export const roomMemberProfile = (roomId: string, userId: string) => apiURL(`room/${roomId}/member/${userId}`);
18+
19+
export const groupMemberProfile = (groupId: string, userId: string) =>
20+
apiURL(`group/${groupId}/member/${userId}`);
21+
22+
export const roomMemberProfile = (roomId: string, userId: string) =>
23+
apiURL(`room/${roomId}/member/${userId}`);
24+
25+
export const groupMemberIds = (groupId: string, start?: string) =>
26+
apiURL(`group/${groupId}/members/ids`, start ? { start } : null);
27+
28+
export const roomMemberIds = (roomId: string, start?: string) =>
29+
apiURL(`room/${roomId}/members/ids`, start ? { start } : null);
30+
1231
export const leaveGroup = (groupId: string) => apiURL(`group/${groupId}/leave`);
32+
1333
export const leaveRoom = (roomId: string) => apiURL(`room/${roomId}/leave`);

test/client.spec.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,36 @@ describe("client", () => {
7777
});
7878
});
7979

80+
it("getGroupMemberIds", () => {
81+
return client.getGroupMemberIds("test_group_id")
82+
.then((ids) => deepEqual(ids, [
83+
"group-test_group_id-0",
84+
"group-test_group_id-1",
85+
"group-test_group_id-2",
86+
"group-test_group_id-3",
87+
"group-test_group_id-4",
88+
"group-test_group_id-5",
89+
"group-test_group_id-6",
90+
"group-test_group_id-7",
91+
"group-test_group_id-8",
92+
]));
93+
});
94+
95+
it("getRoomMemberIds", () => {
96+
return client.getRoomMemberIds("test_room_id")
97+
.then((ids) => deepEqual(ids, [
98+
"room-test_room_id-0",
99+
"room-test_room_id-1",
100+
"room-test_room_id-2",
101+
"room-test_room_id-3",
102+
"room-test_room_id-4",
103+
"room-test_room_id-5",
104+
"room-test_room_id-6",
105+
"room-test_room_id-7",
106+
"room-test_room_id-8",
107+
]));
108+
});
109+
80110
it("getMessageContent", () => {
81111
return client.getMessageContent("test_message_id")
82112
.then((s) => getStreamData(s))

test/helpers/test-server.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,23 @@ function listen(port: number, middleware?: express.RequestHandler) {
2727

2828
app.use(bodyParser.json());
2929

30+
// for getIds API
31+
app.get("/:groupOrRoom/:id/members/ids", (req, res) => {
32+
const ty: string = req.params.groupOrRoom;
33+
const id: string = req.params.id;
34+
const start: number = parseInt(req.query.start, 10) || 0;
35+
36+
const result: { memberIds: string[], next?: string } = {
37+
memberIds: [start, start + 1, start + 2].map((i) => `${ty}-${id}-${i}`),
38+
};
39+
40+
if (start / 3 < 2) {
41+
result.next = String(start + 3);
42+
}
43+
44+
res.json(result);
45+
});
46+
3047
app.use((req: express.Request, res) => {
3148
if (req.path === "/stream.txt") {
3249
res.sendFile(join(__dirname, "stream.txt"));

0 commit comments

Comments
 (0)