Esempio n. 1
0
def weather(text, reply):
    """weather <location> -- Gets weather data for <location>."""
    if not wunder_key:
        return "This command requires a Weather Underground API key."
    if not dev_key:
        return "This command requires a Google Developers Console API key."

    # use find_location to get location data from the user input
    try:
        location_data = find_location(text)
    except APIError as e:
        return e

    formatted_location = "{lat},{lng}".format(**location_data)

    url = wunder_api.format(wunder_key, formatted_location)
    response = requests.get(url).json()

    if response['response'].get('error'):
        return "{}".format(response['response']['error']['description'])

    forecast_today = response["forecast"]["simpleforecast"]["forecastday"][0]
    forecast_tomorrow = response["forecast"]["simpleforecast"]["forecastday"][1]

    # put all the stuff we want to use in a dictionary for easy formatting of the output
    weather_data = {
        "place"              : response['current_observation']['display_location']['full'],
        "conditions"         : response['current_observation']['weather'],
        "temp_f"             : response['current_observation']['temp_f'],
        "temp_c"             : response['current_observation']['temp_c'],
        "humidity"           : response['current_observation']['relative_humidity'],
        "wind_kph"           : response['current_observation']['wind_kph'],
        "wind_mph"           : response['current_observation']['wind_mph'],
        "wind_direction"     : response['current_observation']['wind_dir'],
        "today_conditions"   : forecast_today['conditions'],
        "today_high_f"       : forecast_today['high']['fahrenheit'],
        "today_high_c"       : forecast_today['high']['celsius'],
        "today_low_f"        : forecast_today['low']['fahrenheit'],
        "today_low_c"        : forecast_today['low']['celsius'],
        "tomorrow_conditions": forecast_tomorrow['conditions'],
        "tomorrow_high_f"    : forecast_tomorrow['high']['fahrenheit'],
        "tomorrow_high_c"    : forecast_tomorrow['high']['celsius'],
        "tomorrow_low_f"     : forecast_tomorrow['low']['fahrenheit'],
        "tomorrow_low_c"     : forecast_tomorrow['low']['celsius']
    }

    # Get the more accurate URL if available, if not, get the generic one.
    if "?query=," in response["current_observation"]['ob_url']:
        weather_data['url'] = web.shorten(response["current_observation"]['forecast_url'])
    else:
        weather_data['url'] = web.shorten(response["current_observation"]['ob_url'])

    reply("{place} - \x02Current:\x02 {conditions}, {temp_f}F/{temp_c}C, {humidity}, "
          "Wind: {wind_mph}MPH/{wind_kph}KPH {wind_direction}, \x02Today:\x02 {today_conditions}, "
          "High: {today_high_f}F/{today_high_c}C, Low: {today_low_f}F/{today_low_c}C. "
          "\x02Tomorrow:\x02 {tomorrow_conditions}, High: {tomorrow_high_f}F/{tomorrow_high_c}C, "
          "Low: {tomorrow_low_f}F/{tomorrow_low_c}C - {url}".format(**weather_data))
Esempio n. 2
0
def test_isgd_errors(mock_requests):
    mock_requests.add(mock_requests.GET, 'http://is.gd/create.php', status=429)
    from cloudbot.util import web
    with pytest.raises(web.ServiceHTTPError):
        web.shorten('https://example.com', service='is.gd')

    mock_requests.reset()
    with pytest.raises(web.ServiceError):
        web.shorten('https://example.com', service='is.gd')
Esempio n. 3
0
def weather(text, reply):
    """weather <location> -- Gets weather data for <location>."""
    if not wunder_key:
        return "This command requires a Weather Underground API key."
    if not dev_key:
        return "This command requires a Google Developers Console API key."

    # use find_location to get location data from the user input
    try:
        location_data = find_location(text)
    except APIError as e:
        return e

    formatted_location = "{lat},{lng}".format(**location_data)

    url = wunder_api.format(wunder_key, formatted_location)
    response = requests.get(url).json()

    if response['response'].get('error'):
        return "{}".format(response['response']['error']['description'])

    forecast_today = response["forecast"]["simpleforecast"]["forecastday"][0]
    forecast_tomorrow = response["forecast"]["simpleforecast"]["forecastday"][1]

    # put all the stuff we want to use in a dictionary for easy formatting of the output
    weather_data = {
        "place": response['current_observation']['display_location']['full'],
        "conditions": response['current_observation']['weather'],
        "temp_f": response['current_observation']['temp_f'],
        "temp_c": response['current_observation']['temp_c'],
        "humidity": response['current_observation']['relative_humidity'],
        "wind_kph": response['current_observation']['wind_kph'],
        "wind_mph": response['current_observation']['wind_mph'],
        "wind_direction": response['current_observation']['wind_dir'],
        "today_conditions": forecast_today['conditions'],
        "today_high_f": forecast_today['high']['fahrenheit'],
        "today_high_c": forecast_today['high']['celsius'],
        "today_low_f": forecast_today['low']['fahrenheit'],
        "today_low_c": forecast_today['low']['celsius'],
        "tomorrow_conditions": forecast_tomorrow['conditions'],
        "tomorrow_high_f": forecast_tomorrow['high']['fahrenheit'],
        "tomorrow_high_c": forecast_tomorrow['high']['celsius'],
        "tomorrow_low_f": forecast_tomorrow['low']['fahrenheit'],
        "tomorrow_low_c": forecast_tomorrow['low']['celsius']
    }

    # Get the more accurate URL if available, if not, get the generic one.
    if "?query=," in response["current_observation"]['ob_url']:
        weather_data['url'] = web.shorten(response["current_observation"]['forecast_url'])
    else:
        weather_data['url'] = web.shorten(response["current_observation"]['ob_url'])

    reply("{place} - \x02Current:\x02 {conditions}, {temp_f}F/{temp_c}C, {humidity}, "
          "Wind: {wind_kph}KPH/{wind_mph}MPH {wind_direction}, \x02Today:\x02 {today_conditions}, "
          "High: {today_high_f}F/{today_high_c}C, Low: {today_low_f}F/{today_low_c}C. "
          "\x02Tomorrow:\x02 {tomorrow_conditions}, High: {tomorrow_high_f}F/{tomorrow_high_c}C, "
          "Low: {tomorrow_low_f}F/{tomorrow_low_c}C - {url}".format(**weather_data))
