66import me .minecraftauth .lib .account .AccountType ;
77import me .minecraftauth .lib .account .Identity ;
88import me .minecraftauth .lib .exception .LookupException ;
9+ import me .minecraftauth .lib .account .platform .twitch .SubTier ;
910import org .json .simple .parser .JSONParser ;
1011import org .json .simple .parser .ParseException ;
1112
12- import java .util .Arrays ;
13- import java .util .HashMap ;
14- import java .util .Map ;
15- import java .util .Optional ;
13+ import java .util .*;
14+ import java .util .function .Predicate ;
1615
1716public class AuthService {
1817
1918 private static final JSONParser JSON_PARSER = new JSONParser ();
2019
20+ // prevent instantiation
21+ private AuthService () {}
22+
23+ private static boolean expectResponseBody (HttpRequest request , Predicate <Dynamic > predicate ) throws LookupException {
24+ int status = request .code ();
25+ String body = request .body ();
26+
27+ if (status / 100 == 2 ) {
28+ try {
29+ Dynamic response = Dynamic .from (JSON_PARSER .parse (body ));
30+ return predicate .test (response );
31+ } catch (HttpRequest .HttpRequestException | ParseException e ) {
32+ throw new LookupException ("Failed to parse API response" , e );
33+ }
34+ } else {
35+ throw new LookupException ("MinecraftAuth server returned bad response: " + status + " / " + body );
36+ }
37+ }
38+ private static boolean expectTrue (HttpRequest request ) throws LookupException {
39+ return expectResponseBody (request , dynamic -> dynamic .dget ("result" ).convert ().intoString ().equals ("true" ));
40+ }
41+
2142 /**
2243 * Look up all of an identifier's linked accounts
2344 * @param from the account type to query by
@@ -28,23 +49,24 @@ public class AuthService {
2849 public static Optional <Identity > lookup (AccountType from , Object identifier ) throws LookupException {
2950 HttpRequest request = HttpRequest .get ("https://minecraftauth.me/api/lookup?" + from .name ().toLowerCase () + "=" + identifier )
3051 .userAgent ("MinecraftAuthLib" );
52+ String body = request .body ();
3153
32- if (request .code () >= 200 && request . code () <= 299 ) {
54+ if (request .code () / 100 == 2 ) {
3355 try {
34- Dynamic response = Dynamic .from (JSON_PARSER .parse (request . body () ));
56+ Dynamic response = Dynamic .from (JSON_PARSER .parse (body ));
3557
3658 Map <AccountType , Account > identifiers = new HashMap <>();
3759 response .children ().forEach (dynamic -> Arrays .stream (AccountType .values ())
3860 .filter (accountType -> accountType .name ().equalsIgnoreCase (dynamic .key ().convert ().intoString ()))
3961 .findFirst ().ifPresent (type -> identifiers .put (type , Account .from (type , dynamic .dget ("identifier" ).convert ().intoString ()))));
4062 return Optional .of (new Identity (identifiers ));
41- } catch (ParseException e ) {
63+ } catch (HttpRequest . HttpRequestException | ParseException e ) {
4264 throw new LookupException ("Failed to parse API response" , e );
4365 }
4466 } else if (request .code () == 404 ) {
4567 return Optional .empty ();
4668 } else {
47- throw new LookupException ("MinecraftAuth server returned bad code: " + request .code ());
69+ throw new LookupException ("MinecraftAuth server returned bad code: " + request .code () + " / " + body );
4870 }
4971 }
5072
@@ -59,20 +81,169 @@ public static Optional<Identity> lookup(AccountType from, Object identifier) thr
5981 public static Optional <Account > lookup (AccountType from , Object identifier , AccountType to ) throws LookupException {
6082 HttpRequest request = HttpRequest .get ("https://minecraftauth.me/api/lookup/" + to .name ().toLowerCase () + "?" + from .name ().toLowerCase () + "=" + identifier )
6183 .userAgent ("MinecraftAuthLib" );
84+ String body = request .body ();
6285
6386 if (request .code () / 100 == 2 ) {
6487 try {
65- Dynamic response = Dynamic .from (JSON_PARSER .parse (request . body () ));
88+ Dynamic response = Dynamic .from (JSON_PARSER .parse (body ));
6689 String id = response .dget (to .name ().toLowerCase () + ".identifier" ).convert ().intoString ();
6790 return Optional .of (Account .from (to , id ));
68- } catch (ParseException e ) {
91+ } catch (HttpRequest . HttpRequestException | ParseException e ) {
6992 throw new LookupException ("Failed to parse API response" , e );
7093 }
7194 } else if (request .code () == 404 ) {
7295 return Optional .empty ();
7396 } else {
74- throw new LookupException ("MinecraftAuth server returned bad code : " + request .code ());
97+ throw new LookupException ("MinecraftAuth server returned bad response : " + request .code () + " / " + body );
7598 }
7699 }
77100
101+ private static boolean isFollowing (String serverToken , AccountType platform , UUID minecraftUuid ) throws LookupException {
102+ HttpRequest request = HttpRequest .get ("https://minecraftauth.me/api/following?platform=" + platform .name ().toLowerCase () + "&minecraft=" + minecraftUuid )
103+ .userAgent ("MinecraftAuthLib" )
104+ .authorization ("Basic " + serverToken );
105+ return expectTrue (request );
106+ }
107+
108+ private static boolean isSubscribed (String serverToken , AccountType platform , UUID minecraftUuid , Object data ) throws LookupException {
109+ HttpRequest request = HttpRequest .get ("https://minecraftauth.me/api/subscribed?platform=" + platform .name ().toLowerCase () + "&minecraft=" + minecraftUuid + (data != null ? "&data=" + data : "" ))
110+ .userAgent ("MinecraftAuthLib" )
111+ .authorization ("Basic " + serverToken );
112+ return expectTrue (request );
113+ }
114+
115+ /**
116+ * Query if the given Discord user ID is in the given Discord server
117+ * @param serverToken the server authentication token to query data for
118+ * @param minecraftUuid the Minecraft player UUID to query
119+ * @param serverId the Discord server ID to query
120+ * @return if the given Discord user (and the Minecraft Authentication bot) is in the given server
121+ * @throws LookupException if the API returns abnormal error code
122+ */
123+ public static boolean isDiscordMemberPresent (String serverToken , UUID minecraftUuid , String serverId ) throws LookupException {
124+ HttpRequest request = HttpRequest .get ("https://minecraftauth.me/api/discord/present?minecraft=" + minecraftUuid + "&server=" + serverId )
125+ .userAgent ("MinecraftAuthLib" )
126+ .authorization ("Basic " + serverToken );
127+ return expectTrue (request );
128+ }
129+ /**
130+ * Query if the given Discord user ID has the given Discord role
131+ * @param serverToken the server authentication token to query data for
132+ * @param minecraftUuid the Minecraft player UUID to query
133+ * @param roleId the Discord role ID to query
134+ * @return if the given Discord user has the given role
135+ * @throws LookupException if the API returns abnormal error code
136+ */
137+ public static boolean isDiscordRolePresent (String serverToken , UUID minecraftUuid , String roleId ) throws LookupException {
138+ return isSubscribed (serverToken , AccountType .DISCORD , minecraftUuid , roleId );
139+ }
140+
141+ /**
142+ * Query if the given Patreon uid is a patron of the server token's Patreon campaign
143+ * @param serverToken the server authentication token to query data for
144+ * @param minecraftUuid the Minecraft player UUID to query
145+ * @return if the given Patreon uid is a patron of the server token's Patreon campaign
146+ * @throws LookupException if the API returns abnormal error code
147+ */
148+ public static boolean isSubscribedPatreon (String serverToken , UUID minecraftUuid ) throws LookupException {
149+ return isSubscribed (serverToken , AccountType .PATREON , minecraftUuid , null );
150+ }
151+ /**
152+ * Query if the given Patreon uid is a patron of the server token's Patreon campaign
153+ * @param serverToken the server authentication token to query data for
154+ * @param minecraftUuid the Minecraft player UUID to query
155+ * @param tierTitle the title of the requested Patreon tier
156+ * @return if the given Patreon uid is a patron of the server token's Patreon campaign
157+ * @throws LookupException if the API returns abnormal error code
158+ */
159+ public static boolean isSubscribedPatreon (String serverToken , UUID minecraftUuid , String tierTitle ) throws LookupException {
160+ return isSubscribed (serverToken , AccountType .PATREON , minecraftUuid , tierTitle );
161+ }
162+
163+ /**
164+ * Query if the given Glimpse user is a sponsor of the server token's Glimpse user
165+ * @param serverToken the server authentication token to query data for
166+ * @param minecraftUuid the Minecraft player UUID to query
167+ * @return if the given Glimpse user is a sponsor of the server token's Glimpse user
168+ * @throws LookupException if the API returns abnormal error code
169+ */
170+ public static boolean isSubscribedGlimpse (String serverToken , UUID minecraftUuid ) throws LookupException {
171+ return isSubscribed (serverToken , AccountType .GLIMPSE , minecraftUuid , null );
172+ }
173+ /**
174+ * Query if the given Glimpse user is a sponsor of the server token's Glimpse user
175+ * @param serverToken the server authentication token to query data for
176+ * @param minecraftUuid the Minecraft player UUID to query
177+ * @param levelName the name of the requested Glimpse level
178+ * @return if the given Glimpse user is a sponsor of the server token's Glimpse user
179+ * @throws LookupException if the API returns abnormal error code
180+ */
181+ public static boolean isSubscribedGlimpse (String serverToken , UUID minecraftUuid , String levelName ) throws LookupException {
182+ return isSubscribed (serverToken , AccountType .GLIMPSE , minecraftUuid , levelName );
183+ }
184+
185+ /**
186+ * Query if the given Twitch uid is following the server token's Twitch channel
187+ * @param serverToken the server authentication token to query data for
188+ * @param minecraftUuid the Minecraft player UUID to query
189+ * @return if the given Twitch uid is following the server token's Twitch channel
190+ * @throws LookupException if the API returns abnormal error code
191+ */
192+ public static boolean isFollowingTwitch (String serverToken , UUID minecraftUuid ) throws LookupException {
193+ return isFollowing (serverToken , AccountType .TWITCH , minecraftUuid );
194+ }
195+ /**
196+ * Query if the given Twitch uid is subbed to the server token's Twitch channel
197+ * @param serverToken the server authentication token to query data for
198+ * @param minecraftUuid the Minecraft player UUID to query
199+ * @return if the given Twitch uid is subbed to the server token's Twitch channel
200+ * @throws LookupException if the API returns abnormal error code
201+ */
202+ public static boolean isSubscribedTwitch (String serverToken , UUID minecraftUuid ) throws LookupException {
203+ return isSubscribed (serverToken , AccountType .TWITCH , minecraftUuid , null );
204+ }
205+ /**
206+ * Query if the given Twitch uid is subbed to the server token's Twitch channel
207+ * @param serverToken the server authentication token to query data for
208+ * @param minecraftUuid the Minecraft player UUID to query
209+ * @param tier the required tier level to qualify as being subscribed
210+ * @return if the given Twitch uid is subbed to the server token's Twitch channel
211+ * @throws LookupException if the API returns abnormal error code
212+ */
213+ public static boolean isSubscribedTwitch (String serverToken , UUID minecraftUuid , SubTier tier ) throws LookupException {
214+ return isSubscribed (serverToken , AccountType .TWITCH , minecraftUuid , tier .getValue ());
215+ }
216+
217+ /**
218+ * Query if the player's YouTube account is subscribed to the server token's YouTube channel
219+ * @param serverToken the server authentication token to query data for
220+ * @param minecraftUuid the Minecraft player UUID to query
221+ * @return if the player's YouTube account is subscribed to the server token's YouTube channel
222+ * @throws LookupException if the API returns abnormal error code
223+ */
224+ public static boolean isSubscribedYouTube (String serverToken , UUID minecraftUuid ) throws LookupException {
225+ return isFollowing (serverToken , AccountType .GOOGLE , minecraftUuid );
226+ }
227+ /**
228+ * Query if the player's YouTube account is a paid member of the server token's YouTube channel
229+ * @param serverToken the server authentication token to query data for
230+ * @param minecraftUuid the Minecraft player UUID to query
231+ * @return if the player's YouTube account is a paid member of the server token's YouTube channel
232+ * @throws LookupException if the API returns abnormal error code
233+ */
234+ public static boolean isMemberYouTube (String serverToken , UUID minecraftUuid ) throws LookupException {
235+ return isSubscribed (serverToken , AccountType .GOOGLE , minecraftUuid , null );
236+ }
237+ /**
238+ * Query if the player's YouTube account is a paid member of the server token's YouTube channel
239+ * @param serverToken the server authentication token to query data for
240+ * @param minecraftUuid the Minecraft player UUID to query
241+ * @param tier the required tier level to qualify as being a member
242+ * @return if the player's YouTube account is a paid member of the server token's YouTube channel
243+ * @throws LookupException if the API returns abnormal error code
244+ */
245+ public static boolean isMemberYouTube (String serverToken , UUID minecraftUuid , String tier ) throws LookupException {
246+ return isSubscribed (serverToken , AccountType .GOOGLE , minecraftUuid , tier );
247+ }
248+
78249}
0 commit comments