Пример #1
0
def ddg(bot: DeltaBot, payload: str, message: Message,
        replies: Replies) -> None:
    """Search in DuckDuckGo."""
    mode = _get_mode(bot, message.get_sender_contact().addr)
    page = 'lite' if mode == 'htmlzip' else 'html'
    url = "https://duckduckgo.com/{}?q={}".format(page, quote_plus(payload))
    replies.add(**_download_file(bot, url, mode))
Пример #2
0
def w(bot: DeltaBot, payload: str, message: Message, replies: Replies) -> None:
    """Search in Wikipedia."""
    sender = message.get_sender_contact().addr
    lang = _get_locale(bot, sender)
    url = "https://{}.m.wikipedia.org/wiki/?search={}".format(
        lang, quote_plus(payload))
    replies.add(**_download_file(bot, url, _get_mode(bot, sender)))
Пример #3
0
def lines_top(message: Message, replies: Replies) -> None:
    """Send Color Lines scoreboard.

    Example: `/lines_top`
    """
    limit = 15
    text = '🏆 Color Lines Scoreboard\n\n'
    game = db.get_game_by_addr(message.get_sender_contact().addr)
    if not game:
        games = db.get_games(limit)
    else:
        games = db.get_games()
    if not games:
        text += '(Empty list)'
    for n, g in enumerate(games[:limit], 1):
        text += '#{} {} {}\n'.format(n, db.get_nick(g['addr']), g['score'])
    if game:
        player_pos = games.index(game)
        if player_pos >= limit:
            text += '\n'
            if player_pos > limit:
                pgame = games[player_pos - 1]
                text += '#{} {} {}\n'.format(player_pos,
                                             db.get_nick(pgame['addr']),
                                             pgame['score'])
            text += '#{} {} {}\n'.format(player_pos + 1,
                                         db.get_nick(game['addr']),
                                         game['score'])
            if player_pos < len(games) - 1:
                ngame = games[player_pos + 1]
                text += '#{} {} {}\n'.format(player_pos + 2,
                                             db.get_nick(ngame['addr']),
                                             ngame['score'])
    replies.add(text=text)
Пример #4
0
def lyrics(payload: str, replies: Replies) -> None:
    """Get song lyrics.
    """
    base_url = 'https://www.lyrics.com'
    url = "{}/lyrics/{}".format(base_url, quote(payload))
    with requests.get(url, headers=HEADERS) as r:
        r.raise_for_status()
        soup = bs4.BeautifulSoup(r.text, 'html.parser')
    best_matches = soup.find('div', class_='best-matches')
    a = best_matches and best_matches.a
    if not a:
        soup = soup.find('div', class_='sec-lyric')
        a = soup and soup.a
    if a:
        artist, name = map(unquote_plus, a['href'].split('/')[-2:])
        url = base_url + a['href']
        with requests.get(url, headers=HEADERS) as r:
            r.raise_for_status()
            soup = bs4.BeautifulSoup(r.text, 'html.parser')
            lyric = soup.find(id='lyric-body-text')
            if lyric:
                text = '🎵 {} - {}\n\n{}'.format(name, artist,
                                                   lyric.get_text())
                replies.add(text=text)
                return

    replies.add(text='No results for: {}'.format(payload))
Пример #5
0
def echo(payload: str, replies: Replies) -> None:
    """Echo back received text.

    To use it send a message like:
    /echo hello world
    """
    replies.add(text=payload or "echo")
Пример #6
0
def filter_messages(bot: DeltaBot, message: Message, replies: Replies) -> None:
    """Process turns in Exquisite Corpse game groups
    """
    if not message.chat.is_group():
        sender = message.get_sender_contact()
        g = db.get_game_by_turn(sender.addr)

        if g is None:
            return

        if len(message.text.split()) < 10:
            text = '❌ Text too short. Send a message with at least 10 words'
            replies.add(text=text)
        else:
            paragraph = g['text'] + ' ' + message.text
            db.set_text(g['gid'], paragraph)

            p = db.get_player_by_addr(sender.addr)
            assert p is not None
            if p['round'] == 3:
                db.delete_player(p['addr'])
            else:
                db.set_player(p['addr'], p['round'] + 1, g['gid'])

            p = _get_by_round(g['gid'])

            if p is None:  # End Game
                text = _end_game(g['gid'])
                replies.add(text=text, chat=bot.get_chat(g['gid']))
            else:
                db.set_turn(g['gid'], p['addr'])
                _run_turn(bot, p, bot.get_chat(g['gid']), paragraph)
