Bläddra i källkod

Merge branch 'gpt_restrication'

# Conflicts:
#	netflix-service/src/main/java/com/cyksj/service/chatgpt/ChatGptAccountService.java
#	netflix-service/src/main/java/com/cyksj/service/chatgpt/impl/ChatGptAccountServiceImpl.java
#	netflix-web/src/main/java/com/cyksj/web/controller/mirror/MirrorController.java
chenbiao 1 år sedan
förälder
incheckning
c23d4bd7ce

+ 5 - 0
netflix-common/src/main/java/com/cyksj/dto/RedisKey.java

@@ -67,4 +67,9 @@ public class RedisKey {
      * 客服下标
      */
     public static String SERVICE_INDEX_KEY ="service_index_key";
+
+    /**
+     * 镜像gpt 当日使用量
+     */
+    public static String CHATGPT_USER_RESTRICTION ="chatgpt:user:restriction:";
 }

+ 11 - 0
netflix-dao/src/main/java/com/cyksj/mapper/ChatgptUserRestrictionMapper.java

@@ -0,0 +1,11 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.ChatgptUserRestriction;
+
+/**
+ * @author chan
+ * @date 2024/12/26 15:35
+ */
+public interface ChatgptUserRestrictionMapper extends BaseMapper<ChatgptUserRestriction> {
+}

+ 29 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/ChatgptUserVerifyDto.java

@@ -0,0 +1,29 @@
+package com.cyksj.model.dto;
+
+import lombok.Data;
+
+/**
+ * @author chan
+ * @date 2024/12/26 16:20
+ */
+@Data
+public class ChatgptUserVerifyDto {
+
+    /**
+     * 用户凭证
+     */
+    private String userToken;
+
+    /**
+     * 验证id
+     */
+    private String restrictionId;
+
+    private String ticket;
+
+    private String randStr;
+
+    private String ip;
+
+    private String userAgent;
+}

+ 45 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/ChatgptUserRestriction.java

@@ -0,0 +1,45 @@
+package com.cyksj.model.entity;
+
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author chan
+ * @date 2024/12/26 15:33
+ */
+@Data
+public class ChatgptUserRestriction extends BaseEntity{
+
+    /**
+     *  风控id
+     */
+    private String restrictionId;
+
+    /**
+     * 用户凭证
+     */
+    private String userToken;
+
+    /**
+     * 是否解锁成功
+     */
+    private Boolean success;
+
+    /**
+     * 成功时间
+     */
+    private Date successTime;
+
+    /**
+     * 验证地址
+     */
+    private String url;
+
+    private String referer;
+
+    private String userAgent;
+
+    private String verifyUserAgent;
+
+}

+ 25 - 1
netflix-service/src/main/java/com/cyksj/service/chatgpt/ChatGptAccountService.java

@@ -1,12 +1,12 @@
 package com.cyksj.service.chatgpt;
 
+import com.cyksj.model.dto.ChatgptUserVerifyDto;
 import com.cyksj.model.entity.ChatgptSession;
 import com.cyksj.model.entity.ChatgptUser;
 import com.cyksj.model.views.ChatGptUserView;
 import com.cyksj.model.views.ChatgptCarInfoView;
 import com.ejlchina.searcher.SearchResult;
 
-import javax.servlet.http.Cookie;
 import java.time.LocalDateTime;
 import java.util.List;
 
