Compare commits

...

10 Commits

53 changed files with 1009 additions and 327 deletions

53
pom.xml
View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.1</version> <version>3.1.5</version>
<relativePath/> <!-- lookup parent from repository --> <relativePath/> <!-- lookup parent from repository -->
</parent> </parent>
<groupId>com.lion</groupId> <groupId>com.lion</groupId>
@ -14,13 +14,9 @@
<name>LionWebsite</name> <name>LionWebsite</name>
<description>LionWebsite</description> <description>LionWebsite</description>
<properties> <properties>
<java.version>17</java.version> <java.version>21</java.version>
</properties> </properties>
<dependencies> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
@ -28,12 +24,13 @@
<dependency> <dependency>
<groupId>org.mybatis.spring.boot</groupId> <groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId> <artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.2</version> <version>3.0.3</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>1.18.30</version>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
@ -44,7 +41,7 @@
<dependency> <dependency>
<groupId>org.mybatis.spring.boot</groupId> <groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId> <artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.2</version> <version>3.0.3</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
@ -57,7 +54,7 @@
<dependency> <dependency>
<groupId>cn.hutool</groupId> <groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId> <artifactId>hutool-all</artifactId>
<version>5.8.11</version> <version>5.8.20</version>
</dependency> </dependency>
<dependency> <dependency>
@ -104,12 +101,40 @@
<dependency> <dependency>
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
<artifactId>netty-all</artifactId> <artifactId>netty-all</artifactId>
<version>4.1.86.Final</version> <version>4.1.101.Final</version>
</dependency>
<dependency>
<groupId>com.github.pengrad</groupId>
<artifactId>java-telegram-bot-api</artifactId>
<version>6.9.1</version>
</dependency>
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
<version>2.7.0</version>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<configuration>
<imageName>lionwebsite</imageName>
<buildArgs>
<arg>--gc=G1</arg>
<arg>-Ob</arg>
<arg>-H:+ReportExceptionStackTraces</arg>
<arg>--initialize-at-build-time=org.apache.commons.logging.LogFactory,org.apache.commons.logging.LogFactoryService</arg>
</buildArgs>
<metadataRepository>
<enabled>true</enabled>
</metadataRepository>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
@ -122,14 +147,6 @@
</excludes> </excludes>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins> </plugins>
</build> </build>

View File

@ -0,0 +1,30 @@
package com.lion.lionwebsite.Configuration;
import com.lion.lionwebsite.Domain.*;
import com.lion.lionwebsite.Message.*;
import com.pengrad.telegrambot.TelegramBot;
import com.pengrad.telegrambot.model.Chat;
import com.pengrad.telegrambot.model.Message;
import com.pengrad.telegrambot.model.MessageEntity;
import com.pengrad.telegrambot.response.SendResponse;
import com.sun.tools.javac.Main;
import org.springframework.aot.hint.annotation.RegisterReflectionForBinding;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.pengrad.telegrambot.model.User;
@Configuration
@RegisterReflectionForBinding(classes = {CRC32Cache.class, CustomConfiguration.class,
GalleryForQuery.class, Gallery.class, GalleryTask.class, MaskDomain.class,
PageNameCache.class, ShareFile.class, Tag.class, TagMark.class, User.class,
SendResponse.class, Message.class, com.pengrad.telegrambot.model.User.class,
Chat.class, MessageEntity.class,
AbstractMethodError.class, DeleteGalleryMessage.class, DownloadPostMessage.class, DownloadStatusMessage.class,
GalleryPageQueryMessage.class, GalleryRequestMessage.class, IdentityMessage.class, MaintainMessage.class, ResponseMessage.class, UpdateGalleryMessage.class})
public class CustomBean {
@Bean
public TelegramBot getTelegramBot(){
return new TelegramBot("5222939329:AAHa6l9ZuVVdNSDLPI_H-c8O_VgeOEw5plA");
}
}

View File