Пример #7
0
def filter_messages(message: Message, bot: DeltaBot, replies: Replies) -> None:
    """Natural language processing and learning.
    """
    if replies.has_replies() or not message.text:
        return

    self_contact = bot.self_contact
    name = bot.account.get_config('displayname')
    quote = message.quote

    reply_to_dash = _getdefault(bot, 'reply_to_dash', '1') not in ('0', 'no')
    resp = None
    if reply_to_dash and message.text.startswith('#') and \
       len(message.text) > 1:
        resp = CBOT.get_response(message.text[1:])
    elif not message.chat.is_group() or (quote and quote.get_sender_contact()
                                         == self_contact):
        resp = CBOT.get_response(message.text)
    elif self_contact.addr in message.text or (name and name in message.text):
        resp = CBOT.get_response(
            _rmprefix(_rmprefix(message.text, self_contact.addr),
                      name).strip(':,').strip())

    if resp:
        bot.logger.debug('Confidence: %s | message: %s | reply: %s',
                         resp.confidence, resp.in_response_to, resp.text)
        if resp.confidence >= float(_getdefault(bot, 'min_confidence', '0')):
            replies.add(text=resp.text)
        else:
            replies.add(text=random.choice(default_replies))

    if quote and quote.text and _getdefault(bot, 'learn') == '1':
        CBOT.learn_response(
            Statement(text=message.text, in_response_to=quote.text))
Пример #8
0
def poll_new(bot: DeltaBot, payload: str, message: Message,
             replies: Replies) -> None:
    """Create a new public poll.

    Example:
    /poll_new Do you like polls?
    yes
    no
    maybe
    """
    lines = []
    for ln in payload.split("\n"):
        ln = ln.strip()
        if ln:
            lines.append(ln)

    if len(lines) < 3:
        replies.add(text="❌ Invalid poll, at least two options needed")
        return

    question = lines.pop(0)

    poll = Poll(addr=message.get_sender_contact().addr, question=question)
    for i, opt in enumerate(lines, 1):
        poll.options.append(Option(id=i, text=opt))
    with session_scope() as session:
        session.add(poll)
        session.flush()
        text, html = _format_poll(bot, poll)
    replies.add(text=text, html=html)
def quote(bot: DeltaBot, payload: str, message: Message,
          replies: Replies) -> None:
    """Get Wikiquote quotes.

    Search in Wikiquote or get the quote of the day if no text is given.
    Example: `/quote Richard Stallman`
    """
    locale = _get_locale(bot, message.get_sender_contact().addr)
    if locale in wq.supported_languages():
        lang = locale
    else:
        lang = None
    if payload:
        authors = wq.search(payload, lang=lang)
        if authors:
            if payload.lower() == authors[0].lower():
                author = authors[0]
            else:
                author = choice(authors)
            text = f'"{choice(wq.quotes(author, max_quotes=200, lang=lang))}"\n\n― {author}'
        else:
            text = f"No quote found for: {payload}"
    else:
        _quote, author = wq.quote_of_the_day(lang=lang)
        text = f'"{_quote}"\n\n― {author}'

    replies.add(text=text)
Пример #10
0
def _check_feed(bot: DeltaBot, f: sqlite3.Row) -> None:
    fchats = db.get_fchats(f['url'])

    if not fchats:
        db.remove_feed(f['url'])
        return

    bot.logger.debug('Checking feed: %s', f['url'])
    d = feedparser.parse(f['url'], etag=f['etag'], modified=f['modified'])

    bozo_exception = d.get('bozo_exception', '')
    if d.get('bozo') == 1 and not isinstance(bozo_exception,
                                             CharacterEncodingOverride):
        bot.logger.exception(bozo_exception)
        return

    if d.entries and f['latest']:
        d.entries = get_new_entries(d.entries,
                                    tuple(map(int, f['latest'].split())))
    if not d.entries:
        return

    html = format_entries(d.entries[:50])
    replies = Replies(bot, logger=bot.logger)
    for gid in fchats:
        try:
            replies.add(html=html, chat=bot.get_chat(gid))
        except (ValueError, AttributeError):
            db.remove_fchat(gid)
    replies.send_reply_messages()

    latest = get_latest_date(d.entries) or f['latest']
    modified = d.get('modified') or d.get('updated')
    db.update_feed(f['url'], d.get('etag'), modified, latest)
