· 6 years ago · Nov 22, 2019, 05:20 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
275goods = {"Kurwa": {"90MG Blackcurrant": 250,
276 "90MG Blueberry": 250,
277 "90MG Bubblegum": 250,
278 "90MG Kiwi": 250,
279 "90MG Mango": 250,
280 "90MG Pineapple": 250,
281 "90MG Purple Grape": 250,
282 "90MG Вишня": 250,
283 "90MG Чифирь": 250,
284 "90MG Extremely Strong": 250,
285 "90MG Tic Tac": 250,
286 "90MG Ванильная кола": 250,
287 "90MG Морс": 250},
288
289 "Mad": {"Blackberry": 250,
290 "Cherry": 250,
291 "Fatality 100MG": 280,
292 "Mint": 250},
293
294 "Corvus": {"Flash Orange": 220,
295 "Hulk Feijoa": 220,
296 "Joker Wild Berries": 220,
297 "Logan Melon": 220,
298 "Brutal Menthol": 220,
299 "Extreme Menthol": 220,
300 "Strong Menthol": 220},
301
302 "Boshki": {"Hardcore 100MG Forest Berry": 280,
303 "Super Strong Fresh Aloe": 280,
304 "Super Strong Gummy Bear": 280,
305 "Super Strong Menthol": 280},
306
307 "Nictech": {"Extremely Strong": 280,
308 "Kasta Red": 240,
309 "Slim Barberry": 250,
310 "Slim Citrus Mix": 250,
311 "Slim Energy": 250,
312 "Slim Tropic Mix": 250,
313 "Strong": 240},
314 "Arqa": {"65MG Cold Bergamot Candy": 250,
315 "65MG Cold Berry Lemonade": 250,
316 "65MG Cold Caramel Ice Cream": 250,
317 "65MG Cold Chokeberry Cocktail": 250,
318 "65MG Cold Extreme Cola": 250,
319 "65MG Cold Winter Tale": 250,
320 "Black Cold Barberry": 220,
321 "Black Cold Cherry": 220,
322 "Black Cold Citrus Mix": 220,
323 "Black Cold Green Apple": 220,
324 "Black Cold Mint": 220},
325
326 "Lyft": {"Berry Frost Mellow Slim": 230,
327 "Blueberry Slim": 230,
328 "Freeze X-Strong Slim": 230,
329 "Ice Cool Strong Slim": 230,
330 "Lime Slim": 230,
331 "Lime Strong Slim": 230,
332 "Limited Edition Strawberry Bloom Slim": 250,
333 "Liquorice Strong Slim": 230,
334 "Melon Slim": 230,
335 "Mint Easy Slim": 230,
336 "Mint Slim": 230,
337 "Polar Mint Medium Slim": 230,
338 "Tropic Breeze Slim": 230,
339 "Winterchill X-Strong Slim": 230},
340
341 "Vote": {"20MG Cherry": 250,
342 "20MG Cola": 250,
343 "20MG Green Apple": 250,
344 "20MG Strawberry": 250,
345 "40MG Cherry": 250,
346 "40MG Cola": 250,
347 "40MG Green Apple": 250,
348 "40MG Strawberry": 250,
349 "60MG Cherry": 250,
350 "60MG Cola": 250,
351 "60MG Green Apple": 250,
352 "60MG Strawberry": 250},
353
354 "Taboo": {"80 Mint": 230,
355 "Extreme Cold Energy": 230,
356 "Extreme Grape": 230,
357 "Extreme Kiwi & Strawberry": 230,
358 "Strong Mint": 230},
359
360 "Fedrs Ice Cool": {"Mint": 250,
361 "Energy": 250,
362 "Pear": 250,
363 "Spearmint": 250,
364 "Barberry": 250,
365 "Melon": 250,
366 "Cola Vanilla": 250,
367 "Mint Skull & Energy Skull": 250},
368
369 "Скиф": {"Fruits Арбуз Яблоко": 250,
370 "Fruits Мята Яблоко": 250,
371 "Strong Mint Белый": 250,
372 "Super Extreme Mint Коричневый": 250,
373 "Super Extreme Mint Красный": 250,
374 "Ultra Strong Mint Синий": 230},
375
376 "Alfa": {"Cold Клубника": 230,
377 "Cold Кокос": 230,
378 "Cold Мята": 230,
379 "Cold Черешня": 230,
380 "Cold Черника": 230,
381 "Cold Яблоко": 230,
382 "Cold Лайм": 230},
383
384 "Blax": {"Black Edition Cold Dry Extreme Hard Lemon & Lime": 230,
385 "Black Edition Cold Dry Extreme Hard Strawberry & Raspberry": 230,
386 "Black Edition Cold Dry Ultra Strong": 230,
387 "Slim & White Cola Cherry": 250,
388 "Slim & White Grapefruit": 250,
389 "Slim & White Milkshake": 250,
390 "150 Barberry": 280,
391 "150 Bubble Gum": 280,
392 "150 Energy": 280,
393 "150 Strawberry Raspberry": 280,
394 "Black Edition Cold Dry Extreme Hard": 230,
395 "Black Edition Cold Dry Extreme Hard Cherry & Cola": 230},
396
397 "Самоубийца 249 МГ": {"Energy Burn": 300,
398 "Мята": 300,
399 "Малина": 300,
400 "Яблоко": 300},
401
402 "Cuba": {"Silver": 220,
403 "Gold": 220,
404 "Power": 240,
405 "Watermelon": 240,
406 "Ананас": 240,
407 "Вишневый сок": 240,
408 "Земляника": 240,
409 "Йогурт": 240}
410 }
411
412### КЛАВИАТУРЫ
413
414goodsKb = telebot.types.ReplyKeyboardMarkup(True)
415goodsKb.row("Вернуться в меню")
416for good in goods:
417 goodsKb.row(good)
418
419startKb = telebot.types.ReplyKeyboardMarkup(True)
420rows = ["Каталог", "FAQ", "Помощь"]
421for row in rows:
422 startKb.row(row)
423
424paymentKb = telebot.types.ReplyKeyboardMarkup(True)
425paymentKb.row("Qiwi")
426paymentKb.row("Карта")
427
428payKb = telebot.types.ReplyKeyboardMarkup(True)
429payKb.row("Вернуться в меню")
430payKb.row("Оплатил")
431
432helpKb = telebot.types.ReplyKeyboardMarkup(True)
433helpKb.row("Сменить город")
434helpKb.row("Вызвать администратора")
435helpKb.row("Вернуться в меню")
436
437def getGoodList(goodStr):
438 d = goodStr.split(' | ')
439 if d[0] in goods and d[1] in goods[d[0]]:
440 price = goods[d[0]][d[1]]
441 good = [d[0], d[1], price]
442 return good
443 else:
444 return False
445
446
447def generateCatalog(name):
448 kb = telebot.types.ReplyKeyboardMarkup(True)
449 kb.row("Вернуться в каталог")
450 for good in goods[name]:
451 kb.row(name + " | " + good + " | Цена: " + str(goods[name][good]))
452 return kb
453
454
455def generateCities():
456 kb = telebot.types.ReplyKeyboardMarkup(True)
457 for city in cities:
458 kb.row(city)
459 return kb
460
461
462def generateAreas(name):
463 kb = telebot.types.ReplyKeyboardMarkup(True)
464 for area in cities[name]:
465 kb.row(area)
466 return kb
467
468### ФУНКЦИИ ДЛЯ БОТА
469
470def randomString(stringLength=10):
471 """Generate a random string of fixed length """
472 letters = string.ascii_lowercase
473 return ''.join(random.choice(letters) for i in range(stringLength))
474
475
476def makeInvoice(amount):
477 billId = random.randrange(1, 10000000000000000)
478 dateNow = datetime.datetime.now() + datetime.timedelta(hours=3)
479 expirationDateTime = dateNow.strftime('%Y-%m-%dT%H:%M:%S+03:00')
480 amount = str(round(Decimal(float(amount)), 2)) #прости меня, господи
481 data = {"amount": {"currency": "RUB", "value": amount}, "comment": "Оплата товара", "expirationDateTime": expirationDateTime}
482 headers = {"Authorization": "Bearer " + secret_key, "Accept": "application/json", "Content-Type": "application/json"}
483 req = requests.put("https://api.qiwi.com/partner/bill/v1/bills/{0}".format(str(billId)), data=json.dumps(data), headers = headers)
484 req = req.json()
485 if "errorCode" in req:
486 print("Error in making invoice!" + req["description"])
487 raise
488 return False
489 else:
490 return req["payUrl"]
491
492
493def getHistory():
494 url = "https://edge.qiwi.com/payment-history/v2/persons/{0}/payments".format(str(qiwi))
495 headers = {"Accept": "application/json", "Content-Type": "application/json", "Authorization": "Bearer " + qiwi_token}
496 req = requests.get(url, params={"rows": 1, "operation": "IN"}, headers = headers)
497 if req.status_code == 200:
498 req = req.json()
499 return req
500 return req
501 # raise ValueError
502
503previousTransactions = [getHistory()]
504
505print("everything loaded!")
506
507### ОБРАБОТКА СООБЩЕНИЙ
508
509@bot.message_handler(commands=['start'])
510def start(message):
511 if not isuserready(message.from_user.id):
512 bot.send_message(message.chat.id, startGorodText, parse_mode="markdown", reply_markup = generateCities())
513 print("sent cities to {0}".format(str(message.from_user.id)))
514 return
515 bot.send_message(message.chat.id, startText, parse_mode="markdown", reply_markup = startKb)
516 print("got start msg from id {0}".format(str(message.from_user.id)))
517
518
519@bot.message_handler(content_types=['text'])
520def send_text(message):
521 print("got msg from id {0} : {1}".format(str(message.from_user.id), message.text))
522 if message.text in cities and message.from_user.id not in usercity:
523 bot.send_message(message.chat.id, "Выбери свой район", reply_markup = generateAreas(message.text))
524 usercity[message.from_user.id] = message.text
525
526
527 elif message.from_user.id in usercity and message.text in cities[usercity[message.from_user.id]]:
528 userswrite(message.from_user.id, usercity[message.from_user.id])
529 start(message)
530
531
532 elif message.text.lower() in ["меню", "вернуться в меню"]:
533 start(message)
534
535
536 elif message.text.lower() in ["каталог", "вернуться в каталог"]:
537 bot.send_message(message.chat.id, "*Список марок:* (список можно пролистывать)", reply_markup = goodsKb, parse_mode="markdown")
538
539
540 elif message.text in goods:
541 bot.send_message(message.chat.id, "*Каталог марки {0}:* (список можно проматывать)".format(message.text), reply_markup = generateCatalog(message.text), parse_mode = "markdown")
542 print("sent catalog {0}".format(message.text))
543
544
545 elif message.from_user.id in usersteps and usersteps[message.from_user.id] == "Qiwi":
546 text = """
547 Вы выбрали товар *{0}*
548 Стоимость товара: *{1}*
549 Счет для оплаты товара: *{2}*
550
551 При переводе на Qiwi *обязательно* укажите следующий комментарий: `{3}` (с телефона этот комментарий можно скопировать долгим тапом по нему)
552 Если при переводе вы не укажете данный комментарий, то *оплата не засчитается!*
553
554 Когда вы завершите оплату, нажмите кнопку *ОПЛАТИЛ!*
555 """
556 choose = userchosen[message.from_user.id]
557 price = goods[choose[0]][choose[1]]
558 wallet = qiwi
559 readyText = text.format(choose[0] + " " + choose[1], price, wallet, randomString())
560 bot.send_message(message.chat.id, readyText, parse_mode = "markdown", reply_markup = payKb)
561 del(usersteps[message.from_user.id])
562 print("sent pay window to user {0}".format(str(message.from_user.id)))
563
564
565 elif message.from_user.id in usersteps and usersteps[message.from_user.id] == "Карта":
566 text = """
567 Вы выбрали товар <b>{0}</b>
568 Стоимость товара: <b>{1}</b>
569 Ссылка для оплаты товара: {2}
570
571 Для оплаты вам нужно перейти по ссылке и оплатить товар.
572
573 Когда вы завершите оплату, нажмите кнопку <b>ОПЛАТИЛ!</b>
574 """
575 choose = userchosen[message.from_user.id]
576 price = goods[choose[0]][choose[1]]
577 link = makeInvoice(int(price))
578 #link = "test"
579 del(usersteps[message.from_user.id])
580 readyText = text.format(choose[0] + " " + choose[1], price, link)
581 bot.send_message(message.chat.id, readyText, parse_mode = "HTML", reply_markup = payKb)
582 print("sent invoice window to user {0}".format(str(message.from_user.id)))
583
584
585 elif message.text in ["Qiwi", "Карта"] and message.from_user.id in userchosen:
586 usersteps[message.from_user.id] = message.text
587 bot.send_message(message.chat.id, "Пожалуйста, введите свой адрес для доставки, в формате: Улица, номер дома, квартира:", reply_markup = telebot.types.ReplyKeyboardRemove())
588
589
590 elif message.text.lower() == "оплатил":
591 bot.send_message(message.chat.id, "Оплата не найдена! Попробуйте еще раз.")
592 trans = [getHistory()]
593 if trans != previousTransactions:
594 bot.send_message(admin, "!!! Пополнение киви! Получена оплата от {0}".format(str(message.from_user.id)))
595 print("GOT PAY CONFIRM!! user: {0}".format(str(message.from_user.id)))
596
597
598 elif len(message.text.split(' | ')) == 3:
599 d = getGoodList(message.text)
600 if d:
601 userchosen[message.from_user.id] = [d[0], d[1]]
602 bot.send_message(message.chat.id, "Выберите удобный способ оплаты", reply_markup = paymentKb)
603 print("sent good to user {0} for price of {1}".format(str(message.from_user.id), str(d[2])))
604
605
606 elif message.text.lower() == "faq":
607 bot.send_message(message.chat.id, faqText, parse_mode="markdown")
608 print("sent faq to {0}".format(str(message.from_user.id)))
609
610
611
612 elif message.text.lower() == "помощь":
613 bot.send_message(message.chat.id, helpText, reply_markup = helpKb, parse_mode="markdown")
614 print("sent help to {0}".format(str(message.from_user.id)))
615
616
617 elif message.text.lower() == "сменить город" and isuserready(message.from_user.id):
618 usersremove(message.from_user.id)
619 start(message)
620 print("sent change city to {0}".format(str(message.from_user.id)))
621
622
623 elif message.from_user.id in useradmin:
624 useradmin.pop(message.from_user.id)
625 bot.forward_message(admin, message.chat.id, message.message_id)
626 bot.send_message(message.chat.id, "Администратор получил ваше сообщение и ответит вам в ближайшее время!", reply_markup = startKb)
627
628
629 elif message.text.lower() == "вызвать администратора":
630 useradmin[message.from_user.id] = 1
631 bot.send_message(message.chat.id, "Пожалуйста, напишите вашу проблему в чат.", reply_markup = telebot.types.ReplyKeyboardRemove())
632
633try:
634 bot.polling()
635except Exception as exc:
636 bot.send_message(admin, "ВНИМАНИЕ!!! Бот упал, произошла ошибка! Тип ошибки: {0} Текст ошибки: {1}".format(str(type(exc)), str(exc)))