all repos — nasg @ de269ef39efa0a11f7fed59e7526f950efcfec30

- moved Tips from footer to bottom of each singular with an "encourage creation" header
- google vision api binding for images (not in use yet)
- konami code css preparations
- experimental gallery css
- minor code cleanups
Peter Molnar hello@petermolnar.eu
Sat, 01 Dec 2018 10:43:13 +0000
commit

de269ef39efa0a11f7fed59e7526f950efcfec30

parent

9af56f89e7a9968eefaa2b64c8157b743d6efe6b

M exiftool.pyexiftool.py

@@ -2,22 +2,28 @@ import re

import subprocess import json import os +import keys +import requests + +from pprint import pprint EXIFDATE = re.compile( r'^(?P<year>[0-9]{4}):(?P<month>[0-9]{2}):(?P<day>[0-9]{2})\s+' r'(?P<time>[0-9]{2}:[0-9]{2}:[0-9]{2})$' ) -class Exif(dict): +class CachedMeta(dict): def __init__(self, fpath): self.fpath = fpath - self._read() @property def cfile(self): return os.path.join( os.path.dirname(self.fpath), - ".%s.json" % (os.path.basename(self.fpath)) + ".%s.%s.json" % ( + self.__class__.__name__, + os.path.basename(self.fpath) + ) ) @property

@@ -31,7 +37,7 @@ return False

def _read(self): if not self._is_cached: - self._call_exiftool() + self._call_tool() self._cache_update() else: self._cache_read()

@@ -44,9 +50,65 @@ def _cache_read(self):

