示例#1
0
    async def handle(message: SlackMessage, bot: SlackAdapter, db: DB):

        pattern = "|".join(
            [".*(?:gibbe|give) money.*", ".*pay me.*", ".*:watermelon:.*"])

        trigger = re.compile(pattern, re.IGNORECASE)

        message_ts = arrow.get(message.ts, 'X')

        if not is_payable(message_ts) or not bot.understands(
                message, with_pattern=trigger):
            return

        user_id = message.user

        with db.session_scope() as session:
            user = User.get_by_slack_id(session, user_id)

            if not user:
                return

            latest_mine = session \
                .query(KKredsTransaction) \
                .filter(KKredsTransaction.to_user_id == user.id) \
                .filter(KKredsTransaction.is_mined) \
                .order_by(KKredsTransaction.created_at.desc()) \
                .first()

            if latest_mine and latest_mine.created_at:
                message_ts_stripped = strip_date(message_ts)
                latest_mine_time_stripped = strip_date(latest_mine.created_at)
                if latest_mine_time_stripped >= message_ts_stripped:
                    return

            amount = 1

            if should_2020_04_mega_pay(message_ts):
                amount = randint(1, 10_000)

            kaori_user = User.get_by_slack_id(session, bot.id)
            mined_kkred = KKredsTransaction(from_user=kaori_user,
                                            to_user=user,
                                            amount=amount,
                                            is_mined=True,
                                            created_at=message_ts.datetime)

            session.add(mined_kkred)

        pluralized = '1 kkred' if amount == 1 else f'{amount} kkreds'
        bot.reply(message, f'successfully mined {pluralized}')
示例#2
0
def fake_user(test_db: DB) -> User:
    with test_db.session_scope() as session:
        name = str(uuid4())

        u = User(name=f'{name}-user',
                 slack_id=f'{name}-slack-id',
                 api_key=str(uuid4()))

        session.add(u)
        session.commit()

        return u
示例#3
0
    async def handle(message: SlackMessage, bot: SlackAdapter, db: DB):
        pattern = re.compile('balance', re.IGNORECASE)

        if not bot.addressed_by(message) or not bot.understands(
                message, with_pattern=pattern):
            return

        with db.session_scope() as session:
            user = User.get_by_slack_id(session, message.user)
            balance = get_kkred_balance(user, session)

        pluralized_kkreds = 'kkred' if balance == 1 else 'kkreds'
        return bot.reply(message,
                         f'your balance is {balance} {pluralized_kkreds}')
示例#4
0
    def make_user():
        session: Session
        with test_db.session_scope() as session:
            name = str(uuid4())

            u = User(name=f'{name}-user',
                     slack_id=f'{name}-slack-id',
                     api_key=str(uuid4()))

            session.add(u)
            session.commit()
            session.refresh(u)
            session.expunge(u)

            return u
示例#5
0
def test_card_hydration(db_session: Session):
    from ..engine.test.cards.meme_cards import sachiko
    expected_max_hp = sachiko.max_hp

    name = str(uuid4())

    user = User(name=f'{name}-user',
                slack_id=f'{name}-slack-id',
                api_key=str(uuid4()))

    db_session.add(user)
    db_session.commit()

    card = Card(name=name,
                slug=name,
                owner=user.id,
                creation_thread_channel=f'ch-{name}',
                creation_thread_ts=f'ts-{name}')

    card.set_rarity(sachiko.rarity)

    card.stupid = sachiko.stupid
    card.baby = sachiko.baby
    card.cursed = sachiko.cursed
    card.horny = sachiko.horny
    card.clown = sachiko.clown
    card.feral = sachiko.feral

    card.primary_nature = str(sachiko.nature[0])
    card.secondary_nature = str(sachiko.nature[1])

    db_session.add(card)
    db_session.commit()

    db_session.refresh(card)

    assert bool(card.id) is True
    assert bool(card.name) is True
    assert bool(card.rarity) is True
    assert bool(card.primary_nature) is True
    assert bool(card.secondary_nature) is True

    assert card.engine is not None
    assert card.engine.max_hp == expected_max_hp

    db_session.flush()
示例#6
0
def test_image_from_slack(db_session: Session):
    image_file = Path(__file__) \
        .parent \
        .joinpath('../../../../tests/fixtures/kaori.png') \
        .resolve()

    file = {'id': 'ZZZ'}

    slack_user = str(uuid4())

    message = SlackMessage({
        'event': {
            'user': slack_user,
            'files': [file],
        },
    })

    user = User(name=str(uuid4()), slack_id=slack_user, api_key=str(uuid4()))

    db_session.add(user)
    db_session.commit()

    def fake_downloader(*args, **kwargs):
        return 'fake.png', image_file.open('rb')

    img = Image.from_slack_message(message=message,
                                   session=db_session,
                                   slack_adapter=Mock(spec=SlackAdapter,
                                                      client=None),
                                   uploader=LocalFileUploader(),
                                   slack_file_downloader=fake_downloader)

    db_session.add(img)
    db_session.commit()

    assert re.match(r'https://kaori-img.ngrok.io/fake-sha512-\S+.png',
                    img.url) is not None
    assert img.owner == user.id

    db_session.flush()
示例#7
0
    def from_slack_message(message: SlackMessage,
                           session: Session,
                           slack_adapter: SlackAdapter,
                           uploader: FileUploader,
                           slack_file_downloader=download_slack_file) -> Image:
        file = message.files[0]

        if not file:
            raise RuntimeError('no file in message')

        user = User.get_by_slack_id(session, message.user)
        if not user:
            raise UserNotFound('no user, try refreshing users')

        name, downloaded_file = slack_file_downloader(
            file['id'], slack_client=slack_adapter.client)

        digest = file_digest(downloaded_file)

        url = uploader.upload(hashed_file_name(name, file_hash=digest),
                              downloaded_file)

        return Image(slack_file_id=file['id'], owner=user.id, url=url)
