You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
92 lines
3.4 KiB
Python
92 lines
3.4 KiB
Python
1 year ago
|
#!/usr/bin/env python3
|
||
|
#import curses
|
||
|
import curses
|
||
|
import requests
|
||
|
from bs4 import BeautifulSoup
|
||
|
|
||
|
def main(stdscr):
|
||
|
stdscr.clear()
|
||
|
stdscr.addstr("Hacker News Browsing\n")
|
||
|
stdscr.refresh()
|
||
|
|
||
|
# Initialize variables
|
||
|
stories = []
|
||
|
story_index = 0
|
||
|
search_term = ""
|
||
|
author_name = ""
|
||
|
|
||
|
while True:
|
||
|
# Fetch stories from HN API
|
||
|
if not stories:
|
||
|
url = "https://hacker-news.firebaseio.com/v0/topstories.json"
|
||
|
r = requests.get(url)
|
||
|
data = r.json()
|
||
|
stories = [story for story in data]
|
||
|
|
||
|
# Display current story title
|
||
|
story_id = stories[story_index]
|
||
|
url = f"https://hacker-news.firebaseio.com/v0/item/{story_id}.json"
|
||
|
r = requests.get(url)
|
||
|
data = r.json()
|
||
|
stdscr.move(1, 0) # Move cursor back up top of screen
|
||
|
stdscr.clrtobot() # Clear entire screen (including status bar)
|
||
|
stdscr.addstr(f"\nTitle: {data['title']}\n")
|
||
|
|
||
|
# Display current story score
|
||
|
stdscr.addstr(f"Score: {data['score']} points | ")
|
||
|
|
||
|
# Display current story URL
|
||
|
stdscr.addstr(f"URL: https://news.ycombinator.com/item?id={data['id']}")
|
||
|
|
||
|
# Display current story author name
|
||
|
stdscr.addstr("\nAuthor: ")
|
||
|
if data["by"] == None:
|
||
|
stdscr.addstr("<Unknown>")
|
||
|
else:
|
||
|
stdscr.addstr(data["by"])
|
||
|
|
||
|
# Display current story comments count
|
||
|
stdscr.addstr(f"\nComments: {len(data['kids']) if 'kids' in data else 0} | ")
|
||
|
|
||
|
# Display current story time ago string
|
||
|
soup = BeautifulSoup(requests.get(f"https://news.ycombinator.com/item?id={data['id']}").text, "html.parser")
|
||
|
timeago = soup.find("span", {"class": "age"} )["title"].replace(",","")
|
||
|
stdscr.addstr(f"{timeago}\n")
|
||
|
|
||
|
# Display search and author prompts on bottom row
|
||
|
stdscr.addstr(3, 0, "\x1b[6 q", curses.A_REVERSE + curses.A_BOLD) # Enable reverse video mode for highlighted characters
|
||
|
stdscr.addstr(4, 0, f"Search: {search_term}", curses.color_pair(2)) # Set color pair to green for search term
|
||
|
stdscr.addstr(5, 0, f"Author: {author_name}", curses.color_pair(3)) # Set color pair to blue for author name
|
||
|
|
||
|
# Refresh screen
|
||
|
stdscr.refresh()
|
||
|
|
||
|
# Wait for user input
|
||
|
key = stdscr.getch()
|
||
|
|
||
|
# Process input
|
||
|
if key == ord('q'):
|
||
|
break
|
||
|
elif key == curses.KEY_UP:
|
||
|
story_index -= 1
|
||
|
if story_index < 0:
|
||
|
story_index = len(stories)-1
|
||
|
elif key == curses.KEY_DOWN:
|
||
|
story_index += 1
|
||
|
if story_index >= len(stories):
|
||
|
story_index = 0
|
||
|
elif key == curses.KEY_LEFT:
|
||
|
pass # TODO: Implement previous page navigation
|
||
|
elif key == curses.KEY_RIGHT:
|
||
|
pass # TODO: Implement next page navigation
|
||
|
#elif key == ord('/') or key == ord('?'):
|
||
|
# search_prompt(stdscr)
|
||
|
#elif key == ord('a') or key == ord('A'):
|
||
|
# author_prompt(stdscr)
|
||
|
|
||
|
# Update colors for selected item in list
|
||
|
stdscr.addstr(1+story_index, 0, chr(27)+chr(91)+"7"+chr(27)+chr(91)+"m", curses.color_pair(1)) # Highlight selected item with yellow background
|
||
|
stdscr.addstr(1+(story_index+1)%len(stories), 0, chr(27)+chr(91)+"4"+chr(27)+chr(91)+"m", curses.color_pair(1)) # Reset background of all unselected items
|
||
|
|
||
|
curses.wrapper(main)
|