지난 포스팅에 이어 슬랙 봇을 이용한 불용한자 알아보기를 이어서 진행한다.
슬랙의 커스텀 슬래시 커맨드를 이용하여 유저에게 슬랙 봇이 DM을 보내는 기능까지 작성했었다.
이 후에 최초로 구상한 것은 슬래시 커맨드가 발생하였을 때
위 이미지와 같은 plain text
를 보내서 메시지를 유저에게 전달하고,
유저가 답변을 작성한 것을 바탕으로 다음 로직을 실행하도록 작성하는 방향으로 생각하였다.
Block Kit Builder 슬랙에서 제공하는 킷 빌더를 통해서 여러가지 Block 메시지를 구성할 수 있다.
유저와 상호작용을 하기 위해서 plain_text_input
에서 유저가 입력한 메시지를 얻어내려면
앱 페이지에서 Interactivity & Shortcuts 메뉴로 들어간 후 이미지처럼
트리거가 발생했을 때 작동하는 엔드포인트를 설정해주어야 한다.
@app.post("/myname")
async def input_myname():
channel_id = "U023VKA2PUJ"
blocks = [
{
"dispatch_action": True,
"type": "input",
"element": {
"type": "plain_text_input",
"action_id": "plain_text_input-action",
"placeholder": {
"type": "plain_text",
"text": "ex) 金炯旭"
},
},
"label": {
"type": "plain_text",
"text": "당신의 이름을 '한자'로 입력해 주세요.",
"emoji": True
}
}
]
slack_client = SlackAPI(config.slack_bot_token)
result = slack_client.post_message(
channel_id=channel_id,
text="나의이름은",
blocks=blocks
)
return
슬래시 커맨드가 발생했을 때 유저가 입력할 수 있는 텍스트 폼을 보내준다.
@app.post("/interactive")
async def post_message(request: Request):
form_data = await request.form()
payload = json.loads(form_data.get("payload"))
print(payload.get("actions"))
return
유저가 입력했을 때 위에서 설정한 것 처럼 이 엔드포인트로 정보가 들어오게 된다.
form_data
형식으로 받고 payload
라는 키에 정보들이 들어있으며 텍스트에 입력한 값은 actions
의 value
에서 찾을 수 있다.
이제 유저가 입력한 값을 바탕으로 DB에서 찾아서 메시지를 다시 유저에게 알려주도록 한다.
from pydantic import BaseModel, Field
class ChinaCharacterInfo(BaseModel):
chn_character_no: int = Field(...)
cha_name: str = Field(...)
kor_name: str = Field(...)
description: str = Field(...)
call_name: str = Field(...)
pydantic 모델을 사용하여 DB에서 얻은 값들을 담아주고,
from sqlalchemy.orm import Session
from db.models.china_character import ChinaCharacterInfo
from db.schema.china_character import ChinaCharacter
async def get_china_character_name(
name: list[str],
db: Session
):
query = db.query(ChinaCharacter).filter(ChinaCharacter.CHA_NAME.in_(name)).all()
result = [
ChinaCharacterInfo(
chn_character_no=row.CHN_CHARACTER_NO,
cha_name=row.CHA_NAME,
kor_name=row.KOR_NAME,
description=row.DESCRIPTION,
call_name=row.CALL_NAME,
) for row in query
]
return result
사용자가 입력한 이름을 1글자 단위로 쪼개서 디비에서 검색한다.
@app.post("/interactive")
async def post_message(request: Request, db: Session = Depends(get_db)):
form_data = await request.form()
payload = json.loads(form_data.get("payload"))
myname = payload["actions"][0]["value"]
name_list = [myname[i:i+1] for i in range(len(myname))]
result = await get_china_character_name(name_list, db)
if not result:
message = "멋진 이름입니다. 당신의 이름에는 불용한자가 없습니다!"
else:
name_text = ""
for name in result:
name_text = f"{name_text}불용한자는 [{name.cha_name},{name.kor_name}]이며, 이 한자는 {name.description}\n"
message = f"당신의 이름 중 불용한자는 총 {len(result)}개 입니다...\n{name_text}\n\n부모님이 주신 소중한 이름, 재미로만 봐주세요 🥹"
channel_id = "U023VKA2PUJ"
slack_client = SlackAPI(config.slack_bot_token)
slack_client.post_message(
channel_id=channel_id,
text=message,
)
return
이제 슬랙에서 실제로 사용해본다.
테스트로 디비에 있는 값들 아무거나 넣어봤는데 무시무시한 뜻 풀이다.
역시, 이런 거는 재미로만 보는것이 정신건강에 이롭다.
디비에 없는 경우도 잘 나온다.
기능을 우선 만들어보고자 코드가 많이 더러워졌기 때문에 다음번엔 기능을 추가하면서 코드를 정리해보려고 한다.