Esempio n. 4
0
def shorten(text):
    """<url> [custom] - shortens a url with [custom] as an optional custom shortlink"""
    args = text.split()
    url = args[0]
    custom = args[1] if len(args) > 1 else None

    try:
        return web.shorten(url, custom=custom)
    except web.ServiceError as e:
        return e.message
Esempio n. 5
0
def books(text):
    """books <query> -- Searches Google Books for <query>."""
    if not dev_key:
        return "This command requires a Google Developers Console API key."

    json = requests.get(book_search_api,
                        params={
                            "q": text,
                            "key": dev_key,
                            "country": "US"
                        }).json()

    if json.get('error'):
        if json['error']['code'] == 403:
            print(json['error']['message'])
            return "The Books API is off in the Google Developers Console (or check the console)."
        else:
            return 'Error performing search.'

    if json['totalItems'] == 0:
        return 'No results found.'

    book = json['items'][0]['volumeInfo']
    title = book['title']
    try:
        author = book['authors'][0]
    except KeyError:
        try:
            author = book['publisher']
        except KeyError:
            author = "Unknown Author"

    try:
        description = formatting.truncate_str(book['description'], 130)
    except KeyError:
        description = "No description available."

    try:
        year = book['publishedDate'][:4]
    except KeyError:
        year = "No Year"

    try:
        page_count = book['pageCount']
        pages = ' - \x02{:,}\x02 page{}'.format(page_count,
                                                "s"[page_count == 1:])
    except KeyError:
        pages = ''

    link = web.shorten(book['infoLink'], service="goo.gl", key=dev_key)

    return "\x02{}\x02 by \x02{}\x02 ({}){} - {} - {}".format(
        title, author, year, pages, description, link)
Esempio n. 6
0
def isgd(text):
    """<url> [custom] - shortens a url using is.gd with [custom] as an optional custom shortlink, or unshortens <url> if already short"""
    args = text.split()
    url = args[0]
    custom = args[1] if len(args) > 1 else None

    try:
        if 'is.gd' in url:
            return web.expand(url, 'is.gd')
        else:
            return web.shorten(url, custom, 'is.gd')
    except web.ServiceError as e:
        return e.message
Esempio n. 7
0
def gitio(text):
    """<url> [custom] - shortens a github URL <url> using git.io with [custom] as an optional custom shortlink, or unshortens <url> if already short"""
    args = text.split()
    url = args[0]
    custom = args[1] if len(args) > 1 else None

    try:
        if 'git.io' in url:
            return web.expand(url, 'git.io')
        else:
            return web.shorten(url, custom, 'git.io')
    except web.ServiceError as e:
        return e.message
Esempio n. 8
0
def weather(text, reply):
    """weather <location> -- Gets weather data for <location>."""
    if not wunder_key:
        return "This command requires a Weather Underground API key."
    if not dev_key:
        return "This command requires a Google Developers Console API key."
 
    # use find_location to get location data from the user input
    try:
        location_data = find_location(text)
    except APIError as e:
        return e
 
    formatted_location = "{lat},{lng}".format(**location_data)
 
    url = wunder_api.format(wunder_key, formatted_location)
    response = requests.get(url).json()
 
    if response['response'].get('error'):
        return "{}".format(response['response']['error']['description'])
 
    #forecast_today = response["forecast"]["simpleforecast"]["forecastday"][0]
    #forecast_tomorrow = response["forecast"]["simpleforecast"]["forecastday"][1]
 
    # put all the stuff we want to use in a dictionary for easy formatting of the output
    weather_data = {
        "place": response['current_observation']['display_location']['full'],
        "conditions": response['current_observation']['weather'],
        "temp_f": response['current_observation']['temp_f'],
        "temp_c": response['current_observation']['temp_c']
    }
 
    # Get the more accurate URL if available, if not, get the generic one.
    if "?query=," in response["current_observation"]['ob_url']:
        weather_data['url'] = web.shorten(response["current_observation"]['forecast_url'])
    else:
        weather_data['url'] = web.shorten(response["current_observation"]['ob_url'])
 
    reply("{place} - \x02Current:\x02 {conditions}, {temp_f}F/{temp_c}C".format(**weather_data))
