From acb98060b39068bf62721f6a5031c3b3efff65f7 Mon Sep 17 00:00:00 2001 From: Alex Lardner Date: Fri, 31 Jul 2026 01:06:49 -0700 Subject: [PATCH] initial commit --- .gitignore | 1 + blahblah/__init__.py | 0 blahblah/__pycache__/__init__.cpython-314.pyc | Bin 0 -> 143 bytes blahblah/__pycache__/bbdb.cpython-314.pyc | Bin 0 -> 3214 bytes blahblah/__pycache__/db.cpython-314.pyc | Bin 0 -> 2268 bytes blahblah/__pycache__/main.cpython-314.pyc | Bin 0 -> 6468 bytes blahblah/bbdb.py | 62 +++++++ blahblah/main.py | 155 ++++++++++++++++++ run.sh | 3 + 9 files changed, 221 insertions(+) create mode 100644 .gitignore create mode 100644 blahblah/__init__.py create mode 100644 blahblah/__pycache__/__init__.cpython-314.pyc create mode 100644 blahblah/__pycache__/bbdb.cpython-314.pyc create mode 100644 blahblah/__pycache__/db.cpython-314.pyc create mode 100644 blahblah/__pycache__/main.cpython-314.pyc create mode 100644 blahblah/bbdb.py create mode 100644 blahblah/main.py create mode 100755 run.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..98e6ef6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.db diff --git a/blahblah/__init__.py b/blahblah/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/blahblah/__pycache__/__init__.cpython-314.pyc b/blahblah/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9754ddf0ac9306021864dbdd2ddca80c3a81abdc GIT binary patch literal 143 zcmdPq58 PL5xq#jEsy$%s>_Zb6_6S literal 0 HcmV?d00001 diff --git a/blahblah/__pycache__/bbdb.cpython-314.pyc b/blahblah/__pycache__/bbdb.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..41f01daf551f806ba38b961a214b4d7300725584 GIT binary patch literal 3214 zcmc&$OK%fb6u$GY$B)FgX=w_H@PrgALn0!SAXSut@)%l^#Bs-t0|F5__JkOXJ?@=} zcu1&5LWPt?+Nx5!=%U-~SoBwP6_i$3Bcv|6XxRlq#J1;L&-f9d2(?1JnmKdk%zb|M zJKx;FNN0#Z`D@O&Uhxs~C%$-vcb)Bv;8e*~qHzgg*PootX?!=ac})N-Xks_feBH!| z+M?!%h)KC+Xkmfu3(Inls6|Y z0M9;>C8KWZ3YXAI+ju8%-Hy}Dksj% z$=QsoUQDDjX}Mxrwj~cVs$z>`K~5wy>ZhtEr?kY(n085?QZEg))v=4Vq01TdVx~R5 zXclgv`Le^qYEq#nv5v z-Yk`hw!%A7VR2!pXy^`KShNt+xa^!9UN%emaL&llLRqK76>46G=GO3{kz2;Q#aS#Y zo~Yb%0>yIC9yiQuGz@*P4$3A`aGL}6F)<`E+r54;kJf5T*Nf1F6BRV{(JHbX9is(@! zx#FWZcgM#%cSP)*9>9pmYU6_A@whBglmSO7>o-zBX?hUe-htbi0R!6^>Ut9Dc^v9_ z5{f+z#Wq8I)rqI!$OCKb&gz|qU;g~w?+1=;hU3*qcc*IswHAzgQ`iXfyz~h^|5m`= z@2{q42lU92-Ai}`kZtvcY^*G~%71i^kOIVd$>-cMr*TaI7>49r=bvF4$5$*D^qcD( zjl!G4IsPS+mU6a*9UrYPsAFLvS1y}2ptZ0-d*Q=jxUF}=RLLtMa)+Oz`QBoW`rO%DL`FU? zpVww*TrSOjrfMn*(I-F~Me$Qyha+e}l`u7LEG*^nwn=Y+AgoZ!q>L|4U`e<0%Vt?u z1V$Qqh&9402m!FfCCN42W+dr{D1-A9I6#tvy+2(3_HuRnUa}VISW{M&hlACLnke0$ zx;wQI9euR&X!$qsTrC_~JF|M`;n@xGP?HSM11mTZ1N=HT{~hqA?(YS+mzxa8!M%W- z)h0p4$1gSWQJz%O6OdMjC_REEh6XdvMKEU=3day+OpMo23j=CnhJnCYG!C`<;I`0d zM=spCc6#;n#`_bS;mIfAnaAOo&G77oINOBkU*`?&hS4bQ7|gE+hi_&I%ME6Z!G~=x zL3~{FIRW!iKYQ$xAk)ySiW=xm58l0^?WQ%^Pq9HMA;}f~_K``THvD+^Cic1HI^QC6 ze3P^FADWAMsGu9Vtuw+7!h~>n7Ghr|4Y3*kv3d}A3rh87h!5eEUPFAO1#!#>ub^bJ z4A~#?`MwdpMM&NZ@xi&&Bp!7t>{ydlGr)U1s4y9k+f^k=kHbt_wSsm*z|{(m^(z(p zQ)RFhdICPPweEud6vBVte}jJnrbP$Pbbx6)g}hCykH3aBJN&&N)JT_hs6%zA$MFx3 zhcH~$ZlaIYf}IZ{dm^m_>yj3MX6!V_&H%I@Us0tfCJ);}*86%Lt-7`a&Xml;ilLvS wI4BB$h5NiEa2)ps`QU}v!9`y5N?dfO3x2jQB0QJkb^;(PI}tFi&@k-(0YIc2`2YX_ literal 0 HcmV?d00001 diff --git a/blahblah/__pycache__/db.cpython-314.pyc b/blahblah/__pycache__/db.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..03bc9c813b7e9972b1af30690037aced56a6ffab GIT binary patch literal 2268 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 literal 0 HcmV?d00001 diff --git a/blahblah/bbdb.py b/blahblah/bbdb.py new file mode 100644 index 0000000..bac476b --- /dev/null +++ b/blahblah/bbdb.py @@ -0,0 +1,62 @@ +import sqlite3, datetime + +def initBlog(db_file): + db = sqlite3.connect(db_file) + db.execute(""" + CREATE TABLE IF NOT EXISTS posts ( + id INTEGER PRIMARY KEY, + title TEXT, + body TEXT NOT NULL, + timestamp INTEGER + ) + """) + + db.commit() + return db + +def newPost(db, title, body): + now = datetime.datetime.now() + time = int(now.timestamp() * 1000) + db.execute( + "INSERT INTO posts (title, body, timestamp) VALUES (?, ?, ?)", + (title, body, time) + ) + db.commit() + +def getPost(db, index: int): + db.row_factory = sqlite3.Row + cur = db.cursor() + cur.execute("SELECT * FROM posts WHERE id = (?)", (index,)) + return cur.fetchone() + + +def getAllPosts(db): + db.row_factory = sqlite3.Row + return db.execute("SELECT * FROM posts ORDER BY timestamp DESC").fetchall() + +def deletePost(db, index: int): + db.execute( + "DELETE FROM posts WHERE id = ?", + (index,) + ) + db.commit() + +def updateTitle(db, index: int, title): + db.execute( + "UPDATE posts SET title = (?) WHERE id = (?)", + (title, index,) + ) + db.commit() + +def updateBody(db, index: int, body): + db.execute( + "UPDATE posts SET body = (?) WHERE id = (?)", + (body, index,) + ) + db.commit() + +#if __name__ == "__main__": + #db = initBlog("blog.db") + + #db.close() + diff --git a/blahblah/main.py b/blahblah/main.py new file mode 100644 index 0000000..89b8e55 --- /dev/null +++ b/blahblah/main.py @@ -0,0 +1,155 @@ +from blahblah import bbdb +import tempfile +import subprocess +import os + +def mainMenu(): + print(""" + _ _ _ _ _ _ + | |__ | | __ _| |__ | |__ | | __ _| |__ + | '_ \\| |/ _` | '_ \\| '_ \\| |/ _` | '_ \\ + | |_) | | (_| | | | | |_) | | (_| | | | | + |_.__/|_|\\__,_|_| |_|_.__/|_|\\__,_|_| |_| + + 1. [N]ew Post + 2. [E]dit Post + 3. [D]elete Post + 4. [L]ist Posts + + 5. [G]enerate HTML + + 6. [Q]uit + """) + choice = input("Choose an option: ") + return choice + +def writeNew(db): + print(""" + + Write New Post + + 1. [N]ew Micropost + 2. [L]oad Post From File + """) + + choice = input("Choose an option: ") + + if choice == "n" or choice == "N" or choice == "1": + post = input("Enter your post: ") + print('You entered: "' + post + '"') + confirmPost = input("Publish this micropost (Y/N)? ") + if confirmPost == 'y' or confirmPost == 'Y': + bbdb.newPost(db, None, post) + +def editPost(db): + try: + postID = int(input("Enter the numerical ID of the post to edit or [Q]uit: ")) + except ValueError: + print("Cancelled edit.") + return + + try: + post = bbdb.getPost(db, postID) + except: + print("Error finding post.") + return + else: + print(post["id"], post["title"]) + print(post["body"]) + + print(""" + + 1. Edit [T]itle + 2. Edit [B]ody + + """) + + repeat = True + + while (repeat): + choice = input("Choose which field to edit or [Q]uit: ") + if choice == 't' or choice == 'T' or choice == "1": + newTitle = input("Enter a new title: ") + print('Your new title is "' + newTitle + '"') + confirmEdit = input("Publish this edited title [Y/N]? ") + if confirmEdit == 'y' or confirmEdit == 'Y': + repeat = False + try: + bbdb.updateTitle(db, postID, newTitle) + except: + print("Error updating title.") + else: + print("Updated title.") + elif choice == 'b' or choice == 'B' or choice == "2": + editor = os.environ.get("EDITOR", os.environ.get("VISUAL", "vi")) + + with tempfile.NamedTemporaryFile(suffix=".tmp", mode="w+", delete=False) as tf: + tf.write(post["body"]) + path = tf.name + + try: + subprocess.call([editor, path]) + with open(path, "r") as f: + newBody = f.read() + finally: + os.unlink(path) + + print('Your new body text is:\n\n' + newBody + "\n") + confirmEdit = input("Publish this edited post [Y/N]? ") + if confirmEdit == 'y' or confirmEdit == 'Y': + repeat = False + try: + bbdb.updateBody(db, postID, newBody) + except: + print("Error updating post body.") + else: + print("Updated post body.") + + elif choice == 'q' or choice == 'Q': + repeat = False + + +def listPosts(db): + for p in bbdb.getAllPosts(db): + print("***") + print(p["id"], p["title"]) + print(p["body"]) + print("\n") + +def confirmDelete(db): + try: + post = int(input("Enter the ID of the post to PERMANENTLY DELETE or [Q]uit: ")) + except ValueError: + print("Cancelled delete.") + return + + try: + bbdb.deletePost(db, post) + except: + print(post) + print("Error deleting post") + else: + print("Deleted post ", post) + +if __name__ == "__main__": + db = bbdb.initBlog("blog.db") + + running = True; + foo = 0; + + while(running): + choice = mainMenu() + + if choice == 'q' or choice == 'Q' or choice == "6": + running = False + elif choice == 'n' or choice == 'N' or choice == "1": + writeNew(db) + elif choice == 'e' or choice == 'E' or choice == "2": + editPost(db) + elif choice == 'd' or choice == 'D' or choice == "3": + confirmDelete(db) + elif choice == 'l' or choice == 'L' or choice == "4": + listPosts(db) + + db.close() + diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..5f52513 --- /dev/null +++ b/run.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +python3 -m blahblah.main