├── accenbot-logo-1.png └── src ├── main ├── webapp │ ├── index.jsp │ └── WEB-INF │ │ └── web.xml ├── java │ └── org │ │ └── accen │ │ └── dmzj │ │ ├── core │ │ ├── annotation │ │ │ ├── DependMode.java │ │ │ ├── AutowiredParam.java │ │ │ ├── AutowiredRegular.java │ │ │ ├── Dependency.java │ │ │ ├── Rejection.java │ │ │ ├── MessageRegular.java │ │ │ ├── CmdMessage.java │ │ │ ├── CmdRequest.java │ │ │ ├── Order.java │ │ │ ├── FuncSwitchGroup.java │ │ │ ├── HandlerChain.java │ │ │ ├── CmdMeta.java │ │ │ ├── CmdRegular.java │ │ │ ├── CmdNotice.java │ │ │ ├── GeneralMessage.java │ │ │ └── FuncSwitch.java │ │ ├── meta │ │ │ ├── PostType.java │ │ │ ├── MessageType.java │ │ │ ├── RequestSubType.java │ │ │ ├── RequestType.java │ │ │ ├── MetaEventType.java │ │ │ ├── MetaSubType.java │ │ │ ├── MessageSubType.java │ │ │ ├── NoticeType.java │ │ │ └── NoticeSubType.java │ │ ├── handler │ │ │ ├── EventHandler.java │ │ │ ├── cmd │ │ │ │ ├── CallbackAdpter.java │ │ │ │ ├── CmdAdapter.java │ │ │ │ ├── AtSelfCmd.java │ │ │ │ ├── BiliBiliCookie.java │ │ │ │ ├── Repeat.java │ │ │ │ ├── ChaosMode.java │ │ │ │ ├── KamenRiderCmd.java │ │ │ │ ├── RepeatModeSwitch.java │ │ │ │ ├── GroupNotice.java │ │ │ │ ├── BaiduBaike.java │ │ │ │ ├── Draw.java │ │ │ │ ├── TimerCmd.java │ │ │ │ ├── SetWelcome.java │ │ │ │ └── TriggerProSwitchCmd.java │ │ │ ├── group │ │ │ │ ├── System.java │ │ │ │ ├── Subscribe.java │ │ │ │ ├── Default.java │ │ │ │ ├── Audio.java │ │ │ │ ├── Entry.java │ │ │ │ ├── Pedia.java │ │ │ │ └── Image.java │ │ │ ├── callbacker │ │ │ │ ├── AsyncCallback.java │ │ │ │ ├── CallbackListener.java │ │ │ │ └── CallbackManager.java │ │ │ ├── listen │ │ │ │ ├── ListenStatus.java │ │ │ │ ├── ListenAdpter.java │ │ │ │ ├── ChaosListener.java │ │ │ │ ├── RandomRepeatListener.java │ │ │ │ └── SetuCatchListener.java │ │ │ ├── ModeCmd.java │ │ │ └── CmdManager.java │ │ ├── api │ │ │ ├── pixivc │ │ │ │ ├── Auth.java │ │ │ │ ├── AuthFresher.java │ │ │ │ ├── AuthHolder.java │ │ │ │ ├── PixivcAuthConfiguration.java │ │ │ │ ├── PixivicApiClient.java │ │ │ │ ├── LocalAuthHolder.java │ │ │ │ ├── PixivcAuthConfigurationProperties.java │ │ │ │ └── PixivcAuthFeignRequestInterceptor.java │ │ │ ├── LoliconApiClient.java │ │ │ ├── vo │ │ │ │ ├── BilibiliBangumiInfo.java │ │ │ │ ├── SteamApp.java │ │ │ │ ├── BilibiliUserInfo.java │ │ │ │ ├── BaikeResult.java │ │ │ │ ├── BilibliVideoInfo.java │ │ │ │ ├── Music163Result.java │ │ │ │ ├── SteamNew.java │ │ │ │ ├── ImageResult.java │ │ │ │ ├── YoudaoTranslateResult.java │ │ │ │ └── BilibiliSearch.java │ │ │ ├── PixivcatApiClient.java │ │ │ ├── steam │ │ │ │ ├── SteamStoreApiClient.java │ │ │ │ ├── SteamNewsFormatter.java │ │ │ │ ├── SteamVariableConfiguration.java │ │ │ │ ├── SteamPoweredApiClient.java │ │ │ │ └── SteamConfiguration.java │ │ │ ├── HitokotoApiClient.java │ │ │ ├── bilibili │ │ │ │ ├── LiveBilibiliApiClient.java │ │ │ │ └── ApiVcBilibiliApiClient.java │ │ │ ├── YoudaoApiClient.java │ │ │ ├── KaassApiClient.java │ │ │ ├── JiRenGuApiClient.java │ │ │ ├── GoogleTranslateApiClient.java │ │ │ ├── Wiki33mApiClient.java │ │ │ ├── MusicApiClient.java │ │ │ ├── QqNickApiClient.java │ │ │ ├── SaucenaoApiClient.java │ │ │ ├── cq │ │ │ │ ├── CqhttpConfiguration.java │ │ │ │ └── CqHttpConfigurationProperties.java │ │ │ └── baidu │ │ │ │ └── BaikeRedirectClient.java │ │ ├── autoconfigure │ │ │ ├── Workdirer.java │ │ │ ├── ContextPostProcessor.java │ │ │ ├── EventPostProcessor.java │ │ │ ├── ProxyPostProcessor.java │ │ │ ├── EventCmdPostProcessor.java │ │ │ ├── CmdWorkdirIniter.java │ │ │ └── NonBeanEnviromentIniter.java │ │ ├── feign │ │ │ ├── auth │ │ │ │ ├── FirstTimeCallCase.java │ │ │ │ ├── AuthFeignRequestInterceptor.java │ │ │ │ ├── AbstractHeaderAuthCounterFeignRequestInterceptor.java │ │ │ │ └── HeaderAuthFeignRequestInterceptor.java │ │ │ └── GloabalFeignConfigration.java │ │ ├── exception │ │ │ ├── CmdRegisterException.java │ │ │ ├── MessageRegularException.java │ │ │ ├── AutowiredParamIndexException.java │ │ │ ├── DependencyRejectionException.java │ │ │ ├── AutowiredRegularIndexException.java │ │ │ ├── CmdRegularException.java │ │ │ ├── AutowiredParamException.java │ │ │ ├── PixivcAuthInitialExcpetion.java │ │ │ ├── DataNeverInitedException.java │ │ │ ├── CmdRegisterDuplicateException.java │ │ │ ├── BiliBiliCookieExpired.java │ │ │ └── BiliBiliCookieNeverInit.java │ │ ├── task │ │ │ ├── TimerTask.java │ │ │ ├── TaskProcessor.java │ │ │ ├── GeneralTask.java │ │ │ ├── TaskManager.java │ │ │ └── TaskCoolqProcessor.java │ │ ├── timer │ │ │ ├── RankType.java │ │ │ ├── PrankSchedule.java │ │ │ ├── SuddenSetuSchedule.java │ │ │ └── ReportTimeSchedule.java │ │ └── security │ │ │ └── CqhttpSecurity.java │ │ ├── util │ │ ├── setu │ │ │ ├── SetuGreper.java │ │ │ ├── PixivSetuGreper.java │ │ │ └── CqSetuGreper.java │ │ ├── render │ │ │ ├── Scaleable.java │ │ │ ├── Render.java │ │ │ ├── Backgroudable.java │ │ │ ├── LocalFileRenderImage.java │ │ │ ├── PixivUrlRenderImage.java │ │ │ └── TextRenderUtil.java │ │ ├── RandomMeta.java │ │ ├── SystemUtil.java │ │ ├── ApplicationContextUtil.java │ │ ├── QuickClassParamIndexUtil.java │ │ ├── ApproximatelyEqualsUtil.java │ │ ├── ImageUtil.java │ │ ├── CmdTipsMapper.java │ │ ├── QmessageUtil.java │ │ └── GoogleUtil.java │ │ ├── web │ │ ├── vo │ │ │ ├── SysQnum.java │ │ │ ├── CmdNodeRelation.java │ │ │ ├── CmdGameNode.java │ │ │ ├── CmdGame.java │ │ │ ├── CmdTips.java │ │ │ ├── CmdWiki.java │ │ │ ├── SysFile.java │ │ │ ├── CfgConfigValue.java │ │ │ ├── CmdMyCard.java │ │ │ ├── CmdSvPk.java │ │ │ ├── CmdSvCard.java │ │ │ ├── CfgQuickReply.java │ │ │ ├── Qmessage.java │ │ │ ├── SysRecordCount.java │ │ │ ├── CfgListenStatus.java │ │ │ ├── CfgResource.java │ │ │ ├── SysGroupMember.java │ │ │ └── CmdBuSub.java │ │ ├── dao │ │ │ ├── SysQnumMapper.java │ │ │ ├── SysFileMapper.java │ │ │ ├── CmdWikiMapper.java │ │ │ ├── QmessageMapper.java │ │ │ ├── SysRecordCountMapper.java │ │ │ ├── CfgListenStatusMapper.java │ │ │ ├── CfgConfigValueMapper.java │ │ │ └── CmdGameMapper.java │ │ └── controller │ │ │ └── EventAcceptController.java │ │ └── DmzjSpringBootApplication.java └── resources │ ├── META-INF │ ├── spring.factories │ └── accenbot-metadata.json │ ├── banner.txt │ └── application.yml └── test └── java └── dmzjbot ├── Demo.java └── Test2.java /accenbot-logo-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AcceNoi/accenbot/HEAD/accenbot-logo-1.png -------------------------------------------------------------------------------- /src/main/webapp/index.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Hello World!