Esempio n. 9
0
def isgd(text):
    """<url> [custom] - shortens a url using is.gd with [custom] as an optional custom shortlink,
    or unshortens <url> if already short"""
    args = text.split()
    url = args[0]
    custom = args[1] if len(args) > 1 else None

    try:
        if 'is.gd' in url:
            return web.expand(url, 'is.gd')
        else:
            return web.shorten(url, custom, 'is.gd')
    except web.ServiceError as e:
        return e.message
Esempio n. 10
0
def gitio(text):
    """<url> [custom] - shortens a github URL <url> using git.io with [custom] as an optional custom shortlink,
    or unshortens <url> if already short"""
    args = text.split()
    url = args[0]
    custom = args[1] if len(args) > 1 else None

    try:
        if 'git.io' in url:
            return web.expand(url, 'git.io')
        else:
            return web.shorten(url, custom, 'git.io')
    except web.ServiceError as e:
        return e.message
Esempio n. 11
0
def googl(text, reply):
    """<url> [custom] - shorten <url> using goo.gl with [custom] as an option custom shortlink,
    or unshortens <url> if already short"""
    args = text.split()
    url = args[0]
    custom = args[1] if len(args) > 1 else None

    try:
        if 'goo.gl' in url:
            return web.expand(url, 'goo.gl')
        else:
            return web.shorten(url, custom, 'goo.gl')
    except web.ServiceError as e:
        reply(e.message)
        raise
Esempio n. 12
0
def books(text):
    """books <query> -- Searches Google Books for <query>."""
    if not dev_key:
        return "This command requires a Google Developers Console API key."

    json = requests.get(book_search_api, params={"q": text, "key": dev_key, "country": "US"}).json()

    if json.get('error'):
        if json['error']['code'] == 403:
            print(json['error']['message'])
            return "The Books API is off in the Google Developers Console (or check the console)."
        else:
            return 'Error performing search.'

    if json['totalItems'] == 0:
        return 'No results found.'

    book = json['items'][0]['volumeInfo']
    title = book['title']
    try:
        author = book['authors'][0]
    except KeyError:
        try:
            author = book['publisher']
        except KeyError:
            author = "Unknown Author"

    try:
        description = formatting.truncate_str(book['description'], 130)
    except KeyError:
        description = "No description available."

    try:
        year = book['publishedDate'][:4]
    except KeyError:
        year = "No Year"

    try:
        page_count = book['pageCount']
        pages = ' - \x02{:,}\x02 page{}'.format(page_count, "s"[page_count == 1:])
    except KeyError:
        pages = ''

    link = web.shorten(book['infoLink'], service="goo.gl", key=dev_key)

    return "\x02{}\x02 by \x02{}\x02 ({}){} - {} - {}".format(title, author, year, pages, description, link)
Esempio n. 13
0
def malmsearch(text, reply, bot):

    text = urllib.parse.quote(text)

    try:
        user = bot.config.get("api_keys", {}).get("mal_user", None)
        password = bot.config.get("api_keys", {}).get("mal_pass", None)
    except:
        reply("No api key found.")

    url = 'https://myanimelist.net/api/manga/search.xml?q={}'.format(text)

    try:
        request = requests.get(url, auth=(user, password))
    except Exception as c:
        reply('Error: {}'.format(c))

    soup = BeautifulSoup(request.text)
    title = http.strip_html(soup.find('title'))
    chapters = http.strip_html(soup.find('chapters'))
    mtype = http.strip_html(soup.find('type'))
    score = http.strip_html(soup.find('score'))
    status = http.strip_html(soup.find('status'))
    start_date = http.strip_html(soup.find('start_date'))
    end_date = http.strip_html(soup.find('end_date'))

    if end_date == '0000-00-00' and status is not 'Publishing':
        end_date = 'has not ended'
    elif status == 'Publishing':
        end_date = 'will end on {}'.format(end_date)
    else:
        end_date = 'ended {}'.format(end_date)

    id = http.strip_html(soup.find('id'))
    url = web.shorten(
        'https://' +
        urllib.parse.quote('myanimelist.net/manga/{}/{}'.format(id, title)))

    reply('{}, {}, {}, {} chapters. {}, started {}, {}. {}'.format(
        title, mtype, score, chapters, status, start_date, end_date, url))