Пример #11
0
def wf_unbridge(message: Message, replies: Replies) -> None:
    """Remove bridge with the WriteFreely blog in the chat it is sent.

    Example: `/wf_unbridge`
    """
    db.del_chat(message.chat.id)
    replies.add(text='✔️Removed bridge.')
Пример #12
0
def filter_messages(bot: DeltaBot, message: Message, replies: Replies) -> None:
    """Detect messages like +1 or -1 to increase/decrease score.
    """
    if not message.quote:
        return
    score = _parse(message.text)
    if not score:
        return
    sender = message.get_sender_contact().addr
    is_admin = bot.is_admin(sender)
    if score < 0 and not is_admin:
        return
    if not is_admin and db.get_score(sender) - score < 0:
        replies.add(text="❌ You can't give what you don't have...",
                    quote=message)
        return
    receiver = message.quote.get_sender_contact().addr
    if sender == receiver:
        return

    sender_score = _add_score(sender, -score)
    receiver_score = _add_score(receiver, score)
    if is_admin:
        text = '{0}: {1}{4}'
    else:
        text = '{0}: {1}{4}\n{2}: {3}{4}'
    text = text.format(
        bot.get_contact(receiver).name, receiver_score,
        bot.get_contact(sender).name, sender_score,
        _getdefault(bot, 'score_badge'))
    replies.add(text=text, quote=message)
Пример #13
0
def c4_play(bot: DeltaBot, payload: str, message: Message, replies: Replies) -> None:
    """Invite a friend to play Connect4.

    Example: `/c4_play [email protected]`
    """
    if not payload:
        replies.add(text="Missing address")
        return

    if payload == bot.self_contact.addr:
        replies.add(text="Sorry, I don't want to play")
        return

    p1 = message.get_sender_contact().addr
    p2 = payload
    if p1 == p2:
        replies.add(text="You can't play with yourself")
        return

    g = db.get_game_by_players(p1, p2)

    if g is None:  # first time playing with p2
        chat = bot.create_group(
            '4️⃣ {} 🆚 {} [c4]'.format(p1, p2), [p1, p2])
        b = Board()
        db.add_game(p1, p2, chat.id, b.export(), p1)
        text = 'Hello {1},\nYou have been invited by {0} to play Connect4'
        text += '\n\n{2}: {0}\n{3}: {1}\n\n'
        text = text.format(
            p1, p2, b.get_disc(BLACK), b.get_disc(WHITE))
        replies.add(text=text + _run_turn(chat.id), chat=chat)
    else:
        text = 'You already have a game group with {}'.format(p2)
        replies.add(text=text, chat=bot.get_chat(g['gid']))
Пример #14
0
def chatter_learn(payload: str, replies: Replies) -> None:
    """Learn new response.

    You must provide two lines, the first line is the question and the
    second line is the response.
    """
    LIST_TRAINER.train(payload.split('\n', maxsplit=1))
    replies.add(text='✔️Learned.')
Пример #15
0
def web(bot: DeltaBot, payload: str, message: Message,
        replies: Replies) -> None:
    """Download a webpage or file."""
    mode = _get_mode(bot, message.get_sender_contact().addr)
    try:
        replies.add(**_download_file(bot, payload, mode))
    except FileTooBig as err:
        replies.add(text=str(err))
Пример #16
0
def topic(message: Message, replies: Replies) -> None:
    """Show IRC channel topic.
    """
    chan = db.get_channel_by_gid(message.chat.id)
    if not chan:
        replies.add(text='This is not an IRC channel')
    else:
        replies.add(text='Topic:\n{}'.format(irc_bridge.get_topic(chan)))
