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)
Beispiel #2
0
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]
Beispiel #5
0
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()
Beispiel #6
0
        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)
Beispiel #7
0
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"
Beispiel #8
0
 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)
Beispiel #9
0
 def test_esipy_client_wrong_cache(self):
     with self.assertRaises(ValueError):
         EsiClient(cache=DictCache)
Beispiel #10
0
 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')
Beispiel #11
0
 def test_esipy_client_without_cache(self):
     client_without_cache = EsiClient(cache=None)
     self.assertTrue(isinstance(client_without_cache.cache, DummyCache))
Beispiel #12
0
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)
Beispiel #13
0
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)
Beispiel #14
0
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
Beispiel #15
0
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.
Beispiel #16
0
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()
Beispiel #17
0
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
Beispiel #18
0
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
Beispiel #19
0
"""
    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'](
Beispiel #20
0
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)
Beispiel #21
0
# 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')

Beispiel #22
0
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):
Beispiel #23
0
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})
Beispiel #25
0
        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 :")
Beispiel #26
0
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)
Beispiel #27
0
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!'
Beispiel #28
0
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__):
Beispiel #30
0
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()