일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 자바
- 푸시푸시
- 클라우드
- MySQL
- 데이트
- c
- 데이터베이스
- python
- docker
- mysql on docker
- C언어
- java
- ansible install
- 정보처리기사
- streamsets 강의
- 도커 elk
- 도커
- 스트림셋이란?
- 스트림셋
- c++
- 앤서블 설치
- 알고리즘
- 도커 시작하기
- mysql docker
- 백준
- 코딩
- 도커 mysql
- elk stack
- nvidia docker
- 파이썬
- Today
- Total
리그캣의 개발놀이터
롯데 스펙태클 프로그래밍 직무 시험. 본문
Programming_곽승혁(940128)
상황분석 (주제1)
글로벌 기업은 협업을 위한 메신저의 활용을 중요시 그로 인하여 롯데 그룹은 메시징을 통한 협업 및 커뮤니티 플랫폼 구축
롯데그룹 및 파트너사의 이메일과 도메인을 자동으로 묶이게 하는 시스템
업무용 자동응답 챗봇 및 사용자 간 대화가 가능한 멀티 협업 환경 지원
문제 정의
여러 사람이 이용할 수 있는 커뮤니케이션 포탈 제작 - (챗봇 먼저 구현 후 추후 개발)
보안 인증을 통한 사용자 등록과 관리 - (django user auth form 사용하도록)
단순 반복적 행정 처리 - (챗봇 시스템 구현 가능 - POLLING 기능으로 메시지를 통한 명령어 처리)
모바일 PC 환경에서 모두 사용 가능토록 구현 - (모바일, PC 환경에서 이미 구축되어 있는 플랫폼 이용)
왜 챗봇 인가?
나의 가장 많이 구현 했던 프로젝트 챗봇 나의 강점
일정 관리 봇
알림 기능
내용
출근 후 10:00 그날 일정을 알림
각 일정 10분 전에 알림
일정 추가나 삭제될 시 해당 채팅방에 알림
18:00 퇴근 30분 전에 내일 일정 자동 출력
구현 방법
해당 구글 캘린더와 SLACK 자체를 연동하여 Push 알람을 받게끔 설정. 체크박스로 얼마든지 쉽게 구현슬랙 봇이 폴링 기법을 사용하여 시간을 지속해서 체크 그 후 지정한 시간이 되었을 때 내일 일정
명령어 호출출력
이슈
해당 명령어를 호출할 때 채널의 이름이 필요하여 소스 안에서 해당 채널로 변경해 주어야 함
일정 안내
내용
모든 일정 확인 (일정-모두)
당일 일정 확인 (일정-오늘)
내일 일정 확인 (일정-내일)
구현 방법
해당 명령어를 챗봇이 인식하고 각 명령어에 따라 해당하는 명령어를 unionCalendar.py에서 호출
이슈
함수 지향적으로 프로그램을 구현하기 번거로웠지만, 막상 구현하니 유지보수가 간단하다고 생각
일정 추가
내용
새로운 일정 추가 [일정-추가 (-D|-d) 날짜 (-T|-t) 시작:시간~끝나는:시간 (-S:-s) 일정제목]
구현방법
해당 명령어를 챗봇이 인식하고 각 명령어에 따라 해당하는 명령어를 unionCalendar.py에서 호출
날짜, 시작시각, 끝나는 시간은 일정한 포맷에 맞추어야 하므로 포맷을 맞추어주는 함수 따로 구현
정규식을 사용하여 구현하여서 중간에 띄어쓰기나 대소문자가 바뀌어도 상관없음
명령어 순서는 일치하여야 하며 하나라도 빠뜨릴 시 실행 안 되게 구현
이슈
일정을 추가할 때 참여자의 이메일이 필요하므로 소스 안에 미리 각자의 이메일 기재 필요
인턴 일정이 한 달 정도 제한, 날짜 기재 만이 오히려 효율적일 것으로 예상하여 月 기재는 없앰
일정 삭제
내용
기존 일정 삭제 [일정-삭제 (-D|-d) 날짜 (-S:-s) 일정제목]
구현방법
해당 명령어를 챗봇이 인식하고 각 명령어에 따라 해당하는 명령어를 unionCalendar.py에서 호출
일정에 해당하는 Id를 갖고 있어야 해당 일정을 지울 수 있어. 일정 제목으로 해당 id를 뽑아내는 함수를 따로 구현
정규식을 사용하여 구현 하여서 중간에 띄어쓰기나 대소문자가 바뀌어도 상관 없음
해당 날짜에 해당하는 제목의 일정이 없으면 구현이 안되게 개발
명령어 순서는 일치하여야 하며 하나라도 빠뜨릴 시 실행안되게 구현
이슈
같은 날 같은 제목의 일정이 있으면 for문을 돌리기 때문에 맨 마지막 일정 하나만 없어짐
추 후에 시간과 같이 지정해서 제거를 시키던지, 한꺼번에 여러개의 일정을 제거할 수 있는 명령어 구현 필요하다 생각함
시스템 구성도
소스코드
게시판
Django 프레임워크를 사용. 소스코드는 .zip로 제출하겠습니다.
챗봇
dailybot.py
# -*- coding: utf-8 -*- import calendarunion import os import time import datetime import json import urllib from slackclient import SlackClient from slacker import Slacker import re # starterbot's ID as an environment variable #BOT_ID = os.environ.get("BOT_ID") BOT_ID = "U89P3Q9T3" # constants AT_BOT = "<@" + BOT_ID + ">" EXAMPLE_COMMAND = u"일정-도와줘" EXAMPLE_COMMAND1 = u"안녕" LIST_ALL = u"일정-모두" LIST_TOMORROW = u"일정-내일" LIST_TODAY = u"일정-오늘" INSERT_EVENT = u"일정-추가" DELETE_EVENT = u"일정-삭제" BL = True; # instantiate Slack & Twilio clients #slack = Slacker(os.environ.get('SLACK_BOT_TOKEN')) #slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN')) slack = Slacker("xoxb-281785825921-Cvg6DimfiXwQJgnGf1vPao9r") slack_client = SlackClient("xoxb-281785825921-Cvg6DimfiXwQJgnGf1vPao9r") def post_to_channel(message, channel): slack.chat.post_message(channel, message, as_user=True) def parse_slack(msg): output_list = msg if output_list and len(output_list) > 0: for output in output_list: if output and 'text' in output and BOT_ID not in output: channel = output['channel'] command = output['text'] # Get text in JSON answer = slack_answer(command, channel) # Go to desk if answer : post_to_channel(answer, channel) return None def calendar_report(): now = datetime.datetime.now() hour = now.hour min = now.minute sec = now.second; global BL if hour == 17 and min == 55 and BL: payload = {"text": "내일 일정확인해볼래?"} url = "https://hooks.slack.com/services/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" req = urllib2.Request(url) req.add_header('Content-Type', 'application/json') urllib2.urlopen(req, json.dumps(payload)) BL = False if hour == 18 and min == 00: BL = True return None def slack_answer(txt, channel): if txt == EXAMPLE_COMMAND1: answer = "안녕? 나는 일정봇이야. 명령어를 입력해줘! 명령어를 모른다면 '일정-도와줘'를 검색해봐:)" elif txt == EXAMPLE_COMMAND: answer = "자 한번 사용해보자" calendarunion.help_command(channel) elif txt.find(LIST_ALL) != -1: answer = "검색이 모두 완료되었어:smile:" calendarunion.get_AllList(channel) elif txt.find(LIST_TOMORROW) != -1: answer = "미리 준비하자>__<" calendarunion.get_TomorrowList(channel) elif txt.find(LIST_TODAY) != -1: answer = "오늘 하루도 힘내^__^" calendarunion.get_TodayList(channel) elif txt.find(INSERT_EVENT) != -1: cmd = re.compile(r"((^\S+)+\s*(-D|-d)+\s*(\d{2})+\s*(-T|-t)+\s*((\d+):(\d+))(-|~)((\d+):(\d+))+\s*(-S|-s)+\s*(\D+))") if re.match(cmd,txt) is not None: answer = "*★*일정 추가 완료*★*:smile:" matchobj = cmd.search(txt) E_Day=matchobj.group(4) s_Time=matchobj.group(6) e_Time=matchobj.group(10) event_Name = matchobj.group(14) s_dateTime = calendarunion.convert(E_Day, s_Time) e_dateTime = calendarunion.convert(E_Day, e_Time) calendarunion.insert_Event(event_Name, s_dateTime, e_dateTime, channel) else: answer = "정확하게 입력바랍니다.ex)일정추가 날짜 00:00~00:00 일정제목" return None elif txt.find(DELETE_EVENT) != -1: cmd = re.compile(r"((^\S+)+\s*(-D|-d)+\s*(\d{2})+\s*(-S|-s)+\s*(\D+))") if re.match(cmd, txt) is not None: answer = "*☆*일정 제거 완료*☆*:smile:" matchobj = cmd.search(txt) D_Day=matchobj.group(4) E_Summary=matchobj.group(6) Event_Id=calendarunion.get_EventID(D_Day,E_Summary,channel) print(Event_Id) if Event_Id=='error': return None calendarunion.delete_Event(Event_Id,channel) else: answer = "정확하게 입력바랍니다.ex)일정제거 날짜 일정제목" return None #payload = {"text": "내일일정 알림!!!"} #url = "https://hooks.slack.com/services/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" #req = urllib2.Request(url) #req.add_header('Content-Type', 'application/json') #urllib2.urlopen(req, json.dumps(payload)) #return None else: return None return answer if __name__ == "__main__": if slack_client.rtm_connect(): print("Connected!") while True: calendar_report() parse_slack(slack_client.rtm_read()) time.sleep(1) else: print("Connection failed.") |
calendarunion.py
# -*- coding: utf-8 -*- from __future__ import print_function import httplib2 import os from slackclient import SlackClient from apiclient import discovery from oauth2client import client from oauth2client import tools from oauth2client import file from httplib2 import Http from oauth2client.file import Storage from slacker import Slacker import datetime #library??? #slack = Slacker(os.environ.get('SLACK_BOT_TOKEN')) slack = Slacker("xoxb-281785825921-Cvg6DimfiXwQJgnGf1vPao9r") def post_to_channel(message, channel): slack.chat.post_message(channel, message, as_user=True) try: import argparse flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args() except ImportError: flags = None SCOPES = 'https://www.googleapis.com/auth/calendar'#, 'https://www.googleapis.com/auth/calendar.readonly', 'https://www.googleapis.com/auth/plus.login' CLIENT_SECRET_FILE = 'client_secret.json' APPLICATION_NAME = 'Google Calendar API Python Quickstart' CA_NAME='skuniv.ac.kr_86in1lo83oq31vht666aotr7kk@group.calendar.google.com'#our calendar EMAIL = 'league3236@skuniv.ac.kr','subeen2150@skuniv.ac.kr','shs4161@skuniv.ac.kr','jebigbang18@skuniv.ac.kr','mynadahun@skuniv.ac.kr','sports1014@skuniv.ac.kr','twinpapa2003@skuniv.ac.kr' def get_credentials(): """Gets valid user credentials from storage. If nothing has been stored, or if the stored credentials are invalid, the OAuth2 flow is completed to obtain the new credentials. Returns: Credentials, the obtained credential. """ home_dir = os.path.expanduser('~') credential_dir = os.path.join(home_dir, '.credentials') if not os.path.exists(credential_dir): os.makedirs(credential_dir) credential_path = os.path.join(credential_dir, 'calendar-python-quickstart.json') store = Storage(credential_path) credentials = store.get() if not credentials or credentials.invalid: flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES) flow.user_agent = APPLICATION_NAME if flags: credentials = tools.run_flow(flow, store, flags) else: # Needed only for compatibility with Python 2.6 credentials = tools.run(flow, store) answer='Storing credentials to ' + credential_path return credentials def get_AllList(channel): """Shows basic usage of the Google Calendar API. Creates a Google Calendar API service object and outputs a list of the next 10 events on the user's calendar. """ credentials = get_credentials() http = credentials.authorize(httplib2.Http()) service = discovery.build('calendar', 'v3', http=http) now1 = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time #print('Getting the upcoming 10 events') eventsResult = service.events().list( calendarId=CA_NAME, timeMin=now1, maxResults=10, singleEvents=True, orderBy='startTime').execute() events = eventsResult.get('items', []) #now1 = datetime.datetime.now() answer=u'날짜 시간 제목\n' #nowDate = now.strftime('%Y-%m-%d') #print(nowDate) # 2015-04-19 if not events: answer = u'모든 일정이 비었어:( \n일정추가 명령어로 일정을 등록해보는건 어때?' attachments = [ { "text": answer, "fallback": "ALL daily", "callback_id": "ALL_daily", "color": "#f44182", "attachment_type": "default", } ] for event in events: start = event['start'].get('dateTime', event['start'].get('date')) answer=answer+start.split('+')[0].split('T')[0]+u' '+start.split('+')[0].split('T')[1].split(':')[0]+(':')+start.split(':')[1]+u' '+event['summary']+u"\n" attachments = [ { "text": answer, "fallback": "You are unable to choose a game", "callback_id": "wopr_game", "color": "#f4eb41", "attachment_type": "default", } ] slack.chat.post_message(channel, attachments=attachments, as_user=True) return None def get_TodayList(channel): """Shows basic usage of the Google Calendar API. Creates a Google Calendar API service object and outputs a list of the next 10 events on the user's calendar. """ credentials = get_credentials() http = credentials.authorize(httplib2.Http()) service = discovery.build('calendar', 'v3', http=http) now1 = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time #print('Getting the upcoming 10 events') eventsResult = service.events().list( calendarId=CA_NAME, timeMin=now1, maxResults=10, singleEvents=True, orderBy='startTime').execute() events = eventsResult.get('items', []) now=datetime.datetime.now() nowDate = now.strftime('%Y-%m-%d') answer =u"오늘 일정이야\n" post_to_channel(answer,channel) answer=u'시간 제목\n' if not events: answer = u'오늘 일정이 비었어:( \n일정추가 명령어로 일정을 등록해보는건 어때?' post_to_channel(answer, channel) return None for event in events: start = event['start'].get('dateTime') end = event['end'].get('dateTime') today = start.split('T')[0] if today == nowDate: answer = answer + start.split('+')[0].split('T')[1].split(':')[0]+(':')+start.split(':')[1]+"~"+end.split('+')[0].split('T')[1].split(':')[0]+(':')+start.split(':')[1]+u" "+event['summary']+u"\n" attachments = [ { "text": answer, "fallback": "Today daily", "callback_id": "Today_daily", "color": "#3AA3E3", "attachment_type": "default", } ] slack.chat.post_message(channel, attachments=attachments, as_user=True) #post_to_channel(answer,channel) #print(event['id']) return None def get_TomorrowList(channel): """Shows basic usage of the Google Calendar API. Creates a Google Calendar API service object and outputs a list of the next 10 events on the user's calendar. """ credentials = get_credentials() http = credentials.authorize(httplib2.Http()) service = discovery.build('calendar', 'v3', http=http) now1 = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time # print('Getting the upcoming 10 events') eventsResult = service.events().list( calendarId=CA_NAME, timeMin=now1, maxResults=10, singleEvents=True, orderBy='startTime').execute() events = eventsResult.get('items', []) now = datetime.datetime.now() tomorrowDate = str(now + datetime.timedelta(days=1)).split(' ')[0] answer = u"내일 일정이야\n" post_to_channel(answer, channel) answer = u'시간 제목\n' if not events: answer = u'내일 일정이 비었어:( \n일정추가 명령어로 일정을 등록해보는건 어때?' post_to_channel(answer, channel) return None for event in events: start = event['start'].get('dateTime') end = event['end'].get('dateTime') tomorrow = start.split('T')[0] if tomorrow == tomorrowDate: answer = answer + start.split('+')[0].split('T')[1].split(':')[0] + (':') + start.split(':')[1] + "~" + \ end.split('+')[0].split('T')[1].split(':')[0] + (':') + start.split(':')[1] + u" " + event[ 'summary'] + u"\n" attachments = [ { "text": answer, "fallback": "Tomorrow_List", "callback_id": "Tomorrow_List", "color": "#9541f4", "attachment_type": "default", } ] slack.chat.post_message(channel, attachments=attachments, as_user=True) return None def insert_Event(EventName,StartTime,EndTime,channel): store = file.Storage('storage.json') creds = store.get() if not creds or creds.invalid: flow = client.flow_from_clientsecrets('client_secret.json', SCOPES) creds = tools.run_flow(flow, store) GCAL = discovery.build('calendar', 'v3', http=creds.authorize(Http())) GMT_OFF = '+09:00' # PDT/MST/GMT-7 EVENT = { 'summary': EventName, 'start': {'dateTime': StartTime+'%s' % GMT_OFF},#2017-07-12T14:00:00 'end': {'dateTime': EndTime+'%s' % GMT_OFF},#2017-07-12T14:30:00 'attendees': [ {'email': EMAIL[0]}, {'email': EMAIL[1]}, {'email': EMAIL[2]}, {'email': EMAIL[3]}, {'email': EMAIL[4]}, {'email': EMAIL[5]}, {'email': EMAIL[6]}, ], } e = GCAL.events().insert(calendarId=CA_NAME, sendNotifications=True, body=EVENT).execute() answer=u'''*** *[%s]* 일정을 추가중입니다 --- •시작시간: %s •끝나는시간: %s''' % (e['summary'], e['start']['dateTime'].split('T')[0] + " " + e['start']['dateTime'].split('+')[0].split('T')[1].split(':')[0]+(':')+e['start']['dateTime'].split(':')[1], e['end']['dateTime'].split('T')[0] + " " + e['end']['dateTime'].split('+')[0].split('T')[1].split(':')[0]+(':')+e['start']['dateTime'].split(':')[1]) post_to_channel(answer, channel) return 0 #print('DAY:'+start.split('+')[0].split('T')[0],'Time:'+start.split('+')[0].split('T')[1].split(':')[0]+(':')+start.split(':')[1],'Summary:'+event['summary']) def convert(date,time): now = datetime.datetime.now() result = now.strftime('%Y-%m-') + date + 'T' + time + ':00' return result def delete_Event(Event_Id,channel): credentials = get_credentials() http = credentials.authorize(httplib2.Http()) service = discovery.build('calendar', 'v3', http=http) now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time #print('Getting the upcoming 10 events') eventsResult = service.events().list( calendarId=CA_NAME, timeMin=now, maxResults=10, singleEvents=True, orderBy='startTime').execute() events = eventsResult.get('items', []) answer=u'***일정 제거중***' post_to_channel(answer, channel) service.events().delete(calendarId=CA_NAME, eventId=Event_Id).execute() return 0 def get_EventID(D_Day,E_Summary,channel): credentials = get_credentials() http = credentials.authorize(httplib2.Http()) service = discovery.build('calendar', 'v3', http=http) now1 = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time # print('Getting the upcoming 10 events') eventsResult = service.events().list( calendarId=CA_NAME, timeMin=now1, maxResults=10, singleEvents=True, orderBy='startTime').execute() events = eventsResult.get('items', []) now = datetime.datetime.now() WhatDate = now.strftime('%Y-%m-'+D_Day) for event in events: start = event['start'].get('dateTime') today = start.split('T')[0] if ((today == WhatDate) and (event['summary']==E_Summary)): event_id = event['id'] return event_id return 'error' def help_command(channel): answer = "*도움말*:smile:\n*명령어*\n\t일정-도와줘\t일정봇의 명령어들을 볼 수 있습니다.\n\t일정-모두\t모든 일정을 확인할 수 있습니다.\n\t일정-오늘\t오늘 일정을 확인할 수 있습니다.\n\t일정-내일\t내일 일정을 확인할 수 있습니다.\n\t일정-추가\t일정을 추가할 수 있습니다.\n\t\t[일정-추가 (-D|-d) 날짜 (-T|-t) 시작:시간~끝나는:시간 (-S:-s)일정제목]\n\t\t일정-추가 -d 18 -t 12:00~13:00 -S 점심시간\n\t일정-삭제\t\t일정을 삭제 할 수 있습니다.\n\t\t[일정-삭제 (-D|-d) 날짜 (-S:-s)일정제목]\n\t\t일정-삭제 -d 18 -S 점심시간" attachments = [ { "text": answer, "fallback": "Help_Command", "callback_id": "Help_Command", "color": "#42f459", "attachment_type": "default", } ] slack.chat.post_message(channel, attachments=attachments, as_user=True) return None def main(): print('실행되는중') #command("event all") #get_AllList(channel) #command("event today") #get_TodayList() #command("Tomorrow") #get_TomorrowList() #insert #command("insert 15 13:00-14:00 summary") #((^\D+)\s(\d+)\s((\d+):(\d+))(-|~)((\d+):(\d+))\s(\D+)) #E_Day='14' #s_Time='13:00' #e_Time='14:00' #event_Name = 'test' #s_dateTime = convert(E_Day,s_Time) #e_dateTime = convert(E_Day,e_Time) #insert_Event(event_Name,s_dateTime,e_dateTime,channel) #combine start delete #command(ex:delete 12 melong) (day"(\d[+2])")(summary"(^\D+)\s+(\d+2)\s+(\D+)"3GROUP USE) #D_Day='12' #E_Summary='melong' #Event_Id=get_EventID(D_Day,E_Summary) #delete_Event(Event_Id) if __name__ == '__main__': main() |
화면 캡처
'팀 활동 > 프로젝트' 카테고리의 다른 글
축구 매칭 웹 페이지 만들기 - 엔티티 표 (0) | 2018.01.25 |
---|---|
축구 매칭 웹 페이지 만들기 - NEEDS 조사 (0) | 2018.01.25 |
아두이노로 만드는 리듬게임. (2) | 2018.01.23 |
XML을 이용한 개인 시간표 게시판 (0) | 2018.01.22 |
c언어 러쉬아워(RushHour) 텀 프로젝트 최종보고서 2 (0) | 2018.01.21 |