Просмотр исходного кода

广告-v0.01

(cherry picked from commit 0ba0879923560461bbf3270ddc466047f3a78823)
MOKASZ\lw12420 1 год назад
Родитель
Сommit
25d93526e0

+ 47 - 0
launch-admin/src/main/java/com/webflux/launchadmin/mysql/controller/applet/AppletInController.java

@@ -0,0 +1,47 @@
+package com.webflux.launchadmin.mysql.controller.applet;
+
+import com.webflux.launchadmin.mysql.entity.applet.AppletIds;
+import com.webflux.launchadmin.mysql.service.applet.AppletServiceInterface;
+import com.webflux.launchcommon.returnObj.Paged;
+import com.webflux.launchcommon.returnObj.RStatus;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import reactor.core.publisher.Mono;
+
+@RestController
+@RequestMapping("in/applet")
+public class AppletInController {
+
+    @Autowired
+    private AppletServiceInterface appletServiceInterface;
+
+    /**
+     * 列表查询
+     * @return
+     */
+    @GetMapping("getList")
+    public Mono<RStatus<Paged<AppletIds>>> getList(){
+       return appletServiceInterface.getList();
+    }
+
+    /**
+     * 添加
+     * @param appletId
+     * @return {@link Mono}<{@link RStatus}<{@link Boolean}>>
+     */
+    @PostMapping("add")
+    public Mono<RStatus<Boolean>> add(@RequestParam("appletId") String appletId) {
+        return appletServiceInterface.add(appletId);
+    }
+
+    /**
+     * 移除
+     * @param id
+     * @return {@link Mono}<{@link RStatus}<{@link Boolean}>>
+     */
+    @DeleteMapping("delete/{id}")
+    public Mono<RStatus<Boolean>> delete(@PathVariable("id") Long id) {
+        return appletServiceInterface.delete(id);
+    }
+
+}

+ 57 - 0
launch-admin/src/main/java/com/webflux/launchadmin/mysql/controller/applet/AppletOutController.java

@@ -0,0 +1,57 @@
+package com.webflux.launchadmin.mysql.controller.applet;
+
+import com.webflux.launchadmin.mysql.controller.applet.res.AppletH5Data;
+import com.webflux.launchadmin.mysql.controller.applet.res.DataRes;
+import com.webflux.launchadmin.mysql.service.applet.AppletServiceInterface;
+import com.webflux.launchcommon.returnObj.RStatus;
+import jakarta.validation.constraints.NotNull;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import reactor.core.publisher.Mono;
+
+@RestController
+@RequestMapping("out/applet")
+public class AppletOutController {
+
+    @Autowired
+    private AppletServiceInterface appletServiceInterface;
+
+    /**
+     * 获取打开广告地址
+     * @param unique 同一用户使用一条scheme链接
+     * @return {@link Mono}<{@link RStatus}<{@link AppletH5Data}>>
+     */
+    @GetMapping("getOpenLink")
+    public Mono<RStatus<AppletH5Data>> getOpenLink(@RequestParam("unique") String unique){
+        return  appletServiceInterface.getOpenLink(unique);
+    }
+
+    /**
+     * 推送
+     * @param unique unique
+     * @param id 相册id
+     * @param state 1:看完 0:中断 2:进行中
+     * @return {@link Mono}<{@link RStatus}<{@link DataRes}>>
+     */
+    @GetMapping("pushState")
+    public Mono<RStatus<String>> pushState(@NotNull(message = " unique notNull") @RequestParam("unique") String unique,
+                                              @NotNull(message = " id notNull")@RequestParam("id") Long id ,
+                                              @NotNull(message = " state notNull") @RequestParam("state") Long state ){
+      return   appletServiceInterface.pushState(unique,id,String.valueOf(state));
+    }
+    /**
+     * 通过 unique 和相册 id 获取看视频状态
+     * @param unique unique
+     * @param id 相册id
+     * @return {@link Mono}<{@link RStatus}<{@link DataRes}>>
+     */
+    @GetMapping("getUniqueState")
+    public Mono<RStatus<DataRes>>  getUniqueState(@RequestParam("unique") String unique,@RequestParam("id") Long id  ){
+        return   appletServiceInterface.getUniqueState(unique,id);
+    }
+
+
+}

