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><code>ttbp</code> stands for "tilde.town blogging platform", the original working name for | ||||
| this project.</p> | ||||
| 
 | ||||
| <p><img src="http://tilde.town/~endorphant/ttbp/screenshots/ttbp-main.png" alt="ttbp main menu screenshot" /></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><img alt="ttbp main menu screenshot" src="http://tilde.town/~endorphant/ttbp/screenshots/ttbp-main.png" /></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><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, or keep all your entries private | ||||
| to the tilde.town server.</p> | ||||
| 
 | ||||
| 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>to use, run <code>feels</code> while logged in to tilde.town</p> | ||||
| 
 | ||||
| <p>(<code>feels</code> is a tilde.town specific command; if you're running this locally, or on | ||||
| a different server, run <code>ttbp</code> from the command line)</p> | ||||
| 
 | ||||
| <h3 id="quickstart">QUICK START</h3> | ||||
| 
 | ||||
| <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>QUICK START</h3> | ||||
| <p>no coding or html experience is necessary to get started. just log in to your | ||||
| tilde.town account and enter:</p> | ||||
| 
 | ||||
| <p><code>feels</code></p> | ||||
| 
 | ||||
| <p>ttbp will ask you a few questions to get you started. after that, writing and | ||||
| reading entries all happen within the program.</p> | ||||
| 
 | ||||
| <p>that's it!</p> | ||||
| 
 | ||||
| <h3 id="support">SUPPORT</h3> | ||||
| 
 | ||||
| <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> | ||||
| 
 | ||||
| <h3 id="writingentries">writing entries</h3> | ||||
| 
 | ||||
| <p>entries are recorded as plaintext files in your ~/.ttbp/entries | ||||
| directory. you can edit them there directly, or fix old entries, or | ||||
| delete entries.</p> | ||||
| 
 | ||||
| <p><em>warning</em>: 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.</p> | ||||
| 
 | ||||
| <h4 id="generalentrywritingnotes">general entry-writing notes</h4> | ||||
| 
 | ||||
| <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 id="privacy">privacy</h3> | ||||
| 
 | ||||
| <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 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>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 | ||||
| <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> | ||||
| 
 | ||||
| <h3 id="changingyourpagelayout">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> | ||||
| 
 | ||||
| <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>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> | ||||
| <li>(future feature: having multiple stylesheets you can select)</li></ul> | ||||
| </li> | ||||
| 
 | ||||
| <li>to modify the page header, edit your ~/.ttbp/config/header.txt | ||||
| 
 | ||||
| 
 | ||||
| <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>you might note that there's a place marked off in the default header where | ||||
| you can safely put custom HTML elements!</li></ul> | ||||
| </li> | ||||
| 
 | ||||
| <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 id="generaltipstroubleshooting">general tips/troubleshooting</h3> | ||||
| 
 | ||||
| <h3>general tips/troubleshooting</h3> | ||||
| <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 | ||||
|   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 id="futurefeatures">future features</h3> | ||||
| 
 | ||||
| <h3>future features</h3> | ||||
| <p>these are a few ideas being kicked around, or under active development:</p> | ||||
| 
 | ||||
| <ul> | ||||
| <li>better entry privacy/publish control options</li> | ||||
| 
 | ||||
| <li>stylesheet/theme selector</li> | ||||
| 
 | ||||
| <li>responding to entries</li> | ||||
| 
 | ||||
| <li>paginated list view</li> | ||||
| 
 | ||||
| <li>better entry display within ttbp</li> | ||||
| <li>better entry display within ttbp (currently just offloads to <code>less</code>)</li> | ||||
| <li>buried feels browser</li> | ||||
| </ul> | ||||
| 
 | ||||
| <h3 id="dependencies">dependencies</h3> | ||||
| 
 | ||||
| <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> | ||||
| <h3>dependencies</h3> | ||||
| <p>(this section is only relevant if you plan on forking the repo and running an | ||||
| instance of this yourself)</p> | ||||
| 
 | ||||
| <ul> | ||||
| <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/six">six</a></li> | ||||
| </ul> | ||||
| 
 | ||||
| <h3 id="contributing">contributing</h3> | ||||
| 
 | ||||
