123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- #! /usr/bin/python3
- import curses
- from html.parser import HTMLParser
- from mastodon import Mastodon
-
- def initColours():
- # 0: White on black
- curses.init_pair(1, 4, 0) # 1: Blue on black
- curses.init_pair(2, 1, 0) # 2: Red on black
- curses.init_pair(3, 6, 0) # 3: Cyan on black
- curses.init_pair(4, 2, 0) # 4: Green on black
-
- def newLine(ncwin, lines=1):
- cy, cx = ncwin.getyx()
- # my, mx = ncwin.getmaxyx()
- try:
- ncwin.move(cy + lines, 0)
- except curses.error:
- pass
-
- def bump(win):
- my, mx = win.getmaxyx()
- cy, cx = win.getyx()
- if cx < mx and cx != 0:
- try:
- win.move(cy, cx + 1)
- except curses.error:
- pass
-
- def typeset(text, win, attr, colour):
- my, mx = win.getmaxyx()
- line = 0
- position = 0
- strlen = len(text)
- while position < (strlen):
- cy, cx = win.getyx()
- if cx == mx:
- if cy == my:
- raise curses.error("Out of space")
- rem = (mx - cx) + 0
- nsp = text.find(' ', position)
- if (strlen - position <= rem):
- win.addnstr(text[position:], rem,
- attr | curses.color_pair(colour))
- position = strlen
- elif (nsp == -1 or nsp - position > rem): # and not strlen - position <= rem:
- if cx == 0:
- win.addnstr(text[position:], rem, attr |
- curses.color_pair(colour))
- position = position + rem
- else:
- newLine(win)
- else:
- win.addnstr(text[position:], nsp - position,
- attr | curses.color_pair(colour))
- position = max(nsp, 0) + 1
- bump(win)
-
- def printPost(win, post, parser):
- # win.addstr(post["account"]["acct"], curses.A_BOLD)
- typeset("@{}".format(post["account"]["acct"]), win, curses.A_BOLD, 0)
- if (post["reblog"] is not None):
- # win.addstr(" boosted ")
- typeset(" boosted ", win, 0, 0)
- # win.addstr(post["reblog"]["account"]["acct"], curses.A_BOLD)
- typeset("@{}".format(post["reblog"]["account"]["acct"]), win,
- curses.A_BOLD, 0)
- # win.addstr(":")
- typeset(":", win, 0, 0)
- newLine(win)
- if (post["spoiler_text"] != ""):
- # win.addstr(post["spoiler_text"], curses.A_UNDERLINE)
- typeset(post["spoiler_text"], win, curses.A_UNDERLINE, 0)
- newLine(win)
- parser.feed(post["content"])
- if parser.openp:
- newLine(win)
-
- for att in post["media_attachments"]:
- # typeset("[IMG: {}, <{}>]".format(att["alt"], att["src"]))
- typeset("[IMG: {}]".format(att["description"] if
- att["description"] is not None
- else "(Alt text missing)"),
- win, 0, 4)
- newLine(win)
-
- if (post["reblog"] is not None):
- for att in post["reblog"]["media_attachments"]:
- # typeset("[IMG: {}, <{}>]".format(att["alt"], att["src"]))
- typeset("[IMG: {}]".format(att["description"] if
- att["description"] is not None
- else "(Alt text missing)"),
- win, 0, 4)
- newLine(win)
-
- botstring = "{} @ {} UTC".format(post["visibility"],
- post["created_at"
- ].strftime(
- "%Y-%m-%d %H:%M:%S"))
- cy, cx = win.getyx()
- my, mx = win.getmaxyx()
- # win.addstr(cy, mx - len(botstring), botstring, curses.A_UNDERLINE)
- win.move(cy, mx - len(botstring))
- typeset(botstring, win, curses.A_UNDERLINE, 0)
-
- newLine(win, 1)
-
- def printAtLevel(stdscr, col1, col2, posts, parser, level):
- col1.clear()
- col2.clear()
- col1.move(0, 0)
- col2.move(0, 0)
- printPost(col1, posts[level], parser)
- newLine(col1)
- printPost(col1, posts[(level + 1) % len(posts)], parser)
- try:
- col2.addstr(str(posts[level]["content"]))
- col2.addstr(str(posts[level]["media_attachments"]))
- col2.addstr(str(posts[level].keys()))
- except curses.error:
- pass
- stdscr.noutrefresh()
- col1.noutrefresh()
- col2.noutrefresh()
- curses.doupdate()
-
- class PostParser(HTMLParser):
- def __init__(self, ncwin, defncatt):
- HTMLParser.__init__(self)
- self.win = ncwin
- self.defncatt = defncatt
- self.curatt = defncatt
- self.openp = False
- self.colour = 0
- self.colstack = []
-
- def handle_starttag(self, tag, attrs):
- if tag == 'p':
- self.curatt = self.defncatt
- self.colstack = []
- self.colour = 0
- # newLine(self.win)
- elif tag == 'strong' or tag == 'b':
- self.curatt = self.curatt ^ curses.A_REVERSE
- elif tag == 'em' or tag == 'i':
- self.curatt = self.curatt ^ curses.A_BOLD
- elif tag == 'br':
- newLine(self.win)
- elif tag == 'a':
- self.colstack.append(self.colour)
- self.colour = 1
- elif tag == 'code':
- self.colstack.append(self.colour)
- self.colour = 3
- elif tag == 'img':
- typeset("[IMG: {}, <{}>]".format(att["alt"], att["src"]), self.win,
- 0, 4)
-
-
- def handle_endtag(self, tag):
- if tag == 'p':
- newLine(self.win, 2)
- self.openp = False
- elif tag == 'strong' or tag == 'b':
- self.curatt = self.curatt ^ curses.A_REVERSE
- elif tag == 'em' or tag == 'i':
- self.curatt = self.curatt ^ curses.A_BOLD
- elif tag == 'a':
- self.colour = self.colstack.pop()
- elif tag == 'code':
- self.colour = self.colstack.pop()
-
- def handle_data(self, data):
- try:
- # self.win.addstr(data, self.curatt | curses.color_pair(self.colour))
- typeset(data, self.win, self.curatt, self.colour)
- except curses.error:
- pass
- self.openp = True
-
-
- # print(mastodon.timeline()[0]["content"])
-
-
- def main(stdscr):
- initColours()
- mastodon = Mastodon(
- access_token = 'd100.club_usercred.secret',
- api_base_url = 'd100.club'
- )
- posts = mastodon.timeline()
- stdscr.clear()
- # stdscr.addstr("test")
- curses.halfdelay(10)
- my, mx = stdscr.getmaxyx()
- c1w = c2w = (mx - 3) // 2
- if (mx % 2) != 0:
- c2w = c2w - 1
- colw1 = curses.newwin(my - 2, c1w, 1, 1)
- colw2 = curses.newwin(my - 2, c2w, 1, 1 + c1w + 2)
- stdscr.border()
- # colw1.border()
- # colw2.border()
- parser = PostParser(colw1, 0)
- # colw1.move(0,0)
- # stdscr.addstr(0, 0, 'test')
- # colw2.addstr(0, 0, 'test2')
- # colw1.addstr(0, 0, 'test3')
- i = 'c'
- q = 0
- printAtLevel(stdscr, colw1, colw2, posts, parser, q)
- con = True
- while con:
- i = stdscr.getch()
- if (i == ord('q')):
- con = False
- elif (i == ord('j')):
- q = (q + 1) % len(posts)
- printAtLevel(stdscr, colw1, colw2, posts, parser, q)
- elif (i == ord('k')):
- q = (q - 1) % len(posts)
- printAtLevel(stdscr, colw1, colw2, posts, parser, q)
-
- curses.wrapper(main)
|