이번에는 저번에 만들었던 디스코드 챗봇에 급식 파서를 활용하여
급식을 알려주는 챗봇을 만들도록 하겠습니다.
이전과정
[
디스코드 챗봇 만들기 --> http://mandu-mandu.tistory.com/64
급식 파서 만들기 --> http://mandu-mandu.tistory.com/21
]
코드 작성하기
필요한 모듈로는, datetime 모듈과 만들어둔 parser.py가 필요합니다.
parser.py를 디스코드 봇 소스가 있는 디렉토리로 옮겨두고
아래 코드를, 디스코드 봇 소스 상단에 추가해줍시다.
import datetime
from parser import *
내일의 식단을 출력하기
먼저, 내일의 식단을 출력하는 코드를 작성하겠습니다.
코드를 작성하기 위해 내일의 식단을 출력하는 그 과정을 구상해 봅시다.
1. 디스코드에서 사용자로부터 명령어를 인식합니다.
저는 '!t' 로 설정하겠습니다.
2. 명령어를 인식한 시점으로부터 다음날의 날짜값과 그 날짜의 요일값을 가져옵니다.
파서의 함수가 필요로 하는 인자가 조식.중식.석식 여부 / 날짜 / 요일이기 때문입니다.
모두 datetime 함수를 사용합니다.
3. 급식을 파싱하는 함수를 호출합니다. 그리고 그 값을 저장합니다.
4. 그 값을 출력합니다.
제가 다니는 학교의 급식 상황을 보면, 조식이 전혀 없고 중식이 없을 경우 100% 석식이 없습니다.
이에 따라 조건절을 추가하여 출력되는 메세지를 '최적화'하였습니다.
(식단 내용 외 날짜등의 정보도 같이 출력해주기 때문입니다.)
중식이 없을 경우 급식이 없다고 출력,
중식이 있고 석식은 없을 경우 중식만 출력,
중식 석식 모두 있을 경우 모두 출력.
이를 코드로 구현하면 아래처럼 됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | if message.content.startswith('!to'): #메세지의 내용의 시작이 !to로 시작할 경우 to_tomorrow = datetime.datetime.today() + datetime.timedelta(days=1) #오늘 날짜에 하루를 더함 local_date2 = to_tomorrow.strftime("%Y.%m.%d") #위에서 구한 날짜를 년.월.일 형식으로 저장 local_weekday2 = to_tomorrow.weekday() #위에서 구한 날짜의 요일값을 저장 l_diet = get_diet(2, local_date2, local_weekday2) #점심식단을 파싱해옴 d_diet = get_diet(3, local_date2, local_weekday2) #석식식단을 파싱해옴 if len(l_diet) == 1: #점심식단의 길이가 1일경우 = parser.py에서 식단이 없을경우 공백한자리를 반환함. await client.send_message(message.channel, "급식이 없습니다.") #급식이 없다고 메세지 보냄 elif len(d_diet) == 1: #점심식단의 길이가 1이 아니고 석식식단의 길이가 1일경우 = 점심식단만 있을경우 lunch = local_date2 + " 중식\n" + l_diet #날짜와 "중식"을 앞에 붙여서 await client.send_message(message.channel, lunch) #메세지 보냄 else: #둘다 길이가 1이 아닐경우 = 점심, 석식 식단 모두 있을 경우 lunch = local_date2 + " 중식\n" + l_diet #앞에 부가적인 내용을 붙여서 dinner = local_date2 + " 석식\n" + d_diet await client.send_message(message.channel, lunch) #메세지를 보냄 await client.send_message(message.channel, dinner) | cs |
코드상
@client.event
async def on_message(message):
아래에 위치하게 됩니다.
상황에 따라 if가 이미 있을 경우
if message.content.startswith('!to'):
if를 elif로 바꿔서 사용해야 합니다. (파이썬의 기본...)
특정 날짜의 식단을 출력하기
이제 날짜값을 주면 그 날짜의 급식을 출력하는 코드를 작성하겠습니다.
코드의 구성은 위 '내일의 식단을 출력하기'의 코드에서 2번의 내용만 수정해 주면 됩니다.
1. 디스코드에서 사용자로부터 명령어를 인식합니다.
저는 '!t' 로 설정하겠습니다.
2. 날짜를 입력하라는 메세지를 보냅니다. 그리고 받은 날짜의 요일값을 구합니다. (코드로 구현하면 길어집니다.)
datetime 모듈을 이용합니다.
3. 급식을 파싱하는 함수를 호출합니다. 그리고 그 값을 저장합니다.
4. 그 값을 출력합니다.
제가 다니는 학교의 급식 상황을 보면, 조식이 전혀 없고 중식이 없을 경우 100% 석식이 없습니다.
이에 따라 조건절을 추가하여 출력되는 메세지를 '최적화'하였습니다.
(식단 내용 외 날짜등의 정보도 같이 출력해주기 때문입니다.)
중식이 없을 경우 급식이 없다고 출력,
중식이 있고 석식은 없을 경우 중식만 출력,
중식 석식 모두 있을 경우 모두 출력.
이를 코드로 구현하면 아래와 같습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | elif message.content.startswith('!g'): await client.send_message(message.channel, '날짜를 보내주세요...') #날짜를 보내달라는 메세지를 보냄 meal_date = await client.wait_for_message(timeout=15.0, author=message.author) #제한시간은 15초 if meal_date is None: #값이 존재하지 않거나 시간이 초과되었을 경우 await client.send_message(message.channel, '15초내로 입력해주세요. 다시시도 : !g') #다시 시도하라는 메세지를 보냄 return else: #값이 있다면 meal_date = str(meal_date.content) # str형으로 변환, (사용자로부터 20180219와 같은 형태로 받아야 합니다.) meal_date = '20' + meal_date[:2] + '.' + meal_date[2:4] + '.' + meal_date[4:6] # 2018.02.19 사이에 점을 추가함 #(사용자로부터 점이 포함된 값으로 받을경우 위 코드를 삭제해도 됩니다.) s = meal_date.replace('.', ', ') # 2018, 02, 19 점을 반점으로 교체 ss = "datetime.datetime(" + s + ").weekday()" #eval함수를 통해 요일값을 구하기 위한 작업 try: whatday = eval(ss) #요일값을 구해서 whatday에 저장 except: #오류가 날 경우 다시 시도하라는 메세지를 보냄 await client.send_message(message.channel, '올바른 값으로 다시 시도하세요 : !g') return #이하 '내일 식단을 출력하기'와 같음 l_diet = get_diet(2, meal_date, whatday) d_diet = get_diet(3, meal_date, whatday) if len(l_diet) == 1: l_diet = "급식이 없습니다." await client.send_message(message.channel, embed=l_diet) elif len(d_diet) == 1: lunch = meal_date + " 중식\n" + l_diet await client.send_message(message.channel, embed=lunch) else: lunch = meal_date + " 중식\n" + l_diet dinner = meal_date + " 석식\n" + d_diet await client.send_message(message.channel, lunch) await client.send_message(message.channel, dinner) | cs |
파서의 함수를 호출하는 부분에서 윗부분이 많이 복잡해진 것을 알 수 있습니다.
아래부분은 기존과 변화가 없기 때문에 주석을 달지 않았습니다.
위 둘을 합친 전체 코드는 아래와 같게 됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | import discord import asyncio import datetime from parser import * client = discord.Client() @client.event async def on_ready(): print('Logged in as') print(client.user.name) print(client.user.id) print('------') @client.event async def on_message(message): if message.content.startswith('!to'): #메세지의 내용의 시작이 !to로 시작할 경우 to_tomorrow = datetime.datetime.today() + datetime.timedelta(days=1) #오늘 날짜에 하루를 더함 local_date2 = to_tomorrow.strftime("%Y.%m.%d") #위에서 구한 날짜를 년.월.일 형식으로 저장 local_weekday2 = to_tomorrow.weekday() #위에서 구한 날짜의 요일값을 저장 l_diet = get_diet(2, local_date2, local_weekday2) #점심식단을 파싱해옴 d_diet = get_diet(3, local_date2, local_weekday2) #석식식단을 파싱해옴 if len(l_diet) == 1: #점심식단의 길이가 1일경우 = parser.py에서 식단이 없을경우 공백한자리를 반환함. await client.send_message(message.channel, "급식이 없습니다.") #급식이 없다고 메세지 보냄 elif len(d_diet) == 1: #점심식단의 길이가 1이 아니고 석식식단의 길이가 1일경우 = 점심식단만 있을경우 lunch = local_date2 + " 중식\n" + l_diet #날짜와 "중식"을 앞에 붙여서 await client.send_message(message.channel, lunch) #메세지 보냄 else: #둘다 길이가 1이 아닐경우 = 점심, 석식 식단 모두 있을 경우 lunch = local_date2 + " 중식\n" + l_diet #앞에 부가적인 내용을 붙여서 dinner = local_date2 + " 석식\n" + d_diet await client.send_message(message.channel, lunch) #메세지를 보냄 await client.send_message(message.channel, dinner) elif message.content.startswith('!g'): await client.send_message(message.channel, '날짜를 보내주세요...') #날짜를 보내달라는 메세지를 보냄 meal_date = await client.wait_for_message(timeout=15.0, author=message.author) #제한시간은 15초 if meal_date is None: #값이 존재하지 않거나 시간이 초과되었을 경우 await client.send_message(message.channel, '15초내로 입력해주세요. 다시시도 : !g') #다시 시도하라는 메세지를 보냄 return else: #값이 있다면 meal_date = str(meal_date.content) # str형으로 변환, (사용자로부터 20180219와 같은 형태로 받아야 합니다.) meal_date = '20' + meal_date[:2] + '.' + meal_date[2:4] + '.' + meal_date[4:6] # 2018.02.19 사이에 점을 추가함 #(사용자로부터 점이 포함된 값으로 받을경우 위 코드를 삭제해도 됩니다.) s = meal_date.replace('.', ', ') # 2018, 02, 19 점을 반점으로 교체 ss = "datetime.datetime(" + s + ").weekday()" #eval함수를 통해 요일값을 구하기 위한 작업 try: whatday = eval(ss) #요일값을 구해서 whatday에 저장 except: #오류가 날 경우 다시 시도하라는 메세지를 보냄 await client.send_message(message.channel, '올바른 값으로 다시 시도하세요 : !g') return #이하 '내일 식단을 출력하기'와 같음 l_diet = get_diet(2, meal_date, whatday) d_diet = get_diet(3, meal_date, whatday) if len(l_diet) == 1: l_diet = "급식이 없습니다." await client.send_message(message.channel, embed=l_diet) elif len(d_diet) == 1: lunch = meal_date + " 중식\n" + l_diet await client.send_message(message.channel, embed=lunch) else: lunch = meal_date + " 중식\n" + l_diet dinner = meal_date + " 석식\n" + d_diet await client.send_message(message.channel, lunch) await client.send_message(message.channel, dinner) client.run('token') | cs |
# 글을 작성하면서 보니
#[23,35]과 [59,72]가 하는 일이 같은데
#함수로 하나 정의해서 같이 쓰는게
#효율적일 것 같다는 생각이 듭니다..
#지금은 귀찮으니 PASS
#############
18.03.03 추가
!g 를 통해 특정 날짜의 급식을 부르는 과정에서
날짜값을 받고 처리하는 과정에서 한자리 달의 경우 오류가 발생,
이 부분을 수정하여 한자리 달의 경우도 가능합니다.
수정된 코드는 깃허브를 확인.
https://github.com/M4ndU/inhun_discord_chat_bot_2
############
'Project > Programming' 카테고리의 다른 글
[Python] Python으로 카카오톡 봇 만들기 (2) - 급식 파서 활용하기 (14) | 2018.02.22 |
---|---|
[Python] Python으로 카카오톡 봇 만들기 (1) - 봇 생성부터 테스트까지 (25) | 2018.02.21 |
[Python] Python으로 디스코드 봇 만들기 (3) - 부가적 기능 추가하기 (5) | 2018.02.19 |
[Python] Python으로 디스코드 봇 만들기 (1) - 봇 생성부터 테스트까지 (76) | 2018.02.19 |
[Python] Beautifulsoup로 급식 식단 파서 만들기 (6) | 2017.12.04 |