示例#1
0
def etymology(word):
    # @@ <nsh> sbp, would it be possible to have a flag for .ety to get 2nd/etc
    # entries? - http://swhack.com/logs/2006-07-19#T15-05-29

    if len(word) > 25:
        raise ValueError("Word too long: %s[…]" % word[:10])

    ety = get(ETYURI % web.quote(word))
    if ety.status_code != 200:
        return None

    # Let's find it
    start = ety.text.find("word__defination")
    start = ety.text.find("<p>", start)
    stop = ety.text.find("</p>", start)
    sentence = ety.text[start + 3:stop]
    # Clean up
    sentence = unescape(sentence)
    sentence = sub('<[^<]+?>', '', sentence)

    maxlength = 275
    if len(sentence) > maxlength:
        sentence = sentence[:maxlength]
        words = sentence[:-5].split(' ')
        words.pop()
        sentence = ' '.join(words) + ' […]'

    sentence = '"' + sentence.replace('"', "'") + '"'
    return sentence + ' - ' + (ETYURI % web.quote(word))
def wikt(word):
    bytes = requests.get(uri % web.quote(word)).text
    bytes = r_ul.sub('', bytes)

    mode = None
    etymology = None
    definitions = {}
    for line in bytes.splitlines():
        is_new_mode = False
        if 'id="Etymology' in line:
            mode = 'etymology'
            is_new_mode = True
        else:
            for pos in PARTS_OF_SPEECH:
                if 'id="{}"'.format(pos.replace(' ', '_')) in line:
                    mode = pos.lower()
                    is_new_mode = True
                    break

        if not is_new_mode:
            # 'id="' can occur in definition lines <li> when <sup> tag is used for references;
            # make sure those are not excluded (see e.g., abecedarian).
            if ('id="' in line) and ('<li>' not in line):
                mode = None
            elif (mode == 'etymology') and ('<p>' in line):
                etymology = text(line)
            elif (mode is not None) and ('<li>' in line):
                definitions.setdefault(mode, []).append(text(line))

        if '<hr' in line:
            break
    return etymology, definitions
示例#3
0
def say_snippet(bot, trigger, server, query, show_url=True, commanded=False):
    page_name = query.replace('_', ' ')
    query = quote(query.replace(' ', '_'))
    url = 'https://{}/wiki/{}'.format(server, query)

    # If the trigger looks like another instance of this plugin, assume it is
    if trigger.startswith(PLUGIN_OUTPUT_PREFIX) and trigger.endswith(' | ' +
                                                                     url):
        return

    try:
        snippet = mw_snippet(server, query)
        # Coalesce repeated whitespace to avoid problems with <math> on MediaWiki
        # see https://github.com/sopel-irc/sopel/issues/2259
        snippet = re.sub(r"\s+", " ", snippet)
    except KeyError:
        msg = 'Error fetching snippet for "{}".'.format(page_name)
        if commanded:
            bot.reply(msg)
        else:
            bot.say(msg)
        return

    msg = '{} | "{}'.format(page_name, snippet)

    trailing = '"'
    if show_url:
        trailing += ' | ' + url

    bot.say(msg, truncation=' […]', trailing=trailing)
示例#4
0
def update_rates(bot):
    global rates, rates_updated

    # If we have data that is less than 24h old, return
    if time.time() - rates_updated < 24 * 60 * 60:
        LOGGER.debug('Skipping rate update; cache is less than 24h old')
        return

    # Update crypto rates
    LOGGER.debug('Updating crypto rates from %s', CRYPTO_URL)
    response = requests.get(CRYPTO_URL)
    response.raise_for_status()
    rates_crypto = response.json()

    # Update fiat rates
    if bot.config.currency.fixer_io_key is not None:
        LOGGER.debug('Updating fiat rates from Fixer.io')
        if bot.config.currency.fiat_provider != 'fixer.io':
            # Warning about future behavior change
            LOGGER.warning(
                'fiat_provider is set to %s, but Fixer.io API key is present; '
                'using Fixer anyway. In Sopel 8, fiat_provider will take precedence.',
                bot.config.currency.fiat_provider)

        proto = 'https:' if bot.config.currency.fixer_use_ssl else 'http:'
        response = requests.get(proto + FIAT_PROVIDERS['fixer.io'].format(
            web.quote(bot.config.currency.fixer_io_key)))

        if not response.json()['success']:
            raise FixerError('Fixer.io request failed with error: {}'.format(
                response.json()['error']))
    else:
        LOGGER.debug('Updating fiat rates from %s',
                     bot.config.currency.fiat_provider)
        response = requests.get(
            FIAT_PROVIDERS[bot.config.currency.fiat_provider])

    response.raise_for_status()
    rates_fiat = response.json()

    rates = rates_fiat['rates']
    rates['EUR'] = 1.0  # Put this here to make logic easier

    eur_btc_rate = 1 / rates_crypto['rates']['eur']['value']

    for rate in rates_crypto['rates']:
        if rate.upper() not in rates:
            rates[rate.upper(
            )] = rates_crypto['rates'][rate]['value'] * eur_btc_rate

    # if an error aborted the operation prematurely, we want the next call to retry updating rates
    # therefore we'll update the stored timestamp at the last possible moment
    rates_updated = time.time()
    LOGGER.debug('Rate update completed')
