Merge remote-tracking branch 'danbooru_atomizer/master'
This commit is contained in:
commit
31de1416b1
3 changed files with 160 additions and 0 deletions
19
get.py
Normal file
19
get.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
from retry import retry
|
||||
import requests, requests.exceptions
|
||||
|
||||
class StatusCodeError(Exception):
|
||||
def __init__(self, code, url):
|
||||
self.code = code
|
||||
self.url = url
|
||||
def __str__(self):
|
||||
return 'request for {} returned status code {}'.format(self.url, self.code)
|
||||
|
||||
@retry((requests.exceptions.ConnectionError, StatusCodeError, ValueError), tries=6, wait=300)
|
||||
def get(uri, json=False):
|
||||
r = requests.get(uri)
|
||||
if r.status_code != 200:
|
||||
raise StatusCodeError(r.status_code, uri)
|
||||
if json:
|
||||
return r.json()
|
||||
return r
|
||||
|
17
retry.py
Normal file
17
retry.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
# so damn useful it deserved its own file
|
||||
|
||||
import time
|
||||
|
||||
def retry(Exceptions, tries=10, wait=1):
|
||||
if type(Exceptions) == Exception:
|
||||
Exceptions = (Exceptions,)
|
||||
def retryer(f):
|
||||
def deco(*args, **kwargs):
|
||||
for i in range(tries - 1):
|
||||
try:
|
||||
return f(*args, **kwargs)
|
||||
except Exceptions:
|
||||
time.sleep(wait)
|
||||
return f(*args, **kwargs)
|
||||
return deco
|
||||
return retryer
|
124
run.py
Executable file
124
run.py
Executable file
|
@ -0,0 +1,124 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
from urllib.parse import quote_plus
|
||||
from xml.dom.minidom import parseString as parseXML
|
||||
import datetime
|
||||
from get import get
|
||||
|
||||
lament = lambda *args, **kwargs: print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
parseDate = lambda s: datetime.datetime.strptime(s+'+0000', '%Y-%m-%dT%H:%M:%SZ%z')
|
||||
formatDate = lambda dt: dt.strftime('%FT%TZ')
|
||||
|
||||
# we only need a handful of mime types so we may as well inline them
|
||||
mimes = {
|
||||
'png': 'image/png',
|
||||
'jpg': 'image/jpeg',
|
||||
'gif': 'image/gif',
|
||||
'swf': 'application/x-shockwave-flash',
|
||||
}
|
||||
|
||||
class Untitled:
|
||||
template = """
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||
</feed>
|
||||
""".strip()
|
||||
|
||||
def __init__(self, urls, max_entries=512):
|
||||
self.urls = urls
|
||||
self.max_entries = max_entries
|
||||
self.title = 'Danbooru - Personalized Feed'
|
||||
self.items = []
|
||||
|
||||
def parse(self, q):
|
||||
url = self.urls['atom'] + quote_plus(q)
|
||||
xml = get(url).text
|
||||
dom = parseXML(xml)
|
||||
|
||||
entries = dom.getElementsByTagName('entry')
|
||||
for entry in entries:
|
||||
getText = lambda tn: entry.getElementsByTagName(tn)[0].firstChild.nodeValue
|
||||
|
||||
item = {
|
||||
'title': getText('title'),
|
||||
'id': getText('id').split('/')[-1],
|
||||
'updated': getText('updated'),
|
||||
'summary': getText('summary'),
|
||||
'img': entry.getElementsByTagName('img')[0].getAttribute('src'),
|
||||
'query': q,
|
||||
}
|
||||
item['updated_unix'] = parseDate(item['updated']).timestamp()
|
||||
|
||||
self.items.append(item)
|
||||
|
||||
def generate(self):
|
||||
self.items = sorted(self.items, key=lambda d: d['updated_unix'], reverse=True)
|
||||
self.items = self.items[:self.max_entries]
|
||||
|
||||
now = formatDate(datetime.datetime.utcnow())
|
||||
|
||||
dom = parseXML(self.template)
|
||||
feed = dom.firstChild
|
||||
|
||||
def newText(entity_name, text):
|
||||
e = dom.createElement(entity_name)
|
||||
e.appendChild(dom.createTextNode(text))
|
||||
return e
|
||||
|
||||
def newLink(**kwargs):
|
||||
link = dom.createElement('link')
|
||||
for k, v in kwargs.items():
|
||||
link.setAttribute(k, v)
|
||||
return link
|
||||
|
||||
feed.appendChild(newText('title', self.title))
|
||||
feed.appendChild(newLink(href=self.urls['feed'], rel='self'))
|
||||
feed.appendChild(newText('id', self.urls['feed']))
|
||||
feed.appendChild(newText('updated', now))
|
||||
|
||||
for item in self.items:
|
||||
ext = item['img'].split('.')[-1]
|
||||
mime = mimes[ext]
|
||||
alt = self.urls['post'] + item['id']
|
||||
query_quote = quote_plus(item['query'])
|
||||
|
||||
entry = dom.createElement('entry')
|
||||
entry.appendChild(newText('title', item['title']))
|
||||
entry.appendChild(newLink(href=alt, rel="alternate"))
|
||||
entry.appendChild(newText('id', alt))
|
||||
entry.appendChild(newText('published', item['updated']))
|
||||
entry.appendChild(newText('updated', item['updated']))
|
||||
entry.appendChild(newLink(rel="enclosure", type=mime, href=item['img']))
|
||||
entry.appendChild(newText('summary', item['summary']))
|
||||
|
||||
author = dom.createElement('author')
|
||||
author.appendChild(newText('name', item['query']))
|
||||
author.appendChild(newText('uri', self.urls['query'] + query_quote))
|
||||
|
||||
entry.appendChild(author)
|
||||
|
||||
feed.appendChild(entry)
|
||||
|
||||
return dom.toxml()
|
||||
|
||||
urls = {
|
||||
'atom': 'https://danbooru.donmai.us/posts.atom?limit=48&tags=',
|
||||
'post': 'https://danbooru.donmai.us/posts/',
|
||||
'img': 'https://danbooru.donmai.us/ssd/data/preview/',
|
||||
'query': 'https://danbooru.donmai.us/posts?tags=',
|
||||
}
|
||||
|
||||
if __name__ == '__main__':
|
||||
urls['feed'] = sys.argv[1]
|
||||
|
||||
untitled = Untitled(urls)
|
||||
|
||||
queries = sys.stdin.read()
|
||||
|
||||
for q in queries.splitlines():
|
||||
lament(q)
|
||||
untitled.parse(q)
|
||||
|
||||
print(untitled.generate())
|
Loading…
Reference in a new issue