@@ -59,6 +59,30 @@ public interface ChatGptAccountService {
 
     void gptSwitchModel(long userId, Long relationId);
 
+    /**
+     * 风控检测
+     * @param userToken
+     * @param referer
+     * @param userAgent
+     * @return
+     */
+    String isRestrictions(String userToken, String referer, String userAgent);
+
+    /**
+     * 获取验证状态
+     * @param userToken
+     * @param restrictionId
+     * @return
+     */
+    Boolean gptRestrictionStatus(String userToken, String restrictionId);
+
+    /**
+     * 验证
+     * @param chatgptUserVerifyDto
+     * @return
+     */
+    Boolean verifyRestriction(ChatgptUserVerifyDto chatgptUserVerifyDto);
+
     /**
      * gpt3日体验卡
      */

+ 90 - 0
netflix-service/src/main/java/com/cyksj/service/chatgpt/impl/ChatGptAccountServiceImpl.java

@@ -1,5 +1,6 @@
 package com.cyksj.service.chatgpt.impl;
 
+import cn.hutool.core.date.DateField;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUnit;
 import cn.hutool.core.date.DateUtil;
@@ -16,10 +17,14 @@ import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.snowflake.Sequence;
 import com.cyksj.common.util.Jsons;
+import com.cyksj.common.util.SmsUtil;
 import com.cyksj.common.util.StringUtil;
+import com.cyksj.dto.RedisKey;
 import com.cyksj.mapper.*;
 import com.cyksj.mapper.station.CollegeStudentStationUseTicketRecordMapper;
+import com.cyksj.model.dto.ChatgptUserVerifyDto;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.views.ChatGptUserView;
 import com.cyksj.model.views.ChatgptCarInfoView;
@@ -64,6 +69,9 @@ public class ChatGptAccountServiceImpl implements ChatGptAccountService {
 
     private static final String GPT_PROXY = "https://chat-chan-87jztgkf257d.xyhelper.org";
 
+    private static final String RESTRICTION_URL = "https://nf.video/bind/web/validating";
+
+    private final static Sequence SEQUENCE = new Sequence(0);
 
     private final RedisService redisService;
 
@@ -99,6 +107,8 @@ public class ChatGptAccountServiceImpl implements ChatGptAccountService {
 
     private final ChatgptTrialRecordMapper chatgptTrialRecordMapper;
 
+    private final ChatgptUserRestrictionMapper chatgptUserRestrictionMapper;
+
     @Override
     public String getGptSession(String account, String password) {
         String officialSession = "";
@@ -665,6 +675,86 @@ public class ChatGptAccountServiceImpl implements ChatGptAccountService {
         return DOMAIN;
     }
 
+    @Override
+    public String isRestrictions(String userToken, String referer, String userAgent) {
+        //从redis 中查询该usertoken 当日使用次数
+        DateTime now = DateTime.now();
+        DateTime dateTime = DateUtil.beginOfDay(now.toJdkDate());
+        DateTime endOfDayTime = DateUtil.endOfDay(now.toJdkDate());
+        DateTime twelveHoursAgo = DateUtil.offset(now, DateField.HOUR, -6);
+        ChatgptUserRestriction chatgptUserRestriction = chatgptUserRestrictionMapper.selectOne(Wrappers.lambdaQuery(ChatgptUserRestriction.class)
+                .eq(ChatgptUserRestriction::getUserToken, userToken)
+                .ge(ChatgptUserRestriction::getCreatedTime, twelveHoursAgo.toString()).eq(ChatgptUserRestriction::getSuccess, false).last(" limit 1"));
+        if (chatgptUserRestriction != null) {
+            JSONObject result = new JSONObject();
+            result.putOpt("url",chatgptUserRestriction.getUrl());
+            result.putOpt("code",1);
+            return result.toString();
+        }
+        String numStr = redisService.getStr(RedisKey.CHATGPT_USER_RESTRICTION + userToken);
+        if (StringUtils.isNotBlank(numStr) && StringUtils.isNumeric(numStr)) {
+            long num = Long.parseLong(numStr);
+            if (num >= 150) {
+                //触发限制,需要人机验证
+                Integer count = chatgptUserRestrictionMapper.selectCount(Wrappers.lambdaQuery(ChatgptUserRestriction.class).eq(ChatgptUserRestriction::getUserToken, userToken)
+                        .ge(ChatgptUserRestriction::getCreatedTime, dateTime.toString()));
+                if (count > 10) {
+                    chatgptUserMapper.update(null, Wrappers.lambdaUpdate(ChatgptUser.class).eq(ChatgptUser::getUserToken, userToken).set(ChatgptUser::getIsBlock, 1));
+                }
+                ChatgptUserRestriction restriction = new ChatgptUserRestriction();
+
+                restriction.setRestrictionId(SEQUENCE.nextId().toString());
+                restriction.setUrl(RESTRICTION_URL + "?restrictionId=" + restriction.getRestrictionId() + "&userToken=" + userToken);
+                restriction.setUserToken(userToken);
+                restriction.setUserAgent(userAgent);
+                restriction.setReferer(referer);
+                chatgptUserRestrictionMapper.insert(restriction);
+                JSONObject result = new JSONObject();
+                result.putOpt("url",restriction.getUrl());
+                result.putOpt("code",1);
+                return result.toString();
+            }
+        }
+        JSONObject result = new JSONObject();
+        result.putOpt("code",0);
+        redisService.incr(RedisKey.CHATGPT_USER_RESTRICTION + userToken, 1L);
+        long between = DateUtil.between(now, endOfDayTime, DateUnit.SECOND, true);
+        redisService.expire(RedisKey.CHATGPT_USER_RESTRICTION + userToken, between);
+        return result.toString();
+    }
+
+    @Override
+    public Boolean gptRestrictionStatus(String userToken, String restrictionId) {
+        ChatgptUserRestriction chatgptUserRestriction = chatgptUserRestrictionMapper.selectOne(Wrappers.lambdaQuery(ChatgptUserRestriction.class)
+                .eq(ChatgptUserRestriction::getUserToken, userToken)
+                .eq(ChatgptUserRestriction::getRestrictionId, restrictionId)
+                .last(" limit 1"));
+        if (chatgptUserRestriction == null) {
+            throw BusinessRuntimeException.getInstance("该验证异常.");
+        }else {
+            return chatgptUserRestriction.getSuccess();
+        }
+    }
+
+    @Override
+    public Boolean verifyRestriction(ChatgptUserVerifyDto chatgptUserVerifyDto) {
+        SmsUtil.checkTencentCaptcha(chatgptUserVerifyDto.getTicket(), chatgptUserVerifyDto.getIp(), chatgptUserVerifyDto.getRandStr());
+        // 清除一定次数,以及修改验证状态
+        ChatgptUserRestriction chatgptUserRestriction = chatgptUserRestrictionMapper.selectOne(Wrappers.lambdaQuery(ChatgptUserRestriction.class)
+                .eq(ChatgptUserRestriction::getUserToken, chatgptUserVerifyDto.getUserToken())
+                .eq(ChatgptUserRestriction::getRestrictionId, chatgptUserVerifyDto.getRestrictionId())
+                .eq(ChatgptUserRestriction::getSuccess, false)
+                .last(" limit 1"));
+        if (chatgptUserRestriction != null) {
+            chatgptUserRestriction.setSuccess(true);
+            chatgptUserRestriction.setVerifyUserAgent(chatgptUserVerifyDto.getUserAgent());
+            chatgptUserRestriction.setSuccessTime(new Date());
+            chatgptUserRestrictionMapper.updateById(chatgptUserRestriction);
+            redisService.decr(RedisKey.CHATGPT_USER_RESTRICTION + chatgptUserVerifyDto.getUserToken(), 50L);
+        }
+        return true;
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public String trialGpt(String clientIP, String trialToken, String userAgent) {

+ 52 - 0
netflix-web/src/main/java/com/cyksj/web/controller/mirror/MirrorController.java

@@ -16,6 +16,7 @@ import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.GroupsMapper;
 import com.cyksj.mapper.GroupsRelationMapper;
 import com.cyksj.mapper.renew.RenewUpgradePackageMapper;
+import com.cyksj.model.dto.ChatgptUserVerifyDto;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.views.*;
 import com.cyksj.service.chatgpt.ChatGptAccountService;
@@ -424,6 +425,57 @@ public class MirrorController {
         return GatewayResponse.SUCCESS.newBuilder().toResult(lumaHost + (EnvCommonService.active_pre.equals(envCommonService.getEnv()) ? "/8083":"/8085") +"/api/applets/luma/lumaMirrorWithToken/" + lumaUser.getUserToken());
     }
 
+    /**
+     * gpt 次数风控
+     * @return
+     */
+    @GetMapping("/gpt/restrictions")
+    public String gptRestrictions(){
+        String authorization = request.getHeader("Authorization");
+        String referer = request.getHeader("Referer");
+        String userAgent = request.getHeader("User-Agent");
+        if (StringUtils.isNotBlank(authorization)) {
+            if (authorization.length() > 7) {
+                String userToken = authorization.substring(7);
+                return chatGptAccountService.isRestrictions(userToken,referer,userAgent);
+            }
+        }
+        JSONObject result = new JSONObject();
+        result.putOpt("code",0);
+        return result.toString();
+    }
+
+    /**
+     * 获取验证状态
+     * @return
+     */
+    @GetMapping("/gpt/restrictions/status")
+    public Result<Boolean> gptRestrictionStatus(String userToken, String restrictionId){
+        if (StringUtils.isAnyBlank(userToken, restrictionId)) {
+            throw BusinessRuntimeException.getInstance("缺少必填参数");
+        }
+        Boolean success = chatGptAccountService.gptRestrictionStatus(userToken, restrictionId);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(success);
+    }
+
+    /**
+     * 验证
+     * @return
+     */
+    @PostMapping("/gpt/restrictions/verify")
+    public Result<Boolean> verifyRestriction(@RequestBody  ChatgptUserVerifyDto chatgptUserVerifyDto){
+        if (StringUtils.isAnyBlank(chatgptUserVerifyDto.getUserToken(), chatgptUserVerifyDto.getRestrictionId(),chatgptUserVerifyDto.getTicket(),chatgptUserVerifyDto.getRandStr())) {
+            throw BusinessRuntimeException.getInstance("缺少必填参数");
+        }
+        String ip = ServletUtil.getClientIP(request);
+        chatgptUserVerifyDto.setUserAgent(request.getHeader("User-Agent"));
+        chatgptUserVerifyDto.setIp(ip);
+        Boolean success = chatGptAccountService.verifyRestriction(chatgptUserVerifyDto);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(success);
+    }
+
+
+
 
     /**
      * gpt3天体验