Esempio n. 14
0
def wow_armoury_format(data, link):
    """Format armoury data into a human readable string"""

    if data.status_code != 200 and data.status_code != 404:
        # The page returns 404 if the character or realm is not found.
        try:
            data.raise_for_status()
        except Exception as e:
            return 'An error occurred while trying to fetch the data. ({})'.format(str(e))

    data = data.json()

    if len(data) == 0:
        return 'Could not find any results.'

    if 'reason' in data:
        # Something went wrong (i.e. realm does not exist, character does not exist, or page not found).
        return data['reason']

    if 'name' in data:
        niceurl = link.replace('/api/wow/', '/wow/en/') + '/simple'

        try:
            return '{0} is a level \x0307{1}\x0F {2} {3} on {4} with \x0307{5}\x0F achievement points and \x0307{6}' \
                   '\x0F honourable kills. Armoury Profile: {7}' \
                .format(data['name'], data['level'], wow_get_gender(data['gender']), wow_get_class(data['class'], True),
                        data['realm'], data['achievementPoints'], data['totalHonorableKills'], web.shorten(niceurl))
        except Exception as e:
            return 'Unable to fetch information for {}. Does the realm or character exist? ({})'.format(niceurl, str(e))

    return 'An unexpected error occurred.'
Esempio n. 15
0
def weather(text, reply, db, nick, bot, notice):
    """weather <location> [dontsave] -- Gets weather data
    for <location> from Wunderground."""

    api_key = bot.config.get("api_keys", {}).get("wunderground")

    if not api_key:
        return "Error: No wunderground API details."

    # initialise weather DB
    db.execute("create table if not exists weather(nick primary key, loc)")

    # if there is no input, try getting the users last location from the DB
    if not text:
        location = db.execute("select loc from weather where nick=lower(:nick)",
                              {"nick": nick}).fetchone()
        print(location)
        if not location:
            # no location saved in the database, send the user help text
            notice(weather.__doc__)
            return
        loc = location[0]

        # no need to save a location, we already have it
        dontsave = True
    else:
        # see if the input ends with "dontsave"
        dontsave = text.endswith(" dontsave")

        # remove "dontsave" from the input string after checking for it
        if dontsave:
            loc = text[:-9].strip().lower()
        else:
            loc = text

    location = http.quote_plus(loc)

    request_url = base_url.format(api_key, "geolookup/forecast/conditions", location)
    response = http.get_json(request_url)

    if 'location' not in response:
        try:
            location_id = response['response']['results'][0]['zmw']
        except KeyError:
            return "Could not get weather for that location."

        # get the weather again, using the closest match
        request_url = base_url.format(api_key, "geolookup/forecast/conditions", "zmw:" + location_id)
        response = http.get_json(request_url)

    if response['location']['state']:
        place_name = "\x02{}\x02, \x02{}\x02 (\x02{}\x02)".format(response['location']['city'],
                                                                  response['location']['state'],
                                                                  response['location']['country'])
    else:
        place_name = "\x02{}\x02 (\x02{}\x02)".format(response['location']['city'],
                                                      response['location']['country'])

    forecast_today = response["forecast"]["simpleforecast"]["forecastday"][0]
    forecast_tomorrow = response["forecast"]["simpleforecast"]["forecastday"][1]

    # put all the stuff we want to use in a dictionary for easy formatting of the output
    weather_data = {
        "place": place_name,
        "conditions": response['current_observation']['weather'],
        "temp_f": response['current_observation']['temp_f'],
        "temp_c": response['current_observation']['temp_c'],
        "humidity": response['current_observation']['relative_humidity'],
        "wind_kph": response['current_observation']['wind_kph'],
        "wind_mph": response['current_observation']['wind_mph'],
        "wind_direction": response['current_observation']['wind_dir'],
        "today_conditions": forecast_today['conditions'],
        "today_high_f": forecast_today['high']['fahrenheit'],
        "today_high_c": forecast_today['high']['celsius'],
        "today_low_f": forecast_today['low']['fahrenheit'],
        "today_low_c": forecast_today['low']['celsius'],
        "tomorrow_conditions": forecast_tomorrow['conditions'],
        "tomorrow_high_f": forecast_tomorrow['high']['fahrenheit'],
        "tomorrow_high_c": forecast_tomorrow['high']['celsius'],
        "tomorrow_low_f": forecast_tomorrow['low']['fahrenheit'],
        "tomorrow_low_c": forecast_tomorrow['low']['celsius'],
        "url": web.shorten(response["current_observation"]['forecast_url'] + "?apiref=e535207ff4757b18")
    }

    reply("{place} - \x02Current:\x02 {conditions}, {temp_f}F/{temp_c}C, {humidity}, "
          "Wind: {wind_kph}KPH/{wind_mph}MPH {wind_direction}, \x02Today:\x02 {today_conditions}, "
          "High: {today_high_f}F/{today_high_c}C, Low: {today_low_f}F/{today_low_c}C. "
          "\x02Tomorrow:\x02 {tomorrow_conditions}, High: {tomorrow_high_f}F/{tomorrow_high_c}C, "
          "Low: {tomorrow_low_f}F/{tomorrow_low_c}C - {url}".format(**weather_data))

    if location and not dontsave:
        db.execute("insert or replace into weather(nick, loc) values (:nick, :loc)",
                   {"nick": nick.lower(), "loc": loc})
        db.commit()