Пример #17
0
def img(bot: DeltaBot, payload: str, replies: Replies) -> None:
    """Search for images, returns image links.
    """
    text = '\n\n'.join(_get_images(bot, payload))
    if text:
        replies.add(text='{}:\n\n{}'.format(payload, text))
    else:
        replies.add(text='No results for: {}'.format(payload))
Пример #18
0
def cmd_read(bot: DeltaBot, payload: str, message: Message,
             replies: Replies) -> None:
    """Download a webpage and try to improve its readability."""
    mode = _get_mode(bot, message.get_sender_contact().addr)
    try:
        replies.add(**_download_file(bot, payload, mode, True))
    except FileTooBig as err:
        replies.add(text=str(err))
Пример #19
0
def _roll_dice(count: int, quote: Message, replies: Replies) -> None:
    dices = []
    total = 0
    for _ in range(count):
        rand = random.randrange(0, 6)
        total += rand + 1
        dices.append(DICES[rand])
    replies.add(text="{} ({})".format(" ".join(dices), total), quote=quote)
Пример #20
0
def wttr(bot: DeltaBot, payload: str, message: Message,
         replies: Replies) -> None:
    """Search weather info from wttr.in"""
    lang = _get_locale(bot, message.get_sender_contact().addr)
    url = 'https://wttr.in/{}_Fnp_lang={}.png'.format(quote(payload), lang)
    reply = _download_file(bot, url)
    reply.pop('text')
    replies.add(**reply)
Пример #21
0
def img1(bot: DeltaBot, payload: str, replies: Replies) -> None:
    """Get an image based on the given text.
    """
    imgs = _download_images(bot, payload, 1)
    if not imgs:
        replies.add(text='No results for: {}'.format(payload))
    else:
        for reply in imgs:
            replies.add(**reply)
Пример #22
0
def friends_leave(message: Message, replies: Replies) -> None:
    """Remove you from the list.
    """
    addr = message.get_sender_contact().addr
    if db.get_bio(addr) is None:
        replies.add(text='You are not in the list yet')
    else:
        db.remove_user(addr)
        replies.add(text='You were removed from the list')
Пример #23
0
def img5(bot: DeltaBot, payload: str, replies: Replies) -> None:
    """Search for images, returns 5 results.
    """
    imgs = _download_images(bot, payload, 5)
    if not imgs:
        replies.add(text='No results for: {}'.format(payload))
    else:
        for reply in imgs:
            replies.add(**reply)
Пример #24
0
def corpse_leave(bot: DeltaBot, message: Message, replies: Replies) -> None:
    """Leave Exquisite Corpse game in current group.

    Example: `/corpse_leave`
    """
    p = db.get_player_by_addr(message.get_sender_contact().addr)
    if p:
        _remove_from_game(bot, p, db.get_game_by_gid(p['game']))
    else:
        replies.add(text='❌ You are not playing Exquisite Corpse.')
def translate_filter(bot: DeltaBot, message: Message,
                     replies: Replies) -> None:
    """Send me in private any text message to translate it."""
    if not message.chat.is_group() and message.text:
        lang = _get_language(bot, message.get_sender_contact().addr)
        if lang in langs.values():
            text = _translate("auto", lang, message.text, bot)
        else:
            text = (f"❌ Invalid language code: {lang!r}."
                    " Send /tr to see the list of available codes.")
        replies.add(text=text, quote=message)
Пример #26
0
def xkcd_get(payload: str, message: Message, replies: Replies) -> None:
    """Get the comic with the given number or a ramdom comic if no number is provided."""
    if not payload:
        comic = xkcd.getRandomComic()
    elif payload.isdigit():
        comic = xkcd.getComic(int(payload))
    else:
        comic = None
    if comic is None or comic.number == -1:
        replies.add(text="❌ Invalid comic number", quote=message)
    else:
        replies.add(**_get_reply(comic))
Пример #27
0
def group_adminchan(bot: DeltaBot, args: list, message: Message,
                    replies: Replies) -> None:
    """Join the admin group of the given channel.
    """
    ch = db.get_channel_by_id(int(args[0]))
    if ch:
        sender = message.get_sender_contact()
        _add_contact(bot.get_chat(ch['admin']), sender)
        text = '{}\n\n{}'.format(ch['name'], ch['topic'] or '-')
        replies.add(text=text, chat=bot.get_chat(sender))
    else:
        replies.add(text='❌ Invalid ID')