示例#8
0
    async def handle(message: SlackMessage, bot: SlackAdapter, db: DB):

        pattern = re.compile(r'(?:pay|tip|give|send)\s+(\S*)\s+(\S*)',
                             re.IGNORECASE)

        if not bot.addressed_by(message):
            return

        matches = bot.understands(message, with_pattern=pattern)

        if not matches:
            return

        message_ts = arrow.get(message.ts, 'X')

        sending_user_id = message.user

        with db.session_scope() as session:
            sending_user = User.get_by_slack_id(session, sending_user_id)

            if not sending_user:
                return

            receiving_user_raw = matches[1]

            if not is_user_mention(receiving_user_raw):
                return bot.reply(
                    message,
                    'User has to be an `@` mention. Like it has to be a real blue `@` mention.'
                )

            receiving_user = User.get_by_slack_id(
                session, extract_user_id_from_mention(receiving_user_raw))

            if not receiving_user:
                return bot.reply(message, 'Could not find that user')

            if sending_user.id == receiving_user.id:
                return bot.reply(message, 'You can’t send money to yourself.')

            amount_raw = matches[2]

            try:
                amount = Decimal(amount_raw)
            except InvalidOperation:
                return bot.reply(
                    message,
                    'That amount is invalid. Try a decimal or integer value')

            if amount <= 0:
                return bot.reply(message, 'Amount has to be non-zero')

            if amount > get_kkred_balance(sending_user, session):
                return bot.reply(message, 'You don’t have enough kkreds')

            transaction = KKredsTransaction(from_user=sending_user,
                                            to_user=receiving_user,
                                            amount=amount,
                                            created_at=message_ts.datetime)

            session.add(transaction)

            bot.reply(message,
                      f'successfully sent {amount} to {receiving_user.name}')
示例#9
0
    async def handle(message: SlackMessage, bot: SlackAdapter, db: DB,
                     file_uploader: FileUploader):
        if not bot.addressed_by(message) or not message.is_thread:
            return

        try:
            session: Session
            with db.session_scope() as session:
                card = resume_card(session,
                                   thread_ts=message.thread_ts,
                                   user=message.user)

                # this thread is not related to a card creation, ignore
                if not card:
                    return

                # lol god this is quickly getting away from me
                # just let me finish this and I'll refactor later
                user_input = ''

                catch_all_pattern = re.compile(r'(.*)', re.IGNORECASE)
                matches = bot.understands(message,
                                          with_pattern=catch_all_pattern)

                if not matches:
                    return

                user_input = matches[1].strip()

                if user_input == 'refresh preview':
                    refresh_card_preview(card, bot)
                    return

                if card.creation_cursor == 'set_image':
                    if message.files:
                        img = Image.from_slack_message(message=message,
                                                       session=session,
                                                       slack_adapter=bot,
                                                       uploader=file_uploader)
                        card.image = img
                        card.creation_cursor = 'query_description'
                        bot.react(message, 'thumbsup')
                    else:
                        bot.reply(message, 'upload an image to slack')
                        return

                card, replies = next_card_creation_step(
                    card=card,
                    user_input=user_input,
                    session=session,
                    kaori_user=User.get_by_slack_id(session, bot.id))

                refresh_card_preview(card, bot)

                session.merge(card)
                session.commit()

                for reply in replies:
                    if reply == ':+1:':
                        bot.react(message, 'thumbsup')
                    else:
                        if isinstance(reply, dict):
                            bot.reply(message, create_thread=True, **reply)
                        else:
                            bot.reply(message, reply, create_thread=True)

        except InvalidCardName as e:
            bot.reply(message, str(e))
        except IntegrityError as e:
            bot.reply(
                message,
                f"Something is wrong with that input...try again or ask Austin to fix it. Code {e.code}"
            )
            print(e)
示例#10
0
    async def handle(message: SlackMessage, bot: SlackAdapter, db: DB,
                     file_uploader: FileUploader):
        if not bot.addressed_by(message):
            return

        # start a conversation
        if not bot.understands(message,
                               with_pattern=re.compile(
                                   r'create\s+card|card\s+create$', re.I)):
            return

        if message.is_thread_reply:
            return

        try:
            with db.session_scope() as session:
                user = User.get_by_slack_id(session, message.user)

                if not user:
                    raise UserNotFound('cannot find user')

                # allow creation to recover from errors
                card = resume_card(session,
                                   thread_ts=message.thread_ts,
                                   user=message.user)

                if not card:
                    card = initialize_card(message, user)

                    session.add(card)
                    session.commit()

                draft_message = bot.reply(message,
                                          **render_card(card=card,
                                                        preview_header=True),
                                          create_thread=True,
                                          reply_broadcast=True)

                bot.reply(
                    message,
                    blocks=instructions_blocks(bot_name=bot.mention_string),
                    create_thread=True)

                if not draft_message.get('ok'):
                    print(draft_message)
                    return

                card.draft_message_ts = draft_message.get('ts')
                session.merge(card)

        except UserNotFound as e:
            bot.reply(
                message,
                "Something is wrong...cannot find your user. Try 'kaori refresh users'"
            )
            return

        # fake thread
        # todo: this is kinda dumb
        message = copy.deepcopy(message)
        message.is_thread = True
        message.thread_ts = message.ts

        await UpdateCardCommand.handle(message=message,
                                       bot=bot,
                                       db=db,
                                       file_uploader=file_uploader)