From 01e7ad61391e5ab969e4a3cda17cdd02f05d3d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=82=85=E4=B8=9C=E6=B5=B7?= <296322762@qq.com> Date: Mon, 9 Sep 2024 11:39:59 +0800 Subject: [PATCH] Add presence function --- dependency-reduced-pom.xml | 404 ++++++++++++++++++ .../im/server/api/presence/PresenceIT.java | 192 +++++++++ .../java/com/easemob/im/server/EMService.java | 20 + .../im/server/api/presence/PresenceApi.java | 186 ++++++++ .../presence/PresenceSubscribeResource.java | 28 ++ .../presence/PresenceUserStatusResource.java | 46 ++ .../PresenceUserStatusSubscribeResource.java | 55 +++ .../get/PresenceUserStatusGetRequest.java | 21 + .../get/PresenceUserStatusGetResponse.java | 22 + .../api/presence/get/UserStatusGet.java | 47 ++ .../PresenceUserOnlineCountResponse.java | 19 + .../presence/online/UserOnlineCountGet.java | 41 ++ .../set/PresenceUserStatusSetRequest.java | 21 + .../api/presence/set/UserStatusSet.java | 46 ++ ...nceUserStatusSubscribeListGetResponse.java | 19 + .../PresenceUserStatusSubscribeRequest.java | 21 + .../PresenceUserStatusSubscribeResponse.java | 22 + .../PresenceUserStatusSubscribeResult.java | 31 ++ .../subscribe/UserStatusSubscribe.java | 45 ++ .../subscribe/UserStatusSubscribeListGet.java | 41 ++ .../subscribe/UserStatusUnSubscribe.java | 42 ++ 21 files changed, 1369 insertions(+) create mode 100644 dependency-reduced-pom.xml create mode 100644 im-sdk-core/src/integration-test/java/com/easemob/im/server/api/presence/PresenceIT.java create mode 100644 im-sdk-core/src/main/java/com/easemob/im/server/api/presence/PresenceApi.java create mode 100644 im-sdk-core/src/main/java/com/easemob/im/server/api/presence/PresenceSubscribeResource.java create mode 100644 im-sdk-core/src/main/java/com/easemob/im/server/api/presence/PresenceUserStatusResource.java create mode 100644 im-sdk-core/src/main/java/com/easemob/im/server/api/presence/PresenceUserStatusSubscribeResource.java create mode 100644 im-sdk-core/src/main/java/com/easemob/im/server/api/presence/get/PresenceUserStatusGetRequest.java create mode 100644 im-sdk-core/src/main/java/com/easemob/im/server/api/presence/get/PresenceUserStatusGetResponse.java create mode 100644 im-sdk-core/src/main/java/com/easemob/im/server/api/presence/get/UserStatusGet.java create mode 100644 im-sdk-core/src/main/java/com/easemob/im/server/api/presence/online/PresenceUserOnlineCountResponse.java create mode 100644 im-sdk-core/src/main/java/com/easemob/im/server/api/presence/online/UserOnlineCountGet.java create mode 100644 im-sdk-core/src/main/java/com/easemob/im/server/api/presence/set/PresenceUserStatusSetRequest.java create mode 100644 im-sdk-core/src/main/java/com/easemob/im/server/api/presence/set/UserStatusSet.java create mode 100644 im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/PresenceUserStatusSubscribeListGetResponse.java create mode 100644 im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/PresenceUserStatusSubscribeRequest.java create mode 100644 im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/PresenceUserStatusSubscribeResponse.java create mode 100644 im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/PresenceUserStatusSubscribeResult.java create mode 100644 im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/UserStatusSubscribe.java create mode 100644 im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/UserStatusSubscribeListGet.java create mode 100644 im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/UserStatusUnSubscribe.java diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml new file mode 100644 index 000000000..e8d876d73 --- /dev/null +++ b/dependency-reduced-pom.xml @@ -0,0 +1,404 @@ + + + 4.0.0 + com.easemob.im + im-sdk-core + im-sdk-core + 1.0.9 + OpenAPI Java + https://github.com/openapitools/openapi-generator + + + fudonghai + fudonghai@easemob.com + https://github.com/fudonghai + + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + scm:git:git@github.com:easemob/easemob-im-server-sdk.git + scm:git:git@github.com:easemob/easemob-im-server-sdk.git + https://github.com/easemob/easemob-im-server-sdk/tree/master_java_2.0 + + + + + META-INF + ${project.basedir} + + LICENSE + + + + ${project.basedir}/src/main/resources + + + + + maven-shade-plugin + 3.2.4 + + + package + + shade + + + + + com.google.code.gson + io.gsonfire + com.squareup.okhttp3 + com.squareup.okio + org.jetbrains.kotlin + org.apache.commons + com.google.guava + + + + + com.google.gson + shaded.com.google.gson + + + io.gsonfire + shaded.io.gsonfire + + + okhttp3 + shaded.okhttp3 + + + okio + shaded.okio + + + kotlin + shaded.kotlin + + + org + shaded.org + + + + + + + + maven-compiler-plugin + 3.8.1 + + + -Xlint:all + -Xlint:-options + -Xlint:-processing + -Xlint:-serial + + true + ${java.version} + ${java.version} + + + + maven-jar-plugin + 3.2.0 + + + + true + true + + + + + + maven-deploy-plugin + 2.8.2 + + + maven-enforcer-plugin + 3.0.0-M3 + + + enforce-no-snapshots + + enforce + + + + + true + No Snapshots in releases allowed! + + + + + + + + maven-surefire-plugin + 2.22.2 + + random + **/*Test.java + + + + maven-source-plugin + 3.2.1 + + + attach-sources + + jar + + + + + + maven-javadoc-plugin + 3.2.0 + + + attach-javadocs + + jar + + + + + UTF-8 + UTF-8 + UTF-8 + + + + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + + + --pinentry-mode + loopback + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.7.0 + true + + ossrh-releases + https://oss.sonatype.org/ + true + + + + maven-release-plugin + 2.5.3 + + + maven-site-plugin + 3.7.1 + + + maven-project-info-reports-plugin + 3.0.0 + + + org.jacoco + jacoco-maven-plugin + 0.8.6 + + + + prepare-agent + + + + report + test + + report + + + + + + + + + ci + + + + maven-gpg-plugin + 1.6 + + + sign-artifacts + none + + + + + + + + + + com.google.code.findbugs + jsr305 + 3.0.2 + compile + + + jakarta.annotation + jakarta.annotation-api + 1.3.5 + provided + + + org.openapitools + jackson-databind-nullable + 0.2.6 + compile + + + javax.ws.rs + jsr311-api + 1.1.1 + compile + + + javax.ws.rs + javax.ws.rs-api + 2.1.1 + compile + + + org.junit.jupiter + junit-jupiter-engine + 5.10.0 + test + + + junit-platform-engine + org.junit.platform + + + junit-jupiter-api + org.junit.jupiter + + + apiguardian-api + org.apiguardian + + + + + org.junit.platform + junit-platform-runner + 1.10.0 + test + + + junit + junit + + + junit-platform-launcher + org.junit.platform + + + junit-platform-suite-api + org.junit.platform + + + junit-platform-suite-commons + org.junit.platform + + + apiguardian-api + org.apiguardian + + + + + + + + com.squareup.okhttp3 + okhttp-bom + ${okhttp-version} + pom + import + + + com.squareup.okhttp3 + logging-interceptor + ${okhttp-version} + + + com.google.code.gson + gson + ${gson-version} + + + org.apache.commons + commons-lang3 + ${commons-lang3-version} + + + com.google.guava + guava + ${google-guava-version} + + + + + + ossrh-releases + Nexus Release Repository + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + ossrh-snapshots + Nexus Snapshot Repository + https://oss.sonatype.org/content/repositories/snapshots/ + + + + 0.2.6 + 1.8 + 30.0-jre + 5.10.0 + 2.1.1 + ${java.version} + 2.10.1 + 1.1.1 + 3.5 + 2.27.2 + UTF-8 + 1.3.5 + 1.10.0 + 4.11.0 + 1.9.0 + ${java.version} + + diff --git a/im-sdk-core/src/integration-test/java/com/easemob/im/server/api/presence/PresenceIT.java b/im-sdk-core/src/integration-test/java/com/easemob/im/server/api/presence/PresenceIT.java new file mode 100644 index 000000000..ea2dac57a --- /dev/null +++ b/im-sdk-core/src/integration-test/java/com/easemob/im/server/api/presence/PresenceIT.java @@ -0,0 +1,192 @@ +package com.easemob.im.server.api.presence; + +import com.easemob.im.server.api.AbstractIT; +import com.easemob.im.server.api.presence.subscribe.PresenceUserStatusSubscribeResult; +import com.easemob.im.server.api.util.Utilities; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; + +public class PresenceIT extends AbstractIT { + + PresenceIT() {super();} + + @Test + void testGetUserStatus() { + String randomUsername = Utilities.randomUserName(); + String randomPassword = Utilities.randomPassword(); + String resource = "ios_100000"; + String status = "1"; + String ext = "在线"; + + assertDoesNotThrow(() -> this.service.user().create(randomUsername, randomPassword) + .block(Utilities.IT_TIMEOUT)); + + assertDoesNotThrow(() -> this.service.presence().setUserStatus(randomUsername, resource, status, ext) + .block(Utilities.IT_TIMEOUT)); + + List userStatusList = assertDoesNotThrow(() -> this.service.presence().getUserStatus("u1", Arrays.asList(randomUsername)) + .block(Utilities.IT_TIMEOUT)); + assertNotNull(userStatusList); + + userStatusList.forEach(userStatus -> { + Map us = (Map) userStatus.getStatus(); + assertEquals(status, us.get(resource)); + assertEquals(ext, userStatus.getExt()); + }); + + List userStatusList1 = assertDoesNotThrow(() -> this.service.presence().getUserStatus("u1", Arrays.asList("u10000")) + .block(Utilities.IT_TIMEOUT)); + assertNotNull(userStatusList1); + + userStatusList1.forEach(userStatus -> { + List us = (List) userStatus.getStatus(); + assertEquals(0, us.size()); + }); + + assertDoesNotThrow(() -> this.service.user().delete(randomUsername) + .block(Utilities.IT_TIMEOUT)); + } + + @Test + void testSubscribeUserStatus() throws InterruptedException { + String randomUsername1 = Utilities.randomUserName(); + String randomUsername2 = Utilities.randomUserName(); + String randomUsername3 = Utilities.randomUserName(); + String randomPassword = Utilities.randomPassword(); + String resource = "ios_100000"; + String status = "1"; + String ext = "在线"; + + assertDoesNotThrow(() -> this.service.user().create(randomUsername1, randomPassword) + .block(Utilities.IT_TIMEOUT)); + assertDoesNotThrow(() -> this.service.user().create(randomUsername2, randomPassword) + .block(Utilities.IT_TIMEOUT)); + + assertDoesNotThrow(() -> this.service.presence().setUserStatus(randomUsername1, resource, status, ext) + .block(Utilities.IT_TIMEOUT)); + assertDoesNotThrow(() -> this.service.presence().setUserStatus(randomUsername2, resource, status, ext) + .block(Utilities.IT_TIMEOUT)); + + List subscribeUserStatusList = assertDoesNotThrow(() -> this.service.presence().subscribeUserStatus(randomUsername3, Arrays.asList(randomUsername1, randomUsername2), 86400L) + .block(Utilities.IT_TIMEOUT)); + assertNotNull(subscribeUserStatusList); + assertEquals(2, subscribeUserStatusList.size()); + + Thread.sleep(10000); + + PresenceUserStatusSubscribeResult + subscribeResult = assertDoesNotThrow(() -> this.service.presence().getSubscribeList(randomUsername3, 1, 10) + .block(Utilities.IT_TIMEOUT)); + assertNotNull(subscribeResult); + assertNotNull(subscribeResult.getSubscribeResourceList()); + assertEquals("2", subscribeResult.getTotalNumber()); + + assertDoesNotThrow(() -> this.service.user().delete(randomUsername1) + .block(Utilities.IT_TIMEOUT)); + assertDoesNotThrow(() -> this.service.user().delete(randomUsername2) + .block(Utilities.IT_TIMEOUT)); + assertDoesNotThrow(() -> this.service.user().delete(randomUsername3) + .block(Utilities.IT_TIMEOUT)); + } + + @Test + void testUnsubscribeUserStatus() throws InterruptedException { + String randomUsername1 = Utilities.randomUserName(); + String randomUsername2 = Utilities.randomUserName(); + String randomPassword = Utilities.randomPassword(); + String resource = "ios_100000"; + String status = "1"; + String ext = "在线"; + + assertDoesNotThrow(() -> this.service.user().create(randomUsername1, randomPassword) + .block(Utilities.IT_TIMEOUT)); + assertDoesNotThrow(() -> this.service.user().create(randomUsername2, randomPassword) + .block(Utilities.IT_TIMEOUT)); + + assertDoesNotThrow(() -> this.service.presence().setUserStatus(randomUsername1, resource, status, ext) + .block(Utilities.IT_TIMEOUT)); + + assertDoesNotThrow(() -> this.service.presence().subscribeUserStatus(randomUsername2, Arrays.asList(randomUsername1), 86400L) + .block(Utilities.IT_TIMEOUT)); + + Thread.sleep(10000); + + PresenceUserStatusSubscribeResult + subscribeResult = assertDoesNotThrow(() -> this.service.presence().getSubscribeList(randomUsername2, 1, 10) + .block(Utilities.IT_TIMEOUT)); + assertNotNull(subscribeResult); + assertNotNull(subscribeResult.getSubscribeResourceList()); + assertEquals("1", subscribeResult.getTotalNumber()); + + subscribeResult.getSubscribeResourceList().forEach(subscribeResource -> { + assertEquals(randomUsername1, subscribeResource.getUid()); + }); + + assertDoesNotThrow(() -> this.service.presence().unsubscribeUserStatus(randomUsername2, Arrays.asList(randomUsername1)) + .block(Utilities.IT_TIMEOUT)); + + Thread.sleep(10000); + + PresenceUserStatusSubscribeResult + subscribeResult1 = assertDoesNotThrow(() -> this.service.presence().getSubscribeList(randomUsername2, 1, 10) + .block(Utilities.IT_TIMEOUT)); + assertNotNull(subscribeResult1); + assertEquals("0", subscribeResult1.getTotalNumber()); + + subscribeResult.getSubscribeResourceList().forEach(subscribeResource -> { + assertEquals(randomUsername1, subscribeResource.getUid()); + }); + + assertDoesNotThrow(() -> this.service.user().delete(randomUsername1) + .block(Utilities.IT_TIMEOUT)); + assertDoesNotThrow(() -> this.service.user().delete(randomUsername2) + .block(Utilities.IT_TIMEOUT)); + } + + @Test + void testGetOnlineCount() throws InterruptedException { +// String randomOwnerUsername = Utilities.randomUserName(); +// String randomPassword = Utilities.randomPassword(); +// +// String randomMemberUsername = Utilities.randomUserName(); +// List members = new ArrayList<>(); +// members.add(randomMemberUsername); +// String resource = "ios_100000"; +// String status = "1"; +// String ext = "在线"; +// +// assertDoesNotThrow(() -> this.service.user().create(randomOwnerUsername, randomPassword) +// .block(Utilities.IT_TIMEOUT)); +// assertDoesNotThrow(() -> this.service.user().create(randomMemberUsername, randomPassword) +// .block(Utilities.IT_TIMEOUT)); +// +// String groupId = assertDoesNotThrow(() -> this.service.group() +// .createPublicGroup(randomOwnerUsername, "group", "group description", members, 200, +// true).block(Utilities.IT_TIMEOUT)); +// +// assertDoesNotThrow(() -> this.service.presence().setUserStatus(randomOwnerUsername, resource, status, ext) +// .block(Utilities.IT_TIMEOUT)); +// +// assertDoesNotThrow(() -> this.service.presence().setUserStatus(randomMemberUsername, resource, status, ext) +// .block(Utilities.IT_TIMEOUT)); +// +// Thread.sleep(3000); +// +// Integer onlineCount = assertDoesNotThrow(() -> this.service.presence().getUserOnlineCount(groupId, 1) +// .block(Utilities.IT_TIMEOUT)); +// assertEquals(2, onlineCount); +// +// assertDoesNotThrow( +// () -> this.service.group().destroyGroup(groupId).block(Utilities.IT_TIMEOUT)); +// assertDoesNotThrow(() -> this.service.user().delete(randomOwnerUsername) +// .block(Utilities.IT_TIMEOUT)); +// assertDoesNotThrow(() -> this.service.user().delete(randomMemberUsername) +// .block(Utilities.IT_TIMEOUT)); + } + +} diff --git a/im-sdk-core/src/main/java/com/easemob/im/server/EMService.java b/im-sdk-core/src/main/java/com/easemob/im/server/EMService.java index a87de67fc..84c084018 100644 --- a/im-sdk-core/src/main/java/com/easemob/im/server/EMService.java +++ b/im-sdk-core/src/main/java/com/easemob/im/server/EMService.java @@ -8,6 +8,7 @@ import com.easemob.im.server.api.metadata.MetadataApi; import com.easemob.im.server.api.moderation.ModerationApi; import com.easemob.im.server.api.mute.MuteApi; +import com.easemob.im.server.api.presence.PresenceApi; import com.easemob.im.server.api.push.PushApi; import com.easemob.im.server.api.token.TokenApi; import com.easemob.im.server.api.room.RoomApi; @@ -50,6 +51,8 @@ public class EMService { private final MuteApi muteApi; + private final PresenceApi presenceApi; + public EMService(EMProperties properties) { log.debug("EMService properties: {}", properties); this.context = new DefaultContext(properties); @@ -66,6 +69,7 @@ public EMService(EMProperties properties) { this.pushApi = new PushApi(this.context); this.moderationApi = new ModerationApi(this.context); this.muteApi = new MuteApi(this.context); + this.presenceApi = new PresenceApi(this.context); } public Context getContext() { @@ -265,4 +269,20 @@ public ModerationApi moderation() { public MuteApi mute() { return this.muteApi; } + + /** + * Presence用户在线状态API. + * 支持:
+ * - 设置用户在线状态信息
+ * - 批量订阅在线状态
+ * - 批量获取在线状态信息
+ * - 查询单个群组的在线成员数量
+ * - 取消订阅多个用户的在线状态
+ * - 查询订阅列表
+ * + * @return {@code MuteApi} + */ + public PresenceApi presence() { + return this.presenceApi; + } } diff --git a/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/PresenceApi.java b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/PresenceApi.java new file mode 100644 index 000000000..978f7dba2 --- /dev/null +++ b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/PresenceApi.java @@ -0,0 +1,186 @@ +package com.easemob.im.server.api.presence; + +import com.easemob.im.server.api.Context; +import com.easemob.im.server.api.presence.get.UserStatusGet; +import com.easemob.im.server.api.presence.online.UserOnlineCountGet; +import com.easemob.im.server.api.presence.set.UserStatusSet; +import com.easemob.im.server.api.presence.subscribe.PresenceUserStatusSubscribeResult; +import com.easemob.im.server.api.presence.subscribe.UserStatusSubscribe; +import com.easemob.im.server.api.presence.subscribe.UserStatusSubscribeListGet; +import com.easemob.im.server.api.presence.subscribe.UserStatusUnSubscribe; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + * Presence 在线状态 API。 + */ +public class PresenceApi { + + private UserStatusGet userStatusGet; + + private UserStatusSet userStatusSet; + + private UserStatusSubscribe userStatusSubscribe; + + private UserStatusUnSubscribe userStatusUnSubscribe; + + private UserStatusSubscribeListGet userStatusSubscribeListGet; + + private UserOnlineCountGet userOnlineCountGet; + + public PresenceApi(Context context) { + this.userStatusGet = new UserStatusGet(context); + this.userStatusSet = new UserStatusSet(context); + this.userStatusSubscribe = new UserStatusSubscribe(context); + this.userStatusUnSubscribe = new UserStatusUnSubscribe(context); + this.userStatusSubscribeListGet = new UserStatusSubscribeListGet(context); + this.userOnlineCountGet = new UserOnlineCountGet(context); + } + + /** + * 设置用户在线状态信息。 + *

+ * API使用示例: + *

 {@code
+     * EMService service;
+     * try {
+     *     service.presence().setUserStatus("username", "resource", "1", "ext").block();
+     * } catch (EMException e) {
+     *     e.getErrorCode();
+     *     e.getMessage();
+     * }
+     * }
+ * + * @param username 设置哪个用户的在线状态信息。 + * @param resource 要设置用户在哪个设备的在线状态信息,即传入服务器分配给每个设备资源的唯一标识符,格式为 {device type}_{resource ID},其中设备类型 device type 可以是 android、ios 或 web,资源 ID resource ID 由 SDK 分配。例如,android_123423453246。 + * @param status 用户的在线状态:- 0:离线;- 1:在线;- 其它数字字符串:自定义在线状态。 + * @param ext 在线状态扩展信息。建议不超过 1024 字节。 + * @return 成功或错误 + * @see 设置用户在线状态信息 + */ + public Mono setUserStatus(String username, String resource, String status, String ext) { + return this.userStatusSet.execute(username, resource, status, ext); + } + + /** + * 批量获取在线状态信息。 + *

+ * API使用示例: + *

 {@code
+     * EMService service;
+     * try {
+     *     List usernames = Arrays.asList("test_user1", "test_user2");
+     *     List userStatus = service.presence().getUserStatus("operator", usernames).block();
+     * } catch (EMException e) {
+     *     e.getErrorCode();
+     *     e.getMessage();
+     * }
+     * }
+ * + * @param operator 操作者用户名 + * @param usernames 需要获取其在线状态的用户列表,例如 ["user1", "user2"],最多可传 100 个用户 ID。 + * @return 成功或错误 + * @see 批量获取在线状态信息 + */ + public Mono> getUserStatus(String operator, List usernames) { + return this.userStatusGet.execute(operator, usernames); + } + + /** + * 批量订阅在线状态。 + *

+ * API使用示例: + *

 {@code
+     * EMService service;
+     * try {
+     *     List usernames = Arrays.asList("test_user1", "test_user2");
+     *     List subscribeUserStatus = service.presence().subscribeUserStatus("operator", usernames, 86400).block();
+     * } catch (EMException e) {
+     *     e.getErrorCode();
+     *     e.getMessage();
+     * }
+     * }
+ * + * @param operator 为哪个用户订阅在线状态。 + * @param usernames 被订阅用户的用户 ID 数组,例如 ["user1", "user2"]。该数组最多可包含 100 个用户 ID。 + * @param expiry 订阅时长,单位为秒,最大值为 2,592,000,即 30 天。 + * @return 成功或错误 + * @see 批量订阅在线状态 + */ + public Mono> subscribeUserStatus(String operator, List usernames, Long expiry) { + return this.userStatusSubscribe.execute(operator, usernames, expiry); + } + + /** + * 取消订阅多个用户的在线状态。 + *

+ * API使用示例: + *

 {@code
+     * EMService service;
+     * try {
+     *     List usernames = Arrays.asList("test_user1", "test_user2");
+     *     service.presence().unsubscribeUserStatus("operator", usernames).block();
+     * } catch (EMException e) {
+     *     e.getErrorCode();
+     *     e.getMessage();
+     * }
+     * }
+ * + * @param operator 为哪个用户取消订阅的在线状态。 + * @param usernames 要取消订阅在线状态的用户 ID 数组,例如 ["user1", "user2"],最多可传 100 个用户 ID。 + * @return 成功或错误 + * @see 取消订阅多个用户的在线状态 + */ + public Mono unsubscribeUserStatus(String operator, List usernames) { + return this.userStatusUnSubscribe.execute(operator, usernames); + } + + /** + * 查询订阅列表。 + *

+ * API使用示例: + *

 {@code
+     * EMService service;
+     * try {
+     *     PresenceUserStatusSubscribeResult result = service.presence().getSubscribeList("operator", 1, 10).block();
+     * } catch (EMException e) {
+     *     e.getErrorCode();
+     *     e.getMessage();
+     * }
+     * }
+ * + * @param operator 查询哪个用户的订阅列表。若传入的用户 ID 不存在或未订阅其他用户的在线状态,返回空列表。 + * @param pageNum 要查询的页码。该参数的值须大于等于 1。若不传,默认值为 1。 + * @param pageSize 每页显示的订阅用户数量。取值范围为 [1,500],若不传默认值为 1。 + * @return 成功或错误 + * @see 查询订阅列表 + */ + public Mono getSubscribeList(String operator, int pageNum, int pageSize) { + return this.userStatusSubscribeListGet.execute(operator, pageNum, pageSize); + } + + /** + * 查询单个群组的在线成员数量。 + *

+ * API使用示例: + *

 {@code
+     * EMService service;
+     * try {
+     *     Integer onlineCount = service.presence().getUserOnlineCount("1324236456", 1).block();
+     * } catch (EMException e) {
+     *     e.getErrorCode();
+     *     e.getMessage();
+     * }
+     * }
+ * + * @param id 群组 ID。 + * @param type 查询类型,查询群组的在线成员数量,传 1 即可。 + * @return 成功或错误 + * @see 查询单个群组的在线成员数量 + */ + public Mono getUserOnlineCount(String id, int type) { + return this.userOnlineCountGet.execute(id, type); + } + +} diff --git a/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/PresenceSubscribeResource.java b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/PresenceSubscribeResource.java new file mode 100644 index 000000000..f05d7865b --- /dev/null +++ b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/PresenceSubscribeResource.java @@ -0,0 +1,28 @@ +package com.easemob.im.server.api.presence; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class PresenceSubscribeResource { + + @JsonProperty("uid") + private String uid; + + @JsonProperty("expiry") + private String expiry; + + @JsonCreator + public PresenceSubscribeResource(@JsonProperty("uid") String uid, + @JsonProperty("expiry") String expiry) { + this.uid = uid; + this.expiry = expiry; + } + + public String getUid() { + return uid; + } + + public String getExpiry() { + return expiry; + } +} diff --git a/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/PresenceUserStatusResource.java b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/PresenceUserStatusResource.java new file mode 100644 index 000000000..01c0d3ee9 --- /dev/null +++ b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/PresenceUserStatusResource.java @@ -0,0 +1,46 @@ +package com.easemob.im.server.api.presence; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class PresenceUserStatusResource { + + @JsonProperty("uid") + private String uid; + + @JsonProperty("last_time") + private String lastTime; + + @JsonProperty("ext") + private String ext; + + @JsonProperty("status") + private Object status; + + @JsonCreator + public PresenceUserStatusResource(@JsonProperty("uid") String uid, + @JsonProperty("last_time") String lastTime, + @JsonProperty("ext") String ext, + @JsonProperty("status") Object status) { + this.uid = uid; + this.lastTime = lastTime; + this.ext = ext; + this.status = status; + } + + public String getUid() { + return uid; + } + + public String getLastTime() { + return lastTime; + } + + public String getExt() { + return ext; + } + + public Object getStatus() { + return status; + } +} diff --git a/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/PresenceUserStatusSubscribeResource.java b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/PresenceUserStatusSubscribeResource.java new file mode 100644 index 000000000..86e29ed26 --- /dev/null +++ b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/PresenceUserStatusSubscribeResource.java @@ -0,0 +1,55 @@ +package com.easemob.im.server.api.presence; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class PresenceUserStatusSubscribeResource { + + @JsonProperty("uid") + private String uid; + + @JsonProperty("last_time") + private String lastTime; + + @JsonProperty("ext") + private String ext; + + @JsonProperty("expiry") + private String expiry; + + @JsonProperty("status") + private Object status; + + @JsonCreator + public PresenceUserStatusSubscribeResource(@JsonProperty("uid") String uid, + @JsonProperty("last_time") String lastTime, + @JsonProperty("ext") String ext, + @JsonProperty("expiry") String expiry, + @JsonProperty("status") Object status) { + this.uid = uid; + this.lastTime = lastTime; + this.ext = ext; + this.expiry = expiry; + this.status = status; + } + + public String getUid() { + return uid; + } + + public String getLastTime() { + return lastTime; + } + + public String getExt() { + return ext; + } + + public String getExpiry() { + return expiry; + } + + public Object getStatus() { + return status; + } +} diff --git a/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/get/PresenceUserStatusGetRequest.java b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/get/PresenceUserStatusGetRequest.java new file mode 100644 index 000000000..ed64a0121 --- /dev/null +++ b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/get/PresenceUserStatusGetRequest.java @@ -0,0 +1,21 @@ +package com.easemob.im.server.api.presence.get; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +public class PresenceUserStatusGetRequest { + + @JsonProperty("usernames") + private List usernames; + + @JsonCreator + public PresenceUserStatusGetRequest(@JsonProperty("usernames") List usernames) { + this.usernames = usernames; + } + + public List getUsernames() { + return usernames; + } +} diff --git a/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/get/PresenceUserStatusGetResponse.java b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/get/PresenceUserStatusGetResponse.java new file mode 100644 index 000000000..7d0f0f850 --- /dev/null +++ b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/get/PresenceUserStatusGetResponse.java @@ -0,0 +1,22 @@ +package com.easemob.im.server.api.presence.get; + +import com.easemob.im.server.api.presence.PresenceUserStatusResource; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +public class PresenceUserStatusGetResponse { + + @JsonProperty("result") + private List userStatusResources; + + @JsonCreator + public PresenceUserStatusGetResponse(@JsonProperty("result") List userStatusResources) { + this.userStatusResources = userStatusResources; + } + + public List getUserStatusResources() { + return userStatusResources; + } +} diff --git a/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/get/UserStatusGet.java b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/get/UserStatusGet.java new file mode 100644 index 000000000..42cc11251 --- /dev/null +++ b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/get/UserStatusGet.java @@ -0,0 +1,47 @@ +package com.easemob.im.server.api.presence.get; + +import com.easemob.im.server.api.Context; +import com.easemob.im.server.api.DefaultErrorMapper; +import com.easemob.im.server.api.ErrorMapper; +import com.easemob.im.server.api.presence.PresenceUserStatusResource; +import com.easemob.im.server.api.user.status.UserStatusResponse; +import com.easemob.im.server.exception.EMUnknownException; +import reactor.core.publisher.Mono; + +import java.util.List; + +public class UserStatusGet { + + private Context context; + + public UserStatusGet(Context context) { + this.context = context; + } + + public Mono> execute(String operator, List usernames) { + return this.context.getHttpClient() + .flatMap(httpClient -> httpClient + .headers(header -> header.add("Content-Type", "application/json")) + .post() + .uri(String.format("/users/%s/presence", operator)) + .send(Mono.create(sink -> sink.success(this.context.getCodec().encode(new PresenceUserStatusGetRequest(usernames))))) + .responseSingle((rsp, buf) -> { + return buf.switchIfEmpty( + Mono.error(new EMUnknownException("response is null"))) + .flatMap(byteBuf -> { + ErrorMapper mapper = new DefaultErrorMapper(); + mapper.statusCode(rsp); + mapper.checkError(byteBuf); + return Mono.just(byteBuf); + }); + })) + .map(buf -> { + PresenceUserStatusGetResponse response = + this.context.getCodec().decode(buf, PresenceUserStatusGetResponse.class); + buf.release(); + return response; + }) + .map(PresenceUserStatusGetResponse::getUserStatusResources); + } + +} diff --git a/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/online/PresenceUserOnlineCountResponse.java b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/online/PresenceUserOnlineCountResponse.java new file mode 100644 index 000000000..f2c499818 --- /dev/null +++ b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/online/PresenceUserOnlineCountResponse.java @@ -0,0 +1,19 @@ +package com.easemob.im.server.api.presence.online; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class PresenceUserOnlineCountResponse { + + @JsonProperty("result") + private Integer result; + + @JsonCreator + public PresenceUserOnlineCountResponse(@JsonProperty("result") Integer result) { + this.result = result; + } + + public Integer getResult() { + return result; + } +} diff --git a/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/online/UserOnlineCountGet.java b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/online/UserOnlineCountGet.java new file mode 100644 index 000000000..1c637541a --- /dev/null +++ b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/online/UserOnlineCountGet.java @@ -0,0 +1,41 @@ +package com.easemob.im.server.api.presence.online; + +import com.easemob.im.server.api.Context; +import com.easemob.im.server.api.DefaultErrorMapper; +import com.easemob.im.server.api.ErrorMapper; +import com.easemob.im.server.exception.EMUnknownException; +import reactor.core.publisher.Mono; + +public class UserOnlineCountGet { + + private Context context; + + public UserOnlineCountGet(Context context) { + this.context = context; + } + + public Mono execute(String id, int type) { + return this.context.getHttpClient() + .flatMap(httpClient -> httpClient + .headers(header -> header.add("Content-Type", "application/json")) + .get() + .uri(String.format("/presence/online/%s/type/%d", id, type)) + .responseSingle((rsp, buf) -> { + return buf.switchIfEmpty( + Mono.error(new EMUnknownException("response is null"))) + .flatMap(byteBuf -> { + ErrorMapper mapper = new DefaultErrorMapper(); + mapper.statusCode(rsp); + mapper.checkError(byteBuf); + return Mono.just(byteBuf); + }); + })) + .map(buf -> { + PresenceUserOnlineCountResponse response = + this.context.getCodec().decode(buf, PresenceUserOnlineCountResponse.class); + buf.release(); + return response; + }) + .map(PresenceUserOnlineCountResponse::getResult); + } +} diff --git a/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/set/PresenceUserStatusSetRequest.java b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/set/PresenceUserStatusSetRequest.java new file mode 100644 index 000000000..2628faca7 --- /dev/null +++ b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/set/PresenceUserStatusSetRequest.java @@ -0,0 +1,21 @@ +package com.easemob.im.server.api.presence.set; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +public class PresenceUserStatusSetRequest { + + @JsonProperty("ext") + private String ext; + + @JsonCreator + public PresenceUserStatusSetRequest(@JsonProperty("ext") String ext) { + this.ext = ext; + } + + public String getExt() { + return ext; + } +} diff --git a/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/set/UserStatusSet.java b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/set/UserStatusSet.java new file mode 100644 index 000000000..b87c57346 --- /dev/null +++ b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/set/UserStatusSet.java @@ -0,0 +1,46 @@ +package com.easemob.im.server.api.presence.set; + +import com.easemob.im.server.api.Context; +import com.easemob.im.server.api.DefaultErrorMapper; +import com.easemob.im.server.api.ErrorMapper; +import com.easemob.im.server.api.presence.PresenceUserStatusResource; +import com.easemob.im.server.api.presence.get.PresenceUserStatusGetRequest; +import com.easemob.im.server.api.presence.get.PresenceUserStatusGetResponse; +import com.easemob.im.server.exception.EMNotFoundException; +import com.easemob.im.server.exception.EMUnknownException; +import io.netty.util.ReferenceCounted; +import reactor.core.publisher.Mono; + +import java.util.List; + +public class UserStatusSet { + + private Context context; + + public UserStatusSet(Context context) { + this.context = context; + } + + public Mono execute(String username, String resource, String status, String ext) { + return this.context.getHttpClient() + .flatMap(httpClient -> httpClient + .headers(header -> header.add("Content-Type", "application/json")) + .post() + .uri(String.format("/users/%s/presence/%s/%s", username, resource, status)) + .send(Mono.create(sink -> sink.success(this.context.getCodec().encode(new PresenceUserStatusSetRequest(ext))))) + .responseSingle((rsp, buf) -> { + return buf.switchIfEmpty( + Mono.error(new EMUnknownException("response is null"))) + .flatMap(byteBuf -> { + ErrorMapper mapper = new DefaultErrorMapper(); + mapper.statusCode(rsp); + mapper.checkError(byteBuf); + return Mono.just(byteBuf); + }); + })) + .doOnSuccess(ReferenceCounted::release) + .onErrorResume(EMNotFoundException.class, errorIgnored -> Mono.empty()) + .then(); + } + +} diff --git a/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/PresenceUserStatusSubscribeListGetResponse.java b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/PresenceUserStatusSubscribeListGetResponse.java new file mode 100644 index 000000000..b256adef7 --- /dev/null +++ b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/PresenceUserStatusSubscribeListGetResponse.java @@ -0,0 +1,19 @@ +package com.easemob.im.server.api.presence.subscribe; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class PresenceUserStatusSubscribeListGetResponse { + + @JsonProperty("result") + private PresenceUserStatusSubscribeResult result; + + @JsonCreator + public PresenceUserStatusSubscribeListGetResponse(@JsonProperty("result") PresenceUserStatusSubscribeResult result) { + this.result = result; + } + + public PresenceUserStatusSubscribeResult getResult() { + return result; + } +} diff --git a/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/PresenceUserStatusSubscribeRequest.java b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/PresenceUserStatusSubscribeRequest.java new file mode 100644 index 000000000..df229d3cc --- /dev/null +++ b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/PresenceUserStatusSubscribeRequest.java @@ -0,0 +1,21 @@ +package com.easemob.im.server.api.presence.subscribe; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +public class PresenceUserStatusSubscribeRequest { + + @JsonProperty("usernames") + private List usernames; + + @JsonCreator + public PresenceUserStatusSubscribeRequest(@JsonProperty("usernames") List usernames) { + this.usernames = usernames; + } + + public List getUsernames() { + return usernames; + } +} diff --git a/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/PresenceUserStatusSubscribeResponse.java b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/PresenceUserStatusSubscribeResponse.java new file mode 100644 index 000000000..16933ecde --- /dev/null +++ b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/PresenceUserStatusSubscribeResponse.java @@ -0,0 +1,22 @@ +package com.easemob.im.server.api.presence.subscribe; + +import com.easemob.im.server.api.presence.PresenceUserStatusSubscribeResource; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +public class PresenceUserStatusSubscribeResponse { + + @JsonProperty("result") + private List userStatusSubscribeResources; + + @JsonCreator + public PresenceUserStatusSubscribeResponse(@JsonProperty("result") List userStatusSubscribeResources) { + this.userStatusSubscribeResources = userStatusSubscribeResources; + } + + public List getUserStatusSubscribeResources() { + return userStatusSubscribeResources; + } +} diff --git a/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/PresenceUserStatusSubscribeResult.java b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/PresenceUserStatusSubscribeResult.java new file mode 100644 index 000000000..f62829bda --- /dev/null +++ b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/PresenceUserStatusSubscribeResult.java @@ -0,0 +1,31 @@ +package com.easemob.im.server.api.presence.subscribe; + +import com.easemob.im.server.api.presence.PresenceSubscribeResource; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +public class PresenceUserStatusSubscribeResult { + + @JsonProperty("totalnum") + private String totalNumber; + + @JsonProperty("sublist") + private List subscribeResourceList; + + @JsonCreator + public PresenceUserStatusSubscribeResult(@JsonProperty("totalnum") String totalNumber, + @JsonProperty("sublist") List subscribeResourceList) { + this.totalNumber = totalNumber; + this.subscribeResourceList = subscribeResourceList; + } + + public String getTotalNumber() { + return totalNumber; + } + + public List getSubscribeResourceList() { + return subscribeResourceList; + } +} diff --git a/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/UserStatusSubscribe.java b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/UserStatusSubscribe.java new file mode 100644 index 000000000..e3202d3a9 --- /dev/null +++ b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/UserStatusSubscribe.java @@ -0,0 +1,45 @@ +package com.easemob.im.server.api.presence.subscribe; + +import com.easemob.im.server.api.Context; +import com.easemob.im.server.api.DefaultErrorMapper; +import com.easemob.im.server.api.ErrorMapper; +import com.easemob.im.server.api.presence.PresenceUserStatusSubscribeResource; +import com.easemob.im.server.exception.EMUnknownException; +import reactor.core.publisher.Mono; + +import java.util.List; + +public class UserStatusSubscribe { + + private Context context; + + public UserStatusSubscribe(Context context) { + this.context = context; + } + + public Mono> execute(String operator, List usernames, Long expiry) { + return this.context.getHttpClient() + .flatMap(httpClient -> httpClient + .headers(header -> header.add("Content-Type", "application/json")) + .post() + .uri(String.format("/users/%s/presence/%s", operator, expiry)) + .send(Mono.create(sink -> sink.success(this.context.getCodec().encode(new PresenceUserStatusSubscribeRequest(usernames))))) + .responseSingle((rsp, buf) -> { + return buf.switchIfEmpty( + Mono.error(new EMUnknownException("response is null"))) + .flatMap(byteBuf -> { + ErrorMapper mapper = new DefaultErrorMapper(); + mapper.statusCode(rsp); + mapper.checkError(byteBuf); + return Mono.just(byteBuf); + }); + })) + .map(buf -> { + PresenceUserStatusSubscribeResponse response = + this.context.getCodec().decode(buf, PresenceUserStatusSubscribeResponse.class); + buf.release(); + return response; + }) + .map(PresenceUserStatusSubscribeResponse::getUserStatusSubscribeResources); + } +} diff --git a/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/UserStatusSubscribeListGet.java b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/UserStatusSubscribeListGet.java new file mode 100644 index 000000000..10e94cffc --- /dev/null +++ b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/UserStatusSubscribeListGet.java @@ -0,0 +1,41 @@ +package com.easemob.im.server.api.presence.subscribe; + +import com.easemob.im.server.api.Context; +import com.easemob.im.server.api.DefaultErrorMapper; +import com.easemob.im.server.api.ErrorMapper; +import com.easemob.im.server.exception.EMUnknownException; +import reactor.core.publisher.Mono; + +public class UserStatusSubscribeListGet { + + private Context context; + + public UserStatusSubscribeListGet(Context context) { + this.context = context; + } + + public Mono execute(String operator, int pageNum, int pageSize) { + return this.context.getHttpClient() + .flatMap(httpClient -> httpClient + .headers(header -> header.add("Content-Type", "application/json")) + .get() + .uri(String.format("/users/%s/presence/sublist?pageNum=%d&pageSize=%d", operator, pageNum, pageSize)) + .responseSingle((rsp, buf) -> { + return buf.switchIfEmpty( + Mono.error(new EMUnknownException("response is null"))) + .flatMap(byteBuf -> { + ErrorMapper mapper = new DefaultErrorMapper(); + mapper.statusCode(rsp); + mapper.checkError(byteBuf); + return Mono.just(byteBuf); + }); + })) + .map(buf -> { + PresenceUserStatusSubscribeListGetResponse response = + this.context.getCodec().decode(buf, PresenceUserStatusSubscribeListGetResponse.class); + buf.release(); + return response; + }) + .map(PresenceUserStatusSubscribeListGetResponse::getResult); + } +} diff --git a/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/UserStatusUnSubscribe.java b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/UserStatusUnSubscribe.java new file mode 100644 index 000000000..2dc4ea9c8 --- /dev/null +++ b/im-sdk-core/src/main/java/com/easemob/im/server/api/presence/subscribe/UserStatusUnSubscribe.java @@ -0,0 +1,42 @@ +package com.easemob.im.server.api.presence.subscribe; + +import com.easemob.im.server.api.Context; +import com.easemob.im.server.api.DefaultErrorMapper; +import com.easemob.im.server.api.ErrorMapper; +import com.easemob.im.server.exception.EMNotFoundException; +import com.easemob.im.server.exception.EMUnknownException; +import io.netty.util.ReferenceCounted; +import reactor.core.publisher.Mono; + +import java.util.List; + +public class UserStatusUnSubscribe { + + private Context context; + + public UserStatusUnSubscribe(Context context) { + this.context = context; + } + + public Mono execute(String operator, List usernames) { + return this.context.getHttpClient() + .flatMap(httpClient -> httpClient + .headers(header -> header.add("Content-Type", "application/json")) + .delete() + .uri(String.format("/users/%s/presence", operator)) + .send(Mono.create(sink -> sink.success(this.context.getCodec().encode(usernames)))) + .responseSingle((rsp, buf) -> { + return buf.switchIfEmpty( + Mono.error(new EMUnknownException("response is null"))) + .flatMap(byteBuf -> { + ErrorMapper mapper = new DefaultErrorMapper(); + mapper.statusCode(rsp); + mapper.checkError(byteBuf); + return Mono.just(byteBuf); + }); + })) + .doOnSuccess(ReferenceCounted::release) + .onErrorResume(EMNotFoundException.class, errorIgnored -> Mono.empty()) + .then(); + } +}