- 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
This commit is contained in:
Peter Molnar 2018-12-01 10:43:13 +00:00
parent 9af56f89e7
commit de269ef39e
9 changed files with 191 additions and 49 deletions

View file

@ -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 @@ class Exif(dict):
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 @@ class Exif(dict):
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
def _call_exiftool(self):
class GoogleVision(CachedMeta):
def __init__(self, fpath, imgurl):
self.fpath = fpath
self.imgurl = imgurl
self._read()
@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

22
nasg.py
View file

@ -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
@ -717,6 +717,10 @@ class WebImage(object):
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):
return Exif(self.fpath)
@ -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 @@ def make():
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)

View file

@ -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',

View file

@ -9,9 +9,12 @@
{% 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>

View file

@ -17,6 +17,9 @@
<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 @@
<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 @@
</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 @@
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 @@
</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>

View file

@ -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;
}

5
templates/style-kcl.css Normal file
View file

@ -0,0 +1,5 @@
body {
font-family: serif;
background-color: #0f0;
color: #f00;
}

View file

@ -319,6 +319,19 @@ body > footer h2,
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;

View file

@ -23,28 +23,28 @@ function applyTheme(mode) {
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');
})