mirror of
https://gitcode.com/ageerle/ruoyi-ai.git
synced 2026-04-04 23:37:32 +00:00
init v1.0.0
This commit is contained in:
@@ -14,7 +14,9 @@
|
||||
<module>ruoyi-demo</module>
|
||||
<module>ruoyi-generator</module>
|
||||
<module>ruoyi-job</module>
|
||||
<module>ruoyi-midjourney</module>
|
||||
<module>ruoyi-system</module>
|
||||
<module>ruoyi-live</module>
|
||||
</modules>
|
||||
|
||||
<artifactId>ruoyi-modules</artifactId>
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<!--
|
||||
~ MIT License
|
||||
~
|
||||
~ Copyright (c) 2023 OrdinaryRoad
|
||||
~
|
||||
~ Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
~ of this software and associated documentation files (the "Software"), to deal
|
||||
~ in the Software without restriction, including without limitation the rights
|
||||
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
~ copies of the Software, and to permit persons to whom the Software is
|
||||
~ furnished to do so, subject to the following conditions:
|
||||
~
|
||||
~ The above copyright notice and this permission notice shall be included in all
|
||||
~ copies or substantial portions of the Software.
|
||||
~
|
||||
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
~ SOFTWARE.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>live-chat-client-commons</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<artifactId>live-chat-client-commons-base</artifactId>
|
||||
<name>ordinaryroad-live-chat-client-commons-base</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.base.constant;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
public class Constants {
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.base.exception;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/5
|
||||
*/
|
||||
public class BaseException extends RuntimeException {
|
||||
|
||||
public BaseException() {
|
||||
}
|
||||
|
||||
public BaseException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public BaseException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public BaseException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public BaseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.base.listener;
|
||||
|
||||
|
||||
/**
|
||||
* 连接回调
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
public interface IBaseConnectionListener<T> {
|
||||
|
||||
/**
|
||||
* 连接建立成功
|
||||
*/
|
||||
default void onConnected(T t) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接建立失败
|
||||
*
|
||||
* @param t
|
||||
*/
|
||||
default void onConnectFailed(T t) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接断开
|
||||
*
|
||||
* @param t
|
||||
*/
|
||||
default void onDisconnected(T t) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.base.listener;
|
||||
|
||||
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.BaseCmdMsg;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.BaseMsg;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.ICmdMsg;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.IMsg;
|
||||
|
||||
/**
|
||||
* Base消息回调
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
public interface IBaseMsgListener<T, CmdEnum extends Enum<CmdEnum>> {
|
||||
|
||||
/**
|
||||
* 收到消息(所有消息)
|
||||
*
|
||||
* @param msg IMsg
|
||||
*/
|
||||
default void onMsg(T t, IMsg msg) {
|
||||
this.onMsg(msg);
|
||||
}
|
||||
|
||||
default void onMsg(IMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到cmd消息(所有cmd)
|
||||
*
|
||||
* @param cmd CmdEnum
|
||||
* @param cmdMsg BaseCmdMsg
|
||||
*/
|
||||
default void onCmdMsg(T t, CmdEnum cmd, ICmdMsg<CmdEnum> cmdMsg) {
|
||||
this.onCmdMsg(cmd, cmdMsg);
|
||||
}
|
||||
|
||||
default void onCmdMsg(CmdEnum cmd, ICmdMsg<CmdEnum> cmdMsg) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到其他cmd消息(存在Enum,但Listener没有对应的回调)
|
||||
*
|
||||
* @param cmd CmdEnum
|
||||
* @param cmdMsg BaseCmdMsg
|
||||
*/
|
||||
default void onOtherCmdMsg(T t, CmdEnum cmd, ICmdMsg<CmdEnum> cmdMsg) {
|
||||
this.onOtherCmdMsg(cmd, cmdMsg);
|
||||
}
|
||||
|
||||
default void onOtherCmdMsg(CmdEnum cmd, ICmdMsg<CmdEnum> cmdMsg) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到未知cmd消息
|
||||
*
|
||||
* @param cmdString 实际收到的cmd字符串
|
||||
* @param msg BaseMsg
|
||||
*/
|
||||
default void onUnknownCmd(T t, String cmdString, IMsg msg) {
|
||||
this.onUnknownCmd(cmdString, msg);
|
||||
}
|
||||
|
||||
default void onUnknownCmd(String cmdString, IMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到cmd消息(所有cmd)
|
||||
*
|
||||
* @param cmd CmdEnum
|
||||
* @param cmdMsg BaseCmdMsg
|
||||
* @deprecated use {@link #onCmdMsg(T, Enum, ICmdMsg)}
|
||||
*/
|
||||
default void onCmdMsg(T t, CmdEnum cmd, BaseCmdMsg<CmdEnum> cmdMsg) {
|
||||
this.onCmdMsg(cmd, cmdMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #onCmdMsg(Enum, ICmdMsg)}
|
||||
*/
|
||||
default void onCmdMsg(CmdEnum cmd, BaseCmdMsg<CmdEnum> cmdMsg) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到其他cmd消息(存在Enum,但Listener没有对应的回调)
|
||||
*
|
||||
* @param cmd CmdEnum
|
||||
* @param cmdMsg BaseCmdMsg
|
||||
* @deprecated use {@link #onOtherCmdMsg(T, Enum, ICmdMsg)}
|
||||
*/
|
||||
default void onOtherCmdMsg(T t, CmdEnum cmd, BaseCmdMsg<CmdEnum> cmdMsg) {
|
||||
this.onOtherCmdMsg(cmd, cmdMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #onOtherCmdMsg(Enum, ICmdMsg)}
|
||||
*/
|
||||
default void onOtherCmdMsg(CmdEnum cmd, BaseCmdMsg<CmdEnum> cmdMsg) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到未知cmd消息
|
||||
*
|
||||
* @param cmdString 实际收到的cmd字符串
|
||||
* @param msg BaseMsg
|
||||
* @deprecated use {@link #onUnknownCmd(T, String, IMsg)}
|
||||
*/
|
||||
default void onUnknownCmd(T t, String cmdString, BaseMsg msg) {
|
||||
this.onUnknownCmd(cmdString, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #onUnknownCmd(String, IMsg)}
|
||||
*/
|
||||
default void onUnknownCmd(String cmdString, BaseMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.base.listener;
|
||||
|
||||
|
||||
/**
|
||||
* 弹幕消息回调
|
||||
*
|
||||
* @author mjz
|
||||
* @since 0.0.6
|
||||
*/
|
||||
public interface IDanmuMsgListener<T, DanmuMsg> {
|
||||
|
||||
/**
|
||||
* 收到弹幕
|
||||
*/
|
||||
default void onDanmuMsg(T t, DanmuMsg msg) {
|
||||
this.onDanmuMsg(msg);
|
||||
}
|
||||
|
||||
default void onDanmuMsg(DanmuMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.base.listener;
|
||||
|
||||
|
||||
/**
|
||||
* 进入房间消息回调
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/12/14
|
||||
* @since 0.0.16
|
||||
*/
|
||||
public interface IEnterRoomMsgListener<T, EnterRoomMsg> {
|
||||
|
||||
/**
|
||||
* 用户进入房间
|
||||
*/
|
||||
default void onEnterRoomMsg(T t, EnterRoomMsg msg) {
|
||||
this.onEnterRoomMsg(msg);
|
||||
}
|
||||
|
||||
default void onEnterRoomMsg(EnterRoomMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.base.listener;
|
||||
|
||||
|
||||
/**
|
||||
* 礼物消息回调
|
||||
*
|
||||
* @author mjz
|
||||
* @since 0.0.8
|
||||
*/
|
||||
public interface IGiftMsgListener<T, GiftMsg> {
|
||||
|
||||
|
||||
/**
|
||||
* 收到礼物
|
||||
*/
|
||||
default void onGiftMsg(T t, GiftMsg msg) {
|
||||
this.onGiftMsg(msg);
|
||||
}
|
||||
|
||||
default void onGiftMsg(GiftMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.base.listener;
|
||||
|
||||
|
||||
/**
|
||||
* 点赞消息回调
|
||||
*
|
||||
* @author mjz
|
||||
* @since 0.2.0
|
||||
*/
|
||||
public interface ILikeMsgListener<T, LikeMsg> {
|
||||
|
||||
/**
|
||||
* 收到点赞
|
||||
*/
|
||||
default void onLikeMsg(T t, LikeMsg msg) {
|
||||
this.onLikeMsg(msg);
|
||||
}
|
||||
|
||||
default void onLikeMsg(LikeMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.base.listener;
|
||||
|
||||
|
||||
/**
|
||||
* 醒目留言消息回调
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/9/24
|
||||
* @since 0.0.11
|
||||
*/
|
||||
public interface ISuperChatMsgListener<T, SuperChatMsg> {
|
||||
|
||||
/**
|
||||
* 收到醒目留言
|
||||
*/
|
||||
default void onSuperChatMsg(T t, SuperChatMsg msg) {
|
||||
this.onSuperChatMsg(msg);
|
||||
}
|
||||
|
||||
default void onSuperChatMsg(SuperChatMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.base.msg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
public abstract class BaseCmdMsg<CmdEnum extends Enum<CmdEnum>> extends BaseMsg
|
||||
implements ICmdMsg<CmdEnum> {
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.base.msg;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
||||
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.exception.BaseException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public abstract class BaseMsg implements IMsg {
|
||||
|
||||
public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
|
||||
|
||||
/**
|
||||
* 未知属性都放在这
|
||||
*/
|
||||
private final Map<String, JsonNode> unknownProperties = new HashMap<>();
|
||||
|
||||
@JsonAnyGetter
|
||||
public Map<String, JsonNode> getUnknownProperties() {
|
||||
return unknownProperties;
|
||||
}
|
||||
|
||||
@JsonAnySetter
|
||||
public void setOther(String key, JsonNode value) {
|
||||
this.unknownProperties.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
return OBJECT_MAPPER.writeValueAsString(this);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new BaseException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.base.msg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/10/2
|
||||
*/
|
||||
public interface ICmdMsg<CmdEnum extends Enum<CmdEnum>> extends IMsg {
|
||||
|
||||
String getCmd();
|
||||
|
||||
void setCmd(String cmd);
|
||||
|
||||
CmdEnum getCmdEnum();
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.base.msg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/8
|
||||
*/
|
||||
public interface IDanmuMsg extends IMsg {
|
||||
|
||||
/**
|
||||
* 粉丝牌名称
|
||||
*/
|
||||
String getBadgeName();
|
||||
|
||||
/**
|
||||
* 粉丝牌等级
|
||||
*/
|
||||
byte getBadgeLevel();
|
||||
|
||||
/**
|
||||
* 弹幕发送者id
|
||||
*/
|
||||
String getUid();
|
||||
|
||||
/**
|
||||
* 弹幕发送者用户名
|
||||
*/
|
||||
String getUsername();
|
||||
|
||||
/**
|
||||
* 弹幕发送者头像地址
|
||||
*
|
||||
* @since 0.0.11
|
||||
*/
|
||||
default String getUserAvatar() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 弹幕内容
|
||||
*/
|
||||
String getContent();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.base.msg;
|
||||
|
||||
/**
|
||||
* 入房消息
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/12/26
|
||||
* @since 0.0.16
|
||||
*/
|
||||
public interface IEnterRoomMsg extends IMsg {
|
||||
|
||||
/**
|
||||
* 粉丝牌名称
|
||||
*/
|
||||
String getBadgeName();
|
||||
|
||||
/**
|
||||
* 粉丝牌等级
|
||||
*/
|
||||
byte getBadgeLevel();
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
String getUid();
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
String getUsername();
|
||||
|
||||
/**
|
||||
* 头像地址
|
||||
*/
|
||||
default String getUserAvatar() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.base.msg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/8
|
||||
*/
|
||||
public interface IGiftMsg extends IMsg {
|
||||
|
||||
/**
|
||||
* 粉丝牌名称
|
||||
*/
|
||||
default String getBadgeName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 粉丝牌等级
|
||||
*/
|
||||
default byte getBadgeLevel() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送方id
|
||||
*/
|
||||
String getUid();
|
||||
|
||||
/**
|
||||
* 发送方用户名
|
||||
*/
|
||||
String getUsername();
|
||||
|
||||
/**
|
||||
* 发送方头像地址
|
||||
*
|
||||
* @since 0.0.11
|
||||
*/
|
||||
default String getUserAvatar() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 礼物名称
|
||||
*/
|
||||
String getGiftName();
|
||||
|
||||
/**
|
||||
* 礼物图像地址
|
||||
*/
|
||||
String getGiftImg();
|
||||
|
||||
/**
|
||||
* 礼物id
|
||||
*/
|
||||
String getGiftId();
|
||||
|
||||
/**
|
||||
* 礼物数量
|
||||
*/
|
||||
int getGiftCount();
|
||||
|
||||
/**
|
||||
* 单个礼物价格
|
||||
*/
|
||||
int getGiftPrice();
|
||||
|
||||
/**
|
||||
* 接收方id
|
||||
*/
|
||||
String getReceiveUid();
|
||||
|
||||
/**
|
||||
* 接收方用户名
|
||||
*/
|
||||
String getReceiveUsername();
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.base.msg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2024/1/31
|
||||
* @since 0.2.0
|
||||
*/
|
||||
public interface ILikeMsg extends IMsg {
|
||||
|
||||
/**
|
||||
* 粉丝牌名称
|
||||
*/
|
||||
default String getBadgeName(){
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 粉丝牌等级
|
||||
*/
|
||||
default byte getBadgeLevel(){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 点赞者id
|
||||
*/
|
||||
String getUid();
|
||||
|
||||
/**
|
||||
* 点赞者用户名
|
||||
*/
|
||||
String getUsername();
|
||||
|
||||
/**
|
||||
* 点赞者头像地址
|
||||
*/
|
||||
default String getUserAvatar() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 点赞数
|
||||
*/
|
||||
default int getClickCount() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.base.msg;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
public interface IMsg extends Serializable {
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.base.msg;
|
||||
|
||||
/**
|
||||
* 醒目留言
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/9/22
|
||||
*/
|
||||
public interface ISuperChatMsg extends IDanmuMsg {
|
||||
|
||||
/**
|
||||
* 醒目留言持续时间,单位秒
|
||||
*/
|
||||
int getDuration();
|
||||
|
||||
@Override
|
||||
default String getBadgeName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
default byte getBadgeLevel() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<!--
|
||||
~ MIT License
|
||||
~
|
||||
~ Copyright (c) 2023 OrdinaryRoad
|
||||
~
|
||||
~ Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
~ of this software and associated documentation files (the "Software"), to deal
|
||||
~ in the Software without restriction, including without limitation the rights
|
||||
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
~ copies of the Software, and to permit persons to whom the Software is
|
||||
~ furnished to do so, subject to the following conditions:
|
||||
~
|
||||
~ The above copyright notice and this permission notice shall be included in all
|
||||
~ copies or substantial portions of the Software.
|
||||
~
|
||||
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
~ SOFTWARE.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>live-chat-client-commons</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<artifactId>live-chat-client-commons-client</artifactId>
|
||||
<name>live-chat-client-commons-client</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>live-chat-client-commons-base</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>live-chat-client-commons-util</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.client;
|
||||
|
||||
import lombok.Getter;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseMsgListener;
|
||||
import tech.ordinaryroad.live.chat.client.commons.client.config.BaseLiveChatClientConfig;
|
||||
import tech.ordinaryroad.live.chat.client.commons.client.enums.ClientStatusEnums;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
public abstract class BaseLiveChatClient<
|
||||
Config extends BaseLiveChatClientConfig,
|
||||
MsgListener extends IBaseMsgListener<?, ?>
|
||||
> implements IBaseLiveChatClient<MsgListener> {
|
||||
|
||||
private final Config config;
|
||||
@Getter
|
||||
private volatile ClientStatusEnums status = ClientStatusEnums.NEW;
|
||||
protected PropertyChangeSupport statusChangeSupport = new PropertyChangeSupport(status);
|
||||
protected volatile boolean cancelReconnect = false;
|
||||
protected final List<MsgListener> msgListeners = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
protected BaseLiveChatClient(Config config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public Config getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(Runnable success) {
|
||||
this.connect(success, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
this.connect(null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect(boolean cancelReconnect) {
|
||||
this.cancelReconnect = cancelReconnect;
|
||||
this.disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Object msg) {
|
||||
this.send(msg, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Object msg, Runnable success) {
|
||||
this.send(msg, success, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Object msg, Consumer<Throwable> failed) {
|
||||
this.send(msg, null, failed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDanmu(Object danmu) {
|
||||
this.sendDanmu(danmu, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDanmu(Object danmu, Runnable success) {
|
||||
this.sendDanmu(danmu, success, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDanmu(Object danmu, Consumer<Throwable> failed) {
|
||||
this.sendDanmu(danmu, null, failed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clickLike(int count) {
|
||||
this.clickLike(count, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clickLike(int count, Runnable success) {
|
||||
this.clickLike(count, success, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clickLike(int count, Consumer<Throwable> failed) {
|
||||
this.clickLike(count, null, failed);
|
||||
}
|
||||
|
||||
protected abstract void tryReconnect();
|
||||
|
||||
protected abstract String getWebSocketUriString();
|
||||
|
||||
/**
|
||||
* 判断是否处于某个状态,或者处于后续状态
|
||||
*
|
||||
* @param status {@link ClientStatusEnums}
|
||||
* @return false: 还没有到达该状态
|
||||
*/
|
||||
protected boolean checkStatus(ClientStatusEnums status) {
|
||||
return this.status.getCode() >= Objects.requireNonNull(status).getCode();
|
||||
}
|
||||
|
||||
protected void setStatus(ClientStatusEnums status) {
|
||||
ClientStatusEnums oldStatus = this.status;
|
||||
if (oldStatus != status) {
|
||||
this.status = status;
|
||||
this.statusChangeSupport.firePropertyChange("status", oldStatus, status);
|
||||
}
|
||||
}
|
||||
|
||||
public void addStatusChangeListener(PropertyChangeListener listener) {
|
||||
this.statusChangeSupport.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void removeStatusChangeListener(PropertyChangeListener listener) {
|
||||
this.statusChangeSupport.removePropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
for (PropertyChangeListener propertyChangeListener : this.statusChangeSupport.getPropertyChangeListeners()) {
|
||||
this.statusChangeSupport.removePropertyChangeListener(propertyChangeListener);
|
||||
}
|
||||
this.msgListeners.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addMsgListener(MsgListener msgListener) {
|
||||
if (msgListener == null) {
|
||||
return false;
|
||||
}
|
||||
return this.msgListeners.add(msgListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addMsgListeners(List<MsgListener> msgListeners) {
|
||||
if (msgListeners == null || msgListeners.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return this.msgListeners.addAll(msgListeners);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeMsgListener(MsgListener msgListener) {
|
||||
if (msgListener == null) {
|
||||
return false;
|
||||
}
|
||||
return this.msgListeners.remove(msgListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeMsgListeners(List<MsgListener> msgListeners) {
|
||||
if (msgListeners == null || msgListeners.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return this.msgListeners.removeAll(msgListeners);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllMsgListeners() {
|
||||
this.msgListeners.clear();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.client;
|
||||
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseMsgListener;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/5
|
||||
*/
|
||||
public interface IBaseLiveChatClient<MsgListener extends IBaseMsgListener<?, ?>> {
|
||||
|
||||
void init();
|
||||
|
||||
boolean addMsgListener(MsgListener msgListener);
|
||||
|
||||
boolean addMsgListeners(List<MsgListener> msgListeners);
|
||||
|
||||
boolean removeMsgListener(MsgListener msgListener);
|
||||
|
||||
boolean removeMsgListeners(List<MsgListener> msgListeners);
|
||||
|
||||
void removeAllMsgListeners();
|
||||
|
||||
void connect(Runnable success, Consumer<Throwable> failed);
|
||||
|
||||
void connect(Runnable success);
|
||||
|
||||
void connect();
|
||||
|
||||
/**
|
||||
* 手动断开连接
|
||||
*
|
||||
* @param cancelReconnect 取消本次的自动重连(如果启用自动重连)
|
||||
*/
|
||||
void disconnect(boolean cancelReconnect);
|
||||
|
||||
void disconnect();
|
||||
|
||||
void destroy();
|
||||
|
||||
void send(Object msg);
|
||||
|
||||
void send(Object msg, Runnable success, Consumer<Throwable> failed);
|
||||
|
||||
void send(Object msg, Runnable success);
|
||||
|
||||
void send(Object msg, Consumer<Throwable> failed);
|
||||
|
||||
/**
|
||||
* 发送弹幕
|
||||
*
|
||||
* @param danmu 弹幕内容
|
||||
* @since 0.0.6
|
||||
*/
|
||||
void sendDanmu(Object danmu);
|
||||
|
||||
/**
|
||||
* 发送弹幕
|
||||
*
|
||||
* @param danmu 弹幕内容
|
||||
* @since 0.0.6
|
||||
*/
|
||||
void sendDanmu(Object danmu, Runnable success, Consumer<Throwable> failed);
|
||||
|
||||
/**
|
||||
* 发送弹幕
|
||||
*
|
||||
* @param danmu 弹幕内容
|
||||
* @since 0.0.6
|
||||
*/
|
||||
void sendDanmu(Object danmu, Runnable success);
|
||||
|
||||
/**
|
||||
* 发送弹幕
|
||||
*
|
||||
* @param danmu 弹幕内容
|
||||
* @since 0.0.6
|
||||
*/
|
||||
void sendDanmu(Object danmu, Consumer<Throwable> failed);
|
||||
|
||||
/**
|
||||
* 为直播间点赞
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
void clickLike(int count);
|
||||
|
||||
/**
|
||||
* 为直播间点赞
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
void clickLike(int count, Runnable success, Consumer<Throwable> failed);
|
||||
|
||||
/**
|
||||
* 为直播间点赞
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
void clickLike(int count, Runnable success);
|
||||
|
||||
/**
|
||||
* 为直播间点赞
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
void clickLike(int count, Consumer<Throwable> failed);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.client.config;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.exception.BaseException;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
|
||||
/**
|
||||
* 直播间弹幕客户端配置
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@SuperBuilder(toBuilder = true)
|
||||
public abstract class BaseLiveChatClientConfig {
|
||||
|
||||
protected PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
|
||||
public static final long DEFAULT_HEARTBEAT_INITIAL_DELAY = 15;
|
||||
public static final long DEFAULT_HEARTBEAT_PERIOD = 25;
|
||||
public static final long DEFAULT_MIN_SEND_DANMU_PERIOD = 3000L;
|
||||
|
||||
private String websocketUri;
|
||||
|
||||
/**
|
||||
* 浏览器中的Cookie
|
||||
*/
|
||||
private String cookie;
|
||||
|
||||
/**
|
||||
* 直播间id
|
||||
*/
|
||||
private Object roomId;
|
||||
|
||||
/**
|
||||
* 是否启用自动重连
|
||||
*/
|
||||
@Builder.Default
|
||||
private boolean autoReconnect = Boolean.TRUE;
|
||||
|
||||
/**
|
||||
* 重试延迟时间(秒),默认5s后重试
|
||||
*/
|
||||
@Builder.Default
|
||||
private int reconnectDelay = 5;
|
||||
|
||||
/**
|
||||
* 首次发送心跳包的延迟时间(秒)
|
||||
*/
|
||||
@Builder.Default
|
||||
private long heartbeatInitialDelay = DEFAULT_HEARTBEAT_INITIAL_DELAY;
|
||||
|
||||
/**
|
||||
* 心跳包发送周期(秒)
|
||||
*/
|
||||
@Builder.Default
|
||||
private long heartbeatPeriod = DEFAULT_HEARTBEAT_PERIOD;
|
||||
|
||||
/**
|
||||
* 最小发送弹幕时间间隔(毫秒)
|
||||
*/
|
||||
@Builder.Default
|
||||
private long minSendDanmuPeriod = DEFAULT_MIN_SEND_DANMU_PERIOD;
|
||||
|
||||
public void setCookie(String cookie) {
|
||||
String oldValue = this.cookie;
|
||||
this.cookie = cookie;
|
||||
this.propertyChangeSupport.firePropertyChange("cookie", oldValue, cookie);
|
||||
}
|
||||
|
||||
public void setRoomId(Object roomId) {
|
||||
if (!(roomId instanceof Number || roomId instanceof String)) {
|
||||
throw new BaseException("房间ID仅支持数字或字符串,所传参数类型:" + roomId.getClass() + "值:" + roomId);
|
||||
}
|
||||
Object oldValue = this.roomId;
|
||||
this.roomId = roomId;
|
||||
this.propertyChangeSupport.firePropertyChange("roomId", oldValue, roomId);
|
||||
}
|
||||
|
||||
public void setWebsocketUri(String websocketUri) {
|
||||
String oldValue = this.websocketUri;
|
||||
this.websocketUri = websocketUri;
|
||||
this.propertyChangeSupport.firePropertyChange("websocketUri", oldValue, websocketUri);
|
||||
}
|
||||
|
||||
public void setMinSendDanmuPeriod(long minSendDanmuPeriod) {
|
||||
long oldValue = this.minSendDanmuPeriod;
|
||||
this.minSendDanmuPeriod = minSendDanmuPeriod;
|
||||
this.propertyChangeSupport.firePropertyChange("minSendDanmuPeriod", oldValue, minSendDanmuPeriod);
|
||||
}
|
||||
|
||||
public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
|
||||
this.propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
|
||||
}
|
||||
|
||||
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||
this.propertyChangeSupport.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
|
||||
this.propertyChangeSupport.removePropertyChangeListener(propertyName, listener);
|
||||
}
|
||||
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||
this.propertyChangeSupport.removePropertyChangeListener(listener);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.client.enums;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
public enum ClientStatusEnums {
|
||||
/**
|
||||
* 新创建
|
||||
*/
|
||||
NEW(0),
|
||||
|
||||
/**
|
||||
* 已初始化
|
||||
*/
|
||||
INITIALIZED(1),
|
||||
|
||||
/**
|
||||
* 连接中
|
||||
*/
|
||||
CONNECTING(100),
|
||||
|
||||
/**
|
||||
* 重新连接中
|
||||
*/
|
||||
RECONNECTING(101),
|
||||
|
||||
/**
|
||||
* 已连接
|
||||
*/
|
||||
CONNECTED(200),
|
||||
|
||||
/**
|
||||
* 连接失败
|
||||
*/
|
||||
CONNECT_FAILED(401),
|
||||
|
||||
/**
|
||||
* 已断开连接
|
||||
*/
|
||||
DISCONNECTED(400),
|
||||
|
||||
/**
|
||||
* 已销毁
|
||||
*/
|
||||
DESTROYED(-1),
|
||||
;
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
ClientStatusEnums(int order) {
|
||||
this.code = order;
|
||||
}
|
||||
|
||||
private final int code;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>live-chat-client-commons</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<artifactId>live-chat-client-commons-util</artifactId>
|
||||
<name>live-chat-client-commons-util</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.util;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.net.HttpCookie;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/27
|
||||
*/
|
||||
public class OrLiveChatCookieUtil {
|
||||
|
||||
public static String toString(List<HttpCookie> cookies) {
|
||||
if (CollUtil.isEmpty(cookies)) {
|
||||
return StrUtil.EMPTY;
|
||||
}
|
||||
|
||||
return cookies.stream().map(httpCookie -> {
|
||||
httpCookie.setVersion(0);
|
||||
return httpCookie.toString();
|
||||
}).collect(Collectors.joining("; "));
|
||||
}
|
||||
|
||||
public static Map<String, String> parseCookieString(String cookies) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
if (StrUtil.isNotBlank(cookies) && !StrUtil.isNullOrUndefined(cookies)) {
|
||||
try {
|
||||
String[] split = cookies.split("; ");
|
||||
for (String s : split) {
|
||||
String[] split1 = s.split("=");
|
||||
map.put(split1[0], split1[1]);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("cookie解析失败 " + cookies, e);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static String getCookieByName(Map<String, String> cookieMap, String name, Supplier<String> supplier) {
|
||||
String str = MapUtil.getStr(cookieMap, name);
|
||||
return str == null ? supplier.get() : str;
|
||||
}
|
||||
|
||||
public static String getCookieByName(String cookie, String name, Supplier<String> supplier) {
|
||||
String str = MapUtil.getStr(parseCookieString(cookie), name);
|
||||
return str == null ? supplier.get() : str;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.util;
|
||||
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/12/2
|
||||
*/
|
||||
public class OrLiveChatNumberUtil extends NumberUtil {
|
||||
|
||||
public static long parseLong(Object object){
|
||||
return NumberUtil.parseLong(StrUtil.toStringOrNull(object));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.util;
|
||||
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/28
|
||||
*/
|
||||
public class OrLiveChatReflectUtil extends ReflectUtil {
|
||||
|
||||
public static Method getGetterMethod(Class<?> objectClass, String key) {
|
||||
Method method;
|
||||
if (key.startsWith("is")) {
|
||||
method = ReflectUtil.getMethodByNameIgnoreCase(objectClass, key);
|
||||
if (method == null) {
|
||||
ReflectUtil.getMethodByNameIgnoreCase(objectClass, "get" + key);
|
||||
}
|
||||
} else {
|
||||
method = ReflectUtil.getMethodByNameIgnoreCase(objectClass, "get" + key);
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.commons.util;
|
||||
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/7
|
||||
*/
|
||||
public class OrLocalDateTimeUtil extends LocalDateTimeUtil {
|
||||
|
||||
public static ZoneId ZONE_ID_CTT = ZoneId.of(ZoneId.SHORT_IDS.get("CTT"));
|
||||
|
||||
/**
|
||||
* 获取中国标准时间的当前时间戳(毫秒)
|
||||
*/
|
||||
public static long zonedCurrentTimeMillis() {
|
||||
ZonedDateTime now = ZonedDateTime.now(ZONE_ID_CTT);
|
||||
return now.toEpochSecond() * 1000 + now.getNano() / 1_000_000;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取中国标准时间的当前时间戳(秒)
|
||||
*/
|
||||
public static long zonedCurrentTimeSecs() {
|
||||
return ZonedDateTime.now(ZONE_ID_CTT).toEpochSecond();
|
||||
}
|
||||
}
|
||||
43
ruoyi-modules/ruoyi-live/live-chat-client-commons/pom.xml
Normal file
43
ruoyi-modules/ruoyi-live/live-chat-client-commons/pom.xml
Normal file
@@ -0,0 +1,43 @@
|
||||
<!--
|
||||
~ MIT License
|
||||
~
|
||||
~ Copyright (c) 2023 OrdinaryRoad
|
||||
~
|
||||
~ Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
~ of this software and associated documentation files (the "Software"), to deal
|
||||
~ in the Software without restriction, including without limitation the rights
|
||||
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
~ copies of the Software, and to permit persons to whom the Software is
|
||||
~ furnished to do so, subject to the following conditions:
|
||||
~
|
||||
~ The above copyright notice and this permission notice shall be included in all
|
||||
~ copies or substantial portions of the Software.
|
||||
~
|
||||
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
~ SOFTWARE.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-live</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<artifactId>live-chat-client-commons</artifactId>
|
||||
|
||||
<modules>
|
||||
<module>live-chat-client-commons-base</module>
|
||||
<module>live-chat-client-commons-util</module>
|
||||
<module>live-chat-client-commons-client</module>
|
||||
</modules>
|
||||
</project>
|
||||
@@ -0,0 +1,54 @@
|
||||
<!--
|
||||
~ MIT License
|
||||
~
|
||||
~ Copyright (c) 2023 OrdinaryRoad
|
||||
~
|
||||
~ Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
~ of this software and associated documentation files (the "Software"), to deal
|
||||
~ in the Software without restriction, including without limitation the rights
|
||||
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
~ copies of the Software, and to permit persons to whom the Software is
|
||||
~ furnished to do so, subject to the following conditions:
|
||||
~
|
||||
~ The above copyright notice and this permission notice shall be included in all
|
||||
~ copies or substantial portions of the Software.
|
||||
~
|
||||
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
~ SOFTWARE.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>live-chat-client-servers</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<artifactId>live-chat-client-servers-netty-client</artifactId>
|
||||
<name>live-chat-client-servers-netty</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>live-chat-client-commons-client</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>live-chat-client-servers-netty</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.servers.netty.client.base;
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.codec.http.HttpClientCodec;
|
||||
import io.netty.handler.codec.http.HttpObjectAggregator;
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import io.netty.handler.stream.ChunkedWriteHandler;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.exception.BaseException;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseConnectionListener;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseMsgListener;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.IMsg;
|
||||
import tech.ordinaryroad.live.chat.client.commons.client.BaseLiveChatClient;
|
||||
import tech.ordinaryroad.live.chat.client.commons.client.enums.ClientStatusEnums;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.client.config.BaseNettyClientConfig;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.handler.base.BaseBinaryFrameHandler;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.handler.base.BaseConnectionHandler;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class BaseNettyClient
|
||||
<Config extends BaseNettyClientConfig,
|
||||
CmdEnum extends Enum<CmdEnum>,
|
||||
Msg extends IMsg,
|
||||
MsgListener extends IBaseMsgListener<BinaryFrameHandler, CmdEnum>,
|
||||
ConnectionHandler extends BaseConnectionHandler<ConnectionHandler>,
|
||||
BinaryFrameHandler extends BaseBinaryFrameHandler<BinaryFrameHandler, CmdEnum, Msg, MsgListener>
|
||||
>
|
||||
extends BaseLiveChatClient<Config, MsgListener> {
|
||||
|
||||
@Getter
|
||||
private final EventLoopGroup workerGroup;
|
||||
@Getter
|
||||
private final Bootstrap bootstrap = new Bootstrap();
|
||||
private BinaryFrameHandler binaryFrameHandler;
|
||||
private ConnectionHandler connectionHandler;
|
||||
private IBaseConnectionListener<ConnectionHandler> connectionListener;
|
||||
private Channel channel;
|
||||
@Getter
|
||||
private URI websocketUri;
|
||||
protected IBaseConnectionListener<ConnectionHandler> clientConnectionListener;
|
||||
/**
|
||||
* 控制弹幕发送频率
|
||||
*/
|
||||
private volatile long lastSendDanmuTimeInMillis;
|
||||
|
||||
public abstract ConnectionHandler initConnectionHandler(IBaseConnectionListener<ConnectionHandler> clientConnectionListener);
|
||||
|
||||
public abstract BinaryFrameHandler initBinaryFrameHandler();
|
||||
|
||||
protected BaseNettyClient(Config config, EventLoopGroup workerGroup, IBaseConnectionListener<ConnectionHandler> connectionListener) {
|
||||
super(config);
|
||||
this.workerGroup = workerGroup;
|
||||
this.connectionListener = connectionListener;
|
||||
}
|
||||
|
||||
public void onConnected(ConnectionHandler connectionHandler) {
|
||||
this.setStatus(ClientStatusEnums.CONNECTED);
|
||||
if (this.connectionListener != null) {
|
||||
this.connectionListener.onConnected(connectionHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public void onConnectFailed(ConnectionHandler connectionHandler) {
|
||||
this.setStatus(ClientStatusEnums.CONNECT_FAILED);
|
||||
tryReconnect();
|
||||
if (this.connectionListener != null) {
|
||||
this.connectionListener.onConnectFailed(connectionHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public void onDisconnected(ConnectionHandler connectionHandler) {
|
||||
this.setStatus(ClientStatusEnums.DISCONNECTED);
|
||||
tryReconnect();
|
||||
if (this.connectionListener != null) {
|
||||
this.connectionListener.onDisconnected(connectionHandler);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
if (checkStatus(ClientStatusEnums.INITIALIZED)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.websocketUri = new URI(getWebSocketUriString());
|
||||
SslContext sslCtx = SslContextBuilder.forClient().build();
|
||||
|
||||
this.clientConnectionListener = new IBaseConnectionListener<ConnectionHandler>() {
|
||||
@Override
|
||||
public void onConnected(ConnectionHandler connectionHandler) {
|
||||
BaseNettyClient.this.onConnected(connectionHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectFailed(ConnectionHandler connectionHandler) {
|
||||
BaseNettyClient.this.onConnectFailed(connectionHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnected(ConnectionHandler connectionHandler) {
|
||||
BaseNettyClient.this.onDisconnected(connectionHandler);
|
||||
}
|
||||
};
|
||||
this.binaryFrameHandler = this.initBinaryFrameHandler();
|
||||
this.connectionHandler = this.initConnectionHandler(this.clientConnectionListener);
|
||||
|
||||
this.bootstrap.group(this.workerGroup)
|
||||
// 创建Channel
|
||||
.channel(NioSocketChannel.class)
|
||||
.remoteAddress(this.websocketUri.getHost(), getInetPort())
|
||||
.option(ChannelOption.TCP_NODELAY, true)
|
||||
.option(ChannelOption.SO_KEEPALIVE, true)
|
||||
// Channel配置
|
||||
.handler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(SocketChannel ch) {
|
||||
// 责任链
|
||||
ChannelPipeline pipeline = ch.pipeline();
|
||||
|
||||
// 放到第一位 addFirst 支持wss链接服务端
|
||||
pipeline.addFirst(sslCtx.newHandler(ch.alloc(), BaseNettyClient.this.websocketUri.getHost(), getInetPort()));
|
||||
|
||||
// 添加一个http的编解码器
|
||||
pipeline.addLast(new HttpClientCodec());
|
||||
// 添加一个用于支持大数据流的支持
|
||||
pipeline.addLast(new ChunkedWriteHandler());
|
||||
// 添加一个聚合器,这个聚合器主要是将HttpMessage聚合成FullHttpRequest/Response
|
||||
pipeline.addLast(new HttpObjectAggregator(BaseNettyClient.this.getConfig().getAggregatorMaxContentLength()));
|
||||
|
||||
// 连接处理器
|
||||
pipeline.addLast(BaseNettyClient.this.connectionHandler);
|
||||
// 弹幕处理器
|
||||
pipeline.addLast(BaseNettyClient.this.binaryFrameHandler);
|
||||
}
|
||||
});
|
||||
this.setStatus(ClientStatusEnums.INITIALIZED);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new BaseException(e);
|
||||
} catch (SSLException e) {
|
||||
throw new BaseException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private int getInetPort() {
|
||||
int port = this.websocketUri.getPort();
|
||||
return port == -1 ? "wss".equalsIgnoreCase(websocketUri.getScheme()) ? 443 : 80 : port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(Runnable success, Consumer<Throwable> failed) {
|
||||
if (this.cancelReconnect) {
|
||||
this.cancelReconnect = false;
|
||||
}
|
||||
if (!checkStatus(ClientStatusEnums.INITIALIZED)) {
|
||||
return;
|
||||
}
|
||||
if (getStatus() == ClientStatusEnums.CONNECTED) {
|
||||
return;
|
||||
}
|
||||
if (getStatus() != ClientStatusEnums.RECONNECTING) {
|
||||
this.setStatus(ClientStatusEnums.CONNECTING);
|
||||
}
|
||||
this.bootstrap.connect().addListener((ChannelFutureListener) connectFuture -> {
|
||||
if (connectFuture.isSuccess()) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("连接建立成功!");
|
||||
}
|
||||
this.channel = connectFuture.channel();
|
||||
// 监听是否握手成功
|
||||
this.connectionHandler.getHandshakeFuture().addListener((ChannelFutureListener) handshakeFuture -> {
|
||||
try {
|
||||
connectionHandler.sendAuthRequest(channel);
|
||||
if (success != null) {
|
||||
success.run();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("认证包发送失败,断开连接", e);
|
||||
this.disconnect();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
log.error("连接建立失败", connectFuture.cause());
|
||||
this.onConnectFailed(this.connectionHandler);
|
||||
if (failed != null) {
|
||||
failed.accept(connectFuture.cause());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
if (this.channel == null) {
|
||||
return;
|
||||
}
|
||||
this.channel.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tryReconnect() {
|
||||
if (this.cancelReconnect) {
|
||||
this.cancelReconnect = false;
|
||||
return;
|
||||
}
|
||||
if (!getConfig().isAutoReconnect()) {
|
||||
return;
|
||||
}
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn("{}s后将重新连接 {}", getConfig().getReconnectDelay(), getConfig().getRoomId());
|
||||
}
|
||||
workerGroup.schedule(() -> {
|
||||
this.setStatus(ClientStatusEnums.RECONNECTING);
|
||||
this.connect();
|
||||
}, getConfig().getReconnectDelay(), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Object msg, Runnable success, Consumer<Throwable> failed) {
|
||||
ChannelFuture future = this.channel.writeAndFlush(msg);
|
||||
if (success != null || failed != null) {
|
||||
future.addListener((ChannelFutureListener) channelFuture -> {
|
||||
if (channelFuture.isSuccess()) {
|
||||
if (success != null) {
|
||||
success.run();
|
||||
}
|
||||
} else {
|
||||
if (failed != null) {
|
||||
failed.accept(channelFuture.cause());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
super.destroy();
|
||||
|
||||
// 销毁时不需要重连
|
||||
this.cancelReconnect = true;
|
||||
workerGroup.shutdownGracefully().addListener(future -> {
|
||||
if (future.isSuccess()) {
|
||||
this.setStatus(ClientStatusEnums.DESTROYED);
|
||||
} else {
|
||||
throw new BaseException("client销毁失败", future.cause());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getWebSocketUriString() {
|
||||
return getConfig().getWebsocketUri();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setStatus(ClientStatusEnums status) {
|
||||
if (log.isDebugEnabled()) {
|
||||
if (getStatus() != status) {
|
||||
log.debug("{} 状态变化 {} => {}\n", getClass().getSimpleName(), getStatus(), status);
|
||||
}
|
||||
}
|
||||
super.setStatus(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDanmu(Object danmu, Runnable success, Consumer<Throwable> failed) {
|
||||
throw new BaseException("暂未支持该功能");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clickLike(int count, Runnable success, Consumer<Throwable> failed) {
|
||||
throw new BaseException("暂未支持该功能");
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送弹幕前判断是否可以发送
|
||||
*
|
||||
* @param checkConnected 是否检查Client连接状态
|
||||
*/
|
||||
protected boolean checkCanSendDanmu(boolean checkConnected) {
|
||||
if (checkConnected && getStatus() != ClientStatusEnums.CONNECTED) {
|
||||
throw new BaseException("连接未建立,无法发送弹幕");
|
||||
}
|
||||
if (System.currentTimeMillis() - this.lastSendDanmuTimeInMillis <= getConfig().getMinSendDanmuPeriod()) {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn("发送弹幕频率过快,忽略该次发送");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean checkCanSendDanmu() {
|
||||
return checkCanSendDanmu(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送弹幕后调用该方法
|
||||
*/
|
||||
protected void finishSendDanmu() {
|
||||
this.lastSendDanmuTimeInMillis = System.currentTimeMillis();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("弹幕发送完成");
|
||||
}
|
||||
}
|
||||
|
||||
public void iteratorMsgListeners(Consumer<MsgListener> consumer) {
|
||||
binaryFrameHandler.iteratorMsgListeners(consumer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.servers.netty.client.config;
|
||||
|
||||
import io.netty.handler.codec.http.HttpHeaders;
|
||||
import io.netty.handler.codec.http.HttpObjectAggregator;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import tech.ordinaryroad.live.chat.client.commons.client.config.BaseLiveChatClientConfig;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@SuperBuilder(toBuilder = true)
|
||||
public abstract class BaseNettyClientConfig extends BaseLiveChatClientConfig {
|
||||
|
||||
/**
|
||||
* 聚合器允许的最大消息体长度,默认 64*1024 byte
|
||||
*
|
||||
* @see HttpObjectAggregator#HttpObjectAggregator(int)
|
||||
*/
|
||||
@Builder.Default
|
||||
private int aggregatorMaxContentLength = 64 * 1024;
|
||||
|
||||
/**
|
||||
* WebSocketClientHandshaker最大消息体长度,默认 64*1024 byte
|
||||
*
|
||||
* @see WebSocketClientHandshakerFactory#newHandshaker(URI, WebSocketVersion, String, boolean, HttpHeaders, int)
|
||||
*/
|
||||
@Builder.Default
|
||||
private int maxFramePayloadLength = 64 * 1024;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.servers.netty.client.handler;
|
||||
|
||||
import lombok.Getter;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseMsgListener;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.IMsg;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.client.base.BaseNettyClient;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.handler.base.BaseBinaryFrameHandler;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* BaseClientBinaryFrameHandler
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/30
|
||||
*/
|
||||
public abstract class BaseNettyClientBinaryFrameHandler<
|
||||
Client extends BaseNettyClient<?, ?, ?, ?, ?, ?>,
|
||||
BinaryFrameHandler extends BaseBinaryFrameHandler<BinaryFrameHandler, CmdEnum, Msg, MsgListener>,
|
||||
CmdEnum extends Enum<CmdEnum>,
|
||||
Msg extends IMsg,
|
||||
MsgListener extends IBaseMsgListener<BinaryFrameHandler, CmdEnum>>
|
||||
extends BaseBinaryFrameHandler<BinaryFrameHandler, CmdEnum, Msg, MsgListener> {
|
||||
|
||||
@Getter
|
||||
protected final Client client;
|
||||
|
||||
public BaseNettyClientBinaryFrameHandler(List<MsgListener> msgListeners, Client client, long roomId) {
|
||||
super(msgListeners, roomId);
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public BaseNettyClientBinaryFrameHandler(List<MsgListener> msgListeners, Client client) {
|
||||
super(msgListeners, client.getConfig().getRoomId());
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public BaseNettyClientBinaryFrameHandler(List<MsgListener> msgListeners, long roomId) {
|
||||
super(msgListeners, roomId);
|
||||
this.client = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.servers.netty.client.handler;
|
||||
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
|
||||
import lombok.Getter;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseConnectionListener;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.client.base.BaseNettyClient;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.handler.base.BaseConnectionHandler;
|
||||
|
||||
/**
|
||||
* BaseClientConnectionHandler
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/27
|
||||
*/
|
||||
public abstract class BaseNettyClientConnectionHandler<
|
||||
Client extends BaseNettyClient<?, ?, ?, ?, ?, ?>,
|
||||
ConnectionHandler extends BaseConnectionHandler<ConnectionHandler>>
|
||||
extends BaseConnectionHandler<ConnectionHandler> {
|
||||
|
||||
@Getter
|
||||
protected final Client client;
|
||||
|
||||
public BaseNettyClientConnectionHandler(WebSocketClientHandshaker handshaker, Client client, IBaseConnectionListener<ConnectionHandler> listener) {
|
||||
super(handshaker, listener);
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public BaseNettyClientConnectionHandler(WebSocketClientHandshaker handshaker, Client client) {
|
||||
this(handshaker, client, null);
|
||||
}
|
||||
|
||||
public BaseNettyClientConnectionHandler(WebSocketClientHandshaker handshaker, IBaseConnectionListener<ConnectionHandler> listener) {
|
||||
super(handshaker, listener);
|
||||
this.client = null;
|
||||
}
|
||||
|
||||
public BaseNettyClientConnectionHandler(WebSocketClientHandshaker handshaker, long roomId) {
|
||||
super(handshaker, null);
|
||||
this.client = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<!--
|
||||
~ MIT License
|
||||
~
|
||||
~ Copyright (c) 2023 OrdinaryRoad
|
||||
~
|
||||
~ Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
~ of this software and associated documentation files (the "Software"), to deal
|
||||
~ in the Software without restriction, including without limitation the rights
|
||||
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
~ copies of the Software, and to permit persons to whom the Software is
|
||||
~ furnished to do so, subject to the following conditions:
|
||||
~
|
||||
~ The above copyright notice and this permission notice shall be included in all
|
||||
~ copies or substantial portions of the Software.
|
||||
~
|
||||
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
~ SOFTWARE.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>live-chat-client-servers</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<artifactId>live-chat-client-servers-netty</artifactId>
|
||||
<name>live-chat-client-servers-netty</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>live-chat-client-commons-base</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.servers.netty.frame.base;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/1/5
|
||||
*/
|
||||
public abstract class BaseBinaryWebSocketFrame extends BinaryWebSocketFrame {
|
||||
|
||||
public BaseBinaryWebSocketFrame(ByteBuf byteBuf) {
|
||||
super(byteBuf);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.servers.netty.handler.base;
|
||||
|
||||
import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseMsgListener;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.BaseCmdMsg;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.BaseMsg;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.ICmdMsg;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.IMsg;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
||||
/**
|
||||
* 消息处理器
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/1/4
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class BaseBinaryFrameHandler<
|
||||
T extends BaseBinaryFrameHandler<?, ?, ?, ?>,
|
||||
CmdEnum extends Enum<CmdEnum>,
|
||||
Msg extends IMsg,
|
||||
MsgListener extends IBaseMsgListener<T, CmdEnum>
|
||||
> extends SimpleChannelInboundHandler<BinaryWebSocketFrame>
|
||||
implements IBaseMsgListener<T, CmdEnum> {
|
||||
|
||||
@Getter
|
||||
private final Object roomId;
|
||||
protected final List<MsgListener> msgListeners;
|
||||
|
||||
public BaseBinaryFrameHandler(List<MsgListener> msgListeners, Object roomId) {
|
||||
this.msgListeners = msgListeners;
|
||||
this.roomId = roomId;
|
||||
if (this.msgListeners == null || this.msgListeners.isEmpty()) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("listener not set");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解码收到的二进制流
|
||||
*
|
||||
* @param byteBuf ByteBuf
|
||||
* @return List<Msg>
|
||||
*/
|
||||
protected abstract List<Msg> decode(ByteBuf byteBuf);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void channelRead0(ChannelHandlerContext ctx, BinaryWebSocketFrame message) {
|
||||
ByteBuf byteBuf = message.content();
|
||||
List<Msg> msgList = this.decode(byteBuf);
|
||||
if (msgList == null || msgList.isEmpty()) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("msgList is empty");
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (Msg msg : msgList) {
|
||||
this.onMsg((T) BaseBinaryFrameHandler.this, msg);
|
||||
if (msg instanceof ICmdMsg<?>) {
|
||||
ICmdMsg<?> cmdMsg = (ICmdMsg<?>) msg;
|
||||
Enum<?> cmdEnum = cmdMsg.getCmdEnum();
|
||||
if (cmdEnum == null) {
|
||||
this.onUnknownCmd((T) BaseBinaryFrameHandler.this, cmdMsg.getCmd(), cmdMsg);
|
||||
} else {
|
||||
this.onCmdMsg((T) BaseBinaryFrameHandler.this, (CmdEnum) cmdEnum, (ICmdMsg<CmdEnum>) cmdMsg);
|
||||
}
|
||||
}
|
||||
if (msg instanceof BaseCmdMsg<?>) {
|
||||
BaseCmdMsg<?> cmdMsg = (BaseCmdMsg<?>) msg;
|
||||
Enum<?> cmdEnum = cmdMsg.getCmdEnum();
|
||||
if (cmdEnum == null) {
|
||||
this.onUnknownCmd((T) BaseBinaryFrameHandler.this, cmdMsg.getCmd(), cmdMsg);
|
||||
} else {
|
||||
this.onCmdMsg((T) BaseBinaryFrameHandler.this, (CmdEnum) cmdEnum, (BaseCmdMsg<CmdEnum>) cmdMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
if (cause.getCause() instanceof UnrecognizedPropertyException) {
|
||||
log.error("缺少字段:{}", cause.getMessage());
|
||||
} else {
|
||||
super.exceptionCaught(ctx, cause);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMsg(T t, IMsg msg) {
|
||||
IBaseMsgListener.super.onMsg(t, msg);
|
||||
iteratorMsgListeners(msgListener -> msgListener.onMsg(t, msg));
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写该方法,判断CMD,或者调用{@link IBaseMsgListener#onOtherCmdMsg(Object, Enum, ICmdMsg)}
|
||||
*
|
||||
* @param t BaseBinaryFrameHandler
|
||||
* @param cmd CmdEnum
|
||||
* @param cmdMsg BaseMsg
|
||||
*/
|
||||
@Override
|
||||
public void onCmdMsg(T t, CmdEnum cmd, ICmdMsg<CmdEnum> cmdMsg) {
|
||||
IBaseMsgListener.super.onCmdMsg(t, cmd, cmdMsg);
|
||||
iteratorMsgListeners(msgListener -> msgListener.onCmdMsg(t, cmd, cmdMsg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnknownCmd(T t, String cmdString, IMsg msg) {
|
||||
IBaseMsgListener.super.onUnknownCmd(t, cmdString, msg);
|
||||
iteratorMsgListeners(msgListener -> msgListener.onUnknownCmd(t, cmdString, msg));
|
||||
}
|
||||
|
||||
@SuppressWarnings("ForLoopReplaceableByForEach")
|
||||
public void iteratorMsgListeners(Consumer<MsgListener> consumer) {
|
||||
if (msgListeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < msgListeners.size(); i++) {
|
||||
consumer.accept(msgListeners.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCmdMsg(T t, CmdEnum cmd, BaseCmdMsg<CmdEnum> cmdMsg) {
|
||||
IBaseMsgListener.super.onCmdMsg(t, cmd, cmdMsg);
|
||||
iteratorMsgListeners(msgListener -> msgListener.onCmdMsg(t, cmd, cmdMsg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnknownCmd(T t, String cmdString, BaseMsg msg) {
|
||||
IBaseMsgListener.super.onUnknownCmd(t, cmdString, msg);
|
||||
iteratorMsgListeners(msgListener -> msgListener.onUnknownCmd(t, cmdString, msg));
|
||||
}
|
||||
|
||||
public String getRoomIdAsString() {
|
||||
if (this.roomId == null) {
|
||||
return "";
|
||||
}
|
||||
return this.roomId.toString();
|
||||
}
|
||||
|
||||
public long getRoomIdAsLong() {
|
||||
String roomIdAsString = this.getRoomIdAsString();
|
||||
if (roomIdAsString.trim().isEmpty()) {
|
||||
return 0L;
|
||||
}
|
||||
return Long.parseLong(roomIdAsString);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.servers.netty.handler.base;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.handler.codec.http.FullHttpResponse;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketHandshakeException;
|
||||
import io.netty.handler.ssl.SslCloseCompletionEvent;
|
||||
import io.netty.handler.ssl.SslHandshakeCompletionEvent;
|
||||
import io.netty.util.concurrent.ScheduledFuture;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseConnectionListener;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
/**
|
||||
* 连接处理器
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/21
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class BaseConnectionHandler<ConnectionHandler extends BaseConnectionHandler<?>> extends SimpleChannelInboundHandler<FullHttpResponse> {
|
||||
|
||||
private final WebSocketClientHandshaker handshaker;
|
||||
@Getter
|
||||
private ChannelPromise handshakeFuture;
|
||||
private final IBaseConnectionListener<ConnectionHandler> listener;
|
||||
/**
|
||||
* 客户端发送心跳包
|
||||
*/
|
||||
private ScheduledFuture<?> scheduledFuture = null;
|
||||
|
||||
public BaseConnectionHandler(WebSocketClientHandshaker handshaker, IBaseConnectionListener<ConnectionHandler> listener) {
|
||||
this.handshaker = handshaker;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public BaseConnectionHandler(WebSocketClientHandshaker handshaker) {
|
||||
this(handshaker, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handlerAdded(ChannelHandlerContext ctx) {
|
||||
this.handshakeFuture = ctx.newPromise();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) {
|
||||
this.handshaker.handshake(ctx.channel());
|
||||
}
|
||||
|
||||
protected void channelRead0(ChannelHandlerContext ctx, FullHttpResponse msg) throws Exception {
|
||||
// 判断是否正确握手
|
||||
if (this.handshaker.isHandshakeComplete()) {
|
||||
handshakeSuccessfully(ctx, msg);
|
||||
} else {
|
||||
try {
|
||||
handshakeSuccessfully(ctx, msg);
|
||||
} catch (WebSocketHandshakeException e) {
|
||||
handshakeFailed(msg, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("userEventTriggered {}", evt.getClass());
|
||||
}
|
||||
if (evt instanceof SslHandshakeCompletionEvent) {
|
||||
heartbeatCancel();
|
||||
heartbeatStart(ctx);
|
||||
if (this.listener != null) {
|
||||
listener.onConnected((ConnectionHandler) BaseConnectionHandler.this);
|
||||
}
|
||||
} else if (evt instanceof SslCloseCompletionEvent) {
|
||||
heartbeatCancel();
|
||||
if (this.listener != null) {
|
||||
listener.onDisconnected((ConnectionHandler) BaseConnectionHandler.this);
|
||||
}
|
||||
} else {
|
||||
log.error("待处理 {}", evt.getClass());
|
||||
}
|
||||
super.userEventTriggered(ctx, evt);
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始发送心跳包
|
||||
*/
|
||||
private void heartbeatStart(ChannelHandlerContext ctx) {
|
||||
scheduledFuture = ctx.executor().scheduleAtFixedRate(() -> {
|
||||
sendHeartbeat(ctx);
|
||||
}, getHeartbeatInitialDelay(), getHeartbeatPeriod(), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消发送心跳包
|
||||
*/
|
||||
private void heartbeatCancel() {
|
||||
if (null != scheduledFuture && !scheduledFuture.isCancelled()) {
|
||||
scheduledFuture.cancel(true);
|
||||
scheduledFuture = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void sendHeartbeat(ChannelHandlerContext ctx);
|
||||
|
||||
public abstract void sendAuthRequest(Channel channel);
|
||||
|
||||
protected abstract long getHeartbeatPeriod();
|
||||
|
||||
protected abstract long getHeartbeatInitialDelay();
|
||||
|
||||
private void handshakeSuccessfully(ChannelHandlerContext ctx, FullHttpResponse msg) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("握手完成!");
|
||||
}
|
||||
this.handshaker.finishHandshake(ctx.channel(), msg);
|
||||
this.handshakeFuture.setSuccess();
|
||||
}
|
||||
|
||||
private void handshakeFailed(FullHttpResponse msg, WebSocketHandshakeException e) {
|
||||
log.error("握手失败!status:" + msg.status(), e);
|
||||
this.handshakeFuture.setFailure(e);
|
||||
if (listener != null) {
|
||||
this.listener.onConnectFailed((ConnectionHandler) this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
log.error("exceptionCaught", cause);
|
||||
if (!this.handshakeFuture.isDone()) {
|
||||
this.handshakeFuture.setFailure(cause);
|
||||
}
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
46
ruoyi-modules/ruoyi-live/live-chat-client-servers/pom.xml
Normal file
46
ruoyi-modules/ruoyi-live/live-chat-client-servers/pom.xml
Normal file
@@ -0,0 +1,46 @@
|
||||
<!--
|
||||
~ MIT License
|
||||
~
|
||||
~ Copyright (c) 2023 OrdinaryRoad
|
||||
~
|
||||
~ Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
~ of this software and associated documentation files (the "Software"), to deal
|
||||
~ in the Software without restriction, including without limitation the rights
|
||||
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
~ copies of the Software, and to permit persons to whom the Software is
|
||||
~ furnished to do so, subject to the following conditions:
|
||||
~
|
||||
~ The above copyright notice and this permission notice shall be included in all
|
||||
~ copies or substantial portions of the Software.
|
||||
~
|
||||
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
~ SOFTWARE.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-live</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<artifactId>live-chat-client-servers</artifactId>
|
||||
<name>live-chat-client-servers</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
<module>live-chat-client-servers-netty</module>
|
||||
<module>live-chat-client-servers-netty-client</module>
|
||||
</modules>
|
||||
</project>
|
||||
@@ -0,0 +1,70 @@
|
||||
<!--
|
||||
~ MIT License
|
||||
~
|
||||
~ Copyright (c) 2023 OrdinaryRoad
|
||||
~
|
||||
~ Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
~ of this software and associated documentation files (the "Software"), to deal
|
||||
~ in the Software without restriction, including without limitation the rights
|
||||
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
~ copies of the Software, and to permit persons to whom the Software is
|
||||
~ furnished to do so, subject to the following conditions:
|
||||
~
|
||||
~ The above copyright notice and this permission notice shall be included in all
|
||||
~ copies or substantial portions of the Software.
|
||||
~
|
||||
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
~ SOFTWARE.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>live-chat-clients</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<artifactId>live-chat-client-bilibili</artifactId>
|
||||
<name>live-chat-client-bilibili</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>live-chat-client-servers-netty-client</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.aayushatharva.brotli4j</groupId>
|
||||
<artifactId>brotli4j</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java-util</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>${junit-jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.bilibili.api;
|
||||
|
||||
import cn.hutool.cache.impl.TimedCache;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import lombok.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.api.request.BilibiliLikeReportV3Request;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.api.request.BilibiliSendMsgRequest;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.exception.BaseException;
|
||||
import tech.ordinaryroad.live.chat.client.commons.util.OrLiveChatCookieUtil;
|
||||
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static tech.ordinaryroad.live.chat.client.commons.base.msg.BaseMsg.OBJECT_MAPPER;
|
||||
|
||||
/**
|
||||
* B站API简易版
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/5/5
|
||||
*/
|
||||
@Slf4j
|
||||
public class BilibiliApis {
|
||||
|
||||
public static final TimedCache<Long, String> GIFT_IMG_CACHE = new TimedCache<>(TimeUnit.DAYS.toMillis(1));
|
||||
public static final String KEY_COOKIE_CSRF = "bili_jct";
|
||||
public static final String KEY_UID = "DedeUserID";
|
||||
|
||||
@SneakyThrows
|
||||
public static RoomInitResult roomInit(long roomId, String cookie) {
|
||||
@Cleanup
|
||||
HttpResponse response = createGetRequest("https://api.live.bilibili.com/room/v1/Room/room_init?id=" + roomId, cookie).execute();
|
||||
JsonNode dataJsonNode = responseInterceptor(response.body());
|
||||
return OBJECT_MAPPER.readValue(dataJsonNode.toString(), RoomInitResult.class);
|
||||
}
|
||||
|
||||
public static JsonNode roomGiftConfig(long roomId, String cookie) {
|
||||
@Cleanup
|
||||
HttpResponse response = createGetRequest("https://api.live.bilibili.com/xlive/web-room/v1/giftPanel/roomGiftConfig?platform=pc&source=live&build=0&global_version=0&room_id=" + roomId, cookie).execute();
|
||||
return responseInterceptor(response.body());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param roomId
|
||||
* @param type 直播间用0
|
||||
* @return <pre>{@code
|
||||
* {
|
||||
* "group": "live",
|
||||
* "business_id": 0,
|
||||
* "refresh_row_factor": 0.125,
|
||||
* "refresh_rate": 100,
|
||||
* "max_delay": 5000,
|
||||
* "token": "-wm5-Qo4BBAztd1qp5ZJpgyTMRBhCc7yikz5d9rAd63PV46G9BMwl0R10kMM8Ilb-UieZGjLtipPrz4Cvi0DdhGFwOi8PJpFN9K-LoXh6Z_4yjEIwgRerDiMIstHzJ80J3B7wnRisAYkWA==",
|
||||
* "host_list": [{
|
||||
* "host": "ali-bj-live-comet-09.chat.bilibili.com",
|
||||
* "port": 2243,
|
||||
* "wss_port": 443,
|
||||
* "ws_port": 2244
|
||||
* }, {
|
||||
* "host": "ali-gz-live-comet-02.chat.bilibili.com",
|
||||
* "port": 2243,
|
||||
* "wss_port": 443,
|
||||
* "ws_port": 2244
|
||||
* }, {
|
||||
* "host": "broadcastlv.chat.bilibili.com",
|
||||
* "port": 2243,
|
||||
* "wss_port": 443,
|
||||
* "ws_port": 2244
|
||||
* }]
|
||||
* }
|
||||
* }</pre>
|
||||
*/
|
||||
public static JsonNode getDanmuInfo(long roomId, int type, String cookie) {
|
||||
@Cleanup
|
||||
HttpResponse response = createGetRequest("https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo?id=" + roomId + "&type=" + type, cookie).execute();
|
||||
return responseInterceptor(response.body());
|
||||
}
|
||||
|
||||
public static String getGiftImgById(long giftId, long roomId) {
|
||||
if (!GIFT_IMG_CACHE.containsKey(giftId)) {
|
||||
ThreadUtil.execAsync(() -> {
|
||||
updateGiftImgCache(roomId, null);
|
||||
});
|
||||
}
|
||||
|
||||
return GIFT_IMG_CACHE.get(giftId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新礼物图片缓存
|
||||
*/
|
||||
public static void updateGiftImgCache(long roomId, String cookie) {
|
||||
JsonNode jsonNode = roomGiftConfig(roomId, cookie);
|
||||
for (JsonNode node : jsonNode.get("global_gift").get("list")) {
|
||||
long giftId = node.get("id").asLong();
|
||||
String giftImgUrl = node.get("webp").asText();
|
||||
GIFT_IMG_CACHE.put(giftId, giftImgUrl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送弹幕
|
||||
*
|
||||
* @param request {@link BilibiliSendMsgRequest}
|
||||
* @param cookie Cookie
|
||||
*/
|
||||
public static void sendMsg(BilibiliSendMsgRequest request, String cookie) {
|
||||
if (StrUtil.isBlank(cookie)) {
|
||||
throw new BaseException("发送弹幕接口cookie不能为空");
|
||||
}
|
||||
Map<String, Object> stringObjectMap = BeanUtil.beanToMap(request);
|
||||
@Cleanup HttpResponse execute = HttpUtil.createPost("https://api.live.bilibili.com/msg/send")
|
||||
.cookie(cookie)
|
||||
.form(stringObjectMap)
|
||||
.execute();
|
||||
responseInterceptor(execute.body());
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送弹幕
|
||||
*
|
||||
* @param msg 内容
|
||||
* @param realRoomId 真实房间id
|
||||
* @param cookie Cookie
|
||||
*/
|
||||
public static void sendMsg(String msg, long realRoomId, String cookie) {
|
||||
String biliJct = OrLiveChatCookieUtil.getCookieByName(cookie, KEY_COOKIE_CSRF, () -> {
|
||||
throw new BaseException("cookie中缺少参数" + KEY_COOKIE_CSRF);
|
||||
});
|
||||
BilibiliSendMsgRequest request = new BilibiliSendMsgRequest(msg, StrUtil.toString(ZonedDateTime.now(ZoneId.of("Asia/Shanghai")).toEpochSecond()), realRoomId, biliJct, biliJct);
|
||||
sendMsg(request, cookie);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为主播点赞
|
||||
*
|
||||
* @param request {@link BilibiliLikeReportV3Request}
|
||||
* @param cookie Cookie
|
||||
*/
|
||||
public static void likeReportV3(BilibiliLikeReportV3Request request, String cookie) {
|
||||
if (StrUtil.isBlank(cookie)) {
|
||||
throw new BaseException("为主播点赞接口cookie不能为空");
|
||||
}
|
||||
Map<String, Object> stringObjectMap = BeanUtil.beanToMap(request);
|
||||
@Cleanup HttpResponse execute = HttpUtil.createPost("https://api.live.bilibili.com/xlive/app-ucenter/v1/like_info_v3/like/likeReportV3")
|
||||
.cookie(cookie)
|
||||
.form(stringObjectMap)
|
||||
.execute();
|
||||
responseInterceptor(execute.body());
|
||||
}
|
||||
|
||||
/**
|
||||
* 为主播点赞
|
||||
*
|
||||
* @param anchor_id 主播Uid {@link RoomInitResult#uid}
|
||||
* @param realRoomId 真实房间Id {@link RoomInitResult#room_id}
|
||||
* @param cookie Cookie
|
||||
*/
|
||||
public static void likeReportV3(long anchor_id, long realRoomId, String cookie) {
|
||||
String uid = OrLiveChatCookieUtil.getCookieByName(cookie, KEY_UID, () -> {
|
||||
throw new BaseException("cookie中缺少参数" + KEY_UID);
|
||||
});
|
||||
String biliJct = OrLiveChatCookieUtil.getCookieByName(cookie, KEY_COOKIE_CSRF, () -> {
|
||||
throw new BaseException("cookie中缺少参数" + KEY_COOKIE_CSRF);
|
||||
});
|
||||
BilibiliLikeReportV3Request request = new BilibiliLikeReportV3Request(realRoomId, uid, anchor_id, biliJct, biliJct);
|
||||
likeReportV3(request, cookie);
|
||||
}
|
||||
|
||||
public static HttpRequest createGetRequest(String url, String cookies) {
|
||||
return HttpUtil.createGet(url)
|
||||
.cookie(cookies);
|
||||
}
|
||||
|
||||
private static JsonNode responseInterceptor(String responseString) {
|
||||
try {
|
||||
JsonNode jsonNode = OBJECT_MAPPER.readTree(responseString);
|
||||
int code = jsonNode.get("code").asInt();
|
||||
if (code == 0) {
|
||||
// 成功
|
||||
return jsonNode.get("data");
|
||||
} else {
|
||||
throw new BaseException(jsonNode.get("message").asText());
|
||||
}
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new BaseException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class RoomInitResult {
|
||||
private long room_id;
|
||||
private int short_id;
|
||||
private long uid;
|
||||
private int need_p2p;
|
||||
private boolean is_hidden;
|
||||
private boolean is_locked;
|
||||
private boolean is_portrait;
|
||||
private int live_status;
|
||||
private int hidden_till;
|
||||
private int lock_till;
|
||||
private boolean encrypted;
|
||||
private boolean pwd_verified;
|
||||
private long live_time;
|
||||
private int room_shield;
|
||||
private int is_sp;
|
||||
private int special_type;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.bilibili.api.request;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2024/1/31
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class BilibiliLikeReportV3Request {
|
||||
/**
|
||||
* 本次点赞次数
|
||||
*/
|
||||
private int click_time = 1;
|
||||
/**
|
||||
* 房间真实ID
|
||||
*/
|
||||
private long room_id;
|
||||
/**
|
||||
* Cookie中的DedeUserID
|
||||
*/
|
||||
private String uid;
|
||||
/**
|
||||
* RoomInitResult中的uid
|
||||
*/
|
||||
private long anchor_id;
|
||||
/**
|
||||
* Cookie中的bili_jct
|
||||
*/
|
||||
private String csrf;
|
||||
/**
|
||||
* Cookie中的bili_jct
|
||||
*/
|
||||
private String csrf_token;
|
||||
/**
|
||||
* 暂时留空
|
||||
*/
|
||||
private String visit_id = StrUtil.EMPTY;
|
||||
|
||||
public BilibiliLikeReportV3Request(long room_id, String uid, long anchor_id, String csrf, String csrf_token) {
|
||||
this.room_id = room_id;
|
||||
this.uid = uid;
|
||||
this.anchor_id = anchor_id;
|
||||
this.csrf = csrf;
|
||||
this.csrf_token = csrf_token;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.bilibili.api.request;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/7
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class BilibiliSendMsgRequest {
|
||||
private String bubble = "0";
|
||||
/**
|
||||
* 弹幕内容
|
||||
*/
|
||||
private String msg;
|
||||
/**
|
||||
* 弹幕颜色
|
||||
*/
|
||||
private String color = "16777215";
|
||||
private String mode = "1";
|
||||
private String room_type = "0";
|
||||
private String jumpfrom = "0";
|
||||
/**
|
||||
* 字体大小
|
||||
*/
|
||||
private String fontsize = "25";
|
||||
/**
|
||||
* 时间戳(秒)
|
||||
*/
|
||||
private String rnd;
|
||||
/**
|
||||
* 房间真实ID
|
||||
*/
|
||||
private long roomid;
|
||||
/**
|
||||
* Cookie中的bili_jct
|
||||
*/
|
||||
private String csrf;
|
||||
/**
|
||||
* Cookie中的bili_jct
|
||||
*/
|
||||
private String csrf_token;
|
||||
|
||||
public BilibiliSendMsgRequest(String msg, String rnd, long roomid, String csrf, String csrf_token) {
|
||||
this.msg = msg;
|
||||
this.rnd = rnd;
|
||||
this.roomid = roomid;
|
||||
this.csrf = csrf;
|
||||
this.csrf_token = csrf_token;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.bilibili.client;
|
||||
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.handler.codec.http.DefaultHttpHeaders;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.api.BilibiliApis;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.config.BilibiliLiveChatClientConfig;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.constant.BilibiliCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.listener.IBilibiliConnectionListener;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.listener.IBilibiliMsgListener;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.msg.base.IBilibiliMsg;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.netty.handler.BilibiliBinaryFrameHandler;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.netty.handler.BilibiliConnectionHandler;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.exception.BaseException;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseConnectionListener;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.client.base.BaseNettyClient;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* B站直播间弹幕客户端
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/20
|
||||
*/
|
||||
@Slf4j
|
||||
public class BilibiliLiveChatClient extends BaseNettyClient<
|
||||
BilibiliLiveChatClientConfig,
|
||||
BilibiliCmdEnum,
|
||||
IBilibiliMsg,
|
||||
IBilibiliMsgListener,
|
||||
BilibiliConnectionHandler,
|
||||
BilibiliBinaryFrameHandler
|
||||
> {
|
||||
|
||||
private BilibiliApis.RoomInitResult roomInitResult = new BilibiliApis.RoomInitResult();
|
||||
|
||||
public BilibiliLiveChatClient(BilibiliLiveChatClientConfig config, List<IBilibiliMsgListener> msgListeners, IBilibiliConnectionListener connectionListener, EventLoopGroup workerGroup) {
|
||||
super(config, workerGroup, connectionListener);
|
||||
addMsgListeners(msgListeners);
|
||||
|
||||
// 初始化
|
||||
this.init();
|
||||
}
|
||||
|
||||
public BilibiliLiveChatClient(BilibiliLiveChatClientConfig config, IBilibiliMsgListener msgListener, IBilibiliConnectionListener connectionListener, EventLoopGroup workerGroup) {
|
||||
super(config, workerGroup, connectionListener);
|
||||
addMsgListener(msgListener);
|
||||
|
||||
// 初始化
|
||||
this.init();
|
||||
}
|
||||
|
||||
public BilibiliLiveChatClient(BilibiliLiveChatClientConfig config, IBilibiliMsgListener msgListener, IBilibiliConnectionListener connectionListener) {
|
||||
this(config, msgListener, connectionListener, new NioEventLoopGroup());
|
||||
}
|
||||
|
||||
public BilibiliLiveChatClient(BilibiliLiveChatClientConfig config, IBilibiliMsgListener msgListener) {
|
||||
this(config, msgListener, null, new NioEventLoopGroup());
|
||||
}
|
||||
|
||||
public BilibiliLiveChatClient(BilibiliLiveChatClientConfig config) {
|
||||
this(config, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
roomInitResult = BilibiliApis.roomInit(getConfig().getRoomId(), getConfig().getCookie());
|
||||
super.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BilibiliConnectionHandler initConnectionHandler(IBaseConnectionListener<BilibiliConnectionHandler> clientConnectionListener) {
|
||||
return new BilibiliConnectionHandler(
|
||||
WebSocketClientHandshakerFactory.newHandshaker(getWebsocketUri(), WebSocketVersion.V13, null, true, new DefaultHttpHeaders(), getConfig().getMaxFramePayloadLength()),
|
||||
BilibiliLiveChatClient.this, clientConnectionListener
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BilibiliBinaryFrameHandler initBinaryFrameHandler() {
|
||||
return new BilibiliBinaryFrameHandler(super.msgListeners, BilibiliLiveChatClient.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDanmu(Object danmu, Runnable success, Consumer<Throwable> failed) {
|
||||
if (!checkCanSendDanmu(false)) {
|
||||
return;
|
||||
}
|
||||
if (danmu instanceof String) {
|
||||
String msg = (String) danmu;
|
||||
try {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("{} bilibili发送弹幕 {}", getConfig().getRoomId(), danmu);
|
||||
}
|
||||
|
||||
boolean sendSuccess = false;
|
||||
try {
|
||||
BilibiliApis.sendMsg(msg, roomInitResult.getRoom_id(), getConfig().getCookie());
|
||||
sendSuccess = true;
|
||||
} catch (Exception e) {
|
||||
log.error("bilibili弹幕发送失败", e);
|
||||
if (failed != null) {
|
||||
failed.accept(e);
|
||||
}
|
||||
}
|
||||
if (!sendSuccess) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("bilibili弹幕发送成功 {}", danmu);
|
||||
}
|
||||
if (success != null) {
|
||||
success.run();
|
||||
}
|
||||
finishSendDanmu();
|
||||
} catch (Exception e) {
|
||||
log.error("bilibili弹幕发送失败", e);
|
||||
if (failed != null) {
|
||||
failed.accept(e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
super.sendDanmu(danmu, success, failed);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clickLike(int count, Runnable success, Consumer<Throwable> failed) {
|
||||
if (count <= 0) {
|
||||
throw new BaseException("点赞次数必须大于0");
|
||||
}
|
||||
|
||||
boolean successfullyClicked = false;
|
||||
try {
|
||||
BilibiliApis.likeReportV3(roomInitResult.getUid(), roomInitResult.getRoom_id(), getConfig().getCookie());
|
||||
successfullyClicked = true;
|
||||
} catch (Exception e) {
|
||||
log.error("Bilibili为直播间点赞失败", e);
|
||||
if (failed != null) {
|
||||
failed.accept(e);
|
||||
}
|
||||
}
|
||||
if (!successfullyClicked) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Bilibili为直播间点赞成功");
|
||||
}
|
||||
if (success != null) {
|
||||
success.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.bilibili.config;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.constant.ProtoverEnum;
|
||||
import tech.ordinaryroad.live.chat.client.commons.util.OrLiveChatNumberUtil;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.client.config.BaseNettyClientConfig;
|
||||
|
||||
/**
|
||||
* B站直播间弹幕客户端配置
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/21
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@SuperBuilder(toBuilder = true)
|
||||
public class BilibiliLiveChatClientConfig extends BaseNettyClientConfig {
|
||||
|
||||
/**
|
||||
* @see ProtoverEnum
|
||||
*/
|
||||
@Builder.Default
|
||||
private ProtoverEnum protover = ProtoverEnum.NORMAL_ZLIB;
|
||||
|
||||
@Builder.Default
|
||||
private String websocketUri = "wss://broadcastlv.chat.bilibili.com:443/sub";
|
||||
|
||||
@Override
|
||||
public Long getRoomId() {
|
||||
return OrLiveChatNumberUtil.parseLong(super.getRoomId());
|
||||
}
|
||||
|
||||
public void setProtover(ProtoverEnum protover) {
|
||||
ProtoverEnum oldValue = this.protover;
|
||||
this.protover = protover;
|
||||
super.propertyChangeSupport.firePropertyChange("protover", oldValue, protover);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.bilibili.constant;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/1/6
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum BilibiliCmdEnum {
|
||||
/**
|
||||
* 游客状态下,5分钟后会出现登录提示,弹幕中的用户名、用户id等信息将不再可见
|
||||
*/
|
||||
LOG_IN_NOTICE,
|
||||
/**
|
||||
* 收到弹幕
|
||||
*/
|
||||
DANMU_MSG,
|
||||
/**
|
||||
* 收到礼物
|
||||
*/
|
||||
SEND_GIFT,
|
||||
/**
|
||||
* 有人上舰
|
||||
*/
|
||||
GUARD_BUY,
|
||||
/**
|
||||
* 欢迎舰长
|
||||
*/
|
||||
WELCOME_GUARD,
|
||||
WELCOME,
|
||||
/**
|
||||
* 礼物连击
|
||||
*/
|
||||
COMBO_SEND,
|
||||
/**
|
||||
* 欢迎高能用户、(舰长?待验证)特殊消息
|
||||
*/
|
||||
ENTRY_EFFECT,
|
||||
HOT_RANK_CHANGED,
|
||||
HOT_RANK_CHANGED_V2,
|
||||
INTERACT_WORD,
|
||||
/**
|
||||
* 开始直播
|
||||
*/
|
||||
LIVE,
|
||||
LIVE_INTERACTIVE_GAME,
|
||||
NOTICE_MSG,
|
||||
/**
|
||||
* 高能榜数量更新
|
||||
*/
|
||||
ONLINE_RANK_COUNT,
|
||||
ONLINE_RANK_TOP3,
|
||||
ONLINE_RANK_V2,
|
||||
PK_BATTLE_END,
|
||||
PK_BATTLE_FINAL_PROCESS,
|
||||
PK_BATTLE_PROCESS,
|
||||
PK_BATTLE_PROCESS_NEW,
|
||||
PK_BATTLE_SETTLE,
|
||||
PK_BATTLE_SETTLE_USER,
|
||||
PK_BATTLE_SETTLE_V2,
|
||||
/**
|
||||
* 主播准备中
|
||||
*/
|
||||
PREPARING,
|
||||
ROOM_REAL_TIME_MESSAGE_UPDATE,
|
||||
/**
|
||||
* 停止直播的房间ID列表
|
||||
*/
|
||||
STOP_LIVE_ROOM_LIST,
|
||||
/**
|
||||
* 醒目留言
|
||||
*/
|
||||
SUPER_CHAT_MESSAGE,
|
||||
SUPER_CHAT_MESSAGE_JPN,
|
||||
/**
|
||||
* 删除醒目留言
|
||||
*/
|
||||
SUPER_CHAT_MESSAGE_DELETE,
|
||||
WIDGET_BANNER,
|
||||
/**
|
||||
* 点赞数更新
|
||||
*/
|
||||
LIKE_INFO_V3_UPDATE,
|
||||
/**
|
||||
* 为主播点赞
|
||||
*/
|
||||
LIKE_INFO_V3_CLICK,
|
||||
HOT_ROOM_NOTIFY,
|
||||
/**
|
||||
* 观看人数变化
|
||||
*/
|
||||
WATCHED_CHANGE,
|
||||
POPULAR_RANK_CHANGED,
|
||||
COMMON_NOTICE_DANMAKU,
|
||||
LIVE_MULTI_VIEW_CHANGE,
|
||||
RECOMMEND_CARD,
|
||||
PK_BATTLE_START_NEW,
|
||||
PK_BATTLE_ENTRANCE,
|
||||
AREA_RANK_CHANGED,
|
||||
ROOM_BLOCK_MSG,
|
||||
USER_TOAST_MSG,
|
||||
PK_BATTLE_PRE_NEW,
|
||||
PK_BATTLE_RANK_CHANGE,
|
||||
PK_BATTLE_START,
|
||||
PK_BATTLE_PRE,
|
||||
PLAY_TAG,
|
||||
;
|
||||
|
||||
public static BilibiliCmdEnum getByString(String cmd) {
|
||||
try {
|
||||
return BilibiliCmdEnum.valueOf(cmd);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.bilibili.constant;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/1/5
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum OperationEnum {
|
||||
HANDSHAKE(0),
|
||||
HANDSHAKE_REPLY(1),
|
||||
/**
|
||||
* 心跳包
|
||||
*/
|
||||
HEARTBEAT(2),
|
||||
/**
|
||||
* 心跳包回复(人气值)
|
||||
*/
|
||||
HEARTBEAT_REPLY(3),
|
||||
SEND_MSG(4),
|
||||
|
||||
/**
|
||||
* 普通包(命令)
|
||||
*/
|
||||
SEND_SMS_REPLY(5),
|
||||
DISCONNECT_REPLY(6),
|
||||
|
||||
/**
|
||||
* 认证包
|
||||
*/
|
||||
AUTH(7),
|
||||
|
||||
/**
|
||||
* 认证包回复
|
||||
*/
|
||||
AUTH_REPLY(8),
|
||||
RAW(9),
|
||||
PROTO_READY(10),
|
||||
PROTO_FINISH(11),
|
||||
CHANGE_ROOM(12),
|
||||
CHANGE_ROOM_REPLY(13),
|
||||
REGISTER(14),
|
||||
REGISTER_REPLY(15),
|
||||
UNREGISTER(16),
|
||||
UNREGISTER_REPLY(17),
|
||||
;
|
||||
|
||||
private final int code;
|
||||
|
||||
public static OperationEnum getByCode(int code) {
|
||||
for (OperationEnum value : OperationEnum.values()) {
|
||||
if (value.code == code) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.bilibili.constant;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/1/5
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum ProtoverEnum {
|
||||
/**
|
||||
* 普通包正文不使用压缩
|
||||
*/
|
||||
NORMAL_NO_COMPRESSION(0),
|
||||
/**
|
||||
* 心跳及认证包正文不使用压缩
|
||||
*/
|
||||
HEARTBEAT_AUTH_NO_COMPRESSION(1),
|
||||
/**
|
||||
* 普通包正文使用zlib压缩
|
||||
*/
|
||||
NORMAL_ZLIB(2),
|
||||
/**
|
||||
* 普通包正文使用brotli压缩,解压为一个带头部的协议0普通包
|
||||
*/
|
||||
NORMAL_BROTLI(3),
|
||||
;
|
||||
|
||||
private final int code;
|
||||
|
||||
|
||||
public static ProtoverEnum getByCode(int code) {
|
||||
for (ProtoverEnum value : ProtoverEnum.values()) {
|
||||
if (value.code == code) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user