+ 8 - 0
launch-admin/src/main/java/com/webflux/launchadmin/mysql/controller/applet/res/AppletH5Data.java

@@ -0,0 +1,8 @@
+package com.webflux.launchadmin.mysql.controller.applet.res;
+
+import lombok.Data;
+
+@Data
+public class AppletH5Data {
+    private String openlink;
+}

+ 8 - 0
launch-admin/src/main/java/com/webflux/launchadmin/mysql/controller/applet/res/DataRes.java

@@ -0,0 +1,8 @@
+package com.webflux.launchadmin.mysql.controller.applet.res;
+
+import lombok.Data;
+
+@Data
+public class DataRes {
+    private Integer state;
+}

+ 15 - 0
launch-admin/src/main/java/com/webflux/launchadmin/mysql/controller/testController.java

@@ -11,6 +11,7 @@ import com.webflux.launchadmin.mysql.entity.planNew.BackgroupImage;
 import com.webflux.launchadmin.mysql.entity.planNew.Image;
 import com.webflux.launchadmin.mysql.entity.test.Tweet;
 import com.webflux.launchadmin.mysql.repository.test.TweetRepository;
+import com.webflux.launchadmin.mysql.service.applet.AppletServiceInterface;
 import com.webflux.launchadmin.mysql.service.ip.BlacklistService;
 import com.webflux.launchadmin.mysql.task.SyncImageToRedis;
 import com.webflux.launchadmin.mysql.service.test.TweetService;
