feedbot/feedbot.py

191 lines
4.8 KiB
Python

import feedparser
import requests
import textwrap
import logging
import pnutpy
import click
import time
import re
import os
import models as zdb
from PIL import ImageFile
SNAP_USER_DATA = os.environ.get('SNAP_USER_DATA')
dr = False
@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.option('--dryrun', is_flag=True)
@click.version_option(version='0.2.2')
def main(ctx, db, prime, debug, dryrun):
global dr
if debug:
logging.basicConfig(level=logging.DEBUG)
else:
logging.basicConfig(level=logging.INFO)
if dryrun:
dr = dryrun
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')
def enable(uid):
'''Enable posts to pnut'''
user = zdb.User.get(pnut_uid=uid)
user.pnut_enabled = 1
user.save()
@main.command()
@click.argument('uid')
def disable(uid):
'''Disable posts to pnut'''
user = zdb.User.get(pnut_uid=uid)
user.pnut_enabled = 0
user.save()
@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:
if not dr:
entry = zdb.Entries(feedid=fid, link=link)
entry.save()
if prime:
logging.debug(f"saving {link}...")
elif user.pnut_enabled:
logging.debug(f"posting {link}...")
pnutpost(post, source, user.pnut_token)
else:
logging.debug(f"pnut disabled, saving {link}...")
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]
if hasattr(entry, 'media_content'):
for media in entry.media_content:
if media["medium"] == "image":
raw.append(embed_image(media["url"]))
try:
rx = re.compile('<.*?>')
text = re.sub(rx, '', entry.summary)
lchk = textwrap.wrap(text, 256)
if len(lchk) > 1:
pretext = textwrap.wrap(text, 250)
longpost = {
'type': "nl.chimpnut.blog.post",
'value': {
'body': text,
'tstamp': time.time() * 1000
}
}
raw.append(longpost)
text = pretext + " [...](" + entry.link + ")"
if dr:
logging.info({'text': text, 'raw': raw})
else:
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, 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
}
return {'type': "io.pnut.core.oembed", 'value': embed}
else:
return {}