diff --git a/backend/src/main/java/com/alttd/altitudeweb/controllers/chat/ChatController.java b/backend/src/main/java/com/alttd/altitudeweb/controllers/chat/ChatController.java index f69dab7..860c42c 100644 --- a/backend/src/main/java/com/alttd/altitudeweb/controllers/chat/ChatController.java +++ b/backend/src/main/java/com/alttd/altitudeweb/controllers/chat/ChatController.java @@ -2,6 +2,7 @@ package com.alttd.altitudeweb.controllers.chat; import com.alttd.altitudeweb.api.ChatApi; import com.alttd.altitudeweb.model.ChatMessageDto; +import com.alttd.altitudeweb.model.PlayerNameDto; import com.alttd.altitudeweb.model.ServerStateDto; import com.alttd.altitudeweb.services.chat.ChatService; import lombok.RequiredArgsConstructor; @@ -11,6 +12,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; import java.util.List; +import java.util.UUID; @Slf4j @RestController @@ -31,4 +33,11 @@ public class ChatController implements ChatApi { //TODO [Stijn] [2026-07-18]: Implement handling server state updates (push to listeners) throw new UnsupportedOperationException("Not implemented"); } + + @Override + public ResponseEntity getName(UUID uuid) { + return chatService.getPlayerName(uuid) + .map(ResponseEntity::ok) + .orElse(ResponseEntity.notFound().build()); + } } diff --git a/backend/src/main/java/com/alttd/altitudeweb/services/chat/ChatService.java b/backend/src/main/java/com/alttd/altitudeweb/services/chat/ChatService.java index a8dcb9f..cfc55d3 100644 --- a/backend/src/main/java/com/alttd/altitudeweb/services/chat/ChatService.java +++ b/backend/src/main/java/com/alttd/altitudeweb/services/chat/ChatService.java @@ -5,7 +5,10 @@ import com.alttd.altitudeweb.controllers.chat.ChatMessageMapper; import com.alttd.altitudeweb.controllers.chat.ChatMessageType; import com.alttd.altitudeweb.database.Databases; import com.alttd.altitudeweb.database.chat.ChatLogMapper; +import com.alttd.altitudeweb.database.chat.NicknameMapper; +import com.alttd.altitudeweb.database.luckperms.UUIDUsernameMapper; import com.alttd.altitudeweb.model.PermissionClaimDto; +import com.alttd.altitudeweb.model.PlayerNameDto; import com.alttd.altitudeweb.services.chat.event_publisher.EventPublisher; import com.alttd.altitudeweb.services.chat.event_publisher.EventUser; import com.alttd.altitudeweb.setup.Connection; @@ -142,4 +145,22 @@ public class ChatService { return chatMessages.tailMap(instant, false).values().stream().toList(); } + public Optional getPlayerName(UUID uuid) { + String username = Connection.getConnection(Databases.LUCK_PERMS) + .runQueryWithResult(sqlSession -> sqlSession.getMapper(UUIDUsernameMapper.class).getUsernameFromUUID(uuid.toString())); + + if (username == null) { + return Optional.empty(); + } + + Optional nickname = Connection.getConnection(Databases.CHAT) + .runQueryWithResult(sqlSession -> sqlSession.getMapper(NicknameMapper.class).getNicknameFromUUID(uuid.toString())); + + PlayerNameDto playerNameDto = new PlayerNameDto(); + playerNameDto.setName(username); + playerNameDto.setNickname(nickname.orElse(null)); + + return Optional.of(playerNameDto); + } + } diff --git a/backend/src/test/java/com/alttd/altitudeweb/services/chat/ChatServiceTest.java b/backend/src/test/java/com/alttd/altitudeweb/services/chat/ChatServiceTest.java index 35eb5d5..011f714 100644 --- a/backend/src/test/java/com/alttd/altitudeweb/services/chat/ChatServiceTest.java +++ b/backend/src/test/java/com/alttd/altitudeweb/services/chat/ChatServiceTest.java @@ -49,7 +49,7 @@ class ChatServiceTest { verify(eventPublisher).sendToUsers(anyString(), captor.capture()); MessageForUser messageForUser = captor.getValue(); - EventUser user = new EventUser(UUID.randomUUID(), List.of()); + EventUser user = new EventUser(UUID.randomUUID(), List.of(), null); String result = messageForUser.get(user); assertTrue(result.contains("hello")); @@ -73,10 +73,10 @@ class ChatServiceTest { MessageForUser messageForUser = captor.getValue(); - EventUser regularUser = new EventUser(UUID.randomUUID(), List.of()); + EventUser regularUser = new EventUser(UUID.randomUUID(), List.of(), null); assertFalse(messageForUser.get(regularUser).contains("staff chat"), "Regular user should not see GAC message"); - EventUser modUser = new EventUser(UUID.randomUUID(), List.of(PermissionClaimDto.MOD.getValue())); + EventUser modUser = new EventUser(UUID.randomUUID(), List.of(PermissionClaimDto.MOD.getValue()), null); assertTrue(messageForUser.get(modUser).contains("staff chat"), "MOD should see GAC message"); } @@ -101,9 +101,9 @@ class ChatServiceTest { MessageForUser messageForUser = captor.getValue(); - EventUser sender = new EventUser(senderUuid, List.of()); - EventUser receiver = new EventUser(receiverUuid, List.of()); - EventUser other = new EventUser(UUID.randomUUID(), List.of()); + EventUser sender = new EventUser(senderUuid, List.of(), null); + EventUser receiver = new EventUser(receiverUuid, List.of(), null); + EventUser other = new EventUser(UUID.randomUUID(), List.of(), null); assertTrue(messageForUser.get(sender).contains("private message"), "Sender should see their own message"); assertTrue(messageForUser.get(receiver).contains("private message"), "Receiver should see the message"); @@ -127,7 +127,7 @@ class ChatServiceTest { verify(eventPublisher).sendToUsers(anyString(), captor.capture()); MessageForUser messageForUser = captor.getValue(); - EventUser user = new EventUser(UUID.randomUUID(), List.of()); + EventUser user = new EventUser(UUID.randomUUID(), List.of(), null); assertTrue(messageForUser.get(user).contains("global hello")); } @@ -148,8 +148,8 @@ class ChatServiceTest { verify(eventPublisher).sendToUsers(anyString(), captor.capture()); MessageForUser messageForUser = captor.getValue(); - EventUser regularUser = new EventUser(UUID.randomUUID(), List.of()); - EventUser headModUser = new EventUser(UUID.randomUUID(), List.of(PermissionClaimDto.HEAD_MOD.getValue())); + EventUser regularUser = new EventUser(UUID.randomUUID(), List.of(), null); + EventUser headModUser = new EventUser(UUID.randomUUID(), List.of(PermissionClaimDto.HEAD_MOD.getValue()), null); assertFalse(messageForUser.get(regularUser).contains("blocked message")); assertTrue(messageForUser.get(headModUser).contains("blocked message")); diff --git a/database/src/main/java/com/alttd/altitudeweb/database/chat/NicknameMapper.java b/database/src/main/java/com/alttd/altitudeweb/database/chat/NicknameMapper.java new file mode 100644 index 0000000..06f0b95 --- /dev/null +++ b/database/src/main/java/com/alttd/altitudeweb/database/chat/NicknameMapper.java @@ -0,0 +1,15 @@ +package com.alttd.altitudeweb.database.chat; + +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.Optional; + +public interface NicknameMapper { + @Select(""" + SELECT nickname + FROM nicknames + WHERE uuid = #{uuid} + """) + Optional getNicknameFromUUID(@Param("uuid") String uuid); +} diff --git a/database/src/main/java/com/alttd/altitudeweb/setup/Connection.java b/database/src/main/java/com/alttd/altitudeweb/setup/Connection.java index 51a9c11..f2358ce 100644 --- a/database/src/main/java/com/alttd/altitudeweb/setup/Connection.java +++ b/database/src/main/java/com/alttd/altitudeweb/setup/Connection.java @@ -144,6 +144,26 @@ public class Connection { }).start(); } + public T runQueryWithResult(QueryFunction function) { + if (sqlSessionFactory == null) { + sqlSessionFactory = createSqlSessionFactory(settings, addMappers); + } + + try (SqlSession session = sqlSessionFactory.openSession()) { + T result = function.apply(session); + session.commit(); + return result; + } catch (Exception e) { + log.error("Failed to run query", e); + throw e; + } + } + + @FunctionalInterface + public interface QueryFunction { + T apply(SqlSession session); + } + private SqlSessionFactory createSqlSessionFactory(DatabaseSettings settings, AddMappers addMappers) { try { Configuration configuration = getConfiguration(settings); diff --git a/database/src/main/java/com/alttd/altitudeweb/setup/InitializeChat.java b/database/src/main/java/com/alttd/altitudeweb/setup/InitializeChat.java index b54ee4c..f57c925 100644 --- a/database/src/main/java/com/alttd/altitudeweb/setup/InitializeChat.java +++ b/database/src/main/java/com/alttd/altitudeweb/setup/InitializeChat.java @@ -2,6 +2,7 @@ package com.alttd.altitudeweb.setup; import com.alttd.altitudeweb.database.Databases; import com.alttd.altitudeweb.database.chat.ChatLogMapper; +import com.alttd.altitudeweb.database.chat.NicknameMapper; import com.alttd.altitudeweb.database.votingplugin.VotingPluginUsersMapper; import lombok.extern.slf4j.Slf4j; @@ -12,6 +13,7 @@ public class InitializeChat { log.info("Initializing Chat"); Connection.getConnection(Databases.CHAT, (configuration) -> { configuration.addMapper(ChatLogMapper.class); + configuration.addMapper(NicknameMapper.class); }).join(); log.debug("Initialized Chat"); } diff --git a/open_api/src/main/resources/chat-api.yml b/open_api/src/main/resources/chat-api.yml index 8f77bc0..c94e837 100644 --- a/open_api/src/main/resources/chat-api.yml +++ b/open_api/src/main/resources/chat-api.yml @@ -45,8 +45,40 @@ paths: responses: "202": description: Accepted + + /chat/player/{uuid}/name: + get: + tags: + - chat + summary: Gets the name, and nickname of the player associated with that uuid + operationId: getName + parameters: + - name: uuid + in: path + required: true + schema: + type: string + format: uuid + responses: + "200": + description: The player's name and nickname + content: + application/json: + schema: + $ref: "#/components/schemas/PlayerName" + "404": + description: Player not found components: schemas: + PlayerName: + type: object + required: + - name + properties: + name: + type: string + nickname: + type: string User: type: object required: