feedbot/feedbot.py

143 lines
3.6 KiB
Python

import feedparser
import requests
import logging
import pnutpy
import click
import re
import os
import models as zdb
from PIL import ImageFile
SNAP_USER_DATA = os.environ.get('SNAP_USER_DATA')
@click.group(invoke_without_command=True)
@click.pass_context
@click.option('--db')
@click.option('--prime', is_flag=True)
@click.option('--debug', is_flag=True)
@click.version_option(version='0.1.0')
def main(ctx, db, prime, debug):
if debug:
logging.basicConfig(level=logging.DEBUG)
if SNAP_USER_DATA is None and db is not None:
db_file = db
else:
db_file = SNAP_USER_DATA + '/feeds.db'
zdb.db.init(db_file)
zdb.create_tables()
if ctx.invoked_subcommand is None:
for feed in zdb.Feeds.select():
fetch(feed.url, feed.pnut_uid, feed.id, prime)
@main.command()
@click.argument('username')
@click.argument('token')
def adduser(username, token):
'''Add a pnut user'''
pnutpy.api.add_authorization_token(token)
pass
try:
pnut_user, meta = pnutpy.api.get_user('me')
user = zdb.User(pnut_uid=pnut_user.id, pnut_token=token, pnut_enabled=True)
user.save()
except pnutpy.errors.PnutAuthAPIException:
logging.error(f"pnut user token not valid")
@main.command()
@click.argument('uid')
@click.argument('url')
def add(uid, url):
'''Add a feed'''
feed = zdb.Feeds(pnut_uid=uid, url=url)
feed.save()
def fetch(url, pnut_uid, fid, prime):
feed = feedparser.parse(url)
try:
user = zdb.User.get(pnut_uid=pnut_uid)
source = {
'link': feed.feed.link,
'username': feed.feed.title,
'avatar': feed.feed.image.href
}
for post in reversed(feed.entries):
link = post.link
try:
entry = zdb.Entries.get(feedid=fid, link=link)
logging.debug(f"skipping {link}...")
except zdb.Entries.DoesNotExist:
entry = zdb.Entries(feedid=fid, link=link)
entry.save()
if prime:
logging.debug(f"saving {link}...")
else:
logging.debug(f"posting {link}...")
pnutpost(post, source, user.pnut_token)
except zdb.User.DoesNotExist:
logging.error(f"user {pnut_uid} not found")
except Exception:
logging.exception("bad stuff")
def pnutpost(entry, source, token):
pnutpy.api.add_authorization_token(token)
crosspost = {
'type': "io.pnut.core.crosspost",
'value': {
'canonical_url': entry.link,
#'source': {'url': source['link']},
'user': {
'username': source['username'],
'avatar_image': source['avatar']
}
}
}
raw = [crosspost]
for link in entry.links:
if link.rel == "enclosure":
if "image" in link.type:
raw.append(embed_image(link))
try:
rx = re.compile('<.*?>')
text = re.sub(rx, '', entry.summary)
p, meta = pnutpy.api.create_post(data={'text': text, 'raw': raw})
except Exception:
logging.exception("bad stuff")
def embed_image(link):
resume_header = {'Range': 'bytes=0-2000000'}
r = requests.get(link.href, stream=True, headers=resume_header)
p = ImageFile.Parser()
p.feed(r.content)
if p.image:
width, height = p.image.size
embed = {
'version': "1.0",
'type': "photo",
'width': width,
'height': height,
'url': link.href
}
return {'type': "io.pnut.core.oembed", 'value': embed}
else:
return {}