· 6 years ago · Jan 08, 2020, 12:12 AM
1#!/usr/bin/env python3
2import sqlite3
3import sys
4import os
5from hashlib import *
6import time
7
8"""
9+---------------------------------------------------------------------------+
10|BITTODO-TBI v10.1x -s--v |
11|STABLE |
12|© Samuel Cheng 2019 |
13|License: GPL-3.0 |
14| ->gnu.org/licenses/gpl-3.0.en.html |
15| |
16|email extrasupermega@gmx.us for bug report! |
17| |
18|Requirements: |
19| 1. SQLite3 |
20| 2. sys |
21| 3. os |
22| 4. Hashlib |
23| 5.Time |
24+---------------------------------------------------------------------------+
25"""
26
27
28welcome = """
29WELCOME TO
30==> Bit TODO (Text-Based Interface)<== V5.9x-STABLE
31© Samuel Cheng 2019
32License: GPL-3.0 -> gnu.org/licenses/gpl-3.0.en.html
33Powered by SQLite3 for Python 3
34
35 __...--~~~~~-._ _.-~~~~~--...__
36 // `V' \\
37 // BIT | TODO \\
38 //__...--~~~~~~-._ | _.-~~~~~~--...__\\
39 //__.....----~~~~._\ | /_.~~~~----.....__\\
40====================\\\\|//====================
41 `---`
42
43email extrasupermega@gmx.us for bug report!
44SUB to my Youtube Channel [Mellifluous Meditations] PLS support me by clicking this link!
45http://gestyy.com/w6uivq
46
47----SQL INJECTION PROTECTION----
48----Password Protection----
49Changelog:
50 v7.5x ->
51 Changed to blake2b from md5
52 Added Changelog
53 v8.9x ->
54 Changed to hashchains
55 Minor bug fixes
56"""
57
58debug = False
59
60
61class sql:
62 exit_if = ["e", "exit"]
63 help_if = ["h", "help"]
64 createTable_bool = True
65 createTable = """
66CREATE TABLE ToDo (
67 Item varchar(255),
68 Done varchar(255),
69 User varchar(255),
70 Name varchar(255)
71);"""
72 insert = """
73INSERT INTO ToDo (Item, Done, User, Name)
74VALUES ('{item}', 'False', '{user}', '{name}');
75"""
76 delete = """
77DELETE FROM ToDo WHERE Item = "{item}" AND User = "{user}" AND Name = "{name}"
78"""
79 toggle_true = """
80UPDATE ToDo SET Done="False" WHERE Item = "{item}" AND User = "{user}" AND Name = '{name}'
81"""
82 toggle_false = """
83UPDATE ToDo SET Done="True" WHERE Item = "{item}" AND User = "{user}" AND Name = '{name}'
84"""
85 toggle_check = """
86SELECT Done FROM ToDo Where Item = "{item}" AND User = "{user}" AND Name = '{name}'
87"""
88 find_all_distinct = """
89SELECT DISTINCT Name FROM ToDo WHERE User = "{user}"
90"""
91 commands = ["exit", "add", "display", "delete", "toggle", "switchlist", "addlist", "deletelist", "displaylist", "debug"]
92 commands_help = ["Type in \"exit\" to exit!", "Type in \"add [item]\" to add item to database",
93 "Type in \"Display\" to display todo list!",
94 "Type in \"delete [item]\" to delete an item",
95 "Type in \"toggle [item]\" to toggle between DONE and NOT DONE",
96 "Type in \"switchlist\" to switch to an available TODO list!",
97 "Type in \"addlist [item]\" to add a TODO list!",
98 "Type in \"deletelist [item]\" to delete a list!",
99 "Type in \"displaylist\" to display all the available TODO lists for your user",
100 "Type in \"debug\" to toggle debug mode"]
101
102 database = 'ToDo.db'
103
104 def __init__(self, *args, **kwargs):
105 # init connection to database
106 self.connection = sqlite3.connect(sql.database)
107 self.databasename = "main"
108 printdebug("[LOG] Connected to SQLite")
109
110 # init cursor for database
111 self.crsr = self.connection.cursor()
112 printdebug("[LOG] SQLite cursor INITIALIZED")
113
114 # if createtable_bool is true, create table
115 if sql.createTable_bool:
116 try:
117 self.crsr.execute(sql.createTable)
118
119 except:
120 printdebug("Database already exists!\nsetting createTable_bool to False")
121 sql.createTable_bool = False
122 pass
123
124 @staticmethod
125 def parse_action(self, first):
126 if first.__len__() == 0:
127 print("Enter an action followed by a string.\nOr an action\ne.g. exit, help")
128 main.input(main)
129 # Check exit
130 self.parse = first[0].lower()
131 for element in sql.exit_if:
132 if element == self.parse:
133 print("Exiting!")
134 time.sleep(1)
135 sys.exit()
136
137 for element in sql.help_if:
138 if element == self.parse:
139 print("HELP!")
140 for i in range(sql.commands.__len__()):
141 print(sql.commands[i], sql.commands_help[i], sep="\n")
142 main.input(main)
143 valid_command = False
144 for element in sql.commands:
145 if element == self.parse:
146 valid_command = True
147 continue
148 if not valid_command:
149 print("Not a valid command!\nType [help] for list of commands")
150
151 @staticmethod
152 def e(self):
153
154 # exec gonna be in list format
155 sql.mainparse(self)
156
157 # commit changes
158 self.connection.commit()
159 printdebug("[LOG] CHANGE to database COMMITED")
160
161 @staticmethod
162 def add_func(self):
163 self.crsr.execute(sql.insert.format(item=command.item, user=self.username, name=self.databasename))
164 sql.display_func(self)
165
166 @staticmethod
167 def display_func(self):
168 with self.connection:
169 self.crsr.execute(
170 """SELECT * FROM ToDo WHERE User = '{user}' AND Name = '{name}'""".format(user=self.username,
171 name=self.databasename))
172 self.display_database = self.crsr.fetchall()
173 print("GETTING data from \"{name}\"".format(name=self.databasename))
174 print("\n\nITEM, DONE_STATUS")
175 # TODO enumerate self.display_database
176 for element in self.display_database:
177 for i, x in enumerate(element):
178 if i == 0:
179 print(x, end=", ")
180 elif i == 1:
181 print(x)
182 print()
183
184 @staticmethod
185 def delete_func(self):
186
187 self.crsr.execute(sql.delete.format(item=command.item, user=self.username, name=self.databasename))
188 print("DELETED {}!".format(command.item))
189 sql.display_func(self)
190
191 @staticmethod
192 def toggle_func(self):
193 if not command.item:
194 print("Type in an object to toggle!")
195 main.input(main)
196 try:
197 for element in self.crsr.execute(
198 sql.toggle_check.format(item=command.item, user=self.username, name=self.databasename)).fetchone():
199 self.toggle_check_var = element
200 except TypeError:
201 print("There is no such item in the database!")
202 main.input(main)
203
204 if self.toggle_check_var == "True":
205 self.crsr.execute(sql.toggle_true.format(item=command.item, user=self.username, name=self.databasename))
206
207 else:
208 self.crsr.execute(sql.toggle_false.format(item=command.item, user=self.username, name=self.databasename))
209 sql.display_func(self)
210
211 @staticmethod
212 def switch_func(self):
213 all_todo = []
214 foundindex = ""
215 with self.connection:
216 self.crsr.execute(sql.find_all_distinct.format(user=self.username))
217 self.display_database = self.crsr.fetchall()
218 print("Here are the available TODO lists:\n")
219 for element in self.display_database:
220 print(element[0])
221 all_todo.append(element[0])
222
223 print()
224 raw = input("Which TODO list do you want to switch to?\n>>> ").lower()
225
226 # Same search engine
227 found = False
228 for element in all_todo:
229 if element.lower() == raw:
230 found = True
231 foundindex = element
232 if not found:
233 print("TODO list is not found!\n(Tip: Make a new TODO list)")
234 main.input(main)
235 elif found:
236 self.databasename = foundindex
237 print("Switched TODO list!\n")
238 else:
239 print("Bit TODO has run into an unexpected problem.\nError Code: [switch_func]")
240
241 @staticmethod
242 def addtodo_func(self):
243 if not command.item:
244 print("Cannot make the name of a TODO list empty! Try again with \"addlist [item]\"!\n")
245 main.input(main)
246 with self.connection:
247 self.crsr.execute('SELECT DISTINCT Name FROM Todo WHERE User = "{user}"'.format(user=self.username))
248 self.display_database = self.crsr.fetchall()
249 for element in self.display_database:
250 if element[0] == command.item:
251 print("Cannot create a TODO list that already exists!\n")
252 main.input(main)
253 self.databasename = command.item
254 print("Switching to {list}!\n".format(list=self.databasename))
255 print("[WARNING!]:\nIf this TODO list is empty and TODO list is switched, this TODO list will be erased!\n")
256
257 @staticmethod
258 def deletelist_func(self):
259 all_todo = []
260 if not command.item:
261 print("Cannot make the name of a TODO list empty! Try again with \"deletelist [item]\"!\n")
262 main.input(main)
263
264 with self.connection:
265 self.crsr.execute(sql.find_all_distinct.format(user=self.username))
266 self.display_database = self.crsr.fetchall()
267 print("Here are the available TODO lists:\n")
268 for element in self.display_database:
269 print(element[0])
270 all_todo.append(element[0])
271
272 if command.item == "main":
273 print("Default list cannot be deleted!\n")
274 main.input(main)
275
276 for list in all_todo:
277 if list == command.item:
278 print("Deleting TODO list...")
279 self.crsr.execute(
280 """DELETE FROM ToDo WHERE Name = "{name}" AND User = '{user}'""".format(name=self.databasename,
281 user=self.username))
282 print("TODO list DELETED!\n")
283 if self.databasename == list:
284 self.databasename = "main"
285 print("Switching TODO list to default (main)\n")
286
287 @staticmethod
288 def defineusername(self, user):
289 self.username = user
290
291 @staticmethod
292 def debug_func(self):
293 if debug:
294 debug = False
295 print("Debug [OFF]")
296 else:
297 debug = True
298 print("Debug [ON]")
299
300
301
302 @staticmethod
303 def mainparse(self):
304 if command.action == "add":
305 sql.add_func(self)
306
307 if command.action == "display":
308 sql.display_func(self)
309
310 if command.action == "delete":
311 sql.delete_func(self)
312
313 if command.action == "toggle":
314 sql.toggle_func(self)
315
316 if command.action == "switchlist":
317 sql.switch_func(self)
318
319 if command.action == "addlist":
320 sql.addtodo_func(self)
321
322 if command.action == "deletelist":
323 sql.deletelist_func(self)
324
325 if command.action == "debug":
326 sql.debug_func(self)
327
328
329# TODO change tools to command
330class command:
331
332 def __init__(self):
333 self.action = ""
334 self.item = ""
335
336 @staticmethod
337 def usr_input(self, raw):
338 command()
339 self.raw = raw.split()
340 sql.parse_action(sql, self.raw)
341 self.action = self.raw[0].lower()
342 self.item = ' '.join(self.raw[1:])
343 sql.e(sql)
344
345
346class setup:
347 text = """
348+------------------+
349|Setup for BIT TODO|
350+------------------+
351"""
352 success = """
353+----------------+
354|Setup Completed!|
355+----------------+
356"""
357 createTable = """
358CREATE TABLE Secure (
359 Username varchar(255),
360 Password varchar(255)
361);"""
362 insert = """
363INSERT INTO Secure (Username, Password)
364VALUES ('{0}', '{1}');
365"""
366 temp = []
367 userinfo = []
368
369 def __init__(self):
370 print(setup.text)
371 print("Running from: {}".format(os.path.dirname(os.path.realpath(__file__))))
372 setup.sql(self)
373 sql.databasename = "main"
374 # setup.database(self)
375 # setup.createtable(self)
376 setup.loginorsignup(self)
377 print(setup.success)
378 os.system("clear")
379
380 @staticmethod
381 def sql(self):
382 # If database does not exist, Create new database
383 self.connection = sqlite3.connect("Users.db")
384 self.crsr = self.connection.cursor()
385 try:
386 self.crsr.execute(setup.createTable)
387 printdebug("[LOG] Users.db does not exist!")
388 except:
389 printdebug("[LOG] Users.db exists!")
390 pass
391 with self.connection:
392 self.crsr.execute("SELECT * FROM Secure")
393 self.display_database = self.crsr.fetchall()
394
395 @staticmethod
396 def loginorsignup(self):
397 raw = input("[LOGIN] or [SIGN UP]?\n").lower()
398 if raw == "login":
399 setup.login(self)
400 elif raw == "sign up":
401 setup.signup(self)
402 else:
403 print("Not a valid option!\n")
404 setup.loginorsignup(self)
405
406 @staticmethod
407 def login(self):
408 user = input("Username: ")
409 password = input("Password: ")
410 founduser = False
411
412 #blake2b -> md5 -> sha1
413 first = str(blake2b(password.encode()).hexdigest())
414 second = str(md5(first.encode()).hexdigest())
415 third = sha1(second.encode()).hexdigest()
416
417 for element in self.display_database:
418 if element[0] == user and element[1] == third:
419 print("Logged in as {}".format(element[0]))
420 founduser = True
421 sql.defineusername(sql, user)
422 return
423 if not founduser:
424 print("Either Username or Password is incorrect! Try again.")
425 setup.loginorsignup(self)
426
427 @staticmethod
428 def signup(self):
429 print("Sign up as new USER")
430 user = input("Username: ")
431 password = input("Password: ")
432 found = False
433 with self.connection:
434 # Yes, distinct is a bit extra
435 self.crsr.execute("SELECT DISTINCT Username FROM Secure")
436 self.display_database = self.crsr.fetchall()
437 # Check if recurring usernames
438 for element in self.display_database:
439 if element[0] == user:
440 found = True
441 if found:
442 print("Username is not available!\n")
443 self.loginorsignup(self)
444 print("Username Available!\n")
445
446 #blake2b -> md5 -> sha1
447 first = str(blake2b(password.encode()).hexdigest())
448 second = str(md5(first.encode()).hexdigest())
449 third = sha1(second.encode()).hexdigest()
450
451 self.crsr.execute(setup.insert.format(user, third))
452 print("Signed up!\nRedirecting you back to LOGIN OR SIGNUP\n")
453 self.connection.commit()
454 setup.loginorsignup(self)
455
456
457class main(object):
458
459 def __init__(self):
460 setup()
461 print(welcome)
462 # Faster init sql
463 sql.__init__(sql)
464 while True:
465 main.input(self)
466
467 @staticmethod
468 def input(self):
469 command.usr_input(command, input(">>>"))
470
471def printdebug(text):
472 if debug:
473 print(text)
474
475if __name__ == "__main__":
476 main()