diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml index 9e975bb47..d8be3d724 100644 --- a/ruoyi-admin/pom.xml +++ b/ruoyi-admin/pom.xml @@ -67,6 +67,18 @@ ruoyi-generator + + org.telegram + telegrambots + 6.0.1 + + + + org.projectlombok + lombok + 1.18.30 + + @@ -77,12 +89,12 @@ 2.5.15 true - + @@ -135,7 +147,7 @@ --> ${project.artifactId} - + diff --git a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java index 2ecb34adf..04b4d5abc 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java @@ -1,9 +1,15 @@ package com.ruoyi; +import com.ruoyi.system.bot.TgLongPollingBot; +import lombok.extern.slf4j.Slf4j; import org.mybatis.spring.annotation.MapperScan; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.telegram.telegrambots.meta.TelegramBotsApi; +import org.telegram.telegrambots.updatesreceivers.DefaultBotSession; /** * 启动程序 @@ -12,8 +18,11 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; */ @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) @MapperScan("com.ruoyi.system.mapper") -public class RuoYiApplication +@Slf4j +public class RuoYiApplication implements CommandLineRunner { + @Autowired(required = false) + private TgLongPollingBot tgLongPollingBot; public static void main(String[] args) { // System.setProperty("spring.devtools.restart.enabled", "false"); @@ -29,4 +38,16 @@ public class RuoYiApplication " | | \\ / \\ / \n" + " ''-' `'-' `-..-' "); } + + @Override + public void run(String... args) throws Exception { + if (tgLongPollingBot == null){ + return; + } + TelegramBotsApi botsApi = new TelegramBotsApi(DefaultBotSession.class); + + botsApi.registerBot(tgLongPollingBot); + tgLongPollingBot.setCommands(); + log.info("longPolling模式已启动"); + } } \ No newline at end of file diff --git a/ruoyi-admin/src/main/resources/application-test.yml b/ruoyi-admin/src/main/resources/application-test.yml new file mode 100644 index 000000000..3cd68672a --- /dev/null +++ b/ruoyi-admin/src/main/resources/application-test.yml @@ -0,0 +1,173 @@ +# 项目相关配置 +ruoyi: + # 名称 + name: RuoYi + # 版本 + version: 4.7.8 + # 版权年份 + copyrightYear: 2024 + # 实例演示开关 + demoEnabled: true + # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath) + profile: D:/ruoyi/uploadPath + # 获取ip地址开关 + addressEnabled: false + +# 开发环境配置 +server: + # 服务器的HTTP端口,默认为80 + port: 8080 + servlet: + # 应用的访问路径 + context-path: / + tomcat: + # tomcat的URI编码 + uri-encoding: UTF-8 + # 连接数满后的排队数,默认为100 + accept-count: 1000 + threads: + # tomcat最大线程数,默认为200 + max: 800 + # Tomcat启动初始化的线程数,默认值10 + min-spare: 100 + +# 日志配置 +logging: + level: + com.ruoyi: debug + org.springframework: warn + +# 用户配置 +user: + password: + # 密码错误{maxRetryCount}次锁定10分钟 + maxRetryCount: 5 + +# Spring配置 +spring: + # 模板引擎 + thymeleaf: + mode: HTML + encoding: utf-8 + # 禁用缓存 + cache: false + # 资源信息 + messages: + # 国际化资源文件路径 + basename: static/i18n/messages + jackson: + time-zone: GMT+8 + date-format: yyyy-MM-dd HH:mm:ss + profiles: + active: druid + # 文件上传 + servlet: + multipart: + # 单个文件大小 + max-file-size: 10MB + # 设置总上传的文件大小 + max-request-size: 20MB + # 服务模块 + devtools: + restart: + # 热部署开关 + enabled: true + + redis: + # Redis数据库索引(默认为0) + database: 4 + # Redis服务器地址 + host: 127.0.0.1 + # Redis服务器连接端口 + port: 6379 + # Redis服务器连接密码(默认为空) + password: myredis + jedis: + pool: + # 连接池最大连接数(使用负值表示没有限制) + max-active: 8 + # 连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1 + # 连接池中的最大空闲连接 + max-idle: 8 + # 连接池中的最小空闲连接 + min-idle: 0 + # 连接超时时间(毫秒) + timeout: 2000 + +# MyBatis +mybatis: + # 搜索指定包别名 + typeAliasesPackage: com.ruoyi.**.domain + # 配置mapper的扫描,找到所有的mapper.xml映射文件 + mapperLocations: classpath*:mapper/**/*Mapper.xml + # 加载全局的配置文件 + configLocation: classpath:mybatis/mybatis-config.xml + configuration: + map-underscore-to-camel-case: true + +# PageHelper分页插件 +pagehelper: + helperDialect: mysql + supportMethodsArguments: true + params: count=countSql + +# Shiro +shiro: + user: + # 登录地址 + loginUrl: /login + # 权限认证失败地址 + unauthorizedUrl: /unauth + # 首页地址 + indexUrl: /index + # 验证码开关 + captchaEnabled: true + # 验证码类型 math 数字计算 char 字符验证 + captchaType: math + cookie: + # 设置Cookie的域名 默认空,即当前访问的域名 + domain: + # 设置cookie的有效访问路径 + path: / + # 设置HttpOnly属性 + httpOnly: true + # 设置Cookie的过期时间,天为单位 + maxAge: 30 + # 设置密钥,务必保持唯一性(生成方式,直接拷贝到main运行即可)Base64.encodeToString(CipherUtils.generateNewKey(128, "AES").getEncoded()) (默认启动生成随机秘钥,随机秘钥会导致之前客户端RememberMe Cookie无效,如设置固定秘钥RememberMe Cookie则有效) + cipherKey: + session: + # Session超时时间,-1代表永不过期(默认30分钟) + expireTime: 30 + # 同步session到数据库的周期(默认1分钟) + dbSyncPeriod: 1 + # 相隔多久检查一次session的有效性,默认就是10分钟 + validationInterval: 10 + # 同一个用户最大会话数,比如2的意思是同一个账号允许最多同时两个人登录(默认-1不限制) + maxSession: -1 + # 踢出之前登录的/之后登录的用户,默认踢出之前登录的用户 + kickoutAfter: false + rememberMe: + # 是否开启记住我 + enabled: true + +# 防止XSS攻击 +xss: + # 过滤开关 + enabled: true + # 排除链接(多个用逗号分隔) + excludes: /system/notice/* + # 匹配链接 + urlPatterns: /system/*,/monitor/*,/tool/* + +# Swagger配置 +swagger: + # 是否开启swagger + enabled: true + + +tg: + bot: + name: CnRogerBotTestBot + token: 6926809179:AAEGmh9QOTmO3UhcOv9dY8h8g2nMWzZsE3s + chatid: -1002058165663 \ No newline at end of file diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 7ee7d7a00..3f7281aea 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -166,3 +166,8 @@ swagger: enabled: true +tg: + bot: + name: CnRogerBot + token: 6559243612:AAFOZU6MFq_pX25w71PH874_lVIM2MIhuSE + chatid: -1002058165663 \ No newline at end of file diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java deleted file mode 100644 index 25d1ddd02..000000000 --- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.ruoyi.quartz.task; - -import org.springframework.stereotype.Component; -import com.ruoyi.common.utils.StringUtils; - -/** - * 定时任务调度测试 - * - * @author ruoyi - */ -@Component("ryTask") -public class RyTask -{ - public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i) - { - System.out.println(StringUtils.format("执行多参方法: 字符串类型{},布尔类型{},长整型{},浮点型{},整形{}", s, b, l, d, i)); - } - - public void ryParams(String params) - { - System.out.println("执行有参方法:" + params); - } - - public void ryNoParams() - { - System.out.println("执行无参方法"); - } -} diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/Usdt2TrxxGroupTopicMessageTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/Usdt2TrxxGroupTopicMessageTask.java new file mode 100644 index 000000000..1783824ac --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/Usdt2TrxxGroupTopicMessageTask.java @@ -0,0 +1,17 @@ +package com.ruoyi.quartz.task; + +import com.ruoyi.system.handler.UsdtTransferHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component("usdt2TrxxGroupTopicMessageTask") +public class Usdt2TrxxGroupTopicMessageTask { + @Autowired + private UsdtTransferHandler usdtTransferHandler; + + public void doUsdt2TrxxGroupTopicMessageTask(){ + + + usdtTransferHandler.topicGroupMessage(); + } +} diff --git a/ruoyi-system/pom.xml b/ruoyi-system/pom.xml index 6d54d21d7..5362a61f4 100644 --- a/ruoyi-system/pom.xml +++ b/ruoyi-system/pom.xml @@ -63,6 +63,11 @@ 3.10.6 + + org.telegram + telegrambots + 6.0.1 + diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/api/IOkxApi.java b/ruoyi-system/src/main/java/com/ruoyi/system/api/IOkxApi.java index da358aa20..f059c4c59 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/api/IOkxApi.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/api/IOkxApi.java @@ -2,9 +2,11 @@ package com.ruoyi.system.api; import com.ruoyi.system.api.entity.okx.OkxResponse; +import java.io.IOException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; public interface IOkxApi { OkxResponse getSingleTickerOkxResponse() throws NoSuchAlgorithmException, InvalidKeyException; + OkxResponse getSingleTickerOkxResponse2() throws NoSuchAlgorithmException, InvalidKeyException, IOException; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/api/impl/OkxApiImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/api/impl/OkxApiImpl.java index 3ebaac7ed..d6cff52ab 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/api/impl/OkxApiImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/api/impl/OkxApiImpl.java @@ -5,6 +5,12 @@ import com.ruoyi.common.utils.http.RestTemplateUtils; import com.ruoyi.system.api.IOkxApi; import com.ruoyi.system.api.entity.okx.OkxResponse; import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -13,6 +19,7 @@ import org.springframework.web.util.UriComponentsBuilder; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -37,12 +44,15 @@ public class OkxApiImpl implements IOkxApi { dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); String timestamp = dateFormat.format(new Date()); headers.add("OK-ACCESS-TIMESTAMP", timestamp); - String apiKey = "eb3163ad-5221-491a-9ae9-e74e9637574c"; + + String apiKey = "b5937540-0817-41f8-bff3-3fda1262c744"; headers.add("OK-ACCESS-KEY", apiKey); + String passphrase = "CHenduoqi0101!"; headers.add("OK-ACCESS-PASSPHRASE", passphrase); + String method = "GET"; - String sign = generateSignature(timestamp, "get", "/api/v5/market/ticker?instId=TRX-USDT", "", "4CAAAA212D525D14AA1012E24B5FABDD"); + String sign = generateSignature(timestamp, method, "/api/v5/market/ticker?instId=TRX-USDT", "", "4CAAAA212D525D14AA1012E24B5FABDD"); headers.add("OK-ACCESS-SIGN", sign); //监听 UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://www.okx.com/api/v5/market/ticker?instId=TRX-USDT"); @@ -76,4 +86,53 @@ public class OkxApiImpl implements IOkxApi { byte[] hmacSha256 = mac.doFinal(preHash.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(hmacSha256); } + + @Override + public OkxResponse getSingleTickerOkxResponse2() throws NoSuchAlgorithmException, InvalidKeyException, IOException { + String requestURI = "/api/v5/market/ticker?instId=TRX-USDT"; + CloseableHttpClient httpClient = HttpClients.createDefault(); + String url = "http://www.okx.com"; +// HttpGet httpGet = new HttpGet(url + "/api/v5/market/tickers?instType=SWAP"); + HttpGet httpGet = new HttpGet(url + requestURI); + + // 设置OK-ACCESS-TIMESTAMP + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + String timestamp = dateFormat.format(new Date()); + httpGet.setHeader("OK-ACCESS-TIMESTAMP", timestamp); + + // 设置API密钥 + String apiKey = "b5937540-0817-41f8-bff3-3fda1262c744"; + httpGet.setHeader("OK-ACCESS-KEY", apiKey); + + // 设置Passphrase + String passphrase = "CHenduoqi0101!"; + httpGet.setHeader("OK-ACCESS-PASSPHRASE", passphrase); + + // 设置Content-Type + httpGet.setHeader(org.apache.http.HttpHeaders.CONTENT_TYPE, "application/json"); + + // 设置OK-ACCESS-SIGN + String method = "GET"; +// String requestPath = "/api/v5/market/tickers?instType=SWAP"; + String sign = generateSignature(timestamp, method, requestURI, "", "4CAAAA212D525D14AA1012E24B5FABDD"); + httpGet.setHeader("OK-ACCESS-SIGN", sign); + + // 发起请求 + HttpResponse response = httpClient.execute(httpGet); + HttpEntity entity = response.getEntity(); + if (entity == null) { + log.warn("getSingleTickerOkxResponse:responseEntityBody is null"); + return null; + } + String responseBody = EntityUtils.toString(response.getEntity()); + + OkxResponse okxResponse = JSONUtil.toBean( responseBody, OkxResponse.class); + // 处理响应 +/* String responseBody = EntityUtils.toString(response.getEntity()); + log.info("responseBody:{}", responseBody);*/ + return okxResponse; + } + + } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/bot/CustomBotCommands.java b/ruoyi-system/src/main/java/com/ruoyi/system/bot/CustomBotCommands.java new file mode 100644 index 000000000..fe2308e10 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/bot/CustomBotCommands.java @@ -0,0 +1,31 @@ +package com.ruoyi.system.bot; + +import org.springframework.stereotype.Component; +import org.telegram.telegrambots.meta.api.methods.commands.SetMyCommands; +import org.telegram.telegrambots.meta.api.objects.commands.BotCommand; +import org.telegram.telegrambots.meta.bots.AbsSender; +import org.telegram.telegrambots.meta.exceptions.TelegramApiException; + +import java.util.Arrays; +import java.util.List; + +@Component +public class CustomBotCommands { + public void setCustomBotCommands(AbsSender sender) throws TelegramApiException { + List commands = Arrays.asList( + new BotCommand("/start", "开始使用"), + new BotCommand("/rank", "汇率信息") + /* new BotCommand("/ban", "!或/ban user 时间(可选) 原因(可选)"), + new BotCommand("/dban","可Ban掉用户的同时,删除他的发言,格式参考Ban"), + new BotCommand("/unban", "解封用户,!或/unban user"), + new BotCommand("/mute", "禁言用户,格式参考Ban"), + new BotCommand("/unmute","解除用户发言限制,!或/unmute user")*/ + ); + + SetMyCommands setMyCommands = new SetMyCommands(); + setMyCommands.setCommands(commands); + + sender.execute(setMyCommands); + + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/bot/CustomBotFunction.java b/ruoyi-system/src/main/java/com/ruoyi/system/bot/CustomBotFunction.java new file mode 100644 index 000000000..6f39788b6 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/bot/CustomBotFunction.java @@ -0,0 +1,51 @@ +package com.ruoyi.system.bot; + +import org.springframework.stereotype.Component; +import org.telegram.telegrambots.meta.api.methods.send.SendMessage; +import org.telegram.telegrambots.meta.api.objects.Update; +import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboardMarkup; +import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.KeyboardRow; +import org.telegram.telegrambots.meta.bots.AbsSender; +import org.telegram.telegrambots.meta.exceptions.TelegramApiException; + +import java.util.ArrayList; +import java.util.List; + +@Component +public class CustomBotFunction { + + + + /** + * 对消息进行处理 + * @param sender + * @param update + */ + public void mainFunc(AbsSender sender, Update update) throws TelegramApiException { + if ("/start".equals(update.getMessage().getText())) { + + SendMessage message = new SendMessage(); + message.setChatId(update.getMessage().getChatId().toString()); + message.setText("Please select an option:"); + + // 创建一个 ReplyKeyboardMarkup 对象,用于存储按钮 + ReplyKeyboardMarkup keyboardMarkup = new ReplyKeyboardMarkup(); + List keyboard = new ArrayList<>(); + + // 创建一个按钮行 + KeyboardRow row = new KeyboardRow(); + row.add("Option 1"); + row.add("Option 2"); + keyboard.add(row); + + // 将按钮行添加到 ReplyKeyboardMarkup 对象中 + keyboardMarkup.setKeyboard(keyboard); + message.setReplyMarkup(keyboardMarkup); + + // 设置按钮显示在输入框底部 + keyboardMarkup.setResizeKeyboard(true); + + sender.execute(message); + } + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/bot/GroupCommands.java b/ruoyi-system/src/main/java/com/ruoyi/system/bot/GroupCommands.java new file mode 100644 index 000000000..ba73e6cde --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/bot/GroupCommands.java @@ -0,0 +1,34 @@ +package com.ruoyi.system.bot; + +import org.springframework.stereotype.Component; +import org.telegram.telegrambots.meta.api.methods.commands.SetMyCommands; +import org.telegram.telegrambots.meta.api.objects.commands.BotCommand; +import org.telegram.telegrambots.meta.api.objects.commands.scope.BotCommandScopeAllChatAdministrators; +import org.telegram.telegrambots.meta.bots.AbsSender; +import org.telegram.telegrambots.meta.exceptions.TelegramApiException; + +import java.util.Arrays; +import java.util.List; + +@Component +public class GroupCommands { + public void setGroupCommands(AbsSender sender) throws TelegramApiException { + List commands = Arrays.asList( + new BotCommand("/setbot", "设置机器人,仅群主可用"), + new BotCommand("/rank", "生成词云排行榜"), + new BotCommand("/ban", "!或/ban user 时间(可选) 原因(可选)"), + new BotCommand("/dban","可Ban掉用户的同时,删除他的发言,格式参考Ban"), + new BotCommand("/unban", "解封用户,!或/unban user"), + new BotCommand("/mute", "禁言用户,格式参考Ban"), + new BotCommand("/unmute","解除用户发言限制,!或/unmute user") + ); + + BotCommandScopeAllChatAdministrators scope = new BotCommandScopeAllChatAdministrators(); + SetMyCommands setMyCommands = new SetMyCommands(); + setMyCommands.setScope(scope); + setMyCommands.setCommands(commands); + + sender.execute(setMyCommands); + + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/bot/TgLongPollingBot.java b/ruoyi-system/src/main/java/com/ruoyi/system/bot/TgLongPollingBot.java new file mode 100644 index 000000000..22ce40639 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/bot/TgLongPollingBot.java @@ -0,0 +1,70 @@ +package com.ruoyi.system.bot; + +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.telegram.telegrambots.bots.TelegramLongPollingBot; +import org.telegram.telegrambots.meta.api.methods.send.SendMessage; +import org.telegram.telegrambots.meta.api.objects.Update; +import org.telegram.telegrambots.meta.exceptions.TelegramApiException; + +@Component +@Slf4j +public class TgLongPollingBot extends TelegramLongPollingBot { + + + @Value("${tg.bot.name}") + private String botName; + + @Value("${tg.bot.token}") + private String botToken; + + @Autowired + private CustomBotFunction customBotFunction; + + @Autowired + private CustomBotCommands customBotCommands; + + + + public void setCommands() throws TelegramApiException { +// groupCommands.setGroupCommands(this); + customBotCommands.setCustomBotCommands(this); + + } + + public void setBotName(String botName) { + this.botName = botName; + } + + public void setBotToken(String botToken) { + this.botToken = botToken; + } + + @Override + public String getBotUsername() { + return this.botName; + } + + @Override + public String getBotToken() { + return this.botToken; + } + + @Override + @SneakyThrows + public void onUpdateReceived(Update update) { +// log.info("消息:{}",update.getMessage().getText()); + SendMessage sendMessage = SendMessage.builder().chatId(update.getMessage().getChatId().toString()).text("收到消息:"+update.getMessage().getChatId().toString()).build(); + try { + customBotFunction.mainFunc(this,update); + execute(sendMessage); + + } catch (TelegramApiException e) { + log.error("ex:{}",e); + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/bot/utils/SendContent.java b/ruoyi-system/src/main/java/com/ruoyi/system/bot/utils/SendContent.java new file mode 100644 index 000000000..2a8a0ce3b --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/bot/utils/SendContent.java @@ -0,0 +1,30 @@ +package com.ruoyi.system.bot.utils; + +import org.springframework.stereotype.Component; +import org.telegram.telegrambots.meta.api.methods.send.SendMessage; +import org.telegram.telegrambots.meta.api.objects.Update; + +@Component +public class SendContent { + + public SendMessage messageText(Update update, String text){ + String chatId; + if (update.getMessage() == null) { + chatId = update.getCallbackQuery().getMessage().getChatId().toString(); + } else { + chatId = update.getMessage().getChatId().toString(); + } + SendMessage message = new SendMessage(); + message.setChatId(chatId); + message.setText(text); + return message; + } + + public SendMessage messageText(String chatId, String text, String parseMode){ + SendMessage message = new SendMessage(); + message.setChatId(chatId); + message.setText(text); + message.setParseMode(parseMode); + return message; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/handler/UsdtTransferHandler.java b/ruoyi-system/src/main/java/com/ruoyi/system/handler/UsdtTransferHandler.java index c9b2e18c5..1c138d0be 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/handler/UsdtTransferHandler.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/handler/UsdtTransferHandler.java @@ -1,16 +1,20 @@ package com.ruoyi.system.handler; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DateUtil; import cn.hutool.json.JSONUtil; import com.google.common.base.Preconditions; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.entity.MonitorAddressInfo; import com.ruoyi.common.core.domain.entity.UsdtExchangeInfo; +import com.ruoyi.common.utils.StringUtils; import com.ruoyi.system.api.IOkxApi; import com.ruoyi.system.api.ITronApi; import com.ruoyi.system.api.entity.okx.OkxResponse; import com.ruoyi.system.api.enums.ContractType; import com.ruoyi.system.api.enums.Symbol; +import com.ruoyi.system.bot.TgLongPollingBot; +import com.ruoyi.system.bot.utils.SendContent; import com.ruoyi.system.dto.Data; import com.ruoyi.system.dto.Token_info; import com.ruoyi.system.dto.TronGridResponse; @@ -19,20 +23,28 @@ import com.ruoyi.system.service.IAccountAddressInfoService; import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.util.AddressUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.text.StrSubstitutor; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; +import org.telegram.telegrambots.meta.api.methods.ParseMode; +import org.telegram.telegrambots.meta.api.methods.send.SendMessage; +import org.telegram.telegrambots.meta.exceptions.TelegramApiException; import org.tron.trident.core.ApiWrapper; import org.tron.trident.core.exceptions.IllegalException; import org.tron.trident.proto.Chain; import org.tron.trident.proto.Response; +import java.io.IOException; import java.math.BigDecimal; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; +import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; @Component @@ -56,6 +68,10 @@ public class UsdtTransferHandler { private RedisTemplate redisTemplate; @Autowired private RedissonClient redissonClient; + @Autowired(required = false) + private TgLongPollingBot longPollingBot; + @Autowired + private SendContent sendContent; public void doMonitorUsdtTransfer(MonitorAddressInfo monitorAddressInfo) throws Exception { @@ -105,7 +121,7 @@ public class UsdtTransferHandler { doTransferUsdtAndStore(oneUsdtToTrx, apiKey, decryptPrivateKey, accountAddress, from, trxValue, dataTo, transactionId, transferValue); redisTemplate.opsForValue().set("transfer_USDT_" + transactionId, transactionId, 1, TimeUnit.DAYS); - }finally { + } finally { if (lock.isLocked()) { if (lock.isHeldByCurrentThread()) { lock.unlock(); @@ -114,7 +130,7 @@ public class UsdtTransferHandler { } } - public void doTransferUsdtAndStore(BigDecimal oneUsdtToTrx, String apiKey, String decryptPrivateKey, String accountAddress, String from, BigDecimal trxValue, String dataTo, String transactionId, BigDecimal transferValue) throws IllegalException { + public void doTransferUsdtAndStore(BigDecimal oneUsdtToTrx, String apiKey, String decryptPrivateKey, String accountAddress, String from, BigDecimal trxValue, String dataTo, String transactionId, BigDecimal transferValue) throws IllegalException, TelegramApiException { String systronApiSwitch = configService.selectConfigByKey("sys.tron.api"); @@ -143,7 +159,31 @@ public class UsdtTransferHandler { .setOrginalExchangeRate(oneUsdtToTrx) .setTrxTxId(txId); + usdtExchangeInfoMapper.insertUsdtExchangeInfo(usdtExchangeInfo); + + doSendTgNotice(oneUsdtToTrx, from, trxValue, transferValue, txId); + } + + private void doSendTgNotice(BigDecimal oneUsdtToTrx, String from, BigDecimal trxValue, BigDecimal transferValue, String txId) throws TelegramApiException { + String sysUsdtTranferNotice = configService.selectConfigByKey("sys.usdt.tranfer.notice"); + String sysTgGroupChatId = configService.selectConfigByKey("sys.tg.group.chat.id"); + if (longPollingBot != null && StringUtils.isNotEmpty(sysUsdtTranferNotice) && StringUtils.isNotEmpty(sysTgGroupChatId)) { + Map arguments = new HashMap<>(); + arguments.put("usdtAmount", transferValue); + arguments.put("exchangeRate", oneUsdtToTrx); + arguments.put("trxAmount", trxValue); + arguments.put("FromAddress", from); + arguments.put("txId", txId); + arguments.put("txTime", DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss")); +// String message = MessageFormat.format(sysUsdtTranferNotice, arguments); + StrSubstitutor substitutor = new StrSubstitutor(arguments, "{", "}"); + String message = substitutor.replace(sysUsdtTranferNotice); + SendMessage sendMessage = sendContent.messageText(sysTgGroupChatId, message, ParseMode.HTML); + longPollingBot.execute(sendMessage); + } else { + log.warn("longPollingBot OR sysUsdtTranferNotice OR sysTgGroupChatId is null"); + } } /** @@ -186,8 +226,8 @@ public class UsdtTransferHandler { * @throws NoSuchAlgorithmException * @throws InvalidKeyException */ - public BigDecimal getOneUsdtToTrx() throws NoSuchAlgorithmException, InvalidKeyException { - OkxResponse oksResponse = okxApi.getSingleTickerOkxResponse(); + public BigDecimal getOneUsdtToTrx() throws NoSuchAlgorithmException, InvalidKeyException, IOException { + OkxResponse oksResponse = okxApi.getSingleTickerOkxResponse2(); Preconditions.checkNotNull(oksResponse, "查询费率失败无法兑换"); String code = oksResponse.getCode(); @@ -196,12 +236,63 @@ public class UsdtTransferHandler { List oksResponseDataList = oksResponse.getData(); Preconditions.checkState(CollectionUtil.isNotEmpty(oksResponseDataList), "okx费率响应为空:" + JSONUtil.toJsonStr(oksResponse)); - log.info("oksResponse:{}",oksResponse); + log.info("oksResponse:{}", oksResponse); String last = oksResponseDataList.get(0).getLast(); - BigDecimal oneUsdtToTrx = BigDecimal.ONE.divide(new BigDecimal(last)).setScale(6, BigDecimal.ROUND_HALF_DOWN); +// BigDecimal oneUsdtToTrx = BigDecimal.ONE.divide(new BigDecimal(last)).setScale(6, BigDecimal.ROUND_HALF_DOWN); + + double oneUsdtToTrxDouble = 1 / new Double(last); + BigDecimal oneUsdtToTrx = BigDecimal.valueOf(oneUsdtToTrxDouble).setScale(6, BigDecimal.ROUND_HALF_DOWN); + + log.info("实时汇率:{}",oneUsdtToTrx); + String sysUsdtProportionRate = configService.selectConfigByKey("sys.usdt.proportion.rate"); + + if (StringUtils.isNotEmpty(sysUsdtProportionRate)) { + oneUsdtToTrx = oneUsdtToTrx.multiply(BigDecimal.ONE.subtract(new BigDecimal(sysUsdtProportionRate))).setScale(6, BigDecimal.ROUND_HALF_DOWN); + } return oneUsdtToTrx; } + public void topicGroupMessage() { + + + String sysUsdtGroupTopic = configService.selectConfigByKey("sys.usdt.group.topic"); + String sysTgGroupChatId = configService.selectConfigByKey("sys.tg.group.chat.id"); + + log.info("longPollingBot:{},sysUsdtGroupTopic:{},sysTgGroupChatId:{}", longPollingBot, sysUsdtGroupTopic, sysTgGroupChatId); + + if (longPollingBot != null && StringUtils.isNotEmpty(sysUsdtGroupTopic) && StringUtils.isNotEmpty(sysTgGroupChatId)) { + log.info("进入这里1"); + try { + BigDecimal tenUsdtToTrx = getOneUsdtToTrx().multiply(BigDecimal.TEN); + Map arguments = new HashMap<>(); + arguments.put("tenUsdtToTrx", tenUsdtToTrx); + StrSubstitutor substitutor = new StrSubstitutor(arguments, "{", "}"); + String message = substitutor.replace(sysUsdtGroupTopic); + SendMessage sendMessage = sendContent.messageText(sysTgGroupChatId, message, ParseMode.HTML); + + longPollingBot.execute(sendMessage); + } catch (Exception e) { + + log.error("广播消息异常",e); + } + }else { + log.info("进入这里2"); + log.warn("sysUsdtTranferNotice OR sysTgGroupChatId is null"); + } + } + +/* public static void main(String[] args) { + String res ="{\"code\":\"0\",\"msg\":\"\",\"data\":[{\"instType\":\"SPOT\",\"instId\":\"TRX-USDT\",\"last\":\"0.11108\",\"lastSz\":\"534.839755\",\"askPx\":\"0.11108\",\"askSz\":\"12244.867483\",\"bidPx\":\"0.11107\",\"bidSz\":\"2776.220524\",\"open24h\":\"0.11093\",\"high24h\":\"0.11199\",\"low24h\":\"0.11018\",\"volCcy24h\":\"3721341.18131714737\",\"vol24h\":\"33527411.881202\",\"ts\":\"1713782792103\",\"sodUtc0\":\"0.11134\",\"sodUtc8\":\"0.11081\"}]}"; + OkxResponse okxResponse = JSONUtil.toBean(res, OkxResponse.class); + List oksResponseDataList = okxResponse.getData(); + String last = oksResponseDataList.get(0).getLast(); + + double v = 1 / new Double(last); + BigDecimal bigDecimal = BigDecimal.valueOf(v).setScale(6, BigDecimal.ROUND_HALF_DOWN); + System.out.println(bigDecimal); + }*/ + + }