async def handle(message: SlackMessage, bot: SlackAdapter, db: DB, battler: CardBattler): if not bot.addressed_by(message): return requested_battle = _user_requesting_battle(message=message, bot=bot) if not requested_battle: return attacker_search = requested_battle[1] defender_search = requested_battle[2] with db.session_scope() as session: attacker = Card.search_for_one(session, attacker_search) if not attacker: bot.reply(message, f'no card named "{attacker_search}"', create_thread=True) return defender = Card.search_for_one(session, defender_search) if not defender: bot.reply(message, f'no card named "{defender_search}"', create_thread=True) return battle_url = battler.get_battle_url(attacker.engine, defender.engine) bot.reply(message, create_thread=True, blocks=battle_blocks(attacker=attacker, defender=defender, battle_url=battle_url))
async def handle(message: SlackMessage, bot: SlackAdapter, db: DB): if not bot.addressed_by(message): return show_card_pattern = '|'.join([ '(?:get|show|find) card' ]) show_card_pattern = f'(?:{show_card_pattern})' pattern = re.compile(f'{show_card_pattern} (.+)', re.I) search = bot.understands(message, with_pattern=pattern) if not search: return with db.session_scope() as session: card = Card.search_for_one(session, search[1]) if not card: bot.reply(message, 'no card with that name', create_thread=True) return bot.reply(message, **render_card(card))
async def handle(message: SlackMessage, bot: SlackAdapter, db: DB): if not bot.addressed_by(message): return show_card_pattern = '|'.join([ 'cards? (?:stats|statistics)' ]) if not bot.understands(message, with_pattern=re.compile(show_card_pattern, re.I)): return with db.session_scope() as session: game_cards = get_game_cards(session) if not game_cards: bot.reply(message, "No cards", create_thread=True) return bot.reply(message, blocks=card_stats_blocks(card_total=len(game_cards)), create_thread=True) report = generate_report_charts(game_cards) bot.client.api_call( 'files.upload', channels=message.channel, thread_ts=message.ts, filename='rarity.png', file=report['rarity']) bot.client.api_call( 'files.upload', channels=message.channel, thread_ts=message.ts, filename='natures.png', file=report['natures'])
async def handle(message: SlackMessage, bot: SlackAdapter, db: DB): if not bot.addressed_by(message): return show_card_pattern = '|'.join([ '(?:get|gimme|show|find|list) ?(?:my|muh)? cardo?s' ]) if not bot.understands(message, with_pattern=re.compile(show_card_pattern, re.I)): return with db.session_scope() as session: cards = session.query(Card) \ .join(User) \ .filter(User.slack_id == message.user) \ .filter(Card.published == True) \ .limit(10) \ .all() if not cards: bot.reply(message, "You don't have any cards yet.", create_thread=True) return bot.reply(message, create_thread=True, blocks=card_index_blocks(cards))
def test_card_creation_state_happy(make_fake_user, grant_kkreds): config = test_config db_engine = create_engine(config.DATABASE_URL) make_session = sessionmaker(bind=db_engine, autoflush=False) k = Kaori() initial_ts = str(time()) slack = Mock(spec=SlackClient) slack.api_call = MagicMock(return_value={ 'ok': True, 'ts': initial_ts, }) adapter = SlackAdapter(slack_client=slack) adapter._cached_bot_id = token_hex(2) k.adapters['slack'] = adapter db = DB(make_session=make_session) k.skills |= { db, CardBattler(player_url_base='https://battle.kaori.io/') } k.skills.add(LocalFileUploader()) k.plugins |= { gacha_plugin, } u: User = make_fake_user() slack_id = u.slack_id user_id = u.id grant_kkreds(u, 1e10) def handle(msg): k.handle('slack', msg) channel = "CXXXXXX" def user_message(**kwargs): ts = time() return { "team_id": "TXXXX", "event": { "type": "message", "user": slack_id, "ts": ts, "channel": channel, "event_ts": ts, "channel_type": "channel", **kwargs, }, "type": "event_callback", } with db.session_scope() as session: handle(user_message(text='@kaori create card', ts=initial_ts, event_ts=initial_ts)) card = session.query(Card) \ .join(User) \ .filter(Card.creation_thread_ts == initial_ts) \ .first() assert card.owner == user_id assert card.creation_cursor == 'set_name' name = f'Matt Morgan {token_hex(2)}' handle(user_message(text=f'@kaori {name}', thread_ts=initial_ts)) session.refresh(card) assert card.name == name assert card.creation_cursor == 'set_image' # TODO skipping over image uploading lmao card.creation_cursor = 'set_description' session.commit() handle(user_message(text=f'@kaori ubu uwu', thread_ts=initial_ts)) session.refresh(card) assert card.description == 'ubu uwu' handle(user_message(text=f'@kaori stupid feral', thread_ts=initial_ts)) session.refresh(card) assert card.primary_nature == 'stupid' assert card.secondary_nature == 'feral' handle(user_message(text=f'@kaori S', thread_ts=initial_ts)) session.refresh(card) assert card.rarity_string() == 'S' assert card.published is False handle(user_message(text=f'@kaori yes', thread_ts=initial_ts)) session.refresh(card) assert card.published is True assert card.creation_cursor == 'done'
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)
dramatiq.set_broker(rabbitmq_broker) if not config.SLACK_API_TOKEN: raise ValueError('You are missing a slack token! Please set the SLACK_API_TOKEN environment variable in your ' '.env file or in the system environment') sc = SlackClient(config.SLACK_API_TOKEN) db_engine = create_engine(config.DATABASE_URL) make_session = sessionmaker(bind=db_engine, autoflush=False) k = Kaori() k.adapters['slack'] = SlackAdapter(slack_client=sc) k.skills |= { DB(make_session=make_session), } if hasattr(config, 'USE_GCLOUD_STORAGE') and config.USE_GCLOUD_STORAGE: creds = service_account.Credentials.from_service_account_info(config.GCLOUD_SERVICE_ACCOUNT_INFO) bucket = storage.Client(project=creds.project_id, credentials=creds).bucket(config.IMAGES_BUCKET_GCLOUD) k.skills.add(GCloudStorageUploader(bucket=bucket, base_path=config.IMAGES_BUCKET_PATH)) elif config.KIZUNA_ENV == 'development': k.skills.add(LocalFileUploader()) else: k.logger.warning('no file upload handler specified!') if hasattr(config, 'GACHA_BATTLE_URL_BASE') and config.GACHA_BATTLE_URL_BASE:
def db() -> DB: return DB(make_session=db_sessionmaker())