eve-simple-esi

The Python 3+ library for simple and fast work with https://esi.evetech.net data.


License
MIT
Install
pip install eve-simple-esi==0.0.6

Documentation

Eve Simple ESI

The Python 3+ library for simple and fast work with https://esi.evetech.net data.

Thanks Qandra-Si ( https://github.com/Qandra-Si ) for help and basis of implementation

This library can:

  • locally autorize with eve-online user (with gui and without gui interfase)
  • automatically refresh autorization without gui
  • get data (include data require autorization)
  • post data (include data require autorization)

install:

pypi:

pip install eve-simple-esi

manual:

Just put eve_simple_esi.py to directory with your project

how to use:

  • initialization:

     import eve_simple_esi as esi
    
     settings={
     	'client_id':"<Client ID>", # go to https://developers.eveonline.com/ create app and get Client ID
     	'client_secret':"<Secret Key>", # go to https://developers.eveonline.com/ create app and get Secret Key
     	'client_callback_url':"<Callback URL>", # default http://localhost:8635/ need to be same as in your app in https://developers.eveonline.com/
     	'user_agent':"<User Agent string>",
     	'scopes':<list of scopes>, # ['publicData','esi-location.read_location.v1',...etc.]
     	'port':<port for local web server for authorization>, # default 8635
     }
    
     ESI=esi.ESI(settings)
  • get data:

     data=ESI.op('/characters/{character_id}/',params={'character_id':2117005244})
  • get multipaged data:

     data=ESI.op('/characters/{character_id}/assets/') # if cache is enabled you get all data from all pages with Etag and Last-Modified control
     # 'ESI.max_consistent_try' option can control maximum tries to get valid and consistent data (default 20)
  • get forced single page data:

     data=ESI.op('/characters/{character_id}/assets/',params={'page':6},single=True)
  • post data:

     data=ESI.op('/ui/autopilot/waypoint/',params={'add_to_beginning':False, 'clear_other_waypoints':False, 'destination_id':30000142}, method="POST")
  • post data with body:

     data=ESI.op('/universe/ids/',body=json.dumps(["Gila","Thrasher","Jita","CCP Alpha"]), method="POST")
  • put data with body:

     data=ESI.op('/fleets/{fleet_id}/',params={'fleet_id':123456789},body=json.dumps({"is_free_move": True,"motd": "Fleet now is Free Move"}), method="PUT")
  • delete data:

     data=ESI.op('/fleets/{fleet_id}/members/{member_id}/',params={'fleet_id':123456789,'member_id':987654321}, method="DELETE")
  • get data with headers and other fields:

     data=ESI.op('/characters/{character_id}/', raw=True)
  • gui autorization:

     ESI.gui_auth()

    The builtin webserver starts only when needed for authorization and automatically shutdown when no authorization jobs found

  • cli autorization:

     ESI.auth() #need to go by url and after autorization insert code from url (http://localhost:8635/?code=<requested_code>&state=...)
  • change character for request (if they storred):

     ESI.get("EVE Character Name") # if character never autorized in your program - ESI.gui_auth() or ESI.auth() calls automatically for login
  • complicated requests: documentation

     #action_obj:
     {
     	'get':str, 			# (Required) Api address of Action
     	
     	'link':str, 			# Create parameter with this link name and parent field data params.update({link:parent_field_data})
     	
     	'flags':list, 			# ESI flags for current action get request [flag,...] (individual for each action get request data). see supported flags
     	
     	'map':dict, 			# dict of anctions for fields {field_name:action_obj,...}
     	
     	'fields':list or str, 		# list of raw fields in result [field_name,...] (if it str return only this field raw data and ignore map and id functions)
     	
     	'name': str,			# rename parent field to this name
     	
     	'params': dict, 		# dict of additional params for request {'param_name':value,...}
     	
     	'list_filters':list of list 	# [[field_name,operator,value,filter_action], ...] 
     					# operator can be '==', '!=', '<', '>', '<=', '>=', 'in', 'not in', 'startswith', 'endswith', 're' 
     					# (with 're' operator your value must be compiled regexp object)
     					# action can be 'skip', 'stop'. see supported filter_action
     }
    
     #supported flags:
     'force_cache' 	# get data from cache and dont check etag
     'debug' 	# turns on debug
    
     #supported filter_action:
     'skip'		# skip current row
     'stop'		# skip current row, immediatley return collected data and stop
    

    examples

    • get character data:
       complicated_map={
       	'get':'/characters/{character_id}/',
       	'map':{
       		'alliance_id':{
       			'get':'/alliances/{alliance_id}/',
       			'fields':['name','ticker'],
       			'name':'alliance',
       			'map':{
       				'creator_id':{
       					'link':'character_id',
       					'get':'/characters/{character_id}/',
       					'fields':['name'],
       					'name':'creator'
       				}
       			}
       		},
       		'corporation_id':{
       			'get':'/corporations/{corporation_id}/',
       			'map':{
       				'ceo_id':{
       					'link':'character_id',
       					'get':'/characters/{character_id}/',
       					'fields':['name','security_status'],
       					'name':'ceo'
       				}
       			},
       			'name':'corporation',
       			'fields':['name','ticker']
       		}
       	},
       	'fields':['name','security_status','faction_id'],
       	'id':'character_id'
       }
       data=ESI.map(complicated_map)
      returns:
       {
       	"name": "Samanta ZORG",
       	"security_status": 4.550539685,
       	"character_id": "2112184541",
       	"alliance": {
       		"name": "DEOS Alliance",
       		"ticker": "DEOS",
       		"alliance_id": 99005266,
       		"creator": {
       			"name": "De-Caelo",
       			"character_id": 94177853
       		}
       	},
       	"corporation": {
       		"name": "DC Reunion",
       		"ticker": "DCXLL",
       		"corporation_id": 98313424,
       		"ceo": {
       			"name": "De-Caelo",
       			"security_status": 1.496001863,
       			"character_id": 94177853
       		}
       	}
       }
    • get corporate industry jobs:
       complicated_map={
       	'get':'/characters/{character_id}/',
       	'flags':['force_cache'],
       	'map':{
       		'corporation_id':{
       			'get':'/corporations/{corporation_id}/industry/jobs/',
       			'map':{
       				'product_type_id':{
       					'link':'type_id',
       					'get':'/universe/types/{type_id}/',
       					'flags':['force_cache'],
       					'fields':'name',
       					'name':'job'
       				},
       				'installer_id':{
       					'link':'character_id',
       					'get':'/characters/{character_id}/',
       					'flags':['force_cache'],
       					'fields':'name',
       					'name':'installer'
       				},
       				'facility_id':{
       					'link':'structure_id',
       					'get':'/universe/structures/{structure_id}/',
       					'flags':['force_cache'],
       					'fields':'name',
       					'name':'facility'
       				}
       			},
       			'fields':['job_id','start_date','end_date','status','runs','activity_id'],
       			'params':{'include_completed':True},
       			'name':'industry_jobs',
       			'list_filters':[
       				['status','==','delivered','skip'],
       				['start_date','<',"2020-06-26T22:13:56Z",'stop'],
       			]
       		}
       	}
       }
       data=ESI.map(complicated_map)
      returns:
       [
       	{
       		"job_id": 432601643,
       		"start_date": "2020-07-31T06:17:03Z",
       		"end_date": "2020-07-31T21:00:30Z",
       		"status": "cancelled",
       		"runs": 1,
       		"activity_id": 5,
       		"corporation_id": 98313424,
       		"job": "Strip Miner I Blueprint",
       		"installer": "Simba Researcher",
       		"facility": "A4B-V5 - Lab House"
       	},
       	{
       		"job_id": 430265203,
       		"start_date": "2020-07-08T13:14:32Z",
       		"end_date": "2020-09-11T06:52:12Z",
       		"status": "active",
       		"runs": 1,
       		"activity_id": 4,
       		"corporation_id": 98313424,
       		"job": "Capital Hull Repairer I Blueprint",
       		"installer": "Irida ZORG",
       		"facility": "A4B-V5 - Lab House"
       	},
       	{
       		"job_id": 429341629,
       		"start_date": "2020-06-29T15:31:43Z",
       		"end_date": "2020-06-30T06:21:29Z",
       		"status": "cancelled",
       		"runs": 1,
       		"activity_id": 5,
       		"corporation_id": 98313424,
       		"job": "Radio L Blueprint",
       		"installer": "Himera dior",
       		"facility": "A4B-V5 - Lab House"
       	},
       	...
       ]
  • get character in initialize:

     ESI=esi.ESI(settings,name="EVE Character Name")
  • force cli autorization if no storred character:

     ESI=esi.ESI(settings,name="EVE Character Name", gui=False)
  • use multiplue instance:

     import eve_simple_esi as esi
     
     web_server=esi.ESIAuthWebServer(local_address='localhost', port=8635) # make one instance of webserver for all ESI instances
     
     ESI1=esi.ESI(settings, name="first EVE Character Name", callback_web_server=web_server)
     ESI2=esi.ESI(settings, callback_web_server=web_server)
     ESI3=esi.ESI(settings, callback_web_server=web_server)
     ESI3.gui_auth()
  • fash user switch:

     import eve_simple_esi as esi
     
     ESI=esi.ESI(settings, name="first EVE Character Name")
     data=ESI.op('/characters/{character_id}/')
     ESI.get("second EVE Character Name")
     data=ESI.op('/characters/{character_id}/')
     data=ESI.op('/ui/autopilot/waypoint/',params={'add_to_beginning':False, 'clear_other_waypoints':False, 'destination_id':30000142}, method="POST")
     ESI.get("third EVE Character Name")
     data=ESI.op('/characters/{character_id}/')
  • autoapply self character information if autorized:

     ESI=esi.ESI(settings,name="EVE Character Name")
     data=ESI.op('/characters/{character_id}/') # data for character_id with "EVE Character Name" name
     data=ESI.op('/characters/{character_id}/',params={'character_id':2117005244}) # data for character_id: 2117005244
  • you also can use your own function to get all messages from ESI class:

     def my_print_function(text_string):
     	...
     	print(text_string) # as example
     	...
     	
     ESI=esi.ESI(settings,callback_print=my_print_function)
  • and your own function for request auth_code:

     def my_input_function(text_string):
     	...
     	return input(text_string) # as example
     	
     ESI=esi.ESI(settings,callback_input=my_input_function)
  • and your own class for store user data:

     class custom_callback_saved_data:
     	def read(char_name):
     		...
     		return json.loads(saved_data)
    
     	def write(char_name,data):
     		saved_data=json.dumps(data)
     		...
     	
     ESI=esi.ESI(settings,callback_saved_data=custom_callback_saved_data)
  • and your own webserver class:

     class custom_callback_web_server:
     	def __init__(self, address, port):
     		...
     	def reg_callback(state_string, on_success_function, on_error_function):
     		...
     	...
     ESI=esi.ESI(settings,callback_web_server=custom_callback_web_server)
  • and your own cache server class:

     class custom_callback_cache_server:
     	def Get(self,key):
     		#...
     		if key in cache:
     			return data
     		else:
     			return None
     	def Del(self,key):
     		#...
     	def Set(self,key,data):
     		#...
     	def Clear(self):
     		#...
     	def Close(self):
     		#...
     	def Sync(self):
     		#...
     
     ESI=esi.ESI(settings,callback_cache_server=custom_callback_cache_server)