Пример #28
0
def filter_messages(bot: DeltaBot, message: Message, replies: Replies) -> None:
    """Detect messages like +1 or -1 to increase/decrease score."""
    if message.quote:
        receiver_addr = message.quote.get_sender_contact().addr
        score = _parse(message.text)
    else:
        args = message.text.split(maxsplit=2)
        if len(args) == 2 and "@" in args[0]:
            receiver_addr = args[0]
            score = _parse(args[1])
        else:
            score = 0
    if not score:
        return
    sender_addr = message.get_sender_contact().addr
    is_admin = bot.is_admin(sender_addr)
    if (score < 0 and not is_admin) or sender_addr == receiver_addr:
        return

    with session_scope() as session:
        sender = session.query(User).filter_by(addr=sender_addr).first()
        if not sender:
            sender = User(addr=sender_addr)
            session.add(sender)
        if not is_admin and sender.score - score < 0:
            replies.add(text="❌ You can't give what you don't have...",
                        quote=message)
            return

        if not is_admin:
            sender.score -= score
        sender_score = sender.score

        receiver = session.query(User).filter_by(addr=receiver_addr).first()
        if not receiver:
            receiver = User(addr=receiver_addr)
            session.add(receiver)

        receiver.score += score
        receiver_score = receiver.score

    if is_admin:
        text = "{0}: {1}{4}"
    else:
        text = "{0}: {1}{4}\n{2}: {3}{4}"
    text = text.format(
        bot.get_contact(receiver_addr).name,
        receiver_score,
        bot.get_contact(sender_addr).name,
        sender_score,
        _getdefault(bot, "score_badge"),
    )
    replies.add(text=text, quote=message)
Пример #29
0
def poll_list(message: Message, replies: Replies) -> None:
    """Show your public polls."""
    with session_scope() as session:
        text = ""
        for poll in (session.query(Poll).filter_by(
                addr=message.get_sender_contact().addr).all()):
            if len(poll.question) > 100:
                q = poll.question[:100] + "..."
            else:
                q = poll.question
            text += "📊 /poll_get_{} {}\n\n".format(poll.id, q)
    replies.add(text=text or "❌ Empty list", chat=message.get_sender_chat())
Пример #30
0
def feed_sub(bot: DeltaBot, payload: str, message: Message,
             replies: Replies) -> None:
    """Subscribe current chat to the given feed.
    """
    url = db.normalize_url(payload)
    feed = db.get_feed(url)

    if feed:
        d = feedparser.parse(feed['url'])
    else:
        max_fc = int(_getdefault(bot, 'max_feed_count'))
        if 0 <= max_fc <= len(db.get_feeds()):
            replies.add(text='Sorry, maximum number of feeds reached')
            return
        d = feedparser.parse(url)
        bozo_exception = d.get('bozo_exception', '')
        if (d.get('bozo') == 1 and not isinstance(
                bozo_exception, CharacterEncodingOverride)) or not d.entries:
            replies.add(text='Invalid feed url: {}'.format(url))
            bot.logger.warning('Invalid feed %s: %s', url, bozo_exception)
            return
        feed = dict(
            url=url,
            etag=d.get('etag'),
            modified=d.get('modified') or d.get('updated'),
            latest=get_latest_date(d.entries),
        )
        db.add_feed(url, feed['etag'], feed['modified'], feed['latest'])
    assert feed

    if message.chat.is_group():
        chat = message.chat
    else:
        chat = bot.create_group(
            d.feed.get('title') or url, [message.get_sender_contact()])

    if chat.id in db.get_fchats(feed['url']):
        replies.add(text='Chat alredy subscribed to that feed.', chat=chat)
        return

    db.add_fchat(chat.id, feed['url'])
    title = d.feed.get('title') or '-'
    desc = d.feed.get('description') or '-'
    text = 'Title: {}\n\nURL: {}\n\nDescription: {}'.format(
        title, feed['url'], desc)

    if d.entries and feed['latest']:
        latest = tuple(map(int, feed['latest'].split()))
        html = format_entries(get_old_entries(d.entries, latest)[:5])
        replies.add(text=text, html=html, chat=chat)
    else:
        replies.add(text=text, chat=chat)