Mercurial > hg > skillbot-df
view WebService-EveOnline_changes/Base.pm @ 36:02576525bddb default tip
Added the \!isk command, had to change some stuff at 2 files of WebService::EveOnline (cpan: WebService-EveOnline-0.62) added those in a seperate folder. (Tried checking the http://theantipop.org/eve/trunk/WebService-EveOnline/ svn repo, but that seems to be in diff with the one offered via cpan.)
author | df@i1600 |
---|---|
date | Thu, 03 Dec 2009 18:47:45 +0100 |
parents | |
children |
line wrap: on
line source
package WebService::EveOnline::Base; our $VERSION = "0.62"; use LWP::UserAgent; use HTTP::Request; use XML::Simple; use WebService::EveOnline::Cache; use WebService::EveOnline::API::Character; use WebService::EveOnline::API::Corporation; use WebService::EveOnline::API::Skills; use WebService::EveOnline::API::Transactions; use WebService::EveOnline::API::Journal; use WebService::EveOnline::API::Account; use WebService::EveOnline::API::Map; # U.G.L.Y. You ain't got no alibi (this is where we set up the API mappings, sort out the internal symbol conversion and set max cache times) # max_cache overrides the cache time set in the default EVE webservice response XML (e.g. shorter for wallet, longer for bloodline which # probably won't update every hour...) our $API_MAP = { # Character skills => { endpoint => 'char/CharacterSheet', params => [ [ 'character_id', 'characterID' ] ], max_cache => 900 }, balance => { endpoint => 'char/CharacterSheet', params => [ [ 'character_id', 'characterID' ] ], max_cache => 60 }, race => { endpoint => 'char/CharacterSheet', params => [ [ 'character_id', 'characterID' ] ], max_cache => 604800 }, bloodline => { endpoint => 'char/CharacterSheet', params => [ [ 'character_id', 'characterID' ] ], max_cache => 604800 }, attributes => { endpoint => 'char/CharacterSheet', params => [ [ 'character_id', 'characterID' ] ], }, enhancers => { endpoint => 'char/CharacterSheet', params => [ [ 'character_id', 'characterID' ] ], }, gender => { endpoint => 'char/CharacterSheet', params => [ [ 'character_id', 'characterID' ] ], max_cache => 604800 }, training => { endpoint => 'char/SkillInTraining', params => [ [ 'character_id', 'characterID' ] ], }, accounts => { endpoint => 'char/AccountBalance', params => [ [ 'character_id', 'characterID' ] ], max_cache => 60 }, transactions => { endpoint => 'char/WalletTransactions', params => [ [ 'character_id', 'characterID' ], [ 'before_trans_id', 'beforeTransID' ], [ 'account_key', 'accountKey' ], ], max_cache => 3600 }, kills => { endpoint => 'char/Killlog', params => [ [ 'character_id', 'characterID' ] ], }, orders => { endpoint => 'char/MarketOrders', params => [ [ 'character_id', 'characterID' ] ], }, assets => { endpoint => 'char/AssetList', params => [ [ 'character_id', 'characterID' ] ], }, # Corporation corp_accounts => { endpoint => 'corp/AccountBalance', params => [ [ 'character_id', 'characterID' ] ], max_cache => 60 }, corp_members => { endpoint => 'corp/MemberTracking', params => [ [ 'character_id', 'characterID' ] ], }, corp_assets => { endpoint => 'corp/AssetList', params => [ [ 'character_id', 'characterID' ] ], }, corp_sheet => { endpoint => 'corp/CorporationSheet', params => [ [ 'character_id', 'characterID' ] ], }, corp_transactions => { endpoint => 'corp/WalletTransactions', params => [ [ 'character_id', 'characterID' ], [ 'before_trans_id', 'beforeTransID' ], [ 'account_key', 'accountKey' ], ], max_cache => 3600 }, corp_kills => { endpoint => 'corp/Killlog', params => [ [ 'character_id', 'characterID' ] ], }, corp_orders => { endpoint => 'corp/MarketOrders', params => [ [ 'character_id', 'characterID' ] ], }, corp_baselist => { endpoint => 'corp/StarbaseList', params => [ [ 'character_id', 'characterID' ] ], }, corp_base => { endpoint => 'corp/StarbaseDetail', params => [ [ 'character_id', 'characterID' ] ], }, # Map map_jumps => { endpoint => 'map/Jumps', params => [ [ 'character_id', 'characterID' ] ], }, map_kills => { endpoint => 'map/Kills', params => [ [ 'character_id', 'characterID' ] ], }, map => { endpoint => 'map/Sovereignty', params => undef , }, # Global/Misc character => { endpoint => 'account/Characters', params => undef, max_cache => 3600 }, all_skills => { endpoint => 'eve/SkillTree', params => undef, max_cache => 86400 }, all_reftypes => { endpoint => 'eve/RefTypes', params => undef, }, }; =head2 new Called by WebService::EveOnline->new -- sets things up at the backend without cluttering things up. Doesn't die if not passed an api_key/user_id combination, unlike the latter. =cut sub new { my ($class, $params) = @_; $params ||= {}; $params->{cache_type} ||= "SQLite"; $params->{cache_user} ||= ""; $params->{cache_pass} ||= ""; $params->{cache_dbname} ||= ($^O =~ /MSWin/) ? "c:/windows/temp/webservice_eveonline.db" : "/tmp/webservice_eveonline.db"; $params->{cache_init} ||= "yes"; $params->{cache_maxage} ||= (86400 * 7 * 4); # time (s) between cache rebuilds. 28 days, for now. my $evecache = WebService::EveOnline::Cache->new( { eve_user_id => $params->{user_id}, cache_type => $params->{cache_type}, cache_dbname => $params->{cache_dbname} } ) if $params->{cache_init} eq "yes"; if ($evecache && $evecache->cache_age >= $params->{cache_maxage}) { $evecache->repopulate( { skills => call_api('all_skills'), map => call_api('map') } ); } else { $evecache ||= WebService::EveOnline::Cache->new( { cache_type => "no_cache" } ); } return bless({ _user_id => $params->{user_id}, _api_key => $params->{api_key}, _evecache => $evecache }, $class); } =head2 character, characters Pull back character objects based on your API key -- see examples/show_characters Singlar and plural are provided so as to allow grammatically correct usage given the appropriate context (they both do exactly the same thing under the hood and can be used interchangeably -- handy for contractors... ;-) ) =cut sub characters { return WebService::EveOnline::API::Character->new(@_); } sub character { return WebService::EveOnline::API::Character->new(@_); } =head2 corporation Pull back a corporation information object -- use on a character object for best effect. See examples/show_corporation =cut sub corporation { return WebService::EveOnline::API::Corporation->new(@_); } =head2 skill, skills Pull back skill objects on a character. See examples/skills_overview for more details. Singlar and plural are provided so as to allow grammatically correct usage given the appropriate context (they both do exactly the same thing under the hood and can be used interchangeably). =cut sub skill { return WebService::EveOnline::API::Skills->new(@_); } sub skills { return WebService::EveOnline::API::Skills->new(@_); } =head2 transaction, transactions Returns transaction objects for a particular character/corporation. Singular/plural as above; See examples/show_transactions for more details. =cut sub transaction { return WebService::EveOnline::API::Transactions->new(@_); } sub transactions { return WebService::EveOnline::API::Transactions->new(@_); } =head2 journal Placeholder, for the moment. =cut sub journal { return WebService::EveOnline::API::Journal->new(@_); } =head2 account, accounts Return detailed account objects for a particular character, including corporate account info. The first member of the array ALWAYS returns the selected character's personal account object -- subsequent accounts are from the corporation the character belongs to. See examples/show_character for an example of how to use this. =cut sub account { return WebService::EveOnline::API::Account->new(@_); } sub accounts { return WebService::EveOnline::API::Account->new(@_); } =head2 map Another placeholder. =cut sub map { return WebService::EveOnline::API::Map->new(@_); } =head2 $eve->user_id Returns the current user_id. =cut sub user_id { my ($self, $user_id) = @_; $self->{_user_id} = $user_id if $user_id; return $self->{_user_id}; } =head2 $eve->api_key Returns the current api_key. =cut sub api_key { my ($self, $api_key) = @_; $self->{_api_key} = $api_key if $api_key; return $self->{_api_key}; } =head2 $eve->call_api(<command>, <params>) Call the Eve API and retrieve the results. Look in the cache first. Cache results according to API map settings. =cut sub call_api { my ($self, $command, $params, $base) = @_; my $auth = { user_id => "", api_key => "" }; if (ref($base)) { $auth = { user_id => $base->user_id, api_key => $base->api_key }; } else { $command = $self; } if ( defined($API_MAP->{$command}) ) { my $cache = ref($self) ? $self->{_evecache} : $base->{_evecache}; my $gen_params = _gen_params($self, $API_MAP->{$command}->{params}, $params); my $cached_response = $cache->retrieve( { command => "$command", params => $gen_params } ) if ref($cache); return $cached_response if $cached_response; my $ua = LWP::UserAgent->new; $ua->agent("$WebService::EveOnline::AGENT/$WebService::EveOnline::VERSION"); my $req = HTTP::Request->new( POST => $WebService::EveOnline::EVE_API . $API_MAP->{$command}->{endpoint} . '.xml.aspx' ); $req->content_type("application/x-www-form-urlencoded"); my $content = 'userid=' . $auth->{user_id} . '&apikey=' . $auth->{api_key} . $gen_params; $req->content($content) ; my $res = $ua->request($req); if ($res->is_success) { my $xs = XML::Simple->new(); my $xml = $res->content; warn "RAW XML is:\n$xml\n" if $ENV{EVE_DEBUG} =~ m/xml/i; my $pre = $xs->XMLin($xml); my $data = {}; my $in_error_state = undef; # print out any error content if it's set. if ($pre->{error}) { # error 206 is returned on characters without corp permissions. ignore. FIXME: nasty hack if ($pre->{error}->{code} != "206") { $in_error_state = 1; $data->{error} = "EVE API Error: " . $pre->{error}->{content} . " (" . $pre->{error}->{code} . ")"; } } # at the moment, we deal in hashrefs. one day, these will be objects (like everything else will be ;-P) unless ($in_error_state) { if ($command eq "character") { $data = $pre->{result}->{rowset}->{row}; } elsif ($command eq "skills") { $data->{skills} = $pre->{result}->{rowset}->{skills}->{row} if $pre->{result}->{rowset}->{skills}->{row}; } elsif ($command eq "attributes") { $data = $pre->{result}->{attributes}; } elsif ($command eq "enhancers") { $data = $pre->{result}->{attributeEnhancers}; } elsif ($command eq "gender") { $data = $pre->{result}; } elsif ($command eq "race") { $data = $pre->{result}; } elsif ($command eq "bloodline") { $data = $pre->{result}; } elsif ($command eq "balance") { $data = $pre->{result}; } elsif ($command eq "training") { $data = $pre->{result}; } elsif ($command eq "kills") { $data = $pre->{result}->{rowset}->{row}; } elsif ($command eq "orders") { $data = $pre->{result}->{rowset}->{row}; } elsif ($command eq "corp_kills") { $data = $pre->{result}->{rowset}->{row}; } elsif ($command eq "corp_members") { $data = $pre->{result}->{rowset}->{row}; } elsif ($command eq "corp_orders") { $data = $pre->{result}->{rowset}->{row}; } elsif ($command eq "assets") { $data = $pre->{result}->{rowset}->{row}; } elsif ($command eq "transactions") { $data->{transactions} = $pre->{result}->{rowset}->{row} if $pre->{result}->{rowset}->{row}; } elsif ($command =~ /accounts/) { my $acc = $pre->{result}->{rowset}->{row}; $data->{accounts} = ref($acc) eq "HASH" ? [ $acc ] : $acc; } else { $data = $pre; return $data; } } $data->{_status} ||= "ok"; $data->{_xml} = $xml; $data->{_parsed_as} = $pre; my $stripped_data = undef; unless ($WebService::EveOnline::DEBUG_MODE) { $stripped_data = {}; foreach my $strip_debug (keys %{$data}) { next if $strip_debug =~ /^_/; # skip meta keys $stripped_data->{$strip_debug} = $data->{$strip_debug}; } } if ($cache && ($stripped_data || $data) && !$in_error_state) { # error results are not cached return $cache->store( { command => $command, obj => $self, data => $stripped_data || $data, params => $gen_params, cache_until => $pre->{cachedUntil}, max_cache => $API_MAP->{$command}->{max_cache} } ); } elsif ($in_error_state) { warn $data->{error} . "\n"; return undef; # better error handling is required...; } else { return $stripped_data || $data; } } else { warn "Error code received: " . $res->status_line . "\n" if $ENV{EVE_DEBUG}; return { _status => "error", message => $res->status_line, _raw => undef }; } } else { return { _status => "error", message => "Bad command", _raw => undef }; } } =head2 $character->before_trans_id Set to return transactions older than a particular trans id for character/corp transactions. =cut sub before_trans_id { my ($self, $before_trans_id) = @_; $self->{_before_trans_id} = $before_trans_id if $before_trans_id; return $self->{_before_trans_id} || undef; } =head2 id This will not return anything useful on the base class; call id on characters, accounts, transactions, etc. where appropriate. =cut sub id { return undef; } sub _gen_params { my ($self, $keys, $passed) = @_; return "" unless defined $keys; my @kvp = (); foreach my $param (@{$keys}) { my ($intkey, $evekey) = @{$param}; if ($self->can($intkey)) { push(@kvp, "$evekey=" . ($self->$intkey || $passed->{$intkey})) if ($self->$intkey || $passed->{$intkey}); } else { push(@kvp, "$evekey=" . ($passed->{$evekey} || $passed->{$intkey})) if ($passed->{$evekey} || $passed->{$intkey}); } } return '&' . (join('&', @kvp)); } 1;