mirror of
https://github.com/TheWhiteDog9487/WebAPI.git
synced 2026-08-11 23:01:30 +08:00
Initial commit
This commit is contained in:
+26
@@ -0,0 +1,26 @@
|
||||
package xyz.thewhitedog9487.WebAPI.Configuration;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
@Configuration
|
||||
class SpringSecurityConfiguration {
|
||||
|
||||
@Bean
|
||||
SecurityFilterChain CustomSecurityFilterChain(HttpSecurity Security) throws Exception {
|
||||
Security
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
.authorizeHttpRequests(AuthorizationManagerRequestMatcherRegistry -> {
|
||||
AuthorizationManagerRequestMatcherRegistry
|
||||
.requestMatchers("/ip/**", "/message/**")
|
||||
.permitAll()
|
||||
.anyRequest()
|
||||
.denyAll(); });
|
||||
return Security.build(); }
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package xyz.thewhitedog9487.WebAPI.Controller.Filter;
|
||||
|
||||
import jakarta.servlet.*;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
@Component
|
||||
class SetDefaultContentType extends OncePerRequestFilter {
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||
if (response.getContentType() == null) {
|
||||
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE); }
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package xyz.thewhitedog9487.WebAPI.Controller;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/ip")
|
||||
class IP {
|
||||
@GetMapping("/ip")
|
||||
ResponseEntity<String> GetIP(@RequestHeader Map<String, String> HttpHeader, HttpServletRequest Request) {
|
||||
if (HttpHeader.get("CF-Connecting-IP") instanceof String IP) {
|
||||
/*
|
||||
↑ instanceof的模式变量一定非空
|
||||
相当于是:
|
||||
if (HttpHeader.get("CF-Connecting-IP" != null) {
|
||||
String IP = HttpHeader.get("CF-Connecting-IP");
|
||||
}
|
||||
*/
|
||||
log.info("请求携带了CF-Connecting-IP头部,IP为:{}", IP);
|
||||
return new ResponseEntity<>(IP,
|
||||
MultiValueMap.fromSingleValue(Map.of("Content-Type", "text/plain;charset=UTF-8")),
|
||||
HttpStatus.OK);
|
||||
}
|
||||
else {
|
||||
log.info("请求未携带CF-Connecting-IP头部,HttpServletRequest获取到的IP为:{}", Request.getRemoteAddr());
|
||||
return new ResponseEntity<>(Request.getRemoteAddr(),
|
||||
MultiValueMap.fromSingleValue(Map.of("Content-Type", "text/plain;charset=UTF-8")),
|
||||
HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package xyz.thewhitedog9487.WebAPI.Controller;
|
||||
|
||||
import discord4j.common.util.Snowflake;
|
||||
import discord4j.core.GatewayDiscordClient;
|
||||
import discord4j.rest.http.client.ClientException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.MissingRequestHeaderException;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/message")
|
||||
class Message {
|
||||
@Autowired GatewayDiscordClient DiscordBotClient;
|
||||
@Autowired List<String> ApiKeyList;
|
||||
record PostMessageData(Long ChannelID, String Content) {}
|
||||
|
||||
@PostMapping("/discord")
|
||||
ResponseEntity<ResponseData> DiscordPush(@RequestHeader(value = "X-API-Key", required = true) String ApiKey, @RequestBody PostMessageData RequestBody){
|
||||
if ( ApiKeyList.contains(ApiKey) == false ) {
|
||||
log.warn("API密钥验证失败,密钥:{}", ApiKey);
|
||||
return new ResponseEntity<>(new ResponseData(
|
||||
HttpStatus.UNAUTHORIZED.value(),
|
||||
"API密钥验证失败",
|
||||
Map.of("提供的密钥", ApiKey)), HttpStatus.UNAUTHORIZED); }
|
||||
|
||||
var ChannelID = Snowflake.of(RequestBody.ChannelID);
|
||||
log.info("准备向{}发送消息: {}", ChannelID.asString(), RequestBody.Content);
|
||||
try {
|
||||
var MessageData = DiscordBotClient
|
||||
.rest()
|
||||
.getChannelById(ChannelID)
|
||||
.createMessage(RequestBody.Content)
|
||||
.block();
|
||||
log.info("消息发送成功,ID为:{}", MessageData.id());
|
||||
return new ResponseEntity<>(new ResponseData(
|
||||
HttpStatus.CREATED.value(),
|
||||
"消息发送成功",
|
||||
Map.of(
|
||||
"新ID", MessageData.id().asString(),
|
||||
"频道ID", ChannelID.asString(),
|
||||
"内容", RequestBody.Content)), HttpStatus.CREATED);
|
||||
} catch (ClientException e) {
|
||||
log.error("消息发送失败:", e);
|
||||
return new ResponseEntity<>(new ResponseData(
|
||||
HttpStatus.INTERNAL_SERVER_ERROR.value(),
|
||||
"消息发送失败",
|
||||
Map.of(
|
||||
"错误信息", e.getMessage(),
|
||||
"频道ID", ChannelID.asString(),
|
||||
"内容", RequestBody.Content)), HttpStatus.INTERNAL_SERVER_ERROR);}}
|
||||
|
||||
@ExceptionHandler(MissingRequestHeaderException.class)
|
||||
ResponseEntity<ResponseData> HandleMissingHeader(MissingRequestHeaderException Exception, HttpServletRequest Request) {
|
||||
log.warn("请求缺少必要的头部信息:{}", Exception.getHeaderName());
|
||||
if (Request.getHeader("CF-Connecting-IP") instanceof String IP) {
|
||||
log.warn("请求携带了CF-Connecting-IP头部,IP:{}", IP);
|
||||
} else {
|
||||
log.warn("请求未携带CF-Connecting-IP头部,IP:{}", Request.getRemoteAddr()); }
|
||||
return new ResponseEntity<>(new ResponseData(
|
||||
HttpStatus.BAD_REQUEST.value(),
|
||||
"请求缺少必要的头部信息",
|
||||
Map.of("缺失的头部", Exception.getHeaderName())), HttpStatus.BAD_REQUEST);}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package xyz.thewhitedog9487.WebAPI.Controller;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record ResponseData(int code, Object message, Object data) {
|
||||
static ObjectMapper JsonMapper = new ObjectMapper();
|
||||
public ResponseData(int code) {
|
||||
this(code, null, null); }
|
||||
public ResponseData(int code, Object message) {
|
||||
this(code, List.of(message), null); }
|
||||
|
||||
public String ToJson(){
|
||||
try {
|
||||
return JsonMapper.writeValueAsString(this);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e); } }
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package xyz.thewhitedog9487.WebAPI;
|
||||
|
||||
import discord4j.core.DiscordClientBuilder;
|
||||
import discord4j.core.GatewayDiscordClient;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
class GlobalSharedBean {
|
||||
|
||||
@Bean
|
||||
GatewayDiscordClient GetDiscordClient(){
|
||||
String DiscordBotToken = System.getenv("Discord_Bot_Token");
|
||||
if (DiscordBotToken == null) {
|
||||
log.error("未设置环境变量Discord_Bot_Token,请检查配置。");
|
||||
System.exit(-1); }
|
||||
return DiscordClientBuilder.create(DiscordBotToken)
|
||||
.build()
|
||||
.login()
|
||||
.block();}
|
||||
// TODO: ↑ 看看能不能优化下启动性能
|
||||
|
||||
@Bean
|
||||
List<String> ApiKeyList() {
|
||||
try {
|
||||
return Files.readAllLines(Path.of("API密钥.txt"), StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
try {
|
||||
Files.createFile(Path.of("API密钥.txt"));
|
||||
} catch (IOException e1) {
|
||||
log.error("API密钥文件不存在且无法创建API密钥文件。", e1);
|
||||
System.exit(-1); }
|
||||
log.error("读取API密钥文件不存在,已生成空文件,请放置密钥。", e);
|
||||
System.exit(-1);
|
||||
return null; } }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package xyz.thewhitedog9487.WebAPI;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class WebApiApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
//TODO: 从配置文件或环境变量读取并设置HTTP端口号
|
||||
SpringApplication.run(WebApiApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user