@@ -67,6 +68,8 @@ public class testController {
     private BlacklistService blacklistService;
     @Resource
     TweetService tweetService;
+    @Autowired
+    AppletServiceInterface appletServiceInterface;
     @GetMapping("get55")
     public Mono<Long> get55(@RequestParam("key") String key) {
         return reactiveRedisTemplate.getExpire(key).flatMap(f->{
@@ -74,6 +77,18 @@ public class testController {
             return Mono.just(seconds);
         });
     }
+
+    @GetMapping("get53")
+    public Mono<String>  get53()   {
+        Mono<String> rateReturn = appletServiceInterface.getTonke1("wx07360450c03fb454");
+        return rateReturn;
+    }
+    @GetMapping("get52")
+    public Mono<String>  get52()   {
+        Mono<String> rateReturn = appletServiceInterface.getTonke("wx07360450c03fb454");
+        return rateReturn;
+
+    }
     @GetMapping("get51")
     public Mono<Boolean>  get51(ServerWebExchange exchange)   {
         Mono<Boolean> rateReturn = blacklistService.getRateReturn(exchange);

+ 8 - 0
launch-admin/src/main/java/com/webflux/launchadmin/mysql/entity/applet/AppletIds.java

@@ -0,0 +1,8 @@
+package com.webflux.launchadmin.mysql.entity.applet;
+
+import org.springframework.data.annotation.Id;
+import org.springframework.data.relational.core.mapping.Table;
+
+@Table("applet_ids")
+public record AppletIds(@Id Long id, String appletId) {
+}

+ 270 - 0
launch-admin/src/main/java/com/webflux/launchadmin/mysql/service/applet/AppletService.java

@@ -0,0 +1,270 @@
+package com.webflux.launchadmin.mysql.service.applet;
+
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.webflux.launchadmin.global.BaseException;
+import com.webflux.launchadmin.mysql.controller.applet.res.AppletH5Data;
+import com.webflux.launchadmin.mysql.controller.applet.res.DataRes;
+import com.webflux.launchadmin.mysql.entity.applet.AppletIds;
+import com.webflux.launchadmin.mysql.entity.planNew.PlanNewCommon;
+import com.webflux.launchadmin.mysql.service.sourceMaterial.SourceMaterialInterface;
+import com.webflux.launchcommon.returnObj.Paged;
+import com.webflux.launchcommon.returnObj.RStatus;
+import io.lettuce.core.RedisClient;
+import io.lettuce.core.api.StatefulRedisConnection;
+import io.lettuce.core.api.reactive.RedisReactiveCommands;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.Resource;
+import org.apache.logging.log4j.spi.LoggerContextKey;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
+import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
+import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
+import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
+import org.springframework.data.redis.core.ReactiveRedisTemplate;
+import org.springframework.data.redis.serializer.RedisSerializationContext;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+import org.springframework.data.relational.core.query.Criteria;
+import org.springframework.data.relational.core.query.Query;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.stream.Collectors;
+
+@Service
+public class AppletService implements AppletServiceInterface {
+
+    private static final String keyEnd="_access_token";
+
+    @Resource
+    private R2dbcEntityTemplate r2dbcEntityTemplate;
+
+
+    @Autowired
+    private ReactiveRedisTemplate<String,Object> reactiveRedisTemplates;
+    private static final String wxPosturl="https://api.weixin.qq.com/wxa/generatescheme?access_token=";
+
+    /**
+     * 缓存applet
+     */
+    private static final CopyOnWriteArrayList<String> lists=new CopyOnWriteArrayList<>();
+
+    private RedisReactiveCommands<String, String> reactiveRedisTemplateApplet;
+
+    public  AppletService() {
+        // 手动创建 RedisClient 实例并连接到 Redis 服务器
+        connection();
+    }
+
+    private void connection(){
+        RedisClient redisClient = RedisClient.create("redis://:FQYxUmMtBCcyS22@r-bp1583bbf9fdfee4pd.redis.rds.aliyuncs.com:56565/99");
+        StatefulRedisConnection<String, String> connection = redisClient.connect();
+        // 获取 Reactive API 命令接口
+        this.reactiveRedisTemplateApplet = connection.reactive();
+    }
+    /**
+     * 核对+初始化
+     */
+    @Scheduled(fixedDelay = 160000)
+    public void getAppletIds(){
+        r2dbcEntityTemplate.select(AppletIds.class).all().collectList().flatMap(list->{
+            List<String> collect = list.stream().map(AppletIds::appletId).collect(Collectors.toList());
+            if (!collect.isEmpty()) {
+                List<String> addIps = getAddIps(collect, lists);
+                if (!addIps.isEmpty()) {
+                    lists.addAll(addIps);
+                }
+                List<String> removers = getAddIps(lists, collect);
+                if(!removers.isEmpty()){
+                    lists.removeAll(removers);
+                }
+            }
+            return Mono.just(true);
+        }).subscribe();
+    }
+    @NotNull
+    private List<String> getAddIps(List<String> ips, List<String> ip_white_list) {
+        return ips.stream().filter(o -> !ip_white_list.contains(o)).collect(Collectors.toList());
+    }
+    @Autowired
+    private SourceMaterialInterface sourceMaterialInterface;
+    private final Lock lock = new ReentrantLock();
+    private Mono<String> ping(){
+        try {
+            lock.lock();
+            return   reactiveRedisTemplateApplet.ping().flatMap(response -> {
+                if(!"PONG".equals(response)){
+                    connection();
+                }
+                return Mono.just("SUCCESS");
+            });
+        }finally {
+            lock.unlock();
+        }
+    }
+    @Override
+    public Mono<String> getTonke(String appletIds) {
+        return ping().then(reactiveRedisTemplateApplet.get(appletIds + keyEnd)
+                .switchIfEmpty(Mono.error(new BaseException("获取token结果为空 appletId:"+appletIds)))
+                .flatMap(ret -> {
+                    if (Objects.nonNull(ret) &&!"".equals(ret) ) {
+                        JSONObject jsonObject = JSONUtil.parseObj(ret);
+                        if (jsonObject.containsKey("access_token")) {
+                            String access_token = jsonObject.get("access_token", String.class);
+                            return Mono.just(access_token);
+                        }
+                    }
+                    return Mono.error(new BaseException("redis获取token结果异常 body::"+ret));
+                }).onErrorResume(throwable ->
+                        Mono.error(new BaseException(StrUtil
+                                .format("获取:{} 失败:{}", appletIds, throwable.getMessage())))));
+    }
+
+    @Override
+    public Mono<String> getTonke1(String appletIds) {
+     return     reactiveRedisTemplates.opsForValue().get("ip_rate_limit_range").flatMap(f-> Mono.just(String.valueOf(f)));
+    }
+    @Override
+    public Mono<String> getWxScheme(Mono<String> token){
+      var bodys= """ 
+                    { "expire_interval":1,
+                    "expire_type":1 }
+                """;
+       return token.flatMap(tk->{
+                HttpClient client = HttpClient.newHttpClient();
+                HttpRequest request = HttpRequest.newBuilder()
+                        .uri(URI.create(wxPosturl+tk))
+                        .POST(HttpRequest.BodyPublishers.ofString(bodys))
+                        .header("Content-Type", "application/json")
+                        .build();
+                HttpResponse<String> response = null;
+                try {
+                    response = client.send(request, HttpResponse.BodyHandlers.ofString());
+                    String body = response.body();
+                    JSONObject jsonObject = JSONUtil.parseObj(body);
+                    if (jsonObject.containsKey("errcode")
+                            && jsonObject.get("errcode", Integer.class) == 0
+                            && jsonObject.containsKey("openlink")) {
+                        String openlink = jsonObject.get("openlink", String.class);
+                        return Mono.just(openlink);
+                    }else {
+                       return  Mono.error(new BaseException(StrUtil.format("获取openlink异常 body::{}",body)));
+                    }
+                } catch (IOException e) {
+                    return Mono.error(new BaseException("请求wx generatescheme io 异常 :"+e.getMessage()));
+                } catch (InterruptedException e) {
+                    return Mono.error(new BaseException("请求wx generatescheme Interrupted 异常 :"+e.getMessage()));
+                }
+        });
+    }
+
+    @Override
+    public Mono<RStatus<Paged<AppletIds>>> getList() {
+        return sourceMaterialInterface.page(List.of(), AppletIds.class, 1000, 1);
+    }
+
+    @Override
+    public Mono<RStatus<Boolean>> add(String appletId) {
+        Mono<Long> applet_id = r2dbcEntityTemplate.count(Query.query(Criteria.where("applet_id").is(appletId)), AppletIds.class);
+        Mono<Boolean> mono = applet_id.flatMap(f -> {
+            if (f > 0) {
+                return Mono.error(new BaseException("小程序id 已存在"));
+            }
+            AppletIds appletIds = new AppletIds(null, appletId);
+            return r2dbcEntityTemplate.insert(appletIds).flatMap(appletIds1 -> {
+                lists.add(appletId);
+               return Mono.just(true);
+            });
+        });
+        return RStatus.success(mono);
+    }
+
+    @Override
+    public Mono<RStatus<Boolean>> delete(Long id) {
+        Mono<Boolean> mono = r2dbcEntityTemplate.selectOne(Query.query(Criteria.where("id").is(id)), AppletIds.class)
+                .switchIfEmpty(Mono.error(new BaseException("id 异常")))
+                .flatMap(obj -> r2dbcEntityTemplate.delete(Query.query(Criteria.where("id").is(id)), AppletIds.class)
+                        .flatMap(num -> {
+                            if(num>0){
+                                lists.remove(obj.appletId());
+                                return Mono.just(false);
+                            }
+                            return Mono.just(true);
+                }));
+        return RStatus.success(mono);
+    }
+
+    private Mono<String> getOLink(String unique){
+        if (lists.isEmpty()) {
+            return Mono.error(new BaseException("请维护 appletId "));
+        }
+        String s = lists.get(RandomUtil.randomInt(0, lists.size()));
+        return getWxScheme(getTonke(s))
+                .flatMap(link->
+                        reactiveRedisTemplates.opsForValue()
+                                .set(unique, s, Duration.ofMinutes(getSecondsUntilNextMidnight()))
+                                .flatMap(f->Mono.just(link)));
+    }
+    private static long getSecondsUntilNextMidnight() {
+        LocalDateTime now = LocalDateTime.now();
+        LocalDateTime midnight = now.toLocalDate().plusDays(1).atStartOfDay().plusHours(0).plusSeconds(1).plusMinutes(0);
+        return Duration.between(now, midnight).toMinutes();
+    }
+    @Override
+    public Mono<RStatus<AppletH5Data>> getOpenLink(String unique) {
+        Mono<AppletH5Data> appletH5DataMono1 = reactiveRedisTemplates
+                .opsForValue().get(unique)
+                .switchIfEmpty(getOLink(unique))
+                .flatMap(s -> {
+            AppletH5Data appletH5Data = new AppletH5Data();
+            appletH5Data.setOpenlink(String.valueOf(s));
+            return Mono.just(appletH5Data);
+        });
+        return RStatus.success(appletH5DataMono1);
+    }
+
+    @Override
+    public Mono<RStatus<String>> pushState(String unique, Long id, String state) {
+       return reactiveRedisTemplates.opsForValue().set(unique+"-"+id,state,Duration.ofHours(48)).flatMap(f->{
+            if (f) {
+                return RStatus.success(Mono.just("SUCCESS"));
+            }else {
+                return RStatus.fail(Mono.just("FAIL"));
+            }
+        });
+    }
+
+    @Override
+    public Mono<RStatus<DataRes>> getUniqueState(String unique, Long id) {
+        Mono<DataRes> dataResMono = reactiveRedisTemplates.opsForValue().get(unique +"-"+ id).flatMap(f -> {
+            DataRes dataRes = new DataRes();
+            if (Objects.nonNull(f) && "1".equals(f)) {
+                dataRes.setState(1);
+            } else if (Objects.nonNull(f) && "2".equals(f)) {
+                dataRes.setState(2);
+            }else {
+                dataRes.setState(0);
+            }
+            return Mono.just(dataRes);
+        });
+        return RStatus.success(dataResMono);
+    }
+}

+ 34 - 0
launch-admin/src/main/java/com/webflux/launchadmin/mysql/service/applet/AppletServiceInterface.java

@@ -0,0 +1,34 @@
+package com.webflux.launchadmin.mysql.service.applet;
+
+import com.webflux.launchadmin.mysql.controller.applet.res.AppletH5Data;
+import com.webflux.launchadmin.mysql.controller.applet.res.DataRes;
+import com.webflux.launchadmin.mysql.entity.applet.AppletIds;
+import com.webflux.launchcommon.returnObj.Paged;
+import com.webflux.launchcommon.returnObj.RStatus;
+import reactor.core.publisher.Mono;
+
+
+public interface AppletServiceInterface {
+
+    Mono<String> getTonke(String appletIds);
+
+    /**
+     * 测试2个redis 获取功能
+     * @param appletIds
+     * @return
+     */
+    Mono<String> getTonke1(String appletIds);
+    Mono<String> getWxScheme(Mono<String> token);
+
+    Mono<RStatus<Paged<AppletIds>>> getList();
+
+    Mono<RStatus<Boolean>> add(String appletId);
+
+    Mono<RStatus<Boolean>> delete(Long id);
+
+    Mono<RStatus<AppletH5Data>> getOpenLink(String unique);
+
+    Mono<RStatus<String>> pushState(String unique, Long id, String state);
+
+    Mono<RStatus<DataRes>> getUniqueState(String unique, Long id);
+}

+ 25 - 0
launch-admin/src/main/java/com/webflux/launchadmin/mysql/service/applet/redisCache/AppletCacheImp.java

@@ -0,0 +1,25 @@
+package com.webflux.launchadmin.mysql.service.applet.redisCache;
+
+import com.webflux.launchadmin.mysql.entity.applet.AppletIds;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.CachePut;
+import org.springframework.stereotype.Service;
+import reactor.core.publisher.Mono;
+
+@Service
+public class AppletCacheImp implements AppletCacheinterface{
+    private static final String APPLETKEY="java-webflux-applet-id-";
+
+
+    @Override
+    @CachePut(cacheNames = APPLETKEY,key = "#appletIds.id()")
+    public Mono<AppletIds> insetCasheRedis(AppletIds appletIds) {
+        return Mono.just(appletIds);
+    }
+
+    @Override
+    @CacheEvict(cacheNames = APPLETKEY,key = "#appletIds.id()")
+    public Mono<AppletIds> removeCasheRedis(AppletIds appletIds) {
+        return Mono.just(appletIds);
+    }
+}

+ 9 - 0
launch-admin/src/main/java/com/webflux/launchadmin/mysql/service/applet/redisCache/AppletCacheinterface.java

@@ -0,0 +1,9 @@
+package com.webflux.launchadmin.mysql.service.applet.redisCache;
+
+import com.webflux.launchadmin.mysql.entity.applet.AppletIds;
+import reactor.core.publisher.Mono;
+
+public interface AppletCacheinterface {
+     Mono<AppletIds> insetCasheRedis(AppletIds appletIds);
+     Mono<AppletIds> removeCasheRedis(AppletIds appletIds);
+}