示例#5
0
def say_section(bot, trigger, server, query, section):
    page_name = query.replace('_', ' ')
    query = quote(query.replace(' ', '_'))

    snippet = mw_section(server, query, section)
    if not snippet:
        bot.reply("Error fetching section \"{}\" for page \"{}\".".format(section, page_name))
        return

    msg = '{} - {} | "{}"'.format(page_name, section.replace('_', ' '), snippet)
    bot.say(msg, truncation=' […]"')
示例#6
0
def py(bot, trigger):
    """Evaluate a Python expression."""
    if not trigger.group(2):
        return bot.reply('I need an expression to evaluate.')

    query = trigger.group(2)
    uri = bot.config.py.oblique_instance + 'py/'
    answer = get(uri + quote(query)).content.decode('utf-8')
    if answer:
        bot.say(answer)
    else:
        bot.reply('Sorry, no result.')
示例#7
0
def py(bot, trigger):
    """Evaluate a Python expression."""
    query = trigger.group(2)
    if not query:
        bot.reply('What expression do you want me to evaluate?')
        return

    uri = bot.config.py.oblique_instance + 'py/'
    answer = get(uri + quote(query)).content.decode('utf-8')
    if answer:
        bot.say(answer)
    else:
        bot.reply('Sorry, no result.')
示例#8
0
def f_etymology(bot, trigger):
    """Look up the etymology of a word"""
    word = trigger.group(2)

    try:
        result = etymology(word)
    except IOError:
        msg = "Can't connect to etymonline.com (%s)" % (ETYURI % web.quote(word))
        bot.say(msg, trigger.sender)
        return NOLIMIT
    except (AttributeError, TypeError):
        result = None
    except ValueError as ve:
        result = str(ve)

    if result is not None:
        bot.say(result, trigger.sender)
    else:
        uri = ETYSEARCH % web.quote(word)
        msg = 'Can\'t find the etymology for "%s". Try %s' % (word, uri)
        bot.say(msg, trigger.sender)
        return NOLIMIT
示例#9
0
文件: calc.py 项目: kratos13/sopel
def py(bot, trigger):
    """Evaluate a Python expression."""
    if not trigger.group(2):
        return bot.say("Need an expression to evaluate")

    query = trigger.group(2)
    uri = BASE_TUMBOLIA_URI + 'py/'
    answer = get(uri + quote(query)).content.decode('utf-8')
    if answer:
        # bot.say can potentially lead to 3rd party commands triggering.
        bot.reply(answer)
    else:
        bot.reply('Sorry, no result.')
示例#10
0
def say_snippet(bot, trigger, server, query, show_url=True):
    page_name = query.replace('_', ' ')
    query = quote(query.replace(' ', '_'))
    try:
        snippet = mw_snippet(server, query)
    except KeyError:
        if show_url:
            bot.reply("Error fetching snippet for \"{}\".".format(page_name))
        return
    msg = '{} | "{}"'.format(page_name, snippet)
    msg_url = msg + ' | https://{}/wiki/{}'.format(server, query)
    if msg_url == trigger:  # prevents triggering on another instance of Sopel
        return
    if show_url:
        msg = msg_url
    bot.say(msg)
示例#11
0
def say_snippet(bot, trigger, server, query, show_url=True):
    page_name = query.replace('_', ' ')
    query = quote(query.replace(' ', '_'))
    url = 'https://{}/wiki/{}'.format(server, query)

    # If the trigger looks like another instance of this plugin, assume it is
    if trigger.startswith(PLUGIN_OUTPUT_PREFIX) and trigger.endswith(' | ' + url):
        return

    try:
        snippet = mw_snippet(server, query)
    except KeyError:
        if show_url:
            bot.reply("Error fetching snippet for \"{}\".".format(page_name))
        return

    msg = '{} | "{}'.format(page_name, snippet)

    trailing = '"'
    if show_url:
        trailing += ' | ' + url

    bot.say(msg, truncation=' […]', trailing=trailing)
示例#12
0
def mw_section(server, query, section):
    """
    Retrieves a snippet from the specified section from the given page
    on the given server.
    """
    sections_url = ('https://{0}/w/api.php?format=json&redirects'
                    '&action=parse&prop=sections&page={1}'.format(
                        server, query))
    sections = get(sections_url).json()

    section_number = None

    for entry in sections['parse']['sections']:
        if entry['anchor'] == section:
            section_number = entry['index']
            # Needed to handle sections from transcluded pages properly
            # e.g. template documentation (usually pulled in from /doc subpage).
            # One might expect this prop to be nullable because in most cases it
            # will simply repeat the requested page title, but it's always set.
            fetch_title = quote(entry['fromtitle'])
            break

    if not section_number:
        return None

    snippet_url = ('https://{0}/w/api.php?format=json&redirects'
                   '&action=parse&page={1}&prop=text'
                   '&section={2}').format(server, fetch_title, section_number)

    data = get(snippet_url).json()

    parser = WikiParser(section.replace('_', ' '))
    parser.feed(data['parse']['text']['*'])
    text = parser.get_result()
    text = ' '.join(text.split())  # collapse multiple whitespace chars

    return text
示例#13
0
def googleit(bot, trigger):
    """Let me just… Google that for you."""
    if not trigger.group(2):  # No input
        return bot.say('https://www.google.com/')
    bot.say('https://lmgtfy.com/?q=' +
            quote(trigger.group(2).replace(' ', '+'), '+'))
示例#14
0
def test_quote(text, result):
    assert quote(text) == result