File Coverage

blib/lib/WebService/Mojang/Minecraft/UUIDLookup.pm
Criterion Covered Total %
statement 17 37 45.9
branch 0 14 0.0
condition 0 3 0.0
subroutine 6 8 75.0
pod 2 2 100.0
total 25 64 39.0


line stmt bran cond sub pod time code
1             package WebService::Mojang::Minecraft::UUIDLookup;
2              
3 1     1   14672 use 5.006;
  1         2  
4 1     1   4 use strict;
  1         1  
  1         16  
5 1     1   379 use Data::UUID;
  1         574  
  1         51  
6 1     1   434 use Moo;
  1         9300  
  1         4  
7 1     1   1564 use LWP::UserAgent;
  1         37386  
  1         35  
8 1     1   646 use JSON;
  1         8998  
  1         5  
9              
10             our $VERSION = '0.03';
11              
12             =head1 NAME
13              
14             WebService::Mojang::Minecraft::UUIDLookup - look up Minecraft usernames/UUIDs
15              
16             =head1 DESCRIPTION
17              
18             A simple module to use Mojang's API to look up a Minecraft user's UUID from
19             their username (and provide any previous names they've had), or given a UUID,
20             return all names that account has had.
21              
22              
23             =head1 SYNOPSIS
24              
25              
26             use WebService::Mojang::Minecraft::UUIDLookup;
27              
28             my $mojang_lookup = WebService::Mojang::Minecraft::UUIDLookup->new();
29              
30             # Look up a username and get their UUID and previous names
31             if (my $user_details = $mojang_lookup->lookup_user($username)) {
32             say "$username's UUID is " . $user_details->{uuid};
33             if ($user_details->{previous_names}) {
34             say "Previous names for $username: "
35             . join ',', @{ $user_details->{previous_names} };
36             }
37             } else {
38             warn "Username $username not found";
39             }
40              
41             # Or lookup a UUID and find the current username, and any previous ones
42             if (my $user_details = $mojang_lookup->lookup_uuid($user_uuid)) {
43             say "$user_uuid is $user_details->{username}";
44             if ($user_details->{previous_names}) {
45             say "Previous names for $user_details_>{username}: "
46             . join ',', @{ $user_details->{previous_names} };
47             }
48             } else {
49             warn "UUID $user_uuid not found";
50             }
51              
52             =cut
53              
54             has user_agent => (
55             is => 'rw',
56             isa => sub { my $val = shift; ref $val && $val->isa('LWP::UserAgent') },
57             default => sub {
58             LWP::UserAgent->new( agent => __PACKAGE__ . "/$VERSION" ),
59             },
60             );
61             has lookup_previous_usernames => (
62             is => 'rw',
63             default => 1,
64             );
65              
66             =head1 Methods
67              
68             =head2 lookup_user
69              
70             Given a username, return their UUID and any previous usernames they had (unless
71             the lookup_previous_usernames option is set to a false value; it defaults to
72             enabled, but if you don't care about previous usernames and want to save an API
73             call you can disable it.
74              
75             Returns a hash (in list context) or hashref (in scalar context) with the keys:
76              
77             =over
78              
79             =item C
80              
81             The UUID for this username; this identifies the Mojang account, and does not
82             change, even if the user renames their account.
83              
84             =item C
85              
86             The UUID for this username - as C, but formatted using L's
87             C method (e.g. C<85d699cb21774d538366f2cdf9dc93cd> as returned by
88             Mojang becomes C<36643538-3939-6263-3231-373734643533>).
89              
90             =item C
91              
92             The current username for this account
93              
94             =item C
95              
96             An arrayref of previous usernames this account has been known by, unless the
97             C attribute is set to a false value.
98              
99             =back
100              
101             If the account wasn't found, returns undef. Dies if it wasn't possible to
102             retrieve a response from Mojang.
103              
104             =cut
105              
106             sub lookup_user {
107 0     0 1   my ($self, $username) = @_;
108              
109 0           my $response = $self->user_agent->get(
110             "https://api.mojang.com/users/profiles/minecraft/$username"
111             );
112 0 0         if (!$response->is_success) {
113 0           die "Failed to query Mojang API: " . $response->status_line;
114             }
115 0 0         my $result = JSON::from_json($response->decoded_content)
116             or die "Failed to parse Mojang API response";
117            
118             my %return = (
119             uuid => $result->{id},
120             username => $result->{name},
121 0           );
122              
123             # Provide padded uuid too
124 0           $return{formatted_uuid} = Data::UUID->new->to_string($result->{id});
125              
126 0 0 0       if ($result->{id} && $self->lookup_previous_usernames) {
127 0           my $uuid_lookup = $self->lookup_uuid($result->{id});
128 0           $return{previous_usernames} = $uuid_lookup->{previous_usernames};
129             }
130 0 0         return wantarray ? %return : \%return;
131             }
132            
133              
134              
135             =head2 lookup_uuid
136              
137             Given a Mojang account UUID, returns a hash (in list context) or a hashref (in
138             scalar context) with the following keys:
139              
140             =over
141              
142             =item C
143              
144             The account's UUID (as you supplied)
145              
146             =item C
147              
148             The account's current username
149              
150             =item C
151              
152             Any previous usernames this account has used.
153              
154             =back
155              
156             If the account wasn't found, returns undef. Dies if it wasn't possible to
157             retrieve a response from Mojang.
158              
159             =cut
160              
161             sub lookup_uuid {
162 0     0 1   my ($self, $uuid) = @_;
163              
164 0           my $response = $self->user_agent->get(
165             "https://api.mojang.com/user/profiles/$uuid/names"
166             );
167 0 0         if (!$response->is_success) {
168 0           die "Failed to query Mojang API: " . $response->status_line;
169             }
170 0 0         my $result = JSON::from_json($response->decoded_content)
171             or die "Failed to parse Mojang API response";
172            
173 0           my $primary_username = pop @$result;
174             my %return = (
175             uuid => $uuid,
176             username => $primary_username->{name},
177 0           previous_usernames => [ map { $_->{name} } @$result ],
  0            
178             );
179              
180 0 0         return wantarray ? %return : \%return;
181             }
182              
183             =head1 AUTHOR
184              
185             David Precious, C<< >>
186              
187              
188             =head1 BUGS / CONTRIBUTING
189              
190             Bug reports and pull requests are welcomed on GitHub:
191              
192             L
193              
194              
195             =head1 LICENSE AND COPYRIGHT
196              
197             Copyright 2015 David Precious.
198              
199             This program is free software; you can redistribute it and/or modify it
200             under the terms of the the Artistic License (2.0). You may obtain a
201             copy of the full license at:
202              
203             L
204              
205             Any use, modification, and distribution of the Standard or Modified
206             Versions is governed by this Artistic License. By using, modifying or
207             distributing the Package, you accept this license. Do not use, modify,
208             or distribute the Package, if you do not accept this license.
209              
210             If your Modified Version has been derived from a Modified Version made
211             by someone other than you, you are nevertheless required to ensure that
212             your Modified Version complies with the requirements of this license.
213              
214             This license does not grant you the right to use any trademark, service
215             mark, tradename, or logo of the Copyright Holder.
216              
217             This license includes the non-exclusive, worldwide, free-of-charge
218             patent license to make, have made, use, offer to sell, sell, import and
219             otherwise transfer the Package with respect to any patent claims
220             licensable by the Copyright Holder that are necessarily infringed by the
221             Package. If you institute patent litigation (including a cross-claim or
222             counterclaim) against any party alleging that the Package constitutes
223             direct or contributory patent infringement, then this Artistic License
224             to you shall terminate on the date that such litigation is filed.
225              
226             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
227             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
228             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
229             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
230             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
231             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
232             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
233             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
234              
235              
236             =cut
237              
238             1; # End of WebService::Mojang::Minecraft::UUIDLookup