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   13633 use 5.006;
  1         2  
4 1     1   4 use strict;
  1         1  
  1         18  
5 1     1   366 use Data::UUID;
  1         524  
  1         50  
6 1     1   435 use Moo;
  1         10347  
  1         4  
7 1     1   1542 use LWP::UserAgent;
  1         34246  
  1         30  
8 1     1   587 use JSON;
  1         8623  
  1         5  
9              
10             our $VERSION = '0.04';
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             $return{formatted_uuid} = Data::UUID->new->to_string(
125             Data::UUID->new->from_string($result->{id})
126 0           );
127              
128 0 0 0       if ($result->{id} && $self->lookup_previous_usernames) {
129 0           my $uuid_lookup = $self->lookup_uuid($result->{id});
130 0           $return{previous_usernames} = $uuid_lookup->{previous_usernames};
131             }
132 0 0         return wantarray ? %return : \%return;
133             }
134            
135              
136              
137             =head2 lookup_uuid
138              
139             Given a Mojang account UUID, returns a hash (in list context) or a hashref (in
140             scalar context) with the following keys:
141              
142             =over
143              
144             =item C
145              
146             The account's UUID (as you supplied)
147              
148             =item C
149              
150             The account's current username
151              
152             =item C
153              
154             Any previous usernames this account has used.
155              
156             =back
157              
158             If the account wasn't found, returns undef. Dies if it wasn't possible to
159             retrieve a response from Mojang.
160              
161             =cut
162              
163             sub lookup_uuid {
164 0     0 1   my ($self, $uuid) = @_;
165              
166 0           my $response = $self->user_agent->get(
167             "https://api.mojang.com/user/profiles/$uuid/names"
168             );
169 0 0         if (!$response->is_success) {
170 0           die "Failed to query Mojang API: " . $response->status_line;
171             }
172 0 0         my $result = JSON::from_json($response->decoded_content)
173             or die "Failed to parse Mojang API response";
174            
175 0           my $primary_username = pop @$result;
176             my %return = (
177             uuid => $uuid,
178             username => $primary_username->{name},
179 0           previous_usernames => [ map { $_->{name} } @$result ],
  0            
180             );
181              
182 0 0         return wantarray ? %return : \%return;
183             }
184              
185             =head1 AUTHOR
186              
187             David Precious, C<< >>
188              
189              
190             =head1 BUGS / CONTRIBUTING
191              
192             Bug reports and pull requests are welcomed on GitHub:
193              
194             L
195              
196              
197             =head1 LICENSE AND COPYRIGHT
198              
199             Copyright 2015 David Precious.
200              
201             This program is free software; you can redistribute it and/or modify it
202             under the terms of the the Artistic License (2.0). You may obtain a
203             copy of the full license at:
204              
205             L
206              
207             Any use, modification, and distribution of the Standard or Modified
208             Versions is governed by this Artistic License. By using, modifying or
209             distributing the Package, you accept this license. Do not use, modify,
210             or distribute the Package, if you do not accept this license.
211              
212             If your Modified Version has been derived from a Modified Version made
213             by someone other than you, you are nevertheless required to ensure that
214             your Modified Version complies with the requirements of this license.
215              
216             This license does not grant you the right to use any trademark, service
217             mark, tradename, or logo of the Copyright Holder.
218              
219             This license includes the non-exclusive, worldwide, free-of-charge
220             patent license to make, have made, use, offer to sell, sell, import and
221             otherwise transfer the Package with respect to any patent claims
222             licensable by the Copyright Holder that are necessarily infringed by the
223             Package. If you institute patent litigation (including a cross-claim or
224             counterclaim) against any party alleging that the Package constitutes
225             direct or contributory patent infringement, then this Artistic License
226             to you shall terminate on the date that such litigation is filed.
227              
228             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
229             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
230             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
231             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
232             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
233             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
234             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
235             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
236              
237              
238             =cut
239              
240             1; # End of WebService::Mojang::Minecraft::UUIDLookup