· 5 years ago · Feb 03, 2020, 02:24 PM
1import logging
2from telegram import InlineKeyboardButton, InlineKeyboardMarkup, User, ParseMode, InputMediaPhoto
3from telegram.ext import Updater, CommandHandler, CallbackQueryHandler, MessageHandler, Filters, ConversationHandler
4import sqlite3
5import json
6from functools import wraps
7import time
8import copy
9import re
10
11
12
13
14class TelegramBot:
15 def __init__(self, jobqueue):
16 self.token = '1057488566:AAFJlE7QOwvXIu2BEGSaeEPAwPj7vF4eVdA'
17 self.jobqueue = jobqueue
18
19 def start(self, update, context):
20 #Message that gets displayed once /start is chosen
21 #Checks if uesr already exists in Database
22 #If exists, proceeds to the main module
23 user = update.effective_user
24
25 cx = Database().execute(f"SELECT EXISTS(SELECT 1 FROM PayPalMafia_users WHERE id='{user['id']}')").fetchone()[0]
26
27
28 if cx:
29 keyboard = [[InlineKeyboardButton("Dashboard", callback_data="dashboard")],
30 [InlineKeyboardButton("Settings", callback_data="settings")]]
31
32 reply_markup = InlineKeyboardMarkup(keyboard)
33
34 update.message.reply_text("Looks like you're already an existing user, where would you like to go next?", reply_markup=reply_markup)
35
36 return ConversationHandler.START_RESPONSE
37 else:
38
39 update.message.reply_text("""
40Hi! This is PayPalMafiaBot. I will be cashing out your Gift Cards for you.
41
42Send /cancel to stop talking to me.
43
44Please reply with your current PayPal email to set up your profile, You can change this later at your own convenience.""")
45
46 return ConversationHandler.SETUP
47
48
49 def setupuser(self, update, context):
50 message, user = update.message.text, update.effective_user
51
52 #Email validation code
53 regex = '^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$'
54
55 if(re.search(regex,message)):
56 sqlite_insert_query = f"""INSERT INTO PayPalMafia_users(id, username, paypalemail, currency) VALUES ({user['id']},"{user['username']}","{message}", "CAD")"""
57
58 with Database() as db:
59 db.execute(sqlite_insert_query)
60 db.commit()
61
62 keyboard = [[InlineKeyboardButton("Dashboard", callback_data="dashboard")],
63 [InlineKeyboardButton("Settings", callback_data="settings")]]
64
65 reply_markup = InlineKeyboardMarkup(keyboard)
66
67 update.message.reply_text("Your PayPal cashout email has been confirmed successfully!\nWhere would you like to go next?", reply_markup=reply_markup)
68
69 return ConversationHandler.START_RESPONSE
70 else:
71 update.message.reply_text("Invalid email provided. Please try again.")
72
73
74 def cancel(self, update, context):
75 update.message.reply_text("Bye! I hope we can talk again some day.")
76 return ConversationHandler.END
77
78
79 def error(self, update, context):
80 #Log errors caused by updates
81 logger.warning("Update %s caused error %s", update, context.error)
82
83
84 def dashboard(self, update, context):
85 #Dashboard acts as a portal for users to proceed to other modules chosen by them
86
87 query = update.callback_query
88
89 keyboard = [[InlineKeyboardButton("Cashier", callback_data='cashier')],
90 [InlineKeyboardButton("Settings", callback_data='settings')],
91 [InlineKeyboardButton("Cancel", callback_data='cancel')]
92 ]
93
94 reply_markup = InlineKeyboardMarkup(keyboard)
95
96 resp = Database().execute(f"SELECT amount FROM PayPalMafia_cards WHERE id='{update.effective_user.id}' AND date='{datetime.utcnow().strftime('%Y-%m-%d')}' AND used = 1 ;").fetchone()
97 if resp == None:
98 totalcashouttoday = 0
99 else:
100 totalcashouttoday = sum(filter(None, resp))
101
102 query.edit_message_text(f"""
103Welcome {query["first_name"]}
104The dashboard helps you manage Payments, Settings and other essential features.
105Cashouts Today: *${totalcashouttoday}*\n""", reply_markup=reply_markup, parse_mode=ParseMode.MARKDOWN)
106
107 return ConversationHandler.START_RESPONSE
108
109
110 def settings(self, update, context):
111 #Used to manage the settings
112 query = update.callback_query
113
114 resp = Database().execute(f"SELECT paypalemail, currency FROM PayPalMafia_users WHERE id='{update.effective_user.id}';").fetchone()
115 paypalemail, currency = resp[0], resp[1]
116
117 keyboard = [[InlineKeyboardButton("Change PayPal Email", callback_data='enterppemail')],
118 [InlineKeyboardButton("Change Currency", callback_data='currency')],[telegram.InlineKeyboardButton("Return to dashboard", callback_data='dashboard')]]
119
120 reply_markup = InlineKeyboardMarkup(keyboard)
121 query.edit_message_text(f"""
122*Settings*
123PayPal email: {paypalemail}
124Currency: {currency}""", reply_markup=reply_markup, parse_mode=ParseMode.MARKDOWN)
125 return SETTINGS_RESPONSE
126
127
128 def cashierpage(self, update, context):
129 query = update.callback_query
130
131 keyboard = [[InlineKeyboardButton("My Cashouts", callback_data='mycashouts')],
132 [InlineKeyboardButton("Start Cashout", callback_data='cashout')],
133 [InlineKeyboardButton("Return to dashboard", callback_data='dashboard')]]
134
135 reply_markup = InlineKeyboardMarkup(keyboard)
136 context.bot.send_message(chat_id=update.effective_chat.id, text='Choose your option:', reply_markup=reply_markup, one_time_keyboard=True)
137
138 return ConversationHandler.CASHIER_RESPONSE
139
140
141 def startcashouttask(self, update, context):
142 query = update.callback_query
143
144 query.edit_message_text(f'Enter your Cards in a list below in this format:\n\n*CARDNUMBER:12:22:919:CA$5.00:False*', parse_mode=ParseMode.MARKDOWN)
145 return ConversationHandler.CASHOUT_RESPONSE
146
147
148
149 def cashouttask(self, update, context):
150 text, user = update.message.text, update.effective_user.id
151 resp = Database().execute(f"SELECT paypalemail FROM PayPalMafia_users WHERE id='{user}';").fetchone()
152
153 if resp != None:
154 keyboard = [[InlineKeyboardButton("Check Cashout Status", callback_data='cashoutstatus')],
155 [InlineKeyboardButton("Return to dashboard", callback_data='dashboard')]]
156
157 reply_markup = InlineKeyboardMarkup(keyboard)
158
159 orderid = random.randint(100000000000,999999999999)
160
161 cardstext = text.split("\n")
162
163 class PaymentData:
164 def __init__(self, card):
165 self.cardnumber = card[0]
166 self.cardexpmon=card[1]
167 self.cardexpyear=card[2]
168 self.cardcvv=card[3]
169 self.amount=float(card[4])
170 self.email = resp[0]
171
172 cardslist = []
173
174 for card in cardstext:
175 carddata = PaymentData(card.replace('CA$', '').split(':'))
176 cardslist.append(carddata)
177
178 with Database() as db:
179 for card in cardslist:
180 try:
181 #Might want to check this SQL query, doesn't look right
182 db.execute('INSERT INTO PayPalMafia_cards(payment_id, cardnumber, cardexp, cardcvv, amount, currency, username, date, used, id, orderid, success) VALUES ({},{},"{}",{}, {}, "{}", "{}", "{}", {}, {}, {}, 0)'.format(randint(100000000, 999999999), card.cardnumber, '20'+card.cardexpyear+'-'+card.cardexpmon+'-00', card.cardcvv, int(card.amount), 'CAD', user['username'], datetime.utcnow().strftime('%Y-%m-%d'), 1, user, orderid))
183 self.jobqueue.put_nowait(card)
184 except Exception as e:
185 print(e)
186 db.commit()
187
188 update.message.reply_text(f'Your cards have been added to the Queue\n\nPlease use your order ID number to track your cashout: *{orderid}*\n Cashing out to email: *{resp[0]}*', reply_markup=reply_markup, parse_mode=ParseMode.MARKDOWN)
189 else:
190 keyboard = [[InlineKeyboardButton("Update PayPal Email", callback_data='enterppemail')],
191 [InlineKeyboardButton("Go to Settings", callback_data='settings')],
192 [InlineKeyboardButton("Return to dashboard", callback_data='dashboard')]]
193
194 reply_markup = InlineKeyboardMarkup(keyboard)
195 update.message.reply_text(f'You do not have a PayPal Email set to cashout, Please update your email and try again!', parse_mode=ParseMode.MARKDOWN, reply_markup=reply_markup)
196 return ConversationHandler.CARD_CASHOUT_RESPONSE
197
198
199 def cashoutstatuspage(self, update, context):
200 query = update.callback_query
201 query.edit_message_text("Enter your order ID:")
202 return ConversationHandler.CASHOUT_STATUS_RESPONSE
203
204
205 def cashoutstatusquery(self, update, context):
206 text, user = update.message.text, update.effective_user.id
207 resp = Database().execute(f"SELECT cardnumber, amount, success FROM PayPalMafia_cards WHERE id='{user} AND orderid = {text}';").fetchmany()
208 if resp != None:
209 text = 'Card Number | Amount | Success\n ------------- | ------------- | -------------'
210 for card in resp:
211 text.append(f'\n {card[0]} | {card[1]} | {bool(card[2])}')
212
213 keyboard = [[InlineKeyboardButton("Go to Settings", callback_data='settings')],
214 [InlineKeyboardButton("Return to dashboard", callback_data='dashboard')]]
215
216 reply_markup = InlineKeyboardMarkup(keyboard)
217 update.message.reply_text(text, reply_markup=reply_markup)
218 return ConversationHandler.START_RESPONSE
219 else:
220 update.message.reply_text(f'No Orders Found, Try again!')
221
222
223 def mycashoutpage(self, update, context):
224 query = update.callback_query
225
226 keyboard = [[InlineKeyboardButton("Check Cashout Status", callback_data='cashoutstatus')],
227 [InlineKeyboardButton("Today", callback_data='cashoutstoday')],
228 [InlineKeyboardButton("This Week", callback_data='cashoutsweek')],
229 [InlineKeyboardButton("This Month", callback_data='cashoutsmonth')],
230 [InlineKeyboardButton("Year-to-date", callback_data='cashoutsytd')],
231 [InlineKeyboardButton("Return to Cashier", callback_data='cashier')]
232 ]
233
234 reply_markup = InlineKeyboardMarkup(keyboard)
235
236 if query is not None:
237 query.edit_message_text("Choose your option:", reply_markup=reply_markup)
238 else:
239 update.message.reply_text("Choose your option", reply_markup=reply_markup)
240
241
242 def cashouttoday(self, update, context):
243 user = update.effective_user.id
244 resp = Database().execute(f"SELECT amount FROM PayPalMafia_cards WHERE id='{user}' AND date='{datetime.utcnow().strftime('%Y-%m-%d')}' AND used = 1 ;").fetchone()
245 if resp == None:
246 totalcashouttoday = 0
247 else:
248 totalcashouttoday = sum(filter(None, resp))
249
250 keyboard = [[telegram.InlineKeyboardButton("Return to My Cashouts", callback_data='mycashouts')],
251 [telegram.InlineKeyboardButton("Get list of unused cards", callback_data='unusedcards')]]
252
253 reply_markup = telegram.InlineKeyboardMarkup(keyboard)
254 query.edit_message_text(f'Total cashed out today: *${totalcashouttoday}*', parse_mode=telegram.ParseMode.MARKDOWN, reply_markup=reply_markup)
255
256
257 def cashoutweek(self, update, context):
258 user = update.effective_user.id
259 resp = Database().execute(f"SELECT amount FROM PayPalMafia_cards WHERE id='{user}' AND date > '{(datetime.now() - timedelta(days=7)).date().strftime('%Y-%m-%d')}' AND used = 1 ;").fetchone()
260 if resp == None:
261 totalcashouttoday = 0
262 else:
263 totalcashouttoday = sum(filter(None, resp))
264
265 keyboard = [[InlineKeyboardButton("Return to My Cashouts", callback_data='mycashouts')],
266 [InlineKeyboardButton("Get list of unused cards", callback_data='unusedcards')]]
267
268 reply_markup = InlineKeyboardMarkup(keyboard)
269 query.edit_message_text(f'Total cashed out this week: *${totalcashouttoday}*', parse_mode=telegram.ParseMode.MARKDOWN, reply_markup=reply_markup)
270
271
272 def cashoutmonth(self, update, context):
273 user = update.effective_user.id
274 resp = Database().execute(f"SELECT amount FROM PayPalMafia_cards WHERE id='{user}' AND date > '{(datetime.now() - relativedelta(months=-1)).date().strftime('%Y-%m-%d')}' AND used = 1 ;").fetchone()
275 if resp == None:
276 totalcashouttoday = 0
277 else:
278 totalcashouttoday = sum(filter(None, resp))
279
280 keyboard = [[InlineKeyboardButton("Return to My Cashouts", callback_data='mycashouts')],
281 [InlineKeyboardButton("Get list of unused cards", callback_data='unusedcards')]]
282
283 reply_markup = InlineKeyboardMarkup(keyboard)
284 query.edit_message_text(f'Total cashed out this month: *${totalcashouttoday}*', parse_mode=telegram.ParseMode.MARKDOWN, reply_markup=reply_markup)
285
286
287 def cashoutytd(self, update, context):
288 user = update.effective_user.id
289 resp = Database().execute(f"SELECT amount FROM PayPalMafia_cards WHERE id='{user}' AND date > '{(datetime.now() - timedelta(days=365)).date().strftime('%Y-%m-%d')}' AND used = 1 ;").fetchone()
290 if resp == None:
291 totalcashouttoday = 0
292 else:
293 totalcashouttoday = sum(filter(None, resp))
294
295 keyboard = [[InlineKeyboardButton("Return to My Cashouts", callback_data='mycashouts')],
296 [InlineKeyboardButton("Get list of unused cards", callback_data='unusedcards')]]
297
298 reply_markup = InlineKeyboardMarkup(keyboard)
299 query.edit_message_text(f'Total cashed out this month: *${totalcashouttoday}*', parse_mode=telegram.ParseMode.MARKDOWN, reply_markup=reply_markup)
300
301
302 def enterppemail(self, update, context):
303 query = update.callback_query
304 query.edit_message_text("Enter PayPal email:")
305
306
307 def changeppemail(self, update, context):
308 message = update.message.text
309
310 #Email validation code
311 regex = '^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$'
312
313 if(re.search(regex,message)):
314 with Database() as db:
315 db.execute(f"UPDATE PayPalMafia_users SET paypalemail = '{text}' WHERE id={user['id']};")
316 db.commit()
317
318 keyboard = [[InlineKeyboardButton("Dashboard", callback_data="dashboard")],
319 [InlineKeyboardButton("Settings", callback_data="settings")]]
320
321 reply_markup = InlineKeyboardMarkup(keyboard)
322
323 update.message.reply_text(f"Your PayPal cashout email has been changed to {message}!\nWhere would you like to go next?", reply_markup=reply_markup)
324
325 return ConversationHandler.START_RESPONSE
326 else:
327 update.message.reply_text("Invalid email provided. Please try again.")
328
329
330 def currency(self, update, context):
331 query = update.callback_query
332 query.edit_message_text("Unimplemented.")
333 time.sleep(5)
334 self.settings(update, context)
335
336
337 def unusedcards(self, update, context):
338 query = update.callback_query
339 query.edit_message_text("Unimplemented.")
340 time.sleep(5)
341 self.settings(update, context)
342
343
344 def main(self):
345 START_RESPONSE, SETUP, SETTINGS_RESPONSE, CASHIER_RESPONSE, CASHOUT_RESPONSE, CARD_CASHOUT_RESPONSE, CASHOUT_STATUS_RESPONSE, MY_CASHOUT_RESPONSE, AFTER_CASHOUT_RESPONSE, ENTER_EMAIL_RESPONSE = range(10)
346 ppm_conv_handler = ConversationHandler(
347 entry_points = [CommandHandler('start', self.start)],
348
349 states = {
350 START_RESPONSE : [CallbackQueryHandler(self.dashboard, pattern="dashboard"),
351 CallbackQueryHandler(self.settings, pattern="settings"),
352 CallbackQueryHandler(self.cashierpage, pattern="cashier")],
353
354 SETUP : [MessageHandler(Filters.text, self.setupuser)],
355
356 SETTINGS_RESPONSE : [CallbackQueryHandler(self.enterppemail, pattern="enterppemail"),
357 CallbackQueryHandler(self.currency, pattern="currency")],
358 CallbackQueryHandler(self.dashboard, use_pattern="dashboard")],
359
360 CASHIER_RESPONSE : [CallbackQueryHandler(self.mycashoutpage, use_pattern="mycashouts"),
361 CallbackQueryHandler(self.startcashouttask, use_pattern="cashout"),
362 CallbackQueryHandler(self.dashboard, use_pattern="dashboard")],
363
364 CASHOUT_RESPONSE : [MessageHandler(Filters.text, self.cashouttask)],
365
366 CARD_CASHOUT_RESPONSE : [CallbackQueryHandler(self.cashoutstatuspage, use_pattern="cashoutstatus"),
367 CallbackQueryHandler(self.dashboard, use_pattern="dashboard"),
368 CallbackQueryHandler(self.enterppemail, use_pattern="enterppemail"),
369 CallbackQueryHandler(self.settings, use_pattern="settings")],
370
371 CASHOUT_STATUS_RESPONSE : [MessageHandler(Filters.text, self.cashoutstatusquery)],
372
373 MY_CASHOUT_RESPONSE : [CallbackQueryHandler(self.cashouttoday, use_pattern="cashoutstoday"),
374 CallbackQueryHandler(self.cashoutweek, use_pattern="cashoutsweek"),
375 CallbackQueryHandler(self.cashoutmonth, use_pattern="cashoutsmonth"),
376 CallbackQueryHandler(self.cashoutytd, use_pattern="cashoutsytd"),
377 CallbackQueryHandler(self.cashierpage, use_pattern="cashier")],
378
379 AFTER_CASHOUT_RESPONSE : [CallbackQueryHandler(self.mycashoutpage, use_pattern="mycashouts"),
380 CallbackQuery(self.unused, use_pattern="unusedcards")],
381
382 ENTER_EMAIL_RESPONSE : [MessageHandler(Filters.text, self.changeppemail)]
383
384 },
385 fallbacks = [CommandHandler('cancel', self.cancel)]
386 )
387
388 updater = Updater(self.token, use_context=True)
389 dispatcher = updater.dispatcher
390
391 dispatcher.add_handler(ppm_conv_handler)
392 dispatcher.add_error_handler(self.error)
393
394 updater.start_polling()
395 updater.idle()
396
397
398class Database(object):
399 """sqlite3 database class that holds testers jobs"""
400 DB_LOCATION = "user.db"
401
402 def __init__(self):
403 """Initialize db class variables"""
404 self.connection = sqlite3.connect(Database.DB_LOCATION)
405 self.cur = self.connection.cursor()
406
407 def __enter__(self):
408 return self
409
410 def __exit__(self, ext_type, exc_value, traceback):
411 self.cur.close()
412 if isinstance(exc_value, Exception):
413 self.connection.rollback()
414 else:
415 self.connection.commit()
416 self.connection.close()
417
418 def close(self):
419 """close sqlite3 connection"""
420 self.connection.close()
421
422 def execute(self, new_data):
423 """execute a row of data to current cursor"""
424 self.cur.execute(new_data)
425 return self.cur
426
427 def executemany(self, many_new_data):
428 """add many new data to database in one go"""
429 self.create_table()
430 self.cur.executemany('REPLACE INTO jobs VALUES(?, ?, ?, ?)', many_new_data)
431
432 def create_table(self):
433 """create a database table if it does not exist already"""
434 self.cur.execute('''CREATE TABLE IF NOT EXISTS jobs(title text, \
435 job_id integer PRIMARY KEY,
436 company text,
437 age integer)''')
438
439 def commit(self):
440 """commit changes to database"""
441 self.connection.commit()