diff --git a/pom.xml b/pom.xml
index c2440f0f..53bbd586 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
icu.samnya
aqua
- 0.0.16-RELEASE
+ 0.0.17-RELEASE
Aqua Server
A multipurpose game server
diff --git a/src/main/java/icu/samnyan/aqua/AquaBeanNameGenerator.java b/src/main/java/icu/samnyan/aqua/AquaBeanNameGenerator.java
new file mode 100644
index 00000000..50228970
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/AquaBeanNameGenerator.java
@@ -0,0 +1,14 @@
+package icu.samnyan.aqua;
+
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.BeanNameGenerator;
+
+public class AquaBeanNameGenerator implements BeanNameGenerator {
+
+ @Override
+ public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
+ return definition.getBeanClassName();
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/icu/samnyan/aqua/AquaServerApplication.java b/src/main/java/icu/samnyan/aqua/AquaServerApplication.java
index 804cf45e..edee56db 100644
--- a/src/main/java/icu/samnyan/aqua/AquaServerApplication.java
+++ b/src/main/java/icu/samnyan/aqua/AquaServerApplication.java
@@ -4,13 +4,17 @@ import icu.samnyan.aqua.sega.aimedb.AimeDbServer;
import icu.samnyan.aqua.spring.util.AutoChecker;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
-@SpringBootApplication
+@SpringBootApplication()
public class AquaServerApplication {
public static void main(String[] args) throws Exception {
- ConfigurableApplicationContext ctx = SpringApplication.run(AquaServerApplication.class, args);
+ final SpringApplicationBuilder builder = new SpringApplicationBuilder(AquaServerApplication.class);
+ builder.beanNameGenerator(new AquaBeanNameGenerator());
+
+ ConfigurableApplicationContext ctx = builder.run(args);
final AimeDbServer aimeDbServer = ctx.getBean(AimeDbServer.class);
aimeDbServer.start();
diff --git a/src/main/java/icu/samnyan/aqua/sega/allnet/AllNetController.java b/src/main/java/icu/samnyan/aqua/sega/allnet/AllNetController.java
index 8712efe2..4cd3c00e 100644
--- a/src/main/java/icu/samnyan/aqua/sega/allnet/AllNetController.java
+++ b/src/main/java/icu/samnyan/aqua/sega/allnet/AllNetController.java
@@ -126,7 +126,10 @@ public class AllNetController {
case "SDDT":
return "http://" + HOST + ":" + PORT + "/OngekiServlet/";
case "SDEY":
- return "http://" + HOST + ":" + PORT + "/";
+ return "http://" + HOST + ":" + PORT + "/MaimaiServlet/";
+ case "SDEZ":
+ // This leads to http://HOST+PORT/Maimai2Servlet/
+ return HOST + ":" + PORT + "/";
default:
return "http://" + HOST + ":" + PORT + "/";
}
diff --git a/src/main/java/icu/samnyan/aqua/sega/general/filter/CompressionFilter.java b/src/main/java/icu/samnyan/aqua/sega/general/filter/CompressionFilter.java
index 2ae2255c..07f19c43 100644
--- a/src/main/java/icu/samnyan/aqua/sega/general/filter/CompressionFilter.java
+++ b/src/main/java/icu/samnyan/aqua/sega/general/filter/CompressionFilter.java
@@ -28,6 +28,7 @@ public class CompressionFilter extends OncePerRequestFilter {
filterList.add("/ChuniServlet");
filterList.add("/OngekiServlet");
filterList.add("/MaimaiServlet");
+ filterList.add("/Maimai2Servlet");
}
@Override
diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/controller/Maimai2ServletController.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/controller/Maimai2ServletController.java
new file mode 100644
index 00000000..3bc316e4
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/controller/Maimai2ServletController.java
@@ -0,0 +1,245 @@
+package icu.samnyan.aqua.sega.maimai2.controller;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+
+import icu.samnyan.aqua.sega.maimai2.handler.impl.*;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+/**
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+@RestController
+@RequestMapping("Maimai2Servlet")
+public class Maimai2ServletController {
+
+ private final GetGameSettingHandler getGameSettingHandler;
+ private final GetGameEventHandler getGameEventHandler;
+ private final GetGameRankingHandler getGameRankingHandler;
+ private final GetGameTournamentInfoHandler getGameTournamentInfoHandler;
+ private final GetTransferFriendHandler getTransferFriendHandler;
+ private final GetUserActivityHandler getUserActivityHandler;
+ private final UserLoginHandler userLoginHandler;
+ private final UserLogoutHandler userLogoutHandler;
+ private final GetUserDataHandler getUserDataHandler;
+ private final UpsertUserAllHandler upsertUserAllHandler;
+ private final GetUserPreviewHandler getUserPreviewHandler;
+ private final GetUserCharacterHandler getUserCharacterHandler;
+ private final GetUserOptionHandler getUserOptionHandler;
+ private final GetUserItemHandler getUserItemHandler;
+ private final GetUserExtendHandler getUserExtendHandler;
+ private final GetUserGhostHandler getUserGhostHandler;
+ private final GetUserLoginBonusHandler getUserLoginBonusHandler;
+ private final GetUserMapHandler getUserMapHandler;
+ private final GetUserFavoriteHandler getUserFavoriteHandler;
+ private final GetUserCardHandler getUserCardHandler;
+ private final GetUserMusicHandler getUserMusicHandler;
+ private final GetUserRatingHandler getUserRatingHandler;
+ private final GetUserRegionHandler getUserRegionHandler;
+
+ public Maimai2ServletController(GetGameSettingHandler getGameSettingHandler, GetGameEventHandler getGameEventHandler, GetGameRankingHandler getGameRankingHandler, GetGameTournamentInfoHandler getGameTournamentInfoHandler,
+ GetTransferFriendHandler getTransferFriendHandler, GetUserActivityHandler getUserActivityHandler, UserLoginHandler userLoginHandler, UserLogoutHandler userLogoutHandler,
+ GetUserDataHandler getUserDataHandler, UpsertUserAllHandler upsertUserAllHandler, GetUserPreviewHandler getUserPreviewHandler, GetUserCharacterHandler getUserCharacterHandler,
+ GetUserOptionHandler getUserOptionHandler, GetUserItemHandler getUserItemHandler, GetUserExtendHandler getUserExtendHandler, GetUserGhostHandler getUserGhostHandler,
+ GetUserLoginBonusHandler getUserLoginBonusHandler, GetUserMapHandler getUserMapHandler, GetUserFavoriteHandler getUserFavoriteHandler,
+ GetUserCardHandler getUserCardHandler, GetUserMusicHandler getUserMusicHandler, GetUserRatingHandler getUserRatingHandler, GetUserRegionHandler getUserRegionHandler) {
+ this.getGameSettingHandler = getGameSettingHandler;
+ this.getGameEventHandler = getGameEventHandler;
+ this.getGameRankingHandler = getGameRankingHandler;
+ this.getGameTournamentInfoHandler = getGameTournamentInfoHandler;
+ this.getTransferFriendHandler = getTransferFriendHandler;
+ this.getUserActivityHandler = getUserActivityHandler;
+ this.userLoginHandler = userLoginHandler;
+ this.userLogoutHandler = userLogoutHandler;
+ this.getUserDataHandler = getUserDataHandler;
+ this.upsertUserAllHandler = upsertUserAllHandler;
+ this.getUserPreviewHandler = getUserPreviewHandler;
+ this.getUserCharacterHandler = getUserCharacterHandler;
+ this.getUserOptionHandler = getUserOptionHandler;
+ this.getUserItemHandler = getUserItemHandler;
+ this.getUserExtendHandler = getUserExtendHandler;
+ this.getUserGhostHandler = getUserGhostHandler;
+ this.getUserLoginBonusHandler = getUserLoginBonusHandler;
+ this.getUserMapHandler = getUserMapHandler;
+ this.getUserFavoriteHandler = getUserFavoriteHandler;
+ this.getUserCardHandler = getUserCardHandler;
+ this.getUserMusicHandler = getUserMusicHandler;
+ this.getUserRatingHandler = getUserRatingHandler;
+ this.getUserRegionHandler = getUserRegionHandler;
+ }
+
+ // Mandatory for boot
+ @PostMapping("GetGameEventApi")
+ public String getGameEvent(@ModelAttribute Map request) throws JsonProcessingException {
+ return getGameEventHandler.handle(request);
+ }
+
+ @PostMapping("GetGameRankingApi")
+ public String getGameRanking(@ModelAttribute Map request) throws JsonProcessingException {
+ return getGameRankingHandler.handle(request);
+ }
+
+ @PostMapping("GetGameSettingApi")
+ public String getGameSetting(@ModelAttribute Map request) throws JsonProcessingException {
+ return getGameSettingHandler.handle(request);
+ }
+
+ @PostMapping("GetGameTournamentInfoApi")
+ public String getGameTournamentInfoHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return getGameTournamentInfoHandler.handle(request);
+ }
+
+ // Gameplay
+ @PostMapping("GetTransferFriendApi")
+ public String getTransferFriendHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return getTransferFriendHandler.handle(request);
+ }
+
+ @PostMapping("GetUserActivityApi")
+ public String getUserActivityHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return getUserActivityHandler.handle(request);
+ }
+
+ // maybe releated DX Pass? return empty
+ @PostMapping("GetUserCardApi")
+ public String getUserCardHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return getUserCardHandler.handle(request);
+ }
+
+ @PostMapping("GetUserCharacterApi")
+ public String getUserCharacterHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return getUserCharacterHandler.handle(request);
+ }
+
+ @PostMapping("GetUserDataApi")
+ public String getUserDataHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return getUserDataHandler.handle(request);
+ }
+
+ @PostMapping("GetUserExtendApi")
+ public String getUserExtendHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return getUserExtendHandler.handle(request);
+ }
+
+ @PostMapping("GetUserFavoriteApi")
+ public String getUserFavoriteHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return getUserFavoriteHandler.handle(request);
+ }
+
+ // No support, return empty
+ @PostMapping("GetUserGhostApi")
+ public String getUserGhostHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return getUserGhostHandler.handle(request);
+ }
+
+ @PostMapping("GetUserItemApi")
+ public String getUserItemHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return getUserItemHandler.handle(request);
+ }
+
+ @PostMapping("GetUserLoginBonusApi")
+ public String getUserLoginBonusHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return getUserLoginBonusHandler.handle(request);
+ }
+
+ @PostMapping("GetUserMapApi")
+ public String getUserMapHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return getUserMapHandler.handle(request);
+ }
+
+ @PostMapping("GetUserMusicApi")
+ public String getUserMusicHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return getUserMusicHandler.handle(request);
+ }
+
+ @PostMapping("GetUserOptionApi")
+ public String getUserOptionHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return getUserOptionHandler.handle(request);
+ }
+
+ // No support
+ @PostMapping("GetUserPortraitApi")
+ public String getUserPortraitHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return "{\"length\":0,\"userPortraitList\":[]}";
+ }
+
+ @PostMapping("GetUserPreviewApi")
+ public String getUserPreviewHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return getUserPreviewHandler.handle(request);
+ }
+
+ @PostMapping("GetUserRatingApi")
+ public String getUserRatingHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return getUserRatingHandler.handle(request);
+ }
+
+ // I don't know what it is. return empty
+ @PostMapping("GetUserRegionApi")
+ public String getUserRegionHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return getUserRegionHandler.handle(request);
+ }
+
+ // Seems only used for tournament, No Support
+ @PostMapping("GetUserScoreRankingApi")
+ public String getUserScoreRankingHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return "{}";
+ }
+
+ // No support
+ @PostMapping("UploadUserPhotoApi")
+ public String uploadUserPhotoHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return "{\"returnCode\":1,\"apiName\":\"com.sega.maimai2servlet.api.UploadUserPhotoApi\"}";
+ }
+
+ @PostMapping("UploadUserPlaylogApi")
+ public String uploadUserPlaylogHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return "{\"returnCode\":1,\"apiName\":\"com.sega.maimai2servlet.api.UploadUserPlaylogApi\"}";
+ }
+
+ // No support, return error code
+ @PostMapping("UploadUserPortraitApi")
+ public String uploadUserPortraitHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return "{\"returnCode\":-1,\"apiName\":\"com.sega.maimai2servlet.api.UploadUserPortraitApi\"}";
+ }
+
+ @PostMapping("UserLoginApi")
+ public String userLoginHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return userLoginHandler.handle(request);
+ }
+
+ @PostMapping("UserLogoutApi")
+ public String userLogoutHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return userLogoutHandler.handle(request);
+ }
+
+ @PostMapping("UpsertClientBookkeepingApi")
+ public String upsertClientBookkeeping(@ModelAttribute Map request) {
+ return "{\"returnCode\":1,\"apiName\":\"com.sega.maimai2servlet.api.UpsertClientBookkeepingApi\"}";
+ }
+
+ @PostMapping("UpsertClientSettingApi")
+ public String upsertClientSetting(@ModelAttribute Map request) {
+ return "{\"returnCode\":1,\"apiName\":\"com.sega.maimai2servlet.api.UpsertClientSettingApi\"}";
+ }
+
+ @PostMapping("UpsertClientTestmodeApi")
+ public String upsertClientTestmode(@ModelAttribute Map request) {
+ return "{\"returnCode\":1,\"apiName\":\"com.sega.maimai2servlet.api.UpsertClientTestmodeApi\"}";
+ }
+
+ @PostMapping("UpsertClientUploadApi")
+ public String upsertClientUpload(@ModelAttribute Map request) {
+ return "{\"returnCode\":1,\"apiName\":\"com.sega.maimai2servlet.api.UpsertClientUploadApi\"}";
+ }
+
+ // Score saving
+ @PostMapping("UpsertUserAllApi")
+ public String upsertUserAllHandler(@ModelAttribute Map request) throws JsonProcessingException {
+ return upsertUserAllHandler.handle(request);
+ }
+
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/controller/Maimai2ServletControllerAdvice.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/controller/Maimai2ServletControllerAdvice.java
new file mode 100644
index 00000000..558b3c92
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/controller/Maimai2ServletControllerAdvice.java
@@ -0,0 +1,38 @@
+package icu.samnyan.aqua.sega.maimai2.controller;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+
+/**
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+@RestControllerAdvice(basePackages = "icu.samnyan.aqua.sega.maimai2")
+public class Maimai2ServletControllerAdvice {
+
+ private static final Logger logger = LoggerFactory.getLogger(Maimai2ServletControllerAdvice.class);
+
+ /**
+ * Get the map object from json string
+ *
+ * @param request HttpServletRequest
+ */
+ @ModelAttribute
+ public Map preHandle(HttpServletRequest request) throws IOException {
+ byte[] src = request.getInputStream().readAllBytes();
+ String outputString = new String(src, StandardCharsets.UTF_8).trim();
+ logger.info("Request {} : {}", request.getRequestURI(), outputString);
+ ObjectMapper mapper = new ObjectMapper();
+
+ return mapper.readValue(outputString, new TypeReference<>() {
+ });
+ }
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/MapEncountNpcRepository.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/MapEncountNpcRepository.java
new file mode 100644
index 00000000..6974f0eb
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/MapEncountNpcRepository.java
@@ -0,0 +1,23 @@
+package icu.samnyan.aqua.sega.maimai2.dao.userdata;
+
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserDetail;
+import icu.samnyan.aqua.sega.maimai2.model.userdata.MapEncountNpc;
+
+import java.util.Optional;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+/**
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+@Repository("Maimai2MapEncountNpcRepository")
+public interface MapEncountNpcRepository extends JpaRepository {
+
+ Optional findByUserAndMusicId(UserDetail user, int musicId);
+
+ Page findByUser_Card_ExtIdAndMusicId(long userId, int musicId, Pageable page);
+
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserActRepository.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserActRepository.java
new file mode 100644
index 00000000..aafa880b
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserActRepository.java
@@ -0,0 +1,20 @@
+package icu.samnyan.aqua.sega.maimai2.dao.userdata;
+
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserAct;
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserDetail;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+@Repository("Maimai2UserActRepository")
+public interface UserActRepository extends JpaRepository {
+
+ Optional findByUserAndKindAndActivityId(UserDetail user, int kind, int id);
+
+ List findByUser_Card_ExtIdAndKind(long userId, int kind);
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserCharacterRepository.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserCharacterRepository.java
new file mode 100644
index 00000000..39298c8d
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserCharacterRepository.java
@@ -0,0 +1,21 @@
+package icu.samnyan.aqua.sega.maimai2.dao.userdata;
+
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserCharacter;
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserDetail;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+@Repository("Maimai2UserCharacterRepository")
+public interface UserCharacterRepository extends JpaRepository {
+
+ List findByUser_Card_ExtId(long userId);
+
+ Optional findByUserAndCharacterId(UserDetail user, int characterId);
+
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserDataRepository.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserDataRepository.java
new file mode 100644
index 00000000..ca93f173
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserDataRepository.java
@@ -0,0 +1,15 @@
+package icu.samnyan.aqua.sega.maimai2.dao.userdata;
+
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserDetail;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+/**
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+@Repository("Maimai2UserDataRepository")
+public interface UserDataRepository extends JpaRepository {
+ Optional findByCard_ExtId(long userId);
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserExtendRepository.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserExtendRepository.java
new file mode 100644
index 00000000..d4e3be7a
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserExtendRepository.java
@@ -0,0 +1,19 @@
+package icu.samnyan.aqua.sega.maimai2.dao.userdata;
+
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserDetail;
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserExtend;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+/**
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+@Repository("Maimai2UserExtendRepository")
+public interface UserExtendRepository extends JpaRepository {
+
+ Optional findByUser(UserDetail user);
+
+ Optional findByUser_Card_ExtId(Long extId);
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserFavoriteRepository.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserFavoriteRepository.java
new file mode 100644
index 00000000..56eacfd1
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserFavoriteRepository.java
@@ -0,0 +1,21 @@
+package icu.samnyan.aqua.sega.maimai2.dao.userdata;
+
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserDetail;
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserFavorite;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+@Repository("Maimai2UserFavoriteRepository")
+public interface UserFavoriteRepository extends JpaRepository {
+
+ Optional findByUserAndItemKind(UserDetail user, int kind);
+ //Optional findByUserIdAndItemKind(long userId, int kind);
+
+ List findByUserIdAndItemKind(long userId, int kind);
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserItemRepository.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserItemRepository.java
new file mode 100644
index 00000000..dc3430e3
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserItemRepository.java
@@ -0,0 +1,23 @@
+package icu.samnyan.aqua.sega.maimai2.dao.userdata;
+
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserDetail;
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserItem;
+
+import java.util.Optional;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+/**
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+@Repository("Maimai2UserItemRepository")
+public interface UserItemRepository extends JpaRepository {
+
+ Optional findByUserAndItemKindAndItemId(UserDetail user, int itemKind, int itemId);
+
+ Page findByUser_Card_ExtIdAndItemKind(long userId, int kind, Pageable page);
+
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserLoginBonusRepository.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserLoginBonusRepository.java
new file mode 100644
index 00000000..b165064f
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserLoginBonusRepository.java
@@ -0,0 +1,23 @@
+package icu.samnyan.aqua.sega.maimai2.dao.userdata;
+
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserDetail;
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserLoginBonus;
+
+import java.util.Optional;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+/**
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+@Repository("Maimai2UserLoginBonusRepository")
+public interface UserLoginBonusRepository extends JpaRepository {
+
+ Optional findByUserAndBonusId(UserDetail user, int bonusId);
+
+ Page findByUser_Card_ExtId(long userId, Pageable page);
+
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserMapRepository.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserMapRepository.java
new file mode 100644
index 00000000..1d07fe42
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserMapRepository.java
@@ -0,0 +1,23 @@
+package icu.samnyan.aqua.sega.maimai2.dao.userdata;
+
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserDetail;
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserMap;
+
+import java.util.Optional;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+/**
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+@Repository("Maimai2UserMapRepository")
+public interface UserMapRepository extends JpaRepository {
+
+ Optional findByUserAndMapId(UserDetail user, int mapId);
+
+ Page findByUser_Card_ExtId(long userId, Pageable page);
+
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserMusicDetailRepository.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserMusicDetailRepository.java
new file mode 100644
index 00000000..930226dd
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserMusicDetailRepository.java
@@ -0,0 +1,22 @@
+package icu.samnyan.aqua.sega.maimai2.dao.userdata;
+
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserDetail;
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserMusicDetail;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+/**
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+@Repository("Maimai2UserMusicDetailRepository")
+public interface UserMusicDetailRepository extends JpaRepository {
+
+ Optional findByUserAndMusicIdAndLevel(UserDetail user, int musicId, int level);
+
+ Page findByUser_Card_ExtId(long userId, Pageable page);
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserOptionRepository.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserOptionRepository.java
new file mode 100644
index 00000000..22f7dc41
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserOptionRepository.java
@@ -0,0 +1,19 @@
+package icu.samnyan.aqua.sega.maimai2.dao.userdata;
+
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserDetail;
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserOption;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+/**
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+@Repository("Maimai2UserOptionRepository")
+public interface UserOptionRepository extends JpaRepository {
+
+ Optional findByUser(UserDetail user);
+
+ Optional findByUser_Card_ExtId(Long extId);
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserRateRepository.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserRateRepository.java
new file mode 100644
index 00000000..5e60aacd
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserRateRepository.java
@@ -0,0 +1,22 @@
+package icu.samnyan.aqua.sega.maimai2.dao.userdata;
+
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserDetail;
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserRate;
+
+import java.util.List;
+import java.util.Optional;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+/**
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+@Repository("Maimai2UserRateRepository")
+public interface UserRateRepository extends JpaRepository {
+
+ Optional findByUserAndMusicId(UserDetail user, int musicId);
+
+ List findByUser_Card_ExtId(long userId);
+
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserUdemaeRepository.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserUdemaeRepository.java
new file mode 100644
index 00000000..eb4fc27f
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/dao/userdata/UserUdemaeRepository.java
@@ -0,0 +1,19 @@
+package icu.samnyan.aqua.sega.maimai2.dao.userdata;
+
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserDetail;
+import icu.samnyan.aqua.sega.maimai2.model.userdata.UserUdemae;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+/**
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+@Repository("Maimai2UserUdemaeRepository")
+public interface UserUdemaeRepository extends JpaRepository {
+
+ Optional findByUser(UserDetail user);
+
+ Optional findByUser_Card_ExtId(Long extId);
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/handler/BaseHandler.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/handler/BaseHandler.java
new file mode 100644
index 00000000..97ff46f2
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/handler/BaseHandler.java
@@ -0,0 +1,13 @@
+package icu.samnyan.aqua.sega.maimai2.handler;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+
+import java.util.Map;
+
+/**
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+public interface BaseHandler {
+
+ String handle(Map request) throws JsonProcessingException;
+}
diff --git a/src/main/java/icu/samnyan/aqua/sega/maimai2/handler/impl/GetGameEventHandler.java b/src/main/java/icu/samnyan/aqua/sega/maimai2/handler/impl/GetGameEventHandler.java
new file mode 100644
index 00000000..41193915
--- /dev/null
+++ b/src/main/java/icu/samnyan/aqua/sega/maimai2/handler/impl/GetGameEventHandler.java
@@ -0,0 +1,46 @@
+package icu.samnyan.aqua.sega.maimai2.handler.impl;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import icu.samnyan.aqua.sega.maimai2.handler.BaseHandler;
+import icu.samnyan.aqua.sega.util.jackson.StringMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author samnyan (privateamusement@protonmail.com)
+ */
+@Component
+public class GetGameEventHandler implements BaseHandler {
+
+ private static final Logger logger = LoggerFactory.getLogger(GetGameEventHandler.class);
+
+ //private final GameEventRepository gameEventRepository;
+
+ private final StringMapper mapper;
+
+ public GetGameEventHandler(StringMapper mapper) {
+ this.mapper = mapper;
+ }
+
+ @Override
+ public String handle(Map request) throws JsonProcessingException {
+ String type = Integer.toString((int) request.get("type"));
+
+ List