4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/annotation/DependMode.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.annotation; 2 | 3 | public enum DependMode { 4 | ANY,ALL 5 | } 6 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | # Auto Configure 2 | org.springframework.boot.env.EnvironmentPostProcessor=\ 3 | org.accen.dmzj.core.task.api.PixivApiClientInitBefore -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/meta/PostType.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.meta; 2 | 3 | public enum PostType { 4 | MESSAGE, 5 | META_EVENT, 6 | NOTICE, 7 | REQUEST 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/util/setu/SetuGreper.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.util.setu; 2 | 3 | public interface SetuGreper { 4 | /** 5 | * 抓取图片,返回成功数 6 | * @return 7 | */ 8 | int grep(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/EventHandler.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler; 2 | 3 | import java.util.Map; 4 | 5 | public interface EventHandler { 6 | void handle(Map event); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/cmd/CallbackAdpter.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.cmd; 2 | 3 | /** 4 | *允许cmd开放回调的接口,即 5 | */ 6 | public interface CallbackAdpter { 7 | public void callback(); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _____ 2 | (, / | /) 3 | /---| _ _ _ __ (/_ ____/_ 4 | ) / |_(__(___(/_/ (_/_) (_) (__ 5 | (_/ -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/meta/MessageType.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.meta; 2 | 3 | public enum MessageType { 4 | _ALL, 5 | /** 6 | * 私聊 7 | */ 8 | PRIVATE, 9 | /** 10 | * 群聊 11 | */ 12 | GROUP; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/meta/RequestSubType.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.meta; 2 | 3 | public enum RequestSubType { 4 | _ALL, 5 | /** 6 | * 加群请求 7 | */ 8 | ADD, 9 | /** 10 | * 邀请登录号入群 11 | */ 12 | INVITE; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/meta/RequestType.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.meta; 2 | 3 | public enum RequestType { 4 | _ALL, 5 | /** 6 | * 加好友请求 7 | */ 8 | FRIEND, 9 | /** 10 | * 加群请求/邀请 11 | */ 12 | GROUP; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/meta/MetaEventType.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.meta; 2 | 3 | public enum MetaEventType { 4 | _ALL, 5 | /** 6 | * 生命周期 7 | */ 8 | LIFECYCLE, 9 | /** 10 | * 心跳 11 | */ 12 | HEARTBEAT; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/group/System.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.group; 2 | 3 | import org.accen.dmzj.core.annotation.FuncSwitchGroup; 4 | 5 | @FuncSwitchGroup(title = "系统",showMenu = true) 6 | public class System { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/pixivc/Auth.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.pixivc; 2 | /** 3 | * 验证信息,可以继承这个类完善更多信息,比如验证信息的有效期等,我这里只是个简单实现 4 | * @author Accen 5 | * 6 | */ 7 | public record Auth(String auth) { 8 | } 9 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | Archetype Created Web Application 7 | 8 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/autoconfigure/Workdirer.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.autoconfigure; 2 | /** 3 | * 用于cmd初始化时初始化其工作目录 4 | * @author Accen 5 | * 6 | */ 7 | public interface Workdirer { 8 | String workdir(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/group/Subscribe.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.group; 2 | 3 | import org.accen.dmzj.core.annotation.FuncSwitchGroup; 4 | 5 | @FuncSwitchGroup(title = "订阅",showMenu = true, order = 4) 6 | public class Subscribe { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/group/Default.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.group; 2 | 3 | import org.accen.dmzj.core.annotation.FuncSwitchGroup; 4 | 5 | @FuncSwitchGroup(title = "缺省", 6 | showMenu = false) 7 | public class Default { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/group/Audio.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.group; 2 | 3 | import org.accen.dmzj.core.annotation.FuncSwitchGroup; 4 | 5 | @FuncSwitchGroup(title = "音乐", 6 | showMenu = true, 7 | order = 3) 8 | public class Audio { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/group/Entry.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.group; 2 | 3 | import org.accen.dmzj.core.annotation.FuncSwitchGroup; 4 | 5 | @FuncSwitchGroup(title = "词条", 6 | order = 2, 7 | showMenu = true) 8 | public class Entry { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/group/Pedia.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.group; 2 | 3 | import org.accen.dmzj.core.annotation.FuncSwitchGroup; 4 | 5 | @FuncSwitchGroup(title = "百科", 6 | showMenu = true, 7 | order = 5) 8 | public class Pedia { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/util/render/Scaleable.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.util.render; 2 | /** 3 | * 这个接口标识是可以缩放的 4 | * @author Accen 5 | * 6 | */ 7 | public interface Scaleable { 8 | public double getScale(); 9 | public void setScale(double scale); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/meta/MetaSubType.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.meta; 2 | 3 | public enum MetaSubType { 4 | _ALL, 5 | /** 6 | * 生命周期-启用 7 | */ 8 | ENABLE, 9 | /** 10 | * 生命周期-停用 11 | */ 12 | DISABLE, 13 | /** 14 | * 生命周期-websocket连接成功 15 | */ 16 | CONNECT; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/group/Image.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.group; 2 | 3 | import org.accen.dmzj.core.annotation.FuncSwitchGroup; 4 | 5 | @FuncSwitchGroup(title = "图片", 6 | showMenu = true, 7 | matchSigns = {"图片","搜图"}, 8 | order = 1) 9 | public class Image { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/feign/auth/FirstTimeCallCase.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.feign.auth; 2 | /** 3 | * 对初次调用敏感的,适用于懒加载 4 | * @author Accen 5 | * 6 | */ 7 | public interface FirstTimeCallCase { 8 | /** 9 | * 如果是第一次调用,则额外调用此方法 10 | */ 11 | void firstTimeDo(); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/util/render/Render.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.util.render; 2 | 3 | import java.io.File; 4 | import java.io.OutputStream; 5 | /** 6 | * 绘制器 7 | * @author Accen 8 | * 9 | */ 10 | public interface Render { 11 | public void render(File outFile) throws Exception; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/accenbot-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "project":"Accenbot", 3 | "version":"2.2", 4 | "alias":"Magna", 5 | "author":"Accen", 6 | "email":"1339liu@gmail.com", 7 | "profile":"https://github.com/AcceNoi", 8 | "project-page":"https://github.com/AcceNoi/accenbot", 9 | "description":"基于Onebot-kotlin实现的QQ群聊天机器人,遵循OneBot标准。极简、高效的框架。" 10 | } -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/pixivc/AuthFresher.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.pixivc; 2 | 3 | public interface AuthFresher { 4 | /** 5 | * 验证该auth是否有效 6 | * @param auth 7 | * @return 8 | */ 9 | boolean vertify(Auth auth); 10 | /** 11 | * 刷新或产生一个新的auth 12 | * @param auth 13 | * @return 14 | */ 15 | Auth fresh(Auth auth); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/exception/CmdRegisterException.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.exception; 2 | 3 | public class CmdRegisterException extends RuntimeException{ 4 | 5 | /** 6 | * 7 | */ 8 | private static final long serialVersionUID = 2340303086887140181L; 9 | public CmdRegisterException(String message) { 10 | super(message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/exception/MessageRegularException.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.exception; 2 | 3 | public class MessageRegularException extends RuntimeException{ 4 | 5 | /** 6 | * 7 | */ 8 | private static final long serialVersionUID = 5095266396212311055L; 9 | public MessageRegularException(String message) { 10 | super(message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/util/render/Backgroudable.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.util.render; 2 | 3 | import java.awt.Graphics2D; 4 | import java.awt.image.BufferedImage; 5 | /** 6 | * 标识该render是可以自定义backgroud的 7 | * @author Accen 8 | * 9 | */ 10 | public interface Backgroudable { 11 | public void setBackgroud(Graphics2D graph); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/exception/AutowiredParamIndexException.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.exception; 2 | 3 | public class AutowiredParamIndexException extends RuntimeException{ 4 | /** 5 | * 6 | */ 7 | private static final long serialVersionUID = 1638453937508402596L; 8 | 9 | public AutowiredParamIndexException(String message) { 10 | super(message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/exception/DependencyRejectionException.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.exception; 2 | 3 | public class DependencyRejectionException extends RuntimeException{ 4 | /** 5 | * 6 | */ 7 | private static final long serialVersionUID = -3442839373133152592L; 8 | 9 | public DependencyRejectionException(String message) { 10 | super(message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/exception/AutowiredRegularIndexException.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.exception; 2 | 3 | public class AutowiredRegularIndexException extends RuntimeException{ 4 | /** 5 | * 6 | */ 7 | private static final long serialVersionUID = 1638453937508402596L; 8 | 9 | public AutowiredRegularIndexException(String message) { 10 | super(message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/pixivc/AuthHolder.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.pixivc; 2 | /** 3 | * 提供对auth的管理,可以考虑本地管理、远程管理、分布式管理、缓存管理等实现方式 4 | * @author Accen 5 | * 6 | */ 7 | public interface AuthHolder { 8 | /** 9 | * 获得auth 10 | * @return 11 | */ 12 | Auth getAuth(); 13 | /** 14 | * 更新auth 15 | * @param auth 16 | */ 17 | void updateAuth(Auth auth); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/meta/MessageSubType.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.meta; 2 | 3 | public enum MessageSubType { 4 | _ALL, 5 | /** 6 | * 私聊-好友消息 7 | */ 8 | FRIEND, 9 | /** 10 | * 私聊-群临时会话 11 | */ 12 | GROUP, 13 | /** 14 | * 私聊-其他 15 | */ 16 | OTHER, 17 | /** 18 | * 群聊-正常 19 | */ 20 | NORMAL, 21 | /** 22 | * 群聊-匿名 23 | */ 24 | ANONYMOUS, 25 | /** 26 | * 群聊-系统提示 27 | */ 28 | NOTICE; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/exception/CmdRegularException.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.exception; 2 | 3 | public class CmdRegularException extends Exception{ 4 | 5 | /** 6 | * 7 | */ 8 | private static final long serialVersionUID = 2376131230342453625L; 9 | public CmdRegularException(String cmdRegularName) { 10 | super("CmdRegular配置错误!cmdRegularName:{},当enableAutowiredParam设置为false时,不允许使用AutowiredParam进行匹配!"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/LoliconApiClient.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api; 2 | 3 | import java.util.Map; 4 | 5 | import org.springframework.cloud.openfeign.FeignClient; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | 8 | @FeignClient( 9 | name="lolicon", 10 | url="https://api.lolicon.app") 11 | public interface LoliconApiClient { 12 | @GetMapping("/setu/") 13 | public Map setu(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/cmd/CmdAdapter.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.cmd; 2 | 3 | import org.accen.dmzj.core.task.GeneralTask; 4 | import org.accen.dmzj.web.vo.Qmessage; 5 | 6 | /** 7 | * 此类用于处理功能型的消息,例如“新增一条精确匹配” 8 | * @author Accen 9 | * @since 0.1 10 | */ 11 | public interface CmdAdapter { 12 | /** 13 | * 具体操作 14 | * @param qmessage 15 | */ 16 | GeneralTask cmdAdapt(Qmessage qmessage,String selfQnum); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/vo/BilibiliBangumiInfo.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.vo; 2 | 3 | public class BilibiliBangumiInfo { 4 | private long mediaId; 5 | private String name; 6 | public long getMediaId() { 7 | return mediaId; 8 | } 9 | public void setMediaId(long mediaId) { 10 | this.mediaId = mediaId; 11 | } 12 | public String getName() { 13 | return name; 14 | } 15 | public void setName(String name) { 16 | this.name = name; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/exception/AutowiredParamException.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.exception; 2 | 3 | public class AutowiredParamException extends Exception{ 4 | /** 5 | * 6 | */ 7 | private static final long serialVersionUID = 1L; 8 | public AutowiredParamException() { 9 | 10 | } 11 | public AutowiredParamException(String regularName ,String autowiredParamName) { 12 | super("AutowiredParam配置失败!regularName:%s,paramName:%s".formatted(regularName,autowiredParamName)); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/callbacker/AsyncCallback.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.callbacker; 2 | /** 3 | * 用于处理程序内部的异步通知 4 | * @author Accen 5 | * 6 | */ 7 | public interface AsyncCallback { 8 | /** 9 | * 异步的回调,如果message无法说明,可以使用detail传递,相应地就需要实现了AsyncCallback的类去自己与异步方法沟通(即类型转换) 10 | * @param message 11 | * @param detail 12 | * @param callbackParams 13 | */ 14 | public void callback(String message,Object detail,Object... callbackParams); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/exception/PixivcAuthInitialExcpetion.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.exception; 2 | 3 | public class PixivcAuthInitialExcpetion extends RuntimeException{ 4 | 5 | /** 6 | * 7 | */ 8 | private static final long serialVersionUID = 1698518380689364957L; 9 | public PixivcAuthInitialExcpetion(Throwable e) { 10 | super(e); 11 | } 12 | public PixivcAuthInitialExcpetion(String message,Throwable e) { 13 | super(message, e); 14 | } 15 | public PixivcAuthInitialExcpetion() { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/task/TimerTask.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.task; 2 | 3 | import java.util.Date; 4 | 5 | public class TimerTask { 6 | private Date excuteTime; 7 | private GeneralTask task; 8 | public Date getExcuteTime() { 9 | return excuteTime; 10 | } 11 | public void setExcuteTime(Date excuteTime) { 12 | this.excuteTime = excuteTime; 13 | } 14 | public GeneralTask getTask() { 15 | return task; 16 | } 17 | public void setTask(GeneralTask task) { 18 | this.task = task; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/vo/SteamApp.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.vo; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | @SuppressWarnings("preview") 7 | @JsonIgnoreProperties(ignoreUnknown = true) 8 | public record SteamApp(@JsonProperty("applist")AppList applist) { 9 | public record AppList(@JsonProperty("apps") App[] apps) { 10 | public record App(@JsonProperty("appid")int appid,@JsonProperty("name") String name) {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/vo/SysQnum.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.vo; 2 | /** 3 | * 系统qq 4 | * @author Accen 5 | * 6 | */ 7 | public class SysQnum { 8 | private String qnum; 9 | private String secret; 10 | public String getQnum() { 11 | return qnum; 12 | } 13 | public void setQnum(String qnum) { 14 | this.qnum = qnum; 15 | } 16 | public String getSecret() { 17 | return secret; 18 | } 19 | public void setSecret(String secret) { 20 | this.secret = secret; 21 | } 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/listen/ListenStatus.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.listen; 2 | 3 | import org.accen.dmzj.web.vo.CfgListenStatus; 4 | 5 | /** 6 | * 描述此监听器是属于状态面板的,比如XXX模式 7 | * @author 刘伟 8 | * 9 | */ 10 | public interface ListenStatus { 11 | /** 12 | * 状态名 13 | * @return 14 | */ 15 | String name(); 16 | /** 17 | * status name in english 18 | * @return 19 | */ 20 | String nameEn(); 21 | /** 22 | * 此监听器的编号,与{@link CfgListenStatus}对应 23 | * @return 24 | */ 25 | String code(); 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/PixivcatApiClient.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api; 2 | 3 | import org.springframework.cloud.openfeign.FeignClient; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | 7 | import feign.Response; 8 | 9 | @FeignClient( 10 | name="pixivcat", 11 | url="https://pixiv.cat") 12 | public interface PixivcatApiClient { 13 | 14 | @GetMapping("/{pPath}.jpg") 15 | public Response pixivImage(@PathVariable("pPath")String pPath); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/callbacker/CallbackListener.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.callbacker; 2 | 3 | import org.accen.dmzj.web.vo.Qmessage; 4 | /** 5 | * 回调监听 6 | * @author Accen 7 | * 8 | */ 9 | public interface CallbackListener { 10 | /** 11 | * 监听消息,若返回true,则去掉此监听器实例 12 | * 13 | * @param qmessage 14 | * @return 15 | */ 16 | public boolean listen(Qmessage originQmessage,Qmessage qmessage,String selfQnum);//TODO 虽然可以通过返回bool来选择是否移除,但为了保证稳定,应该给监听器增加一个超时timeout自动移除的机制 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/exception/DataNeverInitedException.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.exception; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | public class DataNeverInitedException extends Exception { 6 | 7 | /** 8 | * 9 | */ 10 | private static final long serialVersionUID = 1L; 11 | public DataNeverInitedException() { 12 | super("Data never be inited!"); 13 | } 14 | public DataNeverInitedException(Object obj,Field field) { 15 | super("Data never be inited! >> "+obj.toString()+" : "+field.getName()); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/listen/ListenAdpter.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.listen; 2 | 3 | import java.util.List; 4 | 5 | import org.accen.dmzj.core.task.GeneralTask; 6 | import org.accen.dmzj.web.vo.Qmessage; 7 | 8 | /** 9 | * 监听适配器,会匹配所有的消息,满足一定的条件后触发特定的功能 10 | * @author Accen 11 | * @since 0.1 12 | */ 13 | public interface ListenAdpter { 14 | /** 15 | * 监听,若触发某事件则可能产生多个任务 16 | * @param qmessage 17 | * @param selfQnum 18 | * @return 19 | */ 20 | List listen(Qmessage qmessage,String selfQnum); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/exception/CmdRegisterDuplicateException.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.exception; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | public class CmdRegisterDuplicateException extends Exception{ 6 | 7 | /** 8 | * 9 | */ 10 | private static final long serialVersionUID = 2340303086887140181L; 11 | public CmdRegisterDuplicateException(String cmdName,Class sourceClass,Method sourceMethod) { 12 | super("Cmd register duplicate 错误:%s,位置:%s#%s".formatted(cmdName,sourceClass.getName(),sourceMethod.getName())); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/steam/SteamStoreApiClient.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.steam; 2 | 3 | import org.springframework.cloud.openfeign.FeignClient; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | 7 | @FeignClient(name="steam-store",url="https://store.steampowered.com") 8 | public interface SteamStoreApiClient { 9 | /** 10 | * 获取 11 | * @param appid 12 | * @return 13 | */ 14 | @GetMapping("/app/{appid}") 15 | public String app(@PathVariable("appid")int appid); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/util/RandomMeta.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.util; 2 | 3 | /** 4 | * 用于辅助随机抽取 5 | */ 6 | public class RandomMeta{ 7 | private T obj;//单个抽取对象 8 | private int weight ;//权值, 9 | public T getObj() { 10 | return obj; 11 | } 12 | public void setObj(T obj) { 13 | this.obj = obj; 14 | } 15 | public int getWeight() { 16 | return weight; 17 | } 18 | public void setWeight(int weight) { 19 | this.weight = weight; 20 | } 21 | public RandomMeta(T obj, int weight) { 22 | super(); 23 | this.obj = obj; 24 | this.weight = weight; 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/autoconfigure/ContextPostProcessor.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.autoconfigure; 2 | 3 | import org.accen.dmzj.core.AccenbotContext; 4 | import org.accen.dmzj.core.meta.PostType; 5 | 6 | /** 7 | * 监听accenbotcontext的注册和注销 8 | * @author Accen 9 | * since 2.2 10 | */ 11 | public interface ContextPostProcessor { 12 | /** 13 | * 注册完一个context后收到此通知 14 | * @param postType 15 | * @param context 16 | */ 17 | default public void afterRegisterContext(PostType postType,AccenbotContext context) {} 18 | //TODO 注销 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/annotation/AutowiredParam.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 用于默认匹配Qmessage进行注入 11 | * @author Accen 12 | * 13 | */ 14 | @Target(ElementType.PARAMETER) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Documented 17 | public @interface AutowiredParam { 18 | String value() default ""; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/meta/NoticeType.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.meta; 2 | 3 | public enum NoticeType { 4 | _ALL, 5 | /** 6 | * 群文件上传 7 | */ 8 | GROUP_UPLOAD, 9 | /** 10 | * 群管理变动 11 | */ 12 | GROUP_ADMIN, 13 | /** 14 | * 群成员减少 15 | */ 16 | GROUP_DECREASE, 17 | /** 18 | * 群成员增加 19 | */ 20 | GROUP_INCREASE, 21 | /** 22 | * 群禁言 23 | */ 24 | GROUP_BAN, 25 | /** 26 | * 好友添加 27 | */ 28 | FRIEND_ADD, 29 | /** 30 | * 群消息撤回 31 | */ 32 | GROUP_RECALL, 33 | /** 34 | * 好友消息撤回 35 | */ 36 | FRIEND_RECALL, 37 | /** 38 | * 戳一戳 39 | */ 40 | NOTIFY 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/HitokotoApiClient.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api; 2 | 3 | import java.util.Map; 4 | 5 | import org.springframework.cloud.openfeign.FeignClient; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | 8 | /** 9 | * @see 一言开发者中心 10 | * @author Accen 11 | * 12 | */ 13 | @FeignClient( 14 | name="hitokoto-v1", 15 | url="https://v1.hitokoto.cn") 16 | public interface HitokotoApiClient { 17 | @GetMapping("/?c=a&c=b&c=c&encode=json&charset=utf-8") 18 | Map hitokoto(); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/autoconfigure/EventPostProcessor.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.autoconfigure; 2 | 3 | import java.util.Map; 4 | 5 | import org.accen.dmzj.core.AccenbotContext; 6 | /** 7 | * AccenbotContex的事件处理器前后预置,{@link AccenbotContext#accept(Map)} 8 | * @author Accen 9 | * @since 2.2 10 | */ 11 | public interface EventPostProcessor { 12 | default public void beforeEventPost(Map event) {}; 13 | default public void afterEventPostSuccess(Map event,AccenbotContext context) {}; 14 | default public void afterEventPostFaild(Map event) {}; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/feign/auth/AuthFeignRequestInterceptor.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.feign.auth; 2 | 3 | import feign.RequestInterceptor; 4 | import feign.RequestTemplate; 5 | /** 6 | * 用于认证的拦截器 7 | * @author Accen 8 | * 9 | */ 10 | public abstract class AuthFeignRequestInterceptor implements RequestInterceptor { 11 | /** 12 | * 通过实现此方法,为request添加认证所需 13 | * @param template 14 | */ 15 | abstract protected void resolveRequestTemplate(RequestTemplate template); 16 | @Override 17 | public void apply(RequestTemplate template) { 18 | resolveRequestTemplate(template); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/ModeCmd.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | /** 7 | * 模式切换型的功能 8 | * @author Accen 9 | * 10 | */ 11 | public abstract class ModeCmd { 12 | private Set allowGroup = new HashSet(4); 13 | public void addGroup(String groupId) { 14 | allowGroup.add(groupId); 15 | } 16 | public void removeGroup(String groupId) { 17 | allowGroup.remove(groupId); 18 | } 19 | public abstract boolean modeOpen(String groupId); 20 | protected boolean hasGroup(String groupId) { 21 | return allowGroup.contains(groupId); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/bilibili/LiveBilibiliApiClient.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.bilibili; 2 | 3 | import java.util.Map; 4 | 5 | import org.springframework.cloud.openfeign.FeignClient; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RequestParam; 8 | 9 | @FeignClient(name="bilibili-live", 10 | url="https://api.live.bilibili.com") 11 | public interface LiveBilibiliApiClient { 12 | /** 13 | * 获取直播间相关信息 14 | * @param roomId 15 | * @return 16 | */ 17 | @GetMapping("/xlive/web-room/v1/index/getInfoByRoom") 18 | public Map infoByRoom(@RequestParam("room_id")String roomId); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/feign/auth/AbstractHeaderAuthCounterFeignRequestInterceptor.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.feign.auth; 2 | 3 | import feign.RequestTemplate; 4 | /** 5 | * 6 | * @author Accen 7 | * 8 | */ 9 | public abstract class AbstractHeaderAuthCounterFeignRequestInterceptor 10 | extends HeaderAuthFeignRequestInterceptor 11 | implements FirstTimeCallCase{ 12 | private volatile int callCount = 0; 13 | @Override 14 | public void resolveRequestTemplate(RequestTemplate template) { 15 | if(callCount == 0) { 16 | firstTimeDo(); 17 | } 18 | super.resolveRequestTemplate(template); 19 | callCount++; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/YoudaoApiClient.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api; 2 | 3 | import org.accen.dmzj.core.api.vo.YoudaoTranslateResult; 4 | import org.springframework.cloud.openfeign.FeignClient; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestParam; 7 | 8 | @FeignClient( 9 | name="youdao-fanyi", 10 | url="http://fanyi.youdao.com") 11 | public interface YoudaoApiClient { 12 | 13 | /** 14 | * 翻译api 15 | * @param src 16 | * @param lang 17 | * @return 18 | */ 19 | @GetMapping("/translate?doctype=json") 20 | public YoudaoTranslateResult translate(@RequestParam("i") String src,@RequestParam("type") String lang); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/KaassApiClient.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api; 2 | 3 | import java.util.Map; 4 | 5 | import org.springframework.cloud.openfeign.FeignClient; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RequestParam; 8 | 9 | @FeignClient( 10 | name="kaass", 11 | url="https://api.kaaass.net") 12 | public interface KaassApiClient { 13 | @GetMapping("/biliapi/user/space") 14 | public Map space(@RequestParam("id")long id); 15 | 16 | @GetMapping("/biliapi/user/contribute") 17 | public Map contribute(@RequestParam("id")long id,@RequestParam("page") int page,@RequestParam("pageCount") int pageCount); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/annotation/AutowiredRegular.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 用于匹配Cmd Regular中expression的group位置 11 | * @author Accen 12 | * @since 2.1 13 | */ 14 | @Target(ElementType.PARAMETER) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Documented 17 | public @interface AutowiredRegular { 18 | /** 19 | * group值(应该配置为自然数),若为0,则使用默认值即顺序匹配,其数值若大于expression group的总数则执行错误 20 | * @return 21 | */ 22 | int value() default 0; 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/meta/NoticeSubType.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.meta; 2 | 3 | public enum NoticeSubType { 4 | _ALL, 5 | /** 6 | * 设置管理员 7 | */ 8 | SET, 9 | /** 10 | * 取消管理员 11 | */ 12 | UNSET, 13 | /** 14 | * 群成员减少-主动退群 15 | */ 16 | LEAVE, 17 | /** 18 | * 群成员减少-成员被踢 19 | */ 20 | KICK, 21 | /** 22 | * 群成员减少-登录号被踢 23 | */ 24 | KICK_ME, 25 | /** 26 | * 群成员增加-管理员已同意入群 27 | */ 28 | APPROVE, 29 | /** 30 | * 群成员增加-管理员邀请入群 31 | */ 32 | INVITE, 33 | /** 34 | * 群禁言-禁言 35 | */ 36 | BAN, 37 | /** 38 | * 群禁言-结除禁言 39 | */ 40 | LIFT_BAN, 41 | /** 42 | * 戳一戳 43 | */ 44 | POKE, 45 | /** 46 | * 群红包运气王 47 | */ 48 | LUCKY_KING, 49 | /** 50 | * 群成员荣誉变更 51 | */ 52 | HONOR 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/util/SystemUtil.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.util; 2 | 3 | import java.util.Properties; 4 | 5 | public class SystemUtil { 6 | /** 7 | * 获取当前系统的文件夹符 8 | * @return 9 | */ 10 | public static String getFileSeperate() { 11 | String osName = getSystemProperty("os.name"); 12 | if(osName.matches("Windows.*")) { 13 | return "\\"; 14 | }else { 15 | return "/"; 16 | } 17 | } 18 | public static String getOs() { 19 | return getSystemProperty("os.name").toUpperCase(); 20 | } 21 | /** 22 | * 获取系统变量 23 | * @param var 24 | * @return 25 | */ 26 | private static String getSystemProperty(String var) { 27 | Properties props = System.getProperties(); 28 | return props.getProperty(var); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/JiRenGuApiClient.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api; 2 | /** 3 | * 饥人谷个人开放的api 4 | * @author Accen 5 | * 6 | */ 7 | 8 | import java.util.Map; 9 | 10 | import org.springframework.cloud.openfeign.FeignClient; 11 | import org.springframework.web.bind.annotation.GetMapping; 12 | import org.springframework.web.bind.annotation.RequestParam; 13 | 14 | @FeignClient( 15 | name="jirengu", 16 | url="http://api.jirengu.com") 17 | public interface JiRenGuApiClient { 18 | /** 19 | * 天气api 20 | * @param city 21 | * @return 22 | */ 23 | @GetMapping("/getWeather.php") 24 | public Map weather(@RequestParam("city")String city); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/GoogleTranslateApiClient.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api; 2 | 3 | import java.util.Map; 4 | 5 | import org.springframework.cloud.openfeign.FeignClient; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RequestParam; 8 | 9 | @FeignClient( 10 | name="google-translate", 11 | url="http://translate.google.cn") 12 | public interface GoogleTranslateApiClient { 13 | /** 14 | * google翻译api 15 | * @param lang 16 | * @param word 17 | * @return 18 | */ 19 | @GetMapping("/translate_a/single?client=gtx&dt=t&dj=1&ie=UTF-8") 20 | public Map translate(@RequestParam("tl")String lang,@RequestParam("q")String word,@RequestParam("sl")String sl); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/annotation/Dependency.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 标识一个Cmd是否依赖另一个/多个cmd,需配合order 11 | * @author Accen 12 | * @since 2.2 13 | */ 14 | @Target({ElementType.METHOD,ElementType.TYPE}) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Documented 17 | public @interface Dependency { 18 | String[] value() default {}; 19 | /** 20 | * 依赖模式,默认为all,即依赖value中全部。可改为ANY,即依赖一个即可 21 | * @return 22 | */ 23 | DependMode dependMode() default DependMode.ALL; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/annotation/Rejection.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 标识一个Cmd是否排斥另一个/多个cmd,需配合order 11 | * @author Accen 12 | * @since 2.2 13 | */ 14 | @Target({ElementType.METHOD,ElementType.TYPE}) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Documented 17 | public @interface Rejection { 18 | String[] value() default {}; 19 | /** 20 | * 依赖模式,默认为any,即排斥value中的一个即可。可改为ALL,即需要排斥全部 21 | * @return 22 | */ 23 | DependMode rejectMode() default DependMode.ANY; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/vo/BilibiliUserInfo.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.vo; 2 | 3 | public class BilibiliUserInfo { 4 | private long mid; 5 | private String name; 6 | private long roomId; 7 | private String usign; 8 | public long getMid() { 9 | return mid; 10 | } 11 | public void setMid(long mid) { 12 | this.mid = mid; 13 | } 14 | public String getName() { 15 | return name; 16 | } 17 | public void setName(String name) { 18 | this.name = name; 19 | } 20 | public long getRoomId() { 21 | return roomId; 22 | } 23 | public void setRoomId(long roomId) { 24 | this.roomId = roomId; 25 | } 26 | public String getUsign() { 27 | return usign; 28 | } 29 | public void setUsign(String usign) { 30 | this.usign = usign; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/annotation/MessageRegular.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 在CmdMessage的基础上实现CmdRegular的功能,同时废弃不受AccenbotContex管辖的CmdRegular 11 | *
标注在被CmdMessage注解的Method上,以对message的内容进行匹配并注入到方法中 12 | * @see AutowiredRegular 13 | * @author Accen 14 | * @since 2.2 15 | */ 16 | @Target(ElementType.METHOD) 17 | @Retention(RetentionPolicy.RUNTIME) 18 | @Documented 19 | public @interface MessageRegular { 20 | /** 21 | * 匹配的正则式 22 | * @return 23 | */ 24 | String expression(); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/vo/CmdNodeRelation.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.vo; 2 | 3 | public class CmdNodeRelation { 4 | private long id; 5 | private long pNodeId; 6 | private long cNodeId; 7 | private String checkNo; 8 | public long getId() { 9 | return id; 10 | } 11 | public void setId(long id) { 12 | this.id = id; 13 | } 14 | public long getpNodeId() { 15 | return pNodeId; 16 | } 17 | public void setpNodeId(long pNodeId) { 18 | this.pNodeId = pNodeId; 19 | } 20 | public long getcNodeId() { 21 | return cNodeId; 22 | } 23 | public void setcNodeId(long cNodeId) { 24 | this.cNodeId = cNodeId; 25 | } 26 | public String getCheckNo() { 27 | return checkNo; 28 | } 29 | public void setCheckNo(String checkNo) { 30 | this.checkNo = checkNo; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/Wiki33mApiClient.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api; 2 | 3 | import org.springframework.cloud.openfeign.FeignClient; 4 | 5 | import feign.Param; 6 | import feign.RequestLine; 7 | import feign.Response; 8 | import feign.codec.Decoder; 9 | 10 | /** 11 | * 由孤狼Wiki-QQ提供的获取qq用户头像的api 12 | * @author Accen 13 | * 14 | */ 15 | @FeignClient( 16 | name="qq-33m", 17 | url="https://api.33m.me") 18 | public interface Wiki33mApiClient { 19 | /** 20 | * 获取群或用户的头像 21 | * @param type qtx-群头像 tx2-用户头像 22 | * @param num 23 | * @return 24 | */ 25 | @RequestLine("GET /qq?lx={type}&qq={num}") 26 | public Response qqImage(@Param("type")String type,@Param("num")String num); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/annotation/CmdMessage.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | import org.accen.dmzj.core.meta.MessageSubType; 10 | import org.accen.dmzj.core.meta.MessageType; 11 | 12 | @Target({ElementType.METHOD,ElementType.TYPE}) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Documented 15 | public @interface CmdMessage { 16 | String value() default ""; 17 | String[] executeMethod() default {"execute"}; 18 | int order() default 999; 19 | MessageType[] messageType() default MessageType._ALL; 20 | MessageSubType[] subType() default MessageSubType._ALL; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/vo/BaikeResult.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.vo; 2 | 3 | public class BaikeResult { 4 | private String summary; 5 | private String url; 6 | private String title; 7 | private String imageUrl; 8 | public String getSummary() { 9 | return summary; 10 | } 11 | public void setSummary(String summary) { 12 | this.summary = summary; 13 | } 14 | public String getUrl() { 15 | return url; 16 | } 17 | public void setUrl(String url) { 18 | this.url = url; 19 | } 20 | public String getTitle() { 21 | return title; 22 | } 23 | public void setTitle(String title) { 24 | this.title = title; 25 | } 26 | public String getImageUrl() { 27 | return imageUrl; 28 | } 29 | public void setImageUrl(String imageUrl) { 30 | this.imageUrl = imageUrl; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/vo/CmdGameNode.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.vo; 2 | 3 | public class CmdGameNode { 4 | private long id; 5 | private long gameId; 6 | private String nodeDesc; 7 | private String nodeType;//First,Flow,Last,Result 8 | public long getId() { 9 | return id; 10 | } 11 | public void setId(long id) { 12 | this.id = id; 13 | } 14 | public String getNodeDesc() { 15 | return nodeDesc; 16 | } 17 | public void setNodeDesc(String nodeDesc) { 18 | this.nodeDesc = nodeDesc; 19 | } 20 | public String getNodeType() { 21 | return nodeType; 22 | } 23 | public void setNodeType(String nodeType) { 24 | this.nodeType = nodeType; 25 | } 26 | public long getGameId() { 27 | return gameId; 28 | } 29 | public void setGameId(long gameId) { 30 | this.gameId = gameId; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: datasource: url: jdbc:mysql://localhost:3306/dmzjbot?characterEncoding=UTF-8&serverTimezone=UTC username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver ffmpeg: bin: /usr/local/ffmpeg/bin/ silkv3: bin: /usr/local/ffmpeg/bin/ sys: static: html: music: /usr/local/nginx/html/music/ mime: /usr/local/nginx/html/mime/ upload: /home/user/coolq/upload/ url: music: http://129.204.0.108/music/ upload: http://129.204.0.108/upload/ 2 | coolq: 3 | base: 4 | home: /home/usr/coolq manager: 1339633536 bot: 1023915086 mem: iniCoin: 20 coinIncr: -16 iniFavorability: 0 favorabilityIncr: 1 fuzzymsg: fav: lowerlimit: 9999 coin: decrease: 5 music: list: pageSize: 10 5 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/steam/SteamNewsFormatter.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.steam; 2 | 3 | public class SteamNewsFormatter { 4 | private SteamVariableConfiguration prop; 5 | public SteamNewsFormatter(SteamVariableConfiguration prop) { 6 | this.prop = prop; 7 | } 8 | private final String imgPattern1 = "\\[img\\]\\{STEAM_CLAN_IMAGE\\}"; 9 | private final String imgPattern2 = "\\[/img\\]"; 10 | private final String hPattern1 = "\\[h\\d\\]"; 11 | private final String hPattern2 = "\\[/h\\d\\]"; 12 | public String formatContents(String content) { 13 | //图片转cq格式 14 | String result = content.replaceAll(imgPattern1, "[CQ:image,file=".concat(prop.STEAM_CLAN_IMAGE())) 15 | .replaceAll(imgPattern2, "]"); 16 | //header清除 17 | return result.replaceAll(hPattern1, "").replaceAll(hPattern2, ""); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/autoconfigure/ProxyPostProcessor.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.autoconfigure; 2 | 3 | import org.accen.dmzj.core.AccenbotContext; 4 | import org.accen.dmzj.core.AccenbotContext.AccenbotCmdProxy; 5 | 6 | /** 7 | * 针对proxy生命周期的post processor 8 | * @author Accen 9 | * @since 2.2 10 | */ 11 | public interface ProxyPostProcessor { 12 | /** 13 | * 在Context注册proxy前自行 14 | * @param context 15 | * @param proxy 16 | * @return 17 | */ 18 | //TODO order 19 | default public AccenbotCmdProxy beforeRegisterProxy(AccenbotContext context,AccenbotCmdProxy proxy) {return proxy;} 20 | /** 21 | * 在context注册完proxy后执行 22 | * @param contex 23 | * @param proxy 24 | */ 25 | default public void afterRegisterProxy(AccenbotContext context,AccenbotCmdProxy proxy) {} 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/annotation/CmdRequest.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | import org.accen.dmzj.core.meta.RequestSubType; 10 | import org.accen.dmzj.core.meta.RequestType; 11 | @Target({ElementType.METHOD,ElementType.TYPE}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Documented 14 | public @interface CmdRequest { 15 | String value() default ""; 16 | RequestType[] requestType() default RequestType._ALL; 17 | RequestSubType[] subType() default RequestSubType._ALL; 18 | String[] executeMethod() default {"execute"}; 19 | boolean enableAutowiredParam() default true; 20 | int order() default 999; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/vo/BilibliVideoInfo.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.vo; 2 | 3 | public class BilibliVideoInfo { 4 | private long aId; 5 | private String title; 6 | private long postTime; 7 | public long getaId() { 8 | return aId; 9 | } 10 | public void setaId(long aId) { 11 | this.aId = aId; 12 | } 13 | public String getTitle() { 14 | return title; 15 | } 16 | public void setTitle(String title) { 17 | this.title = title; 18 | } 19 | public long getPostTime() { 20 | return postTime; 21 | } 22 | public void setPostTime(long postTime) { 23 | this.postTime = postTime; 24 | } 25 | public BilibliVideoInfo(long aId, String title, long postTime) { 26 | super(); 27 | this.aId = aId; 28 | this.title = title; 29 | this.postTime = postTime; 30 | } 31 | public BilibliVideoInfo() { 32 | super(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/exception/BiliBiliCookieExpired.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.exception; 2 | 3 | public class BiliBiliCookieExpired extends Exception { 4 | 5 | /** 6 | * 7 | */ 8 | private static final long serialVersionUID = 7187904038556163627L; 9 | 10 | public BiliBiliCookieExpired() { 11 | super(); 12 | } 13 | 14 | public BiliBiliCookieExpired(String message, Throwable cause, boolean enableSuppression, 15 | boolean writableStackTrace) { 16 | super(message, cause, enableSuppression, writableStackTrace); 17 | } 18 | 19 | public BiliBiliCookieExpired(String message, Throwable cause) { 20 | super(message, cause); 21 | } 22 | 23 | public BiliBiliCookieExpired(String message) { 24 | super(message); 25 | } 26 | 27 | public BiliBiliCookieExpired(Throwable cause) { 28 | super(cause); 29 | } 30 | 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/exception/BiliBiliCookieNeverInit.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.exception; 2 | 3 | public class BiliBiliCookieNeverInit extends Exception { 4 | 5 | /** 6 | * 7 | */ 8 | private static final long serialVersionUID = -7318692540075052977L; 9 | 10 | public BiliBiliCookieNeverInit() { 11 | super(); 12 | } 13 | 14 | public BiliBiliCookieNeverInit(String message, Throwable cause, boolean enableSuppression, 15 | boolean writableStackTrace) { 16 | super(message, cause, enableSuppression, writableStackTrace); 17 | } 18 | 19 | public BiliBiliCookieNeverInit(String message, Throwable cause) { 20 | super(message, cause); 21 | } 22 | 23 | public BiliBiliCookieNeverInit(String message) { 24 | super(message); 25 | } 26 | 27 | public BiliBiliCookieNeverInit(Throwable cause) { 28 | super(cause); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/feign/auth/HeaderAuthFeignRequestInterceptor.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.feign.auth; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import feign.RequestTemplate; 7 | /** 8 | * 一个简单的实现,使用Header来做登录验证的拦截器 9 | * @author Accen 10 | * 11 | */ 12 | public class HeaderAuthFeignRequestInterceptor extends AuthFeignRequestInterceptor{ 13 | private Map authHeaders =new HashMap<>(2); 14 | @Override 15 | public void resolveRequestTemplate(RequestTemplate template) { 16 | authHeaders.keySet().forEach(key->{ 17 | if(!template.headers().containsKey(key)) { 18 | template.header(key, authHeaders.get(key)); 19 | } 20 | }); 21 | } 22 | protected void addHeader(String headerKey,String headerValue) { 23 | authHeaders.put(headerKey, headerValue); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/MusicApiClient.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api; 2 | 3 | import org.accen.dmzj.core.api.vo.Music163Result; 4 | import org.springframework.cloud.openfeign.FeignClient; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestParam; 7 | 8 | import feign.Param; 9 | @FeignClient( 10 | name="music163", 11 | url="http://music.163.com") 12 | public interface MusicApiClient { 13 | /** 14 | * 网易云音乐搜索api 15 | * @param s 搜索的内容 16 | * @param offset 偏移(分页) 17 | * @param limit 数量 18 | * @param type 1-歌曲,10-专辑,100-歌手,1000-歌单,1002-歌手,1004-mv,1006-歌词,1009电台 19 | * @return 20 | */ 21 | @GetMapping("/api/search/get/?type=1") 22 | public Music163Result music163Search(@RequestParam("s")String s,@RequestParam("offset")int offset,@RequestParam("limit")int limit,@Param("type")int type); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/annotation/Order.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 定义ContextPostProcessor、EventPostProcessor、EventCmdPostProcessor、ProxyPostProcessor等钩子的执行顺序 11 | * @author Accen 12 | * @since 2.3 13 | */ 14 | @Target(ElementType.METHOD) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Documented 17 | public @interface Order { 18 | public static final int LOWEST_ORDER = Integer.MAX_VALUE; 19 | /** 20 | * 定义顺序 21 | * @return 22 | */ 23 | int value() default LOWEST_ORDER; 24 | /** 25 | * value相等时,使用这个确定,但是一般的类请不要使用这个 26 | * @return 27 | */ 28 | int xvalue() default LOWEST_ORDER; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/util/render/LocalFileRenderImage.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.util.render; 2 | 3 | import java.awt.image.BufferedImage; 4 | import java.io.File; 5 | import java.io.IOException; 6 | 7 | import javax.imageio.ImageIO; 8 | 9 | import render.RenderImage; 10 | 11 | public class LocalFileRenderImage extends RenderImage{ 12 | private File localFile ; 13 | private BufferedImage buff; 14 | public LocalFileRenderImage(File file) throws IOException { 15 | super(); 16 | this.localFile = file; 17 | this.buff = ImageIO.read(localFile); 18 | } 19 | @Override 20 | public BufferedImage getBufferedImage() { 21 | return buff; 22 | } 23 | 24 | @Override 25 | public int getWidth() { 26 | return buff.getWidth(); 27 | } 28 | 29 | @Override 30 | public int getHeight() { 31 | return buff.getHeight(); 32 | } 33 | @Override 34 | public void afterSetStandardWidth(int width) {}; 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/dao/SysQnumMapper.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.dao; 2 | 3 | import java.util.List; 4 | 5 | import org.accen.dmzj.web.vo.SysQnum; 6 | import org.apache.ibatis.annotations.Mapper; 7 | import org.apache.ibatis.annotations.Param; 8 | import org.apache.ibatis.annotations.Result; 9 | import org.apache.ibatis.annotations.ResultMap; 10 | import org.apache.ibatis.annotations.Results; 11 | import org.apache.ibatis.annotations.Select; 12 | 13 | @Mapper 14 | public interface SysQnumMapper { 15 | @Results(id="qnumResultMap",value= { 16 | @Result(property = "qnum",column = "qnum"), 17 | @Result(property = "secret",column = "secret") 18 | }) 19 | @Select("select * from sys_qnum where qnum = #{qnum}") 20 | public SysQnum getByQnum(@Param("qnum") String qnum); 21 | 22 | @ResultMap("qnumResultMap") 23 | @Select("select * from sys_qnum ") 24 | public List getAllQnum(); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/annotation/FuncSwitchGroup.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 功能组 11 | * @author Accen 12 | * 13 | */ 14 | @Target({ElementType.TYPE}) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Documented 17 | public @interface FuncSwitchGroup { 18 | /** 19 | * 分组Key,默认为grp_类名 20 | * @return 21 | */ 22 | String name() default ""; 23 | /** 24 | * 是否要在菜单中展示 25 | * @return 26 | */ 27 | boolean showMenu() default false; 28 | /** 29 | * 分组名 30 | * @return 31 | */ 32 | String title(); 33 | /** 34 | * 排序 35 | * @return 36 | */ 37 | int order() default 99; 38 | String[] matchSigns() default {}; 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/annotation/HandlerChain.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | import org.springframework.core.annotation.AliasFor; 10 | import org.springframework.stereotype.Component; 11 | 12 | @Target({ElementType.TYPE}) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Documented 15 | @Component 16 | public @interface HandlerChain { 17 | @AliasFor(annotation = Component.class) 18 | String value() default ""; 19 | /** 20 | * 处理器的优先级,越大优先级越高越先处理 21 | */ 22 | int order() default 0; 23 | /** 24 | * 处理的事件类型,例如message,notice 25 | * @return 26 | */ 27 | String postType(); 28 | /** 29 | * 是否阻断后续的处理器执行 30 | * @return 31 | */ 32 | boolean isBlock() default false; 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/util/ApplicationContextUtil.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.util; 2 | 3 | import java.util.Map; 4 | 5 | import org.springframework.context.ApplicationContext; 6 | import org.springframework.core.io.Resource; 7 | 8 | public class ApplicationContextUtil { 9 | private static ApplicationContext context; 10 | public static void setContext(ApplicationContext context) { 11 | ApplicationContextUtil.context = context; 12 | } 13 | public static Object getBean(String beanName) { 14 | return context.getBean(beanName); 15 | } 16 | public static T getBean(Class clazz) { 17 | return context.getBean(clazz); 18 | } 19 | public static T getBean(String beanName,Class clazz) { 20 | return context.getBean(clazz); 21 | } 22 | public static Map getBeans(Class clazz){ 23 | return context.getBeansOfType(clazz); 24 | } 25 | public static Resource getResource(String location) { 26 | return context.getResource(location); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/DmzjSpringBootApplication.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj; 2 | 3 | import org.accen.dmzj.util.ApplicationContextUtil; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.context.properties.ConfigurationPropertiesScan; 7 | import org.springframework.cloud.openfeign.EnableFeignClients; 8 | import org.springframework.context.ApplicationContext; 9 | import org.springframework.scheduling.annotation.EnableScheduling; 10 | @SpringBootApplication 11 | @EnableScheduling 12 | @EnableFeignClients 13 | @ConfigurationPropertiesScan 14 | public class DmzjSpringBootApplication { 15 | 16 | public static void main(String[] args) { 17 | System.setProperty("user.timezone","GMT +08"); 18 | ApplicationContext applicationContext = SpringApplication.run(DmzjSpringBootApplication.class, args); 19 | ApplicationContextUtil.setContext(applicationContext); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/vo/CmdGame.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.vo; 2 | 3 | public class CmdGame { 4 | private long id; 5 | private String gameName; 6 | private int coinConsum; 7 | private int favLimit; 8 | private int status;//0-无效 1-启用 2-关闭 9 | public long getId() { 10 | return id; 11 | } 12 | public void setId(long id) { 13 | this.id = id; 14 | } 15 | public String getGameName() { 16 | return gameName; 17 | } 18 | public void setGameName(String gameName) { 19 | this.gameName = gameName; 20 | } 21 | public int getCoinConsum() { 22 | return coinConsum; 23 | } 24 | public void setCoinConsum(int coinConsum) { 25 | this.coinConsum = coinConsum; 26 | } 27 | public int getFavLimit() { 28 | return favLimit; 29 | } 30 | public void setFavLimit(int favLimit) { 31 | this.favLimit = favLimit; 32 | } 33 | public int getStatus() { 34 | return status; 35 | } 36 | public void setStatus(int status) { 37 | this.status = status; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/QqNickApiClient.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api; 2 | 3 | import java.util.Map; 4 | 5 | import org.springframework.cloud.openfeign.FeignClient; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RequestParam; 8 | 9 | /** 10 | * 获取qq昵称的api,返回值如{ 11 | "ret": 0, 12 | "nick": "%E3%82%AF%E3%83%AD%E3%83%8E%E3%82%B9", 13 | "provide_uin": "1339633536" 14 | },注意nick为urlencode后的值 15 | * @author Accen 16 | * 17 | */ 18 | @FeignClient( 19 | name="qq-api", 20 | url="https://api.unipay.qq.com") 21 | public interface QqNickApiClient { 22 | @GetMapping("/v1/r/1450000186/wechat_query?cmd=1&pf=mds_storeopen_qb-__mds_qqclub_tab_-html5&pfkey=pfkey&from_h5=1&from_https=1&openid=openid&openkey=openkey&session_id=hy_gameid&session_type=st_dummy&qq_appid=&offerId=1450000186&sandbox=") 23 | public Map qqNick(@RequestParam("provide_uin")String qq); 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/dmzjbot/Demo.java: -------------------------------------------------------------------------------- 1 | package dmzjbot; 2 | 3 | import java.sql.Date; 4 | 5 | import org.accen.dmzj.core.annotation.AutowiredParam; 6 | import org.accen.dmzj.core.annotation.AutowiredRegular; 7 | import org.accen.dmzj.core.annotation.CmdRegular; 8 | import org.accen.dmzj.core.annotation.GeneralMessage; 9 | import org.accen.dmzj.web.vo.Qmessage; 10 | import org.springframework.stereotype.Component; 11 | 12 | @Component 13 | public class Demo { 14 | @CmdRegular(expression = "^检索(.+)$",enableAutowiredParam = false) 15 | @GeneralMessage 16 | public String search(String key) { 17 | //TODO your code 18 | return "检索结果..."; 19 | } 20 | 21 | @CmdRegular(expression = "^用(.+)引擎检索(\\d+)$") 22 | @GeneralMessage(targetId = "123456") 23 | public String search(Qmessage qmassage 24 | ,@AutowiredParam("message") String msg 25 | ,@AutowiredParam Date sendTime 26 | ,int pid 27 | ,@AutowiredRegular(1) String engine) { 28 | //TODO your code 29 | return "检索结果..."; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/annotation/CmdMeta.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | import org.accen.dmzj.core.meta.MetaEventType; 10 | import org.accen.dmzj.core.meta.MetaSubType; 11 | 12 | /** 13 | * 标识一个meta类型的event处理器 14 | * @author Accen 15 | * 16 | */ 17 | @Target({ElementType.METHOD,ElementType.TYPE}) 18 | @Retention(RetentionPolicy.RUNTIME) 19 | @Documented 20 | public @interface CmdMeta { 21 | String value() default ""; 22 | /** 23 | * 匹配的MetaEventType 24 | * @return 25 | */ 26 | MetaEventType[] metaEventType() default MetaEventType._ALL; 27 | MetaSubType[] subType() default MetaSubType._ALL; 28 | String[] executeMethod() default {"execute"}; 29 | boolean enableAutowiredParam() default true; 30 | int order() default 999; 31 | } -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/task/TaskProcessor.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.task; 2 | 3 | import java.util.concurrent.BlockingQueue; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | public class TaskProcessor implements Runnable{ 9 | /**待处理的任务,由{@link TaskManager}管理*/ 10 | private final BlockingQueue generalTaskQueue; 11 | 12 | private final static Logger logger = LoggerFactory.getLogger(TaskProcessor.class); 13 | 14 | public TaskProcessor(BlockingQueue generalTaskQueue) { 15 | super(); 16 | this.generalTaskQueue = generalTaskQueue; 17 | } 18 | 19 | 20 | @Override 21 | public void run() { 22 | try { 23 | while(true) { 24 | GeneralTask task = generalTaskQueue.take(); 25 | logger.debug("处理任务:${0}",task); 26 | TaskCoolqProcessor processor = new TaskCoolqProcessor(); 27 | processor.processs(task); 28 | } 29 | 30 | } catch (InterruptedException e) { 31 | e.printStackTrace(); 32 | } 33 | 34 | 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/util/QuickClassParamIndexUtil.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.util; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.Arrays; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | public class QuickClassParamIndexUtil { 9 | /** 10 | * 生成Bean属性索引,暂时只支持一层(即复杂类型不会再递归) 11 | * @param clazz 12 | * @return 13 | */ 14 | public static Map generalQuickClassParamIndex(Class clazz){ 15 | Map index = new HashMap(); 16 | Arrays.stream(clazz.getDeclaredMethods()) 17 | .filter(method->method.getName().length()>3&&method.getName().startsWith("get")&&method.getParameterCount()==0) 18 | .forEach(getter->{ 19 | String name = getter.getName().substring(3); 20 | char[] nameChar = name.toCharArray(); 21 | if(nameChar[0]>='A'&&nameChar[0]<='Z') { 22 | nameChar[0] += 32; 23 | name = String.valueOf(nameChar); 24 | } 25 | index.put(name, getter); 26 | }); 27 | return index; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/annotation/CmdRegular.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | import org.accen.dmzj.core.handler.CmdManager; 10 | import org.accen.dmzj.web.vo.Qmessage; 11 | 12 | /** 13 | * 使用正则式进行匹配的cmd,简要化,确保该方法是public修饰的
14 | * 其方法参数暂时只允许简单参数类型和String
15 | * @see CmdManager.CmdRegularManager 16 | * @author Accen 17 | * @since 2.1 18 | * @since 2.2 deprecated 19 | */ 20 | @Target(ElementType.METHOD) 21 | @Retention(RetentionPolicy.RUNTIME) 22 | @Documented 23 | @Deprecated 24 | public @interface CmdRegular { 25 | String name() default ""; 26 | /** 27 | * 待匹配的正则式 28 | * @return 29 | */ 30 | String expression(); 31 | /** 32 | * 是否允许注入{@link Qmessage}参数,默认true 33 | * @return 34 | */ 35 | boolean enableAutowiredParam() default true; 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/vo/Music163Result.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.vo; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | @SuppressWarnings("preview") 7 | @JsonIgnoreProperties(ignoreUnknown = true) 8 | public record Music163Result(@JsonProperty("result") Music163Ctt result,@JsonProperty("code") String code,@JsonProperty("msg") String msg) { 9 | @JsonIgnoreProperties(ignoreUnknown = true) 10 | public record Music163Ctt(@JsonProperty("songs") Music163[] songs,@JsonProperty("songCount") int songCount) {} 11 | @JsonIgnoreProperties(ignoreUnknown = true) 12 | public record Music163(@JsonProperty("id") long id,@JsonProperty("name") String name,@JsonProperty("position") int position 13 | ,@JsonProperty("alias") Object alias,@JsonProperty("status") int status,@JsonProperty("fee") int fee,@JsonProperty("copyrightId") long copyrightId 14 | ,@JsonProperty("disc") String disc,@JsonProperty("no") int no,@JsonProperty("mp3Url") String mp3Url) {} 15 | } -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/vo/SteamNew.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.vo; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | @SuppressWarnings("preview") 7 | @JsonIgnoreProperties(ignoreUnknown = true) 8 | public record SteamNew(@JsonProperty("appnews") AppNew appnews) { 9 | @JsonIgnoreProperties(ignoreUnknown = true) 10 | public record AppNew(@JsonProperty("appid") int appid,@JsonProperty("newsitems") NewsItem[] newsitems,@JsonProperty("count") int count) {} 11 | @JsonIgnoreProperties(ignoreUnknown = true) 12 | public record NewsItem(@JsonProperty("gid") long gid,@JsonProperty("title") String title,@JsonProperty("url") String url,@JsonProperty("is_external_url") boolean is_external_url,@JsonProperty("author") String author,@JsonProperty("contents") String contents,@JsonProperty("feedlabel") String feedlabel,@JsonProperty("date") int date,@JsonProperty("feedname") String feedname,@JsonProperty("feed_type") int feed_type,@JsonProperty("appid") int appid) {} 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/vo/ImageResult.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.vo; 2 | 3 | public class ImageResult { 4 | private String url; 5 | private String similarity;//相似度 6 | private String title; 7 | private String content;//具体来源如Pixiv ID: 76742665及画师 8 | private boolean isSuccess = false;//是否检索成功 9 | 10 | public boolean isSuccess() { 11 | return isSuccess; 12 | } 13 | public void setSuccess(boolean isSuccess) { 14 | this.isSuccess = isSuccess; 15 | } 16 | public String getSimilarity() { 17 | return similarity; 18 | } 19 | public void setSimilarity(String similarity) { 20 | this.similarity = similarity; 21 | } 22 | public String getTitle() { 23 | return title; 24 | } 25 | public void setTitle(String title) { 26 | this.title = title; 27 | } 28 | public String getContent() { 29 | return content; 30 | } 31 | public void setContent(String content) { 32 | this.content = content; 33 | } 34 | public String getUrl() { 35 | return url; 36 | } 37 | public void setUrl(String url) { 38 | this.url = url; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/steam/SteamVariableConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.steam; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.boot.context.properties.ConstructorBinding; 5 | import org.springframework.boot.context.properties.bind.DefaultValue; 6 | import org.springframework.boot.context.properties.bind.Name; 7 | 8 | @ConfigurationProperties("steam.variable") 9 | @ConstructorBinding 10 | public class SteamVariableConfiguration { 11 | private SteamNewsFormatter newsFormatter; 12 | public SteamNewsFormatter newsFormatter() {return this.newsFormatter;} 13 | 14 | private String STEAM_CLAN_IMAGE; 15 | public String STEAM_CLAN_IMAGE() { 16 | return this.STEAM_CLAN_IMAGE; 17 | } 18 | public SteamVariableConfiguration(@Name("STEAM_CLAN_IMAGE")@DefaultValue("https://cdn.cloudflare.steamstatic.com/steamcommunity/public/images/clans") String STEAM_CLAN_IMAGE) { 19 | this.STEAM_CLAN_IMAGE = STEAM_CLAN_IMAGE; 20 | this.newsFormatter = new SteamNewsFormatter(this); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/annotation/CmdNotice.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.annotation; 2 | /** 3 | * 标识一个类、方法,接受Notice类型的Onebot事件上报 4 | * @author Accen 5 | * 6 | */ 7 | 8 | import java.lang.annotation.Documented; 9 | import java.lang.annotation.ElementType; 10 | import java.lang.annotation.Retention; 11 | import java.lang.annotation.RetentionPolicy; 12 | import java.lang.annotation.Target; 13 | 14 | import org.accen.dmzj.core.meta.NoticeSubType; 15 | import org.accen.dmzj.core.meta.NoticeType; 16 | @Target({ElementType.METHOD,ElementType.TYPE}) 17 | @Retention(RetentionPolicy.RUNTIME) 18 | @Documented 19 | public @interface CmdNotice { 20 | String value() default ""; 21 | /** 22 | * 匹配的notice_type 23 | * @return 24 | */ 25 | NoticeType[] noticeType() default NoticeType._ALL; 26 | /** 27 | * 匹配的sub_type 28 | * @return 29 | */ 30 | NoticeSubType[] subType() default NoticeSubType._ALL; 31 | String[] executeMethod() default {"execute"}; 32 | boolean enableAutowiredParam() default true; 33 | int order() default 999; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/autoconfigure/EventCmdPostProcessor.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.autoconfigure; 2 | 3 | import java.lang.reflect.Parameter; 4 | import java.util.Map; 5 | 6 | import org.accen.dmzj.core.AccenbotContext; 7 | import org.accen.dmzj.core.AccenbotContext.AccenbotCmdProxy; 8 | 9 | /** 10 | * cmd执行器前后预置,{@link AccenbotContext#acceptEvent} 11 | * @author Accen 12 | * @since 2.2 13 | */ 14 | public interface EventCmdPostProcessor { 15 | default public boolean beforeEventCmdPost(AccenbotCmdProxy proxy,Map event) {return true;} 16 | default public Object afterEventCmdPost(AccenbotCmdProxy proxy,Map event,Object invokeResult) {return invokeResult;} 17 | 18 | /** 19 | * 处理proxy执行的方法参数 20 | * @param proxy 21 | * @param event 22 | * @param p 23 | * @param lastParameterValue 默认该parameter的值 24 | * @return 25 | */ 26 | default public Object eventCmdParamPost(AccenbotCmdProxy proxy,Map event,Parameter p,Object lastParameterValue) {return lastParameterValue;} 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/annotation/GeneralMessage.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | import org.accen.dmzj.core.handler.CmdManager; 10 | import org.accen.dmzj.core.task.GeneralTask; 11 | 12 | /** 13 | * 配合{@link CmdRegular}标识方法后,将自动将方法的返回值做{@link GeneralTask}处理 14 | * @see CmdManager 15 | * @author Accen 16 | * @since 2.1 17 | */ 18 | @Target(ElementType.METHOD) 19 | @Retention(RetentionPolicy.RUNTIME) 20 | @Documented 21 | public @interface GeneralMessage { 22 | /** 23 | * @see GeneralTask#setType(String) 24 | * @return 25 | */ 26 | String type() default ""; 27 | /** 28 | * @see GeneralTask#setTargetId(String) 29 | * @return 30 | */ 31 | String targetId() default ""; 32 | /** 33 | * @see GeneralTask#setSelfQnum(String) 34 | * @return 35 | */ 36 | String selfNum() default ""; 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/task/GeneralTask.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.task; 2 | 3 | public class GeneralTask { 4 | private String type; 5 | private String targetId; 6 | private String message; 7 | private String selfQnum; 8 | public String getType() { 9 | return type; 10 | } 11 | public void setType(String type) { 12 | this.type = type; 13 | } 14 | public String getTargetId() { 15 | return targetId; 16 | } 17 | public void setTargetId(String targetId) { 18 | this.targetId = targetId; 19 | } 20 | public String getMessage() { 21 | return message; 22 | } 23 | public void setMessage(String message) { 24 | this.message = message; 25 | } 26 | public String getSelfQnum() { 27 | return selfQnum; 28 | } 29 | public void setSelfQnum(String selfQnum) { 30 | this.selfQnum = selfQnum; 31 | } 32 | public GeneralTask(String type, String targetId, String message, String selfQnum) { 33 | super(); 34 | this.type = type; 35 | this.targetId = targetId; 36 | this.message = message; 37 | this.selfQnum = selfQnum; 38 | } 39 | public GeneralTask() { 40 | super(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/cmd/AtSelfCmd.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.cmd; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | import org.accen.dmzj.core.task.GeneralTask; 7 | import org.accen.dmzj.util.CQUtil; 8 | import org.accen.dmzj.web.vo.Qmessage; 9 | import org.springframework.stereotype.Component; 10 | @Component 11 | public class AtSelfCmd implements CmdAdapter { 12 | private final static Pattern pattern = Pattern.compile("^\\[CQ:at,qq=(\\d+)\\]$"); 13 | 14 | @Override 15 | public GeneralTask cmdAdapt(Qmessage qmessage, String selfQnum) { 16 | String message = qmessage.getMessage().trim(); 17 | Matcher matcher = pattern.matcher(message); 18 | if(matcher.matches()) { 19 | if(selfQnum.equals(matcher.group(1))) { 20 | GeneralTask task = new GeneralTask(); 21 | 22 | task.setSelfQnum(selfQnum); 23 | task.setType(qmessage.getMessageType()); 24 | task.setTargetId(qmessage.getGroupId()); 25 | task.setMessage(CQUtil.at(qmessage.getUserId())+" 干嘛?"); 26 | return task; 27 | } 28 | } 29 | return null; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/util/setu/PixivSetuGreper.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.util.setu; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import org.accen.dmzj.core.api.PixivcatApiClient; 7 | import org.accen.dmzj.util.ApplicationContextUtil; 8 | /** 9 | * p站图抓取 10 | * @author Accen 11 | * 12 | */ 13 | public class PixivSetuGreper implements SetuGreper { 14 | private PixivcatApiClient pixivcatClient = ApplicationContextUtil.getBean(PixivcatApiClient.class); 15 | private SetuCatcher setuCatcher = ApplicationContextUtil.getBean(SetuCatcher.class); 16 | 17 | private List pids;//多图用-隔开 18 | 19 | public PixivSetuGreper(String... pids) { 20 | this.pids = Arrays.asList(pids); 21 | } 22 | public PixivSetuGreper(List pids) { 23 | this.pids = pids; 24 | } 25 | 26 | @Override 27 | public int grep() { 28 | if(pids==null||pids.isEmpty()) { 29 | return 0; 30 | }else { 31 | return (int)(pids.parallelStream().filter(pid->{ 32 | return setuCatcher.catchFromPid(pid, pid+SetuCatcher.SETU_SUFFIX); 33 | }).count()); 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/annotation/FuncSwitch.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | import org.accen.dmzj.core.handler.group.Default; 10 | 11 | /** 12 | * 配置在Cmd上面,标识其对应的功能点 13 | * @author Accen 14 | * 15 | */ 16 | @Target({ElementType.TYPE}) 17 | @Retention(RetentionPolicy.RUNTIME) 18 | @Documented 19 | public @interface FuncSwitch { 20 | /** 21 | * 功能key,默认cmd_类名 22 | * @return 23 | */ 24 | String name() default ""; 25 | /** 26 | * 是否要在菜单中展示出来 27 | * @return 28 | */ 29 | boolean showMenu() default false; 30 | /** 31 | * 功能名 32 | * @return 33 | */ 34 | String title(); 35 | /** 36 | * 排序 37 | * @return 38 | */ 39 | int order() default 99; 40 | /** 41 | * 格式 42 | * @return 43 | */ 44 | String format() default ""; 45 | /** 46 | * 所属分组 47 | * @return 48 | */ 49 | Class groupClass() default Default.class; 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/util/ApproximatelyEqualsUtil.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.util; 2 | /** 3 | * 近似相似 4 | * @author Accen 5 | * 6 | */ 7 | public class ApproximatelyEqualsUtil { 8 | public static final int IGNORE_CASE = 1; 9 | public static final int IGNORE_LINE = 2; 10 | public static final int IGNORE_BLANK = 4; 11 | public static boolean aequals(String s,String t,int ignoreLv) { 12 | if(s==null||t==null) { 13 | return false; 14 | } 15 | if((ignoreLv&IGNORE_CASE)==1) { 16 | s = s.toLowerCase(); 17 | t = t.toLowerCase(); 18 | if(s.equalsIgnoreCase(t)) { 19 | return true; 20 | } 21 | } 22 | if((ignoreLv&IGNORE_LINE)==1) { 23 | s = s.replaceAll("_", ""); 24 | t = t.replaceAll("_", ""); 25 | if(s.equalsIgnoreCase(t)) { 26 | return true; 27 | } 28 | } 29 | if((ignoreLv&IGNORE_BLANK)==1) { 30 | s = s.replace(" ", ""); 31 | t = t.replaceAll(" ", ""); 32 | if(s.equals(t)) { 33 | return true; 34 | } 35 | } 36 | return false; 37 | } 38 | public static boolean aequals(String s,String t) { 39 | return aequals(s, t, (1<<5)-1); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/autoconfigure/CmdWorkdirIniter.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.autoconfigure; 2 | 3 | import java.io.File; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.BeansException; 8 | import org.springframework.beans.factory.config.BeanPostProcessor; 9 | import org.springframework.stereotype.Component; 10 | /** 11 | * 初始化cmd时,同时统一初始化其工作目录 12 | * @author Accen 13 | * 14 | */ 15 | @Component 16 | public class CmdWorkdirIniter implements BeanPostProcessor{ 17 | private final static Logger logger = LoggerFactory.getLogger(CmdWorkdirIniter.class); 18 | @SuppressWarnings("preview") 19 | @Override 20 | public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 21 | if(bean instanceof Workdirer wbean) { 22 | String workdir = wbean.workdir(); 23 | File dir = new File(workdir); 24 | if(!dir.exists()) { 25 | logger.info("cmd:{}的工作目录{}不存在,即将创建...", beanName,dir.getName()); 26 | dir.mkdirs(); 27 | } 28 | } 29 | return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/SaucenaoApiClient.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api; 2 | 3 | import org.springframework.cloud.openfeign.FeignClient; 4 | import org.springframework.http.MediaType; 5 | import org.springframework.web.bind.annotation.PostMapping; 6 | import org.springframework.web.bind.annotation.RequestParam; 7 | import org.springframework.web.bind.annotation.RequestPart; 8 | import org.springframework.web.multipart.MultipartFile; 9 | 10 | @FeignClient( 11 | name="saucenao", 12 | url="https://saucenao.com") 13 | public interface SaucenaoApiClient { 14 | /** 15 | * 调用saucenao.com进行图片检索 16 | * @param image 17 | * @return 18 | */ 19 | @PostMapping(value="/search.php",headers= {"Content-Type: multipart/form-data"},consumes = MediaType.MULTIPART_FORM_DATA_VALUE) 20 | public String search(@RequestPart("file") MultipartFile image); 21 | 22 | /** 23 | * 调用saucenao.com进行图片检索 24 | * @param image 25 | * @return 26 | */ 27 | @PostMapping(value="/search.php",headers = {"Content-Type: multipart/form-data"}) 28 | public String search(@RequestParam("url") String url); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/util/ImageUtil.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.util; 2 | 3 | import java.awt.color.ColorSpace; 4 | import java.awt.image.BufferedImage; 5 | import java.awt.image.ColorConvertOp; 6 | import java.io.File; 7 | import java.io.IOException; 8 | 9 | import javax.imageio.ImageIO; 10 | 11 | public class ImageUtil { 12 | /** 13 | * 将图片变成灰度 14 | * @param originImage 15 | * @param newFile 16 | */ 17 | public static void toGray(File originFile,File newFile) { 18 | BufferedImage originImage; 19 | try { 20 | originImage = ImageIO.read(originFile); 21 | BufferedImage newPic = new BufferedImage(originImage.getWidth(), originImage.getHeight(), 22 | BufferedImage.TYPE_3BYTE_BGR); 23 | 24 | ColorConvertOp cco = new ColorConvertOp(ColorSpace 25 | .getInstance(ColorSpace.CS_GRAY), null); 26 | cco.filter(originImage, newPic); 27 | try { 28 | ImageIO.write(newPic, "jpg", newFile); 29 | } catch (IOException e) { 30 | e.printStackTrace(); 31 | } 32 | } catch (IOException e1) { 33 | // TODO Auto-generated catch block 34 | e1.printStackTrace(); 35 | } 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/bilibili/ApiVcBilibiliApiClient.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.bilibili; 2 | 3 | import java.util.Map; 4 | 5 | import org.springframework.cloud.openfeign.FeignClient; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RequestParam; 8 | 9 | /** 10 | * 用来获取B站动态的API,up主不管发文章还是视频,都会已动 态的形式呈现 11 | * @author Accen 12 | * 13 | */ 14 | @FeignClient(name="bilibili-vc", 15 | url="https://api.vc.bilibili.com") 16 | public interface ApiVcBilibiliApiClient { 17 | /** 18 | * 获取up动态 19 | * @param visitorUid 参观者uid(貌似没啥用,b站不知道有没有私密动态的说法) 20 | * @param hostUid up uid 21 | * @param offsetDynamicId 起始id(不含) 22 | * @return 主要解析card字段的json,和desc-timestamp 注意这个timestamp需要*1000才是UNIX时间戳
23 | * type 8:视频
2:普通动态
64:专栏
1:转发动态
4:普通动态(但是解析同转发动态,不知道有什么区别)
256: 音乐
512:番剧
16:小视频(估计还有16,32,128暂时没看出来,) 24 | */ 25 | @GetMapping("/dynamic_svr/v1/dynamic_svr/space_history") 26 | public Map dynamic(@RequestParam("visitor_uid")String visitorUid,@RequestParam("host_uid")String hostUid,@RequestParam("offset_dynamic_id")long offsetDynamicId); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/pixivc/PixivcAuthConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.pixivc; 2 | 3 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | import feign.RequestInterceptor; 8 | import feign.Response; 9 | /** 10 | * pixivc的配置 11 | * @author Accen 12 | * 13 | */ 14 | import feign.codec.ErrorDecoder; 15 | @Configuration 16 | @EnableConfigurationProperties(PixivcAuthConfigurationProperties.class) 17 | public class PixivcAuthConfiguration { 18 | private PixivcAuthConfigurationProperties prop; 19 | public PixivcAuthConfiguration(PixivcAuthConfigurationProperties prop) { 20 | this.prop = prop; 21 | } 22 | 23 | @Bean 24 | public RequestInterceptor pixivcAuthFeignRequestInterceptor() { 25 | return new PixivcAuthFeignRequestInterceptor(this.prop); 26 | } 27 | // /** 28 | // * 处理401 29 | // * @return 30 | // */ 31 | // @Bean 32 | // public ErrorDecoder UnauthorizedErrorDecoder() { 33 | // return (methodKey, response)->{ 34 | // 35 | // return null; 36 | // 37 | // }; 38 | // } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/util/render/PixivUrlRenderImage.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.util.render; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics2D; 5 | import java.awt.Stroke; 6 | import java.io.IOException; 7 | import java.net.URL; 8 | 9 | import render.UrlScalebleRenderImage; 10 | 11 | public class PixivUrlRenderImage extends UrlScalebleRenderImage { 12 | private String pid; 13 | private String title; 14 | private String author; 15 | 16 | public PixivUrlRenderImage(URL url,String pid,String title,String author) throws IOException { 17 | super(url); 18 | this.pid = pid; 19 | this.title = title; 20 | this.author = author; 21 | } 22 | /** 23 | * 写完图片后把元信息也一并写上去 24 | */ 25 | @Override 26 | public void afterRenderMe(Graphics2D graph,int x,int y) { 27 | Color originColor = graph.getColor(); 28 | Stroke originStroke = graph.getStroke(); 29 | //写字 30 | TextRenderUtil.renderTextAndOutline("PID:"+pid,graph ,x+10,y+30); 31 | TextRenderUtil.renderTextAndOutline("Title:"+title,graph,x+10, y+30+30); 32 | TextRenderUtil.renderTextAndOutline("Author:"+author,graph,x+10, y+30+60); 33 | 34 | graph.setColor(originColor); 35 | graph.setStroke(originStroke); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/dao/SysFileMapper.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.dao; 2 | 3 | import org.accen.dmzj.web.vo.SysFile; 4 | import org.apache.ibatis.annotations.Insert; 5 | import org.apache.ibatis.annotations.Param; 6 | import org.apache.ibatis.annotations.Result; 7 | import org.apache.ibatis.annotations.Results; 8 | import org.apache.ibatis.annotations.Select; 9 | 10 | public interface SysFileMapper { 11 | @Results(id = "sysFileMapper",value = { 12 | @Result(property = "id",column = "id"), 13 | @Result(property = "fileName",column = "file_name"), 14 | @Result(property = "fileType",column = "file_type"), 15 | @Result(property = "sha",column = "sha"), 16 | @Result(property = "ftpPath",column = "ftp_path"), 17 | @Result(property = "createTime",column = "create_time"), 18 | @Result(property = "createUserId",column = "create_user_id") 19 | }) 20 | @Select("select * from sys_file where id = #{id}") 21 | public SysFile selectById(@Param("id")String id); 22 | 23 | @Insert("insert into sys_file(id,file_name,file_type,sha,ftp_path,create_time,create_user_id) " 24 | + "values (#{id},#{fileName},#{fileType},#{sha},#{ftpPath},#{createTime},#{createUserId}) ") 25 | public long insert(SysFile file); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/timer/RankType.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.timer; 2 | 3 | import java.time.DayOfWeek; 4 | import java.time.LocalDate; 5 | import java.time.temporal.TemporalAdjusters; 6 | 7 | public enum RankType { 8 | DAY("day"),WEEK("week"),MONTH("month"); 9 | private String mode; 10 | private RankType(String mode) { 11 | this.mode = mode; 12 | } 13 | public String getMode() { 14 | return this.mode; 15 | } 16 | public LocalDate virtualDate(LocalDate factDate,int offset) { 17 | if(factDate==null) { 18 | factDate = LocalDate.now(); 19 | } 20 | LocalDate curVirtualDate = factDate.minusDays(2);//先延迟 21 | 22 | switch(this) { 23 | case DAY: 24 | curVirtualDate = curVirtualDate.minusDays(offset);//再往前推offset天 25 | break; 26 | case WEEK: 27 | curVirtualDate = curVirtualDate 28 | .with(TemporalAdjusters.previous(DayOfWeek.MONDAY)) 29 | .minusWeeks(offset);//变成周一后再往前推offset周 30 | break; 31 | case MONTH: 32 | curVirtualDate = curVirtualDate 33 | .with(TemporalAdjusters.firstDayOfMonth()) 34 | .minusMonths(offset);//变成1号后再往前推offset月 35 | break; 36 | default: 37 | curVirtualDate = curVirtualDate.minusDays(offset);//再往前推offset天 38 | break; 39 | } 40 | return curVirtualDate; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/cmd/BiliBiliCookie.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.cmd; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | import org.accen.dmzj.core.task.GeneralTask; 7 | import org.accen.dmzj.core.api.bilibili.ApiBiliBiliApiClient; 8 | import org.accen.dmzj.web.vo.Qmessage; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Component; 11 | 12 | @Component 13 | public class BiliBiliCookie implements CmdAdapter { 14 | 15 | @Autowired 16 | private ApiBiliBiliApiClient apiClient; 17 | 18 | private final static Pattern grepPattern = Pattern.compile("^设置B站Cookie(.+)"); 19 | @Override 20 | public GeneralTask cmdAdapt(Qmessage qmessage, String selfQnum) { 21 | String message = qmessage.getMessage().trim(); 22 | Matcher matcher = grepPattern.matcher(message); 23 | if(matcher.matches()) { 24 | 25 | apiClient.setSessData(matcher.group(1)); 26 | 27 | GeneralTask task = new GeneralTask(); 28 | task.setSelfQnum(selfQnum); 29 | task.setType(qmessage.getMessageType()); 30 | task.setTargetId(qmessage.getGroupId()); 31 | 32 | task.setMessage("Cookie设置成功!"); 33 | return task; 34 | } 35 | return null; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/timer/PrankSchedule.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.timer; 2 | 3 | import java.time.LocalDate; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.scheduling.annotation.Scheduled; 9 | import org.springframework.stereotype.Component; 10 | 11 | @Component 12 | public class PrankSchedule { 13 | private static final Logger logger = LoggerFactory.getLogger(PrankSchedule.class); 14 | @Autowired 15 | private Prank prank; 16 | /** 17 | * 每天的凌晨1点刷一次日榜 18 | */ 19 | @Scheduled(cron = "0 0 1 * * *") 20 | public void todayRank() { 21 | for(int page=1;page<=9;page++) { 22 | prank.rank(LocalDate.now(), RankType.DAY, 0, page, null); 23 | } 24 | 25 | } 26 | /** 27 | * 每周三的凌晨2点刷一次周榜 28 | */ 29 | @Scheduled(cron = "0 0 2 * * WED") 30 | public void weekRank() { 31 | for(int page=1;page<=9;page++) { 32 | prank.rank(LocalDate.now(), RankType.WEEK, 0, page, null); 33 | } 34 | } 35 | /** 36 | * 每月三号3点刷一次月榜 37 | */ 38 | @Scheduled(cron = "0 0 3 3 * *") 39 | public void monthRank() { 40 | for(int page=1;page<=9;page++) { 41 | prank.rank(LocalDate.now(), RankType.MONTH, 0, page, null); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/vo/CmdTips.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.vo; 2 | /** 3 | * tips实体 4 | * @author Accen 5 | * 6 | */ 7 | public class CmdTips { 8 | private long id; 9 | private String moduleName; 10 | private String moduleCode; 11 | private String cmdFunc; 12 | private String content; 13 | private short status;//1-启用,2-停用 14 | public long getId() { 15 | return id; 16 | } 17 | public void setId(long id) { 18 | this.id = id; 19 | } 20 | public String getModuleName() { 21 | return moduleName; 22 | } 23 | public void setModuleName(String moduleName) { 24 | this.moduleName = moduleName; 25 | } 26 | public String getModuleCode() { 27 | return moduleCode; 28 | } 29 | public void setModuleCode(String moduleCode) { 30 | this.moduleCode = moduleCode; 31 | } 32 | public String getCmdFunc() { 33 | return cmdFunc; 34 | } 35 | public void setCmdFunc(String cmdFunc) { 36 | this.cmdFunc = cmdFunc; 37 | } 38 | public String getContent() { 39 | return content; 40 | } 41 | public void setContent(String content) { 42 | this.content = content; 43 | } 44 | public short getStatus() { 45 | return status; 46 | } 47 | public void setStatus(short status) { 48 | this.status = status; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/vo/YoudaoTranslateResult.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.vo; 2 | 3 | public class YoudaoTranslateResult { 4 | private String type; 5 | private int errorCode; 6 | private int elapsedTime; 7 | private Result[][] translateResult; 8 | public class Result{ 9 | private String src; 10 | private String tgt; 11 | public String getSrc() { 12 | return src; 13 | } 14 | public void setSrc(String src) { 15 | this.src = src; 16 | } 17 | public String getTgt() { 18 | return tgt; 19 | } 20 | public void setTgt(String tgt) { 21 | this.tgt = tgt; 22 | } 23 | 24 | } 25 | public int getElapsedTime() { 26 | return elapsedTime; 27 | } 28 | public void setElapsedTime(int elapsedTime) { 29 | this.elapsedTime = elapsedTime; 30 | } 31 | public String getType() { 32 | return type; 33 | } 34 | public void setType(String type) { 35 | this.type = type; 36 | } 37 | public int getErrorCode() { 38 | return errorCode; 39 | } 40 | public void setErrorCode(int errorCode) { 41 | this.errorCode = errorCode; 42 | } 43 | public Result[][] getTranslateResult() { 44 | return translateResult; 45 | } 46 | public void setTranslateResult(Result[][] translateResult) { 47 | this.translateResult = translateResult; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/cmd/Repeat.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.cmd; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | import org.accen.dmzj.core.annotation.FuncSwitch; 7 | import org.accen.dmzj.core.task.GeneralTask; 8 | import org.accen.dmzj.util.CQUtil; 9 | import org.accen.dmzj.web.vo.Qmessage; 10 | import org.springframework.stereotype.Component; 11 | @FuncSwitch(title = "复读") 12 | @Component 13 | public class Repeat implements CmdAdapter { 14 | 15 | private final static Pattern pattern = Pattern.compile("^老婆说(/|\\$|%)?(.+)"); 16 | 17 | @Override 18 | public GeneralTask cmdAdapt(Qmessage qmessage, String selfQnum) { 19 | String message = qmessage.getMessage().trim(); 20 | Matcher matcher = pattern.matcher(message); 21 | if(matcher.matches()) { 22 | GeneralTask task = new GeneralTask(); 23 | 24 | task.setSelfQnum(selfQnum); 25 | task.setType(qmessage.getMessageType()); 26 | task.setTargetId(qmessage.getGroupId()); 27 | String sign = matcher.group(1); 28 | if("/".equals(sign)) { 29 | //如果为/,则识别为一个语音网络地址 30 | task.setMessage(CQUtil.recordUrl(matcher.group(2))); 31 | }else { 32 | task.setMessage(matcher.group(2).replaceAll("我", "##").replaceAll("你", "我").replaceAll("##", "你")); 33 | } 34 | 35 | return task; 36 | } 37 | return null; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/vo/CmdWiki.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.vo; 2 | 3 | public class CmdWiki { 4 | private long id; 5 | private String article;//来源作品 6 | private String wikiName;//词条名 7 | private String keywords;//检索词。多个使用,隔开 8 | private String content;//说明 9 | private String image;//图片。多个使用,隔开 10 | private int status;//1-保存,2-审核 3-有效 0-无效 11 | public long getId() { 12 | return id; 13 | } 14 | public void setId(long id) { 15 | this.id = id; 16 | } 17 | public String getArticle() { 18 | return article; 19 | } 20 | public void setArticle(String article) { 21 | this.article = article; 22 | } 23 | public String getWikiName() { 24 | return wikiName; 25 | } 26 | public void setWikiName(String wikiName) { 27 | this.wikiName = wikiName; 28 | } 29 | public String getKeywords() { 30 | return keywords; 31 | } 32 | public void setKeywords(String keywords) { 33 | this.keywords = keywords; 34 | } 35 | public String getContent() { 36 | return content; 37 | } 38 | public void setContent(String content) { 39 | this.content = content; 40 | } 41 | public String getImage() { 42 | return image; 43 | } 44 | public void setImage(String image) { 45 | this.image = image; 46 | } 47 | public int getStatus() { 48 | return status; 49 | } 50 | public void setStatus(int status) { 51 | this.status = status; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/CmdManager.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler; 2 | 3 | import java.util.HashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import org.accen.dmzj.core.annotation.FuncSwitch; 8 | import org.accen.dmzj.core.handler.cmd.CmdAdapter; 9 | import org.accen.dmzj.core.task.TaskManager; 10 | import org.accen.dmzj.util.FuncSwitchUtil; 11 | import org.accen.dmzj.web.vo.Qmessage; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Component; 14 | 15 | @Component 16 | public class CmdManager{ 17 | 18 | 19 | /** 20 | * 处理事件的功能 21 | */ 22 | @Autowired 23 | private List allCmds; 24 | @Autowired 25 | private FuncSwitchUtil funcSwitchUtil; 26 | @Autowired 27 | private TaskManager taskManager; 28 | /** 29 | * 受{@link FuncSwitch}控制的功能 30 | */ 31 | Map allShowableCmds = new HashMap<>(16); 32 | public void accept(Qmessage qmessage) { 33 | 34 | allCmds.forEach(cmd->{ 35 | if(funcSwitchUtil.isCmdPass(cmd.getClass(), qmessage.getMessageType(), qmessage.getGroupId())) { 36 | taskManager.addGeneralTask(cmd.cmdAdapt(qmessage, qmessage.getEvent().get("self_id").toString())); 37 | } 38 | }); 39 | cmdRegularManager.accept(qmessage, taskManager); 40 | } 41 | @Autowired 42 | private CmdRegularManager cmdRegularManager; 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/vo/SysFile.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.vo; 2 | 3 | import java.util.Date; 4 | 5 | public class SysFile { 6 | private String id;//使用uuid 7 | private String fileName; 8 | private String fileType;//suffix 9 | private String sha;//sha-1 10 | private String ftpPath; 11 | private Date createTime; 12 | private String createUserId; 13 | public Date getCreateTime() { 14 | return createTime; 15 | } 16 | public void setCreateTime(Date createTime) { 17 | this.createTime = createTime; 18 | } 19 | public String getId() { 20 | return id; 21 | } 22 | public void setId(String id) { 23 | this.id = id; 24 | } 25 | public String getFileName() { 26 | return fileName; 27 | } 28 | public void setFileName(String fileName) { 29 | this.fileName = fileName; 30 | } 31 | public String getFileType() { 32 | return fileType; 33 | } 34 | public void setFileType(String fileType) { 35 | this.fileType = fileType; 36 | } 37 | public String getSha() { 38 | return sha; 39 | } 40 | public void setSha(String sha) { 41 | this.sha = sha; 42 | } 43 | public String getFtpPath() { 44 | return ftpPath; 45 | } 46 | public void setFtpPath(String ftpPath) { 47 | this.ftpPath = ftpPath; 48 | } 49 | public String getCreateUserId() { 50 | return createUserId; 51 | } 52 | public void setCreateUserId(String createUserId) { 53 | this.createUserId = createUserId; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/vo/BilibiliSearch.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.vo; 2 | 3 | import java.util.Map; 4 | 5 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 6 | import com.fasterxml.jackson.annotation.JsonProperty; 7 | 8 | @SuppressWarnings("preview") 9 | @JsonIgnoreProperties(ignoreUnknown = true) 10 | public record BilibiliSearch(@JsonProperty("code") int code,@JsonProperty("message") String message,@JsonProperty("ttl") int ttl,@JsonProperty("data") BilibiliSearchData data) { 11 | public record BilibiliSearchData(@JsonProperty("seid") String seid,@JsonProperty("page") int page,@JsonProperty("pagesize") int pagesize,@JsonProperty("numResults") int numResults 12 | ,@JsonProperty("numPages") int numPages,@JsonProperty("suggest_keyword") String suggest_keyword,@JsonProperty("rqt_type") String rqt_type,@JsonProperty("result") Map[] result) { 13 | /*public record BilibiliSearchDataResult(@JsonProperty("type") String type,@JsonProperty("mid") int mid,@JsonProperty("uname") String uname,@JsonProperty("usign") String usign 14 | ,@JsonProperty("fans") int fans,@JsonProperty("videos") int videos,@JsonProperty("upic") String upic,@JsonProperty("verify_info") String verify_info,@JsonProperty("level") int level 15 | ,@JsonProperty("gender") int gender,@JsonProperty("is_upuser") int is_upuser,@JsonProperty("is_live") int is_live,@JsonProperty("room_id") int room_id) {} 16 | */ 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/dao/CmdWikiMapper.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.dao; 2 | 3 | import java.util.List; 4 | 5 | import org.accen.dmzj.web.vo.CmdWiki; 6 | import org.apache.ibatis.annotations.Mapper; 7 | import org.apache.ibatis.annotations.Param; 8 | import org.apache.ibatis.annotations.Result; 9 | import org.apache.ibatis.annotations.ResultMap; 10 | import org.apache.ibatis.annotations.Results; 11 | import org.apache.ibatis.annotations.Select; 12 | 13 | 14 | @Mapper 15 | public interface CmdWikiMapper { 16 | @Results(id = "cmdWikiMapper",value = { 17 | @Result(property = "id",column = "id"), 18 | @Result(property = "article",column = "article"), 19 | @Result(property = "wikiName",column = "wiki_name"), 20 | @Result(property = "keywords",column = "keywords"), 21 | @Result(property = "content",column = "content"), 22 | @Result(property = "image",column = "image"), 23 | @Result(property = "status",column = "status") 24 | }) 25 | @Select("select * from cmd_wiki where id = #{id}") 26 | public CmdWiki selectById(@Param("id")long id); 27 | 28 | @ResultMap("cmdWikiMapper") 29 | @Select("select * from cmd_wiki where wiki_name = #{name} and status = 3 ") 30 | public CmdWiki selectByName(@Param("name")String wikiName); 31 | 32 | @ResultMap("cmdWikiMapper") 33 | @Select("select * from cmd_wiki where keywords like concat('%',concat(#{keyword},'%')) and status = 3 ") 34 | public List findByKeyword(String keyword); 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/listen/ChaosListener.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.listen; 2 | 3 | import java.util.List; 4 | import java.util.Set; 5 | 6 | import org.accen.dmzj.core.handler.cmd.ChaosMode; 7 | import org.accen.dmzj.core.task.GeneralTask; 8 | import org.accen.dmzj.core.task.TaskManager; 9 | import org.accen.dmzj.util.QmessageUtil; 10 | import org.accen.dmzj.util.RandomUtil; 11 | import org.accen.dmzj.web.vo.Qmessage; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.beans.factory.annotation.Value; 14 | import org.springframework.stereotype.Component; 15 | @Component 16 | public class ChaosListener implements ListenAdpter{ 17 | @Autowired 18 | private ChaosMode chaosModeCmd; 19 | @Autowired 20 | private QmessageUtil qmessageUtil; 21 | @Value("${coolq.chaosmod.prop:0.05}") 22 | private float prop; 23 | @Autowired 24 | private TaskManager taskManager; 25 | @Override 26 | public List listen(Qmessage qmessage, String selfQnum) { 27 | Set groups = qmessageUtil.groupList(); 28 | groups.remove(qmessage.getGroupId()); 29 | if(groups.size()>0 && RandomUtil.randomPass(prop)) { 30 | String group = (String) (groups.toArray())[RandomUtil.randomInt(groups.size())]; 31 | if(chaosModeCmd.modeOpen(group)) { 32 | taskManager.addGeneralTaskQuick(selfQnum, qmessage.getMessageType(), group, qmessage.getMessage()); 33 | } 34 | } 35 | return null; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/vo/CfgConfigValue.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.vo; 2 | 3 | import java.util.Date; 4 | 5 | public class CfgConfigValue { 6 | private long id; 7 | private String targetType; 8 | private String target; 9 | private String configKey; 10 | private String configValue; 11 | private String updateUserId; 12 | private Date updateTime; 13 | public long getId() { 14 | return id; 15 | } 16 | public void setId(long id) { 17 | this.id = id; 18 | } 19 | public String getTargetType() { 20 | return targetType; 21 | } 22 | public void setTargetType(String targetType) { 23 | this.targetType = targetType; 24 | } 25 | public String getTarget() { 26 | return target; 27 | } 28 | public void setTarget(String target) { 29 | this.target = target; 30 | } 31 | public String getConfigKey() { 32 | return configKey; 33 | } 34 | public void setConfigKey(String configKey) { 35 | this.configKey = configKey; 36 | } 37 | public String getConfigValue() { 38 | return configValue; 39 | } 40 | public void setConfigValue(String configValue) { 41 | this.configValue = configValue; 42 | } 43 | public String getUpdateUserId() { 44 | return updateUserId; 45 | } 46 | public void setUpdateUserId(String updateUserId) { 47 | this.updateUserId = updateUserId; 48 | } 49 | public Date getUpdateTime() { 50 | return updateTime; 51 | } 52 | public void setUpdateTime(Date updateTime) { 53 | this.updateTime = updateTime; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/cq/CqhttpConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.cq; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | import org.accen.dmzj.core.feign.auth.HeaderAuthFeignRequestInterceptor; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.util.StringUtils; 9 | 10 | import feign.Request.Options; 11 | import feign.RequestInterceptor; 12 | import feign.Retryer; 13 | 14 | @Configuration 15 | public class CqhttpConfiguration { 16 | private CqHttpConfigurationProperties prop; 17 | public CqhttpConfiguration(CqHttpConfigurationProperties prop) { 18 | this.prop = prop; 19 | } 20 | @Bean 21 | public RequestInterceptor cqhttpRequestInterceptor() { 22 | return new CqhttpAuthRequestInterceptor(this.prop); 23 | } 24 | @Bean 25 | public Retryer cqhttpRetryer() { 26 | return new Retryer.Default(this.prop.period(), this.prop.maxPeriod(), this.prop.maxAttempt()); 27 | } 28 | @Bean 29 | public Options cqhttpOptions() { 30 | return new Options(this.prop.connectTimeout(),TimeUnit.MILLISECONDS, this.prop.readTimeout(),TimeUnit.MILLISECONDS,true); 31 | } 32 | } 33 | class CqhttpAuthRequestInterceptor extends HeaderAuthFeignRequestInterceptor{ 34 | private CqHttpConfigurationProperties prop; 35 | public CqhttpAuthRequestInterceptor(CqHttpConfigurationProperties prop) { 36 | this.prop = prop; 37 | if(StringUtils.hasLength(this.prop.token())){ 38 | super.addHeader("Authorization", "Bearer "+this.prop.token()); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/dao/QmessageMapper.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.dao; 2 | 3 | import org.accen.dmzj.web.vo.Qmessage; 4 | import org.apache.ibatis.annotations.Insert; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Options; 7 | import org.apache.ibatis.annotations.Param; 8 | import org.apache.ibatis.annotations.Result; 9 | import org.apache.ibatis.annotations.Results; 10 | import org.apache.ibatis.annotations.Select; 11 | 12 | @Mapper 13 | public interface QmessageMapper { 14 | @Results(id="qmessageResultMap",value= { 15 | @Result(property = "id",column = "id"), 16 | @Result(property = "messageType",column = "message_type"), 17 | @Result(property = "subType",column = "sub_type"), 18 | @Result(property = "messageId",column = "message_id"), 19 | @Result(property = "groupId",column = "group_id"), 20 | @Result(property = "userId",column = "user_id"), 21 | @Result(property = "message",column = "message"), 22 | @Result(property = "rawMessage",column = "raw_message"), 23 | @Result(property = "sendTime",column = "send_time"), 24 | @Result(property = "font",column = "font") 25 | }) 26 | @Select("select * from qmessage where id = #{id}") 27 | public Qmessage selectById(@Param("id") long id); 28 | @Insert("insert into qmessage(message_type,sub_type,message_id,group_id,user_id,message,raw_message,send_time,font)" 29 | + " values(#{messageType},#{subType},#{messageId},#{groupId},#{userId},#{message},#{rawMessage},#{sendTime},#{font})") 30 | @Options(useGeneratedKeys = true,keyProperty = "id") 31 | public long insert(Qmessage qmessage); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/util/setu/CqSetuGreper.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.util.setu; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | import org.accen.dmzj.util.ApplicationContextUtil; 8 | import org.accen.dmzj.util.FilePersistentUtil; 9 | import org.accen.dmzj.web.vo.Qmessage; 10 | 11 | public class CqSetuGreper implements SetuGreper { 12 | private List imageCqs; 13 | private long minSize; 14 | private long maxSize; 15 | private Qmessage qmessage; 16 | private FilePersistentUtil filePersistentUtil = ApplicationContextUtil.getBean(FilePersistentUtil.class); 17 | private SetuCatcher setuCatcher = ApplicationContextUtil.getBean(SetuCatcher.class); 18 | public CqSetuGreper(long minSize,long maxSize,Qmessage qmessage,String... imageCqs) { 19 | this.qmessage = qmessage; 20 | this.minSize = minSize; 21 | this.maxSize = maxSize; 22 | this.imageCqs = Arrays.asList(imageCqs); 23 | } 24 | public CqSetuGreper(long minSize,long maxSize,Qmessage qmessage,List imageCqs) { 25 | this.qmessage = qmessage; 26 | this.minSize = minSize; 27 | this.maxSize = maxSize; 28 | this.imageCqs = new ArrayList(imageCqs); 29 | } 30 | @Override 31 | public int grep() { 32 | if(imageCqs == null ||imageCqs.isEmpty()) { 33 | return 0; 34 | }else { 35 | return (int)(this.imageCqs.parallelStream() 36 | .filter(cq->{long size = Long.parseLong(filePersistentUtil.getImageMetaInfo(cq)[3]); 37 | return size>=minSize&&size<=maxSize&&setuCatcher.catchFromCqImage(cq, setuCatcher.uuSetuName(qmessage));}) 38 | .count()); 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/baidu/BaikeRedirectClient.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.baidu; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.net.ssl.HostnameVerifier; 6 | import javax.net.ssl.SSLSocketFactory; 7 | 8 | import org.apache.http.HttpResponse; 9 | import org.apache.http.client.HttpClient; 10 | import org.apache.http.client.methods.HttpGet; 11 | import org.apache.http.impl.client.HttpClientBuilder; 12 | 13 | import feign.Client; 14 | import feign.Request; 15 | import feign.Request.Options; 16 | import feign.Response; 17 | 18 | @Deprecated 19 | public class BaikeRedirectClient extends Client.Default { 20 | 21 | public BaikeRedirectClient(SSLSocketFactory sslContextFactory, HostnameVerifier hostnameVerifier) { 22 | super(sslContextFactory, hostnameVerifier); 23 | } 24 | 25 | @Override 26 | public Response execute(Request request, Options options) throws IOException { 27 | HttpClient client = HttpClientBuilder.create().build(); 28 | HttpGet getReq = new HttpGet(request.url()); 29 | HttpResponse originResp = client.execute(getReq); 30 | // Response originResp = super.execute(request, options); 31 | if(originResp.getStatusLine().getStatusCode()>=300&&originResp.getStatusLine().getStatusCode()<400) { 32 | //3XX则表示需要进一步操作即重定向 33 | String newUrl = "https:"+(originResp.getHeaders("Location"))[0].toString(); 34 | //重新定义request 35 | Request newRequest= Request.create(request.httpMethod(), newUrl, request.headers(), request.body(),request.charset()); 36 | return super.execute(newRequest, options); 37 | }else { 38 | return super.execute(request, options); 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/util/CmdTipsMapper.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.util; 2 | 3 | import java.util.List; 4 | 5 | import org.accen.dmzj.web.vo.CmdTips; 6 | import org.apache.ibatis.annotations.Mapper; 7 | import org.apache.ibatis.annotations.Param; 8 | import org.apache.ibatis.annotations.Result; 9 | import org.apache.ibatis.annotations.ResultMap; 10 | import org.apache.ibatis.annotations.Results; 11 | import org.apache.ibatis.annotations.Select; 12 | 13 | @Mapper 14 | public interface CmdTipsMapper { 15 | @Results(id = "cmdTipsMapper",value = { 16 | @Result(property = "id",column = "id"), 17 | @Result(property = "moduleCode",column = "module_code"), 18 | @Result(property = "moduleName",column = "module_name"), 19 | @Result(property = "cmdFunc",column = "cmd_func"), 20 | @Result(property = "content",column = "content"), 21 | @Result(property = "status",column = "status") 22 | }) 23 | @Select("select * from cmd_tips where id = #{id}") 24 | public CmdTips selectById(@Param("id")long id); 25 | 26 | @ResultMap("cmdTipsMapper") 27 | @Select("select * from cmd_tips where module_code = #{moduleCode} and status = 1 ") 28 | public List findByModule(@Param("moduleCode")String moduleCode); 29 | 30 | @ResultMap("cmdTipsMapper") 31 | @Select("select * from cmd_tips where module_code = #{moduleCode} and status = 1 order by random() limit 1 ") 32 | public CmdTips selectByModuleRandom(@Param("moduleCode")String moduleCode); 33 | 34 | @ResultMap("cmdTipsMapper") 35 | @Select("select * from cmd_tips where cmd_func = #{cmdFunc} and status = 1 ") 36 | public CmdTips selectByCmdFunc(@Param("cmdFunc")String cmdFunc); 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/dao/SysRecordCountMapper.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.dao; 2 | 3 | import java.util.List; 4 | 5 | import org.accen.dmzj.web.vo.SysRecordCount; 6 | import org.apache.ibatis.annotations.Mapper; 7 | import org.apache.ibatis.annotations.Param; 8 | import org.apache.ibatis.annotations.Result; 9 | import org.apache.ibatis.annotations.ResultMap; 10 | import org.apache.ibatis.annotations.Results; 11 | import org.apache.ibatis.annotations.Select; 12 | 13 | @Mapper 14 | public interface SysRecordCountMapper { 15 | @Results(id = "sysRecordCountResultMap",value = { 16 | @Result(property = "recordType",column = "record_type"), 17 | @Result(property = "recordTarget",column = "record_target"), 18 | @Result(property = "recordValue",column = "record_value"), 19 | @Result(property = "attr1",column = "attr1"), 20 | @Result(property = "attr2",column = "attr2"), 21 | @Result(property = "createTime",column = "create_time"), 22 | @Result(property = "createUserId",column = "create_user_id"), 23 | @Result(property = "updateTime",column = "update_time"), 24 | @Result(property = "updateUserId",column = "update_user_id") 25 | }) 26 | @Select("select * from sys_record_count where id = #{id}") 27 | public SysRecordCount selectById(@Param("id") long id); 28 | @ResultMap("sysRecordCountResultMap") 29 | @Select("select * from sys_record_count where record_target = #{recordTarget}") 30 | public List findByTarget(@Param("recordTarget") String recordTarget); 31 | @ResultMap("sysRecordCountResultMap") 32 | @Select("select * from sys_record_count where record_type = #{record_type}") 33 | public List findByType(@Param("recordType") String recordType); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/timer/SuddenSetuSchedule.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.timer; 2 | 3 | import org.accen.dmzj.core.handler.GroupMessageEventHandlerAdpter; 4 | import org.accen.dmzj.core.handler.cmd.Setu; 5 | import org.accen.dmzj.core.task.GeneralTask; 6 | import org.accen.dmzj.core.task.TaskManager; 7 | import org.accen.dmzj.util.QmessageUtil; 8 | import org.accen.dmzj.util.RandomUtil; 9 | import org.accen.dmzj.web.vo.Qmessage; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.beans.factory.annotation.Value; 12 | import org.springframework.scheduling.annotation.Scheduled; 13 | import org.springframework.stereotype.Component; 14 | 15 | 16 | @Component 17 | public class SuddenSetuSchedule { 18 | @Autowired 19 | private QmessageUtil qmessageUtil; 20 | @Autowired 21 | private GroupMessageEventHandlerAdpter groupMessageEventhandler; 22 | @Autowired 23 | private Setu setuCmd; 24 | @Value("${coolq.bot}") 25 | private String botId; 26 | @Autowired 27 | private TaskManager taskManager; 28 | @Scheduled(cron = "0 0/10 9,10,11,12,14,15,16,17,18,19,20,21,22,23 * * *") 29 | public void suddenSetu() { 30 | //随机找一个群 31 | String[] groupArr = qmessageUtil.groupList().toArray(String[]::new); 32 | String groupId = groupArr[RandomUtil.randomInt(groupArr.length)]; 33 | if(groupMessageEventhandler.isActiveGroup(Long.valueOf(groupId))) { 34 | //伪造一个qmessage 35 | Qmessage qmessage = new Qmessage(); 36 | qmessage.setMessage("随机涩图");qmessage.setMessageType("group");qmessage.setGroupId(groupId); 37 | 38 | GeneralTask task = setuCmd.cmdAdapt(qmessage, botId); 39 | if(task!=null) { 40 | taskManager.addGeneralTask(task); 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/util/render/TextRenderUtil.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.util.render; 2 | 3 | import java.awt.BasicStroke; 4 | import java.awt.Color; 5 | import java.awt.Font; 6 | import java.awt.Graphics2D; 7 | import java.awt.Shape; 8 | import java.awt.font.TextLayout; 9 | 10 | public class TextRenderUtil { 11 | public static void renderTextAndOutline(String text,Font font,Graphics2D graph,float x,float y,Color textColor,Color outlineColor) { 12 | TextLayout tl = new TextLayout(text, font, graph.getFontRenderContext()); 13 | graph.setColor(textColor); 14 | tl.draw(graph, x, y); 15 | Shape s = tl.getOutline(null); 16 | graph.setStroke(new BasicStroke()); 17 | graph.translate(x, y); 18 | graph.setColor(outlineColor); 19 | graph.draw(s); 20 | graph.translate(-x, -y); 21 | } 22 | public static void renderTextAndOutline(float outlineSize,String text,Font font,Graphics2D graph,float x,float y,Color textColor,Color outlineColor) { 23 | TextLayout tl = new TextLayout(text, font, graph.getFontRenderContext()); 24 | graph.setColor(textColor); 25 | tl.draw(graph, x, y); 26 | Shape s = tl.getOutline(null); 27 | graph.setStroke(new BasicStroke(outlineSize)); 28 | graph.translate(x, y); 29 | graph.setColor(outlineColor); 30 | graph.draw(s); 31 | graph.translate(-x, -y); 32 | } 33 | public static void renderTextAndOutline(String text,Graphics2D graph,float x,float y) { 34 | renderTextAndOutline(text, new Font("Microsoft Yahei", Font.BOLD, 25), graph, x, y, Color.RED.darker(), Color.WHITE); 35 | } 36 | public static void renderTextAndOutline(String text,Font font,Graphics2D graph,float x,float y) { 37 | renderTextAndOutline(0.3f,text, font, graph, x, y, Color.WHITE, Color.BLACK.darker()); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/vo/CmdMyCard.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.vo; 2 | 3 | import java.util.Date; 4 | 5 | public class CmdMyCard { 6 | private long id; 7 | private String targetType; 8 | private String targetId; 9 | private String userId; 10 | private long pkId; 11 | private long cardId; 12 | private short isDeleted; 13 | private Date createTime; 14 | private Date updateTime; 15 | public long getId() { 16 | return id; 17 | } 18 | public void setId(long id) { 19 | this.id = id; 20 | } 21 | public String getTargetType() { 22 | return targetType; 23 | } 24 | public void setTargetType(String targetType) { 25 | this.targetType = targetType; 26 | } 27 | public String getTargetId() { 28 | return targetId; 29 | } 30 | public void setTargetId(String targetId) { 31 | this.targetId = targetId; 32 | } 33 | public String getUserId() { 34 | return userId; 35 | } 36 | public void setUserId(String userId) { 37 | this.userId = userId; 38 | } 39 | public long getPkId() { 40 | return pkId; 41 | } 42 | public void setPkId(long pkId) { 43 | this.pkId = pkId; 44 | } 45 | public long getCardId() { 46 | return cardId; 47 | } 48 | public void setCardId(long cardId) { 49 | this.cardId = cardId; 50 | } 51 | public short getIsDeleted() { 52 | return isDeleted; 53 | } 54 | public void setIsDeleted(short isDeleted) { 55 | this.isDeleted = isDeleted; 56 | } 57 | public Date getCreateTime() { 58 | return createTime; 59 | } 60 | public void setCreateTime(Date createTime) { 61 | this.createTime = createTime; 62 | } 63 | public Date getUpdateTime() { 64 | return updateTime; 65 | } 66 | public void setUpdateTime(Date updateTime) { 67 | this.updateTime = updateTime; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/pixivc/PixivicApiClient.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.pixivc; 2 | 3 | import java.util.Map; 4 | 5 | import org.springframework.cloud.openfeign.FeignClient; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.RequestParam; 9 | 10 | @FeignClient( 11 | name="pixivc-backend", 12 | url="https://pix.ipv4.host", 13 | configuration = PixivcAuthConfiguration.class) 14 | public interface PixivicApiClient { 15 | @GetMapping("/illustrations?pageSize=30&illustType=illust&searchType=original&maxSanityLevel=4") 16 | public Map search(@RequestParam("keyword")String keyword,@RequestParam("page")int page); 17 | /** 18 | * 搜索建议 19 | * @param keyword 20 | * @return 21 | */ 22 | @GetMapping("/keywords/{keyword}/pixivSuggestions") 23 | public Map suggestions(@PathVariable("keyword")String keyword); 24 | /** 25 | * 排行榜 26 | * @param page 27 | * @param date 28 | * @param mode 支持day,week,month 29 | * @return 30 | */ 31 | @GetMapping("/ranks") 32 | public Map rank(@RequestParam("page")int page,@RequestParam("date")String date,@RequestParam("mode")String mode); 33 | /** 34 | * 画师详情 35 | * @param id 36 | * @return 37 | */ 38 | @GetMapping("/artists/{id}") 39 | public Map artist(@PathVariable("id")int id); 40 | /** 41 | * 画师的作品 42 | * @param page 43 | * @param pageSize 44 | * @return 45 | */ 46 | @GetMapping("/artists/{id}/illusts/illust?maxSanityLevel=4") 47 | public Map artistIllusts(@PathVariable("id")int id,@RequestParam("page")int page,@RequestParam("pageSize")int pageSize); 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/controller/EventAcceptController.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.controller; 2 | 3 | import java.io.IOException; 4 | import java.util.Map; 5 | import java.util.stream.Collectors; 6 | 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | 10 | import org.accen.dmzj.core.AccenbotContext; 11 | import org.accen.dmzj.core.security.CqhttpSecurity; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.beans.factory.annotation.Qualifier; 14 | import org.springframework.stereotype.Controller; 15 | import org.springframework.web.bind.annotation.RequestMapping; 16 | 17 | import com.fasterxml.jackson.databind.ObjectMapper; 18 | 19 | @Controller 20 | @RequestMapping("/event") 21 | public class EventAcceptController { 22 | @Autowired 23 | private CqhttpSecurity security; 24 | // @Autowired 25 | // private EventParser parser; 26 | @Autowired 27 | @Qualifier("accenbotContext") 28 | AccenbotContext accentBotContext; 29 | 30 | @RequestMapping("/accept") 31 | public void eventAccept(HttpServletRequest request,HttpServletResponse response) { 32 | String qnum = request.getHeader("X-Self-ID"); 33 | String sig = request.getHeader("X-Signature"); 34 | String body; 35 | try { 36 | body = request.getReader().lines().collect(Collectors.joining()); 37 | if(security.checkCqhttp(qnum, sig, body)) { 38 | //校验通过,将报文交给event模块处理 39 | // parser.parse(qnum, body); 40 | ObjectMapper mapper = new ObjectMapper(); 41 | @SuppressWarnings("unchecked") 42 | Map event = mapper.readValue(body, Map.class); 43 | accentBotContext.accept(event); 44 | } 45 | } catch (IOException e) { 46 | e.printStackTrace(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/steam/SteamPoweredApiClient.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.steam; 2 | 3 | import org.accen.dmzj.core.api.vo.SteamApp; 4 | import org.accen.dmzj.core.api.vo.SteamNew; 5 | import org.springframework.cloud.openfeign.FeignClient; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RequestParam; 8 | 9 | @FeignClient(name="steam-api",url="https://api.steampowered.com/") 10 | public interface SteamPoweredApiClient { 11 | /** 12 | * 获取某个steam app的新闻 13 | * @param appid required steam appid 14 | * @param maxlength 15 | * @param enddatestamp unix epoch timestamp 16 | * @param count 17 | * @param feeds 18 | * @param tags 19 | * @return 20 | */ 21 | @GetMapping("/ISteamNews/GetNewsForApp/v2/") 22 | public SteamNew appNews(@RequestParam("appid")int appid,@RequestParam(name="maxlength",required = false)int maxlength, 23 | @RequestParam(name="enddate",required = false)int enddatestamp,@RequestParam(name="count",required = false)int count, 24 | @RequestParam(name="feeds",required = false)String feeds,@RequestParam(name="tags",required = false)String tags); 25 | /** 26 | * @see SteamPoweredApiClient#appNews(int, int, int, int, String, String) 27 | * @param appid 28 | * @param count 29 | * @return 30 | */ 31 | @GetMapping("/ISteamNews/GetNewsForApp/v2/") 32 | public SteamNew appNews(@RequestParam("appid")int appid,@RequestParam(name="count",required = false)int count); 33 | 34 | /** 35 | * 获取steam app列表 36 | * @return 37 | */ 38 | @GetMapping("/ISteamApps/GetAppList/v2/") 39 | public SteamApp appList(); 40 | 41 | /** 42 | * 获取steam app列表 43 | * @return 44 | */ 45 | @GetMapping("/ISteamApps/GetAppList/v2/") 46 | public String appListStr(); 47 | } -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/vo/CmdSvPk.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.vo; 2 | 3 | import java.util.Date; 4 | 5 | public class CmdSvPk { 6 | private long id; 7 | private String pkName; 8 | private String pkAlias;//简写 9 | private String pkJpName;//日语名称 10 | private String pkEnName;//英语名称 11 | private int pkSeq;//弹数,一般认为最高的就是最新的卡包 12 | private Date createTime; 13 | private String createUserId; 14 | private Date updateTime; 15 | public long getId() { 16 | return id; 17 | } 18 | public void setId(long id) { 19 | this.id = id; 20 | } 21 | public String getPkName() { 22 | return pkName; 23 | } 24 | public void setPkName(String pkName) { 25 | this.pkName = pkName; 26 | } 27 | public String getPkAlias() { 28 | return pkAlias; 29 | } 30 | public void setPkAlias(String pkAlias) { 31 | this.pkAlias = pkAlias; 32 | } 33 | public String getPkJpName() { 34 | return pkJpName; 35 | } 36 | public void setPkJpName(String pkJpName) { 37 | this.pkJpName = pkJpName; 38 | } 39 | public String getPkEnName() { 40 | return pkEnName; 41 | } 42 | public void setPkEnName(String pkEnName) { 43 | this.pkEnName = pkEnName; 44 | } 45 | public int getPkSeq() { 46 | return pkSeq; 47 | } 48 | public void setPkSeq(int pkSeq) { 49 | this.pkSeq = pkSeq; 50 | } 51 | public Date getCreateTime() { 52 | return createTime; 53 | } 54 | public void setCreateTime(Date createTime) { 55 | this.createTime = createTime; 56 | } 57 | public String getCreateUserId() { 58 | return createUserId; 59 | } 60 | public void setCreateUserId(String createUserId) { 61 | this.createUserId = createUserId; 62 | } 63 | public Date getUpdateTime() { 64 | return updateTime; 65 | } 66 | public void setUpdateTime(Date updateTime) { 67 | this.updateTime = updateTime; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/cmd/ChaosMode.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.cmd; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | import org.accen.dmzj.core.annotation.FuncSwitch; 7 | import org.accen.dmzj.core.handler.ModeCmd; 8 | import org.accen.dmzj.core.handler.group.Default; 9 | import org.accen.dmzj.core.task.GeneralTask; 10 | import org.accen.dmzj.util.QmessageUtil; 11 | import org.accen.dmzj.web.vo.Qmessage; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Component; 14 | 15 | @FuncSwitch(groupClass = Default.class, title = "混乱模式") 16 | @Component 17 | public class ChaosMode extends ModeCmd implements CmdAdapter { 18 | 19 | private static final Pattern switchPattern = Pattern.compile("^(开启|关闭)混乱模式$"); 20 | @Autowired 21 | private QmessageUtil qmessageUtil; 22 | @Override 23 | public GeneralTask cmdAdapt(Qmessage qmessage, String selfQnum) { 24 | if(qmessageUtil.isManagerOrGroupManagerOrGroupOwner(qmessage)) { 25 | Matcher matcher = switchPattern.matcher(qmessage.getMessage()); 26 | if(matcher.matches()) { 27 | GeneralTask task = new GeneralTask(); 28 | task.setSelfQnum(selfQnum); 29 | task.setType(qmessage.getMessageType()); 30 | task.setTargetId(qmessage.getGroupId()); 31 | String func = matcher.group(1); 32 | if("开启".equals(func)) { 33 | addGroup(qmessage.getGroupId()); 34 | task.setMessage("CHAOS mode set up!"); 35 | }else if("关闭".equals(func)){ 36 | removeGroup(qmessage.getGroupId()); 37 | task.setMessage("CHAOS mode shutdown!"); 38 | } 39 | return task; 40 | } 41 | } 42 | return null; 43 | } 44 | 45 | @Override 46 | public boolean modeOpen(String groupId) { 47 | // return super.hasGroup(groupId); 48 | return true; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/cmd/KamenRiderCmd.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.cmd; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | import org.accen.dmzj.core.task.GeneralTask; 7 | import org.accen.dmzj.core.task.TaskManager; 8 | import org.accen.dmzj.util.CQUtil; 9 | import org.accen.dmzj.web.dao.CfgResourceMapper; 10 | import org.accen.dmzj.web.vo.CfgResource; 11 | import org.accen.dmzj.web.vo.Qmessage; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.transaction.annotation.Transactional; 14 | @Transactional 15 | public class KamenRiderCmd implements CmdAdapter{ 16 | 17 | @Autowired 18 | private TaskManager taskManager; 19 | 20 | @Autowired 21 | private CfgResourceMapper cfgResourceMapper; 22 | 23 | private static final String KEY_PREFFIX = "record_kamenrider_"; 24 | private static final Pattern pattern = Pattern.compile("^(假面骑士|卡面来打|仮面ライダー)(.*)?(变身|henshin|Henshin|変身).*"); 25 | @Override 26 | public GeneralTask cmdAdapt(Qmessage qmessage, String selfQnum) { 27 | String message = qmessage.getMessage().trim(); 28 | Matcher matcher = pattern.matcher(message); 29 | if(matcher.matches()) { 30 | 31 | taskManager.addGeneralTaskQuick(selfQnum, qmessage.getMessageType(), qmessage.getGroupId(), "変身!"); 32 | 33 | GeneralTask task = new GeneralTask(); 34 | 35 | task.setSelfQnum(selfQnum); 36 | task.setType(qmessage.getMessageType()); 37 | task.setTargetId(qmessage.getGroupId()); 38 | 39 | String riderName = matcher.group(2).trim(); 40 | String key = KEY_PREFFIX+riderName; 41 | CfgResource cr = cfgResourceMapper.selectByKey(key); 42 | if(cr==null) { 43 | //如果找不到,则发送失败音效 44 | key = KEY_PREFFIX+"Error"; 45 | cr = cfgResourceMapper.selectByKey(key); 46 | } 47 | task.setMessage(CQUtil.recordUrl(cr.getCfgResource())); 48 | return task; 49 | } 50 | return null; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/vo/CmdSvCard.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.vo; 2 | 3 | import java.util.Date; 4 | 5 | public class CmdSvCard { 6 | private long id; 7 | private long pkId; 8 | private String cardName; 9 | private String cardNameJp; 10 | private String career;//职业 11 | private int cardRarity;//稀有度 1-铜 2-银 3-金 4-虹 5-异画 12 | private double probability;//抽取概率 13 | private Date createTime; 14 | private String createUserId; 15 | private int status;//1-有效 2-无效 16 | public long getId() { 17 | return id; 18 | } 19 | public void setId(long id) { 20 | this.id = id; 21 | } 22 | public long getPkId() { 23 | return pkId; 24 | } 25 | public void setPkId(long pkId) { 26 | this.pkId = pkId; 27 | } 28 | public String getCardName() { 29 | return cardName; 30 | } 31 | public void setCardName(String cardName) { 32 | this.cardName = cardName; 33 | } 34 | public String getCardNameJp() { 35 | return cardNameJp; 36 | } 37 | public void setCardNameJp(String cardNameJp) { 38 | this.cardNameJp = cardNameJp; 39 | } 40 | public int getCardRarity() { 41 | return cardRarity; 42 | } 43 | public void setCardRarity(int cardRarity) { 44 | this.cardRarity = cardRarity; 45 | } 46 | public double getProbability() { 47 | return probability; 48 | } 49 | public void setProbability(double probability) { 50 | this.probability = probability; 51 | } 52 | public Date getCreateTime() { 53 | return createTime; 54 | } 55 | public void setCreateTime(Date createTime) { 56 | this.createTime = createTime; 57 | } 58 | public String getCreateUserId() { 59 | return createUserId; 60 | } 61 | public void setCreateUserId(String createUserId) { 62 | this.createUserId = createUserId; 63 | } 64 | public int getStatus() { 65 | return status; 66 | } 67 | public void setStatus(int status) { 68 | this.status = status; 69 | } 70 | public String getCareer() { 71 | return career; 72 | } 73 | public void setCareer(String career) { 74 | this.career = career; 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/dao/CfgListenStatusMapper.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.dao; 2 | 3 | import java.util.List; 4 | 5 | import org.accen.dmzj.web.vo.CfgListenStatus; 6 | import org.apache.ibatis.annotations.Mapper; 7 | import org.apache.ibatis.annotations.Param; 8 | import org.apache.ibatis.annotations.Result; 9 | import org.apache.ibatis.annotations.ResultMap; 10 | import org.apache.ibatis.annotations.Results; 11 | import org.apache.ibatis.annotations.Select; 12 | 13 | @Mapper 14 | public interface CfgListenStatusMapper { 15 | @Results(id = "cfgListenStatusResultMap",value = { 16 | @Result(property = "id",column = "id"), 17 | @Result(property = "applyType",column = "apply_type"), 18 | @Result(property = "applyTarget",column = "apply_target"), 19 | @Result(property = "listenerCode",column = "listener_code"), 20 | @Result(property = "listenerStatus",column = "listener_status"), 21 | @Result(property = "listenerStatus2",column = "listener_status2"), 22 | @Result(property = "createUserId",column = "create_user_id"), 23 | @Result(property = "createTime",column = "create_time"), 24 | @Result(property = "updateUserId",column = "update_user_id"), 25 | @Result(property = "updateTime",column = "update_time") 26 | }) 27 | @Select("select * from cfg_listen_status where id = #{id}") 28 | public CfgListenStatus selectById(@Param("id") long id); 29 | 30 | @ResultMap("cfgListenStatusResultMap") 31 | @Select("select * from cfg_listen_status where apply_type = #{applyType} and apply_target=#{applyTarget}") 32 | public List findByApply(@Param("applyTarget") String applyTarget,@Param("applyType") String applyType); 33 | 34 | @ResultMap("cfgListenStatusResultMap") 35 | @Select("select * from cfg_listen_status where apply_type = #{applyType} and apply_target=#{applyTarget} and listener_code = #{listenerCode}") 36 | public CfgListenStatus selectByApplyAndCode(@Param("applyTarget") String applyTarget,@Param("applyType") String applyType,@Param("listenerCode") String listenerCode); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/pixivc/LocalAuthHolder.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.pixivc; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.net.MalformedURLException; 6 | import java.nio.charset.Charset; 7 | import java.nio.file.Files; 8 | 9 | import org.accen.dmzj.core.exception.PixivcAuthInitialExcpetion; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | import org.springframework.util.StringUtils; 13 | 14 | public class LocalAuthHolder implements AuthHolder { 15 | private final static Logger logger = LoggerFactory.getLogger(LocalAuthHolder.class); 16 | Auth auth; 17 | File authLocalFile; 18 | public LocalAuthHolder(PixivcAuthConfigurationProperties prop) { 19 | try { 20 | logger.info("pixivc:当前配置的本地认证文件地址为:{}",prop.authLocation()); 21 | authLocalFile = new File(prop.authLocation()); 22 | if(!authLocalFile.exists()){ 23 | authLocalFile.createNewFile(); 24 | } 25 | } catch (MalformedURLException e) { 26 | logger.error("{}.auth-location配置错误!"); 27 | throw new PixivcAuthInitialExcpetion(e); 28 | } catch (IOException e) { 29 | e.printStackTrace(); 30 | } 31 | } 32 | @Override 33 | public synchronized Auth getAuth() { 34 | if(auth==null) { 35 | //为空的话,则看本地文件中是否有存货 36 | try { 37 | String authStr = Files.readString(authLocalFile.toPath()); 38 | if(StringUtils.hasText(authStr)) { 39 | auth = new Auth(authStr); 40 | return auth; 41 | }else { 42 | return null; 43 | } 44 | 45 | 46 | } catch (MalformedURLException e) { 47 | logger.error("{}.auth-location配置错误!"); 48 | throw new PixivcAuthInitialExcpetion(e); 49 | } catch (IOException e) { 50 | e.printStackTrace(); 51 | } 52 | } 53 | 54 | return auth; 55 | } 56 | 57 | @Override 58 | public void updateAuth(Auth auth) { 59 | this.auth =auth; 60 | String authStr = auth.auth(); 61 | try { 62 | Files.writeString(authLocalFile.toPath(), authStr, Charset.forName("UTF-8")); 63 | } catch (IOException e) { 64 | e.printStackTrace(); 65 | } 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/security/CqhttpSecurity.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.security; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.security.InvalidKeyException; 5 | import java.security.NoSuchAlgorithmException; 6 | 7 | import javax.crypto.Mac; 8 | import javax.crypto.spec.SecretKeySpec; 9 | 10 | import org.accen.dmzj.web.dao.SysQnumMapper; 11 | import org.accen.dmzj.web.vo.SysQnum; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Service; 14 | import org.springframework.util.StringUtils; 15 | 16 | @Service 17 | public class CqhttpSecurity { 18 | @Autowired 19 | private SysQnumMapper sysQnumMapper; 20 | 21 | public boolean checkCqhttp(String qnum,String sig,String body) { 22 | if(!StringUtils.isEmpty(qnum)) { 23 | SysQnum sysQnum = sysQnumMapper.getByQnum(qnum); 24 | if(sysQnum!=null) { 25 | String secret = sysQnum.getSecret(); 26 | if(StringUtils.isEmpty(secret)) { 27 | return true; 28 | } 29 | try { 30 | SecretKeySpec signinKey = new SecretKeySpec(secret.getBytes("utf-8"), "HmacSHA1"); 31 | Mac mac = Mac.getInstance("HmacSHA1"); 32 | mac.init(signinKey); 33 | byte[] rawHmac = mac.doFinal(body.getBytes("utf-8")); 34 | return byte2hex(rawHmac).equals(sig); 35 | } catch (UnsupportedEncodingException e) { 36 | e.printStackTrace(); 37 | } catch (NoSuchAlgorithmException e) { 38 | e.printStackTrace(); 39 | } catch (InvalidKeyException e) { 40 | e.printStackTrace(); 41 | } 42 | 43 | } 44 | } 45 | return false; 46 | } 47 | public static String byte2hex(byte[] b) { 48 | StringBuilder hs = new StringBuilder(); 49 | String stmp; 50 | for (int n = 0; b != null && n < b.length; n++) { 51 | stmp = Integer.toHexString(b[n] & 0XFF); 52 | if (stmp.length() == 1) { 53 | hs.append('0'); 54 | } 55 | hs.append(stmp); 56 | } 57 | return hs.toString().toLowerCase(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/cmd/RepeatModeSwitch.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.cmd; 2 | 3 | import java.util.HashSet; 4 | import java.util.Map; 5 | import java.util.Set; 6 | import java.util.regex.Matcher; 7 | import java.util.regex.Pattern; 8 | 9 | import org.accen.dmzj.core.annotation.FuncSwitch; 10 | import org.accen.dmzj.core.task.GeneralTask; 11 | import org.accen.dmzj.web.vo.Qmessage; 12 | import org.springframework.beans.factory.annotation.Value; 13 | import org.springframework.stereotype.Component; 14 | 15 | @FuncSwitch(title = "复读模式") 16 | @Component 17 | public class RepeatModeSwitch implements CmdAdapter { 18 | 19 | @Value("${coolq.manager}") 20 | private String manager = "1339633536";//管理员qq 21 | 22 | //只保存开启复读模式的,也就是说默认不开启复读 23 | private Set allowGroup = new HashSet(4); 24 | /** 25 | * 判断一个群是否开启复读模式 26 | * @param groupId 27 | * @return 28 | */ 29 | public boolean modeOpen(String groupId) { 30 | // return allowGroup.contains(groupId); 31 | return true; 32 | } 33 | 34 | private static final Pattern pattern = Pattern.compile("^(开启|关闭)复读模式$"); 35 | @Override 36 | public GeneralTask cmdAdapt(Qmessage qmessage, String selfQnum) { 37 | String role = (String) ((Map)qmessage.getEvent().get("sender")).get("role"); 38 | if((!manager.equals(qmessage.getUserId()))&&(!"owner".equals(role))&&(!"admin".equals(role))) { 39 | return null; 40 | } 41 | String message = qmessage.getMessage().trim(); 42 | Matcher matcher = pattern.matcher(message); 43 | if(matcher.matches()) { 44 | GeneralTask task = new GeneralTask(); 45 | task.setSelfQnum(selfQnum); 46 | task.setType(qmessage.getMessageType()); 47 | task.setTargetId(qmessage.getGroupId()); 48 | String type = matcher.group(1); 49 | if("开启".equals(type)) { 50 | allowGroup.add(qmessage.getGroupId()); 51 | task.setMessage("复读模式开启!我也是复读机喵~"); 52 | }else if("关闭".equals(type)) { 53 | allowGroup.remove(qmessage.getGroupId()); 54 | task.setMessage("复读模式关闭!狗头保命喵~(doge"); 55 | } 56 | return task; 57 | } 58 | return null; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/vo/CfgQuickReply.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.vo; 2 | 3 | import java.util.Date; 4 | /** 5 | * 对消息快速回复的配置 6 | * @author Accen 7 | * 8 | */ 9 | public class CfgQuickReply { 10 | private long id; 11 | private int matchType;//1-Precise精确,2-Fuzzy模糊 12 | private String pattern; 13 | private int applyType;//应用类型,1-私信,2-群组,3-讨论组 14 | private String applyTarget;//应用目标号,例如群号 15 | private int needAt;//是否需要at,群组和讨论组时有效,1-需要,2-不需要 16 | private String reply; 17 | private String createUserId; 18 | private Date createTime; 19 | private int status;//0-无效,1-启用,2-停用 20 | public long getId() { 21 | return id; 22 | } 23 | public void setId(long id) { 24 | this.id = id; 25 | } 26 | public int getMatchType() { 27 | return matchType; 28 | } 29 | public void setMatchType(int matchType) { 30 | this.matchType = matchType; 31 | } 32 | public String getPattern() { 33 | return pattern; 34 | } 35 | public void setPattern(String pattern) { 36 | this.pattern = pattern; 37 | } 38 | public int getApplyType() { 39 | return applyType; 40 | } 41 | public void setApplyType(int applyType) { 42 | this.applyType = applyType; 43 | } 44 | public String getApplyTarget() { 45 | return applyTarget; 46 | } 47 | public void setApplyTarget(String applyTarget) { 48 | this.applyTarget = applyTarget; 49 | } 50 | public String getCreateUserId() { 51 | return createUserId; 52 | } 53 | public void setCreateUserId(String createUserId) { 54 | this.createUserId = createUserId; 55 | } 56 | public Date getCreateTime() { 57 | return createTime; 58 | } 59 | public void setCreateTime(Date createTime) { 60 | this.createTime = createTime; 61 | } 62 | public int getStatus() { 63 | return status; 64 | } 65 | public void setStatus(int status) { 66 | this.status = status; 67 | } 68 | public int getNeedAt() { 69 | return needAt; 70 | } 71 | public void setNeedAt(int needAt) { 72 | this.needAt = needAt; 73 | } 74 | public String getReply() { 75 | return reply; 76 | } 77 | public void setReply(String reply) { 78 | this.reply = reply; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/vo/Qmessage.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.vo; 2 | 3 | import java.util.Date; 4 | import java.util.Map; 5 | 6 | public class Qmessage { 7 | private long id; 8 | private String messageType; 9 | private String subType; 10 | private String messageId; 11 | private String groupId; 12 | private String userId; 13 | private String message; 14 | private String rawMessage; 15 | private Date sendTime; 16 | private String font; 17 | private Map event;//原始数据 18 | public long getId() { 19 | return id; 20 | } 21 | public void setId(long id) { 22 | this.id = id; 23 | } 24 | public String getMessageType() { 25 | return messageType; 26 | } 27 | public void setMessageType(String messageType) { 28 | this.messageType = messageType; 29 | } 30 | public String getSubType() { 31 | return subType; 32 | } 33 | public void setSubType(String subType) { 34 | this.subType = subType; 35 | } 36 | public String getMessageId() { 37 | return messageId; 38 | } 39 | public void setMessageId(String messageId) { 40 | this.messageId = messageId; 41 | } 42 | public String getUserId() { 43 | return userId; 44 | } 45 | public void setUserId(String userId) { 46 | this.userId = userId; 47 | } 48 | public String getMessage() { 49 | return message; 50 | } 51 | public void setMessage(String message) { 52 | this.message = message; 53 | } 54 | public String getRawMessage() { 55 | return rawMessage; 56 | } 57 | public void setRawMessage(String rawMessage) { 58 | this.rawMessage = rawMessage; 59 | } 60 | public Date getSendTime() { 61 | return sendTime; 62 | } 63 | public void setSendTime(Date sendTime) { 64 | this.sendTime = sendTime; 65 | } 66 | public String getFont() { 67 | return font; 68 | } 69 | public void setFont(String font) { 70 | this.font = font; 71 | } 72 | public String getGroupId() { 73 | return groupId; 74 | } 75 | public void setGroupId(String groupId) { 76 | this.groupId = groupId; 77 | } 78 | public Map getEvent() { 79 | return event; 80 | } 81 | public void setEvent(Map event) { 82 | this.event = event; 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/vo/SysRecordCount.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.vo; 2 | 3 | import java.util.Date; 4 | /** 5 | * 对业务产生的特殊情况进行记录 6 | * @author Accen 7 | * 8 | */ 9 | public class SysRecordCount { 10 | private long id; 11 | private String recordType;//记录类型,如REPEAT 12 | private String recordTarget;//暂时只用一个字段,但是通常难以用一个字段来确定 13 | private String recordValue; 14 | private String attr1; 15 | private String attr2; 16 | private Date createTime; 17 | private String createUserId; 18 | private Date updateTime; 19 | private String updateUserId; 20 | public long getId() { 21 | return id; 22 | } 23 | public void setId(long id) { 24 | this.id = id; 25 | } 26 | public String getRecordType() { 27 | return recordType; 28 | } 29 | public void setRecordType(String recordType) { 30 | this.recordType = recordType; 31 | } 32 | public String getRecordTarget() { 33 | return recordTarget; 34 | } 35 | public void setRecordTarget(String recordTarget) { 36 | this.recordTarget = recordTarget; 37 | } 38 | public String getRecordValue() { 39 | return recordValue; 40 | } 41 | public void setRecordValue(String recordValue) { 42 | this.recordValue = recordValue; 43 | } 44 | public String getAttr1() { 45 | return attr1; 46 | } 47 | public void setAttr1(String attr1) { 48 | this.attr1 = attr1; 49 | } 50 | public String getAttr2() { 51 | return attr2; 52 | } 53 | public void setAttr2(String attr2) { 54 | this.attr2 = attr2; 55 | } 56 | public Date getCreateTime() { 57 | return createTime; 58 | } 59 | public void setCreateTime(Date createTime) { 60 | this.createTime = createTime; 61 | } 62 | public String getCreateUserId() { 63 | return createUserId; 64 | } 65 | public void setCreateUserId(String createUserId) { 66 | this.createUserId = createUserId; 67 | } 68 | public Date getUpdateTime() { 69 | return updateTime; 70 | } 71 | public void setUpdateTime(Date updateTime) { 72 | this.updateTime = updateTime; 73 | } 74 | public String getUpdateUserId() { 75 | return updateUserId; 76 | } 77 | public void setUpdateUserId(String updateUserId) { 78 | this.updateUserId = updateUserId; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/dao/CfgConfigValueMapper.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.dao; 2 | 3 | import org.accen.dmzj.web.vo.CfgConfigValue; 4 | import org.apache.ibatis.annotations.Insert; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Options; 7 | import org.apache.ibatis.annotations.Param; 8 | import org.apache.ibatis.annotations.Result; 9 | import org.apache.ibatis.annotations.ResultMap; 10 | import org.apache.ibatis.annotations.Results; 11 | import org.apache.ibatis.annotations.Select; 12 | import org.apache.ibatis.annotations.Update; 13 | 14 | @Mapper 15 | public interface CfgConfigValueMapper { 16 | @Results(id = "cfgConfigMapper",value = { 17 | @Result(property = "id",column = "id"), 18 | @Result(property = "targetType",column = "target_type"), 19 | @Result(property = "target",column = "target"), 20 | @Result(property = "configKey",column = "config_key"), 21 | @Result(property = "configValue",column = "config_value"), 22 | @Result(property = "updateUserId",column = "update_user_id"), 23 | @Result(property = "updateTime",column = "update_time") 24 | }) 25 | @Select("select * from cfg_config_value where id = #{id} ") 26 | public CfgConfigValue selectById(@Param("id")long id); 27 | 28 | @ResultMap("cfgConfigMapper") 29 | @Select("select * from cfg_config_value where target_type = #{targetType} and target = #{target} and config_key = #{configKey} ") 30 | public CfgConfigValue selectByTargetAndKey(@Param("targetType")String targetType 31 | ,@Param("target")String target 32 | ,@Param("configKey")String configKey); 33 | 34 | @Insert("insert into cfg_config_value(target_type,target,config_key,config_value,update_user_id,update_time) " 35 | + " values(#{targetType},#{target},#{configKey},#{configValue},#{updateUserId},#{updateTime})") 36 | @Options(useGeneratedKeys = true,keyProperty = "id") 37 | public long insert(CfgConfigValue config); 38 | 39 | @Update("update cfg_config_value set config_value = #{configValue},update_user_id = #{updateUserId},update_time=#{updateTime} " 40 | + " where target_type = #{targetType} and target = #{target} and config_key = #{configKey} ") 41 | public int updateValue(CfgConfigValue config); 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/cmd/GroupNotice.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.cmd; 2 | 3 | import java.net.URLDecoder; 4 | import java.nio.charset.Charset; 5 | import java.util.List; 6 | 7 | import org.accen.dmzj.core.annotation.AutowiredParam; 8 | import org.accen.dmzj.core.annotation.CmdNotice; 9 | import org.accen.dmzj.core.annotation.GeneralMessage; 10 | import org.accen.dmzj.core.api.QqNickApiClient; 11 | import org.accen.dmzj.core.meta.NoticeType; 12 | import org.accen.dmzj.util.CQUtil; 13 | import org.accen.dmzj.util.RandomUtil; 14 | import org.accen.dmzj.web.dao.CfgConfigValueMapper; 15 | import org.accen.dmzj.web.vo.CfgConfigValue; 16 | import org.springframework.beans.factory.annotation.Autowired; 17 | import org.springframework.stereotype.Component; 18 | import org.springframework.util.StringUtils; 19 | 20 | @Component 21 | public class GroupNotice{ 22 | /** 23 | * 进群的配置key 24 | */ 25 | public static final String REPLY_GROUP_INCREASE = "reply_group_increase"; 26 | private static List REPLY_GROUP_DECREASE_VALUES = List.of("精神失常","精神错乱","去泰国做变性手术","去迪拜买房" 27 | ,"感冒","憋尿","天梯十年跪","十连无货","打不过我","掉线","看不懂群友说话","看本子过多","要画本子","守护bilibili"); 28 | 29 | @Autowired 30 | private CfgConfigValueMapper configMapper; 31 | @Autowired 32 | private QqNickApiClient qqNickApiClient; 33 | 34 | @CmdNotice(noticeType = NoticeType.GROUP_INCREASE) 35 | @GeneralMessage 36 | public String increase(@AutowiredParam long userId,@AutowiredParam long groupId) { 37 | //新人加群 38 | CfgConfigValue config = configMapper.selectByTargetAndKey("group", ""+groupId, REPLY_GROUP_INCREASE); 39 | if(config!=null&&StringUtils.hasLength(config.getConfigValue())) { 40 | return CQUtil.at(""+userId)+" "+config.getConfigValue(); 41 | } 42 | return null; 43 | } 44 | @CmdNotice(noticeType = NoticeType.GROUP_DECREASE) 45 | @GeneralMessage 46 | public String decrease(@AutowiredParam long userId) { 47 | String reply = REPLY_GROUP_DECREASE_VALUES.get(RandomUtil.randomInt(REPLY_GROUP_DECREASE_VALUES.size())); 48 | String nick = (String) qqNickApiClient.qqNick(""+userId).get("nick"); 49 | String nickDecoded = URLDecoder.decode(nick, Charset.forName("UTF-8")); 50 | return nickDecoded+"因为"+reply+"离开本群"; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/cmd/BaiduBaike.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.cmd; 2 | 3 | import java.util.List; 4 | 5 | import org.accen.dmzj.core.annotation.AutowiredRegular; 6 | import org.accen.dmzj.core.annotation.CmdMessage; 7 | import org.accen.dmzj.core.annotation.FuncSwitch; 8 | import org.accen.dmzj.core.annotation.GeneralMessage; 9 | import org.accen.dmzj.core.annotation.MessageRegular; 10 | import org.accen.dmzj.core.api.baidu.BaikeApicClientPk; 11 | import org.accen.dmzj.core.api.vo.BaikeResult; 12 | import org.accen.dmzj.core.handler.group.Pedia; 13 | import org.accen.dmzj.core.meta.MessageType; 14 | import org.accen.dmzj.util.CQUtil; 15 | import org.accen.dmzj.util.RandomUtil; 16 | import org.accen.dmzj.web.dao.CmdWikiMapper; 17 | import org.accen.dmzj.web.vo.CmdWiki; 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.stereotype.Component; 20 | 21 | @FuncSwitch(name = "cmd_baike", 22 | title = "百科", 23 | showMenu = true, 24 | format = "了解+[想了解的内容]", 25 | order = 1, 26 | groupClass = Pedia.class) 27 | @Component 28 | public class BaiduBaike { 29 | 30 | 31 | @Autowired 32 | private BaikeApicClientPk baikeApicClientPk; 33 | @Autowired 34 | private CmdWikiMapper cmdWikiMapper; 35 | 36 | @CmdMessage(messageType = MessageType.GROUP) 37 | @MessageRegular(expression = "^了解(.+)") 38 | @GeneralMessage 39 | public String cmdAdapt(@AutowiredRegular(1) String kw) { 40 | 41 | //1.先在wiki中查 42 | CmdWiki wiki = cmdWikiMapper.selectByName(kw); 43 | if(wiki==null) { 44 | //名字没匹配到,再去找关键字 45 | List wikis = cmdWikiMapper.findByKeyword(kw); 46 | if(wikis!=null&&!wikis.isEmpty()) { 47 | wiki = wikis.get(RandomUtil.randomInt(wikis.size())); 48 | } 49 | } 50 | if(wiki==null) { 51 | //2.找不到则去百度百科查 52 | BaikeResult br = baikeApicClientPk.baike(kw); 53 | if(br!=null) { 54 | return CQUtil.imageUrl(br.getImageUrl())+br.getTitle()+"\n"+br.getSummary()+"["+br.getUrl()+"]喵~"; 55 | }else { 56 | return "抱歉,我太弱了,找不到该词条喵~"; 57 | } 58 | }else { 59 | 60 | return (wiki.getImage()==null?"":CQUtil.imageUrl(RandomUtil.randomStringSplit(wiki.getImage()))) 61 | +wiki.getWikiName()+"\n"+wiki.getContent(); 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/util/QmessageUtil.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.util; 2 | 3 | import java.math.BigDecimal; 4 | import java.util.ArrayList; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.Set; 9 | import java.util.stream.Collectors; 10 | 11 | import org.accen.dmzj.core.api.cq.CqhttpClient; 12 | import org.accen.dmzj.web.vo.Qmessage; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.beans.factory.annotation.Value; 15 | import org.springframework.stereotype.Component; 16 | @Component 17 | public class QmessageUtil { 18 | @Value("${coolq.manager}") 19 | public String manager = "1339633536";//管理员qq 20 | @Autowired 21 | private CqhttpClient cqhttpClient; 22 | /** 23 | * 发送者是qq管理员 24 | * @param qmessage 25 | * @return 26 | */ 27 | public boolean isManager(Qmessage qmessage) { 28 | return manager.equals(qmessage.getUserId()); 29 | } 30 | /** 31 | * 发送者是群管理员 32 | * @param qmessage 33 | * @return 34 | */ 35 | public boolean isGroupManager(Qmessage qmessage) { 36 | String role = (String) ((Map)qmessage.getEvent().get("sender")).get("role"); 37 | return "admin".equals(role); 38 | } 39 | /** 40 | * 发送者是群主 41 | * @param qmessage 42 | * @return 43 | */ 44 | public boolean isGroupOwner(Qmessage qmessage) { 45 | String role = (String) ((Map)qmessage.getEvent().get("sender")).get("role"); 46 | return "owner".equals(role); 47 | } 48 | public boolean isManagerOrGroupManagerOrGroupOwner(Qmessage qmessage) { 49 | return isManager(qmessage)||isGroupManager(qmessage)||isGroupOwner(qmessage); 50 | } 51 | private Set groupList ; 52 | /** 53 | * 获取当前bot的群列表 54 | * @return 55 | */ 56 | public Set groupList(){ 57 | if(groupList == null || groupList.isEmpty()) { 58 | List> groupListInfo = (List>) cqhttpClient.groupList().get("data"); 59 | groupList = groupListInfo.parallelStream() 60 | .map(map->new BigDecimal((Integer)map.get("group_id")).stripTrailingZeros().toPlainString()) 61 | .collect(Collectors.toSet()); 62 | } 63 | return groupList==null?new HashSet():new HashSet<>(groupList); 64 | 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/util/GoogleUtil.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.util; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class GoogleUtil { 7 | public static String calculate_token(String text) { 8 | 9 | long b = 406644L; 10 | Long b1 = 3293161072L; 11 | String SALT_1 = "+-a^+6"; 12 | String SALT_2 = "+-3^+b+-f"; 13 | String d = text; 14 | List e = new ArrayList(); 15 | for (int g = 0; g < d.length(); g++) { 16 | int m = charCodeAt(d, g); 17 | if (m < 128) { 18 | e.add(m); // 0{l[6-0]} 19 | } else if (m < 2048) { 20 | e.add(m >> 6 | 192); // 110{l[10-6]} 21 | e.add(m & 0x3F | 0x80); // 10{l[5-0]} 22 | } else if (0xD800 == (m & 0xFC00) && g + 1 < d.length() && 0xDC00 == (charCodeAt(d, g + 1) & 0xFC00)) { 23 | // that's pretty rare... (avoid ovf?) 24 | m = (byte) ((1 << 16) + ((m & 0x03FF) << 10) + (charCodeAt(d, ++g) & 0x03FF)); 25 | e.add(m >> 18 | 0xF0); // 111100{l[9-8*]} 26 | e.add(m >> 12 & 0x3F | 0x80); // 10{l[7*-2]} 27 | e.add(m & 0x3F | 0x80); // 10{(l+1)[5-0]} 28 | } else { 29 | e.add(m >> 12 | 0xE0); // 1110{l[15-12]} 30 | e.add(m >> 6 & 0x3F | 0x80); // 10{l[11-6]} 31 | e.add(m & 0x3F | 0x80); // 10{l[5-0]} 32 | } 33 | } 34 | Long a1 = b; 35 | for (int f = 0; f < e.size(); f++) { 36 | a1 += e.get(f); 37 | a1 = RL(a1, SALT_1); 38 | 39 | } 40 | 41 | a1 = RL(a1, SALT_2); 42 | 43 | a1 ^= b1; 44 | if (0 > a1) { 45 | a1 = (a1 & 2147483647L) + 2147483648L; 46 | } 47 | 48 | a1 = a1 % 1000000; 49 | return a1.toString() + "." + (a1 ^ b); 50 | } 51 | 52 | private static long RL(long a, String seed) { 53 | for (int i = 0; i < seed.length() - 2; i += 3) { 54 | char c = seed.toCharArray()[i + 2]; 55 | long d = (c >= 'a') ? ((int) c - 87) : Integer.parseInt(c + ""); 56 | d = (seed.toCharArray()[i + 1] == '+') ? (_rshift(a, d)) : (a << d); 57 | a = (seed.toCharArray()[i] == '+') ? (a + d & 4294967295L) : (a ^ d); 58 | } 59 | return a; 60 | } 61 | 62 | private static long _rshift(long val, long n) { 63 | long l = (val >= 0) ? (val >> n) : (val + 0x100000000L) >> n; 64 | return l; 65 | } 66 | 67 | private static int charCodeAt(String string, int index) { 68 | return Character.codePointAt(string, index); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/vo/CfgListenStatus.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.vo; 2 | 3 | import java.util.Date; 4 | /** 5 | * qq对象的功能状态 6 | * @author Accen 7 | * 8 | */ 9 | public class CfgListenStatus { 10 | private long id; 11 | private int applyType;//1-私信,2-群组,3-讨论组 12 | private int applyTarget; 13 | private String listenerCode; 14 | private String listenerStatus;//0-无效,1-开启,2-关闭 15 | private String listenerStatus2;//与功能相关的数值,在无法仅通过listenerStatus表达时,使用这个字段增强 16 | private String createUserId; 17 | private Date createTime; 18 | private String updateUserId; 19 | private Date updateTime; 20 | public long getId() { 21 | return id; 22 | } 23 | public void setId(long id) { 24 | this.id = id; 25 | } 26 | public int getApplyType() { 27 | return applyType; 28 | } 29 | public void setApplyType(int applyType) { 30 | this.applyType = applyType; 31 | } 32 | public int getApplyTarget() { 33 | return applyTarget; 34 | } 35 | public void setApplyTarget(int applyTarget) { 36 | this.applyTarget = applyTarget; 37 | } 38 | public String getListenerCode() { 39 | return listenerCode; 40 | } 41 | public void setListenerCode(String listenerCode) { 42 | this.listenerCode = listenerCode; 43 | } 44 | public String getCreateUserId() { 45 | return createUserId; 46 | } 47 | public void setCreateUserId(String createUserId) { 48 | this.createUserId = createUserId; 49 | } 50 | public Date getCreateTime() { 51 | return createTime; 52 | } 53 | public void setCreateTime(Date createTime) { 54 | this.createTime = createTime; 55 | } 56 | public String getUpdateUserId() { 57 | return updateUserId; 58 | } 59 | public void setUpdateUserId(String updateUserId) { 60 | this.updateUserId = updateUserId; 61 | } 62 | public Date getUpdateTime() { 63 | return updateTime; 64 | } 65 | public void setUpdateTime(Date updateTime) { 66 | this.updateTime = updateTime; 67 | } 68 | public String getListenerStatus() { 69 | return listenerStatus; 70 | } 71 | public void setListenerStatus(String listenerStatus) { 72 | this.listenerStatus = listenerStatus; 73 | } 74 | public String getListenerStatus2() { 75 | return listenerStatus2; 76 | } 77 | public void setListenerStatus2(String listenerStatus2) { 78 | this.listenerStatus2 = listenerStatus2; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/callbacker/CallbackManager.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.callbacker; 2 | 3 | import java.util.HashSet; 4 | import java.util.Iterator; 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.Map.Entry; 9 | import java.util.Set; 10 | import java.util.concurrent.ConcurrentHashMap; 11 | 12 | import org.accen.dmzj.web.vo.Qmessage; 13 | import org.springframework.beans.factory.annotation.Value; 14 | import org.springframework.stereotype.Component; 15 | 16 | @Component 17 | public class CallbackManager { 18 | 19 | @Value("${coolq.bot}") 20 | private String botId; 21 | private Map> listeners = new ConcurrentHashMap>(); 22 | /** 23 | * 常驻的listener,通常由listener自己保存上下文,且不通过callbackManager管理其生命周期。 24 | * 例如找图,只会找一次,是可以由callbackManager保存生命周期的,但诸如收藏是由自己管理的(使用cacheMap管理生命周期),那么它就应该是常驻listener 25 | */ 26 | private Set residentListeners = new HashSet(4); 27 | 28 | public void accept(Qmessage qmessage) { 29 | //1.常驻 30 | Iterator residentListenerIte = residentListeners.iterator(); 31 | while(residentListenerIte.hasNext()) { 32 | residentListenerIte.next().listen(null, qmessage, botId); 33 | } 34 | //2.一般 35 | Iterator>> listenerEntries = listeners.entrySet().iterator(); 36 | while(listenerEntries.hasNext()) { 37 | Entry> listenerEntry = listenerEntries.next(); 38 | if(listenerEntry.getValue()==null||listenerEntry.getValue().isEmpty()) { 39 | listenerEntries.remove(); 40 | }else { 41 | Iterator oqmIte = listenerEntry.getValue().iterator(); 42 | while(oqmIte.hasNext()) { 43 | if(listenerEntry.getKey().listen(oqmIte.next(), qmessage, botId)) { 44 | oqmIte.remove(); 45 | } 46 | } 47 | } 48 | 49 | } 50 | } 51 | public void addCallbackListener(CallbackListener listener,Qmessage orginQmessage) { 52 | if(!listeners.containsKey(listener)) { 53 | listeners.put(listener, new LinkedList()); 54 | } 55 | listeners.get(listener).add(orginQmessage); 56 | } 57 | public void addResidentListener(CallbackListener listener) { 58 | residentListeners.add(listener); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/autoconfigure/NonBeanEnviromentIniter.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.autoconfigure; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Modifier; 5 | import java.util.Arrays; 6 | import java.util.regex.Matcher; 7 | import java.util.regex.Pattern; 8 | 9 | import org.springframework.beans.factory.annotation.Value; 10 | import org.springframework.boot.SpringApplication; 11 | import org.springframework.boot.env.EnvironmentPostProcessor; 12 | import org.springframework.core.env.ConfigurableEnvironment; 13 | /* 14 | * 用于初始化非spring管理的实例,允许使用spring管理的参数 15 | * @author Accen 16 | * 17 | */ 18 | public interface NonBeanEnviromentIniter extends EnvironmentPostProcessor { 19 | final Pattern valuePattern = Pattern.compile("^\\$\\{(.+)\\}$"); 20 | @Override 21 | default void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { 22 | Field[] fields = this.getClass().getDeclaredFields(); 23 | // ExpressionParser expressionParser = new SpelExpressionParser(); 24 | Arrays.stream(fields).forEach(field->{ 25 | if(field.isAnnotationPresent(Value.class)) { 26 | String value = field.getAnnotation(Value.class).value(); 27 | if(value!=null&&!value.isBlank()) { 28 | Matcher mt = valuePattern.matcher(value); 29 | if(mt.matches()) { 30 | try { 31 | field.setAccessible(true); 32 | if(Modifier.isStatic(field.getModifiers())) { 33 | field.set(null, environment.getProperty(mt.group(1))); 34 | }else { 35 | field.set(this,environment.getProperty(mt.group(1))); 36 | } 37 | } catch (IllegalArgumentException e) { 38 | e.printStackTrace(); 39 | } catch (IllegalAccessException e) { 40 | e.printStackTrace(); 41 | } 42 | } 43 | /*System.out.println(environment.getProperty("pixivc.account")); 44 | Expression expression = expressionParser.parseExpression(value); 45 | try { 46 | field.set(this, expression.getValue(environment)); 47 | } catch (EvaluationException e) { 48 | e.printStackTrace(); 49 | } catch (IllegalArgumentException e) { 50 | e.printStackTrace(); 51 | } catch (IllegalAccessException e) { 52 | e.printStackTrace(); 53 | // }*/ 54 | 55 | } 56 | } 57 | }); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/vo/CfgResource.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.vo; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * 资源,通过cfgResource定位,支持网络,文件,只要包含协议就行 7 | * @author Accen 8 | * 9 | */ 10 | public class CfgResource { 11 | private long id; 12 | private String cfgKey; 13 | private String cfgResource; 14 | private String resourceType; 15 | private String title; 16 | private String content; 17 | private String image; 18 | private String originResource; 19 | private String createUserId; 20 | private String createUserName; 21 | private Date createTime; 22 | 23 | 24 | public String getCreateUserId() { 25 | return createUserId; 26 | } 27 | public void setCreateUserId(String createUserId) { 28 | this.createUserId = createUserId; 29 | } 30 | public String getCreateUserName() { 31 | return createUserName; 32 | } 33 | public void setCreateUserName(String createUserName) { 34 | this.createUserName = createUserName; 35 | } 36 | 37 | public Date getCreateTime() { 38 | return createTime; 39 | } 40 | public void setCreateTime(Date createTime) { 41 | this.createTime = createTime; 42 | } 43 | public String getTitle() { 44 | return title; 45 | } 46 | public void setTitle(String title) { 47 | this.title = title; 48 | } 49 | public String getContent() { 50 | return content; 51 | } 52 | public void setContent(String content) { 53 | this.content = content; 54 | } 55 | public String getImage() { 56 | return image; 57 | } 58 | public void setImage(String image) { 59 | this.image = image; 60 | } 61 | public long getId() { 62 | return id; 63 | } 64 | public void setId(long id) { 65 | this.id = id; 66 | } 67 | public String getCfgKey() { 68 | return cfgKey; 69 | } 70 | public void setCfgKey(String cfgKey) { 71 | this.cfgKey = cfgKey; 72 | } 73 | public String getCfgResource() { 74 | return cfgResource; 75 | } 76 | public void setCfgResource(String cfgResource) { 77 | this.cfgResource = cfgResource; 78 | } 79 | public String getResourceType() { 80 | return resourceType; 81 | } 82 | public void setResourceType(String resourceType) { 83 | this.resourceType = resourceType; 84 | } 85 | public String getOriginResource() { 86 | return originResource; 87 | } 88 | public void setOriginResource(String originResource) { 89 | this.originResource = originResource; 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/task/TaskManager.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.task; 2 | 3 | import java.util.Arrays; 4 | import java.util.Date; 5 | import java.util.List; 6 | import java.util.concurrent.BlockingQueue; 7 | import java.util.concurrent.ExecutorService; 8 | import java.util.concurrent.Executors; 9 | import java.util.concurrent.LinkedBlockingQueue; 10 | 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.stereotype.Component; 14 | 15 | @Component 16 | public class TaskManager { 17 | private final static Logger logger = LoggerFactory.getLogger(TaskManager.class); 18 | private BlockingQueue generalTaskQueue; 19 | // private Timer timer; 20 | 21 | //线程池 22 | private int poolSize = 10; 23 | private ExecutorService generalTaskProcessorPool = Executors.newFixedThreadPool(poolSize); 24 | 25 | public TaskManager() { 26 | super(); 27 | this.generalTaskQueue = new LinkedBlockingQueue(); 28 | // this.timer = new Timer(); 29 | start(); 30 | } 31 | /** 32 | * 开始任务调度 33 | */ 34 | public void start() { 35 | for(int index = 0;index generalTasks) { 54 | generalTasks.forEach(this::addGeneralTask); 55 | } 56 | public void addGeneralTasks(GeneralTask[] generalTasks) { 57 | Arrays.stream(generalTasks).forEach(this::addGeneralTask); 58 | } 59 | /** 60 | * 新增一个指定时间任务 61 | * @param task 62 | * @param date 63 | */ 64 | public void addTimerTask(GeneralTask task,Date date) { 65 | 66 | } 67 | /**\ 68 | * 快速添加任务 69 | * @param selfQnum 70 | * @param messageType 71 | * @param targetId 72 | * @param message 73 | */ 74 | public void addGeneralTaskQuick(String selfQnum,String messageType,String targetId,String message) { 75 | GeneralTask task = new GeneralTask(); 76 | task.setSelfQnum(selfQnum); 77 | task.setMessage(message); 78 | task.setTargetId(targetId); 79 | task.setType(messageType); 80 | addGeneralTask(task); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/test/java/dmzjbot/Test2.java: -------------------------------------------------------------------------------- 1 | package dmzjbot; 2 | 3 | import java.io.FileOutputStream; 4 | import java.io.IOException; 5 | import java.math.BigDecimal; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | import org.apache.http.Header; 10 | import org.apache.http.HttpResponse; 11 | import org.apache.http.client.ClientProtocolException; 12 | import org.apache.http.client.HttpClient; 13 | import org.apache.http.client.methods.HttpGet; 14 | import org.apache.http.impl.client.HttpClientBuilder; 15 | import org.apache.http.util.EntityUtils; 16 | import org.apache.tomcat.util.http.fileupload.IOUtils; 17 | 18 | import com.google.gson.Gson; 19 | 20 | public class Test2 { 21 | 22 | public static void main(String[] args) { 23 | HttpClient client = HttpClientBuilder.create().build(); 24 | //1.view,获取cid 25 | HttpGet get = new HttpGet("https://api.bilibili.com/x/web-interface/view?aid=64689940"); 26 | try { 27 | HttpResponse resp = client.execute(get); 28 | String ctt = EntityUtils.toString(resp.getEntity(),"UTF-8"); 29 | 30 | Gson gson = new Gson(); 31 | Map data = gson.fromJson(ctt, Map.class); 32 | Double cid = (Double)((List>)((Map)data.get("data")).get("pages")).get(0).get("cid"); 33 | String cidS = new BigDecimal(cid).stripTrailingZeros().toPlainString(); 34 | 35 | //2.playurl 36 | get = new HttpGet("https://api.bilibili.com/x/player/playurl?cid="+cidS+"&avid=64689940&qn=16"); 37 | get.setHeader("Cookie", "SESSDATA=d96c2f63%2C1574302559%2Cdc63a3a1"); 38 | get.setHeader("Host", "api.bilibili.com"); 39 | 40 | resp = client.execute(get); 41 | ctt = EntityUtils.toString(resp.getEntity(),"UTF-8"); 42 | 43 | data = gson.fromJson(ctt, Map.class); 44 | String url= ((List>)((Map)data.get("data")).get("durl")).get(0).get("url").toString(); 45 | 46 | 47 | //3.下载 48 | get = new HttpGet(url); 49 | get.setHeader("Referer", "https://api.bilibili.com/x/web-interface/view?aid=64689940"); 50 | get.setHeader("Range","bytes=0-"); 51 | get.setHeader("Origin", "https://www.bilibili.com"); 52 | 53 | resp = client.execute(get); 54 | 55 | IOUtils.copy(resp.getEntity().getContent(),new FileOutputStream("D:\\Software\\a.flv")); 56 | } catch (ClientProtocolException e) { 57 | e.printStackTrace(); 58 | } catch (IOException e) { 59 | e.printStackTrace(); 60 | } 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/task/TaskCoolqProcessor.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.task; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import org.accen.dmzj.core.api.cq.CqhttpClient; 7 | import org.accen.dmzj.util.ApplicationContextUtil; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import com.fasterxml.jackson.core.JsonProcessingException; 12 | import com.fasterxml.jackson.databind.ObjectMapper; 13 | 14 | public class TaskCoolqProcessor { 15 | private final static Logger logger = LoggerFactory.getLogger(TaskCoolqProcessor.class); 16 | public String processs(GeneralTask task) { 17 | if("group".equals(task.getType())) { 18 | Map resultMap = sendGroupMsg(task.getTargetId(),task.getMessage(),false); 19 | try { 20 | return new ObjectMapper().writeValueAsString(resultMap); 21 | } catch (JsonProcessingException e) { 22 | e.printStackTrace(); 23 | } 24 | }else if("private".equals(task.getType())) { 25 | Map resultMap = sendPrivateMsg(task.getTargetId(),task.getMessage(),false); 26 | try { 27 | return new ObjectMapper().writeValueAsString(resultMap); 28 | } catch (JsonProcessingException e) { 29 | e.printStackTrace(); 30 | } 31 | } 32 | return ""; 33 | } 34 | public Map sendGroupMsg(String groupId,String message,boolean autoEscape) { 35 | Map request = new HashMap(); 36 | request.put("group_id", groupId); 37 | request.put("message", message); 38 | request.put("auto_escape", autoEscape); 39 | CqhttpClient client = ApplicationContextUtil.getBean(CqhttpClient.class); 40 | try { 41 | Map rs = client.sendGroupMsg(request); 42 | return rs; 43 | }catch (Exception e) { 44 | // TODO 暂时不处理 45 | logger.error(e.getMessage()); 46 | } 47 | 48 | return null; 49 | } 50 | public Map sendPrivateMsg(String userId,String message,boolean autoEscape){ 51 | Map request = new HashMap(); 52 | request.put("user_id", userId); 53 | request.put("message", message); 54 | request.put("auto_escape", autoEscape); 55 | CqhttpClient client = ApplicationContextUtil.getBean(CqhttpClient.class); 56 | try { 57 | Map rs = client.sendPrivateMsg(request); 58 | return rs; 59 | }catch (Exception e) { 60 | // TODO 暂时不处理 61 | logger.error(e.getMessage()); 62 | } 63 | return null; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/cmd/Draw.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.cmd; 2 | 3 | import java.awt.image.BufferedImage; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.io.FileNotFoundException; 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.util.Base64; 11 | import java.util.regex.Matcher; 12 | import java.util.regex.Pattern; 13 | 14 | import javax.imageio.ImageIO; 15 | 16 | import org.accen.dmzj.core.annotation.FuncSwitch; 17 | import org.accen.dmzj.core.autoconfigure.Workdirer; 18 | import org.accen.dmzj.core.handler.group.Default; 19 | import org.accen.dmzj.core.task.GeneralTask; 20 | import org.accen.dmzj.util.CQUtil; 21 | import org.accen.dmzj.util.RandomUtil; 22 | import org.accen.dmzj.web.vo.Qmessage; 23 | import org.springframework.stereotype.Component; 24 | 25 | import com.madgag.gif.fmsware.GifDecoder; 26 | @FuncSwitch(groupClass = Default.class, title = "抽签") 27 | @Component 28 | public class Draw implements CmdAdapter,Workdirer{ 29 | @Override 30 | public String workdir() { 31 | return "drawSource/"; 32 | } 33 | 34 | private final static Pattern DRAW_PATTERN = Pattern.compile("^(.+)?抽签$"); 35 | @Override 36 | public GeneralTask cmdAdapt(Qmessage qmessage, String selfQnum) { 37 | String msg = qmessage.getMessage(); 38 | Matcher drawMt = DRAW_PATTERN.matcher(msg); 39 | if(drawMt.matches()) { 40 | String sign = drawMt.group(1); 41 | File gif = new File(workdir()+sign+".gif"); 42 | if(gif.exists()) { 43 | 44 | GifDecoder gifd = new GifDecoder(); 45 | try(InputStream is = new FileInputStream(gif);){ 46 | gifd.read(is); 47 | int count = gifd.getFrameCount(); 48 | int rdm = RandomUtil.randomInt(count); 49 | ByteArrayOutputStream os = new ByteArrayOutputStream(); 50 | BufferedImage rmdBfdImg = gifd.getFrame(rdm); 51 | ImageIO.write(rmdBfdImg, "png", os); 52 | os.flush(); 53 | String rmdBs64 = Base64.getEncoder().encodeToString(os.toByteArray()); 54 | GeneralTask task = new GeneralTask(qmessage.getMessageType(), qmessage.getGroupId() 55 | , CQUtil.at(qmessage.getUserId())+" "+CQUtil.imageBs64(rmdBs64), selfQnum); 56 | return task; 57 | } catch (FileNotFoundException e) { 58 | e.printStackTrace(); 59 | } catch (IOException e) { 60 | e.printStackTrace(); 61 | } 62 | 63 | } 64 | } 65 | return null; 66 | } 67 | 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/pixivc/PixivcAuthConfigurationProperties.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.pixivc; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.boot.context.properties.ConstructorBinding; 5 | import org.springframework.boot.context.properties.bind.DefaultValue; 6 | import org.springframework.boot.context.properties.bind.Name; 7 | 8 | @ConfigurationProperties(PixivcAuthConfigurationProperties.CONFIG_PIXIV_PREFIX) 9 | @ConstructorBinding 10 | public class PixivcAuthConfigurationProperties{ 11 | /*@Bean 12 | public PixivcAuthConfigurationProperties pixivcAuthConfigurationProperties() { 13 | return this; 14 | }*/ 15 | 16 | public static final String CONFIG_PIXIV_PREFIX = "pixivc"; 17 | /* 18 | * 登录失败重试次数 19 | */ 20 | private int loginRetry; 21 | public int loginRetry() {return loginRetry;} 22 | /* 23 | * 本地存储的authorization地址 24 | */ 25 | private String authLocation; 26 | public String authLocation() {return authLocation;} 27 | /* 28 | * 登录用户名 29 | */ 30 | private String username; 31 | public String username() {return username;} 32 | /* 33 | * 密码 34 | */ 35 | private String password; 36 | public String password() {return password;} 37 | /* 38 | * verificationCode获取链接 39 | */ 40 | private String vcUrl; 41 | public String vcUrl() {return vcUrl;} 42 | private Class authHolderClass; 43 | public Class authHolderClass(){return authHolderClass;} 44 | private Class authFresherClass = org.accen.dmzj.core.api.pixivc.HttpAuthFresher.class; 45 | public Class authFresherClass(){return authFresherClass;} 46 | public PixivcAuthConfigurationProperties(int loginRetry 47 | ,@DefaultValue("pixivc.auth")String authLocation 48 | ,@Name("account")String username 49 | ,String password 50 | ,@DefaultValue("https://pix.ipv4.host/verificationCode") String vcUrl 51 | ,@DefaultValue("org.accen.dmzj.core.api.pixivc.LocalAuthHolder") Class authHolderClass 52 | ,@DefaultValue("org.accen.dmzj.core.api.pixivc.HttpAuthFresher") Class authFresherClass) { 53 | this.loginRetry = loginRetry; 54 | this.authLocation = authLocation; 55 | this.username = username; 56 | this.password = password; 57 | this.vcUrl = vcUrl; 58 | this.authHolderClass = authHolderClass; 59 | this.authFresherClass = authFresherClass; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/listen/RandomRepeatListener.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.listen; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | import org.accen.dmzj.core.handler.cmd.RandomRepeatPropModify; 7 | import org.accen.dmzj.core.task.GeneralTask; 8 | import org.accen.dmzj.core.task.TaskManager; 9 | import org.accen.dmzj.util.CQUtil; 10 | import org.accen.dmzj.util.RandomUtil; 11 | import org.accen.dmzj.web.vo.Qmessage; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Component; 14 | import org.springframework.util.StringUtils; 15 | @Component 16 | public class RandomRepeatListener implements ListenAdpter { 17 | @Autowired 18 | private RandomRepeatPropModify randomRepeatPropModifyCmd; 19 | @Autowired 20 | private TaskManager taskManager; 21 | @Override 22 | public List listen(Qmessage qmessage, String selfQnum) { 23 | int prop = randomRepeatPropModifyCmd.getRandomRepeatProp(qmessage.getGroupId()); 24 | if(RandomUtil.randomInt(100))qmessage.getEvent().get("sender")).get("nickname"); 48 | String createCard = (String) ((Map)qmessage.getEvent().get("sender")).get("card");//群名片 49 | String newMsg = qmessage.getMessage(); 50 | 51 | newMsg = newMsg.replaceAll("(我|咱|俺)", "##"); 52 | newMsg = newMsg.replaceAll("(Bot|狐狸|bot|你)", StringUtils.isEmpty(createCard)?createNickName:createCard); 53 | newMsg = newMsg.replaceAll("##", "你"); 54 | //随机加个前缀 55 | if(RandomUtil.randomPass(0.5)) { 56 | newMsg = rdmOralHabits[RandomUtil.randomInt(rdmOralHabits.length)]+newMsg; 57 | } 58 | return newMsg; 59 | }else { 60 | return null; 61 | } 62 | 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/listen/SetuCatchListener.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.listen; 2 | 3 | import java.util.List; 4 | import java.util.Set; 5 | import java.util.regex.Matcher; 6 | import java.util.regex.Pattern; 7 | 8 | import org.accen.dmzj.core.task.GeneralTask; 9 | import org.accen.dmzj.core.task.TaskManager; 10 | import org.accen.dmzj.util.CQUtil; 11 | import org.accen.dmzj.util.setu.CqSetuGreper; 12 | import org.accen.dmzj.util.setu.PixivSetuGreper; 13 | import org.accen.dmzj.util.setu.SetuGreper; 14 | import org.accen.dmzj.web.vo.Qmessage; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.stereotype.Component; 17 | /** 18 | * 本地消息抓取涩图的监听器,现在判断是否是涩图的逻辑比较简单,有待扩展 19 | * @author Accen 20 | * 21 | */ 22 | @Component 23 | public class SetuCatchListener implements ListenAdpter{ 24 | private Set allowedSenders = Set.of("");//yome喵 25 | private long minImageSize = 100*1024;//单位为Byte 26 | private long maxImageSize = 10*1024*1024; 27 | @Autowired 28 | private TaskManager taskManager; 29 | @Override 30 | public List listen(Qmessage qmessage, String selfQnum) { 31 | SetuGreper greper = isSetu(qmessage); 32 | if(greper!=null) { 33 | int successCont = greper.grep(); 34 | //通知 35 | if(successCont>0) { 36 | taskManager.addGeneralTaskQuick(selfQnum, qmessage.getMessageType(), qmessage.getGroupId(), "涩图充能+"+successCont+"!"); 37 | } 38 | 39 | } 40 | return null; 41 | } 42 | /** 43 | * 判断是否是涩图的方法,可实现此方法来扩展 44 | * @param qmessage 45 | * @return 46 | */ 47 | protected SetuGreper isSetu(Qmessage qmessage) { 48 | /*if(!"857083789".equals(qmessage.getGroupId())){ 49 | return false; 50 | } 51 | if(!CQUtil.hasImg(qmessage.getMessage())) { 52 | return null; 53 | }*/ 54 | if(!allowedSenders.contains(qmessage.getUserId())&&!Pattern.matches("^(涩|色|瑟|se)图充能.*", qmessage.getMessage())) { 55 | return null; 56 | } 57 | Matcher mt = pixivPattern.matcher(qmessage.getMessage()); 58 | if(mt.matches()) { 59 | String pidFmting = mt.group(2); 60 | return new PixivSetuGreper(pidFmting.split(",|,|、")); 61 | } 62 | List cqs = CQUtil.grepImageCq(qmessage.getMessage()); 63 | if(!cqs.isEmpty()) { 64 | return new CqSetuGreper(minImageSize, maxImageSize, qmessage, cqs); 65 | } 66 | return null; 67 | } 68 | 69 | private static final Pattern pixivPattern = Pattern.compile("^(涩|色|瑟|se)图充能(\\d+?(-\\d+?){0,1}((,|,|、)\\d+?(-\\d+?){0,1})*)"); 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/cq/CqHttpConfigurationProperties.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.cq; 2 | 3 | import java.util.Set; 4 | 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.boot.context.properties.ConstructorBinding; 7 | import org.springframework.boot.context.properties.bind.DefaultValue; 8 | 9 | @ConfigurationProperties(CqHttpConfigurationProperties.CONFIG_CQHTTP_PREFIX) 10 | @ConstructorBinding 11 | public class CqHttpConfigurationProperties { 12 | public final static String CONFIG_CQHTTP_PREFIX = "cq"; 13 | private String imageLocation; 14 | public String imageLocation() {return imageLocation;} 15 | private String recordLocation; 16 | public String recordLocation() {return recordLocation;} 17 | private String pushUrl; 18 | /** 19 | * 推送cq的地址 20 | * @return 21 | */ 22 | public String pushUrl() { 23 | return this.pushUrl; 24 | } 25 | /** 26 | * 调用cq api时所需的token 27 | */ 28 | private String token; 29 | public String token() { 30 | return this.token; 31 | } 32 | /** 33 | * 最大重试次数 34 | */ 35 | private int maxAttempt; 36 | public int maxAttempt() {return this.maxAttempt;} 37 | private long period; 38 | public long period() {return this.period;} 39 | private long maxPeriod; 40 | public long maxPeriod() {return this.maxPeriod;} 41 | /** 42 | * 超时 43 | */ 44 | private int readTimeout; 45 | public int readTimeout() {return this.readTimeout;} 46 | /** 47 | * 链接超时 48 | */ 49 | private int connectTimeout; 50 | public int connectTimeout() {return this.connectTimeout;} 51 | private String botId; 52 | public String botId() {return this.botId;} 53 | private Set adminId; 54 | public Set adminId(){return adminId;}; 55 | 56 | public CqHttpConfigurationProperties(@DefaultValue("http://localhost:5700")String pushUrl, 57 | String token, 58 | @DefaultValue("1")int maxAttempt, 59 | @DefaultValue("60000")int readTimeout, 60 | @DefaultValue("10000")int connectTimeout, 61 | String botId, 62 | Set adminId, 63 | @DefaultValue("data/OneBot/image/") String imageLocation, 64 | @DefaultValue("data/OneBot/record/") String recordLocation) { 65 | this.pushUrl = pushUrl; 66 | this.token = token; 67 | this.maxAttempt = maxAttempt; 68 | this.readTimeout = readTimeout; 69 | this.connectTimeout = connectTimeout; 70 | this.botId = botId; 71 | this.adminId = adminId; 72 | this.imageLocation = imageLocation; 73 | this.recordLocation = recordLocation; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/vo/SysGroupMember.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.vo; 2 | 3 | import java.util.Date; 4 | 5 | public class SysGroupMember { 6 | private long id; 7 | private String type;//group\discuss\private 8 | private String targetId; 9 | private String userId; 10 | private int coin;//金币 11 | private int checkinCount;//签到次数 12 | private int favorability;//好感度 13 | private Date createTime; 14 | private Date lastCheckinTime;//上次签到时间 15 | private int status;//0-无效 1-有效 2禁用 16 | private int repeatCount;//复读次数 17 | private int cardTicket;//卡券 18 | private String remark;//留言 19 | public int getCardTicket() { 20 | return cardTicket; 21 | } 22 | public void setCardTicket(int cardTicket) { 23 | this.cardTicket = cardTicket; 24 | } 25 | public long getId() { 26 | return id; 27 | } 28 | public void setId(long id) { 29 | this.id = id; 30 | } 31 | public String getType() { 32 | return type; 33 | } 34 | public void setType(String type) { 35 | this.type = type; 36 | } 37 | public String getTargetId() { 38 | return targetId; 39 | } 40 | public void setTargetId(String targetId) { 41 | this.targetId = targetId; 42 | } 43 | public String getUserId() { 44 | return userId; 45 | } 46 | public void setUserId(String userId) { 47 | this.userId = userId; 48 | } 49 | public int getCoin() { 50 | return coin; 51 | } 52 | public void setCoin(int coin) { 53 | this.coin = coin; 54 | } 55 | public Date getCreateTime() { 56 | return createTime; 57 | } 58 | public void setCreateTime(Date createTime) { 59 | this.createTime = createTime; 60 | } 61 | public int getStatus() { 62 | return status; 63 | } 64 | public void setStatus(int status) { 65 | this.status = status; 66 | } 67 | public int getCheckinCount() { 68 | return checkinCount; 69 | } 70 | public void setCheckinCount(int checkinCount) { 71 | this.checkinCount = checkinCount; 72 | } 73 | public int getFavorability() { 74 | return favorability; 75 | } 76 | public void setFavorability(int favorability) { 77 | this.favorability = favorability; 78 | } 79 | public Date getLastCheckinTime() { 80 | return lastCheckinTime; 81 | } 82 | public void setLastCheckinTime(Date lastCheckinTime) { 83 | this.lastCheckinTime = lastCheckinTime; 84 | } 85 | public int getRepeatCount() { 86 | return repeatCount; 87 | } 88 | public void setRepeatCount(int repeatCount) { 89 | this.repeatCount = repeatCount; 90 | } 91 | public String getRemark() { 92 | return remark; 93 | } 94 | public void setRemark(String remark) { 95 | this.remark = remark; 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/dao/CmdGameMapper.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.dao; 2 | 3 | import java.util.List; 4 | 5 | import org.accen.dmzj.web.vo.CmdGame; 6 | import org.accen.dmzj.web.vo.CmdGameNode; 7 | import org.apache.ibatis.annotations.Mapper; 8 | import org.apache.ibatis.annotations.Param; 9 | import org.apache.ibatis.annotations.Result; 10 | import org.apache.ibatis.annotations.ResultMap; 11 | import org.apache.ibatis.annotations.Results; 12 | import org.apache.ibatis.annotations.Select; 13 | @Mapper 14 | public interface CmdGameMapper { 15 | @Results(id = "cmdGameMapper",value = { 16 | @Result(property = "id",column = "id"), 17 | @Result(property = "gameName",column = "game_name"), 18 | @Result(property = "coinConsum",column = "coin_consum"), 19 | @Result(property = "favLimit",column = "fav_limit"), 20 | @Result(property = "status",column = "status") 21 | }) 22 | @Select("select * from cmd_game where id = #{id}") 23 | public CmdGame selectGameById(@Param("id")long id); 24 | @ResultMap("cmdGameMapper") 25 | @Select("select * from cmd_game where game_name = #{gameName} and status = 1 ") 26 | public CmdGame selectGameByName(@Param("gameName")String gameName); 27 | @ResultMap("cmdGameMapper") 28 | @Select("select * from cmd_game where status = 1 ") 29 | public List findAllGame(); 30 | 31 | @Results(id = "cmdGameNodeMapper",value = { 32 | @Result(property = "id",column = "id"), 33 | @Result(property = "gameName",column = "game_name"), 34 | @Result(property = "coinConsum",column = "coin_consum"), 35 | @Result(property = "favLimit",column = "fav_limit"), 36 | @Result(property = "status",column = "status") 37 | }) 38 | @Select("select * from cmd_game_node where id = #{id}") 39 | public CmdGameNode selectGameNodeById(@Param("id")long id); 40 | 41 | @ResultMap("cmdGameNodeMapper") 42 | @Select("select * from cmd_game_node where game_id = #{gameId} and node_type = 'First'}") 43 | public CmdGameNode findFirstNodeByGame(@Param("gameId")long gameId); 44 | @ResultMap("cmdGameNodeMapper") 45 | @Select("select cgn.* from cmd_game_node cgn left join cmd_node_relation cnr on cnr.c_node_id = cgn.id " 46 | + " where cnr.p_node_id = #{parentId} ") 47 | public List findNextNode(@Param("parentId")long parentId); 48 | @ResultMap("cmdGameNodeMapper") 49 | @Select("select cgn.* from cmd_game_node cgn left join cmd_node_relation cnr on cnr.c_node_id = cgn.id " 50 | + " where cnr.p_node_id = #{parentId} and cnr.check_no = #{checkNo}") 51 | public CmdGameNode selectNextNodeByNo(@Param("parentId")long parentId,String checkNo); 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/steam/SteamConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.steam; 2 | 3 | import java.io.File; 4 | import java.nio.charset.Charset; 5 | import java.nio.file.Files; 6 | 7 | import org.accen.dmzj.core.api.vo.SteamApp; 8 | import org.accen.dmzj.core.feign.GloabalFeignConfigration; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.boot.ApplicationRunner; 13 | import org.springframework.boot.context.properties.ConfigurationProperties; 14 | import org.springframework.boot.context.properties.ConstructorBinding; 15 | import org.springframework.boot.context.properties.bind.DefaultValue; 16 | import org.springframework.boot.context.properties.bind.Name; 17 | import org.springframework.context.annotation.Bean; 18 | 19 | @ConfigurationProperties("steam") 20 | @ConstructorBinding 21 | public class SteamConfiguration { 22 | private String key; 23 | private String steamAppListLocation; 24 | public String steamAppListLocation() {return this.steamAppListLocation;} 25 | public String key() { 26 | return this.key; 27 | } 28 | public SteamConfiguration(@Name("key")String key,@DefaultValue("steam_app_list.json")String steamAppListLocation) { 29 | this.key = key; 30 | this.steamAppListLocation = steamAppListLocation; 31 | } 32 | 33 | SteamApp steamApp; 34 | public SteamApp steamApp() {return steamApp;} 35 | @Bean 36 | public ApplicationRunner steamAppListCheckRunner(@Autowired SteamPoweredApiClient apiClient,@Autowired SteamConfiguration conf) { 37 | final Logger logger = LoggerFactory.getLogger(ApplicationRunner.class); 38 | return args->{ 39 | File localAppListFile = new File(conf.steamAppListLocation); 40 | if(!localAppListFile.exists()) { 41 | localAppListFile.createNewFile(); 42 | } 43 | if(localAppListFile.length()>0) { 44 | try{ 45 | conf.steamApp = GloabalFeignConfigration 46 | .recordSupportObjectMapper() 47 | .readValue(Files.readString(localAppListFile.toPath(), Charset.forName("UTF-8")), SteamApp.class); 48 | return; 49 | }catch(Exception e) { 50 | //解析json出错 51 | logger.warn("从{}获取的steam app list出错,将使用{}获取...",conf.steamAppListLocation,"SteamPoweredApiClient"); 52 | } 53 | } 54 | 55 | //配置文件为空,或者内容解析失败,则从接口中获取 56 | conf.steamApp = apiClient.appList(); 57 | Files.writeString(localAppListFile.toPath() 58 | , GloabalFeignConfigration.recordSupportObjectMapper().writeValueAsString(conf.steamApp) 59 | , Charset.forName("UTF-8")); 60 | }; 61 | } 62 | } 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/cmd/TimerCmd.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.cmd; 2 | 3 | import java.util.Timer; 4 | import java.util.TimerTask; 5 | import java.util.regex.Matcher; 6 | import java.util.regex.Pattern; 7 | 8 | import org.accen.dmzj.core.annotation.FuncSwitch; 9 | import org.accen.dmzj.core.task.GeneralTask; 10 | import org.accen.dmzj.core.task.TaskManager; 11 | import org.accen.dmzj.util.CQUtil; 12 | import org.accen.dmzj.web.vo.Qmessage; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.stereotype.Component; 15 | @FuncSwitch(title = "定时提醒") 16 | @Component 17 | public class TimerCmd implements CmdAdapter { 18 | 19 | @Autowired 20 | private TaskManager taskManager; 21 | 22 | private static final Pattern pattern = Pattern.compile("^老婆((\\d)?小时)?(([1-5]?[0-9])?分钟)?(([1-5]?[0-9])秒)?后(提醒我|说)(.+)"); 23 | @Override 24 | public GeneralTask cmdAdapt(Qmessage qmessage, String selfQnum) { 25 | String message = qmessage.getMessage().trim(); 26 | Matcher matcher = pattern.matcher(message); 27 | if(matcher.matches()) { 28 | 29 | int h = matcher.group(2)==null?0:Integer.parseInt(matcher.group(2)); 30 | int m = matcher.group(4)==null?0:Integer.parseInt(matcher.group(4)); 31 | int s = matcher.group(6)==null?0:Integer.parseInt(matcher.group(6)); 32 | String type = matcher.group(7); 33 | String msg = matcher.group(8); 34 | 35 | GeneralTask task = new GeneralTask(); 36 | 37 | task.setSelfQnum(selfQnum); 38 | task.setType(qmessage.getMessageType()); 39 | task.setTargetId(qmessage.getGroupId()); 40 | 41 | if(h+m+s>0) { 42 | Timer nTimer = new Timer(); 43 | nTimer.schedule(new TimerTask() { 44 | 45 | @Override 46 | public void run() { 47 | GeneralTask task2 = new GeneralTask(); 48 | 49 | task2.setSelfQnum(selfQnum); 50 | task2.setType(qmessage.getMessageType()); 51 | task2.setTargetId(qmessage.getGroupId()); 52 | task2.setMessage(("提醒我".equals(type)?CQUtil.at(qmessage.getUserId())+"老公时间到啦,该":"时间到啦")+msg 53 | +("提醒我".equals(type)?"了":"") 54 | +"喵~"); 55 | taskManager.addGeneralTask(task2); 56 | } 57 | }, h*60*60*1000+m*60*1000+s*1000); 58 | task.setMessage(CQUtil.at(qmessage.getUserId())+"老公收到了喵~," 59 | +(0==h?"":h+"小时") 60 | +(0==m?"":m+"分钟") 61 | +(0==s?"":s+"秒") 62 | +"后" 63 | +("提醒我".equals(type)?"提醒你":"说") 64 | +msg+"喵!"); 65 | }else { 66 | task.setMessage(CQUtil.at(qmessage.getUserId())+"老公你在说什么听不懂喵~"); 67 | 68 | } 69 | return task; 70 | 71 | 72 | } 73 | return null; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/api/pixivc/PixivcAuthFeignRequestInterceptor.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.api.pixivc; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | 5 | import org.accen.dmzj.core.feign.auth.AbstractHeaderAuthCounterFeignRequestInterceptor; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | /** 9 | * pix.ipv4.host使用authorization token实现认证 10 | * @author Accen 11 | * 12 | */ 13 | 14 | public class PixivcAuthFeignRequestInterceptor extends AbstractHeaderAuthCounterFeignRequestInterceptor{ 15 | 16 | 17 | @SuppressWarnings("unused") 18 | private final static Logger logger = LoggerFactory.getLogger(PixivcAuthFeignRequestInterceptor.class); 19 | 20 | /** 21 | * auth header 22 | */ 23 | public final static String AUTH_HEADER_KEY = "authorization"; 24 | private PixivcAuthConfigurationProperties prop; 25 | public PixivcAuthFeignRequestInterceptor(PixivcAuthConfigurationProperties prop) { 26 | this.prop = prop; 27 | try { 28 | holder = this.prop.authHolderClass().getDeclaredConstructor(PixivcAuthConfigurationProperties.class).newInstance(prop); 29 | fresher = this.prop.authFresherClass().getDeclaredConstructor(PixivcAuthConfigurationProperties.class).newInstance(prop); 30 | } catch (InstantiationException e) { 31 | e.printStackTrace(); 32 | } catch (IllegalAccessException e) { 33 | e.printStackTrace(); 34 | } catch (IllegalArgumentException e) { 35 | e.printStackTrace(); 36 | } catch (InvocationTargetException e) { 37 | e.printStackTrace(); 38 | } catch (NoSuchMethodException e) { 39 | e.printStackTrace(); 40 | } catch (SecurityException e) { 41 | e.printStackTrace(); 42 | } 43 | 44 | } 45 | /** 46 | * auth持有器 47 | */ 48 | private AuthHolder holder; 49 | /** 50 | * auth刷新器 51 | */ 52 | private AuthFresher fresher; 53 | protected void init() { 54 | Auth auth = holder.getAuth(); 55 | if(auth==null||!fresher.vertify(auth)) { 56 | //现有的auth holder没有存货,或者过期了,则使用fresher去刷新 57 | auth = fresher.fresh(null); 58 | } 59 | 60 | if(auth!=null) { 61 | holder.updateAuth(auth); 62 | } 63 | } 64 | private boolean inited = false; 65 | @Override 66 | public void firstTimeDo() { 67 | /*if(holder.getAuth()==null) { 68 | synchronized (holder) { 69 | if(holder.getAuth()==null) { 70 | init(); 71 | } 72 | } 73 | 74 | }*/ 75 | if(!inited) { 76 | synchronized (holder) { 77 | if(!inited) { 78 | init(); 79 | } 80 | } 81 | } 82 | //添加认证header 83 | if(holder.getAuth().auth()!=null) { 84 | super.addHeader(AUTH_HEADER_KEY, holder.getAuth().auth()); 85 | } 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/web/vo/CmdBuSub.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.web.vo; 2 | 3 | import java.util.Date; 4 | 5 | public class CmdBuSub { 6 | private long id; 7 | private String type;//group\discuss\private 8 | private String targetId; 9 | private String subscriber; 10 | private String subTarget;//订阅源的地址,展示只支持bilibili.com 11 | private String subType;//订阅类型,暂时支持up,番剧 12 | private String subObj;//订阅目标的唯一标识 例如up主id 13 | private String subObjMark;//唯一标识的补充说明 例如up主名字 14 | private Date subTime;//订阅时间 15 | private String status;//1-有效 2-无效 16 | private String attr1;//扩展1,b站up订阅用作roomid#roomStatus。0-未开播,1-已开播 17 | private String attr2; 18 | 19 | private String botId; 20 | public String getType() { 21 | return type; 22 | } 23 | public void setType(String type) { 24 | this.type = type; 25 | } 26 | public String getTargetId() { 27 | return targetId; 28 | } 29 | public void setTargetId(String targetId) { 30 | this.targetId = targetId; 31 | } 32 | public String getSubscriber() { 33 | return subscriber; 34 | } 35 | public void setSubscriber(String subscriber) { 36 | this.subscriber = subscriber; 37 | } 38 | public String getSubTarget() { 39 | return subTarget; 40 | } 41 | public void setSubTarget(String subTarget) { 42 | this.subTarget = subTarget; 43 | } 44 | public String getSubType() { 45 | return subType; 46 | } 47 | public void setSubType(String subType) { 48 | this.subType = subType; 49 | } 50 | public String getSubObj() { 51 | return subObj; 52 | } 53 | public void setSubObj(String subObj) { 54 | this.subObj = subObj; 55 | } 56 | public Date getSubTime() { 57 | return subTime; 58 | } 59 | public void setSubTime(Date subTime) { 60 | this.subTime = subTime; 61 | } 62 | public String getStatus() { 63 | return status; 64 | } 65 | public void setStatus(String status) { 66 | this.status = status; 67 | } 68 | public long getId() { 69 | return id; 70 | } 71 | public void setId(long id) { 72 | this.id = id; 73 | } 74 | public String getSubObjMark() { 75 | return subObjMark; 76 | } 77 | public void setSubObjMark(String subObjMark) { 78 | this.subObjMark = subObjMark; 79 | } 80 | public String getBotId() { 81 | return botId; 82 | } 83 | public void setBotId(String botId) { 84 | this.botId = botId; 85 | } 86 | public String getAttr1() { 87 | return attr1; 88 | } 89 | public void setAttr1(String attr1) { 90 | this.attr1 = attr1; 91 | } 92 | public String getAttr2() { 93 | return attr2; 94 | } 95 | public void setAttr2(String attr2) { 96 | this.attr2 = attr2; 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/timer/ReportTimeSchedule.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.timer; 2 | 3 | import java.time.LocalDateTime; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | import org.accen.dmzj.core.task.GeneralTask; 8 | import org.accen.dmzj.core.task.TaskManager; 9 | import org.accen.dmzj.util.CQUtil; 10 | import org.accen.dmzj.web.dao.CfgResourceMapper; 11 | import org.accen.dmzj.web.vo.CfgResource; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.beans.factory.annotation.Value; 14 | import org.springframework.scheduling.annotation.Scheduled; 15 | import org.springframework.stereotype.Component; 16 | 17 | @Component 18 | public class ReportTimeSchedule { 19 | @Autowired 20 | private TaskManager taskManager; 21 | 22 | @Autowired 23 | private CfgResourceMapper cfgResourceMapper; 24 | 25 | /** 26 | * 每个群对应的闹钟 27 | */ 28 | private Map groupClockMap = new HashMap(); 29 | 30 | @Value("${coolq.bot}") 31 | private String botId; 32 | 33 | @Scheduled(cron = "0 0 * * * *") 34 | public void reportTime() { 35 | //整点报时 36 | int hour = LocalDateTime.now().getHour(); 37 | groupClockMap.forEach((groupId,clock)->{ 38 | String recordUrl = getMp3UrlMoegirl(groupClockMap.get(groupId), hour); 39 | if(recordUrl!=null) { 40 | GeneralTask task = new GeneralTask(); 41 | task.setSelfQnum(botId); 42 | task.setType("group"); 43 | task.setTargetId(groupId); 44 | task.setMessage(CQUtil.recordUrl(recordUrl)); 45 | taskManager.addGeneralTask(task); 46 | } 47 | }); 48 | } 49 | private static final String KEY_PREFFIX = "record_clock_"; 50 | /** 51 | * 萌娘上的报时语音 52 | * @param clock 53 | * @return 54 | */ 55 | private String getMp3UrlMoegirl(String clock,int hour) { 56 | String key = null; 57 | switch (clock) { 58 | case "晓": 59 | key= KEY_PREFFIX+"Akatsuki_"+hour; 60 | break; 61 | case "响": 62 | key = KEY_PREFFIX+"Hibiki_"+hour; 63 | break; 64 | case "吹雪": 65 | key = KEY_PREFFIX+"Fubuki_"+hour; 66 | break; 67 | default: 68 | break; 69 | } 70 | if(null!=key) { 71 | CfgResource cr = cfgResourceMapper.selectByKey(key); 72 | if(cr!=null) { 73 | return cr.getCfgResource(); 74 | } 75 | } 76 | return null; 77 | } 78 | 79 | public boolean isOpenClock(String groupId) { 80 | return groupClockMap.containsKey(groupId); 81 | } 82 | public String openClock(String groupId,String clock) { 83 | return groupClockMap.put(groupId, clock); 84 | } 85 | public String closeClock(String groupId) { 86 | return groupClockMap.remove(groupId); 87 | } 88 | public String getClock(String groupId) { 89 | return groupClockMap.get(groupId); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/cmd/SetWelcome.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.cmd; 2 | 3 | import java.math.BigDecimal; 4 | import java.util.Date; 5 | import java.util.Map; 6 | import java.util.regex.Matcher; 7 | import java.util.regex.Pattern; 8 | 9 | import org.accen.dmzj.core.handler.NoticeEventHandler; 10 | import org.accen.dmzj.core.task.GeneralTask; 11 | import org.accen.dmzj.util.CQUtil; 12 | import org.accen.dmzj.web.dao.CfgConfigValueMapper; 13 | import org.accen.dmzj.web.vo.CfgConfigValue; 14 | import org.accen.dmzj.web.vo.Qmessage; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.beans.factory.annotation.Value; 17 | import org.springframework.stereotype.Component; 18 | 19 | @Component 20 | public class SetWelcome implements CmdAdapter { 21 | 22 | @Value("${coolq.manager}") 23 | private String manager = "1339633536";//管理员qq 24 | @Autowired 25 | private CfgConfigValueMapper configMapper; 26 | @Value("${coolq.welcom.maxlength:15}") 27 | private int welcomLength; 28 | private static final Pattern pattern = Pattern.compile("^设置欢迎词(.+)"); 29 | @Override 30 | public GeneralTask cmdAdapt(Qmessage qmessage, String selfQnum) { 31 | String role = (String) ((Map)qmessage.getEvent().get("sender")).get("role"); 32 | if((!manager.equals(qmessage.getUserId()))&&(!"owner".equals(role))&&(!"admin".equals(role))) { 33 | return null; 34 | } 35 | String message = qmessage.getMessage().trim(); 36 | Matcher matcher = pattern.matcher(message); 37 | if(matcher.matches()) { 38 | GeneralTask task = new GeneralTask(); 39 | 40 | task.setSelfQnum(selfQnum); 41 | task.setType(qmessage.getMessageType()); 42 | task.setTargetId(qmessage.getGroupId()); 43 | 44 | String wlcm = matcher.group(1); 45 | if(wlcm.length()>welcomLength) { 46 | task.setMessage(CQUtil.at(qmessage.getUserId())+" 都说了欢迎词不要超过"+welcomLength+"个字啦喵!!再这样就不理你了喵~"); 47 | }else { 48 | CfgConfigValue configo = configMapper.selectByTargetAndKey("group",qmessage.getGroupId(), NoticeEventHandler.REPLY_GROUP_INCREASE); 49 | if(configo==null) { 50 | CfgConfigValue config = new CfgConfigValue(); 51 | config.setTargetType(qmessage.getMessageType()); 52 | config.setTarget(qmessage.getGroupId()); 53 | config.setConfigKey(NoticeEventHandler.REPLY_GROUP_INCREASE); 54 | config.setConfigValue(wlcm); 55 | configMapper.insert(config); 56 | }else { 57 | configo.setConfigValue(wlcm); 58 | configo.setUpdateTime(new Date()); 59 | configo.setUpdateUserId(qmessage.getUserId()); 60 | configMapper.updateValue(configo); 61 | } 62 | task.setMessage("设置欢迎词成功!赶紧找个人退群加群试试吧喵!"); 63 | } 64 | return task; 65 | } 66 | return null; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/feign/GloabalFeignConfigration.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.feign; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | 6 | import org.springframework.beans.factory.ObjectFactory; 7 | import org.springframework.boot.autoconfigure.http.HttpMessageConverters; 8 | import org.springframework.cloud.openfeign.support.ResponseEntityDecoder; 9 | import org.springframework.cloud.openfeign.support.SpringDecoder; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.http.MediaType; 12 | import org.springframework.http.converter.HttpMessageConverter; 13 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 14 | 15 | import com.fasterxml.jackson.databind.ObjectMapper; 16 | import com.fasterxml.jackson.databind.introspect.AnnotatedMember; 17 | import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; 18 | import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; 19 | 20 | import feign.codec.Decoder; 21 | 22 | public class GloabalFeignConfigration { 23 | @Bean 24 | Decoder feignDecoder() { 25 | @SuppressWarnings("rawtypes") 26 | HttpMessageConverter jacksonConverter = new Text2JsonHttpMessageConverter(recordSupportObjectMapper()); 27 | ObjectFactory objectFactory = () -> new HttpMessageConverters(jacksonConverter); 28 | return new ResponseEntityDecoder(new SpringDecoder(objectFactory)); 29 | } 30 | /** 31 | * 支持record 32 | * @return 33 | */ 34 | public static ObjectMapper recordSupportObjectMapper() { 35 | ObjectMapper objectMapper = new ObjectMapper(); 36 | @SuppressWarnings("serial") 37 | JacksonAnnotationIntrospector jai = new JacksonAnnotationIntrospector() { 38 | /** 39 | * 重写findImplicitPropertyName以支持record 40 | */ 41 | @SuppressWarnings("preview") 42 | @Override 43 | public String findImplicitPropertyName(AnnotatedMember m) { 44 | if(m.getDeclaringClass().isRecord()) { 45 | if(m instanceof AnnotatedParameter p) { 46 | return m.getDeclaringClass().getRecordComponents()[p.getIndex()].getName(); 47 | } 48 | } 49 | return super.findImplicitPropertyName(m); 50 | }; 51 | }; 52 | objectMapper.setAnnotationIntrospector(jai); 53 | 54 | return objectMapper; 55 | 56 | } 57 | 58 | class Text2JsonHttpMessageConverter extends MappingJackson2HttpMessageConverter{ 59 | 60 | public Text2JsonHttpMessageConverter() { 61 | super(); 62 | } 63 | 64 | public Text2JsonHttpMessageConverter(ObjectMapper objectMapper) { 65 | super(objectMapper); 66 | } 67 | 68 | @Override 69 | public void setSupportedMediaTypes(List supportedMediaTypes) { 70 | super.setSupportedMediaTypes(Collections.singletonList(MediaType.TEXT_PLAIN)); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/org/accen/dmzj/core/handler/cmd/TriggerProSwitchCmd.java: -------------------------------------------------------------------------------- 1 | package org.accen.dmzj.core.handler.cmd; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.regex.Matcher; 6 | import java.util.regex.Pattern; 7 | 8 | import org.accen.dmzj.core.annotation.FuncSwitch; 9 | import org.accen.dmzj.core.handler.group.System; 10 | import org.accen.dmzj.core.task.GeneralTask; 11 | import org.accen.dmzj.util.CQUtil; 12 | import org.accen.dmzj.web.dao.CfgConfigValueMapper; 13 | import org.accen.dmzj.web.vo.CfgConfigValue; 14 | import org.accen.dmzj.web.vo.Qmessage; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.stereotype.Component; 17 | @FuncSwitch(groupClass = System.class,showMenu = true, title = "设置词条几率",format = "设置几率\\d%") 18 | @Component 19 | public class TriggerProSwitchCmd implements CmdAdapter { 20 | 21 | private final static Pattern pattern = Pattern.compile("^设置几率([1-9]?\\d|100)%$"); 22 | private Map groupPro = new HashMap(); 23 | private final static String FUZZY_PRO = "FUZZY_PRO"; 24 | @Autowired 25 | private CfgConfigValueMapper configMapper; 26 | //默认为70 27 | public int triggerPro(String groupId) { 28 | // return groupPro.containsKey(groupId)?groupPro.get(groupId):70; 29 | if(groupPro.get(groupId)==null) { 30 | CfgConfigValue config = configMapper.selectByTargetAndKey("group", groupId, FUZZY_PRO); 31 | if(config!=null) { 32 | groupPro.put(groupId, Integer.valueOf(config.getConfigValue())); 33 | } 34 | } 35 | return groupPro.containsKey(groupId)?groupPro.get(groupId):70; 36 | 37 | } 38 | private void putPro(String groupId,int pro) { 39 | groupPro.put(groupId, pro); 40 | CfgConfigValue config = configMapper.selectByTargetAndKey("group", groupId, FUZZY_PRO); 41 | if(config!=null) { 42 | config.setConfigValue(""+pro); 43 | configMapper.updateValue(config); 44 | }else { 45 | config = new CfgConfigValue(); 46 | config.setTargetType("group");config.setTarget(groupId);config.setConfigKey(FUZZY_PRO);config.setConfigValue(""+pro); 47 | configMapper.insert(config); 48 | } 49 | } 50 | @Override 51 | public GeneralTask cmdAdapt(Qmessage qmessage, String selfQnum) { 52 | 53 | String message = qmessage.getMessage().trim(); 54 | Matcher matcher = pattern.matcher(message); 55 | if(matcher.matches()) { 56 | Integer pro = Integer.valueOf(matcher.group(1)); 57 | // groupPro.put(qmessage.getGroupId(), pro); 58 | putPro(qmessage.getGroupId(), pro); 59 | 60 | GeneralTask task = new GeneralTask(); 61 | task.setSelfQnum(selfQnum); 62 | task.setType(qmessage.getMessageType()); 63 | task.setTargetId(qmessage.getGroupId()); 64 | task.setMessage(CQUtil.at(qmessage.getUserId())+"词条触发概率已设置为"+pro+"%了喵~"); 65 | return task; 66 | } 67 | return null; 68 | } 69 | 70 | } 71 | --------------------------------------------------------------------------------