| <h3>contributing</h3> | ||||
| <p>please check out my <a href="https://github.com/modgethanc/ttbp/blob/master/.github/CONTRIBUTING.md">contributor | ||||
| guidelines</a> | ||||
| 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 | ||||
| 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>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 | ||||
| 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, or keep all your entries private | ||||
| to the tilde.town server. | ||||
| 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. | ||||
| 
 | ||||
| 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 | ||||
| a different server, run `ttbp` from the command line) | ||||
| 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. | ||||
| 
 | ||||
| 
 | ||||
| ### QUICK START | ||||
| 
 | ||||
| @ -32,24 +36,37 @@ reading entries all happen within the program. | ||||
| 
 | ||||
| that's it! | ||||
| 
 | ||||
| ### SUPPORT | ||||
| ### 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. you can edit them there directly, or fix old entries, or | ||||
| delete 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. | ||||
| 
 | ||||
| *warning*: 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. | ||||
| 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 | ||||
| 
 | ||||
| @ -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 | ||||
|   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 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). | ||||
| 
 | ||||
| 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 | ||||
| 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.** | ||||
| 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 | ||||
|   * (future feature: having multiple stylesheets you can select) | ||||
| * 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 | ||||
|     you can safely put custom HTML elements! | ||||
|   * 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 | ||||
| 
 | ||||
| * 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 | ||||
|   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: | ||||
| 
 | ||||
| * better entry privacy/publish control options | ||||
| * stylesheet/theme selector | ||||
| * responding to entries | ||||
| * paginated list view | ||||
| * better entry display within ttbp | ||||
| * 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")! | ||||
| 
 | ||||
| ### dependencies | ||||
| 
 | ||||
| @ -118,6 +222,7 @@ instance of this yourself) | ||||
| 
 | ||||
