diff --git a/http-service/src/main/java/net/runelite/http/service/pluginhub/PluginHubController.java b/http-service/src/main/java/net/runelite/http/service/pluginhub/PluginHubController.java index f9f424dc..f85e0d17 100644 --- a/http-service/src/main/java/net/runelite/http/service/pluginhub/PluginHubController.java +++ b/http-service/src/main/java/net/runelite/http/service/pluginhub/PluginHubController.java @@ -46,6 +46,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -86,6 +87,52 @@ public ResponseEntity> get() .body(pluginCounts); } + @GetMapping("/shields/installs/plugin/{pluginName}") + public ResponseEntity installs(@PathVariable String pluginName) + { + if (pluginCounts.isEmpty()) + { + return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE) + .cacheControl(CacheControl.noCache()) + .build(); + } + + long count = pluginCounts.getOrDefault(pluginName, -1L); + return ResponseEntity.ok() + .cacheControl(CacheControl.maxAge(30, TimeUnit.MINUTES).cachePublic()) + .body(new ShieldsFormat(count, "Total installs")); + } + + @GetMapping("/shields/rank/plugin/{pluginName}") + public ResponseEntity rank(@PathVariable String pluginName) + { + if (pluginCounts.isEmpty()) + { + return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE) + .cacheControl(CacheControl.noCache()) + .build(); + } + + + long rank = -1; + long installs = pluginCounts.getOrDefault(pluginName, -1L); + if (installs != -1L) + { + rank = 1; + for (Map.Entry entry : pluginCounts.entrySet()) + { + if (entry.getValue() > installs) + { + rank++; + } + } + } + + return ResponseEntity.ok() + .cacheControl(CacheControl.maxAge(30, TimeUnit.MINUTES).cachePublic()) + .body(new ShieldsFormat(rank, "Plugin rank")); + } + @PostMapping public void submit(HttpServletRequest request, @RequestBody String[] plugins) { diff --git a/http-service/src/main/java/net/runelite/http/service/pluginhub/ShieldsFormat.java b/http-service/src/main/java/net/runelite/http/service/pluginhub/ShieldsFormat.java new file mode 100644 index 00000000..f5627227 --- /dev/null +++ b/http-service/src/main/java/net/runelite/http/service/pluginhub/ShieldsFormat.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024, TheStonedTurtle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.http.service.pluginhub; + +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public class ShieldsFormat +{ + int schemaVersion; + String label; + String message; + String color; + boolean isError; + + public ShieldsFormat(long count, String label) + { + this(1, label, String.valueOf(count), count > 0 ? "007bff" : "red", count < 0); + } +}