forked from endorphant/ttbp
code cleanup
moved a whole bunch of functions around for better code clarity. it's 3am and i can't sleep, so i vaguely expect to have to revert this in the morning.master
parent
82cbcd535c
commit
3a08bcb116
180
bin/_ttbp.py
180
bin/_ttbp.py
|
@ -72,8 +72,8 @@ SPACER = "\n"
|
||||||
INVALID = "please pick a number from the list of options!\n\n"
|
INVALID = "please pick a number from the list of options!\n\n"
|
||||||
DUST = "sorry about the dust, but this part is still under construction. check back later!\n\n"
|
DUST = "sorry about the dust, but this part is still under construction. check back later!\n\n"
|
||||||
QUITS = ['exit', 'quit', 'q', 'x']
|
QUITS = ['exit', 'quit', 'q', 'x']
|
||||||
BACKS = ['back', 'b', 'q']
|
|
||||||
EJECT = "eject button fired! going home now."
|
EJECT = "eject button fired! going home now."
|
||||||
|
RAINBOW = True
|
||||||
|
|
||||||
## ref
|
## ref
|
||||||
|
|
||||||
|
@ -156,13 +156,13 @@ def check_init():
|
||||||
|
|
||||||
## ttbprc validation
|
## ttbprc validation
|
||||||
while not os.path.isfile(TTBPRC):
|
while not os.path.isfile(TTBPRC):
|
||||||
setup_handler()
|
setup_repair()
|
||||||
try:
|
try:
|
||||||
SETTINGS = json.load(open(TTBPRC))
|
SETTINGS = json.load(open(TTBPRC))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
setup_handler()
|
setup_repair()
|
||||||
|
|
||||||
## PATCH CHECK HERE
|
## version checker
|
||||||
if build_mismatch():
|
if build_mismatch():
|
||||||
switch_build()
|
switch_build()
|
||||||
if not updated():
|
if not updated():
|
||||||
|
@ -170,7 +170,7 @@ def check_init():
|
||||||
|
|
||||||
## when ready, enter main program and load core engine
|
## when ready, enter main program and load core engine
|
||||||
raw_input("press <enter> to explore your feels.\n\n")
|
raw_input("press <enter> to explore your feels.\n\n")
|
||||||
core.load()
|
core.load(SETTINGS)
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
else:
|
else:
|
||||||
|
@ -217,7 +217,7 @@ press <enter> to begin, or <ctrl-c> to get out of here.
|
||||||
|
|
||||||
## run user-interactive setup and load core engine
|
## run user-interactive setup and load core engine
|
||||||
setup()
|
setup()
|
||||||
core.load()
|
core.load(SETTINGS)
|
||||||
|
|
||||||
raw_input("\nyou're all good to go, "+chatter.say("friend")+"! hit <enter> to continue.\n\n")
|
raw_input("\nyou're all good to go, "+chatter.say("friend")+"! hit <enter> to continue.\n\n")
|
||||||
return ""
|
return ""
|
||||||
|
@ -251,9 +251,9 @@ def gen_header():
|
||||||
"""
|
"""
|
||||||
return header
|
return header
|
||||||
|
|
||||||
def setup_handler():
|
def setup_repair():
|
||||||
'''
|
'''
|
||||||
setup wrapper function
|
setup repair function
|
||||||
|
|
||||||
* calls setup()
|
* calls setup()
|
||||||
* handles ^c
|
* handles ^c
|
||||||
|
@ -281,7 +281,7 @@ def setup():
|
||||||
global SETTINGS
|
global SETTINGS
|
||||||
|
|
||||||
print("\n\ttext editor:\t" +SETTINGS.get("editor"))
|
print("\n\ttext editor:\t" +SETTINGS.get("editor"))
|
||||||
if publishing():
|
if core.publishing():
|
||||||
print("\tpublish dir:\t" +os.path.join(PUBLIC, SETTINGS.get("publish dir")))
|
print("\tpublish dir:\t" +os.path.join(PUBLIC, SETTINGS.get("publish dir")))
|
||||||
print("\tpubishing:\t"+str(SETTINGS.get("publishing"))+"\n")
|
print("\tpubishing:\t"+str(SETTINGS.get("publishing"))+"\n")
|
||||||
|
|
||||||
|
@ -292,9 +292,9 @@ def setup():
|
||||||
# publishing selection
|
# publishing selection
|
||||||
SETTINGS.update({"publishing":select_publishing()})
|
SETTINGS.update({"publishing":select_publishing()})
|
||||||
update_publishing()
|
update_publishing()
|
||||||
redraw("blog publishing: "+str(publishing()))
|
redraw("blog publishing: "+str(core.publishing()))
|
||||||
|
|
||||||
if publishing():
|
if core.publishing():
|
||||||
print("publish directory: ~"+USER+"/public_html/"+SETTINGS.get("publish dir"))
|
print("publish directory: ~"+USER+"/public_html/"+SETTINGS.get("publish dir"))
|
||||||
|
|
||||||
# save settings
|
# save settings
|
||||||
|
@ -309,25 +309,6 @@ def setup():
|
||||||
|
|
||||||
## menus
|
## menus
|
||||||
|
|
||||||
def print_menu(menu):
|
|
||||||
'''
|
|
||||||
pretty menu handler
|
|
||||||
|
|
||||||
* takes list of options and prints them
|
|
||||||
'''
|
|
||||||
|
|
||||||
i = 0
|
|
||||||
for x in menu:
|
|
||||||
line = []
|
|
||||||
line.append(util.attach_rainbow())
|
|
||||||
line.append("\t[ ")
|
|
||||||
if i < 10:
|
|
||||||
line.append(" ")
|
|
||||||
line.append(str(i)+" ] "+x)
|
|
||||||
line.append(util.attach_reset())
|
|
||||||
print("".join(line))
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
def main_menu():
|
def main_menu():
|
||||||
'''
|
'''
|
||||||
main navigation menu
|
main navigation menu
|
||||||
|
@ -344,7 +325,7 @@ def main_menu():
|
||||||
"read documentation"]
|
"read documentation"]
|
||||||
|
|
||||||
print("you're at ttbp home. remember, you can always press <ctrl-c> to come back here.\n\n")
|
print("you're at ttbp home. remember, you can always press <ctrl-c> to come back here.\n\n")
|
||||||
print_menu(menuOptions)
|
util.print_menu(menuOptions, RAINBOW)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
choice = raw_input("\ntell me about your feels (or 'quit' to exit): ")
|
choice = raw_input("\ntell me about your feels (or 'quit' to exit): ")
|
||||||
|
@ -356,12 +337,12 @@ def main_menu():
|
||||||
redraw()
|
redraw()
|
||||||
today = time.strftime("%Y%m%d")
|
today = time.strftime("%Y%m%d")
|
||||||
write_entry(os.path.join(DATA, today+".txt"))
|
write_entry(os.path.join(DATA, today+".txt"))
|
||||||
www_neighbors(find_ttbps())
|
core.www_neighbors()
|
||||||
elif choice == '1':
|
elif choice == '1':
|
||||||
redraw("your recorded feels, listed by date:\n")
|
redraw("your recorded feels, listed by date:\n")
|
||||||
view_feels(USER)
|
view_feels(USER)
|
||||||
elif choice == '2':
|
elif choice == '2':
|
||||||
users = find_ttbps()
|
users = core.find_ttbps()
|
||||||
redraw("the following "+p.no("user", len(users))+" "+p.plural("is", len(users))+" recording feels on ttbp:\n")
|
redraw("the following "+p.no("user", len(users))+" "+p.plural("is", len(users))+" recording feels on ttbp:\n")
|
||||||
view_neighbors(users)
|
view_neighbors(users)
|
||||||
elif choice == '3':
|
elif choice == '3':
|
||||||
|
@ -370,7 +351,7 @@ def main_menu():
|
||||||
elif choice == '4':
|
elif choice == '4':
|
||||||
redraw("now changing your settings. press <ctrl-c> if you didn't mean to do this.")
|
redraw("now changing your settings. press <ctrl-c> if you didn't mean to do this.")
|
||||||
try:
|
try:
|
||||||
setup()
|
core.load(setup()) # reload settings to core
|
||||||
except KeyboardInterrupt():
|
except KeyboardInterrupt():
|
||||||
redraw(EJECT)
|
redraw(EJECT)
|
||||||
redraw()
|
redraw()
|
||||||
|
@ -399,7 +380,7 @@ def feedback_menu():
|
||||||
|
|
||||||
print("you're about to send mail to ~endorphant about ttbp\n\n")
|
print("you're about to send mail to ~endorphant about ttbp\n\n")
|
||||||
|
|
||||||
print_menu(SUBJECTS)
|
util.print_menu(SUBJECTS, RAINBOW)
|
||||||
choice = raw_input("\npick a category for your feedback: ")
|
choice = raw_input("\npick a category for your feedback: ")
|
||||||
|
|
||||||
cat = ""
|
cat = ""
|
||||||
|
@ -473,10 +454,10 @@ def view_neighbors(users):
|
||||||
sortedUsers.append(user[0])
|
sortedUsers.append(user[0])
|
||||||
userIndex.append(user[2])
|
userIndex.append(user[2])
|
||||||
|
|
||||||
print_menu(sortedUsers)
|
util.print_menu(sortedUsers, RAINBOW)
|
||||||
|
|
||||||
#raw_input("\n\npress <enter> to go back home.\n\n")
|
#raw_input("\n\npress <enter> to go back home.\n\n")
|
||||||
choice = list_select(sortedUsers, "pick a townie to browse their feels, or type 'back' to go home: ")
|
choice = util.list_select(sortedUsers, "pick a townie to browse their feels, or type 'back' to go home: ")
|
||||||
|
|
||||||
if choice is not False:
|
if choice is not False:
|
||||||
redraw("~"+userIndex[choice]+"'s recorded feels, listed by date: \n")
|
redraw("~"+userIndex[choice]+"'s recorded feels, listed by date: \n")
|
||||||
|
@ -571,7 +552,7 @@ editor.
|
||||||
|
|
||||||
left = ""
|
left = ""
|
||||||
|
|
||||||
if publishing():
|
if core.publishing():
|
||||||
core.load_files()
|
core.load_files()
|
||||||
core.write("index.html")
|
core.write("index.html")
|
||||||
left = "posted to "+LIVE+USER+"/"+SETTINGS["publish dir"]+"/index.html\n\n>"
|
left = "posted to "+LIVE+USER+"/"+SETTINGS["publish dir"]+"/index.html\n\n>"
|
||||||
|
@ -613,9 +594,9 @@ def list_entries(metas, entries, prompt):
|
||||||
displays a list of entries for reading selection
|
displays a list of entries for reading selection
|
||||||
'''
|
'''
|
||||||
|
|
||||||
print_menu(entries)
|
util.print_menu(entries, RAINBOW)
|
||||||
|
|
||||||
choice = list_select(entries, "pick an entry from the list, or type 'back' to go back: ")
|
choice = util.list_select(entries, "pick an entry from the list, or type 'back' to go back: ")
|
||||||
|
|
||||||
if choice is not False:
|
if choice is not False:
|
||||||
|
|
||||||
|
@ -646,7 +627,7 @@ def view_feed():
|
||||||
|
|
||||||
feedList = []
|
feedList = []
|
||||||
|
|
||||||
for townie in find_ttbps():
|
for townie in core.find_ttbps():
|
||||||
entryDir = os.path.join("/home", townie, ".ttbp", "entries")
|
entryDir = os.path.join("/home", townie, ".ttbp", "entries")
|
||||||
filenames = os.listdir(entryDir)
|
filenames = os.listdir(entryDir)
|
||||||
|
|
||||||
|
@ -674,124 +655,13 @@ def view_feed():
|
||||||
|
|
||||||
## misc helpers
|
## misc helpers
|
||||||
|
|
||||||
def find_ttbps():
|
|
||||||
'''
|
|
||||||
returns a list of users with a ttbp by checking for a valid ttbprc
|
|
||||||
'''
|
|
||||||
|
|
||||||
users = []
|
|
||||||
|
|
||||||
for townie in os.listdir("/home"):
|
|
||||||
if os.path.exists(os.path.join("/home", townie, ".ttbp", "config", "ttbprc")):
|
|
||||||
users.append(townie)
|
|
||||||
|
|
||||||
return users
|
|
||||||
|
|
||||||
def www_neighbors(users):
|
|
||||||
'''
|
|
||||||
takes a list of users with publiishing turned on and prepares it for www output
|
|
||||||
'''
|
|
||||||
|
|
||||||
userList = []
|
|
||||||
|
|
||||||
for user in users:
|
|
||||||
if not publishing(user):
|
|
||||||
continue
|
|
||||||
|
|
||||||
userRC = json.load(open(os.path.join("/home", user, ".ttbp", "config", "ttbprc")))
|
|
||||||
|
|
||||||
url = LIVE+user+"/"+userRC["publish dir"]
|
|
||||||
|
|
||||||
lastfile = ""
|
|
||||||
files = os.listdir(os.path.join("/home", user, ".ttbp", "entries"))
|
|
||||||
files.sort()
|
|
||||||
for filename in files:
|
|
||||||
if core.valid(filename):
|
|
||||||
lastfile = os.path.join("/home", user, ".ttbp", "entries", filename)
|
|
||||||
|
|
||||||
if lastfile:
|
|
||||||
last = os.path.getctime(lastfile)
|
|
||||||
timestamp = time.strftime("%Y-%m-%d at %H:%M", time.localtime(last)) + " (utc"+time.strftime("%z")[0]+time.strftime("%z")[2]+")"
|
|
||||||
else:
|
|
||||||
timestamp = ""
|
|
||||||
last = 0
|
|
||||||
|
|
||||||
userList.append(["<a href=\""+url+"\">~"+user+"</a> "+timestamp, last])
|
|
||||||
|
|
||||||
# sort user by most recent entry
|
|
||||||
userList.sort(key = lambda userdata:userdata[1])
|
|
||||||
userList.reverse()
|
|
||||||
sortedUsers = []
|
|
||||||
for user in userList:
|
|
||||||
sortedUsers.append(user[0])
|
|
||||||
|
|
||||||
core.write_global_feed(sortedUsers)
|
|
||||||
|
|
||||||
def list_select(options, prompt):
|
|
||||||
'''
|
|
||||||
given a list, cycles through the prompt until a valid index is imputted
|
|
||||||
'''
|
|
||||||
|
|
||||||
ans = ""
|
|
||||||
invalid = True
|
|
||||||
|
|
||||||
while invalid:
|
|
||||||
choice = raw_input("\n\n"+prompt)
|
|
||||||
|
|
||||||
if choice in BACKS:
|
|
||||||
return False
|
|
||||||
|
|
||||||
try:
|
|
||||||
ans = int(choice)
|
|
||||||
except ValueError:
|
|
||||||
return list_select(options, prompt)
|
|
||||||
|
|
||||||
invalid = False
|
|
||||||
|
|
||||||
if ans >= len(options):
|
|
||||||
return list_select(options, prompt)
|
|
||||||
|
|
||||||
return ans
|
|
||||||
|
|
||||||
def input_yn(query):
|
|
||||||
'''
|
|
||||||
given a query, returns boolean True or False by processing y/n input
|
|
||||||
'''
|
|
||||||
|
|
||||||
try:
|
|
||||||
ans = raw_input(query+" [y/n] ")
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
input_yn(query)
|
|
||||||
|
|
||||||
while ans not in ["y", "n"]:
|
|
||||||
ans = raw_input("'y' or 'n' please: ")
|
|
||||||
|
|
||||||
if ans == "y":
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def publishing(username = USER):
|
|
||||||
'''
|
|
||||||
checks .ttbprc for whether or not user opted for www publishing
|
|
||||||
'''
|
|
||||||
|
|
||||||
ttbprc = {}
|
|
||||||
|
|
||||||
if username == USER:
|
|
||||||
ttbprc = SETTINGS
|
|
||||||
|
|
||||||
else:
|
|
||||||
ttbprc = json.load(open(os.path.join("/home", username, ".ttbp", "config", "ttbprc")))
|
|
||||||
|
|
||||||
return ttbprc.get("publishing")
|
|
||||||
|
|
||||||
def select_editor():
|
def select_editor():
|
||||||
'''
|
'''
|
||||||
setup helper for editor selection
|
setup helper for editor selection
|
||||||
'''
|
'''
|
||||||
|
|
||||||
print_menu(EDITORS)
|
util.print_menu(EDITORS, RAINBOW)
|
||||||
choice = raw_input("\npick your favorite text editor: ")
|
choice = raw_input("\npick your favorite text editor: ")
|
||||||
while choice not in ['0', '1', '2', '3', '4', '5']:
|
while choice not in ['0', '1', '2', '3', '4', '5']:
|
||||||
choice = raw_input("\nplease pick a number from the list: ")
|
choice = raw_input("\nplease pick a number from the list: ")
|
||||||
|
@ -837,7 +707,7 @@ def select_publishing():
|
||||||
setup helper for toggling publishing
|
setup helper for toggling publishing
|
||||||
'''
|
'''
|
||||||
|
|
||||||
publish = input_yn("""\
|
publish = util.input_yn("""\
|
||||||
do you want to publish your feels online?
|
do you want to publish your feels online?
|
||||||
|
|
||||||
if yes, your feels will be published to a directory of your choice in
|
if yes, your feels will be published to a directory of your choice in
|
||||||
|
@ -872,7 +742,7 @@ def update_publishing():
|
||||||
|
|
||||||
global SETTINGS
|
global SETTINGS
|
||||||
|
|
||||||
if publishing():
|
if core.publishing():
|
||||||
oldDir = SETTINGS.get("publish dir")
|
oldDir = SETTINGS.get("publish dir")
|
||||||
newDir = select_publish_dir()
|
newDir = select_publish_dir()
|
||||||
SETTINGS.update({"publish dir": newDir})
|
SETTINGS.update({"publish dir": newDir})
|
||||||
|
|
214
bin/core.py
214
bin/core.py
|
@ -33,6 +33,7 @@ import time
|
||||||
import subprocess
|
import subprocess
|
||||||
import re
|
import re
|
||||||
import mistune
|
import mistune
|
||||||
|
import json
|
||||||
|
|
||||||
import chatter
|
import chatter
|
||||||
|
|
||||||
|
@ -47,21 +48,24 @@ DATA = os.path.join(PATH, "entries")
|
||||||
FEED = os.path.join(SOURCE, "www", "index.html")
|
FEED = os.path.join(SOURCE, "www", "index.html")
|
||||||
DOCS = os.path.join(SOURCE, "www", "help.html")
|
DOCS = os.path.join(SOURCE, "www", "help.html")
|
||||||
NOPUB = os.path.join(CONFIG, "nopub")
|
NOPUB = os.path.join(CONFIG, "nopub")
|
||||||
|
SETTINGS = {}
|
||||||
|
|
||||||
HEADER = ""
|
HEADER = ""
|
||||||
FOOTER = ""
|
FOOTER = ""
|
||||||
FILES = []
|
FILES = []
|
||||||
|
|
||||||
def load():
|
def load(ttbprc):
|
||||||
'''
|
'''
|
||||||
get all them globals set up!!
|
get all them globals set up!!
|
||||||
'''
|
'''
|
||||||
|
|
||||||
global HEADER
|
global HEADER
|
||||||
global FOOTER
|
global FOOTER
|
||||||
|
global SETTINGS
|
||||||
|
|
||||||
HEADER = open(os.path.join(CONFIG, "header.txt")).read()
|
HEADER = open(os.path.join(CONFIG, "header.txt")).read()
|
||||||
FOOTER = open(os.path.join(CONFIG, "footer.txt")).read()
|
FOOTER = open(os.path.join(CONFIG, "footer.txt")).read()
|
||||||
|
SETTINGS = ttbprc
|
||||||
|
|
||||||
load_files()
|
load_files()
|
||||||
|
|
||||||
|
@ -92,6 +96,9 @@ def load_files():
|
||||||
FILES.sort()
|
FILES.sort()
|
||||||
FILES.reverse()
|
FILES.reverse()
|
||||||
|
|
||||||
|
|
||||||
|
## html outputting
|
||||||
|
|
||||||
def write(outurl="default.html"):
|
def write(outurl="default.html"):
|
||||||
'''
|
'''
|
||||||
main page renderer
|
main page renderer
|
||||||
|
@ -191,74 +198,6 @@ def write_entry(filename):
|
||||||
|
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
def parse_date(file):
|
|
||||||
'''
|
|
||||||
parses date out of pre-validated filename
|
|
||||||
|
|
||||||
* assumes a filename of YYYYMMDD.txt
|
|
||||||
* returns a list:
|
|
||||||
[0] 'YYYY'
|
|
||||||
[1] 'MM'
|
|
||||||
[2] 'DD'
|
|
||||||
'''
|
|
||||||
|
|
||||||
rawdate = os.path.splitext(os.path.basename(file))[0]
|
|
||||||
|
|
||||||
date = [rawdate[0:4], rawdate[4:6], rawdate[6:]]
|
|
||||||
|
|
||||||
return date
|
|
||||||
|
|
||||||
def meta(entries = FILES):
|
|
||||||
'''
|
|
||||||
metadata generator
|
|
||||||
|
|
||||||
* takes a list of filenames and returns a 2d list:
|
|
||||||
[0] absolute path
|
|
||||||
[1] mtime
|
|
||||||
[2] wc -w
|
|
||||||
[3] timestamp "DD month YYYY at HH:MM"
|
|
||||||
[4] entry date YYYY-MM-DD
|
|
||||||
[5] author
|
|
||||||
|
|
||||||
* sorted in reverse date order by [4]
|
|
||||||
'''
|
|
||||||
|
|
||||||
meta = []
|
|
||||||
|
|
||||||
for filename in entries:
|
|
||||||
mtime = os.path.getmtime(filename)
|
|
||||||
wc = subprocess.check_output(["wc","-w",filename]).split()[0]
|
|
||||||
timestamp = time.strftime("%Y-%m-%d at %H:%M", time.localtime(mtime))
|
|
||||||
date = "-".join(parse_date(filename))
|
|
||||||
author = os.path.split(os.path.split(os.path.split(os.path.split(filename)[0])[0])[0])[1]
|
|
||||||
|
|
||||||
|
|
||||||
meta.append([filename, mtime, wc, timestamp, date, author])
|
|
||||||
|
|
||||||
meta.sort(key = lambda filename:filename[4])
|
|
||||||
meta.reverse()
|
|
||||||
|
|
||||||
return meta
|
|
||||||
|
|
||||||
def valid(filename):
|
|
||||||
'''
|
|
||||||
filename validator
|
|
||||||
|
|
||||||
* check if the filename is YYYYMMDD.txt
|
|
||||||
'''
|
|
||||||
|
|
||||||
filesplit = os.path.splitext(os.path.basename(filename))
|
|
||||||
|
|
||||||
if filesplit[1] != ".txt":
|
|
||||||
return False
|
|
||||||
|
|
||||||
pattern = '^((19|20)\d{2})(0[1-9]|1[0-2])(0[1-9]|1\d|2\d|3[01])$'
|
|
||||||
|
|
||||||
if not re.match(pattern, filesplit[0]):
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def write_global_feed(blogList):
|
def write_global_feed(blogList):
|
||||||
'''
|
'''
|
||||||
main ttbp index printer
|
main ttbp index printer
|
||||||
|
@ -319,6 +258,143 @@ def write_global_feed(blogList):
|
||||||
|
|
||||||
outfile.close()
|
outfile.close()
|
||||||
|
|
||||||
|
## misc helpers
|
||||||
|
|
||||||
|
def meta(entries = FILES):
|
||||||
|
'''
|
||||||
|
metadata generator
|
||||||
|
|
||||||
|
* takes a list of filenames and returns a 2d list:
|
||||||
|
[0] absolute path
|
||||||
|
[1] mtime
|
||||||
|
[2] wc -w
|
||||||
|
[3] timestamp "DD month YYYY at HH:MM"
|
||||||
|
[4] entry date YYYY-MM-DD
|
||||||
|
[5] author
|
||||||
|
|
||||||
|
* sorted in reverse date order by [4]
|
||||||
|
'''
|
||||||
|
|
||||||
|
meta = []
|
||||||
|
|
||||||
|
for filename in entries:
|
||||||
|
mtime = os.path.getmtime(filename)
|
||||||
|
wc = subprocess.check_output(["wc","-w",filename]).split()[0]
|
||||||
|
timestamp = time.strftime("%Y-%m-%d at %H:%M", time.localtime(mtime))
|
||||||
|
date = "-".join(parse_date(filename))
|
||||||
|
author = os.path.split(os.path.split(os.path.split(os.path.split(filename)[0])[0])[0])[1]
|
||||||
|
|
||||||
|
meta.append([filename, mtime, wc, timestamp, date, author])
|
||||||
|
|
||||||
|
meta.sort(key = lambda filename:filename[4])
|
||||||
|
meta.reverse()
|
||||||
|
|
||||||
|
return meta
|
||||||
|
|
||||||
|
def valid(filename):
|
||||||
|
'''
|
||||||
|
filename validator
|
||||||
|
|
||||||
|
* check if the filename is YYYYMMDD.txt
|
||||||
|
'''
|
||||||
|
|
||||||
|
filesplit = os.path.splitext(os.path.basename(filename))
|
||||||
|
|
||||||
|
if filesplit[1] != ".txt":
|
||||||
|
return False
|
||||||
|
|
||||||
|
pattern = '^((19|20)\d{2})(0[1-9]|1[0-2])(0[1-9]|1\d|2\d|3[01])$'
|
||||||
|
|
||||||
|
if not re.match(pattern, filesplit[0]):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def parse_date(file):
|
||||||
|
'''
|
||||||
|
parses date out of pre-validated filename
|
||||||
|
|
||||||
|
* assumes a filename of YYYYMMDD.txt
|
||||||
|
* returns a list:
|
||||||
|
[0] 'YYYY'
|
||||||
|
[1] 'MM'
|
||||||
|
[2] 'DD'
|
||||||
|
'''
|
||||||
|
|
||||||
|
rawdate = os.path.splitext(os.path.basename(file))[0]
|
||||||
|
|
||||||
|
date = [rawdate[0:4], rawdate[4:6], rawdate[6:]]
|
||||||
|
|
||||||
|
return date
|
||||||
|
|
||||||
|
def find_ttbps():
|
||||||
|
'''
|
||||||
|
returns a list of users with a ttbp by checking for a valid ttbprc
|
||||||
|
'''
|
||||||
|
|
||||||
|
users = []
|
||||||
|
|
||||||
|
for townie in os.listdir("/home"):
|
||||||
|
if os.path.exists(os.path.join("/home", townie, ".ttbp", "config", "ttbprc")):
|
||||||
|
users.append(townie)
|
||||||
|
|
||||||
|
return users
|
||||||
|
|
||||||
|
def publishing(username = USER):
|
||||||
|
'''
|
||||||
|
checks .ttbprc for whether or not user opted for www publishing
|
||||||
|
'''
|
||||||
|
|
||||||
|
ttbprc = {}
|
||||||
|
|
||||||
|
if username == USER:
|
||||||
|
ttbprc = SETTINGS
|
||||||
|
|
||||||
|
else:
|
||||||
|
ttbprc = json.load(open(os.path.join("/home", username, ".ttbp", "config", "ttbprc")))
|
||||||
|
|
||||||
|
return ttbprc.get("publishing")
|
||||||
|
|
||||||
|
def www_neighbors():
|
||||||
|
'''
|
||||||
|
takes a list of users with publiishing turned on and prepares it for www output
|
||||||
|
'''
|
||||||
|
|
||||||
|
userList = []
|
||||||
|
|
||||||
|
for user in find_ttbps():
|
||||||
|
if not publishing(user):
|
||||||
|
continue
|
||||||
|
|
||||||
|
userRC = json.load(open(os.path.join("/home", user, ".ttbp", "config", "ttbprc")))
|
||||||
|
|
||||||
|
url = LIVE+user+"/"+userRC["publish dir"]
|
||||||
|
|
||||||
|
lastfile = ""
|
||||||
|
files = os.listdir(os.path.join("/home", user, ".ttbp", "entries"))
|
||||||
|
files.sort()
|
||||||
|
for filename in files:
|
||||||
|
if valid(filename):
|
||||||
|
lastfile = os.path.join("/home", user, ".ttbp", "entries", filename)
|
||||||
|
|
||||||
|
if lastfile:
|
||||||
|
last = os.path.getctime(lastfile)
|
||||||
|
timestamp = time.strftime("%Y-%m-%d at %H:%M", time.localtime(last)) + " (utc"+time.strftime("%z")[0]+time.strftime("%z")[2]+")"
|
||||||
|
else:
|
||||||
|
timestamp = ""
|
||||||
|
last = 0
|
||||||
|
|
||||||
|
userList.append(["<a href=\""+url+"\">~"+user+"</a> "+timestamp, last])
|
||||||
|
|
||||||
|
# sort user by most recent entry
|
||||||
|
userList.sort(key = lambda userdata:userdata[1])
|
||||||
|
userList.reverse()
|
||||||
|
sortedUsers = []
|
||||||
|
for user in userList:
|
||||||
|
sortedUsers.append(user[0])
|
||||||
|
|
||||||
|
write_global_feed(sortedUsers)
|
||||||
|
|
||||||
#############
|
#############
|
||||||
#############
|
#############
|
||||||
#############
|
#############
|
||||||
|
|
74
bin/util.py
74
bin/util.py
|
@ -24,10 +24,12 @@ import time
|
||||||
import random
|
import random
|
||||||
import colorama
|
import colorama
|
||||||
|
|
||||||
|
## misc globals
|
||||||
|
BACKS = ['back', 'b', 'q']
|
||||||
|
|
||||||
|
## color stuff
|
||||||
colorama.init()
|
colorama.init()
|
||||||
|
|
||||||
textcolors = [ colorama.Fore.RED, colorama.Fore.GREEN, colorama.Fore.YELLOW, colorama.Fore.BLUE, colorama.Fore.MAGENTA, colorama.Fore.WHITE, colorama.Fore.CYAN]
|
textcolors = [ colorama.Fore.RED, colorama.Fore.GREEN, colorama.Fore.YELLOW, colorama.Fore.BLUE, colorama.Fore.MAGENTA, colorama.Fore.WHITE, colorama.Fore.CYAN]
|
||||||
|
|
||||||
lastcolor = colorama.Fore.RESET
|
lastcolor = colorama.Fore.RESET
|
||||||
|
|
||||||
p = inflect.engine()
|
p = inflect.engine()
|
||||||
|
@ -125,3 +127,71 @@ def genID(digits=5):
|
||||||
x += 1
|
x += 1
|
||||||
|
|
||||||
return id
|
return id
|
||||||
|
|
||||||
|
def print_menu(menu, rainbow=False):
|
||||||
|
'''
|
||||||
|
A pretty menu handler that takes an incoming lists of
|
||||||
|
options and prints them nicely.
|
||||||
|
|
||||||
|
Set rainbow=True for colorized menus.
|
||||||
|
'''
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
for x in menu:
|
||||||
|
line = []
|
||||||
|
if rainbow:
|
||||||
|
line.append(attach_rainbow())
|
||||||
|
line.append("\t[ ")
|
||||||
|
if i < 10:
|
||||||
|
line.append(" ")
|
||||||
|
line.append(str(i)+" ] "+x)
|
||||||
|
line.append(attach_reset())
|
||||||
|
print("".join(line))
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
def list_select(options, prompt):
|
||||||
|
'''
|
||||||
|
Given a list and query prompt, returns either False as an
|
||||||
|
eject flag, or an integer index of the list Catches cancel
|
||||||
|
option from list defined by BACKS; otherwise, retries on
|
||||||
|
ValueError or IndexError.
|
||||||
|
'''
|
||||||
|
|
||||||
|
ans = ""
|
||||||
|
invalid = True
|
||||||
|
|
||||||
|
choice = raw_input("\n\n"+prompt)
|
||||||
|
|
||||||
|
if choice in BACKS:
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
ans = int(choice)
|
||||||
|
except ValueError:
|
||||||
|
return list_select(options, prompt)
|
||||||
|
|
||||||
|
try:
|
||||||
|
options[ans]
|
||||||
|
except IndexError:
|
||||||
|
return list_select(options, prompt)
|
||||||
|
|
||||||
|
return ans
|
||||||
|
|
||||||
|
def input_yn(query):
|
||||||
|
'''
|
||||||
|
Given a query, returns boolean True or False by processing y/n input
|
||||||
|
'''
|
||||||
|
|
||||||
|
try:
|
||||||
|
ans = raw_input(query+" [y/n] ")
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
input_yn(query)
|
||||||
|
|
||||||
|
while ans not in ["y", "n"]:
|
||||||
|
ans = raw_input("'y' or 'n' please: ")
|
||||||
|
|
||||||
|
if ans == "y":
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue