comments are back

This commit is contained in:
Peter Molnar 2017-06-03 11:07:03 +00:00
parent 18521317d3
commit ba81e496c1

209
nasg.py
View file

@ -15,7 +15,6 @@ import hashlib
import math import math
import asyncio import asyncio
import csv import csv
import operator
import getpass import getpass
import magic import magic
@ -36,8 +35,6 @@ from webmentiontools.send import WebmentionSend
from bleach import clean from bleach import clean
from emoji import UNICODE_EMOJI from emoji import UNICODE_EMOJI
from pprint import pprint
def splitpath(path): def splitpath(path):
parts = [] parts = []
(path, tail) = os.path.split(path) (path, tail) = os.path.split(path)
@ -336,6 +333,9 @@ class Comment(object):
@property @property
def reacji(self): def reacji(self):
if hasattr(self, '_reacji'):
return self._reacji
t = self.meta.get('type', 'webmention') t = self.meta.get('type', 'webmention')
typemap = { typemap = {
'like-of': '👍', 'like-of': '👍',
@ -343,35 +343,62 @@ class Comment(object):
'favorite': '', 'favorite': '',
} }
self._reacji = ''
if t in typemap.keys(): if t in typemap.keys():
return typemap[t] self._reacji = typemap[t]
else:
maybe = clean(self.content).strip()
if maybe in UNICODE_EMOJI:
self._reacji = maybe
maybe = clean(self.content).strip() return self._reacji
if maybe in UNICODE_EMOJI:
return maybe
return '' @property
def h(self):
if hasattr(self, '_h'):
return self._h
record = {
'mtime': self.mtime,
'source': self.source,
'target': self.target
}
h = json.dumps(record, sort_keys=True)
self._h = hashlib.sha1(h.encode('utf-8')).hexdigest()
return self._h
@property @property
def html(self): def html(self):
return shared.Pandoc().convert(self.content) if hasattr(self, '_html'):
return self._html
self._html = shared.Pandoc().convert(self.content)
return self._html
@property @property
def tmplvars(self): def tmplvars(self):
return { if hasattr(self, '_tmplvars'):
return self._tmplvars
self._tmplvars = {
'published': self.published.datetime, 'published': self.published.datetime,
'author': dict(self.meta.get('author', {})), 'author': dict(self.meta.get('author', {})),
'content': self.content, 'content': self.content,
'html': self.html, 'html': self.html,
'source': self.meta.get('source', ''), 'source': self.source,
'target': self.meta.get('target', ''), 'target': self.target,
'type': self.meta.get('type', 'webmention'), 'type': self.meta.get('type', 'webmention'),
'reacji': self.reacji 'reacji': self.reacji,
'id': self.h
} }
return self._tmplvars
@property @property
def published(self): def published(self):
return arrow.get(self.meta.get('date', self.mtime)) if hasattr(self, '_published'):
return self._published
self._published = arrow.get(self.meta.get('date', self.mtime))
return self._published
@property @property
def pubtime(self): def pubtime(self):
@ -379,17 +406,23 @@ class Comment(object):
@property @property
def source(self): def source(self):
s = self.meta.get('source') if hasattr(self, '_source'):
for d in shared.config.get('site', 'domains').split(' '): return self._source
s = self.meta.get('source', '')
domains = shared.config.get('site', 'domains').split(' ')
self._source = s
for d in domains:
if d in s: if d in s:
return '' self._source = ''
return s return self._source
@property @property
def target(self): def target(self):
if hasattr(self, '_target'):
return self._target
t = self.meta.get('target', shared.config.get('site', 'url')) t = self.meta.get('target', shared.config.get('site', 'url'))
t = '{p.path}'.format(p=urllib.parse.urlparse(t)).strip('/') self._target = '{p.path}'.format(p=urllib.parse.urlparse(t)).strip('/')
return t return self._target
class Comments(object): class Comments(object):
@ -552,47 +585,57 @@ class WebImage(object):
@property @property
def rssenclosure(self): def rssenclosure(self):
""" Returns the largest available image for RSS to add as attachment """ """ Returns the largest available image for RSS to add as attachment """
if hasattr(self, '_rssenclosure'):
return self._rssenclosure
target = self.sizes[-1][1] target = self.sizes[-1][1]
return { self._rssenclosure = {
'mime': magic.Magic(mime=True).from_file(target['fpath']), 'mime': magic.Magic(mime=True).from_file(target['fpath']),
'url': target['url'], 'url': target['url'],
'bytes': os.path.getsize(target['fpath']) 'bytes': os.path.getsize(target['fpath'])
} }
return self._rssenclosure
@property @property
def is_photo(self): def is_photo(self):
""" Match image meta against config artist regex to see if the file is if hasattr(self, '_is_photo'):
a photo or just a regular image """ return self._is_photo
pattern = shared.config.get('photo', 'regex', fallback=None)
if not pattern or not isinstance(pattern, str): self._is_photo = False
return False #if not pattern or not isinstance(pattern, str):
pattern = re.compile(pattern) # return False
pattern = re.compile(shared.config.get('photo', 'regex'))
cpr = self.meta.get('Copyright', '') cpr = self.meta.get('Copyright', '')
art = self.meta.get('Artist', '') art = self.meta.get('Artist', '')
if not cpr and not art: if not cpr and not art:
return False return False
if pattern.search(cpr) \ if cpr and art:
or pattern.search(art): if pattern.search(cpr) or pattern.search(art):
return True self._is_photo = True
return False return self._is_photo
@property @property
def is_downsizeable(self): def is_downsizeable(self):
if hasattr(self, '_is_downsizeable'):
return self._is_downsizeable
self._is_downsizeable = False
""" Check if the image is large enough and jpeg or png in order to """ Check if the image is large enough and jpeg or png in order to
downsize it """ downsize it """
fb = self.sizes[-1][0] fb = self.sizes[-1][0]
ftype = self.meta.get('FileType', None) ftype = self.meta.get('FileType', None)
if not ftype: if not ftype:
return False return self._is_downsizeable
if ftype.lower() == 'jpeg' or ftype.lower() == 'png': if ftype.lower() == 'jpeg' or ftype.lower() == 'png':
width = int(self.meta.get('ImageWidth', 0)) width = int(self.meta.get('ImageWidth', 0))
height = int(self.meta.get('ImageHeight', 0)) height = int(self.meta.get('ImageHeight', 0))
if width > fb or height > fb: if width > fb or height > fb:
return True self._is_downsizeable = True
return False
return self._is_downsizeable
def _copy(self): def _copy(self):
target = os.path.join( target = os.path.join(
@ -723,7 +766,10 @@ class Taxonomy(BaseIter):
@property @property
def pages(self): def pages(self):
return math.ceil(len(self.data) / shared.config.getint('common', 'pagination')) if hasattr(self, '_pages'):
return self._pages
self._pages = math.ceil(len(self.data) / shared.config.getint('common', 'pagination'))
return self._pages
def __repr__(self): def __repr__(self):
return "taxonomy %s with %d items" % (self.taxonomy, len(self.data)) return "taxonomy %s with %d items" % (self.taxonomy, len(self.data))
@ -845,6 +891,39 @@ class Taxonomy(BaseIter):
html.write(r) html.write(r)
os.utime(target, (self.mtime, self.mtime)) os.utime(target, (self.mtime, self.mtime))
# ---
# this is a joke
# see http://indieweb.org/YAMLFeed
# don't do YAMLFeeds.
if 1 == page:
yml = {
'site': {
'author': renderer.sitevars['author'],
'url': renderer.sitevars['url'],
'title': renderer.sitevars['title'],
},
'items': [],
}
for p in posttmpls:
yml['items'].append({
'title': p['title'],
'url': "%s/%s/" % ( renderer.sitevars['url'], p['slug']),
'content': p['content'],
'summary': p['summary'],
'published': p['published'],
'updated': p['updated'],
})
target = os.path.join(self.feedp, 'index.yml')
logging.info("rendering YAML feed to %s", target)
fm = frontmatter.loads('')
fm.metadata = yml
with open(target, "wt") as html:
html.write(frontmatter.dumps(fm))
os.utime(target, (self.mtime, self.mtime))
# ---
class Content(BaseIter): class Content(BaseIter):
def __init__(self, images, comments, extensions=['md']): def __init__(self, images, comments, extensions=['md']):
super(Content, self).__init__() super(Content, self).__init__()
@ -983,18 +1062,6 @@ class Singular(object):
self.photo self.photo
) )
#@property
#def isrepost(self):
#isrepost = False
#if len(self.reactions.keys()):
#isrepost = list(self.reactions.keys())[0]
#if isrepost:
#if len(self.reactions[isrepost]) == 1:
#linkto = self.reactions[isrepost][0]
def __filter_images(self): def __filter_images(self):
linkto = False linkto = False
isrepost = None isrepost = None
@ -1072,6 +1139,8 @@ class Singular(object):
@property @property
def reactions(self): def reactions(self):
if hasattr(self, '_reactions'):
return self._reactions
# getting rid of '-' to avoid css trouble and similar # getting rid of '-' to avoid css trouble and similar
convert = { convert = {
'bookmark-of': 'bookmark', 'bookmark-of': 'bookmark',
@ -1088,10 +1157,14 @@ class Singular(object):
x = [x] x = [x]
reactions[v] = x reactions[v] = x
return reactions self._reactions = reactions
return self._reactions
@property @property
def urls(self): def urls(self):
if hasattr(self, '_urls'):
return self._urls
urls = shared.URLREGEX.findall(self.content) urls = shared.URLREGEX.findall(self.content)
for reactionurls in self.reactions.values(): for reactionurls in self.reactions.values():
@ -1106,10 +1179,14 @@ class Singular(object):
continue continue
r.append(link) r.append(link)
return r self._urls = r
return self._urls
@property @property
def lang(self): def lang(self):
if hasattr(self, '_lang'):
return self._lang
lang = 'en' lang = 'en'
try: try:
lang = langdetect.detect("\n".join([ lang = langdetect.detect("\n".join([
@ -1118,7 +1195,8 @@ class Singular(object):
])) ]))
except: except:
pass pass
return lang self._lang = lang
return self._lang
@property @property
def tags(self): def tags(self):
@ -1182,11 +1260,16 @@ class Singular(object):
@property @property
def title(self): def title(self):
if hasattr(self, '_title'):
return self._title
self._title = ''
for maybe in ['title', 'bookmark-of', 'in-reply-to', 'repost-of']: for maybe in ['title', 'bookmark-of', 'in-reply-to', 'repost-of']:
maybe = self.meta.get(maybe, False) maybe = self.meta.get(maybe, False)
if maybe: if maybe:
return maybe self._title = maybe
return '' break
return self._title
@property @property
def url(self): def url(self):
@ -1240,6 +1323,9 @@ class Singular(object):
if not self.isphoto: if not self.isphoto:
return None return None
if hasattr(self, '_exif'):
return self._exif
exif = {} exif = {}
mapping = { mapping = {
'camera': [ 'camera': [
@ -1286,7 +1372,8 @@ class Singular(object):
exif[ekey] = maybe exif[ekey] = maybe
break break
return exif self._exif = exif
return self._exif
@property @property
def rssenclosure(self): def rssenclosure(self):
@ -1343,10 +1430,18 @@ class Singular(object):
) )
async def render(self, renderer): async def render(self, renderer):
# this is only when I want salmentions and I want to include all of the comments as well
# otherwise it affects both webmentions sending and search indexing
#if len(self.comments):
#lctime = self.comments[0].mtime
#if lctime > self.mtime:
#self.mtime = lctime
mtime = self.mtime
if len(self.comments): if len(self.comments):
lctime = self.comments[0].mtime lctime = self.comments[0].mtime
if lctime > self.mtime: if lctime > self.mtime:
self.mtime = lctime mtime = lctime
logging.info("rendering and saving %s", self.fname) logging.info("rendering and saving %s", self.fname)
targetdir = os.path.abspath(os.path.join( targetdir = os.path.abspath(os.path.join(
@ -1357,8 +1452,8 @@ class Singular(object):
if not shared.config.getboolean('params', 'force') and os.path.isfile(target): if not shared.config.getboolean('params', 'force') and os.path.isfile(target):
ttime = int(os.path.getmtime(target)) ttime = int(os.path.getmtime(target))
logging.debug('ttime is %d mtime is %d', ttime, self.mtime) logging.debug('ttime is %d mtime is %d', ttime, mtime)
if ttime == self.mtime: if ttime == mtime:
logging.debug('%s exists and up-to-date (lastmod: %d)', target, ttime) logging.debug('%s exists and up-to-date (lastmod: %d)', target, ttime)
return return
@ -1375,7 +1470,7 @@ class Singular(object):
logging.debug('writing %s', target) logging.debug('writing %s', target)
html.write(r) html.write(r)
html.close() html.close()
os.utime(target, (self.mtime, self.mtime)) os.utime(target, (mtime, mtime))
async def ping(self, pinger): async def ping(self, pinger):