forked from endorphant/ttbp
Merge branch 'master' of github.com:modgethanc/ttbp
commit
198bde8ed3
268
README.html
268
README.html
|
@ -1,160 +1,204 @@
|
||||||
<p><em>a command-line based blogging platform running on tilde.town</em></p>
|
<p><em>a command-line based blogging platform running on tilde.town</em></p>
|
||||||
|
|
||||||
<p><code>ttbp</code> stands for "tilde.town blogging platform", the original working name for
|
<p><code>ttbp</code> stands for "tilde.town blogging platform", the original working name for
|
||||||
this project.</p>
|
this project.</p>
|
||||||
|
<p><img alt="ttbp main menu screenshot" src="http://tilde.town/~endorphant/ttbp/screenshots/ttbp-main.png" /></p>
|
||||||
<p><img src="http://tilde.town/~endorphant/ttbp/screenshots/ttbp-main.png" alt="ttbp main menu screenshot" /></p>
|
<p><img alt="ttbp entries view screenshot" src="http://tilde.town/~endorphant/ttbp/screenshots/ttbp-entries.png" /></p>
|
||||||
|
<p><img alt="ttbp compose view screenshot" src="http://tilde.town/~endorphant/ttbp/screenshots/ttbp-compose.png" /></p>
|
||||||
<p><img src="http://tilde.town/~endorphant/ttbp/screenshots/ttbp-entries.png" alt="ttbp entries view screenshot" /></p>
|
|
||||||
|
|
||||||
<p><img src="http://tilde.town/~endorphant/ttbp/screenshots/ttbp-compose.png" alt="ttbp compose view screenshot" /></p>
|
|
||||||
|
|
||||||
<p><code>ttbp</code> runs from the command line, providing a hub for writing personal blog
|
<p><code>ttbp</code> runs from the command line, providing a hub for writing personal blog
|
||||||
posts and reading posts written by other users of tilde.town. it's a little bit
|
posts and reading posts written by other users of tilde.town. it's a little bit
|
||||||
like livejournal or dreamwidth or tumblr. you can opt to publish your posts to
|
like livejournal or dreamwidth or tumblr. you can opt to publish your posts to a
|
||||||
a public html file hosted on your tilde page, or keep all your entries private
|
public html file hosted on your tilde page, to tilde.town's gopher server, or
|
||||||
to the tilde.town server.</p>
|
keep all your entries private to the tilde.town server.</p>
|
||||||
|
|
||||||
<p>to use, run <code>feels</code> while logged in to tilde.town</p>
|
<p>to use, run <code>feels</code> while logged in to tilde.town</p>
|
||||||
|
<p>this is a project that runs on tilde.town, so all users of this program are
|
||||||
<p>(<code>feels</code> is a tilde.town specific command; if you're running this locally, or on
|
expected to operate under the tilde.town <a href="http://tilde.town/wiki/conduct.html">code of
|
||||||
a different server, run <code>ttbp</code> from the command line)</p>
|
conduct</a>. content/personal issues should be
|
||||||
|
worked out according to the CoC, with support from the <a href="http://tilde.town/wiki/administration/index.html">administrative
|
||||||
<h3 id="quickstart">QUICK START</h3>
|
team</a> if needed.</p>
|
||||||
|
<h3>QUICK START</h3>
|
||||||
<p>no coding or html experience is necessary to get started. just log in to your
|
<p>no coding or html experience is necessary to get started. just log in to your
|
||||||
tilde.town account and enter:</p>
|
tilde.town account and enter:</p>
|
||||||
|
|
||||||
<p><code>feels</code></p>
|
<p><code>feels</code></p>
|
||||||
|
|
||||||
<p>ttbp will ask you a few questions to get you started. after that, writing and
|
<p>ttbp will ask you a few questions to get you started. after that, writing and
|
||||||
reading entries all happen within the program.</p>
|
reading entries all happen within the program.</p>
|
||||||
|
|
||||||
<p>that's it!</p>
|
<p>that's it!</p>
|
||||||
|
<h3>support</h3>
|
||||||
<h3 id="support">SUPPORT</h3>
|
|
||||||
|
|
||||||
<p>if you're having trouble getting started, or run into program errors or strange
|
<p>if you're having trouble getting started, or run into program errors or strange
|
||||||
behavior, please send internal tilde.town mail to ~endorphant and i'll try to
|
behavior, please send internal tilde.town mail to ~endorphant and i'll try to
|
||||||
sort things out!</p>
|
sort things out!</p>
|
||||||
|
<p>there's also a function from the main menu that lets you send feedback/inquiries
|
||||||
<h3 id="writingentries">writing entries</h3>
|
to me directly; this uses internal tilde.town mail, which is what i'll respond
|
||||||
|
to.</p>
|
||||||
<p>entries are recorded as plaintext files in your ~/.ttbp/entries
|
<h3>writing entries</h3>
|
||||||
directory. you can edit them there directly, or fix old entries, or
|
<p>entries are recorded as plaintext files in your <code>~/.ttbp/entries</code> directory.
|
||||||
delete entries.</p>
|
<code>ttbp</code> will use your selected editor to open and write files; each day is its
|
||||||
|
own entry, like a diary page. at midnight for whatever timezone you've set for
|
||||||
<p><em>warning</em>: changing old entries might cause strange things to
|
your user account on tilde.town, you'll get a fresh entry. if you don't write
|
||||||
happen with timestamps. the main program looks at the filename
|
any feels on a particular day, no entries will show up there.</p>
|
||||||
first for setting the date, then the last modified time to sort
|
<p>when you save and quit the text editor, your entry will automatically propagate
|
||||||
recent posts. it expects YYYMMDD.txt as the filename; anything else
|
to the global feels list; if you've opted to publish your feels to html/gopher,
|
||||||
won't show up as a valid entry. yes, this means you can post things out
|
those files will update immediately. you can always go back to the current day's
|
||||||
of date order by creating files with any date you want.</p>
|
entry and edit/add as you'd like, but older entries will not be available for
|
||||||
|
editing from <code>ttbp</code>.</p>
|
||||||
<h4 id="generalentrywritingnotes">general entry-writing notes</h4>
|
<p><em>(since files are just stored as plaintext in your directory, it's possible to
|
||||||
|
edit and move old entries directly from the command line. however, changing old
|
||||||
|
entries might cause strange things to happen with timestamps. the main program
|
||||||
|
looks at the filename first for setting the date, then the last modified time to
|
||||||
|
sort recent posts. it expects YYYMMDD.txt as the filename; anything else won't
|
||||||
|
show up as a valid entry. yes, this means you can post things out of date order
|
||||||
|
by creating files with any date you want.)</em></p>
|
||||||
|
<h4>general entry-writing notes</h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li>you can use <a href="https://daringfireball.net/projects/markdown/syntax">markdown</a></li>
|
<li>you can use <a href="https://daringfireball.net/projects/markdown/syntax">markdown</a></li>
|
||||||
|
|
||||||
<li>you can use html</li>
|
<li>you can use html</li>
|
||||||
|
|
||||||
<li>you can also put things between <code><!-- comments --></code> to have them show up
|
<li>you can also put things between <code><!-- comments --></code> to have them show up
|
||||||
in the feed but not render in a browser (but people can still read
|
in the feed but not render in a browser (but people can still read
|
||||||
them with view-source)</li>
|
them with view-source)</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<h3>reading other feels</h3>
|
||||||
<h3 id="privacy">privacy</h3>
|
<p>the <code>browse global feels</code> feature shows the ten most recent entries that anyone
|
||||||
|
has written on ttbp. this list is only accessible from within tilde.town,
|
||||||
|
although individual entries may be posted to html or gopher.</p>
|
||||||
|
<p>you can also pull up a list of a single user's feels through <code>check out your
|
||||||
|
neighbors</code>, which displays all users who are writing on <code>ttbp</code> based on their
|
||||||
|
most recently updated entry, and a link to their public html blog if they've
|
||||||
|
opted to publish their posts.</p>
|
||||||
|
<p><strong>please note!</strong> entries written on <code>ttbp</code> should be considered sensitive,
|
||||||
|
private information, even if a particular user is publishing entries in a
|
||||||
|
world-viewable way! please be respectful about having access to other people's
|
||||||
|
feels, and do not copy/repeat any information without getting their explicit
|
||||||
|
permission. tilde.town operates on a high level of mutual trust, and <code>ttbp</code> is
|
||||||
|
designed to give individuals control over their content.</p>
|
||||||
|
<h3>privacy</h3>
|
||||||
<p>when you start your ttbp, you have the option of publishing or not publishing
|
<p>when you start your ttbp, you have the option of publishing or not publishing
|
||||||
your blog.</p>
|
your blog.</p>
|
||||||
|
<p>if you opt to not publish, your entires will never be accessible from outside of
|
||||||
<p>if you opt to publish, the program creates a directory <code>~/.ttbp/www</code>
|
the tilde.town network; other tilde.town users will still be able to read your
|
||||||
where it stores all html files it generates, and symlinks this from your
|
entries through the ttbp interface, or by directly accessing your
|
||||||
<code>~/public_html</code> with your chosen blog directory. your blog will also be listed
|
|
||||||
on the <a href="https://tilde.town/~endorphant/ttbp">main ttbp page</a>.</p>
|
|
||||||
|
|
||||||
<p>if you opt to not publish, your entires will never be accessible from outside
|
|
||||||
of the tilde.town network; other tilde.town users will still be able to read
|
|
||||||
your entries through the ttbp interface, or by directly accessing your
|
|
||||||
<code>~/.ttbp/entries</code> directory.</p>
|
<code>~/.ttbp/entries</code> directory.</p>
|
||||||
|
|
||||||
<p>if you want to further protect your entries, you can <code>chmod 700</code> your entries
|
<p>if you want to further protect your entries, you can <code>chmod 700</code> your entries
|
||||||
directory.</p>
|
directory.</p>
|
||||||
|
<p>if you opt to publish, the program creates a directory <code>~/.ttbp/www</code> where it
|
||||||
<h3 id="changingyourpagelayout">changing your page layout</h3>
|
stores all html files it generates, and symlinks this from your <code>~/public_html</code>
|
||||||
|
with your chosen blog directory. your blog will also be listed on the <a href="https://tilde.town/~endorphant/ttbp">main ttbp
|
||||||
<p>you can modify how your blog looks by editing the stylesheet or
|
page</a>.</p>
|
||||||
header and footer files. the program sets you up with basic
|
<p>you can also opt to publish to gopher, and the program will automatically
|
||||||
default. if you break your page somehow, you can force the program to
|
generate a gophermap of your feels.</p>
|
||||||
regenerate your configuration by deleting your ~/.ttbp directory entirely.
|
<p>you can set publishing status on individual entries, or bury individual feels;
|
||||||
<strong>you might want to back up your ~/.ttbp/entries directory before you do
|
see "data management" below for details.</p>
|
||||||
this.</strong></p>
|
<h3>data management</h3>
|
||||||
|
<p>the <code>manage your feels</code> menu provides several tools for organizing your feels.
|
||||||
|
these are all actions you can perform manually from the command line, but doing
|
||||||
|
them from within the program can help keep your files properly linked up.</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>to modify your stylesheet, edit your ~/.ttbp/config/style.css
|
<li><strong>read over feels</strong>--a list of all your entries, which you can open and
|
||||||
|
read like any other feel</li>
|
||||||
|
<li><strong>modify feels publishing</strong>--this lets you toggle privacy on individual
|
||||||
|
posts. entries marked <code>(nopub)</code> will not get written to html or gopher,
|
||||||
|
and toggling them from this menu will immediately publish or unpublish
|
||||||
|
that entry (if you're not publishing your posts at all, these settings
|
||||||
|
won't matter, since your feels will never show up outside of tilde.town)</li>
|
||||||
|
<li><strong>backup your feels</strong>--makes a .tar.gz of all your entries, saving one
|
||||||
|
copy to <code>~/.ttbp/backups/</code> with the current date, and a second copy to
|
||||||
|
your home directory for safekeeping.</li>
|
||||||
|
<li><strong>import a feels backup</strong>--unpacks a backup file into your current feels
|
||||||
|
list. this tool checks the <code>~/.ttbp/backups</code> directory for archives, and
|
||||||
|
expects a file created by the above backup utility. if it detects any file
|
||||||
|
collisions, it will preserve your current live copy and leave the backup
|
||||||
|
verison in a temp directory, and notify you that this happened. also, any
|
||||||
|
entries that were previously marked as <code>(nopub)</code> will retain their nopub
|
||||||
|
status.</li>
|
||||||
|
<li><strong>bury some feels</strong>--hides individual feels from viewing; entries are
|
||||||
|
moved to <code>~/.ttbp/buried</code> (and marked with a unique timestamp to prevent
|
||||||
|
file collision) with permissions set to 600, meaning no one except you
|
||||||
|
will be able to open that file. these entries are also hidden from your
|
||||||
|
own view from <code>read over feels</code>, and you'll have to open the files from
|
||||||
|
the command line if you want to see them. this is intended to be a
|
||||||
|
permament action, so you'll be asked to type the entry date once to load
|
||||||
|
the feel, then shown a preview of that feel, and then type the date again
|
||||||
|
to confirm burying.</li>
|
||||||
|
<li><strong>delete feels by day</strong>--<em>permanently removes individual entries</em>,
|
||||||
|
including deleting published html/gopher files if needed. this action is
|
||||||
|
not recoverable, unless you have a backup to restore; you'll be asked to
|
||||||
|
type the entry date once to load the feel, then shown a preview of that
|
||||||
|
feel, and then type the date again to confirm deletion.</li>
|
||||||
|
<li><strong>purge all feels</strong>--<em>permanently removes all feels</em>, including deleting
|
||||||
|
all published html/gopher files if needed. this action is not recoverable,
|
||||||
|
unless you have a backup to restore. you'll be asked to type a
|
||||||
|
one-time-use purge code to confirm this action.</li>
|
||||||
|
<li><strong>wipe feels account</strong>--<em>permanently removes all data associated with
|
||||||
|
feels</em>, including deleting any published hmtl/gopher files and removing
|
||||||
|
your <code>~/.ttbp</code> directory. any backups that you have in <code>~/.ttbp/backups</code>
|
||||||
|
will also be deleted with this action (which is why the backup function
|
||||||
|
makes a second copy for safekeeping in your home directory). you will no
|
||||||
|
longer show up in any lists as a user.</li>
|
||||||
|
</ul>
|
||||||
|
<h3>settings</h3>
|
||||||
|
<p>the settings menu lets you change specific options for handling your feels and
|
||||||
|
using the interface.</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>(future feature: having multiple stylesheets you can select)</li></ul>
|
<li><strong>editor</strong>--set your text editor</li>
|
||||||
</li>
|
<li><strong>gopher</strong>--opt in or out of automatically posting to gopher</li>
|
||||||
|
<li><strong>post as nopub</strong>--set whether posts default to being published or not
|
||||||
<li>to modify the page header, edit your ~/.ttbp/config/header.txt
|
published (if you're not publishing your feels, this doesn't matter)</li>
|
||||||
|
<li><strong>publish dir</strong>--set the directory under you <code>public_html</code> where feels will be
|
||||||
|
published (if you're not publishing your feels, this defaults to <code>None</code>)</li>
|
||||||
|
<li><strong>publishing</strong>--opt in or out of automatically publishing entries to a
|
||||||
|
world-readable html page</li>
|
||||||
|
<li><strong>rainbows</strong>--opt in or out of having multicolored menu text</li>
|
||||||
|
</ul>
|
||||||
|
<h3>changing your page layout</h3>
|
||||||
|
<p>you can modify how your blog looks by editing the stylesheet or header and
|
||||||
|
footer files. the program sets you up with basic default. if you break your page
|
||||||
|
somehow, you can force the program to regenerate your configuration by deleting
|
||||||
|
your ~/.ttbp directory entirely. <strong>you might want to back up your
|
||||||
|
~/.ttbp/entries directory before you do this.</strong></p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>you might note that there's a place marked off in the default header where
|
<li>to modify your stylesheet, edit your ~/.ttbp/config/style.css</li>
|
||||||
you can safely put custom HTML elements!</li></ul>
|
<li>to modify the page header, edit your ~/.ttbp/config/header.txt</li>
|
||||||
</li>
|
<li>there's a place marked off in the default header where you can safely put
|
||||||
|
custom HTML elements!</li>
|
||||||
<li>to modify the page footer, edit your ~/.ttbp/config/footer.txt</li>
|
<li>to modify the page footer, edit your ~/.ttbp/config/footer.txt</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<h3>general tips/troubleshooting</h3>
|
||||||
<h3 id="generaltipstroubleshooting">general tips/troubleshooting</h3>
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>add <code>alias ttbp="~endorphant/bin/ttbp"</code> to your .bash_aliases for fewer keystrokes</li>
|
|
||||||
|
|
||||||
<li>(similarly, <code>alias ttbp-beta="~endorphant/bin/ttbp-beta"</code>)</li>
|
|
||||||
|
|
||||||
<li>if the date looks like it's ahead or behind, it's because you haven't set
|
<li>if the date looks like it's ahead or behind, it's because you haven't set
|
||||||
your local timezone yet. here are some
|
your local timezone yet. here are some
|
||||||
<a href="http://www.cyberciti.biz/faq/linux-unix-set-tz-environment-variable/">timezone setting instructions</a></li>
|
<a href="http://www.cyberciti.biz/faq/linux-unix-set-tz-environment-variable/">timezone setting instructions</a></li>
|
||||||
|
<li>the feels burying tool will effectively clear your post for the day; you can
|
||||||
|
use this feature to start a fresh entry on a particular day by burying the
|
||||||
|
current day's feels and then editing a new file</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<h3>future features</h3>
|
||||||
<h3 id="futurefeatures">future features</h3>
|
|
||||||
|
|
||||||
<p>these are a few ideas being kicked around, or under active development:</p>
|
<p>these are a few ideas being kicked around, or under active development:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>better entry privacy/publish control options</li>
|
|
||||||
|
|
||||||
<li>stylesheet/theme selector</li>
|
<li>stylesheet/theme selector</li>
|
||||||
|
<li>better entry display within ttbp (currently just offloads to <code>less</code>)</li>
|
||||||
<li>responding to entries</li>
|
<li>buried feels browser</li>
|
||||||
|
|
||||||
<li>paginated list view</li>
|
|
||||||
|
|
||||||
<li>better entry display within ttbp</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
<p>other ideas are listed on github as
|
||||||
<h3 id="dependencies">dependencies</h3>
|
<a href="https://github.com/modgethanc/ttbp/issues?q=is%3Aissue+is%3Aopen+label%3A" title="upcoming+features">upcoming features</a> or <a href="https://github.com/modgethanc/ttbp/issues?q=is%3Aissue+is%3Aopen+label%3A" title="feature+request">feature requests</a>!</p>
|
||||||
|
<h3>dependencies</h3>
|
||||||
<p>(this section is only relevant if you plan on forking the repo and running an
|
<p>(this section is only relevant if you plan on forking the repo and running an
|
||||||
instance of this yourself)</p>
|
instance of this yourself)</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://pypi.python.org/pypi/mistune">mistune</a></li>
|
<li><a href="https://pypi.python.org/pypi/mistune">mistune</a></li>
|
||||||
|
|
||||||
<li><a href="https://pypi.python.org/pypi/inflect">inflect</a></li>
|
<li><a href="https://pypi.python.org/pypi/inflect">inflect</a></li>
|
||||||
|
<li><a href="https://pypi.python.org/pypi/six">six</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<h3>contributing</h3>
|
||||||
<h3 id="contributing">contributing</h3>
|
|
||||||
|
|
||||||
<p>please check out my <a href="https://github.com/modgethanc/ttbp/blob/master/.github/CONTRIBUTING.md">contributor
|
<p>please check out my <a href="https://github.com/modgethanc/ttbp/blob/master/.github/CONTRIBUTING.md">contributor
|
||||||
guidelines</a>
|
guidelines</a>
|
||||||
on github if you'd like to get involved with development!</p>
|
on github if you'd like to get involved with development!</p>
|
||||||
|
|
||||||
<p>if you find any bugs or strange behavior, please message me locally on tildemail
|
<p>if you find any bugs or strange behavior, please message me locally on tildemail
|
||||||
or open a github issue and i'll get back to you as soon as i can.</p>
|
or open a github issue and i'll get back to you as soon as i can.</p>
|
||||||
|
<p>if you're interested in helping with the code, please drop me some tildemail!</p>
|
||||||
<p>if you're interested in helping with the code, please drop me some tildemail!</p>
|
<p>i accept tips for development work on
|
||||||
|
<a href="https://liberapay.com/modgethanc">liberapay</a></p>
|
||||||
|
<h3>contributor shout-outs</h3>
|
||||||
|
<p>thanks to:</p>
|
||||||
|
<ul>
|
||||||
|
<li>~vilmibm, packaging help and gopher support</li>
|
||||||
|
<li>~sanqui, the bug swatter</li>
|
||||||
|
<li>~sinacutie, for css updates</li>
|
||||||
|
</ul>
|
196
README.md
196
README.md
|
@ -11,14 +11,18 @@ this project.
|
||||||
|
|
||||||
`ttbp` runs from the command line, providing a hub for writing personal blog
|
`ttbp` runs from the command line, providing a hub for writing personal blog
|
||||||
posts and reading posts written by other users of tilde.town. it's a little bit
|
posts and reading posts written by other users of tilde.town. it's a little bit
|
||||||
like livejournal or dreamwidth or tumblr. you can opt to publish your posts to
|
like livejournal or dreamwidth or tumblr. you can opt to publish your posts to a
|
||||||
a public html file hosted on your tilde page, or keep all your entries private
|
public html file hosted on your tilde page, to tilde.town's gopher server, or
|
||||||
to the tilde.town server.
|
keep all your entries private to the tilde.town server.
|
||||||
|
|
||||||
to use, run `feels` while logged in to tilde.town
|
to use, run `feels` while logged in to tilde.town
|
||||||
|
|
||||||
(`feels` is a tilde.town specific command; if you're running this locally, or on
|
this is a project that runs on tilde.town, so all users of this program are
|
||||||
a different server, run `ttbp` from the command line)
|
expected to operate under the tilde.town [code of
|
||||||
|
conduct](http://tilde.town/wiki/conduct.html). content/personal issues should be
|
||||||
|
worked out according to the CoC, with support from the [administrative
|
||||||
|
team](http://tilde.town/wiki/administration/index.html) if needed.
|
||||||
|
|
||||||
|
|
||||||
### QUICK START
|
### QUICK START
|
||||||
|
|
||||||
|
@ -32,84 +36,184 @@ reading entries all happen within the program.
|
||||||
|
|
||||||
that's it!
|
that's it!
|
||||||
|
|
||||||
### SUPPORT
|
### support
|
||||||
|
|
||||||
if you're having trouble getting started, or run into program errors or strange
|
if you're having trouble getting started, or run into program errors or strange
|
||||||
behavior, please send internal tilde.town mail to ~endorphant and i'll try to
|
behavior, please send internal tilde.town mail to ~endorphant and i'll try to
|
||||||
sort things out!
|
sort things out!
|
||||||
|
|
||||||
|
there's also a function from the main menu that lets you send feedback/inquiries
|
||||||
|
to me directly; this uses internal tilde.town mail, which is what i'll respond
|
||||||
|
to.
|
||||||
|
|
||||||
### writing entries
|
### writing entries
|
||||||
|
|
||||||
entries are recorded as plaintext files in your ~/.ttbp/entries
|
entries are recorded as plaintext files in your `~/.ttbp/entries` directory.
|
||||||
directory. you can edit them there directly, or fix old entries, or
|
`ttbp` will use your selected editor to open and write files; each day is its
|
||||||
delete entries.
|
own entry, like a diary page. at midnight for whatever timezone you've set for
|
||||||
|
your user account on tilde.town, you'll get a fresh entry. if you don't write
|
||||||
|
any feels on a particular day, no entries will show up there.
|
||||||
|
|
||||||
*warning*: changing old entries might cause strange things to
|
when you save and quit the text editor, your entry will automatically propagate
|
||||||
happen with timestamps. the main program looks at the filename
|
to the global feels list; if you've opted to publish your feels to html/gopher,
|
||||||
first for setting the date, then the last modified time to sort
|
those files will update immediately. you can always go back to the current day's
|
||||||
recent posts. it expects YYYMMDD.txt as the filename; anything else
|
entry and edit/add as you'd like, but older entries will not be available for
|
||||||
won't show up as a valid entry. yes, this means you can post things out
|
editing from `ttbp`.
|
||||||
of date order by creating files with any date you want.
|
|
||||||
|
*(since files are just stored as plaintext in your directory, it's possible to
|
||||||
|
edit and move old entries directly from the command line. however, changing old
|
||||||
|
entries might cause strange things to happen with timestamps. the main program
|
||||||
|
looks at the filename first for setting the date, then the last modified time to
|
||||||
|
sort recent posts. it expects YYYMMDD.txt as the filename; anything else won't
|
||||||
|
show up as a valid entry. yes, this means you can post things out of date order
|
||||||
|
by creating files with any date you want.)*
|
||||||
|
|
||||||
#### general entry-writing notes
|
#### general entry-writing notes
|
||||||
|
|
||||||
* you can use [markdown](https://daringfireball.net/projects/markdown/syntax)
|
* you can use [markdown](https://daringfireball.net/projects/markdown/syntax)
|
||||||
* you can use html
|
* you can use html
|
||||||
* you can also put things between `<!-- comments -->` to have them show up
|
* you can also put things between `<!-- comments -->` to have them show up
|
||||||
in the feed but not render in a browser (but people can still read
|
in the feed but not render in a browser (but people can still read
|
||||||
them with view-source)
|
them with view-source)
|
||||||
|
|
||||||
|
### reading other feels
|
||||||
|
|
||||||
|
the `browse global feels` feature shows the ten most recent entries that anyone
|
||||||
|
has written on ttbp. this list is only accessible from within tilde.town,
|
||||||
|
although individual entries may be posted to html or gopher.
|
||||||
|
|
||||||
|
you can also pull up a list of a single user's feels through `check out your
|
||||||
|
neighbors`, which displays all users who are writing on `ttbp` based on their
|
||||||
|
most recently updated entry, and a link to their public html blog if they've
|
||||||
|
opted to publish their posts.
|
||||||
|
|
||||||
|
**please note!** entries written on `ttbp` should be considered sensitive,
|
||||||
|
private information, even if a particular user is publishing entries in a
|
||||||
|
world-viewable way! please be respectful about having access to other people's
|
||||||
|
feels, and do not copy/repeat any information without getting their explicit
|
||||||
|
permission. tilde.town operates on a high level of mutual trust, and `ttbp` is
|
||||||
|
designed to give individuals control over their content.
|
||||||
|
|
||||||
### privacy
|
### privacy
|
||||||
|
|
||||||
when you start your ttbp, you have the option of publishing or not publishing
|
when you start your ttbp, you have the option of publishing or not publishing
|
||||||
your blog.
|
your blog.
|
||||||
|
|
||||||
if you opt to publish, the program creates a directory `~/.ttbp/www`
|
if you opt to not publish, your entires will never be accessible from outside of
|
||||||
where it stores all html files it generates, and symlinks this from your
|
the tilde.town network; other tilde.town users will still be able to read your
|
||||||
`~/public_html` with your chosen blog directory. your blog will also be listed
|
entries through the ttbp interface, or by directly accessing your
|
||||||
on the [main ttbp page](https://tilde.town/~endorphant/ttbp).
|
|
||||||
|
|
||||||
if you opt to not publish, your entires will never be accessible from outside
|
|
||||||
of the tilde.town network; other tilde.town users will still be able to read
|
|
||||||
your entries through the ttbp interface, or by directly accessing your
|
|
||||||
`~/.ttbp/entries` directory.
|
`~/.ttbp/entries` directory.
|
||||||
|
|
||||||
if you want to further protect your entries, you can `chmod 700` your entries
|
if you want to further protect your entries, you can `chmod 700` your entries
|
||||||
directory.
|
directory.
|
||||||
|
|
||||||
|
if you opt to publish, the program creates a directory `~/.ttbp/www` where it
|
||||||
|
stores all html files it generates, and symlinks this from your `~/public_html`
|
||||||
|
with your chosen blog directory. your blog will also be listed on the [main ttbp
|
||||||
|
page](https://tilde.town/~endorphant/ttbp).
|
||||||
|
|
||||||
|
you can also opt to publish to gopher, and the program will automatically
|
||||||
|
generate a gophermap of your feels.
|
||||||
|
|
||||||
|
you can set publishing status on individual entries, or bury individual feels;
|
||||||
|
see "data management" below for details.
|
||||||
|
|
||||||
|
### data management
|
||||||
|
|
||||||
|
the `manage your feels` menu provides several tools for organizing your feels.
|
||||||
|
these are all actions you can perform manually from the command line, but doing
|
||||||
|
them from within the program can help keep your files properly linked up.
|
||||||
|
|
||||||
|
* **read over feels**--a list of all your entries, which you can open and
|
||||||
|
read like any other feel
|
||||||
|
* **modify feels publishing**--this lets you toggle privacy on individual
|
||||||
|
posts. entries marked `(nopub)` will not get written to html or gopher,
|
||||||
|
and toggling them from this menu will immediately publish or unpublish
|
||||||
|
that entry (if you're not publishing your posts at all, these settings
|
||||||
|
won't matter, since your feels will never show up outside of tilde.town)
|
||||||
|
* **backup your feels**--makes a .tar.gz of all your entries, saving one
|
||||||
|
copy to `~/.ttbp/backups/` with the current date, and a second copy to
|
||||||
|
your home directory for safekeeping.
|
||||||
|
* **import a feels backup**--unpacks a backup file into your current feels
|
||||||
|
list. this tool checks the `~/.ttbp/backups` directory for archives, and
|
||||||
|
expects a file created by the above backup utility. if it detects any file
|
||||||
|
collisions, it will preserve your current live copy and leave the backup
|
||||||
|
verison in a temp directory, and notify you that this happened. also, any
|
||||||
|
entries that were previously marked as `(nopub)` will retain their nopub
|
||||||
|
status.
|
||||||
|
* **bury some feels**--hides individual feels from viewing; entries are
|
||||||
|
moved to `~/.ttbp/buried` (and marked with a unique timestamp to prevent
|
||||||
|
file collision) with permissions set to 600, meaning no one except you
|
||||||
|
will be able to open that file. these entries are also hidden from your
|
||||||
|
own view from `read over feels`, and you'll have to open the files from
|
||||||
|
the command line if you want to see them. this is intended to be a
|
||||||
|
permament action, so you'll be asked to type the entry date once to load
|
||||||
|
the feel, then shown a preview of that feel, and then type the date again
|
||||||
|
to confirm burying.
|
||||||
|
* **delete feels by day**--*permanently removes individual entries*,
|
||||||
|
including deleting published html/gopher files if needed. this action is
|
||||||
|
not recoverable, unless you have a backup to restore; you'll be asked to
|
||||||
|
type the entry date once to load the feel, then shown a preview of that
|
||||||
|
feel, and then type the date again to confirm deletion.
|
||||||
|
* **purge all feels**--*permanently removes all feels*, including deleting
|
||||||
|
all published html/gopher files if needed. this action is not recoverable,
|
||||||
|
unless you have a backup to restore. you'll be asked to type a
|
||||||
|
one-time-use purge code to confirm this action.
|
||||||
|
* **wipe feels account**--*permanently removes all data associated with
|
||||||
|
feels*, including deleting any published hmtl/gopher files and removing
|
||||||
|
your `~/.ttbp` directory. any backups that you have in `~/.ttbp/backups`
|
||||||
|
will also be deleted with this action (which is why the backup function
|
||||||
|
makes a second copy for safekeeping in your home directory). you will no
|
||||||
|
longer show up in any lists as a user.
|
||||||
|
|
||||||
|
### settings
|
||||||
|
|
||||||
|
the settings menu lets you change specific options for handling your feels and
|
||||||
|
using the interface.
|
||||||
|
|
||||||
|
* **editor**--set your text editor
|
||||||
|
* **gopher**--opt in or out of automatically posting to gopher
|
||||||
|
* **post as nopub**--set whether posts default to being published or not
|
||||||
|
published (if you're not publishing your feels, this doesn't matter)
|
||||||
|
* **publish dir**--set the directory under you `public_html` where feels will be
|
||||||
|
published (if you're not publishing your feels, this defaults to `None`)
|
||||||
|
* **publishing**--opt in or out of automatically publishing entries to a
|
||||||
|
world-readable html page
|
||||||
|
* **rainbows**--opt in or out of having multicolored menu text
|
||||||
|
|
||||||
### changing your page layout
|
### changing your page layout
|
||||||
|
|
||||||
you can modify how your blog looks by editing the stylesheet or
|
you can modify how your blog looks by editing the stylesheet or header and
|
||||||
header and footer files. the program sets you up with basic
|
footer files. the program sets you up with basic default. if you break your page
|
||||||
default. if you break your page somehow, you can force the program to
|
somehow, you can force the program to regenerate your configuration by deleting
|
||||||
regenerate your configuration by deleting your ~/.ttbp directory entirely.
|
your ~/.ttbp directory entirely. **you might want to back up your
|
||||||
**you might want to back up your ~/.ttbp/entries directory before you do
|
~/.ttbp/entries directory before you do this.**
|
||||||
this.**
|
|
||||||
|
|
||||||
* to modify your stylesheet, edit your ~/.ttbp/config/style.css
|
* to modify your stylesheet, edit your ~/.ttbp/config/style.css
|
||||||
* (future feature: having multiple stylesheets you can select)
|
|
||||||
* to modify the page header, edit your ~/.ttbp/config/header.txt
|
* to modify the page header, edit your ~/.ttbp/config/header.txt
|
||||||
* you might note that there's a place marked off in the default header where
|
* there's a place marked off in the default header where you can safely put
|
||||||
you can safely put custom HTML elements!
|
custom HTML elements!
|
||||||
* to modify the page footer, edit your ~/.ttbp/config/footer.txt
|
* to modify the page footer, edit your ~/.ttbp/config/footer.txt
|
||||||
|
|
||||||
### general tips/troubleshooting
|
### general tips/troubleshooting
|
||||||
|
|
||||||
* add `alias ttbp="~endorphant/bin/ttbp"` to your .bash_aliases for fewer keystrokes
|
|
||||||
* (similarly, `alias ttbp-beta="~endorphant/bin/ttbp-beta"`)
|
|
||||||
* if the date looks like it's ahead or behind, it's because you haven't set
|
* if the date looks like it's ahead or behind, it's because you haven't set
|
||||||
your local timezone yet. here are some
|
your local timezone yet. here are some
|
||||||
[timezone setting instructions](http://www.cyberciti.biz/faq/linux-unix-set-tz-environment-variable/)
|
[timezone setting instructions](http://www.cyberciti.biz/faq/linux-unix-set-tz-environment-variable/)
|
||||||
|
* the feels burying tool will effectively clear your post for the day; you can
|
||||||
|
use this feature to start a fresh entry on a particular day by burying the
|
||||||
|
current day's feels and then editing a new file
|
||||||
|
|
||||||
### future features
|
### future features
|
||||||
|
|
||||||
these are a few ideas being kicked around, or under active development:
|
these are a few ideas being kicked around, or under active development:
|
||||||
|
|
||||||
* better entry privacy/publish control options
|
|
||||||
* stylesheet/theme selector
|
* stylesheet/theme selector
|
||||||
* responding to entries
|
* better entry display within ttbp (currently just offloads to `less`)
|
||||||
* paginated list view
|
* buried feels browser
|
||||||
* better entry display within ttbp
|
|
||||||
|
other ideas are listed on github as
|
||||||
|
[upcoming features](https://github.com/modgethanc/ttbp/issues?q=is%3Aissue+is%3Aopen+label%3A"upcoming+features") or [feature requests](https://github.com/modgethanc/ttbp/issues?q=is%3Aissue+is%3Aopen+label%3A"feature+request")!
|
||||||
|
|
||||||
### dependencies
|
### dependencies
|
||||||
|
|
||||||
|
@ -118,6 +222,7 @@ instance of this yourself)
|
||||||
|
|
||||||
* [mistune](https://pypi.python.org/pypi/mistune)
|
* [mistune](https://pypi.python.org/pypi/mistune)
|
||||||
* [inflect](https://pypi.python.org/pypi/inflect)
|
* [inflect](https://pypi.python.org/pypi/inflect)
|
||||||
|
* [six](https://pypi.python.org/pypi/six)
|
||||||
|
|
||||||
### contributing
|
### contributing
|
||||||
|
|
||||||
|
@ -129,3 +234,14 @@ if you find any bugs or strange behavior, please message me locally on tildemail
|
||||||
or open a github issue and i'll get back to you as soon as i can.
|
or open a github issue and i'll get back to you as soon as i can.
|
||||||
|
|
||||||
if you're interested in helping with the code, please drop me some tildemail!
|
if you're interested in helping with the code, please drop me some tildemail!
|
||||||
|
|
||||||
|
i accept tips for development work on
|
||||||
|
[liberapay](https://liberapay.com/modgethanc)
|
||||||
|
|
||||||
|
### contributor shout-outs
|
||||||
|
|
||||||
|
thanks to:
|
||||||
|
|
||||||
|
* ~vilmibm, packaging help and gopher support
|
||||||
|
* ~sanqui, the bug swatter
|
||||||
|
* ~sinacutie, for css updates
|
||||||
|
|
|
@ -0,0 +1,170 @@
|
||||||
|
<h1>FEELS MANUAL</h1>
|
||||||
|
<p><code>ttbp</code> stands for "tilde.town blogging platform", the original working name for
|
||||||
|
this project. the complete codebase is available on
|
||||||
|
<a href="https://github.com/modgethanc/ttbp">github</a>.</p>
|
||||||
|
<p><code>ttbp</code> runs from the command line, providing a hub for writing personal blog
|
||||||
|
posts and reading posts written by other users of tilde.town. it's a little bit
|
||||||
|
like livejournal or dreamwidth or tumblr. you can opt to publish your posts to a
|
||||||
|
public html file hosted on your tilde page, to tilde.town's gopher server, or
|
||||||
|
keep all your entries private to the tilde.town server.</p>
|
||||||
|
<p>this is a project that runs on tilde.town, so all users of this program are
|
||||||
|
expected to operate under the tilde.town <a href="http://tilde.town/wiki/conduct.html">code of
|
||||||
|
conduct</a>. content/personal issues should be
|
||||||
|
worked out according to the CoC, with support from the <a href="http://tilde.town/wiki/administration/index.html">administrative
|
||||||
|
team</a> if needed.</p>
|
||||||
|
<h3>support</h3>
|
||||||
|
<p>if you're having trouble getting started, or run into program errors or strange
|
||||||
|
behavior, please send internal tilde.town mail to ~endorphant and i'll try to
|
||||||
|
sort things out!</p>
|
||||||
|
<p>there's also a function from the main menu that lets you send feedback/inquiries
|
||||||
|
to me directly; this uses internal tilde.town mail, which is what i'll respond
|
||||||
|
to.</p>
|
||||||
|
<h3>writing entries</h3>
|
||||||
|
<p>entries are recorded as plaintext files in your <code>~/.ttbp/entries</code> directory.
|
||||||
|
<code>ttbp</code> will use your selected editor to open and write files; each day is its
|
||||||
|
own entry, like a diary page. at midnight for whatever timezone you've set for
|
||||||
|
your user account on tilde.town, you'll get a fresh entry. if you don't write
|
||||||
|
any feels on a particular day, no entries will show up there.</p>
|
||||||
|
<p>when you save and quit the text editor, your entry will automatically propagate
|
||||||
|
to the global feels list; if you've opted to publish your feels to html/gopher,
|
||||||
|
those files will update immediately. you can always go back to the current day's
|
||||||
|
entry and edit/add as you'd like, but older entries will not be available for
|
||||||
|
editing from <code>ttbp</code>.</p>
|
||||||
|
<p><em>(since files are just stored as plaintext in your directory, it's possible to
|
||||||
|
edit and move old entries directly from the command line. however, changing old
|
||||||
|
entries might cause strange things to happen with timestamps. the main program
|
||||||
|
looks at the filename first for setting the date, then the last modified time to
|
||||||
|
sort recent posts. it expects YYYMMDD.txt as the filename; anything else won't
|
||||||
|
show up as a valid entry. yes, this means you can post things out of date order
|
||||||
|
by creating files with any date you want.)</em></p>
|
||||||
|
<h4>general entry-writing notes</h4>
|
||||||
|
<ul>
|
||||||
|
<li>you can use <a href="https://daringfireball.net/projects/markdown/syntax">markdown</a></li>
|
||||||
|
<li>you can use html</li>
|
||||||
|
<li>you can also put things between <code><!-- comments --></code> to have them show up
|
||||||
|
in the feed but not render in a browser (but people can still read them with
|
||||||
|
view-source)</li>
|
||||||
|
</ul>
|
||||||
|
<h3>reading other feels</h3>
|
||||||
|
<p>the <code>browse global feels</code> feature shows the ten most recent entries that anyone
|
||||||
|
has written on ttbp. this list is only accessible from within tilde.town,
|
||||||
|
although individual entries may be posted to html or gopher.</p>
|
||||||
|
<p>you can also pull up a list of a single user's feels through <code>check out your
|
||||||
|
neighbors</code>, which displays all users who are writing on <code>ttbp</code> based on their
|
||||||
|
most recently updated entry, and a link to their public html blog if they've
|
||||||
|
opted to publish their posts.</p>
|
||||||
|
<p><strong>please note!</strong> entries written on <code>ttbp</code> should be considered sensitive,
|
||||||
|
private information, even if a particular user is publishing entries in a
|
||||||
|
world-viewable way! please be respectful about having access to other people's
|
||||||
|
feels, and do not copy/repeat any information without getting their explicit
|
||||||
|
permission. tilde.town operates on a high level of mutual trust, and <code>ttbp</code> is
|
||||||
|
designed to give individuals control over their content.</p>
|
||||||
|
<h3>privacy</h3>
|
||||||
|
<p>when you start your ttbp, you have the option of publishing or not publishing
|
||||||
|
your blog.</p>
|
||||||
|
<p>if you opt to not publish, your entires will never be accessible from outside of
|
||||||
|
the tilde.town network; other tilde.town users will still be able to read your
|
||||||
|
entries through the ttbp interface, or by directly accessing your
|
||||||
|
<code>~/.ttbp/entries</code> directory.</p>
|
||||||
|
<p>if you want to further protect your entries, you can <code>chmod 700</code> your entries
|
||||||
|
directory.</p>
|
||||||
|
<p>if you opt to publish, the program creates a directory <code>~/.ttbp/www</code> where it
|
||||||
|
stores all html files it generates, and symlinks this from your <code>~/public_html</code>
|
||||||
|
with your chosen blog directory. your blog will also be listed on the <a href="https://tilde.town/~endorphant/ttbp">main ttbp
|
||||||
|
page</a>.</p>
|
||||||
|
<p>you can also opt to publish to gopher, and the program will automatically
|
||||||
|
generate a gophermap of your feels.</p>
|
||||||
|
<p>you can set publishing status on individual entries, or bury individual feels;
|
||||||
|
see "data management" below for details.</p>
|
||||||
|
<h3>data management</h3>
|
||||||
|
<p>the <code>manage your feels</code> menu provides several tools for organizing your feels.
|
||||||
|
these are all actions you can perform manually from the command line, but doing
|
||||||
|
them from within the program can help keep your files properly linked up.</p>
|
||||||
|
<ul>
|
||||||
|
<li><strong>read over feels</strong>--a list of all your entries, which you can open and
|
||||||
|
read like any other feel</li>
|
||||||
|
<li><strong>modify feels publishing</strong>--this lets you toggle privacy on individual
|
||||||
|
posts. entries marked <code>(nopub)</code> will not get written to html or gopher,
|
||||||
|
and toggling them from this menu will immediately publish or unpublish
|
||||||
|
that entry (if you're not publishing your posts at all, these settings
|
||||||
|
won't matter, since your feels will never show up outside of tilde.town)</li>
|
||||||
|
<li><strong>backup your feels</strong>--makes a .tar.gz of all your entries, saving one
|
||||||
|
copy to <code>~/.ttbp/backups/</code> with the current date, and a second copy to
|
||||||
|
your home directory for safekeeping.</li>
|
||||||
|
<li><strong>import a feels backup</strong>--unpacks a backup file into your current feels
|
||||||
|
list. this tool checks the <code>~/.ttbp/backups</code> directory for archives, and
|
||||||
|
expects a file created by the above backup utility. if it detects any file
|
||||||
|
collisions, it will preserve your current live copy and leave the backup
|
||||||
|
verison in a temp directory, and notify you that this happened. also, any
|
||||||
|
entries that were previously marked as <code>(nopub)</code> will retain their nopub
|
||||||
|
status.</li>
|
||||||
|
<li><strong>bury some feels</strong>--hides individual feels from viewing; entries are
|
||||||
|
moved to <code>~/.ttbp/buried</code> (and marked with a unique timestamp to prevent
|
||||||
|
file collision) with permissions set to 600, meaning no one except you
|
||||||
|
will be able to open that file. these entries are also hidden from your
|
||||||
|
own view from <code>read over feels</code>, and you'll have to open the files from
|
||||||
|
the command line if you want to see them. this is intended to be a
|
||||||
|
permament action, so you'll be asked to type the entry date once to load
|
||||||
|
the feel, then shown a preview of that feel, and then type the date again
|
||||||
|
to confirm burying.</li>
|
||||||
|
<li><strong>delete feels by day</strong>--<em>permanently removes individual entries</em>,
|
||||||
|
including deleting published html/gopher files if needed. this action is
|
||||||
|
not recoverable, unless you have a backup to restore; you'll be asked to
|
||||||
|
type the entry date once to load the feel, then shown a preview of that
|
||||||
|
feel, and then type the date again to confirm deletion.</li>
|
||||||
|
<li><strong>purge all feels</strong>--<em>permanently removes all feels</em>, including deleting
|
||||||
|
all published html/gopher files if needed. this action is not recoverable,
|
||||||
|
unless you have a backup to restore. you'll be asked to type a
|
||||||
|
one-time-use purge code to confirm this action.</li>
|
||||||
|
<li><strong>wipe feels account</strong>--<em>permanently removes all data associated with
|
||||||
|
feels</em>, including deleting any published hmtl/gopher files and removing
|
||||||
|
your <code>~/.ttbp</code> directory. any backups that you have in <code>~/.ttbp/backups</code>
|
||||||
|
will also be deleted with this action (which is why the backup function
|
||||||
|
makes a second copy for safekeeping in your home directory). you will no
|
||||||
|
longer show up in any lists as a user.</li>
|
||||||
|
</ul>
|
||||||
|
<h3>settings</h3>
|
||||||
|
<p>the settings menu lets you change specific options for handling your feels and
|
||||||
|
using the interface.</p>
|
||||||
|
<ul>
|
||||||
|
<li><strong>editor</strong>--set your text editor</li>
|
||||||
|
<li><strong>gopher</strong>--opt in or out of automatically posting to gopher</li>
|
||||||
|
<li><strong>post as nopub</strong>--set whether posts default to being published or not
|
||||||
|
published (if you're not publishing your feels, this doesn't matter)</li>
|
||||||
|
<li><strong>publish dir</strong>--set the directory under you <code>public_html</code> where feels will be
|
||||||
|
published (if you're not publishing your feels, this defaults to <code>None</code>)</li>
|
||||||
|
<li><strong>publishing</strong>--opt in or out of automatically publishing entries to a
|
||||||
|
world-readable html page</li>
|
||||||
|
<li><strong>rainbows</strong>--opt in or out of having multicolored menu text</li>
|
||||||
|
</ul>
|
||||||
|
<h3>changing your page layout</h3>
|
||||||
|
<p>you can modify how your blog looks by editing the stylesheet or header and
|
||||||
|
footer files. the program sets you up with basic default. if you break your page
|
||||||
|
somehow, you can force the program to regenerate your configuration by deleting
|
||||||
|
your ~/.ttbp directory entirely. <strong>you might want to back up your
|
||||||
|
~/.ttbp/entries directory before you do this.</strong></p>
|
||||||
|
<ul>
|
||||||
|
<li>to modify your stylesheet, edit your ~/.ttbp/config/style.css</li>
|
||||||
|
<li>to modify the page header, edit your ~/.ttbp/config/header.txt</li>
|
||||||
|
<li>there's a place marked off in the default header where you can safely put
|
||||||
|
custom HTML elements!</li>
|
||||||
|
<li>to modify the page footer, edit your ~/.ttbp/config/footer.txt</li>
|
||||||
|
</ul>
|
||||||
|
<h3>general tips/troubleshooting</h3>
|
||||||
|
<ul>
|
||||||
|
<li>if the date looks like it's ahead or behind, it's because you haven't set
|
||||||
|
your local timezone yet. here are some
|
||||||
|
<a href="http://www.cyberciti.biz/faq/linux-unix-set-tz-environment-variable/">timezone setting instructions</a></li>
|
||||||
|
<li>the feels burying tool will effectively clear your post for the day; you can
|
||||||
|
use this feature to start a fresh entry on a particular day by burying the
|
||||||
|
current day's feels and then editing a new file</li>
|
||||||
|
</ul>
|
||||||
|
<h3>future features</h3>
|
||||||
|
<p>these are a few ideas being kicked around, or under active development:</p>
|
||||||
|
<ul>
|
||||||
|
<li>stylesheet/theme selector</li>
|
||||||
|
<li>better entry display within ttbp (currently just offloads to <code>less</code>)</li>
|
||||||
|
<li>buried feels browser</li>
|
||||||
|
</ul>
|
||||||
|
<p>other ideas are listed on github as
|
||||||
|
<a href="https://github.com/modgethanc/ttbp/issues?q=is%3Aissue+is%3Aopen+label%3A" title="upcoming+features">upcoming features</a> or <a href="https://github.com/modgethanc/ttbp/issues?q=is%3Aissue+is%3Aopen+label%3A" title="feature+request">feature requests</a>!</p>
|
|
@ -0,0 +1,196 @@
|
||||||
|
# FEELS MANUAL #
|
||||||
|
|
||||||
|
`ttbp` stands for "tilde.town blogging platform", the original working name for
|
||||||
|
this project. the complete codebase is available on
|
||||||
|
[github](https://github.com/modgethanc/ttbp).
|
||||||
|
|
||||||
|
`ttbp` runs from the command line, providing a hub for writing personal blog
|
||||||
|
posts and reading posts written by other users of tilde.town. it's a little bit
|
||||||
|
like livejournal or dreamwidth or tumblr. you can opt to publish your posts to a
|
||||||
|
public html file hosted on your tilde page, to tilde.town's gopher server, or
|
||||||
|
keep all your entries private to the tilde.town server.
|
||||||
|
|
||||||
|
this is a project that runs on tilde.town, so all users of this program are
|
||||||
|
expected to operate under the tilde.town [code of
|
||||||
|
conduct](http://tilde.town/wiki/conduct.html). content/personal issues should be
|
||||||
|
worked out according to the CoC, with support from the [administrative
|
||||||
|
team](http://tilde.town/wiki/administration/index.html) if needed.
|
||||||
|
|
||||||
|
### support
|
||||||
|
|
||||||
|
if you're having trouble getting started, or run into program errors or strange
|
||||||
|
behavior, please send internal tilde.town mail to ~endorphant and i'll try to
|
||||||
|
sort things out!
|
||||||
|
|
||||||
|
there's also a function from the main menu that lets you send feedback/inquiries
|
||||||
|
to me directly; this uses internal tilde.town mail, which is what i'll respond
|
||||||
|
to.
|
||||||
|
|
||||||
|
### writing entries
|
||||||
|
|
||||||
|
entries are recorded as plaintext files in your `~/.ttbp/entries` directory.
|
||||||
|
`ttbp` will use your selected editor to open and write files; each day is its
|
||||||
|
own entry, like a diary page. at midnight for whatever timezone you've set for
|
||||||
|
your user account on tilde.town, you'll get a fresh entry. if you don't write
|
||||||
|
any feels on a particular day, no entries will show up there.
|
||||||
|
|
||||||
|
when you save and quit the text editor, your entry will automatically propagate
|
||||||
|
to the global feels list; if you've opted to publish your feels to html/gopher,
|
||||||
|
those files will update immediately. you can always go back to the current day's
|
||||||
|
entry and edit/add as you'd like, but older entries will not be available for
|
||||||
|
editing from `ttbp`.
|
||||||
|
|
||||||
|
*(since files are just stored as plaintext in your directory, it's possible to
|
||||||
|
edit and move old entries directly from the command line. however, changing old
|
||||||
|
entries might cause strange things to happen with timestamps. the main program
|
||||||
|
looks at the filename first for setting the date, then the last modified time to
|
||||||
|
sort recent posts. it expects YYYMMDD.txt as the filename; anything else won't
|
||||||
|
show up as a valid entry. yes, this means you can post things out of date order
|
||||||
|
by creating files with any date you want.)*
|
||||||
|
|
||||||
|
#### general entry-writing notes
|
||||||
|
|
||||||
|
* you can use [markdown](https://daringfireball.net/projects/markdown/syntax)
|
||||||
|
* you can use html
|
||||||
|
* you can also put things between `<!-- comments -->` to have them show up
|
||||||
|
in the feed but not render in a browser (but people can still read them with
|
||||||
|
view-source)
|
||||||
|
|
||||||
|
### reading other feels
|
||||||
|
|
||||||
|
the `browse global feels` feature shows the ten most recent entries that anyone
|
||||||
|
has written on ttbp. this list is only accessible from within tilde.town,
|
||||||
|
although individual entries may be posted to html or gopher.
|
||||||
|
|
||||||
|
you can also pull up a list of a single user's feels through `check out your
|
||||||
|
neighbors`, which displays all users who are writing on `ttbp` based on their
|
||||||
|
most recently updated entry, and a link to their public html blog if they've
|
||||||
|
opted to publish their posts.
|
||||||
|
|
||||||
|
**please note!** entries written on `ttbp` should be considered sensitive,
|
||||||
|
private information, even if a particular user is publishing entries in a
|
||||||
|
world-viewable way! please be respectful about having access to other people's
|
||||||
|
feels, and do not copy/repeat any information without getting their explicit
|
||||||
|
permission. tilde.town operates on a high level of mutual trust, and `ttbp` is
|
||||||
|
designed to give individuals control over their content.
|
||||||
|
|
||||||
|
### privacy
|
||||||
|
|
||||||
|
when you start your ttbp, you have the option of publishing or not publishing
|
||||||
|
your blog.
|
||||||
|
|
||||||
|
if you opt to not publish, your entires will never be accessible from outside of
|
||||||
|
the tilde.town network; other tilde.town users will still be able to read your
|
||||||
|
entries through the ttbp interface, or by directly accessing your
|
||||||
|
`~/.ttbp/entries` directory.
|
||||||
|
|
||||||
|
if you want to further protect your entries, you can `chmod 700` your entries
|
||||||
|
directory.
|
||||||
|
|
||||||
|
if you opt to publish, the program creates a directory `~/.ttbp/www` where it
|
||||||
|
stores all html files it generates, and symlinks this from your `~/public_html`
|
||||||
|
with your chosen blog directory. your blog will also be listed on the [main ttbp
|
||||||
|
page](https://tilde.town/~endorphant/ttbp).
|
||||||
|
|
||||||
|
you can also opt to publish to gopher, and the program will automatically
|
||||||
|
generate a gophermap of your feels.
|
||||||
|
|
||||||
|
you can set publishing status on individual entries, or bury individual feels;
|
||||||
|
see "data management" below for details.
|
||||||
|
|
||||||
|
### data management
|
||||||
|
|
||||||
|
the `manage your feels` menu provides several tools for organizing your feels.
|
||||||
|
these are all actions you can perform manually from the command line, but doing
|
||||||
|
them from within the program can help keep your files properly linked up.
|
||||||
|
|
||||||
|
* **read over feels**--a list of all your entries, which you can open and
|
||||||
|
read like any other feel
|
||||||
|
* **modify feels publishing**--this lets you toggle privacy on individual
|
||||||
|
posts. entries marked `(nopub)` will not get written to html or gopher,
|
||||||
|
and toggling them from this menu will immediately publish or unpublish
|
||||||
|
that entry (if you're not publishing your posts at all, these settings
|
||||||
|
won't matter, since your feels will never show up outside of tilde.town)
|
||||||
|
* **backup your feels**--makes a .tar.gz of all your entries, saving one
|
||||||
|
copy to `~/.ttbp/backups/` with the current date, and a second copy to
|
||||||
|
your home directory for safekeeping.
|
||||||
|
* **import a feels backup**--unpacks a backup file into your current feels
|
||||||
|
list. this tool checks the `~/.ttbp/backups` directory for archives, and
|
||||||
|
expects a file created by the above backup utility. if it detects any file
|
||||||
|
collisions, it will preserve your current live copy and leave the backup
|
||||||
|
verison in a temp directory, and notify you that this happened. also, any
|
||||||
|
entries that were previously marked as `(nopub)` will retain their nopub
|
||||||
|
status.
|
||||||
|
* **bury some feels**--hides individual feels from viewing; entries are
|
||||||
|
moved to `~/.ttbp/buried` (and marked with a unique timestamp to prevent
|
||||||
|
file collision) with permissions set to 600, meaning no one except you
|
||||||
|
will be able to open that file. these entries are also hidden from your
|
||||||
|
own view from `read over feels`, and you'll have to open the files from
|
||||||
|
the command line if you want to see them. this is intended to be a
|
||||||
|
permament action, so you'll be asked to type the entry date once to load
|
||||||
|
the feel, then shown a preview of that feel, and then type the date again
|
||||||
|
to confirm burying.
|
||||||
|
* **delete feels by day**--*permanently removes individual entries*,
|
||||||
|
including deleting published html/gopher files if needed. this action is
|
||||||
|
not recoverable, unless you have a backup to restore; you'll be asked to
|
||||||
|
type the entry date once to load the feel, then shown a preview of that
|
||||||
|
feel, and then type the date again to confirm deletion.
|
||||||
|
* **purge all feels**--*permanently removes all feels*, including deleting
|
||||||
|
all published html/gopher files if needed. this action is not recoverable,
|
||||||
|
unless you have a backup to restore. you'll be asked to type a
|
||||||
|
one-time-use purge code to confirm this action.
|
||||||
|
* **wipe feels account**--*permanently removes all data associated with
|
||||||
|
feels*, including deleting any published hmtl/gopher files and removing
|
||||||
|
your `~/.ttbp` directory. any backups that you have in `~/.ttbp/backups`
|
||||||
|
will also be deleted with this action (which is why the backup function
|
||||||
|
makes a second copy for safekeeping in your home directory). you will no
|
||||||
|
longer show up in any lists as a user.
|
||||||
|
|
||||||
|
### settings
|
||||||
|
|
||||||
|
the settings menu lets you change specific options for handling your feels and
|
||||||
|
using the interface.
|
||||||
|
|
||||||
|
* **editor**--set your text editor
|
||||||
|
* **gopher**--opt in or out of automatically posting to gopher
|
||||||
|
* **post as nopub**--set whether posts default to being published or not
|
||||||
|
published (if you're not publishing your feels, this doesn't matter)
|
||||||
|
* **publish dir**--set the directory under you `public_html` where feels will be
|
||||||
|
published (if you're not publishing your feels, this defaults to `None`)
|
||||||
|
* **publishing**--opt in or out of automatically publishing entries to a
|
||||||
|
world-readable html page
|
||||||
|
* **rainbows**--opt in or out of having multicolored menu text
|
||||||
|
|
||||||
|
### changing your page layout
|
||||||
|
|
||||||
|
you can modify how your blog looks by editing the stylesheet or header and
|
||||||
|
footer files. the program sets you up with basic default. if you break your page
|
||||||
|
somehow, you can force the program to regenerate your configuration by deleting
|
||||||
|
your ~/.ttbp directory entirely. **you might want to back up your
|
||||||
|
~/.ttbp/entries directory before you do this.**
|
||||||
|
|
||||||
|
* to modify your stylesheet, edit your ~/.ttbp/config/style.css
|
||||||
|
* to modify the page header, edit your ~/.ttbp/config/header.txt
|
||||||
|
* there's a place marked off in the default header where you can safely put
|
||||||
|
custom HTML elements!
|
||||||
|
* to modify the page footer, edit your ~/.ttbp/config/footer.txt
|
||||||
|
|
||||||
|
### general tips/troubleshooting
|
||||||
|
|
||||||
|
* if the date looks like it's ahead or behind, it's because you haven't set
|
||||||
|
your local timezone yet. here are some
|
||||||
|
[timezone setting instructions](http://www.cyberciti.biz/faq/linux-unix-set-tz-environment-variable/)
|
||||||
|
* the feels burying tool will effectively clear your post for the day; you can
|
||||||
|
use this feature to start a fresh entry on a particular day by burying the
|
||||||
|
current day's feels and then editing a new file
|
||||||
|
|
||||||
|
### future features
|
||||||
|
|
||||||
|
these are a few ideas being kicked around, or under active development:
|
||||||
|
|
||||||
|
* stylesheet/theme selector
|
||||||
|
* better entry display within ttbp (currently just offloads to `less`)
|
||||||
|
* buried feels browser
|
||||||
|
|
||||||
|
other ideas are listed on github as
|
||||||
|
[upcoming features](https://github.com/modgethanc/ttbp/issues?q=is%3Aissue+is%3Aopen+label%3A"upcoming+features") or [feature requests](https://github.com/modgethanc/ttbp/issues?q=is%3Aissue+is%3Aopen+label%3A"feature+request")!
|
2
setup.py
2
setup.py
|
@ -4,7 +4,7 @@ from setuptools import setup
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='ttbp',
|
name='ttbp',
|
||||||
version='0.11.2',
|
version='0.12.0',
|
||||||
description='command line social blogging tool used on tilde.town',
|
description='command line social blogging tool used on tilde.town',
|
||||||
url='https://github.com/modgethanc/ttbp',
|
url='https://github.com/modgethanc/ttbp',
|
||||||
author='~endorphant',
|
author='~endorphant',
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
from .. import util
|
from .. import util
|
||||||
|
|
||||||
|
@ -67,11 +68,14 @@ USER_HOME = os.path.expanduser('~')
|
||||||
PATH = os.path.join(USER_HOME, '.ttbp')
|
PATH = os.path.join(USER_HOME, '.ttbp')
|
||||||
PUBLIC = os.path.join(USER_HOME, 'public_html')
|
PUBLIC = os.path.join(USER_HOME, 'public_html')
|
||||||
WWW = os.path.join(PATH, 'www')
|
WWW = os.path.join(PATH, 'www')
|
||||||
|
GOPHER_ENTRIES = os.path.join(PATH, 'gopher')
|
||||||
GOPHER_PATH = os.path.join(USER_HOME, 'public_gopher', 'feels')
|
GOPHER_PATH = os.path.join(USER_HOME, 'public_gopher', 'feels')
|
||||||
USER_CONFIG = os.path.join(PATH, 'config')
|
USER_CONFIG = os.path.join(PATH, 'config')
|
||||||
TTBPRC = os.path.join(USER_CONFIG, 'ttbprc')
|
TTBPRC = os.path.join(USER_CONFIG, 'ttbprc')
|
||||||
USER_DATA = os.path.join(PATH, 'entries')
|
MAIN_FEELS = os.path.join(PATH, 'entries')
|
||||||
NOPUB = os.path.join(USER_CONFIG, "nopub")
|
BURIED_FEELS = os.path.join(PATH, 'buried')
|
||||||
|
NOPUB = os.path.join(USER_CONFIG, 'nopub')
|
||||||
|
BACKUPS = os.path.join(PATH, 'backups')
|
||||||
|
|
||||||
## UI
|
## UI
|
||||||
|
|
||||||
|
@ -82,9 +86,102 @@ ___________________________________________________________
|
||||||
| ____ ____ ____ _ ____ ____ _ _ ____ _ _ _ ____ |
|
| ____ ____ ____ _ ____ ____ _ _ ____ _ _ _ ____ |
|
||||||
| |___ |___ |___ | [__ |___ |\ | | __ | |\ | |___ |
|
| |___ |___ |___ | [__ |___ |\ | | __ | |\ | |___ |
|
||||||
| | |___ |___ |___ ___] |___ | \| |__] | | \| |___ |
|
| | |___ |___ |___ ___] |___ | \| |__] | | \| |___ |
|
||||||
| ver 0.11.2 (rainbows) |
|
| <gan jue; to feel> ver 0.12.0 |
|
||||||
|__________________________________________________________|
|
|__________________________________________________________|
|
||||||
'''.lstrip()
|
'''.lstrip()
|
||||||
|
# ~ u n s t a b l e e x p e r i m e n t a l b r a n c h ~
|
||||||
|
#'''.lstrip()
|
||||||
|
|
||||||
|
## page texts
|
||||||
|
|
||||||
|
intro_prompt = """
|
||||||
|
i don't recognize you, stranger. let's make friends.
|
||||||
|
|
||||||
|
the feels engine is an internal blogging platform on tilde.town. it assists you
|
||||||
|
in recording your feels, giving you the option to publish to html or gopher, and
|
||||||
|
read the feels of other users on tilde.town.
|
||||||
|
|
||||||
|
press <enter> to set up an account, or <ctrl-c> to quit.
|
||||||
|
""".lstrip()
|
||||||
|
|
||||||
|
credits = """
|
||||||
|
ttbp was written for tilde.town by ~endorphant in python. the codebase is
|
||||||
|
publicly available on github at https://github.com/modgethanc/ttbp
|
||||||
|
|
||||||
|
tips for development are accepted at https://liberapay.com/modgethanc/
|
||||||
|
|
||||||
|
other contributors:
|
||||||
|
~vilmibm, packaging help and gopher support
|
||||||
|
~sanqui, the bug swatter
|
||||||
|
~sinacutie, for css updates
|
||||||
|
|
||||||
|
if you have ideas for ttbp, you are welcome to contact me to discuss them;
|
||||||
|
please send me tildemail or open a github issue. i am not a very experienced
|
||||||
|
developer, and ttbp is one of my first public-facing projects, so i appreciate
|
||||||
|
your patience while i learn how to be a better developer!
|
||||||
|
|
||||||
|
i'd love to hear about your ideas and brainstorm about new features!
|
||||||
|
|
||||||
|
thanks to everyone who reads, listens, writes, and feels."""
|
||||||
|
|
||||||
|
recording = """
|
||||||
|
feels will be recorded for today, {today}.
|
||||||
|
|
||||||
|
if you've already started recording feels for this day, you
|
||||||
|
can pick up where you left off.
|
||||||
|
|
||||||
|
you can write your feels in plaintext, markdown, html, or a mixture of
|
||||||
|
these.
|
||||||
|
|
||||||
|
press <enter> to begin recording your feels in your chosen text
|
||||||
|
editor.
|
||||||
|
|
||||||
|
""".format(today=time.strftime("%d %B %Y"))
|
||||||
|
|
||||||
|
bury_feels_prompt = """\
|
||||||
|
burying a feel removes it from view, including your own. buried feels are
|
||||||
|
stashed in a private directory at:
|
||||||
|
|
||||||
|
{buried_dir}
|
||||||
|
|
||||||
|
you can visit your feels there from the command line, but no one else can view
|
||||||
|
those files.
|
||||||
|
|
||||||
|
(a buried feels browser is in the works; for now, you'll have to use the
|
||||||
|
command line to view your buried feels)
|
||||||
|
|
||||||
|
which day's feels do you want to bury?
|
||||||
|
|
||||||
|
YYYYMMDD (or 'q' to cancel)> """.format(buried_dir=BURIED_FEELS)
|
||||||
|
|
||||||
|
account_wipe_prompt = """\
|
||||||
|
warning! ! ! this action is irreversible!!!
|
||||||
|
|
||||||
|
this tool will remove your entire presence from the feels engine. this includes
|
||||||
|
all posts, settings, and published html/gopher feels. you will no longer be
|
||||||
|
listed anywhere as a user here.
|
||||||
|
|
||||||
|
there is no way for me to help you recover any part of your feels acccount. i
|
||||||
|
respect your need to do this from time to time, so please be sure you're ready!
|
||||||
|
|
||||||
|
i recommend that you make a backup of your feels and stash them somewhere safe,
|
||||||
|
just in case a future version of you still wants to look them over."""
|
||||||
|
|
||||||
|
feels_purge_prompt = """\
|
||||||
|
warning! ! ! this action is irreversible!!!
|
||||||
|
|
||||||
|
there is no way for me to help you recover your feels if you purge them all. i
|
||||||
|
respect your need to do this from time to time, so please be sure you're ready!
|
||||||
|
|
||||||
|
i recommend that you make a backup of your feels and stash them somewhere safe,
|
||||||
|
just in case a future version of you still wants to look them over.
|
||||||
|
"""
|
||||||
|
|
||||||
|
mystery_error = """\
|
||||||
|
sorry, something went wrong! please try to address the error and try again.
|
||||||
|
if you need help, ask in IRC or send mail to ~endorphant and we'll try to
|
||||||
|
figure it out!
|
||||||
|
""".lstrip()
|
||||||
|
|
||||||
## update announcements
|
## update announcements
|
||||||
|
|
||||||
|
@ -152,6 +249,47 @@ version 0.9.3 features:
|
||||||
* added a new option to allow setting entries to default to either public or
|
* added a new option to allow setting entries to default to either public or
|
||||||
non-public on posting; this option only really makes sense if you're
|
non-public on posting; this option only really makes sense if you're
|
||||||
already publishing to html/gopher, but is available either way!
|
already publishing to html/gopher, but is available either way!
|
||||||
|
|
||||||
you can find this option under 'settings' as 'post as nopub'."""
|
you can find this option under 'settings' as 'post as nopub'.""",
|
||||||
|
"0.11.3": """
|
||||||
|
~[version 0.11.3 update]~
|
||||||
|
|
||||||
|
* thanks to ~sinacutie, you can now set custom css for the permalink text
|
||||||
|
styling on your html page. the default permalink style has been added to
|
||||||
|
your current css file, and shouldn't change the appearance of your page.
|
||||||
|
|
||||||
|
if you're not using custom css, don't worry about this!""",
|
||||||
|
"0.12.0": """
|
||||||
|
~[version 0.12.0 update]~
|
||||||
|
|
||||||
|
a lot of new stuff this time! from the main menu, option (1) is now called
|
||||||
|
"manage your feels", which contains an expanded set of tools for organizing
|
||||||
|
your feels:
|
||||||
|
* read over feels (a list of all your entries)
|
||||||
|
* modify feels publishing (toggle privacy on individual entries)
|
||||||
|
* backup your feels (makes a .tar.gz of all your entries)
|
||||||
|
* import a feels backup (unpacks a backup into your feels)
|
||||||
|
* bury some feels (hide individual entries from view)
|
||||||
|
* delete feels by day (permanently remove individual entries)
|
||||||
|
* purge all feels (permanently remove all entries)
|
||||||
|
* wipe feels account (permanently remove everything associated with
|
||||||
|
ttbp)
|
||||||
|
|
||||||
|
each of these tools has expanded descriptions and instructions from the
|
||||||
|
menu, so check them out if you're curious! all of the irreversibl data
|
||||||
|
management actions have confirmation actions, so it's easy to cancel if you
|
||||||
|
accidentally access a tool.
|
||||||
|
|
||||||
|
also, i've updated the documentation file to reflect recent feature changes,
|
||||||
|
including some more details about how things work under the hood, and some
|
||||||
|
clarifications on how existing features work. please give it a read through
|
||||||
|
if you have a chance, and let me know if there's anything else i can
|
||||||
|
improve!
|
||||||
|
|
||||||
|
lastly, i just wanted to mention that i do accept tips for my dev work at
|
||||||
|
https://liberapay.com/modgethanc/ but there's no pressure to donate at all,
|
||||||
|
i'm just making this option available for anyone whose financially stable
|
||||||
|
and wants to kick some spare change my way; this is a labor of love, and i'm
|
||||||
|
happy to work on it regardless :)
|
||||||
|
"""
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,12 @@ body {
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.entry p.permalink {
|
||||||
|
font-size: .6em;
|
||||||
|
font-color: #808080;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
.entry h5 {
|
.entry h5 {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
margin-top: .2em;
|
margin-top: .2em;
|
||||||
|
|
159
ttbp/core.py
159
ttbp/core.py
|
@ -41,6 +41,8 @@ import json
|
||||||
|
|
||||||
from . import chatter
|
from . import chatter
|
||||||
from . import config
|
from . import config
|
||||||
|
from . import gopher
|
||||||
|
from . import util
|
||||||
|
|
||||||
FEED = os.path.join("/home", "endorphant", "public_html", "ttbp", "index.html")
|
FEED = os.path.join("/home", "endorphant", "public_html", "ttbp", "index.html")
|
||||||
SETTINGS = {}
|
SETTINGS = {}
|
||||||
|
@ -75,40 +77,42 @@ def reload_ttbprc(ttbprc={}):
|
||||||
|
|
||||||
SETTINGS = ttbprc
|
SETTINGS = ttbprc
|
||||||
|
|
||||||
|
def get_files(feelsdir=config.MAIN_FEELS):
|
||||||
|
"""Returns a list of user's feels in the given directory (defaults to main
|
||||||
|
feels dir)"""
|
||||||
|
|
||||||
def get_files():
|
|
||||||
"""Returns a list of user's feels."""
|
|
||||||
files = []
|
files = []
|
||||||
for filename in os.listdir(config.USER_DATA):
|
for filename in os.listdir(feelsdir):
|
||||||
if nopub(filename):
|
if nopub(filename):
|
||||||
link = os.path.join(config.WWW,
|
unpublish_feel(filename)
|
||||||
os.path.splitext(
|
else:
|
||||||
os.path.basename(filename))[0]+".html")
|
filename = os.path.join(feelsdir, filename)
|
||||||
if os.path.exists(link):
|
if os.path.isfile(filename) and valid(filename):
|
||||||
subprocess.call(["rm", link])
|
files.append(filename)
|
||||||
continue
|
|
||||||
filename = os.path.join(config.USER_DATA, filename)
|
|
||||||
if os.path.isfile(filename) and valid(filename):
|
|
||||||
files.append(filename)
|
|
||||||
|
|
||||||
files.sort()
|
files.sort()
|
||||||
files.reverse()
|
files.reverse()
|
||||||
|
|
||||||
return files
|
return files
|
||||||
|
|
||||||
|
def load_files(feelsdir=config.MAIN_FEELS):
|
||||||
def load_files():
|
|
||||||
'''
|
'''
|
||||||
file loader
|
file loader
|
||||||
|
|
||||||
* reads user's nopub file
|
* reads user's nopub file
|
||||||
* loads all valid filenames that are not excluded in nopub to global files list
|
* calls get_files() to load all files for given directory
|
||||||
|
* re-renders main html file and/or gopher if needed
|
||||||
'''
|
'''
|
||||||
|
|
||||||
global FILES
|
global FILES
|
||||||
|
|
||||||
load_nopubs()
|
load_nopubs()
|
||||||
FILES = get_files()
|
FILES = get_files(feelsdir)
|
||||||
|
|
||||||
|
if publishing():
|
||||||
|
write_html("index.html")
|
||||||
|
if SETTINGS.get('gopher'):
|
||||||
|
gopher.publish_gopher('feels', FILES)
|
||||||
|
|
||||||
def load_nopubs():
|
def load_nopubs():
|
||||||
"""Load a list of the user's nopub entries.
|
"""Load a list of the user's nopub entries.
|
||||||
|
@ -127,7 +131,7 @@ def load_nopubs():
|
||||||
|
|
||||||
## html outputting
|
## html outputting
|
||||||
|
|
||||||
def write(outurl="default.html"):
|
def write_html(outurl="default.html"):
|
||||||
'''
|
'''
|
||||||
main page renderer
|
main page renderer
|
||||||
|
|
||||||
|
@ -167,7 +171,7 @@ def write_page(filename):
|
||||||
url
|
url
|
||||||
'''
|
'''
|
||||||
|
|
||||||
outurl = os.path.join(config.WWW, "".join(parse_date(filename))+".html")
|
outurl = os.path.join(config.WWW, "".join(util.parse_date(filename))+".html")
|
||||||
outfile = open(outurl, "w")
|
outfile = open(outurl, "w")
|
||||||
|
|
||||||
outfile.write("<!--generated by the tilde.town blogging platform on "+time.strftime("%d %B %y")+"\nhttp://tilde.town/~endorphant/ttbp/-->\n\n")
|
outfile.write("<!--generated by the tilde.town blogging platform on "+time.strftime("%d %B %y")+"\nhttp://tilde.town/~endorphant/ttbp/-->\n\n")
|
||||||
|
@ -197,7 +201,7 @@ def write_entry(filename):
|
||||||
* return as list of strings
|
* return as list of strings
|
||||||
'''
|
'''
|
||||||
|
|
||||||
date = parse_date(filename)
|
date = util.parse_date(filename)
|
||||||
|
|
||||||
entry = [
|
entry = [
|
||||||
"\t\t<p><a name=\""+date[0]+date[1]+date[2]+"\"></a><br /><br /></p>\n",
|
"\t\t<p><a name=\""+date[0]+date[1]+date[2]+"\"></a><br /><br /></p>\n",
|
||||||
|
@ -207,7 +211,7 @@ def write_entry(filename):
|
||||||
]
|
]
|
||||||
|
|
||||||
raw = []
|
raw = []
|
||||||
rawfile = open(os.path.join(config.USER_DATA, filename), "r")
|
rawfile = open(os.path.join(config.MAIN_FEELS, filename), "r")
|
||||||
|
|
||||||
for line in rawfile:
|
for line in rawfile:
|
||||||
raw.append(line)
|
raw.append(line)
|
||||||
|
@ -221,7 +225,7 @@ def write_entry(filename):
|
||||||
# entry.append("</p>\n\t\t\t<p>")
|
# entry.append("</p>\n\t\t\t<p>")
|
||||||
|
|
||||||
#entry.append("</p>\n")
|
#entry.append("</p>\n")
|
||||||
entry.append("\t\t\t<p style=\"font-size:.6em; font-color:#808080; text-align: right;\"><a href=\""+"".join(date)+".html\">permalink</a></p>\n")
|
entry.append("\t\t\t<p class=\"permalink\"><a href=\""+"".join(date)+".html\">permalink</a></p>\n")
|
||||||
entry.append("\n\t\t</div>\n")
|
entry.append("\n\t\t</div>\n")
|
||||||
|
|
||||||
return entry
|
return entry
|
||||||
|
@ -316,7 +320,7 @@ def meta(entries = FILES):
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
wc = "???"
|
wc = "???"
|
||||||
timestamp = time.strftime("%Y-%m-%d at %H:%M", time.localtime(mtime))
|
timestamp = time.strftime("%Y-%m-%d at %H:%M", time.localtime(mtime))
|
||||||
date = "-".join(parse_date(filename))
|
date = "-".join(util.parse_date(filename))
|
||||||
author = os.path.split(os.path.split(os.path.split(os.path.split(filename)[0])[0])[0])[1]
|
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.append([filename, mtime, wc, timestamp, date, author])
|
||||||
|
@ -345,23 +349,6 @@ def valid(filename):
|
||||||
|
|
||||||
return True
|
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():
|
def find_ttbps():
|
||||||
'''
|
'''
|
||||||
returns a list of users with a ttbp by checking for a valid ttbprc
|
returns a list of users with a ttbp by checking for a valid ttbprc
|
||||||
|
@ -457,12 +444,7 @@ def toggle_nopub(filename):
|
||||||
NOPUBS.remove(filename)
|
NOPUBS.remove(filename)
|
||||||
else:
|
else:
|
||||||
NOPUBS.append(filename)
|
NOPUBS.append(filename)
|
||||||
live_html = os.path.join(config.WWW, filename.split(".")[0]+".html")
|
unpublish_feel(filename)
|
||||||
if os.path.exists(live_html):
|
|
||||||
subprocess.call(["rm", live_html])
|
|
||||||
live_gopher = os.path.join(config.GOPHER_PATH, filename)
|
|
||||||
if os.path.exists(live_gopher):
|
|
||||||
subprocess.call(["rm", live_gopher])
|
|
||||||
|
|
||||||
nopub_file = open(config.NOPUB, 'w')
|
nopub_file = open(config.NOPUB, 'w')
|
||||||
nopub_file.write("""\
|
nopub_file.write("""\
|
||||||
|
@ -478,6 +460,93 @@ def toggle_nopub(filename):
|
||||||
|
|
||||||
return action
|
return action
|
||||||
|
|
||||||
|
def bury_feel(filename):
|
||||||
|
"""buries given filename; this removes the feel from any publicly-readable
|
||||||
|
location, and moves the textfile to user's private feels directory.
|
||||||
|
|
||||||
|
timestring will be added to the filename to disambiguate and prevent
|
||||||
|
filename collisions.
|
||||||
|
|
||||||
|
creates buried feels dir if it doesn't exist.
|
||||||
|
|
||||||
|
regenerates feels list and republishes."""
|
||||||
|
|
||||||
|
if not os.path.exists(config.BURIED_FEELS):
|
||||||
|
os.mkdir(config.BURIED_FEELS)
|
||||||
|
subprocess.call(["chmod", "700", config.BURIED_FEELS])
|
||||||
|
|
||||||
|
buryname = os.path.splitext(os.path.basename(filename))[0]+"-"+str(int(time.time()))+".txt"
|
||||||
|
|
||||||
|
subprocess.call(["mv", os.path.join(config.MAIN_FEELS, filename), os.path.join(config.BURIED_FEELS, buryname)])
|
||||||
|
subprocess.call(["chmod", "600", os.path.join(config.BURIED_FEELS, buryname)])
|
||||||
|
|
||||||
|
if publishing():
|
||||||
|
unpublish_feel(filename)
|
||||||
|
|
||||||
|
load_files()
|
||||||
|
|
||||||
|
return os.path.join(config.BURIED_FEELS, buryname)
|
||||||
|
|
||||||
|
def delete_feel(filename):
|
||||||
|
"""deletes given filename; removes the feel from publicly-readable
|
||||||
|
locations, then deletes the original file."""
|
||||||
|
|
||||||
|
feel = os.path.join(config.MAIN_FEELS, filename)
|
||||||
|
if os.path.exists(feel):
|
||||||
|
subprocess.call(["rm", feel])
|
||||||
|
unpublish_feel(filename)
|
||||||
|
load_files(config.MAIN_FEELS)
|
||||||
|
|
||||||
|
def unpublish_feel(filename):
|
||||||
|
"""takes given filename and removes it from public_html and gopher_html, if
|
||||||
|
those locations exists. afterwards, regenerate index files appropriately."""
|
||||||
|
|
||||||
|
live_html = os.path.join(config.WWW,
|
||||||
|
os.path.splitext(os.path.basename(filename))[0]+".html")
|
||||||
|
if os.path.exists(live_html):
|
||||||
|
subprocess.call(["rm", live_html])
|
||||||
|
live_gopher = os.path.join(config.GOPHER_PATH, filename)
|
||||||
|
if os.path.exists(live_gopher):
|
||||||
|
subprocess.call(["rm", live_gopher])
|
||||||
|
|
||||||
|
def process_backup(filename):
|
||||||
|
"""takes given filename and unpacks it into a temp directory, then returns a
|
||||||
|
list of filenames with collisions filtered out.
|
||||||
|
|
||||||
|
ignores any invalidly named files or files that already exist, to avoid
|
||||||
|
clobbering current feels. ignored files are left in the archive directory
|
||||||
|
for the user to manually sort out."""
|
||||||
|
|
||||||
|
backup_dir = os.path.splitext(os.path.splitext(os.path.basename(filename))[0])[0]
|
||||||
|
backup_path = os.path.join(config.BACKUPS, backup_dir)
|
||||||
|
|
||||||
|
if not os.path.exists(backup_path):
|
||||||
|
subprocess.call(["mkdir", backup_path])
|
||||||
|
|
||||||
|
subprocess.call(["chmod", "700", backup_path])
|
||||||
|
subprocess.call(["tar", "-C", backup_path, "-xf", filename])
|
||||||
|
backup_entries = os.path.join(backup_path, "entries")
|
||||||
|
|
||||||
|
backups = os.listdir(backup_entries)
|
||||||
|
current = os.listdir(config.MAIN_FEELS)
|
||||||
|
|
||||||
|
imported = []
|
||||||
|
|
||||||
|
for feel in backups:
|
||||||
|
if os.path.basename(feel) not in current:
|
||||||
|
imported.append(os.path.join(backup_entries, feel))
|
||||||
|
|
||||||
|
imported.sort()
|
||||||
|
return imported
|
||||||
|
|
||||||
|
def import_feels(backups):
|
||||||
|
"""takes a list of filepaths and copies those to current main feels.
|
||||||
|
|
||||||
|
this does not check for collisions.
|
||||||
|
"""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
#############
|
#############
|
||||||
#############
|
#############
|
||||||
|
|
|
@ -7,7 +7,8 @@ import time
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from . import util
|
from . import util
|
||||||
from .core import parse_date
|
from . import config
|
||||||
|
#from .core import parse_date
|
||||||
|
|
||||||
GOPHER_PROMPT = """
|
GOPHER_PROMPT = """
|
||||||
|
|
||||||
|
@ -73,7 +74,7 @@ def publish_gopher(gopher_path, entry_filenames):
|
||||||
if not os.path.exists(gopher_entry_symlink):
|
if not os.path.exists(gopher_entry_symlink):
|
||||||
subprocess.call(["ln", "-s", entry_filename, gopher_entry_symlink])
|
subprocess.call(["ln", "-s", entry_filename, gopher_entry_symlink])
|
||||||
|
|
||||||
label = "-".join(parse_date(entry_filename))
|
label = "-".join(util.parse_date(entry_filename))
|
||||||
gophermap.write('0{file_label}\t{filename}\n'.format(
|
gophermap.write('0{file_label}\t{filename}\n'.format(
|
||||||
file_label=label,
|
file_label=label,
|
||||||
filename=filename))
|
filename=filename))
|
||||||
|
@ -107,3 +108,11 @@ def setup_gopher(gopher_path):
|
||||||
os.makedirs(gopher_entries)
|
os.makedirs(gopher_entries)
|
||||||
|
|
||||||
subprocess.call(["ln", "-s", gopher_entries, ttbp_gopher])
|
subprocess.call(["ln", "-s", gopher_entries, ttbp_gopher])
|
||||||
|
|
||||||
|
def unpublish():
|
||||||
|
"""blanks all gopher things and recreates the directories."""
|
||||||
|
|
||||||
|
subprocess.call(["rm", "-rf", config.GOPHER_PATH])
|
||||||
|
subprocess.call(["rm", "-rf", config.GOPHER_ENTRIES])
|
||||||
|
os.mkdir(config.GOPHER_ENTRIES)
|
||||||
|
subprocess.call(["ln", "-s", config.GOPHER_ENTRIES, config.GOPHER_PATH])
|
||||||
|
|
664
ttbp/ttbp.py
664
ttbp/ttbp.py
|
@ -34,6 +34,7 @@ https://github.com/modgethanc/ttbp
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
|
@ -50,7 +51,7 @@ from . import chatter
|
||||||
from . import gopher
|
from . import gopher
|
||||||
from . import util
|
from . import util
|
||||||
|
|
||||||
__version__ = "0.11.2"
|
__version__ = "0.12.0"
|
||||||
__author__ = "endorphant <endorphant@tilde.town)"
|
__author__ = "endorphant <endorphant@tilde.town)"
|
||||||
|
|
||||||
p = inflect.engine()
|
p = inflect.engine()
|
||||||
|
@ -73,6 +74,7 @@ DEFAULT_SETTINGS = {
|
||||||
"gopher": False,
|
"gopher": False,
|
||||||
"publishing": False,
|
"publishing": False,
|
||||||
"rainbows": False,
|
"rainbows": False,
|
||||||
|
"post as nopub": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
## user globals
|
## user globals
|
||||||
|
@ -81,7 +83,8 @@ SETTINGS = {
|
||||||
"publish dir": None,
|
"publish dir": None,
|
||||||
"gopher": False,
|
"gopher": False,
|
||||||
"publishing": False,
|
"publishing": False,
|
||||||
"rainbows": False
|
"rainbows": False,
|
||||||
|
"post as nopub": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
## ttbp specific utilities
|
## ttbp specific utilities
|
||||||
|
@ -247,10 +250,7 @@ def init():
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
input("""
|
input(config.intro_prompt)
|
||||||
i don't recognize you, stranger. let's make friends.
|
|
||||||
|
|
||||||
press <enter> to begin, or <ctrl-c> to get out of here.""")
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("\n\nthanks for checking in! i'll always be here.\n\n")
|
print("\n\nthanks for checking in! i'll always be here.\n\n")
|
||||||
quit()
|
quit()
|
||||||
|
@ -259,7 +259,7 @@ press <enter> to begin, or <ctrl-c> to get out of here.""")
|
||||||
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
print("...")
|
print("...")
|
||||||
time.sleep(1)
|
time.sleep(.5)
|
||||||
|
|
||||||
## record user in source list
|
## record user in source list
|
||||||
users = open(config.USERFILE, 'a')
|
users = open(config.USERFILE, 'a')
|
||||||
|
@ -272,7 +272,7 @@ press <enter> to begin, or <ctrl-c> to get out of here.""")
|
||||||
print("\ngenerating feels at {path}...".format(path=config.PATH).rstrip())
|
print("\ngenerating feels at {path}...".format(path=config.PATH).rstrip())
|
||||||
subprocess.call(["mkdir", config.PATH])
|
subprocess.call(["mkdir", config.PATH])
|
||||||
subprocess.call(["mkdir", config.USER_CONFIG])
|
subprocess.call(["mkdir", config.USER_CONFIG])
|
||||||
subprocess.call(["mkdir", config.USER_DATA])
|
subprocess.call(["mkdir", config.MAIN_FEELS])
|
||||||
|
|
||||||
versionFile = os.path.join(config.PATH, "version")
|
versionFile = os.path.join(config.PATH, "version")
|
||||||
open(versionFile, "w").write(__version__)
|
open(versionFile, "w").write(__version__)
|
||||||
|
@ -291,13 +291,21 @@ press <enter> to begin, or <ctrl-c> to get out of here.""")
|
||||||
f.write(config.DEFAULT_STYLE)
|
f.write(config.DEFAULT_STYLE)
|
||||||
|
|
||||||
## run user-interactive setup and load core engine
|
## run user-interactive setup and load core engine
|
||||||
time.sleep(1)
|
time.sleep(0.5)
|
||||||
print("done setting up feels!")
|
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!!")
|
print("\nthese are the default settings. you can change any of them now, or change them later at any time!!")
|
||||||
setup()
|
setup()
|
||||||
core.load(SETTINGS)
|
core.load(SETTINGS)
|
||||||
|
|
||||||
input("\nyou're all good to go, "+chatter.say("friend")+"! hit <enter> to continue.\n\n")
|
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")))
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def gen_header():
|
def gen_header():
|
||||||
|
@ -406,7 +414,7 @@ def setup_repair():
|
||||||
save_settings()
|
save_settings()
|
||||||
|
|
||||||
print("...")
|
print("...")
|
||||||
time.sleep(1)
|
time.sleep(0.5)
|
||||||
input("\nyou're all good to go, "+chatter.say("friend")+"! hit <enter> to continue.\n\n")
|
input("\nyou're all good to go, "+chatter.say("friend")+"! hit <enter> to continue.\n\n")
|
||||||
|
|
||||||
def setup():
|
def setup():
|
||||||
|
@ -436,68 +444,74 @@ def setup():
|
||||||
redraw(EJECT)
|
redraw(EJECT)
|
||||||
return SETTINGS
|
return SETTINGS
|
||||||
|
|
||||||
if choice in QUITS:
|
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")))
|
||||||
redraw()
|
redraw()
|
||||||
|
|
||||||
return SETTINGS
|
return SETTINGS
|
||||||
|
|
||||||
# editor selection
|
else:
|
||||||
if settingList[int(choice)] == "editor":
|
redraw("now changing your settings. press <ctrl-c> if you didn't mean to do this.")
|
||||||
SETTINGS.update({"editor": select_editor()})
|
|
||||||
redraw("text editor set to: {editor}".format(editor=SETTINGS["editor"]))
|
|
||||||
save_settings()
|
|
||||||
return setup()
|
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")))
|
|
||||||
redraw()
|
|
||||||
|
|
||||||
return SETTINGS
|
|
||||||
|
|
||||||
def save_settings():
|
def save_settings():
|
||||||
"""
|
"""
|
||||||
Save current settings.
|
Save current settings.
|
||||||
|
@ -516,7 +530,7 @@ def main_menu():
|
||||||
|
|
||||||
menuOptions = [
|
menuOptions = [
|
||||||
"record your feels",
|
"record your feels",
|
||||||
"review your feels",
|
"manage your feels",
|
||||||
"check out your neighbors",
|
"check out your neighbors",
|
||||||
"browse global feels",
|
"browse global feels",
|
||||||
"scribble some graffiti",
|
"scribble some graffiti",
|
||||||
|
@ -537,18 +551,13 @@ def main_menu():
|
||||||
if choice == '0':
|
if choice == '0':
|
||||||
redraw()
|
redraw()
|
||||||
today = time.strftime("%Y%m%d")
|
today = time.strftime("%Y%m%d")
|
||||||
write_entry(os.path.join(config.USER_DATA, today+".txt"))
|
write_entry(os.path.join(config.MAIN_FEELS, today+".txt"))
|
||||||
core.www_neighbors()
|
core.www_neighbors()
|
||||||
elif choice == '1':
|
elif choice == '1':
|
||||||
if core.publishing():
|
intro = "here are some options for managing your feels:"
|
||||||
intro = "here are some options for reviewing your feels:"
|
redraw(intro)
|
||||||
redraw(intro)
|
review_menu(intro)
|
||||||
review_menu(intro)
|
core.load_files()
|
||||||
core.load_files()
|
|
||||||
core.write("index.html")
|
|
||||||
else:
|
|
||||||
redraw("your recorded feels, listed by date:")
|
|
||||||
view_feels(config.USER)
|
|
||||||
elif choice == '2':
|
elif choice == '2':
|
||||||
users = core.find_ttbps()
|
users = core.find_ttbps()
|
||||||
prompt = "the following {usercount} {are} recording feels on ttbp:".format(
|
prompt = "the following {usercount} {are} recording feels on ttbp:".format(
|
||||||
|
@ -571,7 +580,7 @@ def main_menu():
|
||||||
redraw()
|
redraw()
|
||||||
show_credits()
|
show_credits()
|
||||||
elif choice == '8':
|
elif choice == '8':
|
||||||
subprocess.call(["lynx", os.path.join(config.INSTALL_PATH, "..", "README.html")])
|
subprocess.call(["lynx", os.path.join(config.INSTALL_PATH, "..", "doc", "manual.html")])
|
||||||
redraw()
|
redraw()
|
||||||
elif choice in QUITS:
|
elif choice in QUITS:
|
||||||
return stop()
|
return stop()
|
||||||
|
@ -614,26 +623,72 @@ def review_menu(intro=""):
|
||||||
|
|
||||||
menuOptions = [
|
menuOptions = [
|
||||||
"read over feels",
|
"read over feels",
|
||||||
"modify feels publishing"
|
"modify feels publishing",
|
||||||
|
"backup your feels",
|
||||||
|
"import a feels backup",
|
||||||
|
"bury some feels",
|
||||||
|
"delete feels by day",
|
||||||
|
"purge all feels",
|
||||||
|
"wipe feels account"
|
||||||
]
|
]
|
||||||
|
|
||||||
util.print_menu(menuOptions, SETTINGS.get("rainbows", False))
|
util.print_menu(menuOptions, SETTINGS.get("rainbows", False))
|
||||||
|
|
||||||
choice = util.list_select(menuOptions, "what would you like to do with your feels? (or 'back' to return home) ")
|
choice = util.list_select(menuOptions, "what would you like to do with your feels? (or 'q' to return home) ")
|
||||||
|
|
||||||
|
top = ""
|
||||||
|
hasfeels = len(os.listdir(config.MAIN_FEELS)) > 0
|
||||||
|
nofeels = "you don't have any feels to work with, "+chatter.say("friend")+"\n\n> "
|
||||||
|
|
||||||
if choice is not False:
|
if choice is not False:
|
||||||
if choice == 0:
|
if choice == 0:
|
||||||
redraw("your recorded feels, listed by date:")
|
if hasfeels:
|
||||||
view_feels(config.USER)
|
redraw("your recorded feels, listed by date:")
|
||||||
|
view_feels(config.USER)
|
||||||
|
else:
|
||||||
|
top = nofeels
|
||||||
elif choice == 1:
|
elif choice == 1:
|
||||||
redraw("publishing status of your feels:")
|
if hasfeels:
|
||||||
list_nopubs(config.USER)
|
redraw("publishing status of your feels:")
|
||||||
|
list_nopubs(config.USER)
|
||||||
|
else:
|
||||||
|
top = nofeels
|
||||||
|
elif choice == 2:
|
||||||
|
if hasfeels:
|
||||||
|
redraw("FEELS BACKUP")
|
||||||
|
backup_feels()
|
||||||
|
else:
|
||||||
|
top = nofeels
|
||||||
|
elif choice == 3:
|
||||||
|
redraw("loading feels backup")
|
||||||
|
load_backup()
|
||||||
|
elif choice == 4:
|
||||||
|
if hasfeels:
|
||||||
|
redraw("burying feels")
|
||||||
|
bury_feels()
|
||||||
|
else:
|
||||||
|
top = nofeels
|
||||||
|
elif choice == 5:
|
||||||
|
if hasfeels:
|
||||||
|
redraw("deleting feels")
|
||||||
|
delete_feels()
|
||||||
|
else:
|
||||||
|
top = nofeels
|
||||||
|
elif choice == 6:
|
||||||
|
if hasfeels:
|
||||||
|
redraw("!!!PURGING ALL FEELS!!!")
|
||||||
|
purge_feels()
|
||||||
|
else:
|
||||||
|
top = nofeels
|
||||||
|
elif choice == 7:
|
||||||
|
redraw("!!! WIPING FEELS ACCOUNT !!!")
|
||||||
|
wipe_account()
|
||||||
else:
|
else:
|
||||||
redraw()
|
redraw()
|
||||||
return
|
return
|
||||||
|
|
||||||
redraw(intro)
|
redraw(top+intro)
|
||||||
return review_menu()
|
return review_menu(intro)
|
||||||
|
|
||||||
def view_neighbors(users, prompt):
|
def view_neighbors(users, prompt):
|
||||||
'''
|
'''
|
||||||
|
@ -694,7 +749,7 @@ def view_neighbors(users, prompt):
|
||||||
sortedUsers.append(user[0])
|
sortedUsers.append(user[0])
|
||||||
userIndex.append(user[2])
|
userIndex.append(user[2])
|
||||||
|
|
||||||
choice = menu_handler(sortedUsers, "pick a townie to browse their feels, or type 'back' or 'q' to go home: ", 15, SETTINGS.get("rainbows", False), prompt)
|
choice = menu_handler(sortedUsers, "pick a townie to browse their feels, or type 'q' to go home: ", 15, SETTINGS.get("rainbows", False), prompt)
|
||||||
|
|
||||||
if choice is not False:
|
if choice is not False:
|
||||||
redraw("~{user}'s recorded feels, listed by date: \n".format(user=userIndex[choice]))
|
redraw("~{user}'s recorded feels, listed by date: \n".format(user=userIndex[choice]))
|
||||||
|
@ -708,7 +763,6 @@ def view_feels(townie):
|
||||||
'''
|
'''
|
||||||
generates a list of all feels by given townie and displays in
|
generates a list of all feels by given townie and displays in
|
||||||
date order; allows selection of one feel to read.
|
date order; allows selection of one feel to read.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
metas, owner = generate_feels_list(townie)
|
metas, owner = generate_feels_list(townie)
|
||||||
|
@ -733,7 +787,7 @@ def generate_feels_list(user):
|
||||||
showpub = False
|
showpub = False
|
||||||
|
|
||||||
if user == config.USER:
|
if user == config.USER:
|
||||||
entryDir = config.USER_DATA
|
entryDir = config.MAIN_FEELS
|
||||||
owner = "your"
|
owner = "your"
|
||||||
if core.publishing():
|
if core.publishing():
|
||||||
showpub = True
|
showpub = True
|
||||||
|
@ -749,29 +803,320 @@ def generate_feels_list(user):
|
||||||
|
|
||||||
return metas, owner
|
return metas, owner
|
||||||
|
|
||||||
|
def backup_feels():
|
||||||
|
"""creates a tar.gz of user's entries directory"""
|
||||||
|
|
||||||
|
backupfile = os.path.join(os.path.expanduser('~'), "feels-backup-"+time.strftime("%Y%m%d-%H%M%S")+".tar.gz")
|
||||||
|
|
||||||
|
print("""\
|
||||||
|
i'm preparing all of your entries for backup.""")
|
||||||
|
|
||||||
|
print("...")
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
print("""
|
||||||
|
ready to go! a backup file will be saved to your home directory at:
|
||||||
|
{backuploc}""".format(backuploc=backupfile))
|
||||||
|
|
||||||
|
ans = util.input_yn("""\
|
||||||
|
|
||||||
|
would you like to create this backup?
|
||||||
|
|
||||||
|
please enter""")
|
||||||
|
|
||||||
|
if ans:
|
||||||
|
if not subprocess.call(["tar", "-C", config.PATH, "-czf", backupfile, "entries"]):
|
||||||
|
subprocess.call(["chmod", "600", backupfile])
|
||||||
|
if not os.path.exists(config.BACKUPS):
|
||||||
|
subprocess.call(["mkdir", config.BACKUPS])
|
||||||
|
subprocess.call(["chmod", "700", config.BACKUPS])
|
||||||
|
subprocess.call(["cp", backupfile, config.BACKUPS])
|
||||||
|
print("\nbackup saved! i also put a copy at {backup_dir} for you.".format(backup_dir = config.BACKUPS))
|
||||||
|
else:
|
||||||
|
print(config.mystery_error)
|
||||||
|
else:
|
||||||
|
print("no problem, {friend}; come back whenever if you want a backup!".format(friend=chatter.say("friend")))
|
||||||
|
|
||||||
|
input("\n\npress <enter> to go back to managing your feels.\n\n")
|
||||||
|
redraw()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def delete_feels():
|
||||||
|
"""handles deleting feels one at a time"""
|
||||||
|
|
||||||
|
feel = input("""which day's feels do you want to load for deletion?
|
||||||
|
|
||||||
|
YYYYMMDD (or 'q' to cancel)> """)
|
||||||
|
|
||||||
|
if feel in util.BACKS:
|
||||||
|
return
|
||||||
|
|
||||||
|
print("...")
|
||||||
|
time.sleep(0.1)
|
||||||
|
print("""\
|
||||||
|
here's a preview of that feel. press <q> when you're done reviewing!
|
||||||
|
-------------------------------------------------------------""")
|
||||||
|
|
||||||
|
if subprocess.call(["less", os.path.join(config.MAIN_FEELS, feel+".txt")]):
|
||||||
|
redraw("deleting feels")
|
||||||
|
print("""\
|
||||||
|
sorry, i couldn't find feels for {date}!
|
||||||
|
|
||||||
|
please try again, or type <q> to cancel.
|
||||||
|
""".format(date=feel))
|
||||||
|
return delete_feels()
|
||||||
|
|
||||||
|
print("""
|
||||||
|
-------------------------------------------------------------
|
||||||
|
|
||||||
|
feels deletion is irreversible! if you're sure you want to delete this feel,
|
||||||
|
type the date again to confirm, or 'q' to cancel.""")
|
||||||
|
|
||||||
|
confirm = input("[{feeldate}]> ".format(feeldate=feel))
|
||||||
|
|
||||||
|
if confirm == feel:
|
||||||
|
print("...")
|
||||||
|
time.sleep(0.5)
|
||||||
|
core.delete_feel(feel+".txt")
|
||||||
|
print("feels deleted!")
|
||||||
|
else:
|
||||||
|
print("deletion canceled!")
|
||||||
|
|
||||||
|
ans = util.input_yn("""do you want to delete a different feel?
|
||||||
|
please enter""")
|
||||||
|
|
||||||
|
if ans:
|
||||||
|
redraw("deleting feels")
|
||||||
|
return delete_feels()
|
||||||
|
else:
|
||||||
|
print("okay! please come back any time if you want to delete old feels!")
|
||||||
|
input("\n\npress <enter> to go back to managing your feels.\n\n")
|
||||||
|
redraw()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def purge_feels():
|
||||||
|
"""handles deleting all feels"""
|
||||||
|
|
||||||
|
print(config.feels_purge_prompt)
|
||||||
|
|
||||||
|
print("...")
|
||||||
|
time.sleep(0.5)
|
||||||
|
print("...loading feels...")
|
||||||
|
time.sleep(1)
|
||||||
|
print("...")
|
||||||
|
|
||||||
|
feelscount = len(os.listdir(config.MAIN_FEELS))
|
||||||
|
|
||||||
|
if feelscount > 0:
|
||||||
|
purgecode = util.genID(5)
|
||||||
|
|
||||||
|
print("""
|
||||||
|
|
||||||
|
i've loaded up all {count} of your feels for purging. if you're ready, carefully
|
||||||
|
type the following purge code:
|
||||||
|
_________
|
||||||
|
| |
|
||||||
|
| {purgecode} |
|
||||||
|
|_______|
|
||||||
|
""".format(purgecode=purgecode, count=feelscount))
|
||||||
|
|
||||||
|
ans = input("(leave blank or type anything else to cancel) > ")
|
||||||
|
|
||||||
|
if ans == purgecode:
|
||||||
|
print("...")
|
||||||
|
time.sleep(0.5)
|
||||||
|
unpublish()
|
||||||
|
|
||||||
|
if not subprocess.call(["rm", "-rf", config.MAIN_FEELS]):
|
||||||
|
subprocess.call(["mkdir", config.MAIN_FEELS])
|
||||||
|
core.load_files()
|
||||||
|
print("ALL FEELS PURGED! you're ready to start fresh!")
|
||||||
|
else:
|
||||||
|
print(config.mystery_error)
|
||||||
|
else:
|
||||||
|
print("\nfeels purge canceled! you're welcome to come back again.")
|
||||||
|
else:
|
||||||
|
print("you don't have any feels to purge, "+chatter.say("friend"))
|
||||||
|
|
||||||
|
input("\n\npress <enter> to go back to managing your feels.\n\n")
|
||||||
|
redraw()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def wipe_account():
|
||||||
|
"""handles wiping feels account"""
|
||||||
|
|
||||||
|
print(config.account_wipe_prompt)
|
||||||
|
|
||||||
|
print("...")
|
||||||
|
time.sleep(0.5)
|
||||||
|
print("...packaging up all your feels...")
|
||||||
|
time.sleep(1)
|
||||||
|
print("...")
|
||||||
|
purgecode = util.genID(5)
|
||||||
|
|
||||||
|
print("""
|
||||||
|
your account is all packed up! if you're ready, carefully type the following
|
||||||
|
purge code:
|
||||||
|
_________
|
||||||
|
| |
|
||||||
|
| {purgecode} |
|
||||||
|
|_______|
|
||||||
|
""".format(purgecode=purgecode))
|
||||||
|
|
||||||
|
ans = input("(leave blank or type anything else to cancel) > ")
|
||||||
|
|
||||||
|
if ans == purgecode:
|
||||||
|
print("...")
|
||||||
|
time.sleep(0.5)
|
||||||
|
unpublish()
|
||||||
|
|
||||||
|
if core.publishing():
|
||||||
|
publishDir = os.path.join(config.PUBLIC, SETTINGS.get("publish dir"))
|
||||||
|
make_publish_dir(publishDir)
|
||||||
|
|
||||||
|
|
||||||
|
if not subprocess.call(["rm", "-rf", config.PATH]):
|
||||||
|
print("""
|
||||||
|
account deleted! if you ever want to come back, you're always welcome to start
|
||||||
|
fresh :)
|
||||||
|
|
||||||
|
thank you for sharing your feels!""")
|
||||||
|
input("\n\npress <enter> to exit the feels engine.\n\n")
|
||||||
|
sys.exit(stop())
|
||||||
|
else:
|
||||||
|
print(config.mystery_error)
|
||||||
|
else:
|
||||||
|
print("\naccount deletion canceled! you're welcome to come back again.")
|
||||||
|
|
||||||
|
input("\n\npress <enter> to go back to managing your feels.\n\n")
|
||||||
|
redraw()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def load_backup():
|
||||||
|
"""
|
||||||
|
scans for archive files (prompting for a file location if not found), opens,
|
||||||
|
copies files to main feels directory (skipping ones that already exist)
|
||||||
|
"""
|
||||||
|
|
||||||
|
print("scanning backup directory at {directory}...".format(directory=config.BACKUPS))
|
||||||
|
|
||||||
|
time.sleep(.5)
|
||||||
|
print("...\n")
|
||||||
|
|
||||||
|
backups = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
for filename in os.listdir(config.BACKUPS):
|
||||||
|
if "feels-backup" in filename and ".tar" in filename:
|
||||||
|
backups.append(filename)
|
||||||
|
except FileNotFoundError:
|
||||||
|
subprocess.call(["mkdir", config.BACKUPS])
|
||||||
|
|
||||||
|
if len(backups) < 1:
|
||||||
|
print("""
|
||||||
|
sorry, i didn't find any feels backups! if you have a backup file handy, please
|
||||||
|
move it to {directory} and try running this tool again.\
|
||||||
|
""".format(directory=config.BACKUPS))
|
||||||
|
else:
|
||||||
|
print("backup files found:\n")
|
||||||
|
choice = menu_handler(backups, "pick a backup file to load (or 'q' to cancel): ", 15, SETTINGS.get("rainbows", False), "backup files found:")
|
||||||
|
|
||||||
|
if choice is not False:
|
||||||
|
imports = core.process_backup(os.path.join(config.BACKUPS, backups[choice]))
|
||||||
|
for feel in imports:
|
||||||
|
print("importing {entry}".format(entry="-".join(util.parse_date(feel))))
|
||||||
|
subprocess.call(["mv", feel, config.MAIN_FEELS])
|
||||||
|
time.sleep(.01)
|
||||||
|
|
||||||
|
core.load_files()
|
||||||
|
|
||||||
|
tempdir = os.path.join(config.BACKUPS, os.path.splitext(os.path.splitext(os.path.basename(backups[choice]))[0])[0], "entries")
|
||||||
|
|
||||||
|
time.sleep(.5)
|
||||||
|
print("...\n")
|
||||||
|
|
||||||
|
if len(os.listdir(tempdir)) == 0:
|
||||||
|
os.rmdir(tempdir)
|
||||||
|
print("congrats! your feels archive has been unloaded.")
|
||||||
|
else:
|
||||||
|
print("""\
|
||||||
|
i've unloaded as much as i can, but there are still some feels i didn't copy
|
||||||
|
over. this is probably because you have current feels on the same days, and i
|
||||||
|
didn't want to overwrite them.
|
||||||
|
|
||||||
|
you can check out the leftover feels yourself at:
|
||||||
|
|
||||||
|
{directory}""".format(directory=tempdir))
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
input("\n\npress <enter> to go back to managing your feels.\n\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
def bury_feels():
|
||||||
|
"""queries for a feel to bury, then calls the feels burying handler.
|
||||||
|
"""
|
||||||
|
|
||||||
|
feel = input(config.bury_feels_prompt)
|
||||||
|
|
||||||
|
if feel in util.BACKS:
|
||||||
|
return
|
||||||
|
|
||||||
|
print("...")
|
||||||
|
time.sleep(0.1)
|
||||||
|
print("""\
|
||||||
|
here's a preview of that feel. press <q> when you're done reviewing!
|
||||||
|
-------------------------------------------------------------""")
|
||||||
|
|
||||||
|
if subprocess.call(["less", os.path.join(config.MAIN_FEELS, feel+".txt")]):
|
||||||
|
redraw("burying feels")
|
||||||
|
print("""\
|
||||||
|
sorry, i couldn't find feels for {date}!
|
||||||
|
|
||||||
|
please try again, or type <q> to cancel.
|
||||||
|
""".format(date=feel))
|
||||||
|
return delete_feels()
|
||||||
|
|
||||||
|
print("""
|
||||||
|
-------------------------------------------------------------
|
||||||
|
|
||||||
|
feels burying is irreversible! if you're sure you want to bury this feel,
|
||||||
|
type the date again to confirm, or 'q' to cancel.
|
||||||
|
""")
|
||||||
|
|
||||||
|
confirm = input("[{feeldate}]> ".format(feeldate=feel))
|
||||||
|
|
||||||
|
if confirm == feel:
|
||||||
|
print("...")
|
||||||
|
time.sleep(0.5)
|
||||||
|
core.bury_feel(feel+".txt")
|
||||||
|
print("feels buried!")
|
||||||
|
else:
|
||||||
|
print("burying canceled!")
|
||||||
|
|
||||||
|
ans = util.input_yn("""do you want to bury a different feel? please enter""")
|
||||||
|
|
||||||
|
if ans:
|
||||||
|
redraw("burying feels")
|
||||||
|
return bury_feels()
|
||||||
|
else:
|
||||||
|
print("okay! please come back any time if you want to bury your feels!")
|
||||||
|
input("\n\npress <enter> to go back to managing your feels.\n\n")
|
||||||
|
redraw()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
def show_credits():
|
def show_credits():
|
||||||
'''
|
'''
|
||||||
prints author acknowledgements and commentary
|
prints author acknowledgements and commentary
|
||||||
'''
|
'''
|
||||||
|
|
||||||
print("""
|
print(config.credits)
|
||||||
ttbp was written for tilde.town by ~endorphant in python. the codebase is
|
|
||||||
publicly available on github at https://github.com/modgethanc/ttbp
|
|
||||||
|
|
||||||
other contributors:
|
|
||||||
~vilmibm, packaging help and gopher support
|
|
||||||
~sanqui, the bug swatter
|
|
||||||
|
|
||||||
if you have ideas for ttbp, you are welcome to contact me to discuss them;
|
|
||||||
please send me tildemail or open a github issue. i am not a very experienced
|
|
||||||
developer, and ttbp is one of my first public-facing projects, so i appreciate
|
|
||||||
your patience while i learn how to be a better developer!
|
|
||||||
|
|
||||||
i'd love to hear about your ideas and brainstorm about new features!
|
|
||||||
|
|
||||||
thanks to everyone who reads, listens, writes, and feels.\
|
|
||||||
""")
|
|
||||||
|
|
||||||
input("\n\npress <enter> to go back home.\n\n")
|
input("\n\npress <enter> to go back home.\n\n")
|
||||||
redraw()
|
redraw()
|
||||||
|
|
||||||
|
@ -779,24 +1124,12 @@ thanks to everyone who reads, listens, writes, and feels.\
|
||||||
|
|
||||||
## handlers
|
## handlers
|
||||||
|
|
||||||
def write_entry(entry=os.path.join(config.USER_DATA, "test.txt")):
|
def write_entry(entry=os.path.join(config.MAIN_FEELS, "test.txt")):
|
||||||
'''
|
'''
|
||||||
main feels-recording handler
|
main feels-recording handler
|
||||||
'''
|
'''
|
||||||
|
|
||||||
entered = input("""
|
entered = input(config.recording)
|
||||||
feels will be recorded for today, {today}.
|
|
||||||
|
|
||||||
if you've already started recording feels for this day, you
|
|
||||||
can pick up where you left off.
|
|
||||||
|
|
||||||
you can write your feels in plaintext, markdown, html, or a mixture of
|
|
||||||
these.
|
|
||||||
|
|
||||||
press <enter> to begin recording your feels in your chosen text
|
|
||||||
editor.
|
|
||||||
|
|
||||||
""".format(today=time.strftime("%d %B %Y")))
|
|
||||||
|
|
||||||
if entered:
|
if entered:
|
||||||
entryFile = open(entry, "a")
|
entryFile = open(entry, "a")
|
||||||
|
@ -806,22 +1139,24 @@ editor.
|
||||||
|
|
||||||
left = ""
|
left = ""
|
||||||
|
|
||||||
|
core.load_files()
|
||||||
|
|
||||||
if SETTINGS.get("post as nopub"):
|
if SETTINGS.get("post as nopub"):
|
||||||
core.toggle_nopub(os.path.basename(entry))
|
core.toggle_nopub(os.path.basename(entry))
|
||||||
else:
|
else:
|
||||||
if core.publishing():
|
if core.publishing():
|
||||||
core.write("index.html")
|
core.write_html("index.html")
|
||||||
left = "posted to {url}/index.html\n\n>".format(
|
left = "posted to {url}/index.html\n\n> ".format(
|
||||||
url="/".join(
|
url="/".join(
|
||||||
[config.LIVE+config.USER,
|
[config.LIVE+config.USER,
|
||||||
str(SETTINGS.get("publish dir"))]))
|
str(SETTINGS.get("publish dir"))]))
|
||||||
|
|
||||||
if SETTINGS.get('gopher'):
|
if SETTINGS.get('gopher'):
|
||||||
gopher.publish_gopher('feels', core.get_files())
|
gopher.publish_gopher('feels', core.FILES)
|
||||||
left += " also posted to your ~/public_gopher!\n"
|
left += "also posted to your ~/public_gopher!\n\n> "
|
||||||
|
|
||||||
core.load_files()
|
#core.load_files()
|
||||||
redraw(left + " thanks for sharing your feels!")
|
redraw(left + "thanks for sharing your feels!")
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -841,6 +1176,14 @@ def set_nopubs(metas, user, prompt):
|
||||||
"""displays a list of entries for pub/nopub toggling.
|
"""displays a list of entries for pub/nopub toggling.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if core.publishing():
|
||||||
|
nopub_note = ""
|
||||||
|
else:
|
||||||
|
nopub_note = """\
|
||||||
|
(since you're not publishing your entries, these settings don't really matter;
|
||||||
|
none of your feels will be viewable outside of this server)"""
|
||||||
|
print(nopub_note + "\n")
|
||||||
|
|
||||||
entries = []
|
entries = []
|
||||||
for entry in metas:
|
for entry in metas:
|
||||||
pub = ""
|
pub = ""
|
||||||
|
@ -848,14 +1191,13 @@ def set_nopubs(metas, user, prompt):
|
||||||
pub = "(nopub)"
|
pub = "(nopub)"
|
||||||
entries.append(""+entry[4]+" ("+p.no("word", entry[2])+") "+"\t"+pub)
|
entries.append(""+entry[4]+" ("+p.no("word", entry[2])+") "+"\t"+pub)
|
||||||
|
|
||||||
choice = menu_handler(entries, "pick an entry from the list, or type 'q' to go back: ", 10, SETTINGS.get("rainbows", False), prompt)
|
choice = menu_handler(entries, "pick an entry from the list to toggle nopub status, or type 'q' to go back: ", 10, SETTINGS.get("rainbows", False), prompt+"\n\n"+nopub_note)
|
||||||
|
|
||||||
if choice is not False:
|
if choice is not False:
|
||||||
target = os.path.basename(metas[choice][0])
|
target = os.path.basename(metas[choice][0])
|
||||||
action = core.toggle_nopub(target)
|
action = core.toggle_nopub(target)
|
||||||
redraw(prompt)
|
redraw(prompt)
|
||||||
|
|
||||||
core.write("index.html")
|
|
||||||
if SETTINGS["gopher"]:
|
if SETTINGS["gopher"]:
|
||||||
gopher.publish_gopher('feels', core.get_files())
|
gopher.publish_gopher('feels', core.get_files())
|
||||||
|
|
||||||
|
@ -1107,14 +1449,14 @@ def select_publish_dir():
|
||||||
|
|
||||||
publishDir = os.path.join(config.PUBLIC, choice)
|
publishDir = os.path.join(config.PUBLIC, choice)
|
||||||
while os.path.exists(publishDir):
|
while os.path.exists(publishDir):
|
||||||
second = input("\n"+publishDir+"""\
|
second = input("""
|
||||||
already exists!
|
{pDir} already exists!
|
||||||
|
|
||||||
setting this as your publishing directory means this program may
|
setting this as your publishing directory means this program may
|
||||||
delete or overwrite file there!
|
delete or overwrite file there!
|
||||||
|
|
||||||
if you're sure you want to use it, hit <enter> to confirm.
|
if you're sure you want to use it, hit <enter> to confirm.
|
||||||
otherwise, pick another location: """)
|
otherwise, pick another location: """.format(pDir=publishDir))
|
||||||
|
|
||||||
if second == "":
|
if second == "":
|
||||||
break
|
break
|
||||||
|
@ -1159,11 +1501,14 @@ def unpublish():
|
||||||
|
|
||||||
if directory:
|
if directory:
|
||||||
publishDir = os.path.join(config.PUBLIC, directory)
|
publishDir = os.path.join(config.PUBLIC, directory)
|
||||||
subprocess.call(["rm", publishDir])
|
if os.path.exists(publishDir):
|
||||||
|
subprocess.call(["rm", "-rf", publishDir])
|
||||||
|
subprocess.call(["rm", "-rf", config.WWW])
|
||||||
|
make_publish_dir(SETTINGS.get("publish dir"))
|
||||||
|
#SETTINGS.update({"publish dir": None})
|
||||||
|
|
||||||
if SETTINGS.get("gopher"):
|
if SETTINGS.get("gopher"):
|
||||||
SETTINGS.update({"gopher": False})
|
gopher.unpublish()
|
||||||
subprocess.call(["rm", config.GOPHER_PATH])
|
|
||||||
|
|
||||||
def update_publishing():
|
def update_publishing():
|
||||||
'''
|
'''
|
||||||
|
@ -1180,14 +1525,13 @@ def update_publishing():
|
||||||
subprocess.call(["rm", os.path.join(config.PUBLIC, oldDir)])
|
subprocess.call(["rm", os.path.join(config.PUBLIC, oldDir)])
|
||||||
make_publish_dir(newDir)
|
make_publish_dir(newDir)
|
||||||
core.load_files()
|
core.load_files()
|
||||||
core.write("index.html")
|
#core.write_html("index.html")
|
||||||
else:
|
else:
|
||||||
unpublish()
|
unpublish()
|
||||||
SETTINGS.update({"publish dir": None})
|
|
||||||
|
|
||||||
core.load(SETTINGS)
|
core.load(SETTINGS)
|
||||||
|
|
||||||
def make_publish_dir(dir):
|
def make_publish_dir(publish_dir):
|
||||||
'''
|
'''
|
||||||
setup helper to create publishing directory
|
setup helper to create publishing directory
|
||||||
'''
|
'''
|
||||||
|
@ -1200,13 +1544,18 @@ def make_publish_dir(dir):
|
||||||
index.write("<h1>ttbp blog placeholder</h1>")
|
index.write("<h1>ttbp blog placeholder</h1>")
|
||||||
index.close()
|
index.close()
|
||||||
|
|
||||||
publishDir = os.path.join(config.PUBLIC, dir)
|
if core.publishing():
|
||||||
if os.path.exists(publishDir):
|
live = os.path.join(config.PUBLIC, publish_dir)
|
||||||
subprocess.call(["rm", publishDir])
|
if os.path.exists(live):
|
||||||
|
subprocess.call(["rm", live])
|
||||||
|
|
||||||
subprocess.call(["ln", "-s", config.WWW, publishDir])
|
subprocess.call(["ln", "-s", config.WWW, live])
|
||||||
|
|
||||||
print("\n\tpublishing to "+config.LIVE+config.USER+"/"+SETTINGS.get("publish dir")+"/\n\n")
|
return "\n\tpublishing to "+config.LIVE+config.USER+"/"+SETTINGS.get("publish dir")+"/\n\n"
|
||||||
|
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
#print("\n\tpublishing to "+config.LIVE+config.USER+"/"+SETTINGS.get("publish dir")+"/\n\n")
|
||||||
|
|
||||||
def update_gopher():
|
def update_gopher():
|
||||||
'''
|
'''
|
||||||
|
@ -1255,7 +1604,7 @@ def update_user_version():
|
||||||
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
print("...")
|
print("...")
|
||||||
time.sleep(1)
|
time.sleep(0.5)
|
||||||
|
|
||||||
userVersion = ""
|
userVersion = ""
|
||||||
(x, y, z) = [0, 0, 0]
|
(x, y, z) = [0, 0, 0]
|
||||||
|
@ -1284,7 +1633,7 @@ def update_user_version():
|
||||||
|
|
||||||
# repopulate html files
|
# repopulate html files
|
||||||
core.load_files()
|
core.load_files()
|
||||||
core.write("index.html")
|
#core.write_html("index.html")
|
||||||
|
|
||||||
# add publishing setting
|
# add publishing setting
|
||||||
print("\nnew feature!\n")
|
print("\nnew feature!\n")
|
||||||
|
@ -1335,6 +1684,19 @@ def update_user_version():
|
||||||
SETTINGS.update({"post as nopub": False})
|
SETTINGS.update({"post as nopub": False})
|
||||||
save_settings()
|
save_settings()
|
||||||
|
|
||||||
|
if z < 3:
|
||||||
|
# update permalink css
|
||||||
|
style = open(os.path.join(config.USER_CONFIG, 'style.css'), 'r').read()
|
||||||
|
if "permalink" not in style:
|
||||||
|
print("adding new css...")
|
||||||
|
with open(os.path.join(config.USER_CONFIG, 'style.css'), 'a') as f:
|
||||||
|
f.write("""
|
||||||
|
.entry p.permalink {
|
||||||
|
font-size: .6em;
|
||||||
|
font-color: #808080;
|
||||||
|
text-align: right;
|
||||||
|
}""")
|
||||||
|
|
||||||
print("""
|
print("""
|
||||||
you're all good to go, """+chatter.say("friend")+"""! please contact ~endorphant if
|
you're all good to go, """+chatter.say("friend")+"""! please contact ~endorphant if
|
||||||
something strange happened to you during this update.
|
something strange happened to you during this update.
|
||||||
|
@ -1356,6 +1718,14 @@ something strange happened to you during this update.
|
||||||
# version 0.11.2 patch notes
|
# version 0.11.2 patch notes
|
||||||
print(config.UPDATES["0.11.2"])
|
print(config.UPDATES["0.11.2"])
|
||||||
|
|
||||||
|
if y < 11 or z < 3:
|
||||||
|
# version 0.11.3 patch notes
|
||||||
|
print(config.UPDATES["0.11.3"])
|
||||||
|
|
||||||
|
if y < 12:
|
||||||
|
# version 0.12.0 patch notes
|
||||||
|
print(config.UPDATES["0.12.0"])
|
||||||
|
|
||||||
confirm = ""
|
confirm = ""
|
||||||
|
|
||||||
while confirm not in ("x", "<x>", "X", "<X>"):
|
while confirm not in ("x", "<x>", "X", "<X>"):
|
||||||
|
|
21
ttbp/util.py
21
ttbp/util.py
|
@ -26,12 +26,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
from six.moves import input
|
from six.moves import input
|
||||||
|
import os
|
||||||
|
|
||||||
import colorama
|
import colorama
|
||||||
import inflect
|
import inflect
|
||||||
|
|
||||||
## misc globals
|
## misc globals
|
||||||
BACKS = ['back', 'b', 'q']
|
BACKS = ['back', 'b', 'q', '<q>']
|
||||||
NAVS = ['u', 'd']
|
NAVS = ['u', 'd']
|
||||||
|
|
||||||
## color stuff
|
## color stuff
|
||||||
|
@ -214,3 +215,21 @@ def input_yn(query):
|
||||||
ans = input("'y' or 'n' please: ")
|
ans = input("'y' or 'n' please: ")
|
||||||
|
|
||||||
return ans == "y"
|
return ans == "y"
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue