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}')
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
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}')
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
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()
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()
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)
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}')
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)
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)