Skip to content

Commit c99b179

Browse files
Added guilds/{guild_id}/leaderboard/experience and paginated QOTW-Leaderboard route
1 parent b03783c commit c99b179

File tree

11 files changed

+242
-44
lines changed

11 files changed

+242
-44
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package net.javadiscord.javabot.api.routes.data;
2+
3+
import lombok.Data;
4+
5+
/**
6+
* Abstract class which contains basic user values.
7+
*/
8+
@Data
9+
public abstract class UserData {
10+
private long userId;
11+
private String userName;
12+
private String discriminator;
13+
private String effectiveAvatarUrl;
14+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package net.javadiscord.javabot.api.routes.leaderboard.help_experience;
2+
3+
import com.github.benmanes.caffeine.cache.Caffeine;
4+
import net.dv8tion.jda.api.JDA;
5+
import net.dv8tion.jda.api.entities.Guild;
6+
import net.javadiscord.javabot.Bot;
7+
import net.javadiscord.javabot.api.exception.InvalidEntityIdException;
8+
import net.javadiscord.javabot.api.routes.CaffeineCache;
9+
import net.javadiscord.javabot.api.routes.leaderboard.help_experience.model.ExperienceUserData;
10+
import net.javadiscord.javabot.systems.help.HelpExperienceService;
11+
import net.javadiscord.javabot.util.Pair;
12+
import org.springframework.beans.factory.annotation.Autowired;
13+
import org.springframework.http.HttpStatus;
14+
import org.springframework.http.ResponseEntity;
15+
import org.springframework.web.bind.annotation.GetMapping;
16+
import org.springframework.web.bind.annotation.PathVariable;
17+
import org.springframework.web.bind.annotation.RequestParam;
18+
import org.springframework.web.bind.annotation.RestController;
19+
20+
import java.util.List;
21+
import java.util.concurrent.TimeUnit;
22+
23+
/**
24+
* Handles all GET-Requests on the guilds/{guild_id}/leaderboard/experience/ route.
25+
*/
26+
@RestController
27+
public class HelpExperienceLeaderboardController extends CaffeineCache<Pair<Long, Integer>, List<ExperienceUserData>> {
28+
private static final int PAGE_AMOUNT = 8;
29+
private final JDA jda;
30+
31+
/**
32+
* The constructor of this class which initializes the {@link Caffeine} cache.
33+
*
34+
* @param jda The {@link JDA} instance to use.
35+
*/
36+
@Autowired
37+
public HelpExperienceLeaderboardController(final JDA jda) {
38+
super(Caffeine.newBuilder()
39+
.expireAfterWrite(10, TimeUnit.MINUTES)
40+
.build()
41+
);
42+
this.jda = jda;
43+
}
44+
45+
/**
46+
* Serves the specified amount of users. Sorted by the
47+
* amount of help experience.
48+
*
49+
* @param guildId The guilds' id.
50+
* @param page The page to get. Defaults to 1.
51+
* @return The {@link ResponseEntity}.
52+
*/
53+
@GetMapping("guilds/{guild_id}/leaderboard/experience")
54+
public ResponseEntity<List<ExperienceUserData>> getHelpExperienceLeaderboard(
55+
@PathVariable("guild_id") long guildId,
56+
@RequestParam(value = "page", defaultValue = "1") int page
57+
) {
58+
Guild guild = jda.getGuildById(guildId);
59+
if (guild == null) {
60+
throw new InvalidEntityIdException(Guild.class, "You've provided an invalid guild id!");
61+
}
62+
HelpExperienceService service = new HelpExperienceService(Bot.getDataSource());
63+
List<ExperienceUserData> members = getCache().getIfPresent(new Pair<>(guild.getIdLong(), page));
64+
if (members == null || members.isEmpty()) {
65+
members = service.getTopAccounts(PAGE_AMOUNT, page).stream()
66+
.map(p -> ExperienceUserData.of(p, jda.retrieveUserById(p.getUserId()).complete()))
67+
.toList();
68+
getCache().put(new Pair<>(guild.getIdLong(), page), members);
69+
}
70+
return new ResponseEntity<>(members, HttpStatus.OK);
71+
}
72+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package net.javadiscord.javabot.api.routes.leaderboard.help_experience.model;
2+
3+
import lombok.Data;
4+
import lombok.EqualsAndHashCode;
5+
import net.dv8tion.jda.api.entities.User;
6+
import net.javadiscord.javabot.api.routes.data.UserData;
7+
import net.javadiscord.javabot.systems.help.model.HelpAccount;
8+
import org.jetbrains.annotations.NotNull;
9+
import org.jetbrains.annotations.Nullable;
10+
11+
/**
12+
* API-Data class which contains all necessary information about a single users'
13+
* Help-Account.
14+
*/
15+
@Data
16+
@EqualsAndHashCode(callSuper = false)
17+
public class ExperienceUserData extends UserData {
18+
private HelpAccount account;
19+
20+
/**
21+
* Creates a new {@link ExperienceUserData} instance.
22+
*
23+
* @param account The {@link HelpAccount} to use.
24+
* @param user A nullable {@link User}.
25+
* @return The {@link ExperienceUserData}.
26+
*/
27+
public static @NotNull ExperienceUserData of(@NotNull HelpAccount account, @Nullable User user) {
28+
ExperienceUserData data = new ExperienceUserData();
29+
data.setUserId(account.getUserId());
30+
if (user != null) {
31+
data.setUserName(user.getName());
32+
data.setDiscriminator(user.getDiscriminator());
33+
data.setEffectiveAvatarUrl(user.getEffectiveAvatarUrl());
34+
}
35+
data.setAccount(account);
36+
return data;
37+
}
38+
}

src/main/java/net/javadiscord/javabot/api/routes/qotw_leaderboard/QOTWLeaderboardController.java renamed to src/main/java/net/javadiscord/javabot/api/routes/leaderboard/qotw/QOTWLeaderboardController.java

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
package net.javadiscord.javabot.api.routes.qotw_leaderboard;
1+
package net.javadiscord.javabot.api.routes.leaderboard.qotw;
22

33
import com.github.benmanes.caffeine.cache.Caffeine;
44
import net.dv8tion.jda.api.JDA;
55
import net.dv8tion.jda.api.entities.Guild;
66
import net.javadiscord.javabot.Bot;
77
import net.javadiscord.javabot.api.exception.InvalidEntityIdException;
88
import net.javadiscord.javabot.api.routes.CaffeineCache;
9-
import net.javadiscord.javabot.api.routes.qotw_leaderboard.model.QOTWMemberData;
9+
import net.javadiscord.javabot.api.routes.leaderboard.qotw.model.QOTWUserData;
1010
import net.javadiscord.javabot.systems.qotw.QOTWPointsService;
11+
import net.javadiscord.javabot.util.Pair;
1112
import org.springframework.beans.factory.annotation.Autowired;
1213
import org.springframework.http.HttpStatus;
1314
import org.springframework.http.ResponseEntity;
@@ -20,10 +21,11 @@
2021
import java.util.concurrent.TimeUnit;
2122

2223
/**
23-
* Handles all GET-Requests on the {guild_id}/qotw/leaderboard route.
24+
* Handles all GET-Requests on the guilds/{guild_id}/leaderboard/qotw/ route.
2425
*/
2526
@RestController
26-
public class QOTWLeaderboardController extends CaffeineCache<Long, List<QOTWMemberData>> {
27+
public class QOTWLeaderboardController extends CaffeineCache<Pair<Long, Integer>, List<QOTWUserData>> {
28+
private static final int PAGE_AMOUNT = 8;
2729
private final JDA jda;
2830

2931
/**
@@ -45,34 +47,26 @@ public QOTWLeaderboardController(final JDA jda) {
4547
* amount of qotw-points.
4648
*
4749
* @param guildId The guilds' id.
48-
* @param amount The amount of users to return. Defaults to 3.
50+
* @param page The page to get. Defaults to 1.
4951
* @return The {@link ResponseEntity}.
5052
*/
51-
@GetMapping("guilds/{guild_id}/qotw/leaderboard")
52-
public ResponseEntity<List<QOTWMemberData>> getQOTWLeaderboard(
53+
@GetMapping("guilds/{guild_id}/leaderboard/qotw")
54+
public ResponseEntity<List<QOTWUserData>> getQOTWLeaderboard(
5355
@PathVariable("guild_id") long guildId,
54-
@RequestParam(value = "amount", defaultValue = "3") int amount
56+
@RequestParam(value = "page", defaultValue = "1") int page
5557
) {
5658
Guild guild = jda.getGuildById(guildId);
5759
if (guild == null) {
5860
throw new InvalidEntityIdException(Guild.class, "You've provided an invalid guild id!");
5961
}
6062
QOTWPointsService service = new QOTWPointsService(Bot.getDataSource());
61-
List<QOTWMemberData> members = getCache().getIfPresent(guild.getIdLong());
63+
List<QOTWUserData> members = getCache().getIfPresent(new Pair<>(guild.getIdLong(), page));
6264
if (members == null || members.isEmpty()) {
63-
members = service.getTopMembers(amount, guild).stream()
64-
.map(p -> {
65-
QOTWMemberData data = new QOTWMemberData();
66-
data.setUserId(p.second().getIdLong());
67-
data.setUserName(p.second().getUser().getName());
68-
data.setDiscriminator(p.second().getUser().getDiscriminator());
69-
data.setEffectiveAvatarUrl(p.second().getEffectiveAvatarUrl());
70-
data.setAccount(p.first());
71-
return data;
72-
})
65+
members = service.getTopAccounts(PAGE_AMOUNT, page).stream()
66+
.map(p -> QOTWUserData.of(p, jda.retrieveUserById(p.getUserId()).complete()))
7367
.toList();
74-
getCache().put(guild.getIdLong(), members);
68+
getCache().put(new Pair<>(guild.getIdLong(), page), members);
7569
}
76-
return new ResponseEntity<>(members.stream().limit(amount).toList(), HttpStatus.OK);
70+
return new ResponseEntity<>(members, HttpStatus.OK);
7771
}
7872
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package net.javadiscord.javabot.api.routes.leaderboard.qotw.model;
2+
3+
import lombok.Data;
4+
import lombok.EqualsAndHashCode;
5+
import net.dv8tion.jda.api.entities.User;
6+
import net.javadiscord.javabot.api.routes.data.UserData;
7+
import net.javadiscord.javabot.systems.qotw.model.QOTWAccount;
8+
import org.jetbrains.annotations.NotNull;
9+
import org.jetbrains.annotations.Nullable;
10+
11+
/**
12+
* API-Data class which contains all necessary information about a single users'
13+
* QOTW-Account.
14+
*/
15+
@Data
16+
@EqualsAndHashCode(callSuper = false)
17+
public class QOTWUserData extends UserData {
18+
private QOTWAccount account;
19+
20+
/**
21+
* Creates a new {@link QOTWUserData} instance.
22+
*
23+
* @param account The {@link QOTWAccount} to use.
24+
* @param user A nullable {@link User}.
25+
* @return The {@link QOTWUserData}.
26+
*/
27+
public static @NotNull QOTWUserData of(@NotNull QOTWAccount account, @Nullable User user) {
28+
QOTWUserData data = new QOTWUserData();
29+
data.setUserId(account.getUserId());
30+
if (user != null) {
31+
data.setUserName(user.getName());
32+
data.setDiscriminator(user.getDiscriminator());
33+
data.setEffectiveAvatarUrl(user.getEffectiveAvatarUrl());
34+
}
35+
data.setAccount(account);
36+
return data;
37+
}
38+
}

src/main/java/net/javadiscord/javabot/api/routes/metrics/MetricsController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import java.util.concurrent.TimeUnit;
2020

2121
/**
22-
* Handles all GET-Requests on the {guild_id}/metrics route.
22+
* Handles all GET-Requests on the guilds/{guild_id}/metrics/ route.
2323
*/
2424
@Slf4j
2525
@RestController

src/main/java/net/javadiscord/javabot/api/routes/qotw_leaderboard/model/QOTWMemberData.java

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/main/java/net/javadiscord/javabot/api/routes/user_profile/UserProfileController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import java.util.concurrent.TimeUnit;
3535

3636
/**
37-
* Handles all GET-Requests on the {guild_id}/{user_id} route.
37+
* Handles all GET-Requests on the guilds/{guild_id}/users/{user_id}/ route.
3838
*/
3939
@RestController
4040
public class UserProfileController extends CaffeineCache<Pair<Long, Long>, UserProfileData> {

src/main/java/net/javadiscord/javabot/systems/help/HelpExperienceService.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@
1111
import net.javadiscord.javabot.systems.help.model.HelpAccount;
1212
import net.javadiscord.javabot.systems.help.model.HelpTransaction;
1313
import net.javadiscord.javabot.systems.help.model.HelpTransactionMessage;
14+
import net.javadiscord.javabot.util.ExceptionLogger;
1415
import net.javadiscord.javabot.util.Pair;
16+
import org.jetbrains.annotations.NotNull;
1517

1618
import java.sql.Connection;
1719
import java.sql.SQLException;
20+
import java.util.ArrayList;
1821
import java.util.List;
1922
import java.util.Optional;
2023

@@ -37,21 +40,40 @@ public HelpAccount getOrCreateAccount(long userId) throws SQLException {
3740
HelpAccount account;
3841
try (Connection con = this.dataSource.getConnection()) {
3942
con.setAutoCommit(false);
40-
HelpAccountRepository accountRepository = new HelpAccountRepository(con);
41-
Optional<HelpAccount> optional = accountRepository.getByUserId(userId);
43+
HelpAccountRepository repo = new HelpAccountRepository(con);
44+
Optional<HelpAccount> optional = repo.getByUserId(userId);
4245
if (optional.isPresent()) {
4346
account = optional.get();
4447
} else {
4548
account = new HelpAccount();
4649
account.setUserId(userId);
4750
account.setExperience(0);
48-
accountRepository.insert(account);
51+
repo.insert(account);
4952
}
5053
con.commit();
5154
return account;
5255
}
5356
}
5457

58+
/**
59+
* Returns the specified amount of {@link HelpAccount}s, sorted by their experience.
60+
*
61+
* @param amount The amount to retrieve.
62+
* @param page The page to get.
63+
* @return A {@link List} of {@link HelpAccount}s.
64+
*/
65+
public List<HelpAccount> getTopAccounts(int amount, int page) {
66+
List<HelpAccount> accounts = new ArrayList<>(amount);
67+
try (Connection con = dataSource.getConnection()) {
68+
con.setReadOnly(true);
69+
HelpAccountRepository repo = new HelpAccountRepository(con);
70+
return repo.getAccounts(page, amount);
71+
} catch (SQLException e) {
72+
ExceptionLogger.capture(e, getClass().getSimpleName());
73+
return accounts;
74+
}
75+
}
76+
5577
/**
5678
* Gets all recent help transactions from a user.
5779
*
@@ -102,7 +124,7 @@ public HelpTransaction performTransaction(long recipient, double value, HelpTran
102124
}
103125
}
104126

105-
private void checkExperienceRoles(Guild guild, HelpAccount account) {
127+
private void checkExperienceRoles(@NotNull Guild guild, @NotNull HelpAccount account) {
106128
guild.retrieveMemberById(account.getUserId()).queue(member ->
107129
Bot.getConfig().get(guild).getHelpConfig().getExperienceRoles().forEach((key, value) -> {
108130
Pair<Role, Double> role = account.getCurrentExperienceGoal(guild);

src/main/java/net/javadiscord/javabot/systems/qotw/QOTWPointsService.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,23 @@ public List<Pair<QOTWAccount, Member>> getTopMembers(int n, Guild guild) {
105105
}
106106
}
107107

108+
/**
109+
* Gets the specified amount of {@link QOTWAccount}s, sorted by their points.
110+
*
111+
* @param amount The amount to retrieve.
112+
* @param page The page to get.
113+
* @return An unmodifiable {@link List} of {@link QOTWAccount}s.
114+
*/
115+
public List<QOTWAccount> getTopAccounts(int amount, int page) {
116+
try (Connection con = Bot.getDataSource().getConnection()) {
117+
QuestionPointsRepository repo = new QuestionPointsRepository(con);
118+
return repo.getTopAccounts(page, amount);
119+
} catch (SQLException e) {
120+
ExceptionLogger.capture(e, getClass().getSimpleName());
121+
return List.of();
122+
}
123+
}
124+
108125
/**
109126
* Increments a single user's QOTW-Points.
110127
*

0 commit comments

Comments
 (0)