Esempio n. 16
0
def weather(text, reply, db, nick, bot, notice):
    """weather <location> -- Gets weather data for <location>."""
    if not wunder_key:
        return "This command requires a Weather Underground API key."
    if not dev_key:
        return "This command requires a Google Developers Console API key."

    # initialise weather DB
    db.execute("create table if not exists weather(nick primary key, loc)")

    # if there is no input, try getting the users last location from the DB
    if not text:
        location = db.execute("select loc from weather where nick=lower(:nick)",
                              {"nick": nick}).fetchone()
        if not location:
            # no location saved in the database, send the user help text
            notice(weather.__doc__)
            return
        loc = location[0]

        # no need to save a location, we already have it
        dontsave = True
    else:
        # see if the input ends with "dontsave"
        dontsave = text.endswith(" dontsave")

        # remove "dontsave" from the input string after checking for it
        if dontsave:
            loc = text[:-9].strip().lower()
        else:
            loc = text

    # use find_location to get location data from the user input
    try:
        location_data = find_location(loc)
    except APIError as e:
        return e

    formatted_location = "{lat},{lng}".format(**location_data)

    url = wunder_api.format(wunder_key, formatted_location)
    response = requests.get(url).json()

    if response['response'].get('error'):
        return "{}".format(response['response']['error']['description'])

    forecast_today = response["forecast"]["simpleforecast"]["forecastday"][0]
    forecast_tomorrow = response["forecast"]["simpleforecast"]["forecastday"][1]

    # put all the stuff we want to use in a dictionary for easy formatting of the output
    weather_data = {
        "place": response['current_observation']['display_location']['full'],
        "conditions": response['current_observation']['weather'],
        "temp_f": response['current_observation']['temp_f'],
        "temp_c": response['current_observation']['temp_c'],
        "humidity": response['current_observation']['relative_humidity'],
        "wind_kph": response['current_observation']['wind_kph'],
        "wind_mph": response['current_observation']['wind_mph'],
        "wind_direction": response['current_observation']['wind_dir'],
        "today_conditions": forecast_today['conditions'],
        "today_high_f": forecast_today['high']['fahrenheit'],
        "today_high_c": forecast_today['high']['celsius'],
        "today_low_f": forecast_today['low']['fahrenheit'],
        "today_low_c": forecast_today['low']['celsius'],
        "tomorrow_conditions": forecast_tomorrow['conditions'],
        "tomorrow_high_f": forecast_tomorrow['high']['fahrenheit'],
        "tomorrow_high_c": forecast_tomorrow['high']['celsius'],
        "tomorrow_low_f": forecast_tomorrow['low']['fahrenheit'],
        "tomorrow_low_c": forecast_tomorrow['low']['celsius']
    }

    # Get the more accurate URL if available, if not, get the generic one.
    if "?query=," in response["current_observation"]['ob_url']:
        weather_data['url'] = web.shorten(response["current_observation"]['forecast_url'])
    else:
        weather_data['url'] = web.shorten(response["current_observation"]['ob_url'])

    if loc and not dontsave:
        db.execute("insert or replace into weather(nick, loc) values (:nick, :loc)",
                   {"nick": nick.lower(), "loc": loc})
        db.commit()

    reply("{place} - \x02Current:\x02 {conditions}, {temp_f}F/{temp_c}C, {humidity}, "
          "Wind: {wind_mph}MPH/{wind_kph}KPH {wind_direction}, \x02Today:\x02 {today_conditions}, "
          "High: {today_high_f}F/{today_high_c}C, Low: {today_low_f}F/{today_low_c}C. "
          "\x02Tomorrow:\x02 {tomorrow_conditions}, High: {tomorrow_high_f}F/{tomorrow_high_c}C, "
          "Low: {tomorrow_low_f}F/{tomorrow_low_c}C - {url}".format(**weather_data))
Esempio n. 17
0
def test_shorten(mock_requests):
    mock_requests.add(mock_requests.GET,
                      'http://is.gd/create.php',
                      json={'shorturl': 'https://is.gd/foobar'})
    from cloudbot.util import web
    assert web.shorten('https://example.com',
                       service='is.gd') == 'https://is.gd/foobar'

    assert web.Shortener().shorten(
        'https://example.com') == 'https://example.com'

    with pytest.raises(web.ServiceError):
        web.shorten('https://example.com', service='goo.gl')

    mock_requests.add(mock_requests.POST,
                      'https://www.googleapis.com/urlshortener/v1/url',
                      json={},
                      status=requests.codes.bad_request)
    with pytest.raises(web.ServiceHTTPError):
        web.shorten('https://example.com', service='goo.gl')

    mock_requests.replace(mock_requests.POST,
                          'https://www.googleapis.com/urlshortener/v1/url',
                          json={'error': {
                              'message': 'Error'
                          }})
    with pytest.raises(web.ServiceHTTPError):
        web.shorten('https://example.com', service='goo.gl')

    mock_requests.replace(mock_requests.POST,
                          'https://www.googleapis.com/urlshortener/v1/url',
                          json={'id': 'https://goo.gl/foobar'})
    assert web.shorten('https://example.com',
                       service='goo.gl') == 'https://goo.gl/foobar'

    with pytest.raises(web.ServiceError):
        web.shorten('https://example.com', service='git.io')

    mock_requests.add(
        mock_requests.POST,
        'http://git.io',
        status=400,
    )
    with pytest.raises(web.ServiceHTTPError):
        web.shorten('https://example.com', service='git.io')

    mock_requests.replace(mock_requests.POST, 'http://git.io', body='error')
    with pytest.raises(web.ServiceHTTPError):
        web.shorten('https://example.com', service='git.io')

    mock_requests.replace(mock_requests.POST, 'http://git.io', body='error')
    with pytest.raises(web.ServiceHTTPError):
        web.shorten('https://example.com', service='git.io')

    mock_requests.replace(mock_requests.POST,
                          'http://git.io',
                          headers={'Location': 'http://git.io/foobar123'},
                          status=requests.codes.created)
    assert web.shorten('https://example.com',
                       service='git.io') == 'http://git.io/foobar123'

    with pytest.raises(web.ServiceHTTPError):
        web.shorten('https://example.com', service='git.io', custom='test')