with open(self.cfile, 'rt') as f: data = json.loads(f.read()) for k, v in data.items(): - self[k] = self.exifdate2rfc(v) + self[k] = v + +class GoogleVision(CachedMeta): + def __init__(self, fpath, imgurl): + self.fpath = fpath + self.imgurl = imgurl + self._read() - def _call_exiftool(self): + @property + def cntr(self): + curr = 0 + if os.path.exists('/tmp/visionapicallcounter'): + with open('/tmp/visionapicallcounter', 'rt') as f: + curr = int(f.read()) + curr = curr + 1 + with open('/tmp/visionapicallcounter', 'wt') as f: + f.write("%d" % curr) + return curr + + def _call_tool(self): + if (self.cntr >= 500 ): + raise ValueError('already at 500 requests!') + + params = { + "requests": [ + { + "image": { + "source": { + "imageUri": self.imgurl, + } + }, + "features": [ + { + "type": "LANDMARK_DETECTION", + }, + { + "type": "LABEL_DETECTION", + }, + ] + } + ] + } + + url = "https://vision.googleapis.com/v1/images:annotate?key=%s" % (keys.gcloud.get('key')) + r = requests.post(url, json=params) + try: + resp = r.json() + resp = resp['responses'][0] + for k, v in resp.items(): + self[k] = v + except Exception as e: + logging.error('failed to call Google Vision API on: %s, reason: %s', self.fpath, e) + +class Exif(CachedMeta): + def __init__(self, fpath): + self.fpath = fpath + self._read() + + def _call_tool(self): """ Why like this: the # on some of the params forces exiftool to display values like decimals, so the latitude / longitude params
M nasg.pynasg.py

@@ -31,7 +31,7 @@ from emoji import UNICODE_EMOJI

from slugify import slugify import requests from pandoc import Pandoc -from exiftool import Exif +from exiftool import Exif, GoogleVision import settings import keys

@@ -716,6 +716,10 @@ if len(self.mdimg.css):

return self.mdimg.match tmpl = J2.get_template("%s.j2.html" % (self.__class__.__name__)) return tmpl.render(self.tmplvars) + + @cached_property + def vision(self): + return GoogleVision(self.fpath, self.src) @cached_property def meta(self):

@@ -1737,12 +1741,12 @@ def make():

start = int(round(time.time() * 1000)) last = 0 - try: - makecomments() - except Exception as e: - logger.error('failed to make comments: %s', e) - - makeposts(); + if not settings.args.get('nosync'): + try: + makecomments() + except Exception as e: + logger.error('failed to make comments: %s', e) + makeposts(); content = settings.paths.get('content') worker = AsyncWorker()

@@ -1817,8 +1821,8 @@ # copy static

staticfiles = [] staticpaths = [ os.path.join(content, '*.*'), - os.path.join(settings.paths.get('tmpl'), '*.css'), - os.path.join(settings.paths.get('tmpl'), '*.js'), + #os.path.join(settings.paths.get('tmpl'), '*.css'), + #os.path.join(settings.paths.get('tmpl'), '*.js'), ] for p in staticpaths: staticfiles = staticfiles + glob.glob(p)
M pandoc.pypandoc.py

@@ -3,10 +3,6 @@ import logging

class Pandoc(str): def __new__(cls, text): - # TODO: cache? - # import hashlib - # print(hashlib.md5("whatever your string is".encode('utf-8')).hexdigest()) - """ Pandoc command line call with piped in- and output """ cmd = ( 'pandoc',
M templates/Category.j2.htmltemplates/Category.j2.html

@@ -9,9 +9,12 @@ {% block title %}{{ category.title }}{% endblock %}

{% block meta %} <link rel="alternate" type="application/rss+xml" title="{{ category.title }} RSS feed" href="{{ category.feed }}" /> <link rel="alternate" type="application/atom+xml" title="{{ category.title }} ATOM feed" href="{{ category.feed }}atom.xml" /> + <style id="css_gallery" media="speech"> + {% include 'style-gallery.css' %} + </style> {% endblock %} {% block content %} -<main class="content-body h-feed hfeed" property="h-feed"> +<main class="content-body h-feed hfeed {{ category.name }}" property="h-feed"> <header> <h1 class="p-name" property="p-name">{{ category.name }}</h1> </header>
M templates/base.j2.htmltemplates/base.j2.html

@@ -17,6 +17,9 @@ </style>

<style id="css_alt" media="speech"> {% include 'style-alt.css' %} </style> + <style id="css_kcl" media="speech"> + {% include 'style-kcl.css' %} + </style> <style media="print"> {% include 'style-print.css' %} </style>

@@ -72,10 +75,6 @@ <form class="theme" aria-hidden="true">

<svg width="16" height="16"> <use xlink:href="#icon-contrast"></use> </svg> - <span> - <input name="colorscheme" value="auto" id="autoscheme" type="radio"> - <label for="autoscheme">auto</label> - </span> <span> <input name="colorscheme" value="dark" id="darkscheme" type="radio"> <label for="darkscheme">dark</label>

@@ -272,6 +271,27 @@ {% endfor %}

</section> {% endif %} + <section class="encourage"> + <hr /> + <h2>Encourage creation!</h2> + <p>If this entry helped you, or you simply liked it, leave a tip.</p> + <nav> + <ul> + <li> + <a rel="payment" href="https://paypal.me/petermolnar/3GBP"> + <svg width="16" height="16"> + <use xlink:href="#icon-paypal"></use> + </svg> Paypal</a> + </li> + <li> + <a rel="payment" href="https://monzo.me/petermolnar/3"> + <svg width="16" height="16"> + <use xlink:href="#icon-monzo"></use> + </svg> Monzo (UK or Google Pay)</a> + </li> + </ul> + </nav> + </section> {% if post.replies|length %} <section class="replies">

@@ -370,12 +390,11 @@ src="{{ author.avatar }}"

alt="Photo of {{ author.name }}" itemprop="image url" /> </span> - <a class="fn p-name url u-url u-uid" property="p-name u-url u-uid" rel="me" href="{{ site.url }}/about.html"> - <span itemprop="name">{{ author.name }}</span> - </a> - <a class="u-email email" property="u-email" rel="me" href="mailto:{{ author.email }}"> - <span itemprop="email">{{ author.email }}</span> - </a> + <a class="fn p-name url u-url u-uid" property="p-name u-url u-uid" rel="me" href="{{ site.url }}"><span itemprop="name">{{ author.name }}</span></a> + <!-- + <a class="u-url" property="u-url" rel="me" href="{{ site.url }}/about.html">CV</a> + --> + <a class="u-email email" property="u-email" rel="me" href="mailto:{{ author.email }}"><span itemprop="email">{{ author.email }}</span></a> </p> <nav> <ul>

@@ -392,18 +411,6 @@ {% endfor %}

</ul> </nav> </div> - <p> - Leave a tip! - <a rel="payment" href="{{ tips.paypal }}"> - <svg width="16" height="16"> - <use xlink:href="#icon-paypal"></use> - </svg> Paypal</a> - or - <a rel="payment" href="{{ tips.monzo }}"> - <svg width="16" height="16"> - <use xlink:href="#icon-monzo"></use> - </svg> Monzo</a> (UK only). - </p> <p> <a href="https://xn--sr8hvo.ws/🇻🇮📢/previous">←</a> Member of <a href="https://xn--sr8hvo.ws">IndieWeb Webring</a>
A templates/style-gallery.css

@@ -0,0 +1,34 @@

+main.photo { + display: flex; + flex-wrap: wrap; +} + +main.photo article { + max-width: 24em; + margin: 0.6em; + display: grid; + position: relative; +} + +main.photo article figure { + margin: 0; + padding: 0; +} + +main.photo article h2 { + margin: 0; + padding: 0.6em; + background: rgba(0,0,0,0.7); + position: absolute; + top: 50%; + left: 0; + right: 0; + text-align: center; + +} + +main.photo article figcaption, +main.photo article p, +main.photo article section { + display: none; +}
A templates/style-kcl.css

@@ -0,0 +1,5 @@

+body { + font-family: serif; + background-color: #0f0; + color: #f00; +}
M templates/style.csstemplates/style.css

@@ -319,6 +319,19 @@ .theme input {

display: none; } +.encourage { + text-align: center; + padding-bottom: 2em; +} + +.encourage h2 { + color: #080; +} + +.encourage li { + margin: 0 0.6em; +} + @media all and (min-width: 58em) { body > header { text-align: unset;
M templates/themeswitcher.jstemplates/themeswitcher.js

@@ -23,28 +23,28 @@ }

function setTheme(e) { var mode = e.target.value; - if (mode == 'auto') { + var mql = window.matchMedia('(prefers-color-scheme: ' + ALT_THEME + ')'); + /* user wants == mql match => remove storage */ + if ((mode == DEFAULT_THEME && !mql.matches) || (mode == ALT_THEME && mql.matches)) { localStorage.removeItem(STORAGE_KEY); } else { localStorage.setItem(STORAGE_KEY, mode); } - var e = window.matchMedia('(prefers-color-scheme: ' + ALT_THEME + ')'); - autoTheme(e); + autoTheme(mql); } function autoTheme(e) { + var mode = DEFAULT_THEME; var current = localStorage.getItem(STORAGE_KEY); - var mode = 'auto'; - var indicate = 'auto'; if ( current != null) { - indicate = mode = current; + mode = current; } else if (e.matches) { mode = ALT_THEME; } applyTheme(mode); - indicateTheme(indicate); + indicateTheme(mode); } var mql = window.matchMedia('(prefers-color-scheme: ' + ALT_THEME + ')');

@@ -59,3 +59,21 @@ var themeforms = document.getElementsByClassName(STORAGE_KEY);

for(var i = themeforms.length; i--; ) { themeforms[i].style.display = 'inline-block'; } + +function kcl(cb) { + var input = ''; + var key = '38384040373937396665'; + document.addEventListener('keydown', function (e) { + input += ("" + e.keyCode); + if (input === key) { + return cb(); + } + if (!key.indexOf(input)) return; + input = ("" + e.keyCode); + }); +} + +kcl(function () { + var st = document.getElementById('css_kcl'); + st.setAttribute('media', 'all'); +})