Example #1
0
    async def google_search(self, message: discord.Message,
                            argument: str) -> None:
        if not argument:
            return

        google_config = get_config_section('search.google')
        results = await self.http_get_request_json(
            'https://www.googleapis.com/customsearch/v1',
            params={
                'q': argument,
                'key': google_config['api_key'],
                'cx': google_config['search_engine_id'],
                'safe': 'off' if message.channel.is_nsfw() else 'active',
                'num': '1',
            })

        search_result, *rest = results.get('items', [None])
        if not search_result:
            return await message.channel.send(
                f'No results found for `{argument}`')

        return await message.channel.send(
            f'**{search_result["title"]}**\n'
            f'<{search_result["link"]}>\n'
            f'{search_result["snippet"]}', )
Example #2
0
    async def google_search(self, message: discord.Message,
                            argument: str) -> None:
        if not argument:
            return

        google_config = get_config_section('search.google')
        results = await self.http_get_request(
            'https://www.googleapis.com/customsearch/v1?' +
            urlencode({
                'q': argument,
                'key': google_config['api_key'],
                'cx': google_config['search_engine_id'],
                'num': '1',
            }))

        json_results = json.loads(results)
        search_result, *rest = json_results.get('items', [None])
        if not search_result:
            return await message.channel.send(
                f'No results found for `{argument}`')

        return await message.channel.send(
            f'**{search_result["title"]}**\n'
            f'<{search_result["link"]}>'
            f'\n'
            f'{search_result["snippet"]}\n', )
Example #3
0
    async def youtube_search(self, message: discord.Message,
                             argument: str) -> None:
        if not argument:
            return

        youtube_config = get_config_section('search.youtube')
        results = await self.http_get_request(
            'https://www.googleapis.com/youtube/v3/search',
            params={
                'q': argument,
                'part': 'id',
                'type': 'video',
                'key': youtube_config['api_key'],
                'maxResults': '1',
            })

        json_results = json.loads(results)
        search_result, *rest = json_results.get('items', [None])
        if not search_result:
            return await message.channel.send(
                f'No results found for `{argument}`')

        return await message.channel.send(
            f'https://www.youtube.com/watch?v={search_result["id"]["videoId"]}'
        )
Example #4
0
    def is_rate_limited(self, action: str, user_id: int) -> bool:
        rate_limits = self.get_rate_limits(action)
        if not user_id in rate_limits:
            return False

        rate_limit_config = get_config_section('ratelimits')
        duration = timedelta(seconds=rate_limit_config.getint(action))
        return rate_limits[user_id] + duration > datetime.now()
Example #5
0
    def __init__(self, *, loop=None, **options):
        discord_config = get_config_section('discord')

        options.setdefault('max_messages', discord_config.getint('max_messages'))

        super().__init__(
            loop=loop,
            **options,
        )
Example #6
0
async def get_connection_pool():
    qdb_config = get_config_section('quotes')
    return await aiomysql.create_pool(
        host=qdb_config['hostname'],
        port=qdb_config.getint('post', 3306),
        user=qdb_config['username'],
        password=qdb_config['password'],
        db=qdb_config['database'],
    )
Example #7
0
    def is_rate_limited(self, user_id: int, action: str,
                        *sections: Union[str, int]) -> bool:
        rate_limits = self.get_rate_limits(action, *sections)
        if user_id not in rate_limits:
            return False

        rate_limit_config = get_config_section('ratelimits')
        duration = timedelta(seconds=rate_limit_config.getint(action))
        return rate_limits[user_id] + duration > datetime.now()
Example #8
0
    async def metar(self, message: discord.Message, argument: str) -> None:
        if not argument:
            return

        avwx_config = get_config_section('search.avwx')
        results = await self.http_get_request(f'https://avwx.rest/api/metar/{argument}', params={
            'format': 'json',
            'token': avwx_config['api_key']
        })

        json_results = json.loads(results)
        if 'error' in json_results:
            return await message.channel.send(f'```{json_results["error"]}```')

        return await message.channel.send(f'```{json_results["raw"]}```')