Esempio n. 18
0
def weather(text, reply, db, nick, bot, notice):
    """weather <location> [dontsave] -- Gets weather data
    for <location> from Wunderground."""

    api_key = bot.config.get("api_keys", {}).get("wunderground")

    if not api_key:
        return "Error: No wunderground API details."

    # initialise weather DB
    db.execute("create table if not exists weather(nick primary key, loc)")

    # if there is no input, try getting the users last location from the DB
    if not text:
        location = db.execute("select loc from weather where nick=lower(:nick)",
                              {"nick": nick}).fetchone()
        if not location:
            # no location saved in the database, send the user help text
            notice(weather.__doc__)
            return
        loc = location[0]

        # no need to save a location, we already have it
        dontsave = True
    else:
        # see if the input ends with "dontsave"
        dontsave = text.endswith(" dontsave")

        # remove "dontsave" from the input string after checking for it
        if dontsave:
            loc = text[:-9].strip().lower()
        else:
            loc = text

    location = requests.utils.quote(loc)

    request_url = base_url.format(api_key, "geolookup/forecast/conditions", location)

    try:
        request = requests.get(request_url)
        request.raise_for_status()
    except (requests.exceptions.HTTPError, requests.exceptions.ConnectionError) as e:
        return "Could not get weather data: {}".format(e)

    response = request.json()

    if 'location' not in response:
        try:
            location_id = response['response']['results'][0]['zmw']
        except KeyError:
            return "Could not get weather for that location."

        # get the weather again, using the closest match
        request_url = base_url.format(api_key, "geolookup/forecast/conditions", "zmw:" + location_id)
        response = requests.get(request_url).json()

    if response['location']['state']:
        place_name = "\x02{}\x02, \x02{}\x02 (\x02{}\x02)".format(response['location']['city'],
                                                                  response['location']['state'],
                                                                  response['location']['country'])
    else:
        place_name = "\x02{}\x02 (\x02{}\x02)".format(response['location']['city'],
                                                      response['location']['country'])

    forecast_today = response["forecast"]["simpleforecast"]["forecastday"][0]
    forecast_tomorrow = response["forecast"]["simpleforecast"]["forecastday"][1]

    # put all the stuff we want to use in a dictionary for easy formatting of the output
    weather_data = {
        "place": place_name,
        "conditions": response['current_observation']['weather'],
        "temp_f": response['current_observation']['temp_f'],
        "temp_c": response['current_observation']['temp_c'],
        "humidity": response['current_observation']['relative_humidity'],
        "wind_kph": response['current_observation']['wind_kph'],
        "wind_mph": response['current_observation']['wind_mph'],
        "wind_direction": response['current_observation']['wind_dir'],
        "today_conditions": forecast_today['conditions'],
        "today_high_f": forecast_today['high']['fahrenheit'],
        "today_high_c": forecast_today['high']['celsius'],
        "today_low_f": forecast_today['low']['fahrenheit'],
        "today_low_c": forecast_today['low']['celsius'],
        "tomorrow_conditions": forecast_tomorrow['conditions'],
        "tomorrow_high_f": forecast_tomorrow['high']['fahrenheit'],
        "tomorrow_high_c": forecast_tomorrow['high']['celsius'],
        "tomorrow_low_f": forecast_tomorrow['low']['fahrenheit'],
        "tomorrow_low_c": forecast_tomorrow['low']['celsius'],
        "url": web.shorten(response["current_observation"]['forecast_url'] + "?apiref=e535207ff4757b18")
    }

    reply("{place} - \x02Current:\x02 {conditions}, {temp_f}F/{temp_c}C, {humidity}, "
          "Wind: {wind_kph}KPH/{wind_mph}MPH {wind_direction}, \x02Today:\x02 {today_conditions}, "
          "High: {today_high_f}F/{today_high_c}C, Low: {today_low_f}F/{today_low_c}C. "
          "\x02Tomorrow:\x02 {tomorrow_conditions}, High: {tomorrow_high_f}F/{tomorrow_high_c}C, "
          "Low: {tomorrow_low_f}F/{tomorrow_low_c}C - {url}".format(**weather_data))

    if location and not dontsave:
        db.execute("insert or replace into weather(nick, loc) values (:nick, :loc)",
                   {"nick": nick.lower(), "loc": loc})
        db.commit()
