001/* 002 * PlotSquared, a land and world management plugin for Minecraft. 003 * Copyright (C) IntellectualSites <https://intellectualsites.com> 004 * Copyright (C) IntellectualSites team and contributors 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <https://www.gnu.org/licenses/>. 018 */ 019package com.plotsquared.bukkit.uuid; 020 021import com.google.common.util.concurrent.RateLimiter; 022import com.plotsquared.core.configuration.Settings; 023import com.plotsquared.core.uuid.UUIDMapping; 024import com.plotsquared.core.uuid.UUIDService; 025import org.apache.logging.log4j.LogManager; 026import org.apache.logging.log4j.Logger; 027import org.checkerframework.checker.nullness.qual.NonNull; 028import org.enginehub.squirrelid.Profile; 029import org.enginehub.squirrelid.resolver.HttpRepositoryService; 030import org.enginehub.squirrelid.resolver.ProfileService; 031 032import java.io.IOException; 033import java.util.ArrayList; 034import java.util.Collections; 035import java.util.List; 036import java.util.UUID; 037 038/** 039 * UUID service using SquirrelID 040 */ 041@SuppressWarnings("UnstableApiUsage") 042public class SquirrelIdUUIDService implements UUIDService { 043 044 private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + SquirrelIdUUIDService.class.getSimpleName()); 045 046 private final ProfileService profileService; 047 private final RateLimiter rateLimiter; 048 049 /** 050 * Create a new SquirrelID UUID service 051 * 052 * @param rateLimit Mojangs rate limit is 600 requests per 10 minutes. 053 * This parameter specifies how many of those requests 054 * we can use before our internal rate limit kicks in. 055 */ 056 public SquirrelIdUUIDService(final int rateLimit) { 057 this.profileService = HttpRepositoryService.forMinecraft(); 058 // RateLimiter uses request per seconds. The constructor 059 // parameter rateLimit is requests per 600 seconds 060 this.rateLimiter = RateLimiter.create(rateLimit / 600.0D); 061 } 062 063 @Override 064 public @NonNull List<UUIDMapping> getNames(final @NonNull List<UUID> uuids) { 065 final List<UUIDMapping> results = new ArrayList<>(uuids.size()); 066 this.rateLimiter.acquire(uuids.size()); 067 try { 068 try { 069 for (final Profile profile : this.profileService.findAllByUuid(uuids)) { 070 results.add(new UUIDMapping(profile.getUniqueId(), profile.getName())); 071 } 072 } catch (final IllegalArgumentException illegalArgumentException) { 073 // 074 // This means that the UUID was invalid for whatever reason, we'll try to 075 // go through them one by one 076 // 077 if (uuids.size() >= 2) { 078 if (Settings.DEBUG) { 079 LOGGER.info("(UUID) Found invalid UUID in batch. Will try each UUID individually."); 080 } 081 for (final UUID uuid : uuids) { 082 final List<UUIDMapping> result = this.getNames(Collections.singletonList(uuid)); 083 if (result.isEmpty()) { 084 continue; 085 } 086 results.add(result.get(0)); 087 } 088 } else if (uuids.size() == 1 && Settings.DEBUG) { 089 LOGGER.info("(UUID) Found invalid UUID: {}", uuids.get(0)); 090 } 091 } 092 } catch (IOException | InterruptedException e) { 093 e.printStackTrace(); 094 } 095 return results; 096 } 097 098 @Override 099 public @NonNull List<UUIDMapping> getUUIDs(final @NonNull List<String> usernames) { 100 final List<UUIDMapping> results = new ArrayList<>(usernames.size()); 101 this.rateLimiter.acquire(usernames.size()); 102 try { 103 for (final Profile profile : this.profileService.findAllByName(usernames)) { 104 results.add(new UUIDMapping(profile.getUniqueId(), profile.getName())); 105 } 106 } catch (IOException | InterruptedException e) { 107 e.printStackTrace(); 108 } 109 return results; 110 } 111 112}