forked from endorphant/ttbp
		
	Merge branch 'master' of github.com:modgethanc/ttbp
This commit is contained in:
		
						commit
						198bde8ed3
					
				
							
								
								
									
										258
									
								
								README.html
									
									
									
									
									
								
							
							
						
						
									
										258
									
								
								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> | ||||||
							
								
								
									
										192
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										192
									
								
								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,24 +36,37 @@ 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 | ||||||
| 
 | 
 | ||||||
| @ -59,57 +76,144 @@ of date order by creating files with any date you want. | |||||||
|   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 | ||||||
|  | |||||||
							
								
								
									
										170
									
								
								doc/manual.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								doc/manual.html
									
									
									
									
									
										Normal file
									
								
							| @ -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> | ||||||
							
								
								
									
										196
									
								
								doc/manual.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								doc/manual.md
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||||
| 
 | 
 | ||||||
| @ -153,5 +250,46 @@ version 0.9.3 features: | |||||||
|       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; | ||||||
|  | |||||||
							
								
								
									
										155
									
								
								ttbp/core.py
									
									
									
									
									
								
							
							
						
						
									
										155
									
								
								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,19 +77,16 @@ 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): |  | ||||||
|                 subprocess.call(["rm", link]) |  | ||||||
|             continue |  | ||||||
|         filename = os.path.join(config.USER_DATA, filename) |  | ||||||
|             if os.path.isfile(filename) and valid(filename): |             if os.path.isfile(filename) and valid(filename): | ||||||
|                 files.append(filename) |                 files.append(filename) | ||||||
| 
 | 
 | ||||||
| @ -96,19 +95,24 @@ def get_files(): | |||||||
| 
 | 
 | ||||||
|     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]) | ||||||
|  | |||||||
							
								
								
									
										532
									
								
								ttbp/ttbp.py
									
									
									
									
									
								
							
							
						
						
									
										532
									
								
								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,6 +444,8 @@ def setup(): | |||||||
|         redraw(EJECT) |         redraw(EJECT) | ||||||
|         return SETTINGS |         return SETTINGS | ||||||
| 
 | 
 | ||||||
|  |     if choice is not "": | ||||||
|  | 
 | ||||||
|         if choice in QUITS: |         if choice in QUITS: | ||||||
|             redraw() |             redraw() | ||||||
|             return SETTINGS |             return SETTINGS | ||||||
| @ -498,6 +508,10 @@ def setup(): | |||||||
| 
 | 
 | ||||||
|         return SETTINGS |         return SETTINGS | ||||||
| 
 | 
 | ||||||
|  |     else: | ||||||
|  |         redraw("now changing your settings. press <ctrl-c> if you didn't mean to do this.") | ||||||
|  |         return setup() | ||||||
|  | 
 | ||||||
| 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: | ||||||
|  |             if hasfeels: | ||||||
|                 redraw("your recorded feels, listed by date:") |                 redraw("your recorded feels, listed by date:") | ||||||
|                 view_feels(config.USER) |                 view_feels(config.USER) | ||||||
|  |             else: | ||||||
|  |                 top = nofeels | ||||||
|         elif choice == 1: |         elif choice == 1: | ||||||
|  |             if hasfeels: | ||||||
|                 redraw("publishing status of your feels:") |                 redraw("publishing status of your feels:") | ||||||
|                 list_nopubs(config.USER) |                 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,21 +1139,23 @@ 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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user