Esempio n. 19
0
def test_shorten(mock_requests):
    mock_requests.add(
        mock_requests.GET,
        "http://is.gd/create.php",
        json={"shorturl": "https://is.gd/foobar"},
    )
    from cloudbot.util import web

    assert (web.shorten("https://example.com",
                        service="is.gd") == "https://is.gd/foobar")

    assert (web.Shortener().shorten("https://example.com") ==
            "https://example.com")

    with pytest.raises(web.ServiceError):
        web.shorten("https://example.com", service="goo.gl")

    mock_requests.add(
        mock_requests.POST,
        "https://www.googleapis.com/urlshortener/v1/url",
        json={},
        status=requests.codes.bad_request,
    )
    with pytest.raises(web.ServiceHTTPError):
        web.shorten("https://example.com", service="goo.gl")

    mock_requests.replace(
        mock_requests.POST,
        "https://www.googleapis.com/urlshortener/v1/url",
        json={"error": {
            "message": "Error"
        }},
    )
    with pytest.raises(web.ServiceHTTPError):
        web.shorten("https://example.com", service="goo.gl")

    mock_requests.replace(
        mock_requests.POST,
        "https://www.googleapis.com/urlshortener/v1/url",
        json={"id": "https://goo.gl/foobar"},
    )
    assert (web.shorten("https://example.com",
                        service="goo.gl") == "https://goo.gl/foobar")

    with pytest.raises(web.ServiceError):
        web.shorten("https://example.com", service="git.io")

    mock_requests.add(
        mock_requests.POST,
        "http://git.io",
        status=400,
    )
    with pytest.raises(web.ServiceHTTPError):
        web.shorten("https://example.com", service="git.io")

    mock_requests.replace(mock_requests.POST, "http://git.io", body="error")
    with pytest.raises(web.ServiceHTTPError):
        web.shorten("https://example.com", service="git.io")

    mock_requests.replace(mock_requests.POST, "http://git.io", body="error")
    with pytest.raises(web.ServiceHTTPError):
        web.shorten("https://example.com", service="git.io")

    mock_requests.replace(
        mock_requests.POST,
        "http://git.io",
        headers={"Location": "http://git.io/foobar123"},
        status=requests.codes.created,
    )
    assert (web.shorten("https://example.com",
                        service="git.io") == "http://git.io/foobar123")

    with pytest.raises(web.ServiceHTTPError):
        web.shorten("https://example.com", service="git.io", custom="test")
Esempio n. 20
0
def wolframalpha(text, message):
    """<query> -- Computes <query> using Wolfram Alpha."""
    if not api_key:
        return "Missing API key"

    params = {'input': text, 'format': "plaintext", 'appid': api_key}
    request = requests.get(api_url, params=params)
    url = query_url.format(urllib.parse.quote_plus(text))

    try:
        request.raise_for_status()
    except HTTPError as e:
        message("Error getting query: {}".format(e.response.status_code))
        raise

    if request.status_code != requests.codes.ok:
        return "WA error: {} [div] {}".format(request.status_code, url)

    result = etree.fromstring(request.content, parser=parser)

    pod_texts = {}
    for pod in result.xpath("//pod"):
        primary = "primary" in pod.attrib.keys()
        pid = pod.attrib["id"]
        title = pod.attrib["title"]
        # Ignore pods we don't care about
        if not primary and (not pid in list(show_pods) or not show_pods[pid]):
            # Sometimes Result will have a different id
            if not title in list(show_pods) or not show_pods[title]:
                continue

        results = []
        # Format subpods
        #for subpod in pod.xpath('subpod/plaintext/text()'):
        for subpod in pod.xpath('subpod'):
            podinfo = "[h2]{}[/h2] ".format(
                subpod.attrib['title']) if subpod.attrib['title'] else ""

            podresults = []
            for subinfo in subpod.xpath('plaintext/text()'):
                # Itemize units (separate lines)
                values = []
                for item in subinfo.split('\n'):
                    # Format "key | value"
                    item = re.sub(r"^([\w\s]+)\s+\|\s+", "[h4]\\1:[/h4] ",
                                  item)
                    # Replace inner '|' (eg weather forecast)
                    item = re.sub(r"(\))\s+\|\s+", "\\1 [h2]-[/h2] ", item)
                    # Colorize "(extra info)", preceeded with whitespace
                    item = re.sub(r"\s+(\([^()]+\))", " [h3]\\1[/h3]", item)
                    # Remove extra spaces
                    item = re.sub(r'\s{2,}', ' ', item)
                    # Add
                    values.append(item.strip())
                # Put 'em back together
                subinfo = " [div] ".join(values)
                if subinfo:
                    podresults.append(subinfo)

            podinfo += ''.join(podresults)
            results.append(podinfo)

        if results:
            info = " [div] ".join(results)
            if pid == "Input":
                # Strip verbose "Input interp/info"
                title = title.replace(" interpretation",
                                      "").replace(" information", "")
                # Strip open/closing parentheses around input
            if pid in ["AdditionalConversion", "UnitConversion"]:
                # Reduce verbosity (just print "Conversions")
                title = "C" + title[title.index("conv") + 1:]
            title = "[h1]{}[/h1] ".format(title)
            pod_texts[pid] = title + info

    # NOTHING??
    if not pod_texts:
        return "WA ain't found shit! [div] " + url

    # Sometimes input will be the only pod from filtering
    if "Input" in pod_texts and len(pod_texts) == 1:
        return "Extra info filtered [div] " + url

    # get the URL for a user to view this query in a browser
    try:
        short_url = " [div] [h1]Web[/h1] " + web.shorten(url)
    except:
        short_url = None
    if short_url:
        pod_texts['Input'] += short_url

    # Append input to result
    if "Input" in pod_texts and "Result" in pod_texts:
        pod_texts['Result'] = "{} [div] {}".format(pod_texts['Result'],
                                                   pod_texts['Input'])
        del pod_texts['Input']

    # Print result/input first
    if "Input" in pod_texts:
        message(pod_texts['Input'])
        del pod_texts['Input']
    if "Result" in pod_texts:
        message(pod_texts['Result'])
        del pod_texts['Result']

    # Print remaining info
    for key in pod_texts:
        message(pod_texts[key])