Example #9
0
    def __init__(self, *, loop=None, **options):
        discord_config = get_config_section('discord')

        options.setdefault('max_messages',
                           discord_config.getint('max_messages'))

        intents = discord.Intents.default()
        intents.members = True
        super().__init__(
            loop=loop,
            intents=intents,
            **options,
        )

        with open('brain.json', 'rt') as f:
            self.chat_brain = markovify.Text.from_json(f.read())
Example #10
0
    async def stock(self, message: discord.Message, argument: str) -> None:
        if not argument:
            return

        argument = argument.upper()
        alpha_vantage_config = get_config_section('search.alpha-vantage')
        results = await self.http_get_request('https://www.alphavantage.co/query', params={
            'function': 'TIME_SERIES_DAILY',
            'symbol': argument,
            'apikey': alpha_vantage_config['api_key'],
        })

        json_results = json.loads(results)
        time_series = json_results.get('Time Series (Daily)', {})
        if not time_series:
            return await message.channel.send(f'No results found for `{argument}`')

        latest_time_stamp = max(time_series, key=datetime.fromisoformat)
        return await message.channel.send(f"**{argument}**: {time_series[latest_time_stamp]['4. close']}")
Example #11
0
    async def metar(self, message: discord.Message, argument: str) -> None:
        if not argument:
            return

        avwx_config = get_config_section('search.avwx')
        try:
            results = await self.http_get_request_json(
                f'https://avwx.rest/api/metar/{argument}',
                params={
                    'format': 'json',
                    'token': avwx_config['api_key'],
                })

            if 'error' in results:
                return await message.channel.send(f'```{results["error"]}```')

            return await message.channel.send(f'```{results["raw"]}```')
        except JSONDecodeError:
            return await message.channel.send(
                f'```{argument.upper()} does not publish METAR```')
Example #12
0
    async def stock(self, message: discord.Message, argument: str) -> None:
        if not argument:
            return

        argument = argument.upper()
        finnhub_config = get_config_section('search.finnhub')
        result = await self.http_get_request_json(
            'https://finnhub.io/api/v1/quote',
            params={
                'symbol': argument,
                'token': finnhub_config['api_key'],
            })

        if not result:
            return await message.channel.send(
                f'No results found for `{argument}`')
        if 'error' in result:
            return await message.channel.send(
                f'API returned an error: `{result["error"]}`')

        daily_delta = ((result['c'] / result['pc']) - 1) * 100
        return await message.channel.send(
            f"**{argument}**: {result['c']:.2f} ({daily_delta:+.2f}%)")
Example #13
0
    async def google_image_search(self, message: discord.Message,
                                  argument: str) -> None:
        if not argument:
            return

        google_config = get_config_section('search.google')
        results = await self.http_get_request(
            'https://www.googleapis.com/customsearch/v1?' +
            urlencode({
                'q': argument,
                'searchType': 'image',
                'key': google_config['api_key'],
                'cx': google_config['search_engine_id'],
                'safe': 'off' if message.channel.is_nsfw() else 'active',
                'num': '1',
            }))

        json_results = json.loads(results)
        search_result, *rest = json_results.get('items', [None])
        if not search_result:
            return await message.channel.send(
                f'No results found for `{argument}`')

        return await message.channel.send(search_result["link"])
Example #14
0
    def run(self):
        discord_config = get_config_section('discord')

        super().run(discord_config['token'])
