From a4b400648c3025856bedfeff21ca181ffbb1aa69 Mon Sep 17 00:00:00 2001 From: asdf Date: Sun, 15 Dec 2019 13:25:13 +1100 Subject: [PATCH] Menu flows support viewing posted details, display and linting fixes --- config.py | 1 + data.py | 13 ++--- linkulator | 145 ++++++++++++++++++++++++++++++----------------------- 3 files changed, 89 insertions(+), 70 deletions(-) diff --git a/config.py b/config.py index 57455b0..f660f62 100644 --- a/config.py +++ b/config.py @@ -26,6 +26,7 @@ class DefaultUser: datafile: Path = datadir / PATHS.datafile ignorefile: Path = datadir / PATHS.ignorefile settingsfile: Path = datadir / PATHS.settingsfile + lastlogin: float browser: str = "lynx" def save(self): diff --git a/data.py b/data.py index 1ac9d13..cf77811 100644 --- a/data.py +++ b/data.py @@ -128,8 +128,9 @@ class LinkData: """sort link_data by creation date""" self.link_data.sort(key=lambda x: x[2], reverse=True) - def add(self, record): - """Add a record to the data file, and to link_data""" + def add(self, record) -> int: + """Add a record to the data file, and to link_data. Returns a new post + ID, if record is a post, or -1""" if os.path.exists(config.USER.datafile): append_write = "a" # append if already exists else: @@ -145,15 +146,15 @@ class LinkData: ) ) + new_post_id = -1 if record.category: - record = record._replace( - ID_if_parent=max([record[0] for record in self.link_data if record[0]]) - + 1 - ) + new_post_id = max([record[0] for record in self.link_data if record[0]]) + 1 + record = record._replace(ID_if_parent=new_post_id) self.link_data.insert(0, list(record)) self.generate_category_data() else: self.link_data.insert(0, list(record)) + return new_post_id def generate_category_data(self): """generate categories list and category count from sorted link data""" diff --git a/linkulator b/linkulator index 4091485..ec5b7a9 100755 --- a/linkulator +++ b/linkulator @@ -7,7 +7,7 @@ import getpass import signal import subprocess import sys -import time +from time import time from urllib.parse import urlparse from datetime import datetime from shutil import which @@ -40,8 +40,8 @@ def print_categories(): def print_category_details(view_cat): """produces category detail data, prints it to the console. returns dict containing an index of threads""" - header = "\n\n{:>4s} {:<15s}{:<12s} #RESP {:<13s}".format( - "ID#", "DATE", "AUTHOR", "DESC" + header = "\n{}\n\n{:>4s} {:<15s}{:<12s} #RESP {:<13s}".format( + style_text(view_cat["name"].upper(), "bold"), "ID#", "DATE", "AUTHOR", "DESC" ) out = "" link_count = 0 @@ -50,14 +50,14 @@ def print_category_details(view_cat): for line in link_data: if line[4] == view_cat["name"]: link_count += 1 - thread_index[link_count] = str(line[0]) + thread_index[link_count] = line[0] parent_id = line[1] + "+" + str(line[2]) replies = [line for line in link_data if line[3] == parent_id] new_replies = len( [line for line in replies if line[2] >= config.USER.lastlogin] ) newmarker = "*" if new_replies or line[2] >= config.USER.lastlogin else "" - _dt = datetime.utcfromtimestamp(float(line[2])).strftime("%Y-%m-%d") + _dt = datetime.fromtimestamp(float(line[2])).strftime("%Y-%m-%d") out += "{:4d} {:<15s}{:<12s} [{:3d}] {:s}{}\n".format( link_count, _dt, line[1], len(replies), line[6], newmarker ) @@ -71,39 +71,56 @@ def print_category_details(view_cat): return thread_index -def print_thread_details(post_id): +def print_thread_details(post_id) -> tuple: """produces thread detail data, prints it to the console""" - parent_id = "" - url: str = "" + # get post data + parent_id: str = "" + post_url: str = "" for line in link_data: - if str(line[0]) == post_id: - parent_id = line[1] + "+" + str(line[2]) - parent_user = line[1] - parent_timestamp = line[2] - url = line[5] + if line[0] == post_id: + parent_id = "{}+{}".format(line[1], str(line[2])) + post_username = line[1] + post_datetime = datetime.fromtimestamp(float(line[2])).strftime("%c") + post_category = line[4] + post_url = line[5] + post_title = line[6] + # if post is not found, return empty string if parent_id == "": - print("Sorry, no thread found with that ID.") - return "" - for line in link_data: - if line[1] == parent_user and line[2] == parent_timestamp: - ftime = time.strftime( - "%b %d %Y", time.gmtime(float(parent_timestamp)) - ) ## UGGHH... - print("\n\n{:<15}: {}".format(style_text("Title", "bold"), line[6])) - print("{:<15}: {}".format(style_text("Link", "bold"), line[5])) - print("{:<15}: {}".format(style_text("User", "bold"), line[1])) - print("{:<15}: {}".format(style_text("Date", "bold"), ftime)) + raise ValueError("Sorry, no thread found with that ID.") - print("\n{}:\n".format(style_text("Replies", "underline"))) + # get replies data + replies = sorted([line for line in link_data if line[3] == parent_id]) - replies = [line for line in link_data if line[3] == parent_id] + # post detail view + print("\n\n{:<17}: {}".format(style_text("Title", "bold"), post_title)) + print("{:<17}: {}".format(style_text("Link", "bold"), post_url)) + print("{:<17}: {}".format(style_text("Category", "bold"), post_category)) + print("{:<17}: {}".format(style_text("User", "bold"), post_username)) + print("{:<17}: {}".format(style_text("Date", "bold"), post_datetime)) + + # post reply view if replies: + print("\n{}:\n".format(style_text("Replies", "underline"))) for line in replies: - print("{}: {}".format(style_text(line[1], "bold"), line[6])) + comment_author = line[1] + comment_date = datetime.fromtimestamp(float(line[2])).isoformat( + sep=" ", timespec="minutes" + ) + comment = line[6] + print( + " {} {}: {}".format( + comment_date, style_text(comment_author, "bold"), comment + ) + ) else: - print("No replies yet. Be the first!") - return parent_user, parent_timestamp, url + print("\nNo replies yet. Be the first!") + + # return data used by menu control + return parent_id, post_url + + +## CONTROLS def view_link_in_browser(url): @@ -128,7 +145,7 @@ def view_link_in_browser(url): subprocess.call([config.USER.browser, url]) -def reply(parent_user, parent_timestamp): +def reply(parent_id): """Prompt for reply, validate input, save validated input to disk and update link_data. Calls view_thread when complete.""" while True: @@ -144,8 +161,8 @@ def reply(parent_user, parent_timestamp): else: record = data.LinkDataRecord( username=getpass.getuser(), - timestamp=str(time.time()), - parent_id="{}+{}".format(parent_user, parent_timestamp), + timestamp=str(time()), + parent_id=parent_id, link_title_or_comment=comment, ) LinkData.add(record) @@ -185,7 +202,7 @@ def get_input(item: str) -> str: ) -def post_link(): +def post_link() -> int: """Handles the link posting process""" category_text = ( @@ -206,17 +223,17 @@ def post_link(): title = get_input("Title") except ValueError: print("Post cancelled") - return + return -1 record = data.LinkDataRecord( username=getpass.getuser(), - timestamp=str(time.time()), + timestamp=str(time()), category=category, link_URL=url, link_title_or_comment=title, ) - LinkData.add(record) + return LinkData.add(record) def search(keyword): @@ -241,9 +258,6 @@ def search(keyword): ## if next_step... -## CONTROLS - - def menu_view_categories(): """Displays list of categories, takes keyboard input and executes corresponding functions.""" @@ -259,14 +273,15 @@ def menu_view_categories(): if option == "q": return if option == "p": - post_link() + post_id = post_link() + if post_id >= 0: + menu_view_thread_details(post_id) continue - else: - try: - cat_index = categories[int(option) - 1] - menu_view_category_details(cat_index) - except (IndexError, ValueError): - print("Sorry, that category does not exist. Try again.") + try: + cat_index = categories[int(option) - 1] + menu_view_category_details(cat_index) + except (IndexError, ValueError): + print("Sorry, that category does not exist. Try again.") def menu_view_category_details(cat_index): @@ -290,15 +305,16 @@ def menu_view_category_details(cat_index): if option == "m": return if option == "p": - post_link() + post_id = post_link() + if post_id >= 0: + menu_view_thread_details(post_id) continue - else: - try: - link = thread_index[int(option)] - menu_view_thread_details(link) - except (KeyError, ValueError): - # Catch a Post ID that is not in the thread list or is not a number - print("{}\n\n".format(style_text("Invalid category ID/entry", "bold"))) + try: + post_id = thread_index[int(option)] + menu_view_thread_details(post_id) + except (KeyError, ValueError): + # Catch a Post ID that is not in the thread list or is not a number + print("{}\n\n".format(style_text("Invalid category ID/entry", "bold"))) def menu_view_thread_details(post_id): @@ -313,23 +329,24 @@ def menu_view_thread_details(post_id): ) while True: - parent_user, parent_timestamp, url = print_thread_details(post_id) + parent_id, post_url = print_thread_details(post_id) option = input(option_text).lower() if option == "m": return if option == "b": - view_link_in_browser(url) + view_link_in_browser(post_url) continue - elif option == "r": - reply(parent_user, parent_timestamp) + if option == "r": + reply(parent_id) continue - elif option == "p": - post_link() - continue - elif option == "q": + if option == "p": + post_id = post_link() + if post_id >= 0: + continue + break + if option == "q": graceful_exit() - else: - print("{}\n\n".format(style_text("Invalid entry", "bold"))) + print("{}\n\n".format(style_text("Invalid entry", "bold"))) ## GENERAL