things might work
This commit is contained in:
@@ -31,3 +31,5 @@ build/
|
|||||||
|
|
||||||
### Mac OS ###
|
### Mac OS ###
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
.env
|
||||||
@@ -16,6 +16,8 @@
|
|||||||
<netty.version>4.2.17.Final</netty.version>
|
<netty.version>4.2.17.Final</netty.version>
|
||||||
<log4j2.version>2.25.4</log4j2.version>
|
<log4j2.version>2.25.4</log4j2.version>
|
||||||
<jda.version>6.5.0</jda.version>
|
<jda.version>6.5.0</jda.version>
|
||||||
|
<dot.version>3.2.0</dot.version>
|
||||||
|
<postgresql.version>42.7.13</postgresql.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -57,5 +59,17 @@
|
|||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.cdimascio</groupId>
|
||||||
|
<artifactId>dotenv-java</artifactId>
|
||||||
|
<version>${dot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.postgresql</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
<version>${postgresql.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
|
|
||||||
public class Main {
|
|
||||||
static Logger logger = LogManager.getLogger(Main.class);
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package tech.allydoes;
|
||||||
|
|
||||||
|
public class Constants {
|
||||||
|
public static final boolean PRODUCTION = false;
|
||||||
|
public static final String TESTING_GUILD = "";
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
package tech.allydoes;
|
||||||
|
|
||||||
|
import io.github.cdimascio.dotenv.Dotenv;
|
||||||
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
|
import io.netty.channel.*;
|
||||||
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
|
import io.netty.channel.socket.SocketChannel;
|
||||||
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
|
import io.netty.handler.codec.http.HttpObjectAggregator;
|
||||||
|
import io.netty.handler.codec.http.HttpRequestDecoder;
|
||||||
|
import io.netty.handler.codec.http.HttpResponseEncoder;
|
||||||
|
import io.netty.handler.logging.LogLevel;
|
||||||
|
import io.netty.handler.logging.LoggingHandler;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import tech.allydoes.database.DatabaseManager;
|
||||||
|
import tech.allydoes.discord.DiscordManager;
|
||||||
|
import tech.allydoes.web.HttpServerHandler;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
private static DiscordManager discordManager;
|
||||||
|
private static DatabaseManager databaseManager;
|
||||||
|
|
||||||
|
static Logger logger = LogManager.getLogger(Main.class);
|
||||||
|
public final int port;
|
||||||
|
public Main(int port) {
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws InterruptedException {
|
||||||
|
discordManager = new DiscordManager();
|
||||||
|
databaseManager = new DatabaseManager();
|
||||||
|
|
||||||
|
new Main(8080).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
|
||||||
|
EventLoopGroup workerGroup = new NioEventLoopGroup();
|
||||||
|
try {
|
||||||
|
ServerBootstrap serverBootstrap = new ServerBootstrap();
|
||||||
|
serverBootstrap.option(ChannelOption.SO_BACKLOG, 1024);
|
||||||
|
serverBootstrap.group(bossGroup, workerGroup)
|
||||||
|
.channel(NioServerSocketChannel.class)
|
||||||
|
.handler(new LoggingHandler(LogLevel.DEBUG))
|
||||||
|
.childHandler(new ChannelInitializer<SocketChannel>() {
|
||||||
|
@Override
|
||||||
|
protected void initChannel(SocketChannel socketChannel) {
|
||||||
|
ChannelPipeline channelPipeline = socketChannel.pipeline();
|
||||||
|
channelPipeline.addLast(new HttpResponseEncoder());
|
||||||
|
channelPipeline.addLast(new HttpRequestDecoder());
|
||||||
|
channelPipeline.addLast(new HttpObjectAggregator(1048576));
|
||||||
|
channelPipeline.addLast(new HttpServerHandler());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Channel ch = serverBootstrap.bind(this.port).sync().channel();
|
||||||
|
ch.closeFuture().sync();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
bossGroup.shutdownGracefully();
|
||||||
|
workerGroup.shutdownGracefully();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DiscordManager getDiscordManager() {
|
||||||
|
return discordManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DatabaseManager getDatabaseManager() {
|
||||||
|
return databaseManager;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
package tech.allydoes.database;
|
||||||
|
|
||||||
|
import io.github.cdimascio.dotenv.Dotenv;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import java.sql.*;
|
||||||
|
|
||||||
|
public class DatabaseManager {
|
||||||
|
private final Logger LOGGER = LogManager.getLogger(DatabaseManager.class);
|
||||||
|
private final Dotenv dotenv = Dotenv.load();
|
||||||
|
|
||||||
|
public DatabaseManager() {
|
||||||
|
initializeDatabase();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeDatabase() {
|
||||||
|
String user = dotenv.get("DB_USER");
|
||||||
|
String password = dotenv.get("DB_PASSWORD");
|
||||||
|
String host = dotenv.get("DB_HOST");
|
||||||
|
String port = dotenv.get("DB_PORT");
|
||||||
|
|
||||||
|
String defaultDbUrl = String.format("jdbc:postgresql://%s:%s/postgres?sslmode=require", host, port);
|
||||||
|
try (Connection conn = DriverManager.getConnection(defaultDbUrl, user, password)) {
|
||||||
|
conn.setAutoCommit(true);
|
||||||
|
|
||||||
|
boolean dbExists = false;
|
||||||
|
try (Statement statement = conn.createStatement()) {
|
||||||
|
if (statement.execute(Queries.CHECK_IF_DATABASE_EXISTS)) {
|
||||||
|
ResultSet resultSet = statement.getResultSet();
|
||||||
|
resultSet.next();
|
||||||
|
dbExists = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dbExists) {
|
||||||
|
LOGGER.debug("Database does not exist. Creating...");
|
||||||
|
try (Statement statement = conn.createStatement()) {
|
||||||
|
if (statement.execute(Queries.CREATE_DATABASE)) {
|
||||||
|
ResultSet resultSet = statement.getResultSet();
|
||||||
|
resultSet.next();
|
||||||
|
LOGGER.debug("Database created successfully.");
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
LOGGER.error("Failed to create database: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try (Statement statement = conn.createStatement()) {
|
||||||
|
if (statement.execute(Queries.CREATE_SERVER_TABLE)) {
|
||||||
|
ResultSet resultSet = statement.getResultSet();
|
||||||
|
resultSet.next();
|
||||||
|
LOGGER.debug("Server table created successfully.");
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
LOGGER.error("Failed to create server table: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOGGER.debug("Database already exists.");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("Database initialization failed: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getAllNotifiers() {
|
||||||
|
String user = dotenv.get("DB_USER");
|
||||||
|
String password = dotenv.get("DB_PASSWORD");
|
||||||
|
String host = dotenv.get("DB_HOST");
|
||||||
|
String port = dotenv.get("DB_PORT");
|
||||||
|
|
||||||
|
String defaultDbUrl = String.format("jdbc:postgresql://%s:%s/postgres?sslmode=require", host, port);
|
||||||
|
try (Connection conn = DriverManager.getConnection(defaultDbUrl, user, password)) {
|
||||||
|
conn.setAutoCommit(true);
|
||||||
|
|
||||||
|
try (Statement statement = conn.createStatement()) {
|
||||||
|
statement.execute(Queries.SELECT_ALL_SERVER_CHANNELS);
|
||||||
|
ResultSet resultSet = statement.getResultSet();
|
||||||
|
while (resultSet.next()) {
|
||||||
|
String guildId = resultSet.getString("guild_id");
|
||||||
|
String channelId = resultSet.getString("channel_id");
|
||||||
|
String messageId = resultSet.getString("message_id");
|
||||||
|
LOGGER.debug("Notifier for guild {}, channel {}, message {}", guildId, channelId, messageId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
LOGGER.error("getAllNotifiers: Failed to connect: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putNotifier(String guildId, String channelId, String messageId) {
|
||||||
|
String user = dotenv.get("DB_USER");
|
||||||
|
String password = dotenv.get("DB_PASSWORD");
|
||||||
|
String host = dotenv.get("DB_HOST");
|
||||||
|
String port = dotenv.get("DB_PORT");
|
||||||
|
|
||||||
|
String defaultDbUrl = String.format("jdbc:postgresql://%s:%s/postgres?sslmode=require", host, port);
|
||||||
|
try (Connection conn = DriverManager.getConnection(defaultDbUrl, user, password)) {
|
||||||
|
conn.setAutoCommit(true);
|
||||||
|
|
||||||
|
try (PreparedStatement preparedStatement = conn.prepareStatement(Queries.INSERT_SERVER_CHANNEL)) {
|
||||||
|
preparedStatement.setString(1, guildId);
|
||||||
|
preparedStatement.setString(2, channelId);
|
||||||
|
preparedStatement.setString(3, messageId);
|
||||||
|
if (preparedStatement.execute()) {
|
||||||
|
LOGGER.debug("Notifier for guild {}, channel {}, message {} added successfully.", guildId, channelId, messageId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
LOGGER.error("putNotifier: Failed to connect: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package tech.allydoes.database;
|
||||||
|
|
||||||
|
public class Queries {
|
||||||
|
public static final String CHECK_IF_DATABASE_EXISTS = "SELECT 1 FROM pg_database WHERE datname = notifier";
|
||||||
|
public static final String CREATE_DATABASE = "CREATE DATABASE IF NOT EXISTS notifier";
|
||||||
|
public static final String CREATE_SERVER_TABLE = "CREATE TABLE IF NOT EXISTS notifier_channels (guild_id VARCHAR(22) PRIMARY KEY, channel_id VARCHAR(22), message_id VARCHAR(22))";
|
||||||
|
public static final String INSERT_SERVER_CHANNEL = "INSERT INTO notifier_channels (guild_id, channel_id, message_id) VALUES (?, ?, ?)";
|
||||||
|
public static final String DELETE_SERVER_CHANNEL = "DELETE FROM notifier_channels WHERE message_id = ?";
|
||||||
|
public static final String SELECT_ALL_SERVER_CHANNELS = "SELECT guild_id, channel_id, message_id FROM notifier_channels";
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package tech.allydoes.discord;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||||
|
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
||||||
|
|
||||||
|
public interface Command {
|
||||||
|
SlashCommandData getCommandData();
|
||||||
|
boolean isPrivateCommand();
|
||||||
|
void processSlashCommandInteractionEvent(SlashCommandInteractionEvent event);
|
||||||
|
void processButtonInteractionEvent(ButtonInteractionEvent event);
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package tech.allydoes.discord;
|
||||||
|
|
||||||
|
import io.github.cdimascio.dotenv.Dotenv;
|
||||||
|
import net.dv8tion.jda.api.JDA;
|
||||||
|
import net.dv8tion.jda.api.JDABuilder;
|
||||||
|
import net.dv8tion.jda.api.entities.Activity;
|
||||||
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
|
import net.dv8tion.jda.api.requests.GatewayIntent;
|
||||||
|
import net.dv8tion.jda.api.requests.restaction.CommandListUpdateAction;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import tech.allydoes.Constants;
|
||||||
|
import tech.allydoes.discord.commands.SaveChannelCommand;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class DiscordManager {
|
||||||
|
public final Logger LOGGER;
|
||||||
|
private final JDA jda;
|
||||||
|
private final HashMap<String, Command> commands;
|
||||||
|
private final Dotenv dotenv = Dotenv.load();
|
||||||
|
|
||||||
|
public DiscordManager() throws InterruptedException {
|
||||||
|
LOGGER = LogManager.getLogger(DiscordManager.class);
|
||||||
|
commands = new HashMap<>();
|
||||||
|
commands.put("savechannel", new SaveChannelCommand());
|
||||||
|
|
||||||
|
String botToken = Constants.PRODUCTION ? dotenv.get("DISCORD_TOKEN") : dotenv.get("TESTING_TOKEN");
|
||||||
|
jda = JDABuilder
|
||||||
|
.create(botToken, GatewayIntent.GUILD_MESSAGES)
|
||||||
|
.build()
|
||||||
|
.awaitReady();
|
||||||
|
registerSlashCommands();
|
||||||
|
jda.getPresence().setActivity(Activity.competing("in robotics!"));
|
||||||
|
LOGGER.info("Logged in as {}", jda.getSelfUser().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerSlashCommands() {
|
||||||
|
if (Constants.PRODUCTION) {
|
||||||
|
registerSlashCommandsGlobal();
|
||||||
|
} else {
|
||||||
|
registerSlashCommandsGuild(Constants.TESTING_GUILD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerSlashCommandsGlobal() {
|
||||||
|
CommandListUpdateAction commandListUpdateAction = jda.updateCommands();
|
||||||
|
for (Command command : commands.values()) {
|
||||||
|
if (command.isPrivateCommand()) continue;
|
||||||
|
commandListUpdateAction = commandListUpdateAction.addCommands(command.getCommandData());
|
||||||
|
LOGGER.debug("Registered global command: {}", command.getCommandData().getName());
|
||||||
|
}
|
||||||
|
commandListUpdateAction.queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerSlashCommandsGuild(String guildID) {
|
||||||
|
Guild guild = jda.getGuildById(guildID);
|
||||||
|
if (guild == null) return;
|
||||||
|
|
||||||
|
CommandListUpdateAction updateAction = guild.updateCommands();
|
||||||
|
for (Command command : commands.values()) {
|
||||||
|
updateAction = updateAction.addCommands(command.getCommandData());
|
||||||
|
LOGGER.debug("Registered guild command: {}", command.getCommandData().getName());
|
||||||
|
}
|
||||||
|
updateAction.queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Command getCommand(String command) {
|
||||||
|
return commands.get(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JDA getJDA() {
|
||||||
|
return jda;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package tech.allydoes.discord;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.EmbedBuilder;
|
||||||
|
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
public class Embeds {
|
||||||
|
public static MessageEmbed createUnknownLabStatus() {
|
||||||
|
return new EmbedBuilder()
|
||||||
|
.setTitle("Unknown Status")
|
||||||
|
.setDescription("The status of the lab is unknown.")
|
||||||
|
.setColor(0xD3D3D3)
|
||||||
|
.setTimestamp(Instant.now())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package tech.allydoes.discord.commands;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.Permission;
|
||||||
|
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||||
|
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.build.Commands;
|
||||||
|
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
||||||
|
import tech.allydoes.Main;
|
||||||
|
import tech.allydoes.discord.Command;
|
||||||
|
import tech.allydoes.discord.Embeds;
|
||||||
|
|
||||||
|
public class SaveChannelCommand implements Command {
|
||||||
|
@Override
|
||||||
|
public SlashCommandData getCommandData() {
|
||||||
|
return Commands.slash("savechannel", "Saves the channel you are in to be used for the status updates")
|
||||||
|
.setDefaultPermissions(DefaultMemberPermissions.enabledFor(Permission.ADMINISTRATOR));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPrivateCommand() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processSlashCommandInteractionEvent(SlashCommandInteractionEvent event) {
|
||||||
|
event.deferReply(true).queue((interactionHook) -> {
|
||||||
|
interactionHook.getInteraction().getMessageChannel().sendMessageEmbeds(Embeds.createUnknownLabStatus()).queue((embedMessage) -> {
|
||||||
|
String guildId = event.getGuild().getId();
|
||||||
|
String channelId = event.getChannel().getId();
|
||||||
|
String messageId = embedMessage.getId();
|
||||||
|
Main.getDatabaseManager().putNotifier(guildId, channelId, messageId);
|
||||||
|
});
|
||||||
|
event.getHook().editOriginal("Channel saved!").queue();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processButtonInteractionEvent(ButtonInteractionEvent event) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
package tech.allydoes.web;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.channel.ChannelFuture;
|
||||||
|
import io.netty.channel.ChannelFutureListener;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
|
import io.netty.handler.codec.http.*;
|
||||||
|
import io.netty.util.CharsetUtil;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import tech.allydoes.leaderboards.handlers.GET.*;
|
||||||
|
import tech.allydoes.leaderboards.handlers.POST.SetPlayerProfile;
|
||||||
|
import tech.allydoes.leaderboards.handlers.POST.SetScore;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static io.netty.handler.codec.http.HttpHeaderNames.*;
|
||||||
|
import static io.netty.handler.codec.http.HttpHeaderValues.CLOSE;
|
||||||
|
|
||||||
|
public class HttpServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger(HttpServerHandler.class);
|
||||||
|
private final HashMap<String, RequestHandler> requestHandlers = new HashMap<>();
|
||||||
|
|
||||||
|
public HttpServerHandler() {
|
||||||
|
RequestHandler[] handlers = {
|
||||||
|
|
||||||
|
};
|
||||||
|
for (RequestHandler handler : handlers) {
|
||||||
|
requestHandlers.put(handler.getRequestName().toLowerCase(), handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ChannelFuture sendContent(String content, FullHttpRequest request, ChannelHandlerContext channelHandlerContext) {
|
||||||
|
ByteBuf byteBuf = Unpooled.copiedBuffer(content, CharsetUtil.UTF_8);
|
||||||
|
DefaultFullHttpResponse httpResponse = new DefaultFullHttpResponse(request.protocolVersion(), HttpResponseStatus.OK, byteBuf);
|
||||||
|
httpResponse.headers().set(CONTENT_TYPE, "application/json; charset=utf-8");
|
||||||
|
httpResponse.headers().set(CONTENT_LENGTH, byteBuf.readableBytes());
|
||||||
|
return channelHandlerContext.writeAndFlush(httpResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelReadComplete(ChannelHandlerContext channelHandlerContext) {
|
||||||
|
channelHandlerContext.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void channelRead0(ChannelHandlerContext channelHandlerContext, FullHttpRequest request) {
|
||||||
|
ChannelFuture future = processRequest(channelHandlerContext, request);
|
||||||
|
|
||||||
|
request.headers().set(CONNECTION, CLOSE);
|
||||||
|
future.addListener(ChannelFutureListener.CLOSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ChannelFuture processRequest(ChannelHandlerContext channelHandlerContext, FullHttpRequest request) {
|
||||||
|
String path = request.uri().split("\\?", 15)[0].toLowerCase();
|
||||||
|
RequestHandler requestHandler = requestHandlers.get(path);
|
||||||
|
QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.uri());
|
||||||
|
Map<String, List<String>> params = queryStringDecoder.parameters();
|
||||||
|
|
||||||
|
if (requestHandler != null && requestHandler.getRequestType().equalsIgnoreCase(request.method().name())) {
|
||||||
|
if (!hasRequiredParameters(params, requestHandler.getRequiredParameters())) {
|
||||||
|
return channelHandlerContext.writeAndFlush(new DefaultFullHttpResponse(request.protocolVersion(), HttpResponseStatus.BAD_REQUEST));
|
||||||
|
}
|
||||||
|
|
||||||
|
return requestHandler.processRequest(channelHandlerContext, request, params);
|
||||||
|
} else {
|
||||||
|
return channelHandlerContext.writeAndFlush(new DefaultFullHttpResponse(request.protocolVersion(), HttpResponseStatus.NOT_FOUND));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exceptionCaught(ChannelHandlerContext channelHandlerContext, Throwable cause) {
|
||||||
|
LOGGER.info("Unhandled exception in pipeline", cause);
|
||||||
|
|
||||||
|
channelHandlerContext.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR));
|
||||||
|
channelHandlerContext.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasRequiredParameters(Map<String, List<String>> parameters, String[] requiredParameters) {
|
||||||
|
for (String requiredParameter : requiredParameters) {
|
||||||
|
if (!parameters.containsKey(requiredParameter)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (List<String> parameterArray: parameters.values()) {
|
||||||
|
String parameter = parameterArray.getFirst();
|
||||||
|
if (parameter.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package tech.allydoes.web.POST;
|
||||||
|
|
||||||
|
import io.netty.channel.ChannelFuture;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.handler.codec.http.FullHttpRequest;
|
||||||
|
import tech.allydoes.web.RequestHandler;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class PostStatus implements RequestHandler {
|
||||||
|
public static String STATUS = "status";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture processRequest(ChannelHandlerContext channelHandlerContext, FullHttpRequest request, Map<String, List<String>> parameters) {
|
||||||
|
int status = Integer.parseInt(parameters.get(STATUS).getFirst());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRequestName() {
|
||||||
|
return "PostStatus";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRequestType() {
|
||||||
|
return "POST";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getRequiredParameters() {
|
||||||
|
return new String[] {
|
||||||
|
STATUS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package tech.allydoes.web;
|
||||||
|
|
||||||
|
import io.netty.channel.ChannelFuture;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.handler.codec.http.FullHttpRequest;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface RequestHandler {
|
||||||
|
ChannelFuture processRequest(ChannelHandlerContext channelHandlerContext, FullHttpRequest request, Map<String, List<String>> parameters);
|
||||||
|
String getRequestName();
|
||||||
|
String getRequestType();
|
||||||
|
String[] getRequiredParameters();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user