Example #15
0
    async def convert(self, message: discord.Message, argument: str) -> None:
        fixer_config = get_config_section('search.fixer')

        aliases = {
            'inches': 'inch',
            'cm': 'centimeter',
            'centimeters': 'centimeter',
            'ft': 'feet',
            'c': 'celsius',
            'f': 'fahrenheit',
            'k': 'kelvin',
            'mi': 'miles',
            'km': 'kilometers',
            'lbs': 'pounds',
            'kg': 'kilograms',
            'g': 'grams',
            'm': 'meters',
            'hectopascal': 'hPa',
            'inch of mercury': 'inHg',
            'inches of mercury': 'inHg',
            'inhg': 'inHg',
            'hpa': 'hPa',
        }

        conversions = {
            'feet': {
                'centimeter': lambda ft: ft * 30.48,
                'inch': lambda inch: inch * 12.0,
                'meters': lambda m: m / 3.2808,
            },
            'inch': {
                'centimeter': lambda inch: inch * 2.54,
                'feet': lambda ft: ft / 12.0,
                'meters': lambda m: m / 39.37,
            },
            'centimeter': {
                'inch': lambda cm: cm / 2.54,
                'feet': lambda ft: ft / 30.48,
                'meters': lambda m: m / 100,
            },
            'fahrenheit': {
                'celsius': lambda c: (c - 32) * 5 / 9,
                'kelvin': lambda k: (k - 32) * 5 / 9 + 273.15,
            },
            'celsius': {
                'fahrenheit': lambda f: (f * 9 / 5) + 32,
                'kelvin': lambda k: k + 273.15,
            },
            'kelvin': {
                'fahrenheit': lambda f: (f - 273.15) * 9 / 5 + 32,
                'celsius': lambda c: c - 273.15,
            },
            'miles': {
                'kilometers': lambda km: km * 1.609344,
                'meters': lambda m: m * 1609.344,
            },
            'kilometers': {
                'miles': lambda mi: mi / 1.609344,
                'meters': lambda m: m * 1000,
            },
            'pounds': {
                'kilograms': lambda kg: kg / 2.2046226218,
                'grams': lambda g: g / 0.0022046,
            },
            'kilograms': {
                'pounds': lambda lbs: lbs * 2.2046226218,
                'grams': lambda g: g * 1000,
            },
            'grams': {
                'pounds': lambda lbs: lbs * 453.59237,
                'kilograms': lambda kg: kg / 1000,
            },
            'inHg': {
                'hPa': lambda hPa: hPa * 33.8639,
            },
            'hPa': {
                'inHg': lambda inHg: inHg / 33.8639,
            },
            'meters': {
                'centimeter': lambda cm: cm * 100,
                'inch': lambda inch: inch * 39.37,
                'feet': lambda ft: ft * 3.2808,
                'miles': lambda mi: mi * 0.00062137,
                'kilometers': lambda km: km / 1000,
            },
        }

        @memoize
        async def get_supported_symbols() -> set[str]:
            results = await self.http_get_request_json(
                'http://data.fixer.io/api/symbols',
                params={
                    'access_key': fixer_config.get('api_key'),
                })

            return set(results['symbols'].keys())

        try:
            left, to_unit = re.split(r'\s+(?:to|in)\s+',
                                     argument,
                                     flags=re.IGNORECASE,
                                     maxsplit=1)
            amount, from_unit = filter(
                None, re.split(r'(\-?\d+(?:\.?\d+)?)\s*', left))
            amount, from_unit, to_unit = float(
                amount), from_unit.lower(), to_unit.lower()
        except (KeyError, ValueError):
            return await message.add_reaction('❓')

        try:
            # Unit conversion
            to_unit = aliases.get(to_unit, to_unit)
            from_unit = aliases.get(from_unit, from_unit)

            return await message.channel.send(
                f'{amount:.2f} {from_unit} = {conversions[from_unit][to_unit](amount):.2f} {to_unit}',
            )
        except (KeyError, ValueError):
            # Currency conversion
            from_unit = from_unit.upper()
            to_unit = to_unit.upper()

            supported_symbols = await get_supported_symbols()
            if from_unit not in supported_symbols or to_unit not in supported_symbols:
                return await message.add_reaction('❓')

            result = await self.http_get_request_json(
                'http://data.fixer.io/api/latest',
                params={
                    'access_key': fixer_config.get('api_key'),
                    'symbols': f"{from_unit},{to_unit}",
                })

            if not result['success']:
                return await message.channel.send(
                    f'API returned error: ```{result["error"]["info"]}```')

            converted = amount / result["rates"][from_unit] * result["rates"][
                to_unit]
            return await message.channel.send(
                f'{amount:.2f} {from_unit} = {converted:.2f} {to_unit}', )