ttbp/ttbp/ttbp.py

1929 lines
55 KiB
Python
Raw Normal View History

2016-04-30 03:17:06 +00:00
#!/usr/bin/python
2016-05-22 02:18:25 +00:00
'''
ttbp: tilde town blogging platform
(also known as the feels engine)
a console-based blogging program developed for tilde.town
copyright (c) 2016 ~endorphant (endorphant@tilde.town)
ttbp.py:
the main console interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
2016-05-22 02:18:25 +00:00
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
2016-05-22 02:18:25 +00:00
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2016-05-22 02:18:25 +00:00
the complete codebase is available at:
https://github.com/modgethanc/ttbp
'''
2017-11-21 02:48:32 +00:00
from __future__ import absolute_import
2016-05-22 02:18:25 +00:00
2016-04-30 03:17:06 +00:00
import os
2018-03-16 05:30:48 +00:00
import sys
2016-05-01 17:44:49 +00:00
import tempfile
import subprocess
import time
2016-05-01 22:43:12 +00:00
import json
2017-12-04 04:05:04 +00:00
from email.mime.text import MIMEText
import datetime
2018-02-23 20:28:25 +00:00
from six.moves import input
2016-05-01 17:44:49 +00:00
2016-05-03 17:14:53 +00:00
import inflect
2016-04-30 03:17:06 +00:00
2017-11-21 06:02:10 +00:00
from . import config
2017-11-21 02:48:32 +00:00
from . import core
from . import chatter
2017-12-04 03:37:43 +00:00
from . import gopher
2017-11-21 02:48:32 +00:00
from . import util
__version__ = "0.12.2"
__author__ = "endorphant <endorphant@tilde.town)"
2016-05-03 17:14:53 +00:00
p = inflect.engine()
2016-05-01 22:26:26 +00:00
## ui globals
2017-11-21 06:02:10 +00:00
BANNER = util.attach_rainbow() + config.BANNER + util.attach_reset()
SPACER = "\n"
2016-05-01 18:10:04 +00:00
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"
QUITS = ['exit', 'quit', 'q', 'x']
EJECT = "eject button fired! going home now."
RAINBOW = False
2016-05-01 18:10:04 +00:00
2016-05-01 22:26:26 +00:00
## ref
2017-12-06 03:50:45 +00:00
EDITORS = ["nano", "vim", "vi", "emacs", "pico", "ed", "micro"]
SUBJECTS = ["help request", "bug report", "feature suggestion", "general comment"]
DEFAULT_SETTINGS = {
"editor": "nano",
"publish dir": None,
"gopher": False,
2018-01-02 06:21:48 +00:00
"publishing": False,
"rainbows": False,
"post as nopub": False,
}
2016-05-01 22:26:26 +00:00
2017-12-31 17:52:23 +00:00
## user globals
SETTINGS = {
"editor": "nano",
"publish dir": None,
"gopher": False,
2018-01-02 06:21:48 +00:00
"publishing": False,
"rainbows": False,
"post as nopub": False,
2017-12-31 17:52:23 +00:00
}
## ttbp specific utilities
def menu_handler(options, prompt, pagify=10, page=0, rainbow=False, top=""):
'''
This menu handler takes an incoming list of options, pagifies to a
pre-set value, and queries via the prompt. Calls print_menu() and
list_select() as helpers.
'top' is an optional list topper, to be passed to redraw()
'''
optCount = len(options)
total = optCount / pagify
# don't display empty pages
if optCount % pagify == 0:
total = total - 1
2019-07-10 04:36:35 +00:00
if 0:
# temporary fix for menu bug when fewer than 10 entries
#if total < 1:
2018-01-02 06:21:48 +00:00
util.print_menu(options, SETTINGS.get("rainbows", False))
return util.list_select(options, prompt)
else:
2018-02-28 18:16:51 +00:00
return page_helper(options, prompt, pagify, rainbow, page, int(total), top)
def page_helper(options, prompt, pagify, rainbow, page, total, top):
'''
A helper to process pagination.
'pagify' is the number of entries per page of display
'page' is the current page number
'total' is the total number of pages
'top' is displyed after the banner redraw
'''
## make short list
x = 0 + page * pagify
y = x + pagify
optPage = options[x:y]
2018-01-02 06:21:48 +00:00
util.print_menu(optPage, SETTINGS.get("rainbows", False))
2018-02-28 18:16:51 +00:00
print("\n\t( page {page} of {total}; type 'u' or 'd' to scroll up and down)".format(page=page+1, total=total+1))
ans = util.list_select(optPage, prompt)
if ans in util.NAVS:
error = ""
if ans == 'u':
if page == 0:
error = "can't scroll up anymore!\n\n> "
else:
page = page - 1
else:
if page == total:
error = "can't scroll down anymore!\n\n> "
else:
page = page + 1
redraw(error+top)
return page_helper(options, prompt, pagify, rainbow, page, total, top)
elif ans is False:
return ans
else:
# shift answer to refer to index from original list
ans = ans + page * pagify
# return the (shifted) answer and the current page
# alternatively, we can recompute the current page at a call site
return (page, ans)
2016-05-01 18:10:04 +00:00
def redraw(leftover=""):
'''
screen clearing
* clears the screen and reprints the banner, plus whatever leftover text to be hilights
'''
2016-05-01 18:10:04 +00:00
os.system("clear")
print(BANNER)
print(SPACER)
if leftover:
print("> {leftover}\n".format(leftover=leftover))
2016-04-30 03:17:06 +00:00
def main():
'''
main engine head
* called on program start
* calls config check
* proceeds to main menu
* handles ^c and ^d ejects
'''
redraw()
print("""
2016-05-15 04:22:05 +00:00
if you don't want to be here at any point, press <ctrl-d> and it'll all go away.
just keep in mind that you might lose anything you've started here.\
""")
try:
print(check_init())
except EOFError:
print(stop())
return
redraw()
while 1:
try:
print(main_menu())
except EOFError:
print(stop())
break
except KeyboardInterrupt:
redraw(EJECT)
else:
break
2016-04-30 03:34:43 +00:00
def stop():
'''
2018-01-03 03:28:04 +00:00
returns an exit message.
'''
return "\n\n\t"+chatter.say("bye")+"\n\n"
2016-04-30 03:34:43 +00:00
def check_init():
'''
2018-01-03 03:28:04 +00:00
user environment validation
* checks for presence of ttbprc
* checks for last run version
'''
print("\n\n")
if os.path.exists(os.path.join(os.path.expanduser("~"),".ttbp")):
2018-02-20 00:15:21 +00:00
if config.USER == "endorphant":
print("hey boss! :D\n")
else:
print("{greeting}, {user}".format(greeting=chatter.say("greet"),
user=config.USER))
2018-02-28 22:29:10 +00:00
load_settings = load_user_settings()
## ttbp env validation
2018-01-02 06:21:48 +00:00
if not user_up_to_date():
update_user_version()
2018-02-28 22:29:10 +00:00
if not valid_setup(load_settings):
setup_repair()
2017-12-31 17:28:42 +00:00
else:
2018-02-23 20:28:25 +00:00
input("press <enter> to explore your feels.\n\n")
core.load(SETTINGS)
return ""
else:
return init()
2016-04-30 03:34:43 +00:00
def init():
2018-01-03 03:28:04 +00:00
"""Initializes new user by setting up ~/.ttbp directory and config file.
"""
2016-05-01 23:34:20 +00:00
try:
input(config.intro_prompt)
2016-05-01 23:34:20 +00:00
except KeyboardInterrupt:
print("\n\nthanks for checking in! i'll always be here.\n\n")
quit()
2016-05-01 23:34:20 +00:00
2017-12-31 17:52:23 +00:00
print("\nokay! gimme a second to get you set up!")
time.sleep(1)
print("...")
2018-03-22 17:30:32 +00:00
time.sleep(.5)
2017-12-31 17:52:23 +00:00
## record user in source list
2017-11-21 06:02:10 +00:00
users = open(config.USERFILE, 'a')
users.write(config.USER+"\n")
2016-05-01 23:34:20 +00:00
users.close()
#subprocess.call(['chmod', 'a+w', config.USERFILE])
2017-11-22 05:12:49 +00:00
## make .ttbp directory structure
2017-12-31 17:52:23 +00:00
print("\ngenerating feels at {path}...".format(path=config.PATH).rstrip())
2017-11-21 06:02:10 +00:00
subprocess.call(["mkdir", config.PATH])
subprocess.call(["mkdir", config.USER_CONFIG])
subprocess.call(["mkdir", config.MAIN_FEELS])
2016-05-15 04:22:05 +00:00
2017-11-21 06:02:10 +00:00
versionFile = os.path.join(config.PATH, "version")
open(versionFile, "w").write(__version__)
## create header file
header = gen_header()
2017-11-21 06:02:10 +00:00
headerfile = open(os.path.join(config.USER_CONFIG, "header.txt"), 'w')
for line in header:
headerfile.write(line)
headerfile.close()
2016-05-15 04:22:05 +00:00
## copy footer and default stylesheet
2017-11-21 06:39:38 +00:00
with open(os.path.join(config.USER_CONFIG, 'footer.txt'), 'w') as f:
2017-11-21 06:02:10 +00:00
f.write(config.DEFAULT_FOOTER)
2017-11-21 06:39:38 +00:00
with open(os.path.join(config.USER_CONFIG, 'style.css'), 'w') as f:
2017-11-21 06:02:10 +00:00
f.write(config.DEFAULT_STYLE)
2016-05-01 23:34:20 +00:00
## run user-interactive setup and load core engine
2018-03-22 17:30:32 +00:00
time.sleep(0.5)
2017-12-31 17:52:23 +00:00
print("done setting up feels!")
print("\nthese are the default settings. you can change any of them now, or change them later at any time!!")
2016-05-01 23:34:20 +00:00
setup()
core.load(SETTINGS)
input("""
you're all good to go, {friend}! if you have any questions about how things
work here, check out the documentation from the main menu, ask in IRC, or
drop ~endorphant a line!
hit <enter> to continue.
""".format(friend=chatter.say("friend")))
2016-05-01 17:44:49 +00:00
return ""
def gen_header():
'''
header generator
builds header to insert username
'''
2016-05-15 04:22:05 +00:00
header ="""
<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 3.2//EN\">
<html>
<head>
<!--- this header automatically generated by ttbp initialization on """+time.strftime("%Y-%m-%d %h:m")+""" --->
2017-11-21 06:02:10 +00:00
<title>~"""+config.USER+""" on TTBP</title>
2016-05-15 04:22:05 +00:00
<link rel=\"stylesheet\" href=\"style.css\" />
</head>
<body>
<div id=\"meta\">
2017-11-21 06:02:10 +00:00
<h1><a href=\"index.html#\">~"""+config.USER+"""</a>@<a href=\"/~endorphant/ttbp\">TTBP</a></h1>
2016-05-15 04:22:05 +00:00
</div>
2016-05-15 04:22:05 +00:00
<!---put your custom html here-->
<!---don't put anything after this line-->
<div id=\"tlogs\">\
"""
return header
2018-02-28 22:29:10 +00:00
def valid_setup(load_settings):
'''
Checks to see if user has a valid ttbp environment.
'''
2018-02-28 22:29:10 +00:00
if not load_settings:
return False
for option in iter(DEFAULT_SETTINGS):
if option != "publish dir" and SETTINGS.get(option, None) is None:
return False
if core.publishing():
if SETTINGS.get("publish dir", None) is None:
print("CONFIG ERROR! publishing is enabled but no directory is set")
return False
if (not os.path.exists(config.WWW) or
not os.path.exists(os.path.join(config.PUBLIC,
SETTINGS.get("publish dir")))):
print("something's weird with your publishing directories. let's try rebuilding them!")
update_publishing()
return True
2018-02-28 22:29:10 +00:00
def load_user_settings():
"""attempts to load user's ttbprc; returns settings dict if valie, otherwise
returns false"""
global SETTINGS
if not os.path.isfile(config.TTBPRC):
return False
try:
SETTINGS = json.load(open(config.TTBPRC))
except ValueError:
return False
core.load(SETTINGS)
return SETTINGS
def setup_repair():
'''
setup repair function
* calls setup()
* handles ^c
'''
global SETTINGS
2017-12-31 17:52:23 +00:00
print("\nyour ttbp configuration doesn't look right. let me try to fix it....\n\n")
2018-01-02 06:21:48 +00:00
time.sleep(1)
settings_map = {
"editor": select_editor,
"publishing": select_publishing,
"publish dir": select_publish_dir,
2018-01-02 06:21:48 +00:00
"gopher": gopher.select_gopher,
2018-02-28 22:29:10 +00:00
"rainbows": toggle_rainbows,
"post as nopub": toggle_pub_default
}
for option in iter(settings_map):
if SETTINGS.get(option, None) is None:
SETTINGS.update({option: "NOT SET"})
SETTINGS.update({option: settings_map[option]()})
update_publishing()
core.reload_ttbprc(SETTINGS)
save_settings()
2017-12-31 17:52:23 +00:00
print("...")
2018-03-22 17:30:32 +00:00
time.sleep(0.5)
2018-02-23 20:28:25 +00:00
input("\nyou're all good to go, "+chatter.say("friend")+"! hit <enter> to continue.\n\n")
2016-05-01 22:43:12 +00:00
2016-05-01 22:26:26 +00:00
def setup():
'''
master setup function
* editor selection
* publishing toggle (publish/unpublish as needed)
* directory selection
* gopher opt in/out
TODO: break this out better?
'''
2016-05-01 22:26:26 +00:00
global SETTINGS
2017-12-06 03:50:45 +00:00
menuOptions = []
settingList = sorted(list(SETTINGS))
for setting in settingList:
menuOptions.append(setting + ": \t" + str(SETTINGS.get(setting)))
2018-01-02 06:21:48 +00:00
util.print_menu(menuOptions, SETTINGS.get("rainbows", False))
2017-12-06 03:50:45 +00:00
try:
2018-02-23 20:28:25 +00:00
choice = input("\npick a setting to change (or type 'q' to exit): ")
2017-12-06 03:50:45 +00:00
except KeyboardInterrupt:
redraw(EJECT)
return SETTINGS
if choice is not "":
if choice in QUITS:
redraw()
return SETTINGS
# editor selection
if settingList[int(choice)] == "editor":
SETTINGS.update({"editor": select_editor()})
redraw("text editor set to: {editor}".format(editor=SETTINGS["editor"]))
save_settings()
return setup()
# publishing selection
elif settingList[int(choice)] == "publishing":
SETTINGS.update({"publishing":select_publishing()})
core.reload_ttbprc(SETTINGS)
update_publishing()
redraw("publishing set to {publishing}".format(publishing=SETTINGS.get("publishing")))
save_settings()
return setup()
# publish dir selection
elif settingList[int(choice)] == "publish dir":
publish_dir = select_publish_dir()
SETTINGS.update({"publish dir": publish_dir})
#update_publishing()
if publish_dir is None:
redraw("sorry, i can't set a publish directory for you if you don't have html publishing enabled. please enable publishing to continue.")
else:
redraw("publishing your entries to {url}/index.html".format(
url="/".join([config.LIVE+config.USER,
str(SETTINGS.get("publish dir"))])))
save_settings()
return setup()
# gopher opt-in
elif settingList[int(choice)] == "gopher":
SETTINGS.update({'gopher': gopher.select_gopher()})
redraw('gopher publishing set to: {gopher}'.format(gopher=SETTINGS['gopher']))
update_gopher()
save_settings()
return setup()
# rainbow menu selection
elif settingList[int(choice)] == "rainbows":
SETTINGS.update({"rainbows": toggle_rainbows()})
redraw("rainbow menus set to {rainbow}".format(rainbow=SETTINGS.get("rainbows")))
save_settings()
return setup()
#nopub toggling
elif settingList[int(choice)] == "post as nopub":
SETTINGS.update({"post as nopub": toggle_pub_default()})
redraw("posting default set to {nopub}".format(nopub=SETTINGS.get("post as nopub")))
save_settings()
return setup()
input("\nyou're all good to go, {friend}! hit <enter> to continue.\n\n".format(friend=chatter.say("friend")))
2017-12-06 03:50:45 +00:00
redraw()
2016-05-01 22:43:12 +00:00
return SETTINGS
2018-01-02 06:21:48 +00:00
else:
redraw("now changing your settings. press <ctrl-c> if you didn't mean to do this.")
return setup()
2017-12-06 03:50:45 +00:00
def save_settings():
"""
Save current settings.
"""
ttbprc = open(config.TTBPRC, "w")
ttbprc.write(json.dumps(SETTINGS, sort_keys=True, indent=2, separators=(',',':')))
ttbprc.close()
2016-05-01 17:44:49 +00:00
## menus
2016-04-30 03:17:06 +00:00
def main_menu():
'''
main navigation menu
'''
2016-05-01 22:26:26 +00:00
menuOptions = [
2018-10-13 01:34:10 +00:00
"record some feels",
2018-03-12 03:46:15 +00:00
"manage your feels",
2016-05-03 17:46:54 +00:00
"check out your neighbors",
"browse global feels",
2018-10-13 01:34:10 +00:00
"visit your subscriptions",
"scribble some graffiti",
2016-05-03 17:46:54 +00:00
"change your settings",
"send some feedback",
"see credits",
"read documentation"]
print("you're at ttbp home. remember, you can always press <ctrl-c> to come back here.\n")
2018-01-02 06:21:48 +00:00
util.print_menu(menuOptions, SETTINGS.get("rainbows", False))
2016-05-01 17:44:49 +00:00
2016-05-01 22:26:26 +00:00
try:
2018-02-23 20:28:25 +00:00
choice = input("\ntell me about your feels (or type 'q' to exit): ")
2016-05-01 22:26:26 +00:00
except KeyboardInterrupt:
redraw(EJECT)
2016-05-01 22:26:26 +00:00
return main_menu()
2016-05-01 17:44:49 +00:00
if choice == '0':
2016-05-01 23:34:20 +00:00
redraw()
today = time.strftime("%Y%m%d")
write_entry(os.path.join(config.MAIN_FEELS, today+".txt"))
core.www_neighbors()
2016-05-01 17:44:49 +00:00
elif choice == '1':
2018-03-13 21:40:09 +00:00
intro = "here are some options for managing your feels:"
redraw(intro)
review_menu(intro)
core.load_files()
elif choice == '2':
users = core.find_ttbps()
prompt = "the following {usercount} {are} recording feels on ttbp:".format(
usercount=p.no("user", len(users)),
are=p.plural("is", len(users)))
redraw(prompt)
view_neighbors(users, prompt)
elif choice == '3':
redraw("most recent global entries")
2018-10-13 01:14:28 +00:00
view_global_feed()
elif choice == '4':
2018-10-14 17:25:07 +00:00
intro = "your subscriptions list is private; no one but you will know who you're following.\n\n> here are some options for your subscriptions:"
2018-10-13 01:34:10 +00:00
redraw(intro)
subscription_handler(intro)
elif choice == '5':
2018-10-13 01:34:10 +00:00
graffiti_handler()
elif choice == '6':
redraw("now changing your settings. press <ctrl-c> if you didn't mean to do this.")
2017-12-06 03:50:45 +00:00
core.load(setup()) # reload settings to core
2018-10-13 01:34:10 +00:00
elif choice == '7':
redraw("you're about to send mail to ~endorphant about ttbp")
feedback_menu()
2018-10-13 01:34:10 +00:00
elif choice == '8':
redraw()
show_credits()
2018-10-13 01:34:10 +00:00
elif choice == '9':
2018-03-23 03:16:45 +00:00
subprocess.call(["lynx", os.path.join(config.INSTALL_PATH, "..", "doc", "manual.html")])
redraw()
elif choice in QUITS:
2016-05-01 17:44:49 +00:00
return stop()
else:
2016-05-01 18:10:04 +00:00
redraw(INVALID)
2016-05-01 17:44:49 +00:00
return main_menu()
2016-04-30 03:17:06 +00:00
2016-05-01 17:44:49 +00:00
def feedback_menu():
'''
feedback handling menu
* selects feedback type
* calls feedback writing function
'''
2018-01-02 06:21:48 +00:00
util.print_menu(SUBJECTS, SETTINGS.get("rainbows", False))
2018-02-23 20:28:25 +00:00
choice = input("\npick a category for your feedback: ")
2016-04-30 03:17:06 +00:00
2016-05-01 17:44:49 +00:00
cat = ""
2016-05-03 17:14:53 +00:00
if choice in ['0', '1', '2', '3']:
2016-05-01 22:26:26 +00:00
cat = SUBJECTS[int(choice)]
2018-02-23 20:28:25 +00:00
entered = input("""
composing a {mail_category} to ~endorphant.
2016-05-15 04:22:05 +00:00
press <enter> to open an external text editor. mail will be sent once you save and quit.
""".format(mail_category=cat))
2016-05-15 04:22:05 +00:00
redraw(send_feedback(entered, cat))
2016-05-01 18:10:04 +00:00
return
2016-05-01 17:44:49 +00:00
else:
2016-05-01 18:10:04 +00:00
redraw(INVALID)
2016-05-01 17:44:49 +00:00
return feedback_menu()
def review_menu(intro=""):
'''
submenu for reviewing feels.
'''
menuOptions = [
"read over feels",
2018-03-12 02:30:10 +00:00
"modify feels publishing",
"backup your feels",
2018-03-17 02:38:01 +00:00
"import a feels backup",
2018-03-15 20:41:41 +00:00
"bury some feels",
2018-03-12 02:30:10 +00:00
"delete feels by day",
2018-03-13 21:40:09 +00:00
"purge all feels",
2018-03-16 05:30:48 +00:00
"wipe feels account"
]
2018-01-02 06:21:48 +00:00
util.print_menu(menuOptions, SETTINGS.get("rainbows", False))
choice = util.list_select(menuOptions, "what would you like to do with your feels? (or 'q' to return home) ")
2018-03-12 02:30:10 +00:00
top = ""
hasfeels = len(os.listdir(config.MAIN_FEELS)) > 0
2018-03-13 21:40:09 +00:00
nofeels = "you don't have any feels to work with, "+chatter.say("friend")+"\n\n> "
2018-03-12 02:30:10 +00:00
if choice is not False:
if choice == 0:
2018-03-13 21:40:09 +00:00
if hasfeels:
redraw("your recorded feels, listed by date:")
view_feels(config.USER)
else:
top = nofeels
elif choice == 1:
2018-03-13 21:40:09 +00:00
if hasfeels:
redraw("publishing status of your feels:")
list_nopubs(config.USER)
else:
top = nofeels
2018-03-12 02:30:10 +00:00
elif choice == 2:
2018-03-13 21:40:09 +00:00
if hasfeels:
redraw("FEELS BACKUP")
backup_feels()
else:
top = nofeels
2018-03-12 02:30:10 +00:00
elif choice == 3:
2018-03-17 02:38:01 +00:00
redraw("loading feels backup")
load_backup()
2018-03-15 20:41:41 +00:00
elif choice == 4:
2018-03-22 17:46:41 +00:00
if hasfeels:
redraw("burying feels")
bury_feels()
else:
top = nofeels
2018-03-17 02:38:01 +00:00
elif choice == 5:
2018-03-15 20:17:21 +00:00
if hasfeels:
redraw("deleting feels")
delete_feels()
else:
top = nofeels
2018-03-17 02:38:01 +00:00
elif choice == 6:
2018-03-13 21:40:09 +00:00
if hasfeels:
redraw("!!!PURGING ALL FEELS!!!")
purge_feels()
else:
top = nofeels
2018-03-16 05:30:48 +00:00
elif choice == 7:
redraw("!!! WIPING FEELS ACCOUNT !!!")
wipe_account()
else:
redraw()
return
2018-03-12 02:30:10 +00:00
redraw(top+intro)
return review_menu(intro)
2018-10-13 01:34:10 +00:00
def subscription_handler(intro=""):
'''
submenu for managing subscriptions
'''
2018-10-13 19:29:49 +00:00
if not os.path.exists(config.SUBS):
subprocess.call(["touch", config.SUBS])
subprocess.call(["chmod", "600", config.SUBS])
2018-10-13 22:50:44 +00:00
subs_raw = []
if os.path.isfile(config.SUBS):
for line in open(config.SUBS, "r"):
subs_raw.append(line.rstrip())
subs = []
all_users = core.find_ttbps()
for name in subs_raw:
if name in all_users:
subs.append(name)
2018-10-13 01:34:10 +00:00
menuOptions = [
"view subscribed feed",
"manage subscriptions"
]
util.print_menu(menuOptions, SETTINGS.get("rainbows", False))
choice = util.list_select(menuOptions, "what would you like to do with your subscriptions? (or 'q' to return home) ")
top = ""
if choice is not False:
if choice == 0:
2018-10-13 22:50:44 +00:00
if len(subs) > 0:
2018-10-14 19:00:51 +00:00
prompt = "most recent entries from your subscribed pals:"
redraw(prompt)
view_subscribed_feed(subs, prompt)
2018-10-13 22:50:44 +00:00
else:
intro = "it doesn't look like you have any subscriptions to see! add pals with 'manage subscriptions' here."
2018-10-13 01:34:10 +00:00
elif choice == 1:
2018-10-14 17:16:46 +00:00
prompt = "options for managing your subscriptions:"
redraw(prompt)
subscription_manager(subs, prompt)
2018-10-13 01:34:10 +00:00
else:
redraw()
return
redraw(top+intro)
return subscription_handler(intro)
def view_neighbors(users, prompt, page=0):
'''
generates list of all users on ttbp, sorted by most recent post
* if user is publishing, list publish directory
'''
userList = []
## assumes list of users passed in all have valid config files
for user in users:
userRC = json.load(open(os.path.join("/home", user, ".ttbp", "config", "ttbprc")))
## retrieve publishing url, if it exists
url="\t\t\t"
if userRC.get("publish dir"):
2017-11-21 06:02:10 +00:00
url = config.LIVE+user+"/"+userRC.get("publish dir")
## find last entry
try:
files = os.listdir(os.path.join("/home", user, ".ttbp", "entries"))
except OSError:
files = []
files.sort()
lastfile = ""
for filename in files:
if core.valid(filename):
lastfile = os.path.join("/home", user, ".ttbp", "entries", filename)
## generate human-friendly timestamp
ago = "never"
if lastfile:
last = os.path.getctime(lastfile)
since = time.time()-last
ago = util.pretty_time(int(since)) + " ago"
else:
last = 0
## some formatting handwavin
urlpad = ""
if ago == "never":
urlpad = "\t"
userpad = ""
if len(user) < 7:
userpad = "\t"
userList.append(["\t~{user}{userpad}\t({ago}){urlpad}\t{url}".format(user=user,
userpad=userpad, ago=ago, urlpad=urlpad, url=url), last, user])