Skip to content

Commit 4df97ce

Browse files
committed
Improve shop rate limiting & add better errors
1 parent 0f8900f commit 4df97ce

2 files changed

Lines changed: 20 additions & 16 deletions

File tree

src/main/java/net/earthmc/emcapi/endpoint/ShopEndpoint.java

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
import com.google.gson.JsonElement;
55
import com.google.gson.JsonObject;
66
import io.javalin.http.BadRequestResponse;
7+
import io.javalin.http.ForbiddenResponse;
8+
import io.javalin.http.TooManyRequestsResponse;
9+
import io.javalin.http.UnauthorizedResponse;
710
import net.earthmc.emcapi.EMCAPI;
811
import net.earthmc.emcapi.integration.QuickShopIntegration;
912
import net.earthmc.emcapi.manager.KeyManager;
@@ -46,11 +49,23 @@ public List<Shop> getObjectOrNull(JsonElement element, @Nullable String key) {
4649
try {
4750
player = UUID.fromString(string);
4851
} catch (IllegalArgumentException ignored) {
49-
return null;
52+
throw new BadRequestResponse("Your query contains an invalid UUID");
5053
}
5154

5255
integration.throwIfDisabled();
53-
return integration.getPlayerShops(player, key);
56+
UUID keyOwner = KeyManager.getKeyOwner(key);
57+
if (keyOwner == null) {
58+
throw new UnauthorizedResponse("Could not find an owner for this API key");
59+
}
60+
if (!player.equals(KeyManager.getKeyOwner(key))) {
61+
throw new ForbiddenResponse("This API key is not owned by the player queried");
62+
}
63+
Long next = LAST_QUERY_MAP.containsKey(keyOwner) ? LAST_QUERY_MAP.get(keyOwner) + COOLDOWN_SECONDS : null;
64+
Long now = Instant.now().getEpochSecond();
65+
if (next != null && next > now) { // Rate limiting should happen before even querying the shops, not before formatting the data
66+
throw new TooManyRequestsResponse("Too Many Requests. Try again in " + (next - now) + " seconds");
67+
}
68+
return integration.getPlayerShops(player);
5469
}
5570

5671
@Override
@@ -59,16 +74,12 @@ public JsonElement getJsonElement(List<Shop> object, @Nullable String key) {
5974
int counter = 0;
6075
UUID keyOwner = KeyManager.getKeyOwner(key);
6176
if (keyOwner == null) {
62-
return null;
63-
}
64-
if (LAST_QUERY_MAP.containsKey(keyOwner) && LAST_QUERY_MAP.get(keyOwner) > Instant.now().getEpochSecond() - COOLDOWN_SECONDS) {
65-
return null;
77+
throw new UnauthorizedResponse("Could not find an owner for this API key");
6678
}
6779
if (object.isEmpty()) {
6880
return null;
69-
} else {
70-
LAST_QUERY_MAP.put(keyOwner, Instant.now().getEpochSecond());
7181
}
82+
LAST_QUERY_MAP.put(keyOwner, Instant.now().getEpochSecond()); // Mark as a successful query if at least 1 shop was loaded
7283

7384
final List<CompletableFuture<Void>> shopFutures = new ArrayList<>();
7485

src/main/java/net/earthmc/emcapi/integration/QuickShopIntegration.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import com.ghostchu.quickshop.api.QuickShopAPI;
44
import com.ghostchu.quickshop.api.shop.Shop;
5-
import net.earthmc.emcapi.manager.KeyManager;
65

76
import java.util.List;
87
import java.util.UUID;
@@ -13,13 +12,7 @@ public QuickShopIntegration() {
1312
super("QuickShop-Hikari");
1413
}
1514

16-
public List<Shop> getPlayerShops(UUID player, String key) {
17-
if (!isEnabled()) {
18-
return List.of();
19-
}
20-
if (!player.equals(KeyManager.getKeyOwner(key))) {
21-
return List.of();
22-
}
15+
public List<Shop> getPlayerShops(UUID player) {
2316
return QuickShopAPI.getInstance().getShopManager().getAllShops(player);
2417
}
2518
}

0 commit comments

Comments
 (0)