@ -14,9 +14,12 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration @Configuration
public class InterceptorConfiguration implements WebMvcConfigurer { public class InterceptorConfiguration implements WebMvcConfigurer {
@Resource
TaskHandlerInterceptor taskHandlerInterceptor; TaskHandlerInterceptor taskHandlerInterceptor;
public InterceptorConfiguration(TaskHandlerInterceptor taskHandlerInterceptor) {
this.taskHandlerInterceptor = taskHandlerInterceptor;
}
@Override @Override
public void addInterceptors(InterceptorRegistry registry) { public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getPersonalInterceptor()).addPathPatterns("/personal/**", "/remote/**"); registry.addInterceptor(getPersonalInterceptor()).addPathPatterns("/personal/**", "/remote/**");

View File

@ -0,0 +1,266 @@
package com.lion.lionwebsite.Configuration;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.annotations.DeleteProvider;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.UpdateProvider;
import org.apache.ibatis.cache.decorators.FifoCache;
import org.apache.ibatis.cache.decorators.LruCache;
import org.apache.ibatis.cache.decorators.SoftCache;
import org.apache.ibatis.cache.decorators.WeakCache;
import org.apache.ibatis.cache.impl.PerpetualCache;
import org.apache.ibatis.javassist.util.proxy.ProxyFactory;
import org.apache.ibatis.javassist.util.proxy.RuntimeSupport;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl;
import org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl;
import org.apache.ibatis.logging.log4j2.Log4j2Impl;
import org.apache.ibatis.logging.nologging.NoLoggingImpl;
import org.apache.ibatis.logging.slf4j.Slf4jImpl;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.reflection.TypeParameterResolver;
import org.apache.ibatis.scripting.defaults.RawLanguageDriver;
import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution;
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor;
import org.springframework.beans.factory.aot.BeanRegistrationExcludeFilter;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RegisteredBean;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportRuntimeHints;
import org.springframework.core.ResolvableType;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Configuration(proxyBeanMethods = false)
@ImportRuntimeHints(MyBatisNativeConfiguration.MyBaitsRuntimeHintsRegistrar.class)
public class MyBatisNativeConfiguration {
@Bean
MyBatisBeanFactoryInitializationAotProcessor myBatisBeanFactoryInitializationAotProcessor() {
return new MyBatisBeanFactoryInitializationAotProcessor();
}
@Bean
static MyBatisMapperFactoryBeanPostProcessor myBatisMapperFactoryBeanPostProcessor() {
return new MyBatisMapperFactoryBeanPostProcessor();
}
static class MyBaitsRuntimeHintsRegistrar implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
Stream.of(RawLanguageDriver.class,
XMLLanguageDriver.class,
RuntimeSupport.class,
ProxyFactory.class,
Slf4jImpl.class,
Log.class,
JakartaCommonsLoggingImpl.class,
Log4j2Impl.class,
Jdk14LoggingImpl.class,
StdOutImpl.class,
NoLoggingImpl.class,
SqlSessionFactory.class,
PerpetualCache.class,
FifoCache.class,
LruCache.class,
SoftCache.class,
WeakCache.class,
SqlSessionFactoryBean.class,
ArrayList.class,
HashMap.class,
TreeSet.class,
HashSet.class
).forEach(x -> hints.reflection().registerType(x, MemberCategory.values()));
Stream.of(
"org/apache/ibatis/builder/xml/*.dtd",
"org/apache/ibatis/builder/xml/*.xsd"
).forEach(hints.resources()::registerPattern);
}
}
static class MyBatisBeanFactoryInitializationAotProcessor
implements BeanFactoryInitializationAotProcessor, BeanRegistrationExcludeFilter {
private final Set<Class<?>> excludeClasses = new HashSet<>();
MyBatisBeanFactoryInitializationAotProcessor() {
excludeClasses.add(MapperScannerConfigurer.class);
}
@Override public boolean isExcludedFromAotProcessing(RegisteredBean registeredBean) {
return excludeClasses.contains(registeredBean.getBeanClass());
}
@Override
public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) {
String[] beanNames = beanFactory.getBeanNamesForType(MapperFactoryBean.class);
if (beanNames.length == 0) {
return null;
}
return (context, code) -> {
RuntimeHints hints = context.getRuntimeHints();
for (String beanName : beanNames) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName.substring(1));
PropertyValue mapperInterface = beanDefinition.getPropertyValues().getPropertyValue("mapperInterface");
if (mapperInterface != null && mapperInterface.getValue() != null) {
Class<?> mapperInterfaceType = (Class<?>) mapperInterface.getValue();
if (mapperInterfaceType != null) {
registerReflectionTypeIfNecessary(mapperInterfaceType, hints);
hints.proxies().registerJdkProxy(mapperInterfaceType);
hints.resources()
.registerPattern(mapperInterfaceType.getName().replace('.', '/').concat(".xml"));
registerMapperRelationships(mapperInterfaceType, hints);
}
}
}
};
}
private void registerMapperRelationships(Class<?> mapperInterfaceType, RuntimeHints hints) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(mapperInterfaceType);
for (Method method : methods) {
if (method.getDeclaringClass() != Object.class) {
ReflectionUtils.makeAccessible(method);
registerSqlProviderTypes(method, hints, SelectProvider.class, SelectProvider::value, SelectProvider::type);
registerSqlProviderTypes(method, hints, InsertProvider.class, InsertProvider::value, InsertProvider::type);
registerSqlProviderTypes(method, hints, UpdateProvider.class, UpdateProvider::value, UpdateProvider::type);
registerSqlProviderTypes(method, hints, DeleteProvider.class, DeleteProvider::value, DeleteProvider::type);
Class<?> returnType = MyBatisMapperTypeUtils.resolveReturnClass(mapperInterfaceType, method);
registerReflectionTypeIfNecessary(returnType, hints);
MyBatisMapperTypeUtils.resolveParameterClasses(mapperInterfaceType, method)
.forEach(x -> registerReflectionTypeIfNecessary(x, hints));
}
}
}
@SafeVarargs
private <T extends Annotation> void registerSqlProviderTypes(
Method method, RuntimeHints hints, Class<T> annotationType, Function<T, Class<?>>... providerTypeResolvers) {
for (T annotation : method.getAnnotationsByType(annotationType)) {
for (Function<T, Class<?>> providerTypeResolver : providerTypeResolvers) {
registerReflectionTypeIfNecessary(providerTypeResolver.apply(annotation), hints);
}
}
}
private void registerReflectionTypeIfNecessary(Class<?> type, RuntimeHints hints) {
if (!type.isPrimitive() && !type.getName().startsWith("java")) {
hints.reflection().registerType(type, MemberCategory.values());
}
}
}
static class MyBatisMapperTypeUtils {
private MyBatisMapperTypeUtils() {
// NOP
}
static Class<?> resolveReturnClass(Class<?> mapperInterface, Method method) {
Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, mapperInterface);
return typeToClass(resolvedReturnType, method.getReturnType());
}
static Set<Class<?>> resolveParameterClasses(Class<?> mapperInterface, Method method) {
return Stream.of(TypeParameterResolver.resolveParamTypes(method, mapperInterface))
.map(x -> typeToClass(x, x instanceof Class ? (Class<?>) x : Object.class)).collect(Collectors.toSet());
}
private static Class<?> typeToClass(Type src, Class<?> fallback) {
Class<?> result = null;
if (src instanceof Class<?>) {
if (((Class<?>) src).isArray()) {
result = ((Class<?>) src).getComponentType();
} else {
result = (Class<?>) src;
}
} else if (src instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) src;
int index = (parameterizedType.getRawType() instanceof Class
&& Map.class.isAssignableFrom((Class<?>) parameterizedType.getRawType())
&& parameterizedType.getActualTypeArguments().length > 1) ? 1 : 0;
Type actualType = parameterizedType.getActualTypeArguments()[index];
result = typeToClass(actualType, fallback);
}
if (result == null) {
result = fallback;
}
return result;
}
}
static class MyBatisMapperFactoryBeanPostProcessor implements MergedBeanDefinitionPostProcessor, BeanFactoryAware {
private static final org.apache.commons.logging.Log LOG = LogFactory.getLog(
MyBatisMapperFactoryBeanPostProcessor.class);
private static final String MAPPER_FACTORY_BEAN = "org.mybatis.spring.mapper.MapperFactoryBean";
private ConfigurableBeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = (ConfigurableBeanFactory) beanFactory;
}
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if (ClassUtils.isPresent(MAPPER_FACTORY_BEAN, this.beanFactory.getBeanClassLoader())) {
resolveMapperFactoryBeanTypeIfNecessary(beanDefinition);
}
}
private void resolveMapperFactoryBeanTypeIfNecessary(RootBeanDefinition beanDefinition) {
if (!beanDefinition.hasBeanClass() || !MapperFactoryBean.class.isAssignableFrom(beanDefinition.getBeanClass())) {
return;
}
if (beanDefinition.getResolvableType().hasUnresolvableGenerics()) {
Class<?> mapperInterface = getMapperInterface(beanDefinition);
if (mapperInterface != null) {
// Exposes a generic type information to context for prevent early initializing
beanDefinition
.setTargetType(ResolvableType.forClassWithGenerics(beanDefinition.getBeanClass(), mapperInterface));
}
}
}
private Class<?> getMapperInterface(RootBeanDefinition beanDefinition) {
try {
return (Class<?>) beanDefinition.getPropertyValues().get("mapperInterface");
}
catch (Exception e) {
LOG.debug("Fail getting mapper interface type.", e);
return null;
}
}
}
}

View File

