pool_connections=20, pool_maxsize=300, ) # ESI objects to be imported esiapp = EsiApp(cache=LBCACHE, cache_time=21600, datasource=config.ESI_DATASOURCE) esisecurity = EsiSecurity(app=esiapp.get_latest_swagger, redirect_uri="%s%s" % ( config.ESI_REDIRECT_DOMAIN, '/sso/callback', ), client_id=config.ESI_CLIENT_ID, secret_key=config.ESI_SECRET_KEY, headers={'User-Agent': config.ESI_USER_AGENT}) esiclient = EsiClient(security=esisecurity, transport_adapter=TRANSPORT_ADAPTER, cache=LBCACHE, headers={'User-Agent': config.ESI_USER_AGENT}, retry_requests=True) esiclient_nocache = EsiClient(security=esisecurity, transport_adapter=TRANSPORT_ADAPTER, cache=None, headers={'User-Agent': config.ESI_USER_AGENT}, retry_requests=True) # register observers AFTER_TOKEN_REFRESH.add_receiver(token_update_observer)
from esipy import App from esipy import EsiClient from esipy import EsiSecurity # App.create(url, strict=True) # with url = the swagger spec URL, leave strict to default app = App.create( url="https://esi.tech.ccp.is/latest/swagger.json?datasource=tranquility") # basic client, for public endpoints only client = EsiClient( retry_requests=True, # set to retry on http 5xx error (default False) header={ 'User-Agent': 'Something CCP can use to contact you and that define your app' }, raw_body_only= False, # default False, set to True to never parse response and only return raw JSON string content. ) # generate the operation tuple # the parameters given are the actual parameters the endpoint requires market_order_operation = app.op['get_markets_region_id_orders']( region_id=10000002, type_id=34, order_type='all', ) # do the request response = client.request(market_order_operation)
print(f'{KIN3_common.timestamp()} : EsiApp latest loaded') # app_v1 = EsiApp().get_v1_swagger # print(f'{KIN3_common.timestamp()} : EsiApp v1 loaded') app_v2 = EsiApp().get_v2_swagger print(f'{KIN3_common.timestamp()} : EsiApp v2 loaded') security = EsiSecurity(redirect_uri=redirect_uri, client_id=client_id, secret_key=secret_key, headers={'User-Agent': 'something'}) print(f'{KIN3_common.timestamp()} : EsiSecurity loaded') client = EsiClient(security=security, retry_requests=True, headers={'User-Agent': 'something'}, header={'User-Agent': 'something'}) print(f'{KIN3_common.timestamp()} : EsiClient loaded') esi_latest = (app_latest, security, client) # esi_v1 = (app_v1, security, client) esi_v2 = (app_v2, security, client) print(f'{KIN3_common.timestamp()} : --------') #%% if token['expires_in'] < 1200: security.update_token({ 'access_token': '', 'expires_in': -1, 'refresh_token': token['refresh_token'] })
from esipy import App from esipy import EsiClient import json app = App.create( url="https://esi.tech.ccp.is/latest/swagger.json?datasource=tranquility") client = EsiClient( retry_requests=True, header={'User-Agent': 'DumpSkills'}, raw_body_only=False, ) fields = app.op['get_universe_categories_category_id'](category_id=16, ) response = client.request(fields) groups = response.data['groups'] gral = {} for group in groups: g = app.op['get_universe_groups_group_id'](group_id=group) response = client.request(g) group_name = response.data['name'] skills = response.data['types'] group_dict = {} for skill in skills: s = app.op['get_universe_types_type_id'](type_id=skill) response = client.request(s) group_dict[skill] = response.data['name'] gral[group_name] = [{'Category ID': group}, group_dict]
def load_user(character_id): """ Required user loader for Flask-Login """ return User.query.get(character_id) # ----------------------------------------------------------------------- # ESIPY Init # ----------------------------------------------------------------------- # create the app esiapp = App.create(config.ESI_SWAGGER_JSON) # init the security object esisecurity = EsiSecurity(app=esiapp,redirect_uri=config.ESI_CALLBACK,client_id=config.ESI_CLIENT_ID,secret_key=config.ESI_SECRET_KEY,) # init the client esiclient = EsiClient(security=esisecurity, cache=None, headers={'User-Agent': config.ESI_USER_AGENT}) # ----------------------------------------------------------------------- # Login / Logout Routes # ----------------------------------------------------------------------- def generate_token(): """Generates a non-guessable OAuth token""" chars = ('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') rand = random.SystemRandom() random_string = ''.join(rand.choice(chars) for _ in range(40)) return hmac.new( config.SECRET_KEY, random_string, hashlib.sha256 ).hexdigest()
cached = cache.get(key) return cached if cached is not None else default def invalidate(self, key): cache.delete(key) transport_adapter = HTTPAdapter( pool_connections=20, pool_maxsize=300, ) # ESI objects to be imported esiapp = App.create(config.ESI_SWAGGER_JSON) esisecurity = EsiSecurity( app=esiapp, redirect_uri="%s%s" % ( config.ESI_REDIRECT_DOMAIN, '/sso/callback', ), client_id=config.ESI_CLIENT_ID, secret_key=config.ESI_SECRET_KEY, ) esiclient = EsiClient(security=esisecurity, transport_adapter=transport_adapter, cache=LbCache(), headers={'User-Agent': config.ESI_USER_AGENT}) # register observers AFTER_TOKEN_REFRESH.add_receiver(token_update_observer)
app = App.create( url="https://esi.tech.ccp.is/latest/swagger.json?datasource=tranquility") # replace the redirect_uri, client_id and secret_key values # with the values you get from the STEP 1 ! security = EsiSecurity( app=app, redirect_uri='http://*****:*****@gmail.com'}, security=security) # this print a URL where we can log in print security.get_auth_uri(scopes=['esi-markets.structure_markets.v1']) tokens = security.auth( 'drsYPDYBwgMwNKkLOS2egrb-vlpxzITrrDJFiE-lO_4HKjVbLuXOfoGySZlR3hsw0') print tokens { "access_token": "frenafeifafrbaefluerbfeainb", "token_type": "Bearer", "expires_in": 1200, "refresh_token": "fera48ftea4at64fr684fae"
def test_esipy_client_with_cache(self): cache = DictCache() client_with_cache = EsiClient(cache=cache) self.assertTrue(isinstance(client_with_cache.cache, BaseCache)) self.assertEqual(client_with_cache.cache, cache)
def test_esipy_client_wrong_cache(self): with self.assertRaises(ValueError): EsiClient(cache=DictCache)
def test_esipy_client_with_headers(self): client_with_headers = EsiClient(headers={'User-Agent': 'foobar'}) self.assertEqual(client_with_headers._session.headers['User-Agent'], 'foobar')
def test_esipy_client_without_cache(self): client_without_cache = EsiClient(cache=None) self.assertTrue(isinstance(client_without_cache.cache, DummyCache))
class TestEsiPy(unittest.TestCase): CALLBACK_URI = "https://foo.bar/baz/callback" LOGIN_EVE = "https://login.eveonline.com" OAUTH_VERIFY = "%s/oauth/verify" % LOGIN_EVE OAUTH_TOKEN = "%s/oauth/token" % LOGIN_EVE CLIENT_ID = 'foo' SECRET_KEY = 'bar' BASIC_TOKEN = six.u('Zm9vOmJhcg==') SECURITY_NAME = 'evesso' @mock.patch('six.moves.urllib.request.urlopen') def setUp(self, urlopen_mock): # I hate those mock... thx urlopen instead of requests... urlopen_mock.return_value = open('test/resources/swagger.json') self.app = App.create('https://esi.tech.ccp.is/latest/swagger.json') self.security = EsiSecurity( app=self.app, redirect_uri=TestEsiPy.CALLBACK_URI, client_id=TestEsiPy.CLIENT_ID, secret_key=TestEsiPy.SECRET_KEY, ) self.cache = DictCache() self.client = EsiClient(self.security, cache=self.cache) self.client_no_auth = EsiClient(cache=self.cache, retry_requests=True) def tearDown(self): """ clear the cache so we don't have residual data """ self.cache._dict = {} def test_esipy_client_no_args(self): client_no_args = EsiClient() self.assertIsNone(client_no_args.security) self.assertTrue(isinstance(client_no_args.cache, DictCache)) self.assertEqual(client_no_args._session.headers['User-Agent'], 'EsiPy/Client - https://github.com/Kyria/EsiPy') self.assertEqual(client_no_args.raw_body_only, False) def test_esipy_client_with_headers(self): client_with_headers = EsiClient(headers={'User-Agent': 'foobar'}) self.assertEqual(client_with_headers._session.headers['User-Agent'], 'foobar') def test_esipy_client_with_adapter(self): transport_adapter = HTTPAdapter() client_with_adapters = EsiClient(transport_adapter=transport_adapter) self.assertEqual(client_with_adapters._session.get_adapter('http://'), transport_adapter) self.assertEqual(client_with_adapters._session.get_adapter('https://'), transport_adapter) def test_esipy_client_without_cache(self): client_without_cache = EsiClient(cache=None) self.assertTrue(isinstance(client_without_cache.cache, DummyCache)) def test_esipy_client_with_cache(self): cache = DictCache() client_with_cache = EsiClient(cache=cache) self.assertTrue(isinstance(client_with_cache.cache, BaseCache)) self.assertEqual(client_with_cache.cache, cache) def test_esipy_client_wrong_cache(self): with self.assertRaises(ValueError): EsiClient(cache=DictCache) def test_esipy_request_public(self): with httmock.HTTMock(public_incursion): incursions = self.client_no_auth.request( self.app.op['get_incursions']()) self.assertEqual(incursions.data[0].type, 'Incursion') self.assertEqual(incursions.data[0].faction_id, 500019) def test_esipy_request_authed(self): with httmock.HTTMock(*_all_auth_mock_): self.security.auth('let it bee') char_location = self.client.request( self.app.op['get_characters_character_id_location']( character_id=123456789)) self.assertEqual(char_location.data.station_id, 60004756) # force expire self.security.token_expiry = 0 char_location_with_refresh = self.client.request( self.app.op['get_characters_character_id_location']( character_id=123456789)) self.assertEqual(char_location_with_refresh.data.station_id, 60004756) def test_client_cache_request(self): @httmock.all_requests def fail_if_request(url, request): self.fail('Cached data is not supposed to do requests') incursion_operation = self.app.op['get_incursions'] with httmock.HTTMock(public_incursion_no_expires): incursions = self.client_no_auth.request(incursion_operation()) self.assertEqual(incursions.data[0].state, 'mobilizing') with httmock.HTTMock(public_incursion_no_expires_second): incursions = self.client_no_auth.request(incursion_operation()) self.assertEqual(incursions.data[0].state, 'established') with httmock.HTTMock(public_incursion): incursions = self.client_no_auth.request(incursion_operation()) self.assertEqual(incursions.data[0].state, 'mobilizing') with httmock.HTTMock(fail_if_request): incursions = self.client_no_auth.request(incursion_operation()) self.assertEqual(incursions.data[0].state, 'mobilizing') def test_client_warning_header(self): with httmock.HTTMock(public_incursion_warning): warnings.simplefilter('error') incursion_operation = self.app.op['get_incursions'] with self.assertRaises(UserWarning): self.client_no_auth.request(incursion_operation()) def test_client_raw_body_only(self): client = EsiClient(raw_body_only=True) self.assertEqual(client.raw_body_only, True) with httmock.HTTMock(public_incursion): incursions = client.request(self.app.op['get_incursions']()) self.assertIsNone(incursions.data) self.assertTrue(len(incursions.raw) > 0) incursions = client.request(self.app.op['get_incursions'](), raw_body_only=False) self.assertIsNotNone(incursions.data) def test_esipy_reuse_operation(self): operation = self.app.op['get_incursions']() with httmock.HTTMock(public_incursion): incursions = self.client_no_auth.request(operation) self.assertEqual(incursions.data[0].faction_id, 500019) # this shouldn't create any errors incursions = self.client_no_auth.request(operation) self.assertEqual(incursions.data[0].faction_id, 500019) def test_esipy_multi_request(self): operation = self.app.op['get_incursions']() with httmock.HTTMock(public_incursion): count = 0 for req, incursions in self.client_no_auth.multi_request( [operation, operation, operation], threads=2): self.assertEqual(incursions.data[0].faction_id, 500019) count += 1 # Check we made 3 requests self.assertEqual(count, 3) def test_esipy_backoff(self): operation = self.app.op['get_incursions']() start_calls = time.time() with httmock.HTTMock(public_incursion_server_error): incursions = self.client_no_auth.request(operation) self.assertEqual(incursions.data.error, 'broke') end_calls = time.time() # Check we retried 5 times self.assertEqual(incursions.data.count, 5) # Check that backoff slept for a sum > 2 seconds self.assertTrue(end_calls - start_calls > 2) def test_esipy_timeout(self): def send_function(*args, **kwargs): """ manually create a ConnectionError to test the retry and be sure no exception is thrown """ send_function.count += 1 raise ConnectionError send_function.count = 0 self.client_no_auth._session.send = mock.MagicMock( side_effect=send_function) operation = self.app.op['get_incursions']() with httmock.HTTMock(public_incursion): incursions = self.client_no_auth.request(operation) # there shouldn't be any exceptions self.assertEqual(incursions.status, 500) self.assertEqual(send_function.count, 5) def test_esipy_expired_response(self): operation = self.app.op['get_incursions'] with httmock.HTTMock(public_incursion_expired): warnings.filterwarnings('error', '.*returned expired result') with self.assertRaises(UserWarning): self.client_no_auth.request(operation()) warnings.resetwarnings() warnings.simplefilter('ignore') incursions = self.client_no_auth.request(operation()) self.assertEquals(incursions.status, 200)
class EsiCommands(Cog): def __init__(self, bot): self.bot = bot self.esi = EsiClient( retry_requests=True, headers={ 'User-Agent': f'application: MercuryBot contact: {self.bot.config["bot"]["user_agent"]}' }) def _get_esi_id(self, search: str, category: str, strict: bool) -> Union[list, int]: """ Returns the ID for the specified query from ESI. :param search: string representing the search query :param category: the category to search against :param strict: :return: int ID if strict is true, otherwise list of IDs; -1 if not found """ search_op = self.bot.esi_app.op['get_search']( categories=[category], search=search, strict=strict, ) search_response = self.esi.request(search_op) if category not in search_response.data: return -1 if strict: return search_response.data[category][0] else: return search_response.data[category] def _get_char_from_esi(self, char_id: int) -> Optional[dict]: """ Gets public data for the specified character_id. :param char_id: :return: """ char_op = self.bot.esi_app.op['get_characters_character_id']( character_id=char_id, ) try: char_response = self.esi.request(char_op) except APIException as e: logger.error( f"Error getting char with id {char_id} from ESI! Error: {e}") logger.error(traceback.print_exc()) return None return char_response.data def _get_alliance_from_esi(self, ally_id: int) -> Optional[dict]: """ Gets public data for the specified alliance_id :param ally_id: :return: """ ally_op = self.bot.esi_app.op['get_alliances_alliance_id']( alliance_id=ally_id, ) try: ally_response = self.esi.request(ally_op) except APIException as e: logger.error( f"Error getting alliance with id {ally_id} from ESI! Error: {e}" ) logger.error(traceback.print_exc()) return None return ally_response.data def _get_corporation_from_esi(self, corp_id: int) -> Optional[dict]: """ Gets public data for the specified corporation_id :param corp_id: :return: """ corp_op = self.bot.esi_app.op['get_corporations_corporation_id']( corporation_id=corp_id, ) try: corp_response = self.esi.request(corp_op) except APIException as e: logger.error( f"Error getting corporation with id {corp_id} from ESI! Error: {e}" ) logger.error(traceback.print_exc()) return None return corp_response.data def _get_system_from_esi(self, system_id: int) -> Optional[dict]: """ Gets static system data from esi for the specified system_id :param system_id: :return: """ sys_op = self.bot.esi_app.op['get_universe_systems_system_id']( system_id=system_id, ) try: system_response = self.esi.request(sys_op) except APIException as e: logger.error( f"Error getting system with id {system_id} from ESI! Error: {e}" ) logger.error(traceback.print_exc()) return None return system_response.data def _get_region_from_esi(self, region_id: int) -> Optional[dict]: """ Gets static region data from esi for the specified region_id. :param region_id: :return: """ reg_op = self.bot.esi_app.op['get_universe_regions_region_id']( region_id=region_id) try: region_response = self.esi.request(reg_op) except APIException as e: logger.error( f"Error getting region with id {region_id} from ESI! Error: {e}" ) logger.error(traceback.print_exc()) return None return region_response.data def _get_constellation_from_esi(self, constellation_id: int) -> Optional[dict]: """ Gets static constellation data from ESI for the specified constellation_id. :param constellation_id: :return: """ const_op = self.bot.esi_app.op[ 'get_universe_constellations_constellation_id']( constellation_id=constellation_id) try: constellation_response = self.esi.request(const_op) except APIException as e: logger.error( f"Error getting constellation with id {constellation_id} from ESI! Error: {e}" ) logger.error(traceback.print_exc()) return None return constellation_response.data def _get_star_from_esi(self, star_id: int) -> Optional[dict]: """ Gets the static star data from ESI for the given star_id. :param star_id: :return: """ star_op = self.bot.esi_app.op['get_universe_stars_star_id']( star_id=star_id) try: star_response = self.esi.request(star_op) except APIException as e: logger.error( f"Error getting star with id {star_id} from ESI! Error: {a}") logger.error(traceback.print_exc()) return None return star_response.data def _get_system_stats(self, system_id: int) -> Optional[dict]: """ Returns the following data for a given system: - Jumps - Kills - Sovereignty :param system_id: :return: """ # Get System Stats jump_op = self.bot.esi_app.op['get_universe_system_jumps']() kills_op = self.bot.esi_app.op['get_universe_system_kills']() sov_op = self.bot.esi_app.op['get_sovereignty_map']() try: jump_response = self.esi.request(jump_op) kills_response = self.esi.request(kills_op) sov_response = self.esi.request(sov_op) except APIException as e: logger.error(f"Error getting system stats from ESI! Error: {e}") logger.error(traceback.print_exc()) return None ret = dict() ret['sov'] = None for sys in jump_response.data: if sys['system_id'] == system_id: ret['ship_jumps'] = sys['ship_jumps'] break for sys in kills_response.data: if sys['system_id'] == system_id: ret['kills'] = sys break for sys in sov_response.data: if sys['system_id'] == system_id: if len(sys) == 1: break ret['sov'] = sys break return ret @commands.command(aliases=('char', 'ch')) async def character(self, ctx, *, character_name: str): """ Returns public data about the named character. """ # Get ID from ESI char_id = self._get_esi_id(character_name, "character", True) if char_id == -1: return await ctx.send( "Character not found. Please check your spelling and try again." ) # Get Public data char = self._get_char_from_esi(char_id) if char is None: return await ctx.send( "Something went wrong, please try again later.") corp = self._get_corporation_from_esi(char['corporation_id']) if corp is None: return await ctx.send( "Something went wrong, please try again later.") urln = quote_plus(char['name']) urls = { 'zkb': f'https://zkillboard.com/character/{char_id}/', 'who': f'https://evewho.com/pilot/{urln}' } dob = char['birthday'].v age = datetime.now(timezone.utc) - dob embed = discord.Embed(title=f'{char["name"]} Character Info') embed.set_author(name=self.bot.user.name, icon_url=self.bot.user.avatar_url_as(format='png')) embed.set_thumbnail( url=f'https://imageserver.eveonline.com/Character/{char_id}_128.jpg' ) # Fields embed.add_field(name='Corporation', value=f'{corp["name"]} [{corp["ticker"]}]', inline=True) embed.add_field(name='\u200B', value='\u200B', inline=True) # Empty Field if corp['alliance_id'] is not None: ally = self._get_alliance_from_esi(corp['alliance_id']) if ally is None: return await ctx.send( "Something went wrong, please try again later.") embed.add_field(name='Alliance', value=f'{ally["name"]} [{ally["ticker"]}]') embed.add_field(name='Birthday', value=dob.strftime("%a %d %b, %Y"), inline=True) embed.add_field(name='\u200B', value='\u200B', inline=True) # Empty Field embed.add_field(name='Age', value=strftdelta(age), inline=True) embed.add_field(name='Additional Information', value=f'{urls["zkb"]}\n{urls["who"]}', inline=False) return await ctx.send(embed=embed) @commands.command(aliases=('corp', 'co')) async def corporation(self, ctx, *, corporation: str): """ Returns public data about the specified corporation. """ # Get ID corp_id = self._get_esi_id(corporation, "corporation", True) if corp_id == -1: return await ctx.send( "Corporation not found. Please check your spelling and try again." ) # Get Corp data corp = self._get_corporation_from_esi(corp_id) if corp is None: return await ctx.send( "Something went wrong, please try again later.") ceo = self._get_char_from_esi(corp['ceo_id']) if ceo is None: return await ctx.send( "Something went wrong, please try again later.") urls = { 'zkb': f'https://zkillboard.com/corporation/{corp_id}/', 'dotlan': f'https://evemaps.dotlan.net/corp/{corp_id}' } embed = discord.Embed(title=f'{corp["name"]} Corp Info', color=discord.Color.green()) embed.set_author(name=self.bot.user.name, icon_url=self.bot.user.avatar_url_as(format='png')) embed.set_thumbnail( url= f'https://imageserver.eveonline.com/Corporation/{corp_id}_128.png') # Fields embed.add_field(name='Ticker', value=f'[{corp["ticker"]}]', inline=True) embed.add_field(name='\u200B', value='\u200B', inline=True) # Empty Field embed.add_field(name='Member Count', value=f'{corp["member_count"]}', inline=True) embed.add_field(name='CEO', value=f'{ceo["name"]}', inline=True) embed.add_field(name='\u200B', value='\u200B', inline=True) # Empty Field if corp['date_founded'] is not None: embed.add_field( name='Founded', value=corp["date_founded"].v.strftime("%a %d %b, %Y"), inline=True) if corp['alliance_id'] is not None: ally = self._get_alliance_from_esi(corp['alliance_id']) if ally is None: return ctx.send( "Something went wrong, please try again later.") embed.add_field(name='Alliance', value=f'{ally["name"]} [{ally["ticker"]}]', inline=False) embed.add_field(name='Additional Information', value=f'{urls["zkb"]}\n{urls["dotlan"]}', inline=False) return await ctx.send(embed=embed) @commands.command(aliases=('ally', )) async def alliance(self, ctx, *, alliance: str): """ Returns public data about the specified alliance. """ ally_id = self._get_esi_id(alliance, "alliance", True) if ally_id == -1: return await ctx.send( "Alliance not found. Please check your spelling and try again." ) ally = self._get_alliance_from_esi(ally_id) if ally is None: return await ctx.send( "Something went wrong, please try again later.") found_corp = self._get_corporation_from_esi( ally['creator_corporation_id']) if found_corp is None: return await ctx.send( "Something went wrong, please try again later.") founder = self._get_char_from_esi(ally['creator_id']) if founder is None: return await ctx.send( "Something went wrong, please try again later.") exec_corp = None if 'executor_corporation_id' in ally: exec_corp = self._get_corporation_from_esi( ally['executor_corporation_id']) if exec_corp is None: return await ctx.send( "Something went wrong, please try again later.") urls = { 'zkb': f'https://zkillboard.com/alliance/{ally_id}/', 'dotlan': f'https://evemaps.dotlan.net/alliance/{ally_id}' } title = f'{ally["name"]} Alliance Info' if exec_corp is None: title = title + ' (Closed)' embed = discord.Embed(title=title, color=discord.Color.blue()) embed.set_author(name=self.bot.user.name, icon_url=self.bot.user.avatar_url_as(format='png')) embed.set_thumbnail( url=f'https://imageserver.eveonline.com/Alliance/{ally_id}_128.png' ) # Fields embed.add_field(name='Ticker', value=f'[{ally["ticker"]}]', inline=True) embed.add_field(name='\u200B', value='\u200B', inline=True) # Empty Field if exec_corp is not None: embed.add_field( name='Executor Corp', value=f'{exec_corp["name"]} [{exec_corp["ticker"]}]', inline=True) embed.add_field(name='Founder', value=f'{founder["name"]}', inline=True) embed.add_field(name='\u200B', value='\u200B', inline=True) # Empty Field embed.add_field(name='Founding Corp', value=f'{found_corp["name"]} [{found_corp["ticker"]}]', inline=True) embed.add_field(name='Founding Date', value=ally["date_founded"].v.strftime("%a %d %b, %Y"), inline=True) embed.add_field(name='Additional Information', value=f'{urls["zkb"]}\n{urls["dotlan"]}', inline=False) return await ctx.send(embed=embed) @commands.command() async def status(self, ctx): """ Returns the current status of Tranquility """ # Get ESI status status_op = self.bot.esi_app.op['get_status']() try: status_response = self.esi.request(status_op) status_response = status_response.data except APIException as e: embed = discord.Embed(title="Tranquility Status", color=discord.Color.red()) embed.set_author( name=self.bot.user.name, icon_url=self.bot.user.avatar_url_as(format='png')) embed.set_thumbnail( url= f'https://en.wikipedia.org/wiki/CCP_Games#/media/File:CCP_Games_Logo.svg' ) embed.add_field(name="Status", value="*Offline*", inline=True) return await ctx.send(embed=embed) embed = discord.Embed(title="Tranquility Status", color=discord.Color.green()) embed.set_author(name=self.bot.user.name, icon_url=self.bot.user.avatar_url_as(format='png')) embed.set_thumbnail( url=f'https://e.dotlan.net/images/Alliance/434243723_128.png') status = "Online" if "vip" in status_response: if status_response["vip"]: status = f"*{status} (VIP)*" embed.add_field(name="Status", value=status, inline=True) embed.add_field(name='\u200B', value='\u200B', inline=True) # Empty Field embed.add_field(name="Player Count", value='{:,}'.format(status_response['players']), inline=True) embed.add_field(name="Server Version", value=status_response['server_version'], inline=True) embed.add_field(name='\u200B', value='\u200B', inline=True) # Empty Field embed.add_field(name="Uptime", value=strftdelta( datetime.now(timezone.utc) - status_response['start_time'].v), inline=True) return await ctx.send(embed=embed) @commands.command(aliases=('sys', )) async def system(self, ctx, *, system_name: str): """ Returns data about the specified system. """ if re.match(r'[Jj]([0-9]{6})', system_name) or system_name == "Thera": return await ctx.send( 'System Information not available for wormhole systems.') # Get System ID sys_id = self._get_esi_id(system_name, 'solar_system', True) if sys_id == -1: return await ctx.send( "System not found. Please check your spelling and try again.") # Get System Data system = self._get_system_from_esi(sys_id) if system is None: return await ctx.send( "Something went wrong, please try again later.") if 'planets' in system: planets = len(system['planets']) moons = 0 for planet in system['planets']: if 'moons' in planet: moons += len(planet['moons']) else: planets = 0 moons = 0 star = self._get_star_from_esi(system['star_id']) constellation = self._get_constellation_from_esi( system['constellation_id']) if constellation is None: return await ctx.send( "Something went wrong, please try again later.") region = self._get_region_from_esi(constellation['region_id']) if region is None: return await ctx.send( "Something went wrong, please try again later.") stats = self._get_system_stats(sys_id) thumb_url = f'https://images.evetech.net/types/{star["type_id"]}/icon' if stats['sov'] is not None: if 'faction_id' in stats['sov']: thumb_url = f'https://images.evetech.net/corporations/{stats["sov"]["faction_id"]}/logo' elif 'alliance_id' in stats['sov']: thumb_url = f'https://images.evetech.net/alliances/{stats["sov"]["alliance_id"]}/logo' elif 'corporation_id' in stats['sov']: thumb_url = f'https://images.evetech.net/corporations/{stats["sov"]["corporation_id"]}/logo' dotlan = f'http://evemaps.dotlan.net/system/{sys_id}/' zkill = f'https://zkillboard.com/system/{sys_id}/' embed = discord.Embed(title=f'{system["name"]} System Information') embed.set_author( name='CCP Games', icon_url='https://e.dotlan.net/images/Alliance/434243723_128.png') embed.set_thumbnail(url=thumb_url) # Fields embed.add_field( name='Sec Status / Class', value= f'{"{:.2f}".format(system["security_status"])} / {system["security_class"]}' ) embed.add_field(name='\u200B', value='\u200B', inline=True) # Empty Field embed.add_field(name='Region (Constellation)', value=f'{region["name"]} ({constellation["name"]})') embed.add_field(name='Planets / Moons', value=f'{planets} / {moons}') embed.add_field(name='\u200B', value='\u200B', inline=True) # Empty Field if 'stargates' in system: embed.add_field(name='Stargates', value=str(len(system['stargates']))) embed.add_field(name='Stats (Last Hour)', value=f'**Jumps:** {stats["ship_jumps"]} \n' f'**Ship Kills**: {stats["kills"]["ship_kills"]} \n' f'**NPC Kills:** {stats["kills"]["npc_kills"]}\n' f'**Pod Kills:** {stats["kills"]["pod_kills"]}', inline=False) embed.add_field(name='Additional Info', value=f'{dotlan} \n{zkill}') return await ctx.send(embed=embed)
class LinkListener(Cog): def __init__(self, bot): self.bot = bot self.esi = EsiClient( retry_requests=True, headers={ 'User-Agent': f'application: MercuryBot contact: {self.bot.config["bot"]["user_agent"]}' }) async def _get_killmail(self, kill_id: int) -> dict: """ Get killmail from zkill and ESI. :param kill_id: :return: """ # Get zkill data kill_api_url = f'https://zkillboard.com/api/killID/{kill_id}/' async with aiohttp.ClientSession() as session: zkill_km = await get_json(session, kill_api_url) zkill_km = zkill_km['resp'][0] # Get KM data via ESI km_op = self.bot.esi_app.op['get_killmails_killmail_id_killmail_hash']( killmail_id=kill_id, killmail_hash=zkill_km['zkb']['hash'], ) km_response = self.esi.request(km_op) km = km_response.data km['zkb'] = zkill_km['zkb'] return km async def _get_character_name_from_id(self, character_id: int) -> Optional[str]: """ Returns the name of a character for a given character_id. Returns None if the ID is not valid. :param character_id: :return: """ name_op = self.bot.esi_app.op["get_characters_character_id"]( character_id=character_id) try: name_response = self.esi.request(name_op) except APIException: logger.error( f'Error getting name for character with ID {character_id} from ESI.' ) logger.error(traceback.print_exc()) return None return name_response.data['name'] async def type_from_id(self, type_id: int) -> Optional[dict]: """ Returns a type ID from ESI for a given name. Return value of None indicates an invalid type name. :param type_id: :return: """ post_op = self.bot.esi_app.op['get_universe_types_type_id']( type_id=type_id) try: response = self.esi.request(post_op) except APIException: logger.error(f"Issue getting Type with ID {type_id} from ESI!") logger.error(traceback.print_exc()) return None return response.data @Cog.listener() async def on_message(self, message: discord.Message): if message.author == self.bot.user: return # Check for links re_match = re.match( r'(.*)(http[s]?://([A-Za-z]*).[a-zA-z]*(/[a-zA-z]*/?)([0-9]*)[a-zA-Z/]?)', message.content) """ Match Groups: Group 1 (match[1]): anything preceding the link. Group 2 (match[2]): The link in its entirety Group 3 (match[3]): The domain of the URL. This is how we determine if/how to process it. Group 4 (match[4]): Only used for zkill at the moment, to determine if the URL is a kill or not. Group 5 (match[5]): The ID we will need for processing. We know that all the services we want to process use only numeric IDs, so this is fine. (Though probably not the best if we wanted to add dscan.me support or something. """ if re_match: if re_match[3] == 'zkillboard': if re_match[4] == '/kill/': km = await self._get_killmail(re_match[5]) data = extract_mail_data(self.bot.esi_app, self.esi, km) embed = await build_kill_embed(data) return await message.reply(embed=embed) elif re_match[4] == '/character/': char_id = re_match[5] stats = await get_char_stats_from_zkill(char_id) if stats is None: return char_name = await self._get_character_name_from_id(char_id) embed = await build_threat_embed(stats, char_name, char_id) return await message.reply(embed=embed) else: return elif re_match[3] == 'evemarketer': type_id = re_match[5] type_data = await self.type_from_id(type_id) # Rename the type_id key for compatability with embed builder. type_data['id'] = type_data.pop('type_id') market_data = await get_market_data(type_id) embed = await build_market_embed(type_data, market_data['resp']) return await message.reply(embed=embed) else: return
import sqlite3 import datetime from esipy import App from esipy import EsiClient goods = ["Tritanium", "Pyerite", "Mexallon", "Isogen", "Nocxium", "Oxygen"] """list: List of trading goods. """ regions = ["Metropolis", "Heimatar", "Molden Heath", "Derelik", "Curse"] """list: List of regions. """ app = App.create( url="https://esi.tech.ccp.is/latest/swagger.json?datasource=tranquility") client = EsiClient( retry_requests=True, header={'User-Agent': 'Still Console Marcet Client'}, raw_body_only=False, ) conn = sqlite3.connect('eve.db') today = datetime.date.today() now = datetime.datetime.now() c = conn.cursor() def g_id(name): """ Internal function. Returns a response from ESI API with an inventory_type value. Args: name (str): Region name. Returns: Data with goods type id.
redis_client = redis.Redis(host='localhost', port=6379, db=0) cache = RedisCache(redis_client) # init the security object security = EsiSecurity( redirect_uri=config.ESI_CALLBACK, client_id=config.ESI_CLIENT_ID, secret_key=config.ESI_SECRET_KEY, # code_verifier=generate_code_verifier() headers={'User-Agent': config.ESI_USER_AGENT}) # init the client client = EsiClient( cache=cache, security=security, headers={'User-Agent': config.ESI_USER_AGENT}, retry_requests=True, ) ### Authenticate eve_sso_auth_url = security.get_auth_uri( state=helpers.generate_state_token(), # scopes=config.ESI_SCOPES # or None (default) if you don't need any scope scopes=['publicData']) webbrowser.open_new_tab(eve_sso_auth_url) code = input('Code: ') tokens = security.auth(code) security.verify()
utc = pytz.timezone('UTC') # Define PostgresSQL client connection = database.create_connection( "killmails", "postgres", cfg.db_password, "127.0.0.1", "5432" ) connection.autocommit = True cursor = connection.cursor() # Define ESI client esi_app = EsiApp() app = esi_app.get_latest_swagger client = EsiClient( retry_requests=True, # set to retry on http 5xx error (default False) headers={'User-Agent': cfg.agent}, raw_body_only=False, # default False, set to True to never parse response and only return raw JSON string content. ) # Start by getting the json file for the kills on the given dates headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'} print("Downloading json files of killmails") for date in cfg.dates: url = "https://zkillboard.com/api/history/" + date + ".json" print("Downloaded killmail list on " + date) response = requests.get(url, headers=headers) kill_dict = json.loads(response.content) print("Parsing kills on " + date) count = 0 for key in kill_dict: count = count + 1
connection.autocommit = True cursor = connection.cursor() esi_app = EsiApp() app = esi_app.get_dev_swagger security = EsiSecurity( redirect_uri='http://51.158.104.35:5000/tokens/new', client_id='1922eb4bb2294e1ab3f47f15b50de475', secret_key=cfg.secret, headers={'User-Agent': cfg.agent}, ) esi_client = EsiClient( retry_requests=True, headers={'User-Agent': cfg.agent}, security=security, ) class MyClient(discord.Client): async def start_tracking(self, fleet_commander, channel): boss_id = await self.get_character_id(fleet_commander) if not boss_id: await channel.send("Invalid FC name, tracking disabled. See help.") return access_token = await self.get_access_token(boss_id, channel) if not access_token: return
""" This code is released under an MIT license """ import networkx as nx from esipy import App from esipy import EsiClient import config graph = nx.DiGraph() queue = list() # LIFO queue esiapp = App.create(config.ESI_SWAGGER_JSON) # init the client esiclient = EsiClient(cache=None, headers={'User-Agent': config.ESI_USER_AGENT}) # This function gets all of the adjacent systems withing given max_depth (# of jumps) starting with current_location # Go through all stargates in the system and get their destinations. Add all of them in a queue # When done looping through stargates, pop current location node, you done here # Recursively call function to work with next queue element in LIFO manner # The function should stop when you start going out of given range def build_graph(root, current_location, max_depth): if len(queue) == 0: return longest_depth = nx.dag_longest_path_length(graph, root) if longest_depth > max_depth: path = nx.dag_longest_path(graph, root) graph.remove_node(path[-1]) return char_system_info_req = esiapp.op['get_universe_systems_system_id'](
app.config['CORPORATION_ID'] = 98538579 ## ESI from esipy import App as esiapp from esipy import EsiClient, EsiSecurity esi_app = esiapp.create( url="https://esi.tech.ccp.is/latest/swagger.json?datasource=tranquility") esi_security = EsiSecurity( app=esi_app, redirect_uri=app.config['ESI_CALLBACK_URL'], client_id=app.config['ESI_CLIENT_ID'], secret_key=app.config['ESI_SECRET_KEY'], ) esi_client = EsiClient( retry_requests=True, header={ 'User-Agent': 'Something CCP can use to contact you and that define your app' }, raw_body_only=False, security=esi_security) app.config['ESI_REDIRECT_URL'] = esi_security.get_auth_uri( scopes=['esi-contracts.read_corporation_contracts.v1'], state="None") app.config['esi_security'] = esi_security app.config['esi_client'] = esi_client app.config['esi_app'] = esi_app app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://' + app.config[ 'SQL_USER'] + ':' + app.config['SQL_PASSWORD'] + '@localhost/dev' db = SQLAlchemy(app)
# def _hook(url): # return 'file://'+os.getcwd()+'/swagger.t.json' # esiapp = App.load(mainApp.config.get('ESI_SWAGGER_JSON',''), url_load_hook=_hook) esiapp = App.load(mainApp.config.get('ESI_SWAGGER_JSON', '')) esiapp.prepare() esisecurity = EsiSecurity( app=esiapp, redirect_uri=mainApp.config.get('ESI_CALLBACK_URL', ''), client_id=mainApp.config.get('ESI_CLIENT_ID', ''), secret_key=mainApp.config.get('ESI_SECRET', ''), ) esiclient = EsiClient(security=esisecurity, cache=None, headers={'User-Agent': 'Aes Publica'}) from .models import User @lm.user_loader def load_user(id): return User.query.get(int(id)) @lm.unauthorized_handler def unauthorized_callback(): return redirect('/login')
zkill_request_headers = {'user-agent': config.ESI_USER_AGENT} # map of name to nickname, easter egg nicknames = {'Mynxee': 'Space Mom', 'Portia Tigana': 'Tiggs'} # create the app while True: try: esiapp = App.create(config.ESI_SWAGGER_JSON) break except Exception as inst: application.logger.error(inst) # init the client esiclient = EsiClient(security=None, cache=None, headers={'User-Agent': config.ESI_USER_AGENT}, retry_requests=True) # This class will create the standard retry decorator. # It only retries on a 500 status code. class Retry: # By default, retry up to this many times. MAX_TRIES = 3 # This method holds the validation check. def is_valid(self, resp): # By default, only retry if a status code is 500. return resp.status_code == 500 def __call__(self, func):
app.config.from_object(__name__) app.config['SECRET_KEY'] = (os.environ.get('APP_SECRET_KEY_2', 'kdjsfhkshdf')) sender = "*****@*****.**" recipient = "*****@*****.**" ###################################################################### security = EsiSecurity( redirect_uri=REDIRECT_URI, client_id=DEV_API_KEY, secret_key=DEV_API_SECRET_KEY, headers={'User-Agent': '*****@*****.**'}, ) esiapp = EsiApp().get_latest_swagger client = EsiClient(retry_requests=False, headers={'User-Agent': '*****@*****.**'}, security=security) ''' This is the first step, its a log in process for eve SSO, it returns a url for a user to log in from. Once a user logs in it will return a response URL that looks like this: http://localhost/oauth-callback?code=xKUaKODBeEyo2giHHrc9NQ&state=SomeRandomGeneratedState This will return a 404 (until the app is done and can properly reroute to the page to fill an order), you can use that code from within to get security tokens from it, using the code below ''' def login(): token = generate_token() return (security.get_auth_uri(state=token, scopes=[])) def generate_token():
import json import traceback from esipy import EsiApp, EsiClient, EsiSecurity # setup configuration config = configparser.RawConfigParser() config.read('config.conf') client_id = config.get('esi', 'client_id') secret_key = config.get('esi', 'secret_key') refresh_tokens = json.loads(config.get('esi', 'refresh_tokens')) # setup ESI objects print("Building EsiApp app...") app = EsiApp().get_latest_swagger security = EsiSecurity(redirect_uri='http://localhost:8888', client_id=client_id, secret_key=secret_key) client = EsiClient(retry_requests=True, headers={'User-Agent': 'https://github.com/gradiuscypher/eve_online_tools'}, security=security) class EvePit: def __init__(self): self.active_character = None self.active_character_id = None def set_active_character(self, refresh_token): """ Set the active character's authentication via their refresh token :param refresh_token: :return: """ # setup authentication for provided refresh token security.update_token({'access_token': '', 'expires_in': -1, 'refresh_token': refresh_token})
from esipy import EsiClient from esipy import EsiSecurity esi_app = App.create('https://esi.tech.ccp.is/latest/swagger.json?datasource=tranquility') esi_security = EsiSecurity( app=esi_app, redirect_uri='https://localhost/callback/', client_id='ab6c5ead15684e91914db83850aba714', secret_key='MpHBlfeDZPOVarvJRJB8EzsfM1WPL5u7CYiOXqQx' ) uri = esi_security.get_auth_uri(scopes=['esi-wallet.read_character_wallet.v1']) esi_client = EsiClient(esi_security) # Create response header to load afterwards back header_re = { "access_token": '%s' % file.acc, "token_type":"Bearer", "expires_in": int(file.exp_t_s), "refresh_token":"***static***" } #This was for authentication to generate auth-code to get access token print uri x=raw_input("Paste Code :")
class TheraWatch(Cog, command_attrs=dict(hidden=True)): """ Watch the EVE-Scout API for new Thera wormhole connections. """ def __init__(self, bot): self.bot = bot self.TYPE_MODELS = { 'region': TheraEveRegion, 'system': TheraEveSystem, 'constellation': TheraEveConstellation } self.last_thera = None self.channels = None self.esi = EsiClient( retry_requests=True, headers={ 'User-Agent': f'application: MercuryBot contact: {self.bot.config["bot"]["user_agent"]}' }, raw_body_only=False) self.thera.start() def cog_unload(self): self.thera.cancel() async def load_channels(self): """ Updates self.channels. :return: """ systems = await TheraEveSystem.all() constellations = await TheraEveConstellation.all() regions = await TheraEveRegion.all() self.channels = { 'systems': {x.system_id: await x.channels.all() for x in systems}, 'constellations': { x.constellation_id: await x.channels.all() for x in constellations }, 'regions': {x.region_id: await x.channels.all() for x in regions} } async def update_channels(self, location_type: str, location): """ Updates self.channels :param location: A location object :param location_type: string :return: """ plural = f'{location_type}s' self.channels[plural][location.pk] = await location.channels.all() async def location_from_id(self, location_type: str, location_id: int): """ Checks if the ID provided is valid for the type provided. :param location_type: string :param location_id: integer :return: Thera location model. """ RANGES = { 'region': [10000000, 13000000], 'constellation': [20000000, 23000000], 'system': [30000000, 33000000] } if not RANGES[location_type][0] <= location_id <= RANGES[ location_type][1] and location_id is not 0: return -1 if await self.TYPE_MODELS[location_type].filter(pk=location_id ).exists(): return await self.TYPE_MODELS[location_type].filter(pk=location_id ).first() if location_id is not 0: post_op = self.bot.esi_app.op['post_universe_names']( ids=[location_id]) response = self.esi.request(post_op) if location_type not in response.data[0]['category']: logger.debug(response.data) return -1 model_kwargs = { f'{location_type}_id': response.data[0]['id'], 'name': response.data[0]['name'] } location = self.TYPE_MODELS[location_type](**model_kwargs) await location.save() else: # If we want to add all regions take care of this special case. location = self.TYPE_MODELS[location_type](name="All Regions", region_id=0) await location.save() return location async def location_from_name(self, location_type: str, location_name: str): """ Returns the location object for a location using its name. :param location_type: string :param location_name: string :return: Thera location model. """ plural = f'{location_type}s' # Check the DB for the item if await self.TYPE_MODELS[location_type].filter(name=location_name ).exists(): return await self.TYPE_MODELS[location_type].filter( name=location_name).first() if location_name.lower() != "all regions": # Get the system ID from ESI. post_op = self.bot.esi_app.op['post_universe_ids']( names=[location_name]) response = self.esi.request(post_op) if plural not in response.data: return -1 model_kwargs = { f'{location_type}_id': response.data[plural][0]['id'], 'name': response.data[plural][0]['name'] } location = self.TYPE_MODELS[location_type](**model_kwargs) await location.save() else: # If we want to add all regions take care of this special case. location = self.TYPE_MODELS[location_type](name="All Regions", region_id=0) await location.save() return location async def load_last(self): """ Loads the last thera id seen. """ last_thera = await LastThera.first() if last_thera is not None: self.last_thera = last_thera.last_thera @commands.command(aliases=['set_tc', 'tc']) @checks.is_admin() async def set_thera_channel(self, ctx): """ Set the channel to post new thera connections into. """ channels = await TheraChannel.filter(pk=ctx.guild.id) if len(channels) is not 0: return await ctx.send( f'Thera channel already set for `{ctx.guild.name}`. ' f'To change it, please first unset the thera channel using ' f'the `unset_thera_channel` command.') # Set the Thera Channel guild_id = ctx.guild.id channel_id = ctx.channel.id channel = TheraChannel(guild_id=guild_id, channel_id=channel_id) await channel.save() return await ctx.send( f'{ctx.channel.mention} has been set as the ' f'Thera notifications channel for `{ctx.guild.name}`') @commands.command(aliases=['utc', 'delete_tc']) @checks.is_admin() async def unset_thera_channel(self, ctx): """ This command unsets the channel used for thera connection posts. Note: This command can be run from any channel. """ channels = await TheraChannel.filter(pk=ctx.guild.id) if len(channels) is 0: return await ctx.send( f'Thera channel not set for `{ctx.guild.name}`. ' f'Use the `set_thera_channel` command from ' f'the target channel to set it.') await channels[0].delete() # Update self.channels await self.load_channels() # Reloading channels is easier on delete. return await ctx.send(f'Unset thera channel for `{ctx.guild.name}`') @commands.command(aliases=['ts', 'tsys']) @checks.is_admin() async def thera_system(self, ctx, action, *, system): """ Add or remove watchlisted system. Both names and IDs are accepted. Valid Actions: add, remove """ # Get the TheraChannel channel = await TheraChannel.filter(pk=ctx.guild.id).first() if channel is None: return await ctx.send( f'A thera notifications channel must be set up before you can manage watchlisted ' f'locations. To set a thera notifications channel run the ' f'`set_thera_channel` from the target channel.') # First check if we have a name or id name = not system.isnumeric() # Get / Validate the system ID system_obj = None if name: # Get the system ID from ESI. system_obj = await self.location_from_name('system', system) if system_obj == -1: return await ctx.send( f'The system name provided does not appear to be valid. Please ' f'check the spelling and try again or try adding the system by ID.' ) else: system = int(system) system_obj = await self.location_from_id('system', system) if system_obj == -1: return await ctx.send( f'The system ID provided is not valid. Please check the ID and try again ' f'or try adding the system by name.') if action.lower() == 'add': # Make sure we dont have the same system on the list twice. if system_obj in await channel.systems.all(): return await ctx.send( f'System `{system}` already on watchlist.') # Add the system to the list and save the model. await channel.systems.add(system_obj) elif action.lower() == 'remove': # Make sure the system is on the list. if system_obj not in await channel.systems.all(): return await ctx.send( f'System `{system}` is not on the watchlist.') await channel.systems.remove(system_obj) else: return await ctx.send( f'`{action}` is an invalid action. Valid actions are `add` or `remove`.' ) actioned = f'{action}ed' await self.update_channels('system', system_obj) return await ctx.send(f'Watchlist System `{system}` {actioned}.') @commands.command(aliases=['tcon']) @checks.is_admin() async def thera_constellation(self, ctx, action, *, constellation): """ Add or remove a watchlisted constellation. Both names and IDs accepted. Valid Actions: add, remove """ # Get the TheraChannel channel = await TheraChannel.filter(pk=ctx.guild.id).first() if channel is None: return await ctx.send( f'A thera notifications channel must be set up before you can manage watchlisted ' f'locations. To set a thera notifications channel run the ' f'`set_thera_channel` from the target channel.') name = not constellation.isnumeric() constellation_obj = None # Get / Validate constellation id if name: # Get the constellation ID from ESI constellation_obj = await self.location_from_name( 'constellation', constellation) if constellation_obj == -1: return await ctx.send( f'The constellation name provided does not appear to be valid. ' f'Please check the spelling and try again or try adding using its ID.' ) else: constellation = int(constellation) constellation_obj = await self.location_from_id( 'constellation', constellation) if constellation_obj == -1: return await ctx.send( f'The constellation ID provided is not valid. Please check the ID and ' f'try again or try adding using its name.') if action.lower() == 'add': if constellation_obj in await channel.constellations.all(): return await ctx.send( f'Constellation `{constellation}` is already on watchlist.' ) await channel.constellations.add(constellation_obj) elif action.lower() == 'remove': if constellation_obj not in await channel.constellations.all(): return await ctx.send( f'Constellation `{constellation}` is not on the watchlist.' ) await channel.constellations.remove(constellation_obj) else: return await ctx.send( f'`{action}` is an invalid action. Valid actions are `add` and `remove`' ) await self.update_channels('constellation', constellation_obj) return await ctx.send( f'Watchlist Constellation `{constellation}` {action}ed') @commands.command(aliases=['tr', 'treg']) @checks.is_admin() async def thera_region(self, ctx, action, *, region): """ Add or remove a watchlisted region. Both names and IDs accepted. Valid Actions: add, remove """ # Get the TheraChannel channel = await TheraChannel.filter(pk=ctx.guild.id).first() if channel is None: return await ctx.send( f'A thera notifications channel must be set up before you can manage watchlisted ' f'locations. To set a thera notifications channel run the ' f'`set_thera_channel` from the target channel.') name = not region.isnumeric() region_obj = None # Get / Validate region id if name: # Get the region ID from ESI region_obj = await self.location_from_name('region', region) if region_obj == -1: return await ctx.send( f'The region name provided does not appear to be valid. Please check ' f'the spelling and try again or try adding it by ID.') else: region = int(region) region_obj = await self.location_from_id('region', region) if region_obj == -1: return await ctx.send( f'The region ID provided is not valid. Please check the ID and try again ' f'or try adding it by name.') if action.lower() == 'add': if region_obj in await channel.regions.all(): return await ctx.send(f'`{region}` already on the watchlist.') await channel.regions.add(region_obj) elif action.lower() == 'remove': if region_obj not in await channel.regions.all(): return await ctx.send(f'`{region}` is not on the watchlist.') await channel.regions.remove(region_obj) else: return await ctx.send( f'`{action}` is an invalid action. Valid actions are `add` and `remove`.' ) await self.update_channels('region', region_obj) return await ctx.send(f'Watchlist Region `{region}` {action}ed.') @tasks.loop(seconds=60.0) async def thera(self): url = 'https://www.eve-scout.com/api/wormholes' try: async with aiohttp.ClientSession() as session: resp = await get(session, url) hole = list(resp['resp'])[0] hole_id = hole['id'] source = hole['sourceSolarSystem'] if self.last_thera <= hole_id: pass # Do nothing elif source['name'] == "Thera": self.last_thera = hole_id # Ensure we keep track of the last thera id destination = hole['destinationSolarSystem'] if destination['id'] in self.channels['systems']: await self.process_hole(hole) elif destination['constellationID'] in self.channels[ 'constellations']: await self.process_hole(hole) elif destination['regionId'] in self.channels[ 'regions'] or 0 in self.channels['regions']: await self.process_hole(hole) except Exception as e: logger.warning("Exception occurred in thera loop.") logger.warning(traceback.format_exc()) @thera.before_loop async def before_thera(self): # Wait until the bot is ready await self.bot.wait_until_ready() # Load channels and the last thera id. await self.load_channels() await self.load_last() @thera.after_loop async def on_thera_cancel(self): if self.thera.is_being_cancelled(): if self.last_thera is not None: # Save last_thera. last_thera_obj = await LastThera.first() if last_thera_obj is None: new_obj = LastThera(last_thera=self.last_thera) await new_obj.save() else: last_thera_obj.last_thera = self.last_thera await last_thera_obj.save() async def process_hole(self, hole): """ Build the embed for a given hole, and build a dict of which channels to send it to. :param hole: :return: """ # Pull info from hole dict d_system = hole['destinationSolarSystem'] hole_type = hole['destinationWormholeType']['name'] if hole_type == 'K162': hole_type = hole['sourceWormholeType']['name'] system = d_system['name'] region = d_system['region']['name'] c_id = d_system['constellationID'] try: c_name = self.esi.request( self.bot.esi_app. op['get_universe_constellations_constellation_id']( constellation_id=c_id)).data['name'] except: print("oops") in_sig = hole['wormholeDestinationSignatureId'] out_sig = hole['signatureId'] # Build Discord Embed embed = discord.Embed(title="Thera Alert", color=discord.Color.blurple()) embed.set_author( name='EVE-Scout', icon_url= 'http://games.chruker.dk/eve_online/graphics/ids/128/20956.jpg') embed.set_thumbnail( url='https://www.eve-scout.com/images/eve-scout-logo.png') embed.set_footer(text=f"ID: {hole['id']}") embed.add_field(name='Region', value=region, inline=True) embed.add_field(name='\u200B', value='\u200B', inline=True) # Empty Field embed.add_field(name='System (Constellation)', value=f'{system} ({c_name})', inline=True) embed.add_field(name='Signature (In - Out)', value=f'`{in_sig}` - `{out_sig}`', inline=True) embed.add_field(name='\u200B', value='\u200B', inline=True) # Empty Field embed.add_field(name='Type', value=hole_type, inline=True) # Build channels for this hole send_channels = { 'system': list(), 'constellation': list(), 'region': list() } if d_system['id'] in self.channels['systems']: send_channels['system'] += self.channels['systems'][d_system['id']] elif d_system['constellationID'] in self.channels['constellations']: send_channels['constellation'] += self.channels['constellation'][ d_system['constellationId']] elif d_system['regionId'] in self.channels[ 'regions'] or 0 in self.channels['regions']: if 0 in self.channels[ 'regions']: # Send to anyone that specified all regions send_channels['region'] += self.channels['regions'][0] if d_system['regionId'] in self.channels[ 'regions']: # Send to anyone that specified *this* region. send_channels['region'] += self.channels['regions'][ d_system['regionId']] return await self.send_thera(embed, send_channels) async def send_thera(self, embed: discord.Embed, channels: dict): mentions = { 'system': "@everyone", 'constellation': "@here", 'region': "" } for k, v in channels.items(): for c in v: # Get channel channel = self.bot.get_channel(c.channel_id) await channel.send(content=mentions[k], embed=embed)
SECRET_KEY = '' SCOPES = [ 'esi-universe.read_structures.v1', 'esi-markets.structure_markets.v1' ] app = Flask(__name__) esi_app = App.create( url="https://esi.tech.ccp.is/latest/swagger.json?datasource=tranquility") security = EsiSecurity(app=esi_app, redirect_uri='http://127.0.0.1:5000/ESICallback', client_id=CLIENT_ID, secret_key=SECRET_KEY) client = EsiClient(retry_requests=True, header={'User-Agent': 'ESI Token Fetcher'}, security=security) webbrowser.open_new(security.get_auth_uri(scopes=SCOPES)) @app.route('/ESICallback') def esi_callback(): code = request.args.get('code', '') if code: tokens = security.auth(code) return str(tokens) else: return 'No code returned!'
from esipy import EsiClient from esipy import EsiApp from math import sqrt import datetime jumps = {"data": [], "expiry": None} kills = {"data": [], "expiry": None} client = EsiClient( retry_requests=True, # set to retry on http 5xx error (default False) headers={'User-Agent': 'Jagerbot'}, raw_body_only= False, # default False, set to True to never parse response and only return raw JSON string content. ) esi_app = EsiApp() app = esi_app.get_latest_swagger def get_jumps(): if jumps['expiry'] is None or jumps['expiry'] < datetime.datetime.utcnow(): get_system_jumps = app.op['get_universe_system_jumps']() jump_resp = client.request(get_system_jumps) jumps.update({"data": jump_resp.data}) jumps.update({ "expiry": datetime.datetime.utcnow() + datetime.timedelta(seconds=90) }) return jumps['data'] else: return jumps['data']
from lazyblacksmith.extension.esipy.operations import ( get_markets_region_id_orders) from lazyblacksmith.models import ItemPrice from lazyblacksmith.models import Region from lazyblacksmith.models import TaskState from lazyblacksmith.models import db from lazyblacksmith.utils.tasks import is_task_running from lazyblacksmith.utils.time import utcnow from esipy import EsiClient from flask import json from sqlalchemy.exc import SQLAlchemyError # (re)define some required objects esiclient = EsiClient(transport_adapter=transport_adapter, cache=None, headers={'User-Agent': config.ESI_USER_AGENT}, retry_requests=True) logger = logging.getLogger('lb.tasks') @celery_app.task(name="spawn_market_price_tasks", base=LbTask, bind=True) def spawn_market_price_tasks(self): """Celery task to spawn market prices update tasks""" self.start() region_list = Region.query.filter(Region.id.in_( config.ESI_REGION_PRICE)).all() for region in region_list: if not is_task_running(region.id, task_update_region_order_price.__name__):
print(f'{KIN3_common.timestamp()} : EsiApp latest loaded') # app_v1 = EsiApp().get_v1_swagger # print(f'{KIN3_common.timestamp()} : EsiApp v1 loaded') app_v2 = EsiApp().get_v2_swagger print(f'{KIN3_common.timestamp()} : EsiApp v2 loaded') security = EsiSecurity(redirect_uri=redirect_uri, client_id=client_id, secret_key=secret_key, headers={'User-Agent': 'something'}) print(f'{KIN3_common.timestamp()} : EsiSecurity loaded') client = EsiClient(security=security, retry_requests=True, headers={'User-Agent': 'something'}, header={'User-Agent': 'something'}) print(f'{KIN3_common.timestamp()} : EsiClient loaded') KIN3_Esi.esi_latest = (app_latest, security, client) # KIN3_Esi.esi_v1 = (app_v1, security, client) KIN3_Esi.esi_v2 = (app_v2, security, client) KIN3_Esi.is_tranquility_online = 'players' in KIN3_Esi.check_server_status() if KIN3_Esi.is_tranquility_online: print(f'{KIN3_common.timestamp()} : Tranquility server is online') else: print(f'{KIN3_common.timestamp()} : Tranquility server is offline') print(f'{KIN3_common.timestamp()} : --------') bot_token_file = open('./bot_token.txt', 'r') bot_token_lines = bot_token_file.readlines()