diff --git a/README.md b/README.md index 538d30e..f10cb38 100644 --- a/README.md +++ b/README.md @@ -236,6 +236,9 @@ 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) +* [colorama](https://pypi.python.org/pypi/colorama) +* [feedgen](https://pypi.python.org/pypi/feedgen) +* [dateutil](https://pypi.python.org/pypi/python-dateutil) ### contributing diff --git a/setup.py b/setup.py index ee2c1d3..8e2ec14 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,9 @@ setup( 'inflect', 'mistune', 'colorama', - 'six' + 'six', + 'feedgen', + 'python-dateutil', ], include_package_data = True, entry_points = { diff --git a/ttbp/atom.py b/ttbp/atom.py new file mode 100644 index 0000000..0d542b5 --- /dev/null +++ b/ttbp/atom.py @@ -0,0 +1,96 @@ +#!/usr/bin/python + +''' +ttbp: tilde town blogging platform +(also known as the feels engine) +a console-based blogging program developed for tilde.town +copyright (c) 2016 ~endorphant (endorphant@tilde.town) + +atom.py: +Atom feed generation + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +the complete codebase is available at: +https://github.com/modgethanc/ttbp +''' +from . import config +from . import util +from feedgen.feed import FeedGenerator +import os +import mistune +import datetime +import stat +from dateutil import tz + +def publish_atom(entry_filenames, settings): + fg = FeedGenerator() + url = (config.LIVE + config.USER + '/' + + str(settings.get("publish dir"))).rstrip('/') + fg.id(url) + fg.title("{}'s feels".format(config.USER)) + fg.author(name=config.USER) + fg.link(href=url+'/', rel='alternate') + fg.link(href=url+'/atom.xml', rel='self') + fg.language('en') # TODO: feels language should be configurable + fg.updated(datetime.datetime.now(tz.tzlocal())) + + for filename in sorted(entry_filenames): + date = util.parse_date(filename) + title = "-".join(date) + name = "".join(date) + + path = os.path.join(config.MAIN_FEELS, filename) + with open(path) as f: + raw = f.read() + html = mistune.markdown(raw) + + fe = fg.add_entry(order='prepend') + fe.id(url+'/'+name) + fe.link(href=url+'/'+name+'.html', rel="alternate") + fe.title(title) + fe.author(name=config.USER) + fe.content(html, type="html") + try: # crashing because of an invalid date would be sad + year, month, day = [int(x) for x in date] + fe.published(datetime.datetime(year, month, day, + tzinfo=tz.tzlocal())) + stats = os.stat(path) + updated = datetime.datetime.fromtimestamp(stats[stat.ST_MTIME], + tz.tzlocal()) + fe.updated(updated) + except ValueError: + pass + outfile = os.path.join(config.WWW, 'atom.xml') + fg.atom_file(outfile) + +def select_atom(): + publish = util.input_yn(""" +SETTING UP ATOM + +Atom is a syndication format similar to RSS. +it is used so that people can subscribe to blogs and other news sources. + +do you want to generate an atom feed for your feels along the HTML? +this setting only has effect if publishing is enabled. + +you can change this option any time. +""") + return publish diff --git a/ttbp/core.py b/ttbp/core.py index 157017a..470c2e1 100644 --- a/ttbp/core.py +++ b/ttbp/core.py @@ -43,6 +43,7 @@ from . import chatter from . import config from . import gopher from . import util +from . import atom FEED = os.path.join("/home", "endorphant", "public_html", "ttbp", "index.html") SETTINGS = {} @@ -95,6 +96,23 @@ def get_files(feelsdir=config.MAIN_FEELS): return files +def render(files): + out = "" + if publishing(): + write_html("index.html") + out += "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', files) + out += "also posted to your ~/public_gopher!\n\n> " + if SETTINGS.get('atom'): + atom.publish_atom(files, SETTINGS) + out += "also posted to your atom feed {url}/atom.xml!\n\n> " + return out + + def load_files(feelsdir=config.MAIN_FEELS): ''' file loader @@ -108,11 +126,7 @@ def load_files(feelsdir=config.MAIN_FEELS): load_nopubs() FILES = get_files(feelsdir) - - if publishing(): - write_html("index.html") - if SETTINGS.get('gopher'): - gopher.publish_gopher('feels', FILES) + render(FILES) def load_nopubs(): """Load a list of the user's nopub entries. diff --git a/ttbp/ttbp.py b/ttbp/ttbp.py index d103c37..8ae8c28 100644 --- a/ttbp/ttbp.py +++ b/ttbp/ttbp.py @@ -50,6 +50,7 @@ from . import core from . import chatter from . import gopher from . import util +from . import atom __version__ = "0.12.2" __author__ = "endorphant to continue.\n\n".format(friend=chatter.say("friend"))) redraw() @@ -1202,16 +1213,7 @@ def write_entry(entry=os.path.join(config.MAIN_FEELS, "test.txt")): if SETTINGS.get("post as nopub"): core.toggle_nopub(os.path.basename(entry)) else: - if core.publishing(): - 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.FILES) - left += "also posted to your ~/public_gopher!\n\n> " + left = core.render(core.FILES) #core.load_files() redraw(left + "thanks for sharing your feels!")