· 5 years ago · Nov 22, 2019, 05:28 PM
1import telebot
2import string
3import random
4import datetime
5import requests
6import json
7from decimal import Decimal
8import sqlite3
9bot = telebot.TeleBot("1000617680:AAG9Tc4-Tai0YCEQ0rlMlrOrXpSrUbcdTbc")
10print("bot initialized!")
11
12admin = 1017262088 #ID администратора бота, можно получить через бота @userinfobot
13qiwi = 79170651895
14
15secret_key = "eyJ2ZXJzaW9uIjoiUDJQIiwiZGF0YSI6eyJwYXlpbl9tZXJjaGFudF9zaXRlX3VpZCI6IjB2Z2Nidy0wMCIsInVzZXJfaWQiOiI3OTE3MDY1MTg5NSIsInNlY3JldCI6ImZkNjg2MjQ0YjA0Zjc1YmYxYjY3OGYxOWMwMzY1MzcwNTY5YjQ5MTJjOTQ3NzhmNzVjZWRjODRjNmI1YWY0MWQifX0=" # получить тут: https://qiwi.com/p2p-admin/transfers/invoice
16qiwi_token = "b108726bc48a35207becb853e4e68d97" # с доступом к истории, получить на qiwi.com/api
17
18
19#Текст меню
20startText = """
21 *Добро пожаловать в SnusMarket!*
22 Здесь ты можешь купить снюс, электронные сигареты твоих любимых марок по самой выгодной цене!
23 Для того, чтобы открыть каталог, нажми кнопку КАТАЛОГ!
24 """
25
26startGorodText = """
27 *Добро пожаловать в SnusMarket!*
28 Пожалуйста, выбери свой город.
29 """
30
31#Текст FAQ
32faqText = """
33Какие сроки доставки?
34- Доставка осуществляется в течении 1-2 дней, в зависимости от количества заказов.
35
36Почему стоит использовать СНЮС вместо сигарет?
37 - Если вы хотите бросить курить, то СНЮС, это идеальный вариант для Вас.
38
39Доставка курьером или самовывоз?
40 - В ближайшее время будет только доставка курьером по адресу, доставка бесплатная.
41
42СНЮС - это наркотическое изделие?
43 - Нет, снюс, то есть жевательный табак, не является средством, входящим в список запрещенных наркотических изделий.
44
45По каким странам вы осуществляете доставку?
46 - Доставка доступна по Украине, Росии, Казахстане.
47"""
48
49#Текст помощи
50helpText = """
51Выберите, что вам нужно сделать
52"""
53
54usersteps = {}
55useradmin = {}
56userchosen = {}
57usercity = {}
58
59
60def getValuesFromDB(cmd, arg):
61 db = sqlite3.connect("bot.db")
62 c = db.cursor()
63 c.execute(cmd, arg)
64 result = c.fetchall()
65 c.close()
66 return result
67
68def setValuesToDB(cmd, arg):
69 db = sqlite3.connect("bot.db")
70 c = db.cursor()
71 c.execute(cmd, arg)
72 db.commit()
73 c.close()
74 return True
75
76# Старый usersready на текстовом файле
77# def usersready():
78# userstxt = open("users.txt", "r")
79# d = userstxt.read().split('\n')
80# userstxt.close()
81# return d
82
83
84# Новый usersready на sqlite3
85def isuserready(userid):
86 isready = getValuesFromDB('SELECT * FROM users WHERE id = ?', (userid,))
87 return isready
88
89def userswrite(userid, country):
90 return setValuesToDB('INSERT INTO users VALUES (?, ?)', (userid, country))
91
92def usersremove(userid):
93 return setValuesToDB('DELETE FROM users WHERE id = ?', (userid,))
94
95# def userswrite(userid):
96# users = usersready()
97# userstxt = open("users.txt", "w")
98# users.append(str(userid))
99# text = "\n".join(users)
100# userstxt.write(text)
101# userstxt.close()
102# return True
103
104# def usersremove(userid):
105# users = usersready()
106# userstxt = open("users.txt", "w")
107# users.remove(str(userid))
108# if userid in usercity:
109# usercity.pop(userid)
110# text = "\n".join(users)
111# userstxt.write(text)
112# userstxt.close()
113# return True
114
115cities = {"Москва": ["Измайлово",
116 "Сокольники",
117 "Внуково",
118 "Кунцево",
119 "Крюково",
120 "Щукино",
121 "Лефортово",
122 "Выхино-Жулебина",
123 "Медведково",
124 "Якиманка",
125 "Отрадное"],
126
127 "Санкт-Петербург": ["Центральный район",
128 "Невский район",
129 "Кировский район",
130 "Петроградский район",
131 "Московский район",
132 "Василеостровской район",
133 "Главная"],
134
135 "Ростов-На-Дону": ["Ворошиловский",
136 "Железнодорожный",
137 "Кировский",
138 "Ленинский",
139 "Октябрьский",
140 "Первомайский",
141 "Пролетарский",
142 "Советский"],
143
144 "Екатеринбург": ["Верх-Исетский",
145 "Железнодорожный",
146 "Кировский",
147 "Ленинский",
148 "Октябрьский",
149 "Орджоникидзевский",
150 "Чкаловский"],
151
152 "Челябинск": ["Калининский",
153 "Курчатовский",
154 "Ленинский",
155 "Металлургический",
156 "Советский",
157 "Тракторозаводский",
158 "Центральный"],
159
160 "Новосибирск": ["Дзержинский",
161 "Заельцовский",
162 "Калининский",
163 "Кировский",
164 "Ленинский",
165 "Октябрьский",
166 "Советский"],
167
168 "Нижний Новгород": ["Автозаводский",
169 "Канавинский",
170 "Ленинский",
171 "Московский",
172 "Нижегородский",
173 "Приокский",
174 "Советский",
175 "Сормовский"],
176
177 "Казань": ["Авиастроительный",
178 "Кировский",
179 "Московский",
180 "Ново-Савиновский",
181 "Приволжский",
182 "Советский"],
183
184 "Омск": ["Кировский",
185 "Ленинский",
186 "Октябрьский",
187 "Советский",
188 "Центральный"],
189
190 "Самара": ["Октябрьский",
191 "Советский",
192 "Промышленный",
193 "Кировский"],
194
195 "Краснодар": ["Западный",
196 "Карасунский",
197 "Прикубанский",
198 "Центральный"],
199
200 "Саратов": ["Заводской",
201 "Октябрьский",
202 "Ленинский",
203 "Кировский"],
204
205 "Тюмень": ["Восточный",
206 "Калининский",
207 "Ленинский",
208 "Центральный"],
209
210 "Барнаул": ["Железнодорожный",
211 "Индустриальный",
212 "Ленинский",
213 "Октябрьский",
214 "Центральный"],
215
216 "Иркутск": ["Кировский",
217 "Куйбышевский",
218 "Ленинский",
219 "Октябрьский",
220 "Свердловский"],
221
222 "Ярославль": ["Дзержинский",
223 "Заволжский",
224 "Фрунзенский"],
225
226 "Владивосток": ["Ленинский",
227 "Первомайский",
228 "Первореченский"],
229
230 "Оренбург": ["Дзержинский",
231 "Промышленный",
232 "Ленинский"],
233
234 "Томск": ["Кировский",
235 "Ленинский",
236 "Октябрьский",
237 "Советский"],
238
239 "Воронеж": ["Железнодорожный",
240 "Коминтерновский",
241 "Левобережный",
242 "Ленинский",
243 "Советский",
244 "Центральный"],
245
246 "Пермь": ["Дзержинский",
247 "Индустриальный",
248 "Кировский",
249 "Мотовилихинский",
250 "Орджоникидзевский",
251 "Свердловский"],
252
253 "Волгоград": ["Тракторозаводский",
254 "Краснооктябрьский",
255 "Дзержинский",
256 "Советский",
257 "Кировский",
258 "Красноармейский"],
259
260 "Уфа": ["Калининский",
261 "Кировский",
262 "Октябрьский",
263 "Орджоникидзевский",
264 "Советский"],
265
266 "Красноярск": ["Железнодорожный",
267 "Кировский",
268 "Ленинский",
269 "Октябрьский",
270 "Свердловский",
271 "Советский"],
272
273 "Другой город": ["Продолжить"]
274 }
275
276
277goods = {"Kurwa": {"90MG Blackcurrant": 250,
278 "90MG Blueberry": 250,
279 "90MG Bubblegum": 250,
280 "90MG Kiwi": 250,
281 "90MG Mango": 250,
282 "90MG Pineapple": 250,
283 "90MG Purple Grape": 250,
284 "90MG Вишня": 250,
285 "90MG Чифирь": 250,
286 "90MG Extremely Strong": 250,
287 "90MG Tic Tac": 250,
288 "90MG Ванильная кола": 250,
289 "90MG Морс": 250},
290
291 "Mad": {"Blackberry": 250,
292 "Cherry": 250,
293 "Fatality 100MG": 280,
294 "Mint": 250},
295
296 "Corvus": {"Flash Orange": 220,
297 "Hulk Feijoa": 220,
298 "Joker Wild Berries": 220,
299 "Logan Melon": 220,
300 "Brutal Menthol": 220,
301 "Extreme Menthol": 220,
302 "Strong Menthol": 220},
303
304 "Boshki": {"Hardcore 100MG Forest Berry": 280,
305 "Super Strong Fresh Aloe": 280,
306 "Super Strong Gummy Bear": 280,
307 "Super Strong Menthol": 280},
308
309 "Nictech": {"Extremely Strong": 280,
310 "Kasta Red": 240,
311 "Slim Barberry": 250,
312 "Slim Citrus Mix": 250,
313 "Slim Energy": 250,
314 "Slim Tropic Mix": 250,
315 "Strong": 240},
316 "Arqa": {"65MG Cold Bergamot Candy": 250,
317 "65MG Cold Berry Lemonade": 250,
318 "65MG Cold Caramel Ice Cream": 250,
319 "65MG Cold Chokeberry Cocktail": 250,
320 "65MG Cold Extreme Cola": 250,
321 "65MG Cold Winter Tale": 250,
322 "Black Cold Barberry": 220,
323 "Black Cold Cherry": 220,
324 "Black Cold Citrus Mix": 220,
325 "Black Cold Green Apple": 220,
326 "Black Cold Mint": 220},
327
328 "Lyft": {"Berry Frost Mellow Slim": 230,
329 "Blueberry Slim": 230,
330 "Freeze X-Strong Slim": 230,
331 "Ice Cool Strong Slim": 230,
332 "Lime Slim": 230,
333 "Lime Strong Slim": 230,
334 "Limited Edition Strawberry Bloom Slim": 250,
335 "Liquorice Strong Slim": 230,
336 "Melon Slim": 230,
337 "Mint Easy Slim": 230,
338 "Mint Slim": 230,
339 "Polar Mint Medium Slim": 230,
340 "Tropic Breeze Slim": 230,
341 "Winterchill X-Strong Slim": 230},
342
343 "Vote": {"20MG Cherry": 250,
344 "20MG Cola": 250,
345 "20MG Green Apple": 250,
346 "20MG Strawberry": 250,
347 "40MG Cherry": 250,
348 "40MG Cola": 250,
349 "40MG Green Apple": 250,
350 "40MG Strawberry": 250,
351 "60MG Cherry": 250,
352 "60MG Cola": 250,
353 "60MG Green Apple": 250,
354 "60MG Strawberry": 250},
355
356 "Taboo": {"80 Mint": 230,
357 "Extreme Cold Energy": 230,
358 "Extreme Grape": 230,
359 "Extreme Kiwi & Strawberry": 230,
360 "Strong Mint": 230},
361
362 "Fedrs Ice Cool": {"Mint": 250,
363 "Energy": 250,
364 "Pear": 250,
365 "Spearmint": 250,
366 "Barberry": 250,
367 "Melon": 250,
368 "Cola Vanilla": 250,
369 "Mint Skull & Energy Skull": 250},
370
371 "Скиф": {"Fruits Арбуз Яблоко": 250,
372 "Fruits Мята Яблоко": 250,
373 "Strong Mint Белый": 250,
374 "Super Extreme Mint Коричневый": 250,
375 "Super Extreme Mint Красный": 250,
376 "Ultra Strong Mint Синий": 230},
377
378 "Alfa": {"Cold Клубника": 230,
379 "Cold Кокос": 230,
380 "Cold Мята": 230,
381 "Cold Черешня": 230,
382 "Cold Черника": 230,
383 "Cold Яблоко": 230,
384 "Cold Лайм": 230},
385
386 "Blax": {"Black Edition Cold Dry Extreme Hard Lemon & Lime": 230,
387 "Black Edition Cold Dry Extreme Hard Strawberry & Raspberry": 230,
388 "Black Edition Cold Dry Ultra Strong": 230,
389 "Slim & White Cola Cherry": 250,
390 "Slim & White Grapefruit": 250,
391 "Slim & White Milkshake": 250,
392 "150 Barberry": 280,
393 "150 Bubble Gum": 280,
394 "150 Energy": 280,
395 "150 Strawberry Raspberry": 280,
396 "Black Edition Cold Dry Extreme Hard": 230,
397 "Black Edition Cold Dry Extreme Hard Cherry & Cola": 230},
398
399 "Самоубийца 249 МГ": {"Energy Burn": 300,
400 "Мята": 300,
401 "Малина": 300,
402 "Яблоко": 300},
403
404 "Cuba": {"Silver": 220,
405 "Gold": 220,
406 "Power": 240,
407 "Watermelon": 240,
408 "Ананас": 240,
409 "Вишневый сок": 240,
410 "Земляника": 240,
411 "Йогурт": 240}
412 }
413
414### КЛАВИАТУРЫ
415
416goodsKb = telebot.types.ReplyKeyboardMarkup(True)
417goodsKb.row("Вернуться в меню")
418for good in goods:
419 goodsKb.row(good)
420
421startKb = telebot.types.ReplyKeyboardMarkup(True)
422rows = ["Каталог", "FAQ", "Помощь"]
423for row in rows:
424 startKb.row(row)
425
426paymentKb = telebot.types.ReplyKeyboardMarkup(True)
427paymentKb.row("Qiwi")
428paymentKb.row("Карта")
429
430payKb = telebot.types.ReplyKeyboardMarkup(True)
431payKb.row("Вернуться в меню")
432payKb.row("Оплатил")
433
434helpKb = telebot.types.ReplyKeyboardMarkup(True)
435helpKb.row("Сменить город")
436helpKb.row("Вызвать администратора")
437helpKb.row("Вернуться в меню")
438
439def getGoodList(goodStr):
440 d = goodStr.split(' | ')
441 if d[0] in goods and d[1] in goods[d[0]]:
442 price = goods[d[0]][d[1]]
443 good = [d[0], d[1], price]
444 return good
445 else:
446 return False
447
448
449def generateCatalog(name):
450 kb = telebot.types.ReplyKeyboardMarkup(True)
451 kb.row("Вернуться в каталог")
452 for good in goods[name]:
453 kb.row(name + " | " + good + " | Цена: " + str(goods[name][good]))
454 return kb
455
456
457def generateCities():
458 kb = telebot.types.ReplyKeyboardMarkup(True)
459 for city in cities:
460 kb.row(city)
461 return kb
462
463
464def generateAreas(name):
465 kb = telebot.types.ReplyKeyboardMarkup(True)
466 for area in cities[name]:
467 kb.row(area)
468 return kb
469
470### ФУНКЦИИ ДЛЯ БОТА
471
472def randomString(stringLength=10):
473 """Generate a random string of fixed length """
474 letters = string.ascii_lowercase
475 return ''.join(random.choice(letters) for i in range(stringLength))
476
477
478def makeInvoice(amount):
479 billId = random.randrange(1, 10000000000000000)
480 dateNow = datetime.datetime.now() + datetime.timedelta(hours=3)
481 expirationDateTime = dateNow.strftime('%Y-%m-%dT%H:%M:%S+03:00')
482 amount = str(round(Decimal(float(amount)), 2)) #прости меня, господи
483 data = {"amount": {"currency": "RUB", "value": amount}, "comment": "Оплата товара", "expirationDateTime": expirationDateTime}
484 headers = {"Authorization": "Bearer " + secret_key, "Accept": "application/json", "Content-Type": "application/json"}
485 req = requests.put("https://api.qiwi.com/partner/bill/v1/bills/{0}".format(str(billId)), data=json.dumps(data), headers = headers)
486 req = req.json()
487 if "errorCode" in req:
488 print("Error in making invoice!" + req["description"])
489 raise
490 return False
491 else:
492 return req["payUrl"]
493
494
495def getHistory():
496 url = "https://edge.qiwi.com/payment-history/v2/persons/{0}/payments".format(str(qiwi))
497 headers = {"Accept": "application/json", "Content-Type": "application/json", "Authorization": "Bearer " + qiwi_token}
498 req = requests.get(url, params={"rows": 1, "operation": "IN"}, headers = headers)
499 if req.status_code == 200:
500 req = req.json()
501 return req
502 return req
503 # raise ValueError
504
505previousTransactions = [getHistory()]
506
507print("everything loaded!")
508
509### ОБРАБОТКА СООБЩЕНИЙ
510
511@bot.message_handler(commands=['start'])
512def start(message):
513 if not isuserready(message.from_user.id):
514 bot.send_message(message.chat.id, startGorodText, parse_mode="markdown", reply_markup = generateCities())
515 print("sent cities to {0}".format(str(message.from_user.id)))
516 return
517 bot.send_message(message.chat.id, startText, parse_mode="markdown", reply_markup = startKb)
518 print("got start msg from id {0}".format(str(message.from_user.id)))
519
520
521@bot.message_handler(content_types=['text'])
522def send_text(message):
523 print("got msg from id {0} : {1}".format(str(message.from_user.id), message.text))
524 if message.text in cities and message.from_user.id not in usercity:
525 bot.send_message(message.chat.id, "Выбери свой район", reply_markup = generateAreas(message.text))
526 usercity[message.from_user.id] = message.text
527
528
529 elif message.from_user.id in usercity and message.text in cities[usercity[message.from_user.id]]:
530 userswrite(message.from_user.id, usercity[message.from_user.id])
531 start(message)
532
533
534 elif message.text.lower() in ["меню", "вернуться в меню"]:
535 start(message)
536
537
538 elif message.text.lower() in ["каталог", "вернуться в каталог"]:
539 bot.send_message(message.chat.id, "*Список марок:* (список можно пролистывать)", reply_markup = goodsKb, parse_mode="markdown")
540
541
542 elif message.text in goods:
543 bot.send_message(message.chat.id, "*Каталог марки {0}:* (список можно проматывать)".format(message.text), reply_markup = generateCatalog(message.text), parse_mode = "markdown")
544 print("sent catalog {0}".format(message.text))
545
546
547 elif message.from_user.id in usersteps and usersteps[message.from_user.id] == "Qiwi":
548 text = """
549 Вы выбрали товар *{0}*
550 Стоимость товара: *{1}*
551 Счет для оплаты товара: *{2}*
552
553 При переводе на Qiwi *обязательно* укажите следующий комментарий: `{3}` (с телефона этот комментарий можно скопировать долгим тапом по нему)
554 Если при переводе вы не укажете данный комментарий, то *оплата не засчитается!*
555
556 Когда вы завершите оплату, нажмите кнопку *ОПЛАТИЛ!*
557 """
558 choose = userchosen[message.from_user.id]
559 price = goods[choose[0]][choose[1]]
560 wallet = qiwi
561 readyText = text.format(choose[0] + " " + choose[1], price, wallet, randomString())
562 bot.send_message(message.chat.id, readyText, parse_mode = "markdown", reply_markup = payKb)
563 del(usersteps[message.from_user.id])
564 print("sent pay window to user {0}".format(str(message.from_user.id)))
565
566
567 elif message.from_user.id in usersteps and usersteps[message.from_user.id] == "Карта":
568 text = """
569 Вы выбрали товар <b>{0}</b>
570 Стоимость товара: <b>{1}</b>
571 Ссылка для оплаты товара: {2}
572
573 Для оплаты вам нужно перейти по ссылке и оплатить товар.
574
575 Когда вы завершите оплату, нажмите кнопку <b>ОПЛАТИЛ!</b>
576 """
577 choose = userchosen[message.from_user.id]
578 price = goods[choose[0]][choose[1]]
579 link = makeInvoice(int(price))
580 #link = "test"
581 del(usersteps[message.from_user.id])
582 readyText = text.format(choose[0] + " " + choose[1], price, link)
583 bot.send_message(message.chat.id, readyText, parse_mode = "HTML", reply_markup = payKb)
584 print("sent invoice window to user {0}".format(str(message.from_user.id)))
585
586
587 elif message.text in ["Qiwi", "Карта"] and message.from_user.id in userchosen:
588 usersteps[message.from_user.id] = message.text
589 bot.send_message(message.chat.id, "Пожалуйста, введите свой адрес для доставки, в формате: Город(Если он не выбран), Улица, номер дома, квартира:", reply_markup = telebot.types.ReplyKeyboardRemove())
590
591
592 elif message.text.lower() == "оплатил":
593 bot.send_message(message.chat.id, "Оплата не найдена! Попробуйте еще раз.")
594 trans = [getHistory()]
595 if trans != previousTransactions:
596 bot.send_message(admin, "!!! Пополнение киви! Получена оплата от {0}".format(str(message.from_user.id)))
597 print("GOT PAY CONFIRM!! user: {0}".format(str(message.from_user.id)))
598
599
600 elif len(message.text.split(' | ')) == 3:
601 d = getGoodList(message.text)
602 if d:
603 userchosen[message.from_user.id] = [d[0], d[1]]
604 bot.send_message(message.chat.id, "Выберите удобный способ оплаты", reply_markup = paymentKb)
605 print("sent good to user {0} for price of {1}".format(str(message.from_user.id), str(d[2])))
606
607
608 elif message.text.lower() == "faq":
609 bot.send_message(message.chat.id, faqText, parse_mode="markdown")
610 print("sent faq to {0}".format(str(message.from_user.id)))
611
612
613
614 elif message.text.lower() == "помощь":
615 bot.send_message(message.chat.id, helpText, reply_markup = helpKb, parse_mode="markdown")
616 print("sent help to {0}".format(str(message.from_user.id)))
617
618
619 elif message.text.lower() == "сменить город" and isuserready(message.from_user.id):
620 usersremove(message.from_user.id)
621 start(message)
622 print("sent change city to {0}".format(str(message.from_user.id)))
623
624
625 elif message.from_user.id in useradmin:
626 useradmin.pop(message.from_user.id)
627 bot.forward_message(admin, message.chat.id, message.message_id)
628 bot.send_message(message.chat.id, "Администратор получил ваше сообщение и ответит вам в ближайшее время!", reply_markup = startKb)
629
630
631 elif message.text.lower() == "вызвать администратора":
632 useradmin[message.from_user.id] = 1
633 bot.send_message(message.chat.id, "Пожалуйста, напишите вашу проблему в чат.", reply_markup = telebot.types.ReplyKeyboardRemove())
634
635try:
636 bot.polling()
637except Exception as exc:
638 bot.send_message(admin, "ВНИМАНИЕ!!! Бот упал, произошла ошибка! Тип ошибки: {0} Текст ошибки: {1}".format(str(type(exc)), str(exc)))