· 6 years ago · Dec 26, 2019, 10:56 PM
1
2import xlrd #работа с xlsx
3import vk_api #работа с ВК-апи
4import sqlite3 #работа с базой данных
5from vk_api.longpoll import VkLongPoll, VkEventType #работа с ВК-апи
6import pymysql.cursors #работа с базой данных
7import time #работа с временем
8import json #работа с jsoo
9
10path = "kbsp.xlsx" #путь до файла с расписанием
11pathtodb = "users.db" #путь до базы данных
12token = "4958024b92be18be4faa6223e10ca3e119857f1cde0beaea4e63d3e63060dc05bb1c2e1fc61ae32931ecc" #токен VK-api
13
14conn = sqlite3.connect(pathtodb) #подключение к базе данных
15cursor = conn.cursor() #создание объекта управление базой данных
16
17workbook = xlrd.open_workbook(path) #открытие xlsx-файла
18worksheet = workbook.sheet_by_index(0) #создание объекта с данными из файла
19
20
21keyboard = { #создаем таблицу в формате json
22 "one_time": False,
23 "buttons":
24 [
25 [{
26 "action": {
27 "type": "text",
28 "label": "ПН"
29 },
30 "color": "positive"
31 },
32 {
33 "action": {
34 "type": "text",
35 "label": "ВТ"
36 },
37 "color": "positive"
38 },
39
40
41 {
42 "action": {
43 "type": "text",
44 "label": "СР"
45 },
46 "color": "positive"
47 },
48 ],
49 [{
50 "action": {
51 "type": "text",
52 "label": "ЧТ"
53 },
54 "color": "positive"
55 },
56 {
57 "action": {
58 "type": "text",
59 "label": "ПТ"
60 },
61 "color": "positive"
62 },
63
64
65 {
66 "action": {
67 "type": "text",
68 "label": "СБ"
69 },
70 "color": "positive"
71 },
72 ],
73 [
74 {
75 "action": {
76 "type": "text",
77 "label": "СЕГОДНЯ"
78 },
79 "color": "positive"
80 },
81 ],
82 ]
83
84}
85
86keyboard = json.dumps(keyboard, ensure_ascii=False).encode('utf-8')
87keyboard = str(keyboard.decode('utf-8')) #приводим таблицу к нужному формату
88
89
90def selectquery(query): #функция для возращения значений select - запросов
91 cursor.execute(query) #выполнение запроса
92 result = cursor.fetchall()[0][0] #получение данных
93 return result
94
95
96def updatequery(query): #функция для update, insert и прочих запросов, которые обновляют иноформацию
97 cursor.execute(query) #выполнение запроса
98 conn.commit() #обновление базы данных
99
100
101# заменяем все символы перехода строки на пробелы, чтобы вывод не "ломался",
102# когда в расписании присутствует перевод строки (например, когда 2 преподавателя написаны в 2х строках)
103def check(string):
104 string = str(string)
105 if len(string) == 0: #если строка пустая, не возвращаем пустую строку
106 return ""
107 result = ""
108 for s in string: #иначе заменяем все символы перевода строки на пробелы
109 if s != '\n':
110 result += s
111 else:
112 result += " "
113 return result
114
115
116def getusergroupnumber(usergroup): #получаем номер колонки с группой
117 usergroupnumber = 0
118 while(str(worksheet.cell_value(1, usergroupnumber)).find(usergroup) == -1): #перебираем нулевую строку и увеличиваем счетчик, пока не встретим нужное название группы
119 usergroupnumber += 1 #увеличиваем счетчик
120 return usergroupnumber
121
122
123def write_msg(user_id, message, random_id): #отправка сообщения методом VK-api
124 vk.method('messages.send', {'user_id': user_id, 'message': message, 'random_id': random_id})
125
126def send_keyboard(user_id): #отправка сообщения с клавиатурой
127 vk.method('messages.send', {'user_id': user_id, 'message': "Выбери день недели:", 'random_id': 0, "keyboard": keyboard})
128
129def sendrasp(usergroup, day, user_id): # функция отправки расписания
130 usergroupnumber = getusergroupnumber(usergroup) #получаем номер группы
131 start = day * 12 - 9 #считаем номера строк с расписанием на сегодняшний день
132 end = day * 12 + 3
133 result = ""
134 for k in range(start, end): #пробегаемся по всем ячейкам таблицы за конкретный день
135 if len(worksheet.cell_value(k, usergroupnumber)) > 1: #проверяем на наличие предмета в данной ячейке
136 week = getweek() #получаем четность недели
137
138 if (len(worksheet.cell_value(k, 2)) > 1 and week == 1) or (len(worksheet.cell_value(k, 2)) == 0 and week == 0): #проверяем, соответствие четности недели
139 if len(worksheet.cell_value(k, 2)) > 1 and week == 1: #если это первая половина пары, то время для нее берем из ее строки
140 time1 = worksheet.cell_value(k, 2).replace("-", ':') #заменяем "-" на ":"
141 time2 = worksheet.cell_value(k, 3).replace("-", ':')
142 else: #если это вторая половина пары, время для нее берем из передыдущей (особенности расписания)
143 time1 = worksheet.cell_value(k - 1, 2).replace("-", ':')
144 time2 = worksheet.cell_value(k - 1, 3).replace("-", ':')
145
146 result += "{0} пара, ({1} - {2}, {3}): \n{4}, {5} \n\n".format( #формируем строку с парой
147 str(int(worksheet.cell_value(k, 1))), #номер пары
148 time1, #время начала
149 time2, #время конца
150 check(str(worksheet.cell_value(k, usergroupnumber + 3))), #предмет
151 worksheet.cell_value(k, usergroupnumber), #название
152 worksheet.cell_value(k, usergroupnumber + 1) #тип
153 )
154 if result != "":
155 write_msg(user_id, result, 0) #отправляем сообщение с расписанием
156def checkusergroup(user_id): #с помощью базы данных находим группу
157 query = "SELECT count(user_id) FROM users WHERE user_id = {0}".format(str(user_id)) #находим, есть ли юзеры с таким user_id в базе данных
158 result = int(selectquery(query))
159 if result > 0: #если есть, проверяем, ввели ли они группу (status = 1 - группа не введена, 0 - введена)
160 query = "SELECT count(user_id) FROM users WHERE user_id = {0} AND status = '1'".format(str(user_id))
161 result = int(selectquery(query))
162 if (result == 0): #группа введена, отправляем ее название
163 query = "SELECT usergroup FROM users WHERE user_id = {0}".format(str(user_id))
164 usergroup = selectquery(query)
165 return usergroup
166 else: #группа не введена, но юзер есть в базе, значит он прислал название группы
167 return 1
168 else: #это первое сообщение юзера боту, добавляем его в базу данных
169 query = "INSERT INTO users VALUES('{0}', 'none', 1)".format(str(user_id))
170 updatequery(query)
171 return 0
172
173
174def setusergroup(user_id, usergroup): #устанавливаем группу юзеру.
175 query = "UPDATE users SET usergroup = '{1}' WHERE user_id = {0}".format(str(user_id), usergroup) #устанавливаем группу
176 updatequery(query)
177
178 query = "UPDATE users SET status = '0' WHERE user_id = {0}".format(str(user_id)) #устанавливаем статус = 0
179 updatequery(query)
180
181
182def getday():
183 #получаем сегодняшний день, нумерация дней в памяти сервера спешит на 69 часов,
184 # (проверено опытным путем), поэтому вычитаем их
185 day = (int(time.time() - 69*3600) % (24*3600*7)) / (24*3600)
186 print(day)
187 day = int(day)
188 if day == 0 or day > 6: #если дни неучебные, ставим понедельник
189 day = 1
190 return day
191
192
193def getweek(): #получаем четность недели
194 week = (int(time.time()) - 69*3600) // (24*3600*7)
195 return week % 2
196
197
198def daybykeyboard(message): #получаем номер дня недели из его сокращенного названия
199 days = {"ПН" : 1, "ВТ" : 2, "СР" : 3, "ЧТ" : 4, "ПТ" : 5, "СБ" : 6}
200 try:
201 return days[message]
202 except: #если сокращенное название некорректно, возвращаем 0
203 return 0
204
205
206query = "CREATE TABLE IF NOT EXISTS users (user_id int, usergroup text, status int)" #создаем базу данных, если она еще не создана
207updatequery(query)
208
209
210
211vk = vk_api.VkApi(token=token)
212longpoll = VkLongPoll(vk) #создаем объект longpoll VK-api
213
214
215for event in longpoll.listen(): #обработчик событий
216 if event.type == VkEventType.MESSAGE_NEW: #проверяем событие на то, что оно имеет тип нового сообщения
217 if event.to_me:
218 message = event.text #само сообщение
219 user_id = event.user_id #user_id отправителя
220 usergroup = checkusergroup(user_id) #получаем группу из базы данных. 0 - написал впервые, 1 - прислал группу, иначе - название грурры
221
222 if usergroup == 0:
223 write_msg(user_id, "Пришлите номер группы в формате КМБО-03-19", 0) #просим прислать группу
224
225 elif usergroup == 1:
226 try:
227 setusergroup(user_id, message.upper()) #устанавливаем группу
228 write_msg(user_id, "Теперь пришлите любое сообщение, и я будут пришлю расписание группы", 0)
229 send_keyboard(user_id) #отправляем клавиатуру
230 except:
231 write_msg(user_id, "Некорректный номер группы", 0)
232 else:
233 if message == "СЕГОДНЯ":
234 sendrasp(usergroup, getday(), user_id) #присылаем расписание
235 else:
236 day = daybykeyboard(message) #получаем день недели
237 if day != 0:
238 sendrasp(usergroup, day, user_id) #присылаем расписание, если день определен корректно
239 else:
240 write_msg(user_id, "Некорректный номер дня", 0) #отправляем отчет об ошибке
241 send_keyboard(user_id) #отправляем клавиатуру