| * [mistune](https://pypi.python.org/pypi/mistune) | ||||
| * [inflect](https://pypi.python.org/pypi/inflect) | ||||
| * [six](https://pypi.python.org/pypi/six) | ||||
| 
 | ||||
| ### 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. | ||||
| 
 | ||||
| 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( | ||||
|     name='ttbp', | ||||
|     version='0.11.2', | ||||
|     version='0.12.0', | ||||
|     description='command line social blogging tool used on tilde.town', | ||||
|     url='https://github.com/modgethanc/ttbp', | ||||
|     author='~endorphant', | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| from __future__ import absolute_import | ||||
| import os | ||||
| import sys | ||||
| import time | ||||
| 
 | ||||
| from .. import util | ||||
| 
 | ||||
| @ -67,11 +68,14 @@ USER_HOME = os.path.expanduser('~') | ||||
| PATH = os.path.join(USER_HOME, '.ttbp') | ||||
| PUBLIC = os.path.join(USER_HOME, 'public_html') | ||||
| WWW = os.path.join(PATH, 'www') | ||||
| GOPHER_ENTRIES = os.path.join(PATH, 'gopher') | ||||
| GOPHER_PATH = os.path.join(USER_HOME, 'public_gopher', 'feels') | ||||
| USER_CONFIG = os.path.join(PATH, 'config') | ||||
| TTBPRC = os.path.join(USER_CONFIG, 'ttbprc') | ||||
| USER_DATA = os.path.join(PATH, 'entries') | ||||
| NOPUB = os.path.join(USER_CONFIG, "nopub") | ||||
| MAIN_FEELS = os.path.join(PATH, 'entries') | ||||
| BURIED_FEELS = os.path.join(PATH, 'buried') | ||||
| NOPUB = os.path.join(USER_CONFIG, 'nopub') | ||||
| BACKUPS = os.path.join(PATH, 'backups') | ||||
| 
 | ||||
| ## UI | ||||
| 
 | ||||
| @ -82,9 +86,102 @@ ___________________________________________________________ | ||||
| |  ____ ____ ____ _    ____    ____ _  _ ____ _ _  _ ____  | | ||||
| |  |___ |___ |___ |    [__     |___ |\ | | __ | |\ | |___  | | ||||
| |  |    |___ |___ |___ ___]    |___ | \| |__] | | \| |___  | | ||||
| |                                    ver 0.11.2 (rainbows) | | ||||
| |                            <gan jue; to feel> ver 0.12.0 | | ||||
| |__________________________________________________________| | ||||
| '''.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 | ||||
| 
 | ||||
| @ -153,5 +250,46 @@ version 0.9.3 features: | ||||
|       non-public on posting; this option only really makes sense if you're | ||||
|       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; | ||||
| } | ||||
| 
 | ||||
| .entry p.permalink { | ||||
|   font-size: .6em; | ||||
|   font-color: #808080; | ||||
|   text-align: right; | ||||
| } | ||||
| 
 | ||||
| .entry h5 { | ||||
|   text-align: right; | ||||
|   margin-top: .2em; | ||||
|  | ||||
							
								
								
									
										155
									
								
								ttbp/core.py
									
									
									
									
									
								
							
							
						
						
									
										155
									
								
								ttbp/core.py
									
									
									
									
									
								
							| @ -41,6 +41,8 @@ import json | ||||
| 
 | ||||
| from . import chatter | ||||
| from . import config | ||||
| from . import gopher | ||||
| from . import util | ||||
| 
 | ||||
| FEED = os.path.join("/home", "endorphant", "public_html", "ttbp", "index.html") | ||||
| SETTINGS = {} | ||||
| @ -75,19 +77,16 @@ def reload_ttbprc(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 = [] | ||||
|     for filename in os.listdir(config.USER_DATA): | ||||
|     for filename in os.listdir(feelsdir): | ||||
|         if nopub(filename): | ||||
|             link = os.path.join(config.WWW, | ||||
|                                 os.path.splitext( | ||||
|                                     os.path.basename(filename))[0]+".html") | ||||
|             if os.path.exists(link): | ||||
|                 subprocess.call(["rm", link]) | ||||
|             continue | ||||
|         filename = os.path.join(config.USER_DATA, filename) | ||||
|             unpublish_feel(filename) | ||||
|         else: | ||||
|             filename = os.path.join(feelsdir, filename) | ||||
|             if os.path.isfile(filename) and valid(filename): | ||||
|                 files.append(filename) | ||||
| 
 | ||||
| @ -96,19 +95,24 @@ def get_files(): | ||||
| 
 | ||||
|     return files | ||||
| 
 | ||||
| 
 | ||||
| def load_files(): | ||||
| def load_files(feelsdir=config.MAIN_FEELS): | ||||
|     ''' | ||||
|     file loader | ||||
| 
 | ||||
|     * 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 | ||||
| 
 | ||||
|     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(): | ||||
|     """Load a list of the user's nopub entries. | ||||
| @ -127,7 +131,7 @@ def load_nopubs(): | ||||
| 
 | ||||
| ## html outputting | ||||
| 
 | ||||
| def write(outurl="default.html"): | ||||
| def write_html(outurl="default.html"): | ||||
|     ''' | ||||
|     main page renderer | ||||
| 
 | ||||
| @ -167,7 +171,7 @@ def write_page(filename): | ||||
|     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.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 | ||||
|     ''' | ||||
| 
 | ||||
|     date = parse_date(filename) | ||||
|     date = util.parse_date(filename) | ||||
| 
 | ||||
|     entry = [ | ||||
|         "\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 = [] | ||||
|     rawfile = open(os.path.join(config.USER_DATA, filename), "r") | ||||
|     rawfile = open(os.path.join(config.MAIN_FEELS, filename), "r") | ||||
| 
 | ||||
|     for line in rawfile: | ||||
|         raw.append(line) | ||||
| @ -221,7 +225,7 @@ def write_entry(filename): | ||||
|         #    entry.append("</p>\n\t\t\t<p>") | ||||
| 
 | ||||
|     #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") | ||||
| 
 | ||||
|     return entry | ||||
| @ -316,7 +320,7 @@ def meta(entries = FILES): | ||||
|       except subprocess.CalledProcessError: | ||||
|         wc = "???" | ||||
|       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] | ||||
| 
 | ||||
|       meta.append([filename, mtime, wc, timestamp, date, author]) | ||||
| @ -345,23 +349,6 @@ def valid(filename): | ||||
| 
 | ||||
|     return True | ||||
| 
 | ||||
| def parse_date(file): | ||||
|     ''' | ||||
|     parses date out of pre-validated filename | ||||
| 
 | ||||
|     * assumes a filename of YYYYMMDD.txt | ||||
|     * returns a list: | ||||
|       [0] 'YYYY' | ||||
|       [1] 'MM' | ||||
|       [2] 'DD' | ||||
|     ''' | ||||
| 
 | ||||
|     rawdate = os.path.splitext(os.path.basename(file))[0] | ||||
| 
 | ||||
|     date = [rawdate[0:4], rawdate[4:6], rawdate[6:]] | ||||
| 
 | ||||
|     return date | ||||
| 
 | ||||
| def find_ttbps(): | ||||
|     ''' | ||||
|     returns a list of users with a ttbp by checking for a valid ttbprc | ||||
| @ -457,12 +444,7 @@ def toggle_nopub(filename): | ||||
|         NOPUBS.remove(filename) | ||||
|     else: | ||||
|         NOPUBS.append(filename) | ||||
|         live_html = os.path.join(config.WWW, filename.split(".")[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]) | ||||
|         unpublish_feel(filename) | ||||
| 
 | ||||
|     nopub_file = open(config.NOPUB, 'w') | ||||
|     nopub_file.write("""\ | ||||
| @ -478,6 +460,93 @@ def toggle_nopub(filename): | ||||
| 
 | ||||
|     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 | ||||
| 
 | ||||
| from . import util | ||||
| from .core import parse_date | ||||
| from . import config | ||||
| #from .core import parse_date | ||||
| 
 | ||||
| GOPHER_PROMPT = """ | ||||
| 
 | ||||
| @ -73,7 +74,7 @@ def publish_gopher(gopher_path, entry_filenames): | ||||
|             if not os.path.exists(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( | ||||
|                 file_label=label, | ||||
|                 filename=filename)) | ||||
| @ -107,3 +108,11 @@ def setup_gopher(gopher_path): | ||||
|         os.makedirs(gopher_entries) | ||||
| 
 | ||||
|     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 | ||||
| 
 | ||||
| import os | ||||
| import sys | ||||
| import tempfile | ||||
| import subprocess | ||||
| import time | ||||
| @ -50,7 +51,7 @@ from . import chatter | ||||
| from . import gopher | ||||
| from . import util | ||||
| 
 | ||||
| __version__ = "0.11.2" | ||||
| __version__ = "0.12.0" | ||||
| __author__ = "endorphant <endorphant@tilde.town)" | ||||
| 
 | ||||
| p = inflect.engine() | ||||
| @ -73,6 +74,7 @@ DEFAULT_SETTINGS = { | ||||
|         "gopher": False, | ||||
|         "publishing": False, | ||||
|         "rainbows": False, | ||||
|         "post as nopub": False, | ||||
|     } | ||||
| 
 | ||||
| ## user globals | ||||
| @ -81,7 +83,8 @@ SETTINGS = { | ||||
|         "publish dir": None, | ||||
|         "gopher": False, | ||||
|         "publishing": False, | ||||
|         "rainbows": False | ||||
|         "rainbows": False, | ||||
|         "post as nopub": False, | ||||
|         } | ||||
| 
 | ||||
| ## ttbp specific utilities | ||||
| @ -247,10 +250,7 @@ def init(): | ||||
|     """ | ||||
| 
 | ||||
|     try: | ||||
|         input(""" | ||||
| i don't recognize you, stranger. let's make friends. | ||||
| 
 | ||||
| press <enter> to begin, or <ctrl-c> to get out of here.""") | ||||
|         input(config.intro_prompt) | ||||
|     except KeyboardInterrupt: | ||||
|         print("\n\nthanks for checking in! i'll always be here.\n\n") | ||||
|         quit() | ||||
| @ -259,7 +259,7 @@ press <enter> to begin, or <ctrl-c> to get out of here.""") | ||||
| 
 | ||||
|     time.sleep(1) | ||||
|     print("...") | ||||
|     time.sleep(1) | ||||
|     time.sleep(.5) | ||||
| 
 | ||||
|     ## record user in source list | ||||
|     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()) | ||||
|     subprocess.call(["mkdir", config.PATH]) | ||||
|     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") | ||||
|     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) | ||||
| 
 | ||||
|     ## run user-interactive setup and load core engine | ||||
|     time.sleep(1) | ||||
|     time.sleep(0.5) | ||||
|     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!!") | ||||
|     setup() | ||||
|     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 "" | ||||
| 
 | ||||
| def gen_header(): | ||||
| @ -406,7 +414,7 @@ def setup_repair(): | ||||
|     save_settings() | ||||
| 
 | ||||
|     print("...") | ||||
|     time.sleep(1) | ||||
|     time.sleep(0.5) | ||||
|     input("\nyou're all good to go, "+chatter.say("friend")+"! hit <enter> to continue.\n\n") | ||||
| 
 | ||||
| def setup(): | ||||
| @ -436,6 +444,8 @@ def setup(): | ||||
|         redraw(EJECT) | ||||
|         return SETTINGS | ||||
| 
 | ||||
|     if choice is not "": | ||||
| 
 | ||||
|         if choice in QUITS: | ||||
|             redraw() | ||||
|             return SETTINGS | ||||
| @ -498,6 +508,10 @@ def setup(): | ||||
| 
 | ||||
|         return SETTINGS | ||||
| 
 | ||||
|     else: | ||||
|         redraw("now changing your settings. press <ctrl-c> if you didn't mean to do this.") | ||||
|         return setup() | ||||
| 
 | ||||
| def save_settings(): | ||||
|     """ | ||||
|     Save current settings. | ||||
| @ -516,7 +530,7 @@ def main_menu(): | ||||
| 
 | ||||
|     menuOptions = [ | ||||
|             "record your feels", | ||||
|             "review your feels", | ||||
|             "manage your feels", | ||||
|             "check out your neighbors", | ||||
|             "browse global feels", | ||||
|             "scribble some graffiti", | ||||
| @ -537,18 +551,13 @@ def main_menu(): | ||||
|     if choice == '0': | ||||
|         redraw() | ||||
|         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() | ||||
|     elif choice == '1': | ||||
|         if core.publishing(): | ||||
|             intro = "here are some options for reviewing your feels:" | ||||
|         intro = "here are some options for managing your feels:" | ||||
|         redraw(intro) | ||||
|         review_menu(intro) | ||||
|         core.load_files() | ||||
|             core.write("index.html") | ||||
|         else: | ||||
|             redraw("your recorded feels, listed by date:") | ||||
|             view_feels(config.USER) | ||||
|     elif choice == '2': | ||||
|         users = core.find_ttbps() | ||||
|         prompt = "the following {usercount} {are} recording feels on ttbp:".format( | ||||
| @ -571,7 +580,7 @@ def main_menu(): | ||||
|         redraw() | ||||
|         show_credits() | ||||
|     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() | ||||
|     elif choice in QUITS: | ||||
|         return stop() | ||||
| @ -614,26 +623,72 @@ def review_menu(intro=""): | ||||
| 
 | ||||
|     menuOptions = [ | ||||
|             "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)) | ||||
| 
 | ||||
|     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 == 0: | ||||
|             if hasfeels: | ||||
|                 redraw("your recorded feels, listed by date:") | ||||
|                 view_feels(config.USER) | ||||
|             else: | ||||
|                 top = nofeels | ||||
|         elif choice == 1: | ||||
|             if hasfeels: | ||||
|                 redraw("publishing status of your feels:") | ||||
|                 list_nopubs(config.USER) | ||||
|             else: | ||||
|                 top = nofeels | ||||
|         elif choice == 2: | ||||
|             if hasfeels: | ||||
|                 redraw("FEELS BACKUP") | ||||
|                 backup_feels() | ||||
|             else: | ||||
|                 top = nofeels | ||||
|         elif choice == 3: | ||||
|             redraw("loading feels backup") | ||||
|             load_backup() | ||||
|         elif choice == 4: | ||||
|             if hasfeels: | ||||
|                 redraw("burying feels") | ||||
|                 bury_feels() | ||||
|             else: | ||||
|                 top = nofeels | ||||
|         elif choice == 5: | ||||
|             if hasfeels: | ||||
|                 redraw("deleting feels") | ||||
|                 delete_feels() | ||||
|             else: | ||||
|                 top = nofeels | ||||
|         elif choice == 6: | ||||
|             if hasfeels: | ||||
|                 redraw("!!!PURGING ALL FEELS!!!") | ||||
|                 purge_feels() | ||||
|             else: | ||||
|                 top = nofeels | ||||
|         elif choice == 7: | ||||
|             redraw("!!! WIPING FEELS ACCOUNT !!!") | ||||
|             wipe_account() | ||||
|     else: | ||||
|         redraw() | ||||
|         return | ||||
| 
 | ||||
|     redraw(intro) | ||||
|     return review_menu() | ||||
|     redraw(top+intro) | ||||
|     return review_menu(intro) | ||||
| 
 | ||||
| def view_neighbors(users, prompt): | ||||
|     ''' | ||||
| @ -694,7 +749,7 @@ def view_neighbors(users, prompt): | ||||
|         sortedUsers.append(user[0]) | ||||
|         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: | ||||
|         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 | ||||
|     date order; allows selection of one feel to read. | ||||
| 
 | ||||
|     ''' | ||||
| 
 | ||||
|     metas, owner = generate_feels_list(townie) | ||||
| @ -733,7 +787,7 @@ def generate_feels_list(user): | ||||
|     showpub = False | ||||
| 
 | ||||
|     if user == config.USER: | ||||
|         entryDir = config.USER_DATA | ||||
|         entryDir = config.MAIN_FEELS | ||||
|         owner = "your" | ||||
|         if core.publishing(): | ||||
|             showpub = True | ||||
| @ -749,29 +803,320 @@ def generate_feels_list(user): | ||||
| 
 | ||||
|     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(): | ||||
|     ''' | ||||
|     prints author acknowledgements and commentary | ||||
|     ''' | ||||
| 
 | ||||
|     print(""" | ||||
| 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.\ | ||||
|         """) | ||||
| 
 | ||||
|     print(config.credits) | ||||
|     input("\n\npress <enter> to go back home.\n\n") | ||||
|     redraw() | ||||
| 
 | ||||
| @ -779,24 +1124,12 @@ thanks to everyone who reads, listens, writes, and feels.\ | ||||
| 
 | ||||
| ## 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 | ||||
|     ''' | ||||
| 
 | ||||
|     entered = input(""" | ||||
| 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"))) | ||||
|     entered = input(config.recording) | ||||
| 
 | ||||
|     if entered: | ||||
|         entryFile = open(entry, "a") | ||||
| @ -806,21 +1139,23 @@ editor. | ||||
| 
 | ||||
|     left = "" | ||||
| 
 | ||||
|     core.load_files() | ||||
| 
 | ||||
|     if SETTINGS.get("post as nopub"): | ||||
|         core.toggle_nopub(os.path.basename(entry)) | ||||
|     else: | ||||
|         if core.publishing(): | ||||
|             core.write("index.html") | ||||
|             core.write_html("index.html") | ||||
|             left = "posted to {url}/index.html\n\n> ".format( | ||||
|                 url="/".join( | ||||
|                     [config.LIVE+config.USER, | ||||
|                         str(SETTINGS.get("publish dir"))])) | ||||
| 
 | ||||
|         if SETTINGS.get('gopher'): | ||||
|             gopher.publish_gopher('feels', core.get_files()) | ||||
|             left += " also posted to your ~/public_gopher!\n" | ||||
|             gopher.publish_gopher('feels', core.FILES) | ||||
|             left += "also posted to your ~/public_gopher!\n\n> " | ||||
| 
 | ||||
|     core.load_files() | ||||
|     #core.load_files() | ||||
|     redraw(left + "thanks for sharing your feels!") | ||||
| 
 | ||||
|     return | ||||
| @ -841,6 +1176,14 @@ def set_nopubs(metas, user, prompt): | ||||
|     """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 = [] | ||||
|     for entry in metas: | ||||
|         pub = "" | ||||
| @ -848,14 +1191,13 @@ def set_nopubs(metas, user, prompt): | ||||
|             pub = "(nopub)" | ||||
|         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: | ||||
|         target = os.path.basename(metas[choice][0]) | ||||
|         action = core.toggle_nopub(target) | ||||
|         redraw(prompt) | ||||
| 
 | ||||
|         core.write("index.html") | ||||
|         if SETTINGS["gopher"]: | ||||
|             gopher.publish_gopher('feels', core.get_files()) | ||||
| 
 | ||||
| @ -1107,14 +1449,14 @@ def select_publish_dir(): | ||||
| 
 | ||||
|     publishDir = os.path.join(config.PUBLIC, choice) | ||||
|     while os.path.exists(publishDir): | ||||
|         second = input("\n"+publishDir+"""\ | ||||
|  already exists! | ||||
|         second = input(""" | ||||
| {pDir} already exists! | ||||
| 
 | ||||
| setting this as your publishing directory means this program may | ||||
| delete or overwrite file there! | ||||
| 
 | ||||
| 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 == "": | ||||
|             break | ||||
| @ -1159,11 +1501,14 @@ def unpublish(): | ||||
| 
 | ||||
|     if 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"): | ||||
|         SETTINGS.update({"gopher": False}) | ||||
|         subprocess.call(["rm", config.GOPHER_PATH]) | ||||
|         gopher.unpublish() | ||||
| 
 | ||||
| def update_publishing(): | ||||
|     ''' | ||||
| @ -1180,14 +1525,13 @@ def update_publishing(): | ||||
|             subprocess.call(["rm", os.path.join(config.PUBLIC, oldDir)]) | ||||
|         make_publish_dir(newDir) | ||||
|         core.load_files() | ||||
|         core.write("index.html") | ||||
|         #core.write_html("index.html") | ||||
|     else: | ||||
|         unpublish() | ||||
|         SETTINGS.update({"publish dir": None}) | ||||
| 
 | ||||
|     core.load(SETTINGS) | ||||
| 
 | ||||
| def make_publish_dir(dir): | ||||
| def make_publish_dir(publish_dir): | ||||
|     ''' | ||||
|     setup helper to create publishing directory | ||||
|     ''' | ||||
| @ -1200,13 +1544,18 @@ def make_publish_dir(dir): | ||||
|         index.write("<h1>ttbp blog placeholder</h1>") | ||||
|         index.close() | ||||
| 
 | ||||
|     publishDir = os.path.join(config.PUBLIC, dir) | ||||
|     if os.path.exists(publishDir): | ||||
|         subprocess.call(["rm", publishDir]) | ||||
|     if core.publishing(): | ||||
|         live = os.path.join(config.PUBLIC, publish_dir) | ||||
|         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(): | ||||
|     ''' | ||||
| @ -1255,7 +1604,7 @@ def update_user_version(): | ||||
| 
 | ||||
|     time.sleep(1) | ||||
|     print("...") | ||||
|     time.sleep(1) | ||||
|     time.sleep(0.5) | ||||
| 
 | ||||
|     userVersion = "" | ||||
|     (x, y, z) = [0, 0, 0] | ||||
| @ -1284,7 +1633,7 @@ def update_user_version(): | ||||
| 
 | ||||
|             # repopulate html files | ||||
|             core.load_files() | ||||
|             core.write("index.html") | ||||
|             #core.write_html("index.html") | ||||
| 
 | ||||
|         # add publishing setting | ||||
|         print("\nnew feature!\n") | ||||
| @ -1335,6 +1684,19 @@ def update_user_version(): | ||||
|             SETTINGS.update({"post as nopub": False}) | ||||
|             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(""" | ||||
| you're all good to go, """+chatter.say("friend")+"""! please contact ~endorphant if | ||||
| 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 | ||||
|         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 = "" | ||||
| 
 | ||||
|     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 time | ||||
| from six.moves import input | ||||
| import os | ||||
| 
 | ||||
| import colorama | ||||
| import inflect | ||||
| 
 | ||||
| ## misc globals | ||||
| BACKS = ['back', 'b', 'q'] | ||||
| BACKS = ['back', 'b', 'q', '<q>'] | ||||
| NAVS = ['u', 'd'] | ||||
| 
 | ||||
| ## color stuff | ||||
| @ -214,3 +215,21 @@ def input_yn(query): | ||||
|         ans = input("'y' or 'n' please: ") | ||||
| 
 | ||||
|     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