qqbot聊天機器人-會議室的預(yù)訂

github:
https://github.com/cuihee/qqbot-meeting
可能有代碼少許不一樣
xl.py
from meeting_tools import *
# ==========================注意=============================
watch_group_name = ["0.0", 'SIPPR 智能與信息12樓', '智能與信息工程中心']
excel_file_name = "testMeeting.xlsx" # 新建的sheet第一天不太對,但是不影響使用
cmd_list = ['效率助手下載地址', '查詢今天會議室預(yù)訂情況', '查詢明天會議室預(yù)訂情況', 'help', # 0 1 2 3
'順豐的聯(lián)系方式', 'stop', 'watch_group_name']
# 關(guān)鍵詞和觸發(fā)的行為
cmd_dic = {
'效率助手下載地址': '',
'查詢今天會議室預(yù)訂情況': '',
'查詢明天會議室預(yù)訂情況': '',
'help': '',
'順豐的聯(lián)系方式': '',
'stop': '',
'watch_group_name': ''
}
def onQQMessage(bot, contact, member, content):
# 避免機器人自嗨 機器人發(fā)言請注意加上這個字符串
if '機器人回復(fù)' in content:
return
# 監(jiān)視制定的群
if not my_watch_group(contact=contact, group_name=watch_group_name):
return
# todo 用dic替換list
for k, v in cmd_dic.items():
if k in content:
if isinstance(cmd_dic[k], type(func())):
# 是函數(shù) 就執(zhí)行函數(shù)
pass
else:
# 不是函數(shù) 直接輸出
pass
# return
if cmd_list[0] in content:
bot.SendTo(contact, "機器人回復(fù) eepm.sippr.cn ")
return
if cmd_list[1] in content:
report_info = ask_info(excel_file_name, (datetime.date.today() + datetime.timedelta(days=0)).__str__())
bot.SendTo(contact, '機器人回復(fù) \n'+'\n'.join(report_info))
return # 避免對查詢語句進行預(yù)定會議室
if cmd_list[2] in content:
report_info = ask_info(excel_file_name, (datetime.date.today()+datetime.timedelta(days=1)).__str__())
bot.SendTo(contact, '機器人回復(fù) \n'+'\n'.join(report_info))
return # 避免對查詢語句進行預(yù)定會議室
if '[@ME]' in content and cmd_list[3] in content:
bot.SendTo(contact, '機器人回復(fù) 下列引號內(nèi)的命令采用精確匹配。' + cmd_list.__str__())
return
if cmd_list[4] in content:
bot.SendTo(contact, '機器人回復(fù) 順豐 15936240735')
return
if '[@ME]' in content and cmd_list[5] in content:
bot.SendTo(contact, '機器人回復(fù) 已停止')
# bot.Stop()
bot.Unplug('xl')
return
if '[@ME]' in content[:5]:
bot.SendTo(contact, "機器人回復(fù) 只要你at我,我就回復(fù)這一句\n用來查看插件是否啟用中")
return
if cmd_list[6] in content:
bot.SendTo(contact, "機器人回復(fù) "+watch_group_name.__str__())
return
dialog = dialog_clearify(content)
dialog = is_cmd(dialog)
if len(dialog) < 1:
print("不是預(yù)定會議室的語句")
return
else:
yuding_info = member.name + ' 群"' + contact.nick + '" ' + datetime.datetime.today().__str__()[:-7] \
+ ' '
book_ornot = find_yuding(dialog) # True False
riqi = find_riqi(dialog) # 2018-03-13
# print("獲取日期:", riqi)
start_time, end_time = find_shijian(dialog) # 8:00, 9:15
# print("獲取時間:", start_time, end_time)
fangjian = find_fangjian(dialog) # 12樓小會議室
# print("獲取房間名:", get_meetingrooms_names()[fangjian])
yuding_info = yuding_info + riqi + ' '
yuding_info = yuding_info + get_meetingrooms_names()[fangjian] + ' '
yuding_info = yuding_info + start_time + '-' + end_time + ' '
print(yuding_info)
# 表格文件對象
excel_file = get_excel_file(filename=excel_file_name)
# print("獲取文件:", excel_file)
excel_sheet = get_excel_sheet(riqi=riqi, file=excel_file)
# print("獲取sheet:", excel_sheet)
column0 = 2 # 第一列是時間 從第二列開始是會議室編號 12層小會議室0 12層大會議室1 13層會議室2
excel_column = fangjian + column0
# print("獲取列:", excel_column)
excel_date_row = get_excel_row(sheet=excel_sheet, today=riqi) # 下一行是8:00:00
# print("獲取行:", excel_date_row)
delta_row_start, delta_row_end = get_dtime(start_time, end_time)
# print("獲取行區(qū)段:", excel_date_row+delta_row_start, excel_date_row+delta_row_end)
# ==============================================注意=======================================================
# 不管從哪個群里獲取的預(yù)訂信息都反饋到0.0群里面?。。。。。。。。。。。。。。?!
bl = bot.List('group', '0.0')
b = None
if bl:
b = bl[0]
# bot.SendTo(b, 'test')
deal_book(sheet=excel_sheet, start=excel_date_row + delta_row_start,
end=excel_date_row + delta_row_end, column=excel_column,
info=yuding_info, book=book_ornot, bot=bot, contact=b, # 注意這里的 contact !!!!!!!!!!!!!!!!!!!!!
member=member)
# 存儲表格文件
excel_file.save(filename=excel_file_name)
print("\n")
def onPlug(bot):
s = bot.Plugins()
if 'xl_sitter' in s:
pass
else:
bot.Plug('xl_sitter')
def func():
pass
meeting_tools.py
"""
這個文件應(yīng)該放在全局可以import的位置供xl.py調(diào)用
比如說現(xiàn)在我的D:/anaconda/Lib
(xl.py按照要求放在了C:/Users/c2534/.qqbot-tmp/plugins)
有時候(腳本運行后修改這個文件)這個文件會不起作用,手動重啟qqbot用命令 qq fresh-restart掃碼
"""
import datetime
from openpyxl import load_workbook, Workbook
import os
import re
# todo 規(guī)范一下好
def botreply(bot, contact, member, s):
# if '機器人回復(fù)' 開頭:
# return
# 判斷contact還是member
# bot.SendTo(contact, "機器人回復(fù) \n"+s)
pass
def ask_info(file, dates):
info = ['無記錄']
# 打開這個文件
f = get_excel_file(file)
# 用dates[:7]找sheet
fsheet = get_excel_sheet(dates, f)
# 用dates找row
frow = -1
for i in range(1, fsheet.max_row+1):
if fsheet.cell(row=i, column=1).value == dates:
frow = i
break
if frow == -1:
return info
# 默認deltarow為
deltafrow = 52 # 8:00-20:45=12*4+4=52
for i in range(2, fsheet.max_column+1): # 列
for j in range(1+frow, deltafrow+1+frow): # 行
if fsheet.cell(row=j, column=i).value is None:
continue
if fsheet.cell(row=j, column=i).value not in info:
info.append(str(fsheet.cell(row=j, column=i).value))
# 關(guān)閉文件
f.close()
if len(info) > 1:
info[:] = info[1:] # 刪除第一個元素
return info
def my_watch_group(contact, group_name):
return contact.nick in group_name
# todo 考慮使用redis json存儲規(guī)則
# 但因為是py腳本運行 隨時可以修改代碼 需求不強烈
def dialog_clearify(content):
"""
這里面的順序不要亂
:param content:
:return:
"""
d = content
if not isinstance(d, type("字符串類型")):
return ""
clearify_dict = {'~~~': '-', "~~": "-", ' ': ' ',
'~~': '-', '~': '-', '---': '-',
'--': '-', '——': '-', ':': ':',
'~': '-',
'全天': '8:30-18:00',
'12樓': '12層', '13樓': '13層', '十三樓': '13層', '十二樓': '12層',
'今日': '今天', '明日': '明天',
'合昌': '和昌', '合唱': '和昌', '和唱': '和昌',
'點半': ':30', '點30': ':30', '點三十': ':30',
'點': ':00',
'十一': '11', '十二': '12', '十三': '13',
'十四': '14', '十五': '15', '十六': '16',
'十七': '17', '十八': '18', '十九': '19',
'二十': '20', '十': '10',
'九': '9', '八': '8', '七': '7',
'六': '6', '五': '5', '四': '4',
'三': '3', '二': '2', '一': '1',
'下午8:': '20:',
'預(yù)訂': '預(yù)定',
'到': '-',
'(': '(', ')': ')',
',': '.', ',': '.', '。': '.'
}
for (k, v) in clearify_dict.items():
d = d.replace(k, v)
# 5:30-6:00 轉(zhuǎn)換成 17:30-18:00
r1 = re.findall(r'([^0-9:-]?)([1-7])(:[0-9]{2,3}-)([2-8])(:[0-9]{2,3})', d)
if len(r1) >= 1:
d = re.subn(r'([^0-9:-]?)([1-7])(:[0-9]{2,3}-)([2-8])(:[0-9]{2,3})',
r1[0][0] + str(int(r1[0][1]) + 12) + r1[0][2] + str(int(r1[0][3]) + 12) + r1[0][4],
d)[0]
r1 = re.findall(r'([^0-9:])([0-9]{1,3})(-[0-9]{1,3}:[0-9]{2,3})', d)
if len(r1) >= 1:
d = re.subn(r'([^0-9:])([0-9]{1,3})(-[0-9]{1,3}:[0-9]{2,3})', r1[0][0] + r1[0][1] + ':00' + r1[0][2], d)[0]
return d
def is_cmd(dialog):
if not isinstance(dialog, type("")):
return ''
if "會議室" in dialog:
if "預(yù)" in dialog or "訂" in dialog or "定" in dialog:
return dialog
return ''
def get_meetingrooms_names():
return ['小會議室', '大會議室', '13層會議室', '【會議室名稱不詳】無法正確記錄']
def find_fangjian(dialog):
"""
用正則表達式從dialog中取出定義好的會議室名稱
http://www.runoob.com/regexp/regexp-metachar.html
正則表達式教程↑
:param dialog: 傳入的字符串
:return: 傳出會議室序號
"""
huiyishi = get_meetingrooms_names()
meeting_room = '12層大會議室'
r1 = re.findall(r'([1][23]層)', dialog)
r2 = re.findall(r'([大小]?會議室)', dialog)
if r1.__len__() > 0:
if r1[0] == '13層': # 當(dāng)前情況下13層只有一個會議室2
return 2
meeting_room = r1[0] + meeting_room[3:]
if r2.__len__() > 0:
meeting_room = meeting_room[:3] + r2[0]
for i in range(len(huiyishi)):
if meeting_room.find(huiyishi[i]) > -1:
return i # 0 1 2
return len(huiyishi)-1 # 3
def find_shijian(dialog):
st = '8:30'
et = '18:00'
r1 = re.findall(r'([0-9]?[0-9])[:點:]([0-5][0-9])', dialog)
if r1.__len__() >= 1: # 至少有一個時間
st = r1[0][0] + ':' + shijian_fenzhong_round(r1[0][1])
if r1.__len__() >= 2: # 有兩個時間
et = shijian_round2(r1[1][0] + ':' + r1[1][1])
if r1.__len__() <= 0:
if dialog.find('上午') > -1:
st, et = '8:30', '12:00'
if dialog.find('下午') > -1:
st, et = '14:00', '18:00'
# 安全檢查是否在早8:00-20:30之間
if int(st[:st.find(':')]) < 8:
st = '8' + st[st.find(':'):]
if int(st[:st.find(':')]) > 20:
st = '20' + st[st.find(':'):]
if int(et[:et.find(':')]) < 8:
et = '8' + et[et.find(':'):]
if int(et[:et.find(':')]) > 20:
et = '20' + et[et.find(':'):]
return st, et
def shijian_fenzhong_round(s):
if int(s) < 15:
return '00'
if int(s) < 30:
return '15'
if int(s) < 45:
return '30'
if int(s) < 60:
return '45'
return '45'
def shijian_round2(s):
if int(s[-2:]) > 45:
return str(int(s[:s.find(':')])+1) + ':00'
if int(s[-2:]) > 30:
return s[:s.find(':')] + ':45'
if int(s[-2:]) > 15:
return s[:s.find(':')] + ':30'
if int(s[-2:]) > 0:
return s[:s.find(':')] + ':15'
if int(s[-2:]) == 0:
return s
return s
def find_yuding(dialog):
return not ("取消" in dialog)
def find_riqi(dialog):
"""
:param dialog: 4.2
:return: 2018-04-02
"""
findre = re.findall(r'([12]?[0-9])[月.]([0-3]?[0-9])[日號]?', dialog) # 12月02日 10.3
if len(findre) == 1:
if len(findre[0][0]) == 1:
a = '0' + findre[0][0]
else:
a = findre[0][0]
if len(findre[0][1]) == 1:
b = '0' + findre[0][1]
else:
b = findre[0][1]
return datetime.date.today().__str__()[:5] + a + '-' + b # 2018-12-02
findre = re.findall(r'([0-3]?[0-9])[日號]', dialog) # 2號
if len(findre) == 1:
if len(findre[0]) == 1:
a = '0' + findre[0]
else:
a = findre[0]
return datetime.date.today().__str__()[:8] + a # 2018-12-02
if -1 < dialog.find("今"):
return datetime.date.today().__str__()
elif -1 < dialog.find("明"):
return (datetime.date.today() + datetime.timedelta(days=1)).__str__()
elif -1 < dialog.find("后"):
return (datetime.date.today() + datetime.timedelta(days=2)).__str__()
return datetime.date.today().__str__()
def get_excel_row(sheet, today):
"""
:param sheet:
:param today: datetime.date.today().__str__()
:return: row of today 只有日期沒時間的那一行
"""
find_ornot = False
find_row = 0
for i in range(1, sheet.max_row+1):
if sheet.cell(row=i, column=1).value == today:
find_ornot = True
find_row = i
break
if find_ornot:
writetime(sheet=sheet, startrow=find_row + 1)
return find_row
else:
find_row = sheet.max_row + 1
sheet.cell(row=find_row, column=1).value = today
writetime(sheet=sheet, startrow=find_row + 1)
return find_row
def writetime(sheet, startrow):
"""
不包括today信息的一天時間
:param sheet:
:param startrow:
:return:
"""
m = ["00", "15", "30", "45"]
h = [i.__str__() for i in range(8, 21, 1)]
crow = startrow
for _h in h:
for _m in m:
sheet.cell(row=crow, column=1).value = _h + ":" + _m + ":00"
crow = crow + 1
def get_dtime(st, et):
"""
todo 感覺可以寫成一個函數(shù)
計算所給時間段距離8:00的格子數(shù) 默認15min
請注意8:00是第一個格子
:param st: 時間 8:00
:param et: 時間 9:30
:return: 起始時間所在行是當(dāng)天日期所在行+ds
"""
a = int(st[:st.find(":")])
b = int(st[st.find(":") + 1:])
c = int(et[:et.find(":")])
d = int(et[et.find(":") + 1:])
ds = (a - 8) * 4 + b // 15 + 1
de = (c - 8) * 4 + d // 15 + 1
return ds, de
def get_excel_file(filename):
"""
:param filename: 文件名帶后綴的
:return: 打開指定文件名的文件對象
"""
# 得到當(dāng)前系統(tǒng)目錄下的文件名列表
dir_files = os.listdir(os.getcwd())
# 當(dāng)前路徑下有filename文件
if filename in dir_files:
wb = load_workbook(filename)
else:
wb = Workbook()
wb.save(filename)
wb = load_workbook(filename)
return wb
def get_excel_sheet(riqi, file):
sheetnames = file.get_sheet_names() # 所有表名
month_name = riqi[:7] # 目標表名
if month_name in sheetnames: # 存在
return file.get_sheet_by_name(name=month_name)
else:
return create_sheet(month_name, file)
def create_sheet(sheetname, file):
"""
:param sheetname: string
:param file: excel文件對象
:return: sheet對象
"""
# 如果excel文件中有這個名字的sheet 就直接返回這個sheet對象
if sheetname in file.get_sheet_names():
return file.get_sheet_by_name(sheetname)
# 在excel文件中新建一個名為sheetname的sheet
file.create_sheet(sheetname)
sheet = file.get_sheet_by_name(sheetname)
# 左上角 A1 寫入今天的日期
sheet.cell(row=1, column=1).value = datetime.date.today().__str__() # [:8]+"01"
# 寫時間
writetime(sheet=sheet, startrow=2)
# 寫會議室名字
meeting_roomnames = get_meetingrooms_names()
# for (i, n) in meeting_roomnames:
# sheet.cell(row=1, column=i).value = n
for i in range(len(meeting_roomnames)):
sheet.cell(row=1, column=i+2).value = meeting_roomnames[i]
return sheet
def deal_book(sheet, start, end, column, info, book, bot, contact, member):
if book:
# 預(yù)定命令
occupied, occupied_info = is_occupied(sheet, start, end, column) # 是否被占用 占用信息
if occupied:
# 如果占用
bot.SendTo(contact, "機器人回復(fù) 失敗,因為\"" + occupied_info + "\"占用")
# print("您預(yù)定失敗,因為\"" + occupied_info + "\"占用")
else:
# 沒有占用
occupy_it(sheet, start, end, column, info)
bot.SendTo(contact, "機器人回復(fù) 成功\n"+" 記錄的信息: "+member.name+" "+info[-32:])
# print("成功預(yù)定")
else:
# 取消預(yù)定
unoccupy_it(sheet, start, end, column)
bot.SendTo(contact, '機器人回復(fù) '+str(info[:info.find(' 群"')]) + "取消成功")
# print("取消預(yù)定")
print('\n')
def is_occupied(sheet, start, end, column):
busy = False # 假設(shè)沒占用
busy_info = ""
for i in range(start, end, 1):
if sheet.cell(row=i, column=column).value is not None:
busy_info = sheet.cell(row=i, column=column).value
busy = True
break
return busy, busy_info
def occupy_it(sheet, st, en, co, info="占用人信息"):
for i in range(st, en, 1):
sheet.cell(column=co, row=i).value = info
def unoccupy_it(sheet, st, en, co):
for i in range(st, en, 1):
sheet.cell(column=co, row=i).value = None
def excel_file_close(file, name):
file.save(filename=name)
def _test_dialog_clearify():
assert dialog_clearify('預(yù)定4月2日和昌12樓小會議室5:30-6:00') \
== '預(yù)定4月2日和昌12層小會議室17:30-18:00', '對話語句清理函數(shù)dialog_clearify有問題'
assert dialog_clearify('預(yù)定4月2日和昌12樓小會議室2:30-6:00') \
== '預(yù)定4月2日和昌12層小會議室14:30-18:00', '對話語句清理函數(shù)dialog_clearify有問題'
assert dialog_clearify('預(yù)定4月3日和昌12樓大會議室9:00-11:00') \
== '預(yù)定4月3日和昌12層大會議室9:00-11:00', '對話語句清理函數(shù)dialog_clearify有問題'
assert dialog_clearify('預(yù)定4月2日上午和昌12樓小會議室,9:00--11:30') \
== '預(yù)定4月2日上午和昌12層小會議室.9:00-11:30', '對話語句清理函數(shù)dialog_clearify有問題'
assert dialog_clearify('預(yù)定28日(今天)下午12樓大會議室,15:00到16:00') \
== '預(yù)定28日(今天)下午12層大會議室.15:00-16:00', '對話語句清理函數(shù)dialog_clearify有問題'
assert dialog_clearify('預(yù)定今天全天小會議室') \
== '預(yù)定今天8:30-18:00小會議室', '對話語句清理函數(shù)dialog_clearify有問題'
assert dialog_clearify('預(yù)定4月2日和昌13樓大會議室11:00-12:00') \
== '預(yù)定4月2日和昌13層大會議室11:00-12:00', '對話語句清理函數(shù)dialog_clearify有問題'
assert dialog_clearify('預(yù)定27號,下午14點30到17點,和昌12層大會議室') \
== '預(yù)定27號.下午14:30-17:00.和昌12層大會議室', '對話語句清理函數(shù)dialog_clearify有問題'
def _test_find_fangjian():
assert find_fangjian('預(yù)定4月2日和昌12層小會議室17:30-18:00') == 0, '尋找會議室編號函數(shù)find_fangjian有問題'
assert find_fangjian('預(yù)定4月3日和昌12層大會議室9:00-11:00') == 1, '尋找會議室編號函數(shù)find_fangjian有問題'
assert find_fangjian('預(yù)定4月2日和昌13層大會議室11:00-12:00') == 2, '尋找會議室編號函數(shù)find_fangjian有問題'
assert find_fangjian('預(yù)定4月2日和昌13層會議室11:00-12:00') == 2, '尋找會議室編號函數(shù)find_fangjian有問題'
assert find_fangjian('預(yù)定今天8:30-18:00小會議室') == 0, '尋找會議室編號函數(shù)find_fangjian有問題'
assert find_fangjian('預(yù)定今天8:30-18:00老樓會議室') == 3, '尋找會議室編號函數(shù)find_fangjian有問題'
def _test_find_shijian():
assert find_shijian('預(yù)定4月2日和昌12層小會議室17:30-18:00') == ('17:30', '18:00'), '尋找開始和結(jié)束時間函數(shù)find_shijian有問題'
assert find_shijian('預(yù)定4月2日和昌12層小會議室14:30-18:00') == ('14:30', '18:00'), '尋找開始和結(jié)束時間函數(shù)find_shijian有問題'
assert find_shijian('預(yù)定28日(今天)下午12層大會議室.15:00-16:00') == ('15:00', '16:00'), '尋找開始和結(jié)束時間函數(shù)find_shijian有問題'
assert find_shijian('預(yù)定今天8:30-18:00小會議室') == ('8:30', '18:00'), '尋找開始和結(jié)束時間函數(shù)find_shijian有問題'
assert find_shijian('預(yù)定上午大會議室') == ('8:30', '12:00'), '尋找開始和結(jié)束時間函數(shù)find_shijian有問題'
assert find_shijian('訂小會議室 9:10-10:30') == ('9:00', '10:30'), '尋找開始和結(jié)束時間函數(shù)find_shijian有問題'
def _test_find_riqi():
assert find_riqi('預(yù)定4月2日和昌12層小會議室17:30-18:00') == '2018-04-02', '尋找日期函數(shù)find_riqi有問題'
assert find_riqi('預(yù)定今天8:30-18:00小會議室') == datetime.date.today().__str__(), '尋找日期函數(shù)find_riqi有問題'
assert find_riqi('預(yù)定30日下午12樓小會議室.14:00-16:00') == '2018-04-30', '尋找日期函數(shù)find_riqi有問題'
assert find_riqi('預(yù)定27號.下午14:30-17:00.和昌12層大會議室') == '2018-04-27', '尋找日期函數(shù)find_riqi有問題'
assert find_riqi('預(yù)訂12樓大會議室,12點到14點')[:7] == datetime.date.today().__str__()[:7], '尋找日期函數(shù)find_riqi有問題'
if __name__ == '__main__':
_test_dialog_clearify()
_test_find_fangjian()
_test_find_shijian()
_test_find_riqi()
xl_sitter.py
from meeting_tools import *
import time
watch_group_name = ["0.0", '張志琳、劉文、李豪、', 'SIPPR 智能與信息12樓', '智能與信息工程中心']
def onQQMessage(bot, contact, member, content):
# 避免機器人自嗨 機器人發(fā)言請注意加上這個字符串
if '機器人回復(fù)' in content:
return
# 監(jiān)視制定的群
if not my_watch_group(contact=contact, group_name=watch_group_name):
return
if '[@ME]' in content:
if 'start' in content:
bot.Plug('xl')
time.sleep(2)
s = bot.Plugins()
if 'xl' in s:
bot.SendTo(contact, '機器人回復(fù) 插件啟動成功')
else:
bot.SendTo(contact, '機器人回復(fù) 插件啟動失敗')
qqbot聊天機器人-會議室的預(yù)訂的評論 (共 條)