Esempio n. 21
0
def malsearch(text, reply, bot):

    text = urllib.parse.quote(text)

    #grab our mal login

    try:
        user = bot.config.get("api_keys", {}).get("mal_user", None)
        password = bot.config.get("api_keys", {}).get("mal_pass", None)
    except:
        reply("No api key found.")

    url = 'https://myanimelist.net/api/anime/search.xml?q={}'.format(text)

    #try to request anime, reply if failed
    try:
        request = requests.get(url, auth=(user, password))
    except Exception as e:
        reply('Error: {}'.format(e))

    soup = BeautifulSoup(request.text)

    #a whole bunch of sorting
    title = http.strip_html(soup.find('title'))
    episodes = http.strip_html(soup.find('episodes'))
    if episodes == '0':
        episodes = '?'
    status = http.strip_html(soup.find('status'))
    score = http.strip_html(soup.find('score'))
    airtype = http.strip_html(soup.find('type'))
    start_date = http.strip_html(soup.find('start_date'))
    end_date = http.strip_html(soup.find('end_date'))

    #Has the anime ended? Yes.
    if end_date == '0000-00-00' and status is not 'Currently Airing':
        end_date = 'has not ended'
    #no but I know when.
    elif status == 'Currently Airing':
        end_date = 'will end {}'.format(http.strip_html(soup.find('end_date')))
    #no I don't know when.
    else:
        print(status, end_date)
        end_date = 'ended {}'.format(http.strip_html(soup.find('end_date')))

    #in case we want to ever output synopsis to irc
    synopsis = http.strip_html(http.strip_html(soup.find('synopsis')))
    length = len(synopsis)
    if length > 432 and length < 888:
        synopsis_1, synopsis_2 = textwrap.wrap(synopsis, 432)
    elif length > 864:
        synopsis_1, synopsis_2, synopsis_3 = textwrap.wrap(synopsis, 432)

    id = http.strip_html(soup.find('id'))

    url = web.shorten(
        'https://' +
        urllib.parse.quote('myanimelist.net/anime/{}/{}'.format(id, title)))

    reply('{}, {}, {}, {} episodes. {}, started {}, {}. {}'.format(
        title, airtype, score, episodes, status, start_date, end_date, url))

    #more stuff we can add later for synopsis //its really spammy
    """if synopsis_1 is not None and synopsis_2 is not None and synopsis_3 is None:
Esempio n. 22
0
def wow_armoury_format(data, link):
    """Format armoury data into a human readable string"""

    if data.status_code != 200 and data.status_code != 404:
        # The page returns 404 if the character or realm is not found.
        try:
            data.raise_for_status()
        except Exception as e:
            return 'An error occurred while trying to fetch the data. ({})'.format(
                str(e))

    data = data.json()

    if len(data) == 0:
        return 'Could not find any results.'

    if 'reason' in data:
        # Something went wrong (i.e. realm does not exist, character does not exist, or page not found).
        return data['reason']

    if 'name' in data:
        nice_url = link.replace('/api/wow/', '/wow/en/') + '/simple'

        try:
            return '{} is a level \x0307{}\x0F {} {} on {} with \x0307{}\x0F achievement points and \x0307{}' \
                   '\x0F honourable kills. Armoury Profile: {}' \
                .format(data['name'], data['level'], wow_get_gender(data['gender']), wow_get_class(data['class'], True),
                        data['realm'], data['achievementPoints'], data['totalHonorableKills'], web.shorten(nice_url))
        except Exception as e:
            return 'Unable to fetch information for {}. Does the realm or ' \
                   'character exist? ({})'.format(nice_url, str(e))

    return 'An unexpected error occurred.'