@ -18,18 +18,21 @@ import java.util.List;
@RequestMapping("/GalleryManage") @RequestMapping("/GalleryManage")
@Slf4j @Slf4j
public class GalleryManageController { public class GalleryManageController {
@Resource
GalleryManageService galleryManageService; GalleryManageService galleryManageService;
@Resource
CollectService collectService; CollectService collectService;
@Resource
CustomUtil customUtil; CustomUtil customUtil;
@Resource
UserServiceImpl userService; UserServiceImpl userService;
public GalleryManageController(GalleryManageService galleryManageService, CollectService collectService, CustomUtil customUtil, UserServiceImpl userService) {
this.galleryManageService = galleryManageService;
this.collectService = collectService;
this.customUtil = customUtil;
this.userService = userService;
}
@PostMapping("") @PostMapping("")
public String create_task(String link, String targetResolution, String AuthCode, public String create_task(String link, String targetResolution, String AuthCode,
@RequestParam(value = "tags", required = false) List<Integer> tags, @RequestParam(value = "tags", required = false) List<Integer> tags,

View File

@ -1,28 +0,0 @@
package com.lion.lionwebsite.Controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class NavigationController {
@GetMapping("/personal/")
public String personal_index(){
return "self";
}
@GetMapping("/personal/mobile")
public String personal_mobile(){
return "selfMobile";
}
@GetMapping("/")
public String index(){
return "index";
}
@GetMapping("/mobile")
public String mobile(){
return "mobile";
}
}

View File

@ -23,12 +23,15 @@ import java.io.IOException;
@RequestMapping("/personal") @RequestMapping("/personal")
public class PersonalController { public class PersonalController {
@Resource
PersonalServiceImpl personalService; PersonalServiceImpl personalService;
@Resource
LocalServiceImpl localService; LocalServiceImpl localService;
public PersonalController(PersonalServiceImpl personalService, LocalServiceImpl localService) {
this.personalService = personalService;
this.localService = localService;
}
@GetMapping("/sub/self") @GetMapping("/sub/self")
public void sub(HttpServletResponse response, HttpServletRequest request){ public void sub(HttpServletResponse response, HttpServletRequest request){
FileDownload.export(request, response, "sub/sub.txt"); FileDownload.export(request, response, "sub/sub.txt");

View File

@ -4,9 +4,8 @@ package com.lion.lionwebsite.Controller;
import com.lion.lionwebsite.Domain.User; import com.lion.lionwebsite.Domain.User;
import com.lion.lionwebsite.Service.PublicServiceImpl; import com.lion.lionwebsite.Service.PublicServiceImpl;
import com.lion.lionwebsite.Service.RemoteService; import com.lion.lionwebsite.Service.RemoteService;
import com.lion.lionwebsite.Util.FileDownload; import com.lion.lionwebsite.Service.SubService;
import com.lion.lionwebsite.Util.Response; import com.lion.lionwebsite.Util.Response;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -23,12 +22,18 @@ public class PublicController {
final List<String> black_share_codes = new LinkedList<>(); final List<String> black_share_codes = new LinkedList<>();
@Resource
PublicServiceImpl publicService; PublicServiceImpl publicService;
@Resource
RemoteService remoteService; RemoteService remoteService;
SubService subService;
public PublicController(PublicServiceImpl publicService, RemoteService remoteService, SubService subService) {
this.publicService = publicService;
this.remoteService = remoteService;
this.subService = subService;
}
@GetMapping("/ip") @GetMapping("/ip")
public void ip(HttpServletRequest request, String auth, HttpServletResponse response) throws IOException { public void ip(HttpServletRequest request, String auth, HttpServletResponse response) throws IOException {
String ip = request.getHeader("X-Forwarded-For"); String ip = request.getHeader("X-Forwarded-For");
@ -42,31 +47,19 @@ public class PublicController {
response.getOutputStream().write(ip.getBytes(StandardCharsets.UTF_8)); response.getOutputStream().write(ip.getBytes(StandardCharsets.UTF_8));
} }
@GetMapping("/sub/{client}/{AuthCode}") @GetMapping("/sub/{client}/{key}")
public void publicSub(@PathVariable("AuthCode") String AuthCode, public void publicSub(@PathVariable("key") String key,
@PathVariable("client") String client, @PathVariable("client") String client,
HttpServletResponse response, HttpServletResponse response,
HttpServletRequest request) throws IOException { HttpServletRequest request) {
subService.updateSub(response, request, client, key);
if(AuthCode == null || client == null || !AuthCode.equals("covid"))
return;
switch (client){
case "v2ray" -> FileDownload.export(request, response, "sub/DouNaiV2ray.txt");
case "clash" -> FileDownload.export(request, response, "sub/DouNaiClash.txt");
default -> response.getOutputStream().write("client error".getBytes(StandardCharsets.UTF_8));
}
} }
@GetMapping("/GetFile/{path}") @GetMapping("/GetFile/{path}")
public void getFile(HttpServletRequest request, HttpServletResponse response, String ShareCode, @PathVariable("path") String path) throws IOException { public void getFile(HttpServletRequest request, HttpServletResponse response, String ShareCode, @PathVariable("path") String path) throws IOException {
synchronized (black_share_codes) { synchronized (black_share_codes) {
if (black_share_codes.contains(ShareCode)) { if (black_share_codes.contains(ShareCode))
String ip = request.getHeader("X-Forwarded-For") == null ? request.getRemoteAddr() : request.getHeader("X-Forwarded-For");
log.info("dispatch request ip:{} file:{}", ip, path);
return; return;
}
} }
log.info("ShareCode:{}", ShareCode); log.info("ShareCode:{}", ShareCode);

View File

@ -12,9 +12,11 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/query") @RequestMapping("/query")
public class QueryController { public class QueryController {
@Resource
QueryService queryService; QueryService queryService;
public QueryController(QueryService queryService) {
this.queryService = queryService;
}
@GetMapping("") @GetMapping("")
public String query(String keyword, String prev, String next){ public String query(String keyword, String prev, String next){

View File

@ -0,0 +1,39 @@
package com.lion.lionwebsite.Controller;
import com.lion.lionwebsite.Service.SubService;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/personal/subBind/")
public class SubController {
SubService subService;
public SubController(SubService subService) {
this.subService = subService;
}
@PostMapping("")
public String addSubBind(String user){
return subService.insertSubBind(user);
}
@PutMapping("")
public String resetKey(String user){
return subService.resetKey(user);
}
@GetMapping("all")
public String getAllSubBind(){
return subService.selectAllSubBind();
}
@GetMapping("allRecord")
public String getAllSubUpdateRecord(){
return subService.SelectAllSubUpdateRecord();
}
@DeleteMapping("")
public String deleteSubBind(String user){
return subService.deleteSubBind(user);
}
}

View File

@ -9,9 +9,12 @@ import org.springframework.web.bind.annotation.*;
@RequestMapping("/GalleryManage") @RequestMapping("/GalleryManage")
public class TagController { public class TagController {
@Resource
TagService tagService; TagService tagService;
public TagController(TagService tagService) {
this.tagService = tagService;
}
@PostMapping("/tag") @PostMapping("/tag")
public String createTag(String tag){ public String createTag(String tag){
return tagService.createTag(tag); return tagService.createTag(tag);

View File

@ -8,9 +8,12 @@ import org.springframework.web.bind.annotation.*;
@RestController @RestController
@RequestMapping("/personal/user") @RequestMapping("/personal/user")
public class UserController { public class UserController {
@Resource
UserServiceImpl userService; UserServiceImpl userService;
public UserController(UserServiceImpl userService) {
this.userService = userService;
}
@GetMapping("") @GetMapping("")
public String getAllUser(){ public String getAllUser(){
return userService.getAllUser(); return userService.getAllUser();

View File

@ -28,7 +28,7 @@ public interface GalleryMapper {
@Select("select * from gallery where status in ('已提交', '下载中')") @Select("select * from gallery where status in ('已提交', '下载中')")
Gallery[] selectUnDoneGalleries(); Gallery[] selectUnDoneGalleries();
@Select("select * from gallery") @Select("select * from gallery order by createTime")
Gallery[] selectAllGallery(); Gallery[] selectAllGallery();
@Select("select * from gallery where name like #{name} limit 1") @Select("select * from gallery where name like #{name} limit 1")

View File

@ -0,0 +1,43 @@
package com.lion.lionwebsite.Dao;
import com.lion.lionwebsite.Domain.SubBind;
import com.lion.lionwebsite.Domain.SubUpdateRecord;
import org.apache.ibatis.annotations.*;
import java.util.ArrayList;
@Mapper
public interface SubMapper {
@Insert("insert into sub_bind values (#{key}, #{user})")
void insertSubBind(SubBind subBind);
@Select("select * from sub_bind")
ArrayList<SubBind> selectAllSubBind();
@Select("select * from sub_bind where key=#{key}")
SubBind selectSubBind(String key);
@Select("select count(key) from sub_bind where key=#{key}")
boolean selectSubBindExist(String key);
@Select("select count(user) from sub_update_record where user=#{user}")
Integer selectUpdateRecordCount(String user);
@Select("select min(id) from sub_update_record where user=#{user}")
Integer selectMinUpdateRecordId(String user);
@Delete("delete from sub_bind where user=#{user}")
void deleteSubBind(String user);
@Insert("insert into sub_update_record (user, ip, UA, time, location) values (#{user}, #{ip}, #{UA}, #{time}, #{location})")
void insertSubUpdateRecord(SubUpdateRecord subUpdateRecord);
@Select("select * from sub_update_record")
ArrayList<SubUpdateRecord> selectAllSubUpdateRecord();
@Delete("delete from sub_update_record where user=#{user}")
void deleteSubUpdateRecord(String user);
@Delete("delete from sub_update_record where id=#{id}")
void deleteSubUpdateRecordById(int id);
}

View File

@ -15,6 +15,8 @@ public class GalleryTask {
public static byte COMPRESS_COMPLETE = 4; public static byte COMPRESS_COMPLETE = 4;
public static byte COMPRESSING = 5;
public static byte DOWNLOAD_ALL = 3; public static byte DOWNLOAD_ALL = 3;
public static byte DOWNLOAD_PREVIEW = 2; public static byte DOWNLOAD_PREVIEW = 2;

View File

@ -0,0 +1,13 @@
package com.lion.lionwebsite.Domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SubBind {
String key;
String user;
}

View File

@ -0,0 +1,19 @@
package com.lion.lionwebsite.Domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SubUpdateRecord {
int id;
String user;
String ip;
String UA;
Date time;
String location;
}

View File

@ -2,7 +2,6 @@ package com.lion.lionwebsite.Filter;
import com.lion.lionwebsite.Dao.UserMapper; import com.lion.lionwebsite.Dao.UserMapper;
import com.lion.lionwebsite.Util.CustomUtil; import com.lion.lionwebsite.Util.CustomUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.*; import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter; import jakarta.servlet.annotation.WebFilter;
@ -11,9 +10,11 @@ import java.io.IOException;
@WebFilter(filterName = "AccessFilter", urlPatterns = {"/validate"}) @WebFilter(filterName = "AccessFilter", urlPatterns = {"/validate"})
public class AccessFilter implements Filter { public class AccessFilter implements Filter {
@Resource
UserMapper userMapper; UserMapper userMapper;
public AccessFilter(UserMapper userMapper) {
this.userMapper = userMapper;
}
@Override @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

View File

@ -15,11 +15,14 @@ public class TaskHandlerInterceptor implements HandlerInterceptor {
UserMapper userMapper; UserMapper userMapper;
String[] AuthCodes = null; String[] AuthCodes = null;
public TaskHandlerInterceptor(UserMapper userMapper) {
this.userMapper = userMapper;
AuthCodes = userMapper.selectAllAuthCode();
}
@Override @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
if(AuthCodes == null)
AuthCodes = userMapper.selectAllAuthCode();
String auth = request.getParameter("AuthCode"); String auth = request.getParameter("AuthCode");
if(auth != null) if(auth != null)

View File

@ -1,5 +1,8 @@
package com.lion.lionwebsite.Message; package com.lion.lionwebsite.Message;
import lombok.Data;
@Data
public class AbstractMessage { public class AbstractMessage {
public static final byte DOWNLOAD_POST_MESSAGE = 1; public static final byte DOWNLOAD_POST_MESSAGE = 1;
@ -15,6 +18,9 @@ public class AbstractMessage {
public static final byte GALLERY_PAGE_QUERY_MESSAGE = 5; public static final byte GALLERY_PAGE_QUERY_MESSAGE = 5;
public static final byte IDENTITY_MESSAGE = 6; public static final byte IDENTITY_MESSAGE = 6;
public static final byte MAINTAIN_MESSAGE = 7;
public static final byte GALLERY_REQUEST_MESSAGE = 101; public static final byte GALLERY_REQUEST_MESSAGE = 101;
public byte messageType; public byte messageType;

View File

@ -1,10 +1,15 @@
package com.lion.lionwebsite.Message; package com.lion.lionwebsite.Message;
import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
@Data @Data
@AllArgsConstructor
@NoArgsConstructor
public class IdentityMessage extends AbstractMessage{ public class IdentityMessage extends AbstractMessage{
{ {
messageType = IDENTITY_MESSAGE; messageType = IDENTITY_MESSAGE;
} }
String identity;
} }

View File

@ -0,0 +1,7 @@
package com.lion.lionwebsite.Message;
public class MaintainMessage extends AbstractMessage{
{
messageType = MAINTAIN_MESSAGE;
}
}

View File

@ -45,6 +45,7 @@ public class MessageCodec extends ByteToMessageCodec<AbstractMessage> {
case AbstractMessage.DELETE_GALLERY_MESSAGE -> objectMapper.readValue(metadata, DeleteGalleryMessage.class); case AbstractMessage.DELETE_GALLERY_MESSAGE -> objectMapper.readValue(metadata, DeleteGalleryMessage.class);
case AbstractMessage.GALLERY_PAGE_QUERY_MESSAGE -> objectMapper.readValue(metadata, GalleryPageQueryMessage.class); case AbstractMessage.GALLERY_PAGE_QUERY_MESSAGE -> objectMapper.readValue(metadata, GalleryPageQueryMessage.class);
case AbstractMessage.IDENTITY_MESSAGE -> objectMapper.readValue(metadata, IdentityMessage.class); case AbstractMessage.IDENTITY_MESSAGE -> objectMapper.readValue(metadata, IdentityMessage.class);
case AbstractMessage.MAINTAIN_MESSAGE -> objectMapper.readValue(metadata, MaintainMessage.class);
default -> null; default -> null;
}; };

View File

@ -2,16 +2,18 @@ package com.lion.lionwebsite.Service;
import com.lion.lionwebsite.Dao.CollectMapper; import com.lion.lionwebsite.Dao.CollectMapper;
import com.lion.lionwebsite.Util.Response; import com.lion.lionwebsite.Util.Response;
import jakarta.annotation.Resource;
import lombok.Data; import lombok.Data;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service @Service
@Data @Data
public class CollectService { public class CollectService {
@Resource
CollectMapper collectMapper; CollectMapper collectMapper;
public CollectService(CollectMapper collectMapper){
this.collectMapper = collectMapper;
}
public String collectGallery(int gid, int collector){ public String collectGallery(int gid, int collector){
Response response = Response.generateResponse(); Response response = Response.generateResponse();
if(collectMapper.isCollect(gid, collector) == 0) { //没有收藏 if(collectMapper.isCollect(gid, collector) == 0) { //没有收藏

View File

@ -11,12 +11,10 @@ import com.lion.lionwebsite.Util.FileDownload;
import com.lion.lionwebsite.Util.GalleryUtil; import com.lion.lionwebsite.Util.GalleryUtil;
import com.lion.lionwebsite.Util.Response; import com.lion.lionwebsite.Util.Response;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.Data; import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.io.*; import java.io.*;
@ -30,11 +28,10 @@ import static com.lion.lionwebsite.Util.CustomUtil.fourZeroFour;
@Service @Service
@Data @Data
@Slf4j @Slf4j
@ConfigurationProperties(prefix = "gallery-manage-service")
public class GalleryManageService { public class GalleryManageService {
String TargetPath; String TargetPath = "/root/gallery/";
int cacheSize; int cacheSize = 100;
Map<Integer, String> gid2name_cache = new HashMap<>(); Map<Integer, String> gid2name_cache = new HashMap<>();
@ -42,30 +39,37 @@ public class GalleryManageService {
Map<String, String> page2pageNameCache = new HashMap<>(); Map<String, String> page2pageNameCache = new HashMap<>();
@Resource
GalleryMapper galleryMapper; GalleryMapper galleryMapper;
@Resource
CollectMapper collectMapper; CollectMapper collectMapper;
@Resource
CustomConfigurationMapper configurationMapper; CustomConfigurationMapper configurationMapper;
@Resource
UserMapper userMapper; UserMapper userMapper;
@Resource
ShareFileMapper shareFileMapper; ShareFileMapper shareFileMapper;
@Resource
TagMapper tagMapper; TagMapper tagMapper;
@Resource
PageNameCacheMapper pageNameCacheMapper; PageNameCacheMapper pageNameCacheMapper;
@Resource
RemoteService remoteService; RemoteService remoteService;
PushService pushService;
public GalleryManageService(GalleryMapper galleryMapper, CollectMapper collectMapper, CustomConfigurationMapper configurationMapper, UserMapper userMapper, ShareFileMapper shareFileMapper,
TagMapper tagMapper, PageNameCacheMapper pageNameCacheMapper, RemoteService remoteService, PushService pushService){
this.galleryMapper = galleryMapper;
this.collectMapper = collectMapper;
this.configurationMapper = configurationMapper;
this.userMapper = userMapper;
this.shareFileMapper = shareFileMapper;
this.tagMapper = tagMapper;
this.pageNameCacheMapper = pageNameCacheMapper;
this.remoteService = remoteService;
this.pushService = pushService;
}
/** /**
* 创建任务 * 创建任务
* @param link 任务链接 * @param link 任务链接
@ -75,15 +79,20 @@ public class GalleryManageService {
*/ */
public String createTask(String link, String targetResolution, String AuthCode, List<Integer> tidS, byte mode){ public String createTask(String link, String targetResolution, String AuthCode, List<Integer> tidS, byte mode){
Response response = Response.generateResponse(); Response response = Response.generateResponse();
User user = userMapper.selectUserByAuthCode(AuthCode);
// return Response._failure("调试中,请勿提交任务"); // return Response._failure("调试中,请勿提交任务");
if(remoteService.isDead()) if(remoteService.isDead()) {
return Response._failure("节点挂了,找狮子处理"); response.failure("节点挂了,找狮子处理");
pushService.taskCreateReport(user.getUsername(), link, response);
return response.toJSONString();
}
int gid; int gid;
try { try {
gid = Integer.parseInt(link.split("/")[4]); gid = Integer.parseInt(link.split("/")[4]);
}catch (NumberFormatException e){ }catch (NumberFormatException e){
response.failure("链接错误"); response.failure("链接错误");
pushService.taskCreateReport(user.getUsername(), link, response);
return response.toJSONString(); return response.toJSONString();
} }
Gallery gallery; Gallery gallery;
@ -91,6 +100,7 @@ public class GalleryManageService {
//判断数据库中是否有这个任务有则返回状态 //判断数据库中是否有这个任务有则返回状态
if((gallery = galleryMapper.selectGalleryByGid(gid)) != null){ if((gallery = galleryMapper.selectGalleryByGid(gid)) != null){
response.failure("任务队列已有此任务,任务状态: " + gallery.getStatus() + " 请点击查找任务"); response.failure("任务队列已有此任务,任务状态: " + gallery.getStatus() + " 请点击查找任务");
pushService.taskCreateReport(user.getUsername(), link, response);
return response.toJSONString(); return response.toJSONString();
} }
@ -99,28 +109,34 @@ public class GalleryManageService {
gallery = GalleryUtil.parse(link, true, targetResolution); gallery = GalleryUtil.parse(link, true, targetResolution);
if(gallery == null){ if(gallery == null){
log.error("创建任务: {},解析失败", link); log.error("创建任务: {},解析失败", link);
return Response._failure("任务解析失败,未知原因,请检查链接是否正常"); response.failure("任务解析失败,未知原因,请检查链接是否正常");
pushService.taskCreateReport(user.getUsername(), link, response);
return response.toJSONString();
}else{ }else{
log.info("创建任务: {} 目标分辨率:{}", link, targetResolution); log.info("创建任务: {} 目标分辨率:{}", link, targetResolution);
if(remoteService.addGalleryToQueue(gallery, mode) != 0){ if(remoteService.addGalleryToQueue(gallery, mode) != 0){
log.error("传送任务{}失败, 未知原因", gallery.getName()); log.error("传送任务{}失败, 未知原因", gallery.getName());
return Response._failure("任务传送失败,未知原因"); response.failure("任务传送失败,未知原因");
pushService.taskCreateReport(user.getUsername(), link, response);
return response.toJSONString();
} }
} }
}catch (ResolutionNotMatchException e){ }catch (ResolutionNotMatchException e){
e.printStackTrace(); e.printStackTrace();
response.failure("提交失败,分辨率不存在"); response.failure("提交失败,分辨率不存在");
pushService.taskCreateReport(user.getUsername(), link, response);
return response.toJSONString(); return response.toJSONString();
}catch (IOException e){ }catch (IOException e){
e.printStackTrace(); e.printStackTrace();
response.failure("IO错误可能是网络波动"); response.failure("IO错误可能是网络波动");
pushService.taskCreateReport(user.getUsername(), link, response);
return response.toJSONString(); return response.toJSONString();
} }
//处理下载结果将任务插入数据库并且更新每周用量 //处理下载结果将任务插入数据库并且更新每周用量
if(gallery.getStatus().equals("已提交")) { if(gallery.getStatus().equals("已提交")) {
response.success(gallery.toString()); response.success(gallery.toString());
gallery.setDownloader(userMapper.selectUserByAuthCode(AuthCode).getId()); gallery.setDownloader(user.getId());
gallery.setMode(mode); gallery.setMode(mode);
galleryMapper.insertGallery(gallery); galleryMapper.insertGallery(gallery);
@ -136,6 +152,7 @@ public class GalleryManageService {
response.failure("提交失败,未知原因"); response.failure("提交失败,未知原因");
galleryMapper.deleteGalleryByGid(gallery.getGid()); galleryMapper.deleteGalleryByGid(gallery.getGid());
} }
pushService.taskCreateReport(user.getUsername(), link, response);
return response.toJSONString(); return response.toJSONString();
} }

View File

@ -6,14 +6,12 @@ import com.lion.lionwebsite.Dao.ShareFileMapper;
import com.lion.lionwebsite.Domain.CustomConfiguration; import com.lion.lionwebsite.Domain.CustomConfiguration;
import com.lion.lionwebsite.Domain.ShareFile; import com.lion.lionwebsite.Domain.ShareFile;
import com.lion.lionwebsite.Util.CustomUtil; import com.lion.lionwebsite.Util.CustomUtil;
import jakarta.annotation.Resource;
import lombok.Data; import lombok.Data;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.client.HttpClients;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -29,22 +27,26 @@ import java.util.*;
import static java.nio.file.FileVisitResult.CONTINUE; import static java.nio.file.FileVisitResult.CONTINUE;
@Service @Service
@ConfigurationProperties(prefix = "local-service")
@Data @Data
public class LocalServiceImpl{ public class LocalServiceImpl{
String fires; String fires = "https://api.dler.io/sub?target=clash&new_name=true&url=https%3A%2F%2Ffast.losadhwselfff2332dasd.xyz%2Flink%2Fz0pfwyTvC5naXkbb%3Fclash%3D1&insert=false&config=https%3A%2F%2Fraw.githubusercontent.com%2FACL4SSR%2FACL4SSR%2Fmaster%2FClash%2Fconfig%2FACL4SSR_Online.ini";
String DouNaiClash;
String DouNaiV2ray; String DouNaiClash = "https://aaaa.gay/link/X7zEqkIx5gtIGugO?client=clashmeta";
String DouNaiV2ray = "https://aaaa.gay/link/X7zEqkIx5gtIGugO?client=v2";
@Resource
CustomConfigurationMapper configurationMapper; CustomConfigurationMapper configurationMapper;
@Resource
ShareFileMapper shareFIleMapper; ShareFileMapper shareFIleMapper;
@Resource
GalleryMapper galleryMapper; GalleryMapper galleryMapper;
public LocalServiceImpl(CustomConfigurationMapper configurationMapper, ShareFileMapper shareFileMapper, GalleryMapper galleryMapper){
this.shareFIleMapper = shareFileMapper;
this.configurationMapper = configurationMapper;
this.galleryMapper = galleryMapper;
}
/** /**
* 每周周一四点重置额度 * 每周周一四点重置额度
*/ */

View File

@ -43,7 +43,6 @@ import java.util.concurrent.Executors;
@Service @Service
@Data @Data
@ConfigurationProperties(prefix = "personal-service")
@Slf4j @Slf4j
public class PersonalServiceImpl{ public class PersonalServiceImpl{
@Resource @Resource
@ -58,13 +57,17 @@ public class PersonalServiceImpl{
@Resource @Resource
TaskHandlerInterceptor taskHandlerInterceptor; TaskHandlerInterceptor taskHandlerInterceptor;
String StoragePath; String StoragePath = "/storage/";
DateTimeFormatter dateTimeFormatter = CustomUtil.dateTimeFormatter(); DateTimeFormatter dateTimeFormatter = CustomUtil.dateTimeFormatter();
ExecutorService compressThreadPool; ExecutorService compressThreadPool;
PersonalServiceImpl(){ public PersonalServiceImpl(CustomConfigurationMapper configurationMapper, UserMapper userMapper, ShareFileMapper shareFileMapper, TaskHandlerInterceptor taskHandlerInterceptor){
this.configurationMapper = configurationMapper;
this.userMapper = userMapper;
this.shareFileMapper = shareFileMapper;
this.taskHandlerInterceptor = taskHandlerInterceptor;
compressThreadPool = Executors.newFixedThreadPool(1); compressThreadPool = Executors.newFixedThreadPool(1);
} }

View File

@ -37,7 +37,7 @@ public class PublicServiceImpl {
CustomConfigurationMapper configurationMapper; CustomConfigurationMapper configurationMapper;
@Resource @Resource
ShareFileMapper shareFIleMapper; ShareFileMapper shareFileMapper;
@Resource @Resource
UserMapper userMapper; UserMapper userMapper;
@ -45,6 +45,13 @@ public class PublicServiceImpl {
@Resource @Resource
TaskHandlerInterceptor taskHandlerInterceptor; TaskHandlerInterceptor taskHandlerInterceptor;
public PublicServiceImpl(CustomConfigurationMapper configurationMapper, ShareFileMapper shareFileMapper, UserMapper userMapper, TaskHandlerInterceptor taskHandlerInterceptor) {
this.configurationMapper = configurationMapper;
this.shareFileMapper = shareFileMapper;
this.userMapper = userMapper;
this.taskHandlerInterceptor = taskHandlerInterceptor;
}
/** /**
* 记录家里ip地址 * 记录家里ip地址
* @param ip ip地址 * @param ip ip地址
@ -68,7 +75,7 @@ public class PublicServiceImpl {
if(ShareCode == null) { if(ShareCode == null) {
response.failure("ShareCode invalid"); response.failure("ShareCode invalid");
} else { } else {
ShareFile shareFile = shareFIleMapper.selectShareFileByShareCode(ShareCode); ShareFile shareFile = shareFileMapper.selectShareFileByShareCode(ShareCode);
Calendar ExpireTime = Calendar.getInstance(); Calendar ExpireTime = Calendar.getInstance();
Calendar now = Calendar.getInstance(); Calendar now = Calendar.getInstance();
@ -78,7 +85,7 @@ public class PublicServiceImpl {
FileDownload.export(httpRequest, httpResponse, shareFile.getFilePath()); FileDownload.export(httpRequest, httpResponse, shareFile.getFilePath());
return true; return true;
} else { } else {
shareFIleMapper.deleteShareFile(shareFile.getShareCode()); shareFileMapper.deleteShareFile(shareFile.getShareCode());
response.failure("ShareCode is expired or File is not exist"); response.failure("ShareCode is expired or File is not exist");
} }
} else } else

View File

@ -0,0 +1,51 @@
package com.lion.lionwebsite.Service;
import com.lion.lionwebsite.Domain.Gallery;
import com.lion.lionwebsite.Util.Response;
import com.pengrad.telegrambot.TelegramBot;
import com.pengrad.telegrambot.UpdatesListener;
import com.pengrad.telegrambot.model.Update;
import com.pengrad.telegrambot.request.SendMessage;
import jakarta.annotation.Resource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class PushService {
long self = 686839482;
@Resource
TelegramBot bot;
public PushService(TelegramBot bot) {
this.bot = bot;
}
public void taskCreateReport(String username, String link, Response response){
if(response.isSuccess())
sendToMe(String.format("用户%s提交下载%s", username, link));
else
sendToMe(String.format("用户%s提交下载%s , 下载失败:%s", username, link, response.get("data")));
}
public void downloadComplete(Gallery gallery){
sendToMe(gallery.getLink() + " 下载完成");
}
public void storageNodeOnline(){
sendToMe("存储节点上线");
}
public void storageNodeOffline(){
sendToMe("存储节点掉线");
}
public void sendToMe(String text){
System.out.println(text);
SendMessage sendMessage = new SendMessage(self, text);
bot.execute(sendMessage);
}
}

View File

@ -14,10 +14,8 @@ import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.logging.LoggingHandler; import io.netty.handler.logging.LoggingHandler;
import io.netty.util.concurrent.DefaultPromise; import io.netty.util.concurrent.DefaultPromise;
import io.netty.util.concurrent.Promise; import io.netty.util.concurrent.Promise;
import jakarta.annotation.Resource;
import lombok.Data; import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.io.File; import java.io.File;
@ -37,7 +35,6 @@ import java.util.concurrent.atomic.AtomicInteger;
@Service @Service
@Data @Data
@Slf4j @Slf4j
@ConfigurationProperties(prefix = "remote-service")
public class RemoteService { public class RemoteService {
ChannelFuture channelFuture; ChannelFuture channelFuture;
@ -48,11 +45,10 @@ public class RemoteService {
short port = 26321; short port = 26321;
String storagePath;
@Resource
GalleryMapper galleryMapper; GalleryMapper galleryMapper;
PushService pushService;
HashMap<Integer, Promise<AbstractMessage>> promiseHashMap; HashMap<Integer, Promise<AbstractMessage>> promiseHashMap;
EventLoop eventLoopGroup; EventLoop eventLoopGroup;
@ -63,7 +59,9 @@ public class RemoteService {
AtomicInteger atomicInteger; AtomicInteger atomicInteger;
public RemoteService(){ public RemoteService(GalleryMapper galleryMapper, PushService pushService){
this.galleryMapper = galleryMapper;
this.pushService = pushService;
atomicInteger = new AtomicInteger(0); atomicInteger = new AtomicInteger(0);
eventLoopGroup = new DefaultEventLoop(); eventLoopGroup = new DefaultEventLoop();
downloadThread = Executors.newCachedThreadPool(); downloadThread = Executors.newCachedThreadPool();
@ -83,17 +81,21 @@ public class RemoteService {
.handler(new ChannelInitializer<NioSocketChannel>() { .handler(new ChannelInitializer<NioSocketChannel>() {
@Override @Override
protected void initChannel(NioSocketChannel channel){ protected void initChannel(NioSocketChannel channel){
channel.pipeline().addLast(new LengthFieldBasedFrameDecoder(1024, 1, 4)); channel.pipeline().addLast(new LengthFieldBasedFrameDecoder(100000000, 1, 4));
channel.pipeline().addLast(new MessageCodec()); channel.pipeline().addLast(new MessageCodec());
channel.pipeline().addLast(new LoggingHandler()); channel.pipeline().addLast(new LoggingHandler());
channel.pipeline().addLast(new MyChannelInboundHandlerAdapter()); channel.pipeline().addLast(new MyChannelInboundHandlerAdapter());
} }
}).connect(new InetSocketAddress(ip, port)).sync(); }).connect(new InetSocketAddress(ip, port)).sync();
log.info("connect success"); log.info("connect success");
if(pushService != null)
pushService.storageNodeOnline();
channel = channelFuture.channel(); channel = channelFuture.channel();
channel.writeAndFlush(new IdentityMessage()); channel.writeAndFlush(new IdentityMessage("lionwebsite"));
return true; return true;
}catch (Exception e){ }catch (Exception e){
e.printStackTrace();
log.info("connect node failed, wait for node back online"); log.info("connect node failed, wait for node back online");
return false; return false;
} }
@ -149,7 +151,6 @@ public class RemoteService {
} }
public byte cachePreview(String galleryName, short page, File file){ public byte cachePreview(String galleryName, short page, File file){
File parentFile = file.getParentFile(); File parentFile = file.getParentFile();
if(!parentFile.isDirectory()) if(!parentFile.isDirectory())
if(parentFile.mkdirs()) if(parentFile.mkdirs())
@ -289,25 +290,31 @@ public class RemoteService {
public void channelRead(ChannelHandlerContext ctx, Object msg) { public void channelRead(ChannelHandlerContext ctx, Object msg) {
//如果不是响应信息或者响应信息为失败则打印 //如果不是响应信息或者响应信息为失败则打印
if(!(msg instanceof ResponseMessage rm) || rm.getResult() != 0) if(!(msg instanceof ResponseMessage rm) || rm.getResult() != 0)
System.out.println(msg); if(! (msg instanceof MaintainMessage))
System.out.println(msg);
//下载状态 //下载状态
if(msg instanceof DownloadStatusMessage dsm){ if(msg instanceof DownloadStatusMessage dsm){
GalleryTask[] galleryTasks = dsm.getGalleryTasks(); GalleryTask[] galleryTasks = dsm.getGalleryTasks();
for (GalleryTask galleryTask : galleryTasks) { for (GalleryTask galleryTask : galleryTasks) {
Gallery gallery = galleryMapper.selectGalleryByGid(galleryTask.getGid()); Gallery gallery = galleryMapper.selectGalleryByGid(galleryTask.getGid());
if(galleryTask.getStatus() == GalleryTask.DOWNLOAD_COMPLETE){ gallery.setProceeding(galleryTask.getProceeding());
if(!gallery.getName().equals(galleryTask.getName()) && galleryTask.getName() != null)
gallery.setName(galleryTask.getName());
if(galleryTask.getStatus() == GalleryTask.COMPRESS_COMPLETE) {
gallery.setStatus("下载完成"); gallery.setStatus("下载完成");
gallery.setProceeding(galleryTask.getProceeding()); pushService.downloadComplete(gallery);
galleryMapper.updateGallery(gallery);
}else if(galleryTask.getProceeding() != 0){
gallery.setStatus("下载中");
gallery.setProceeding(galleryTask.getProceeding());
if(!gallery.getName().equals(galleryTask.getName()))
gallery.setName(galleryTask.getName());
galleryMapper.updateGallery(gallery);
log.info(gallery.getName() + "下载进度:" + gallery.getProceeding() + "/" + gallery.getPages());
} }
else if(galleryTask.getStatus() == GalleryTask.COMPRESSING)
gallery.setStatus("压缩中");
else if(galleryTask.getProceeding() != 0)
gallery.setStatus("下载中");
log.info(gallery.getName() + "下载进度:" + gallery.getProceeding() + "/" + gallery.getPages());
galleryMapper.updateGallery(gallery);
} }
} }
else if(msg instanceof ResponseMessage rsm) else if(msg instanceof ResponseMessage rsm)
@ -318,8 +325,11 @@ public class RemoteService {
@Override @Override
public void channelUnregistered(ChannelHandlerContext ctx) { public void channelUnregistered(ChannelHandlerContext ctx) {
System.out.println(ctx.channel());
System.out.println(channel);
if(ctx.channel() != null && ctx.channel().remoteAddress().toString().equals(channel.remoteAddress().toString())){ if(ctx.channel() != null && ctx.channel().remoteAddress().toString().equals(channel.remoteAddress().toString())){
System.out.println("activate monitor thread, waiting for node back online"); System.out.println("activate monitor thread, waiting for node back online");
pushService.storageNodeOffline();
monitor = new Thread(RemoteService.this::monitorFunc); monitor = new Thread(RemoteService.this::monitorFunc);
monitor.start(); monitor.start();
} }

View File

@ -0,0 +1,132 @@
package com.lion.lionwebsite.Service;
import cn.hutool.core.util.RandomUtil;
import com.lion.lionwebsite.Dao.SubMapper;
import com.lion.lionwebsite.Domain.SubBind;
import com.lion.lionwebsite.Domain.SubUpdateRecord;
import com.lion.lionwebsite.Util.CustomUtil;
import com.lion.lionwebsite.Util.FileDownload;
import com.lion.lionwebsite.Util.Response;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
@Service
public class SubService {
SubMapper subMapper;
byte[] vIndex;
String dbPath = "ip2region.xdb";
public SubService(SubMapper subMapper) {
this.subMapper = subMapper;
try {
vIndex = Searcher.loadVectorIndexFromFile(dbPath);
}catch (Exception e){
System.out.printf("failed to load vector index from `%s`: %s\n", dbPath, e);
}
}
public String insertSubBind(String user){
Response response = Response.generateResponse();
String key = RandomUtil.randomString(8);
while (subMapper.selectSubBindExist(key))
key = RandomUtil.randomString(8);
SubBind subBind = new SubBind(key, user);
subMapper.insertSubBind(subBind);
return response.success("添加成功").toJSONString();
}
public String resetKey(String user){
Response response = Response.generateResponse();
subMapper.deleteSubBind(user);
subMapper.deleteSubUpdateRecord(user);
String key = RandomUtil.randomString(8);
while (subMapper.selectSubBindExist(key))
key = RandomUtil.randomString(8);
SubBind subBind = new SubBind(key, user);
subMapper.insertSubBind(subBind);
return response.success().toJSONString();
}
public String selectAllSubBind(){
Response response = Response.generateResponse();
ArrayList<SubBind> subBinds = subMapper.selectAllSubBind();
return response.success(CustomUtil.objectMapper.valueToTree(subBinds)).toJSONString();
}
public String SelectAllSubUpdateRecord(){
Response response = Response.generateResponse();
ArrayList<SubUpdateRecord> subUpdateRecords = subMapper.selectAllSubUpdateRecord();
return response.success(CustomUtil.objectMapper.valueToTree(subUpdateRecords)).toJSONString();
}
public void updateSub(HttpServletResponse response, HttpServletRequest request, String client, String key){
if(key == null || client == null)
return;
SubBind subBind = subMapper.selectSubBind(key);
if(subBind == null)
return;
String ip;
if(request.getRemoteAddr().equals("127.0.0.1")){
ip = request.getHeader("X-Forwarded-For");
if(ip.contains(","))
ip = ip.split(",")[0].trim();
if(ip.contains(":"))
ip = ip.split(":")[0].trim();
} else
ip = request.getRemoteAddr();
String UA = request.getHeader("User-Agent");
if(UA == null)
return;
StringBuilder location = new StringBuilder();
Searcher searcher;
try {
searcher = Searcher.newWithVectorIndex(dbPath, vIndex);
String region = searcher.search(ip);
String[] temp = region.split("\\|");
for (int i = 2; i < temp.length; i++)
if(!temp[i].equals("0"))
location.append(temp[i]).append(" ");
} catch (Exception e) {
System.out.printf("failed to create vectorIndex cached searcher with `%s`: %s\n", dbPath, e);
return;
}
SubUpdateRecord subUpdateRecord = new SubUpdateRecord(0, subBind.getUser(), ip, UA, new Date(), location.toString().trim());
subMapper.insertSubUpdateRecord(subUpdateRecord);
if(subMapper.selectUpdateRecordCount(subBind.getUser()) > 10)
subMapper.deleteSubUpdateRecordById(subMapper.selectMinUpdateRecordId(subBind.getUser()));
switch (client){
case "v2" -> FileDownload.export(request, response, "sub/DouNaiV2ray.txt");
case "cat" -> FileDownload.export(request, response, "sub/DouNaiClash.txt");
default -> {
try{
response.getOutputStream().write("client error".getBytes(StandardCharsets.UTF_8));
} catch (IOException ignored){}
}
}
}
public String deleteSubBind(String user){
Response response = Response.generateResponse();
subMapper.deleteSubBind(user);
subMapper.deleteSubUpdateRecord(user);
return response.success("删除成功").toJSONString();
}
}

View File

@ -14,12 +14,14 @@ import java.util.HashMap;
@Service @Service
public class TagService { public class TagService {
@Resource
TagMapper tagMapper; TagMapper tagMapper;
@Resource
GalleryMapper galleryMapper; GalleryMapper galleryMapper;
public TagService(TagMapper tagMapper, GalleryMapper galleryMapper) {
this.tagMapper = tagMapper;
this.galleryMapper = galleryMapper;
}
public String createTag(String tagStr){ public String createTag(String tagStr){
Response response = Response.generateResponse(); Response response = Response.generateResponse();

View File

@ -28,6 +28,13 @@ public class UserServiceImpl{
@Resource @Resource
TaskHandlerInterceptor taskHandlerInterceptor; TaskHandlerInterceptor taskHandlerInterceptor;
public UserServiceImpl(UserMapper userMapper, GalleryMapper galleryMapper, CollectMapper collectMapper, TaskHandlerInterceptor taskHandlerInterceptor) {
this.userMapper = userMapper;
this.galleryMapper = galleryMapper;
this.collectMapper = collectMapper;
this.taskHandlerInterceptor = taskHandlerInterceptor;
}
public String addAuthCode(String targetAuthCode, String people) { public String addAuthCode(String targetAuthCode, String people) {
Response response = Response.generateResponse(); Response response = Response.generateResponse();

View File

@ -1,5 +1,6 @@
package com.lion.lionwebsite.Util; package com.lion.lionwebsite.Util;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lion.lionwebsite.Domain.MaskDomain; import com.lion.lionwebsite.Domain.MaskDomain;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.Data; import lombok.Data;
@ -25,6 +26,7 @@ public class CustomUtil {
public static DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); public static DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public static ObjectMapper objectMapper = new ObjectMapper();
private MaskDomain[] maskDomains; private MaskDomain[] maskDomains;
public String restoreUrl(String link){ public String restoreUrl(String link){
@ -63,14 +65,14 @@ public class CustomUtil {
String preNum = ""; String preNum = "";
String unit = ""; String unit = "";
Pattern patternWithDot = Pattern.compile("(\\d+.\\d+)([A-Z]+)"); Pattern patternWithDot = Pattern.compile("(\\d+.\\d+)(([A-Z]|[a-z])+)");
Matcher matcherWithDot = patternWithDot.matcher(fileSizeString); Matcher matcherWithDot = patternWithDot.matcher(fileSizeString);
if(matcherWithDot.find()){ if(matcherWithDot.find()){
preNum = matcherWithDot.group(1); preNum = matcherWithDot.group(1);
unit = matcherWithDot.group(2); unit = matcherWithDot.group(2);
} }
else { else {
Pattern patternWithoutDot = Pattern.compile("(\\d+)([A-Z]+)"); Pattern patternWithoutDot = Pattern.compile("(\\d+)(([A-Z]|[a-z])+)");
Matcher matcherWithoutDot = patternWithoutDot.matcher(fileSizeString); Matcher matcherWithoutDot = patternWithoutDot.matcher(fileSizeString);
if (matcherWithoutDot.find()) { if (matcherWithoutDot.find()) {
preNum = matcherWithoutDot.group(1); preNum = matcherWithoutDot.group(1);
@ -82,9 +84,9 @@ public class CustomUtil {
return switch (unit) { return switch (unit) {
case "B" -> (long) num; case "B" -> (long) num;
case "KB" -> (long) (ONE_KB * num); case "KB", "KiB" -> (long) (ONE_KB * num);
case "MB" -> (long) (ONE_MB * num); case "MB", "MiB" -> (long) (ONE_MB * num);
case "GB" -> (long) (ONE_GB * num); case "GB", "GiB" -> (long) (ONE_GB * num);
default -> 0; default -> 0;
}; };
} }
@ -105,6 +107,7 @@ public class CustomUtil {
public static short _findIdlePort(){ public static short _findIdlePort(){
for(int i=20000; i<65535; i++){ for(int i=20000; i<65535; i++){
try(ServerSocket ignored = new ServerSocket(i)){ try(ServerSocket ignored = new ServerSocket(i)){
ignored.close();
return (short) i; return (short) i;
}catch (IOException ignored) { }catch (IOException ignored) {
} }

View File

@ -1,14 +1,13 @@
package com.lion.lionwebsite.Util; package com.lion.lionwebsite.Util;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.HashMap;
public class Response { public class Response {
HashMap<String, String> result; ObjectNode result;
public Response(){ public Response(){
result = new HashMap<>(); result = CustomUtil.objectMapper.createObjectNode();
} }
public static Response generateResponse(){ public static Response generateResponse(){
@ -20,7 +19,7 @@ public class Response {
} }
public String get(String key){ public String get(String key){
return result.get(key); return result.get(key).asText();
} }
public void setData(String data){ public void setData(String data){
@ -31,13 +30,20 @@ public class Response {
this.result.put("result", result); this.result.put("result", result);
} }
public void success(){ public Response success(){
setResult("success"); setResult("success");
return this;
} }
public void success(String result){ public Response success(String result){
success(); success();
setData(result); setData(result);
return this;
}
public Response success(JsonNode jsonNode){
success();
this.result.set("data", jsonNode);
return this;
} }
public void failure(){ public void failure(){
@ -50,7 +56,11 @@ public class Response {
} }
public String getResult(){ public String getResult(){
return result.get("data"); return result.get("data").asText();
}
public boolean isSuccess(){
return result.get("result").asText().equals("success");
} }
@ -80,7 +90,6 @@ public class Response {
} }
public String toJSONString(){ public String toJSONString(){
ObjectMapper objectMapper = new ObjectMapper(); return result.toString();
return objectMapper.valueToTree(result).toString();
} }
} }

Binary file not shown.

View File

@ -2,6 +2,8 @@ server:
port: 8888 port: 8888
tomcat: tomcat:
max-swallow-size: 10000MB max-swallow-size: 10000MB
http2:
enabled: true
spring: spring:
datasource: datasource:
@ -26,15 +28,16 @@ personal-service:
StoragePath: /storage/ StoragePath: /storage/
gallery-manage-service: gallery-manage-service:
target-path: /storage/gallery/ target-path: /root/gallery/
cache-size: 100 cache-size: 100
remote-service: remote-service:
ip: 5.255.110.45 ip: 5.255.110.45
local-service: local-service:
fires: https://api.dler.io/sub?target=clash&new_name=true&url=https%3A%2F%2Ffast.losadhwselfff2332dasd.xyz%2Flink%2Fz0pfwyTvC5naXkbb%3Fclash%3D1&insert=false&config=https%3A%2F%2Fraw.githubusercontent.com%2FACL4SSR%2FACL4SSR%2Fmaster%2FClash%2Fconfig%2FACL4SSR_Online.ini fires: https://api.dler.io/sub?target=clash&new_name=true&url=https%3A%2F%2Ffast.losadhwselfff2332dasd.xyz%2Flink%2Fz0pfwyTvC5naXkbb%3Fclash%3D1&insert=false&config=https%3A%2F%2Fraw.githubusercontent.com%2FACL4SSR%2FACL4SSR%2Fmaster%2FClash%2Fconfig%2FACL4SSR_Online.ini
DouNaiClash: https://aaaa.gay/link/A5CXg2cJATerEEoe?client=clashv2 DouNaiClash: https://aaaa.gay/link/X7zEqkIx5gtIGugO?client=clashmeta
DouNaiV2ray: https://aaaa.gay/link/A5CXg2cJATerEEoe?client=v2 DouNaiV2ray: https://aaaa.gay/link/X7zEqkIx5gtIGugO?client=v2
bot:
token: 5222939329:AAHa6l9ZuVVdNSDLPI_H-c8O_VgeOEw5plA

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -6,8 +6,8 @@
<link href="/reset.css" type="text/css"> <link href="/reset.css" type="text/css">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lion</title> <title>Lion</title>
<script type="module" src="/index/index.js"></script> <script type="module" src="/asserts/index/index.js"></script>
<link rel="stylesheet" href="/index/index.css"> <link rel="stylesheet" href="/asserts/index/index.css">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -4,10 +4,10 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.ico" /> <link rel="icon" type="image/svg+xml" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
<title>Vite + Vue</title> <title>Lion</title>
<meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-capable" content="yes">
<script type="module" crossorigin src="/mobile/index.js"></script> <script type="module" crossorigin src="/asserts/mobile/index.js"></script>
<link rel="stylesheet" href="/mobile/index.css"> <link rel="stylesheet" href="/asserts/mobile/index.css">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,8 +5,8 @@
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lion</title> <title>Lion</title>
<script type="module" crossorigin src="/self/index.js"></script> <script type="module" crossorigin src="/asserts/self/index.js"></script>
<link rel="stylesheet" href="/self/index.css"> <link rel="stylesheet" href="/asserts/self/index.css">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

View File

@ -5,8 +5,8 @@
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Personal</title> <title>Personal</title>
<script type="module" crossorigin src="/self/mobile.js"></script> <script type="module" crossorigin src="/asserts/self/mobile.js"></script>
<link rel="stylesheet" href="/self/mobile.css"> <link rel="stylesheet" href="/asserts/self/mobile.css">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>