Compare commits

..

No commits in common. "9cee370a25f9b906134c5ca547912983304d3d42" and "bfa4108a8e532e704c445e2684ae7cbc3003c362" have entirely different histories.

6 changed files with 63 additions and 73 deletions

View File

@ -1,4 +1,5 @@
from datetime import datetime, timedelta import json
from sqlalchemy import create_engine, Column, String, ForeignKey, Integer from sqlalchemy import create_engine, Column, String, ForeignKey, Integer
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
@ -65,26 +66,18 @@ def get_story_by_ref(ref):
session = Session() session = Session()
return session.query(Story).filter(Story.ref==ref).first() return session.query(Story).filter(Story.ref==ref).first()
def get_stories_by_url(url): def get_reflist(amount):
session = Session() session = Session()
return session.query(Story).\ q = session.query(Reflist).order_by(Reflist.rid.desc()).limit(amount)
filter(Story.title != None).\
filter(Story.meta['url'].as_string() == url).\
order_by(Story.meta['date'].desc())
def get_reflist():
session = Session()
q = session.query(Reflist).order_by(Reflist.rid.desc())
return [dict(ref=x.ref, sid=x.sid, source=x.source) for x in q.all()] return [dict(ref=x.ref, sid=x.sid, source=x.source) for x in q.all()]
def get_stories(maxage=60*60*24*2): def get_stories(amount):
time = datetime.now().timestamp() - maxage
session = Session() session = Session()
q = session.query(Reflist, Story.meta).\ q = session.query(Reflist, Story.meta).\
join(Story).\ join(Story).\
filter(Story.title != None).\ filter(Story.title != None).\
filter(Story.meta['date'] > time).\ order_by(Story.meta['date'].desc()).\
order_by(Story.meta['date'].desc()) limit(amount)
return [x[1] for x in q] return [x[1] for x in q]
def put_ref(ref, sid, source): def put_ref(ref, sid, source):

View File

@ -6,13 +6,16 @@ logging.basicConfig(
import requests import requests
import time import time
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
import itertools
import settings import settings
from feeds import hackernews, reddit, tildes, substack, manual, news from feeds import hackernews, reddit, tildes, substack, manual, news
from scrapers import outline, declutter, local from scrapers import outline, declutter, local
ONE_HOUR = 60*60
ONE_DAY = 24*ONE_HOUR
INVALID_DOMAINS = ['youtube.com', 'bloomberg.com', 'wsj.com'] INVALID_DOMAINS = ['youtube.com', 'bloomberg.com', 'wsj.com']
MAX_AGE_IN_DAYS = 3*ONE_DAY
substacks = {} substacks = {}
for key, value in settings.SUBSTACK.items(): for key, value in settings.SUBSTACK.items():
@ -24,39 +27,36 @@ sitemaps = {}
for key, value in settings.SITEMAP.items(): for key, value in settings.SITEMAP.items():
sitemaps[key] = news.Sitemap(value['url'], value.get('tz')) sitemaps[key] = news.Sitemap(value['url'], value.get('tz'))
def get_list(): def list():
feeds = {} feed = []
if settings.NUM_HACKERNEWS: if settings.NUM_HACKERNEWS:
feeds['hackernews'] = [(x, 'hackernews') for x in hackernews.feed()[:settings.NUM_HACKERNEWS]] feed += [(x, 'hackernews') for x in hackernews.feed()[:settings.NUM_HACKERNEWS]]
if settings.NUM_REDDIT: if settings.NUM_REDDIT:
feeds['reddit'] = [(x, 'reddit') for x in reddit.feed()[:settings.NUM_REDDIT]] feed += [(x, 'reddit') for x in reddit.feed()[:settings.NUM_REDDIT]]
if settings.NUM_TILDES: if settings.NUM_TILDES:
feeds['tildes'] = [(x, 'tildes') for x in tildes.feed()[:settings.NUM_TILDES]] feed += [(x, 'tildes') for x in tildes.feed()[:settings.NUM_TILDES]]
if settings.NUM_SUBSTACK: if settings.NUM_SUBSTACK:
feeds['substack'] = [(x, 'substack') for x in substack.top.feed()[:settings.NUM_SUBSTACK]] feed += [(x, 'substack') for x in substack.top.feed()[:settings.NUM_SUBSTACK]]
for key, publication in substacks.items(): for key, publication in substacks.items():
count = settings.SUBSTACK[key]['count'] count = settings.SUBSTACK[key]['count']
feeds[key] = [(x, key) for x in publication.feed()[:count]] feed += [(x, key) for x in publication.feed()[:count]]
for key, sites in categories.items(): for key, sites in categories.items():
count = settings.CATEGORY[key].get('count') or 0 count = settings.CATEGORY[key].get('count') or 0
excludes = settings.CATEGORY[key].get('excludes') excludes = settings.CATEGORY[key].get('excludes')
tz = settings.CATEGORY[key].get('tz') tz = settings.CATEGORY[key].get('tz')
feeds[key] = [(x, key) for x in sites.feed(excludes)[:count]] feed += [(x, key) for x in sites.feed(excludes)[:count]]
for key, sites in sitemaps.items(): for key, sites in sitemaps.items():
count = settings.SITEMAP[key].get('count') or 0 count = settings.SITEMAP[key].get('count') or 0
excludes = settings.SITEMAP[key].get('excludes') excludes = settings.SITEMAP[key].get('excludes')
feeds[key] = [(x, key) for x in sites.feed(excludes)[:count]] feed += [(x, key) for x in sites.feed(excludes)[:count]]
values = feeds.values()
feed = itertools.chain.from_iterable(itertools.zip_longest(*values, fillvalue=None))
feed = list(filter(None, feed))
return feed return feed
def get_article(url): def get_article(url):
@ -124,7 +124,7 @@ def update_story(story, is_manual=False):
logging.info('Story not ready yet') logging.info('Story not ready yet')
return False return False
if story['date'] and not is_manual and story['date'] + settings.MAX_STORY_AGE < time.time(): if story['date'] and not is_manual and story['date'] + MAX_AGE_IN_DAYS < time.time():
logging.info('Story too old, removing') logging.info('Story too old, removing')
return False return False

View File

@ -163,8 +163,6 @@ def get_sitemap_date(a):
return a.find('lastmod').text return a.find('lastmod').text
if a.find('news:publication_date'): if a.find('news:publication_date'):
return a.find('news:publication_date').text return a.find('news:publication_date').text
if a.find('ns2:publication_date'):
return a.find('ns2:publication_date').text
return '' return ''
class Sitemap(_Base): class Sitemap(_Base):

View File

@ -15,7 +15,6 @@ import traceback
import time import time
from urllib.parse import urlparse, parse_qs from urllib.parse import urlparse, parse_qs
import settings
import database import database
import search import search
import feed import feed
@ -28,6 +27,9 @@ from flask_cors import CORS
database.init() database.init()
search.init() search.init()
FEED_LENGTH = 75
news_index = 0
def new_id(): def new_id():
nid = gen_rand_id() nid = gen_rand_id()
while database.get_story(nid): while database.get_story(nid):
@ -40,7 +42,7 @@ cors = CORS(flask_app)
@flask_app.route('/api') @flask_app.route('/api')
def api(): def api():
stories = database.get_stories(settings.MAX_STORY_AGE) stories = database.get_stories(FEED_LENGTH)
res = Response(json.dumps({"stories": stories})) res = Response(json.dumps({"stories": stories}))
res.headers['content-type'] = 'application/json' res.headers['content-type'] = 'application/json'
return res return res
@ -99,9 +101,7 @@ def submit():
def story(sid): def story(sid):
story = database.get_story(sid) story = database.get_story(sid)
if story: if story:
related = database.get_stories_by_url(story.meta['url']) res = Response(json.dumps({"story": story.data}))
related = [r.meta for r in related]
res = Response(json.dumps({"story": story.data, "related": related}))
res.headers['content-type'] = 'application/json' res.headers['content-type'] = 'application/json'
return res return res
else: else:
@ -144,49 +144,51 @@ def static_story(sid):
http_server = WSGIServer(('', 33842), flask_app) http_server = WSGIServer(('', 33842), flask_app)
def _add_new_refs():
for ref, source in feed.get_list():
if database.get_story_by_ref(ref):
continue
try:
nid = new_id()
database.put_ref(ref, nid, source)
logging.info('Added ref ' + ref)
except database.IntegrityError:
continue
def _update_current_story(item):
try:
story = database.get_story(item['sid']).data
except AttributeError:
story = dict(id=item['sid'], ref=item['ref'], source=item['source'])
logging.info('Updating story: {}'.format(str(story['ref'])))
valid = feed.update_story(story)
if valid:
database.put_story(story)
search.put_story(story)
else:
database.del_ref(item['ref'])
logging.info('Removed ref {}'.format(item['ref']))
def feed_thread(): def feed_thread():
ref_list = [] global news_index
try: try:
while True: while True:
# onboard new stories # onboard new stories
if not len(ref_list): if news_index == 0:
_add_new_refs() for ref, source in feed.list():
ref_list = database.get_reflist() if database.get_story_by_ref(ref):
continue
try:
nid = new_id()
database.put_ref(ref, nid, source)
logging.info('Added ref ' + ref)
except database.IntegrityError:
continue
ref_list = database.get_reflist(FEED_LENGTH)
# update current stories # update current stories
if len(ref_list): if news_index < len(ref_list):
item = ref_list.pop(0) item = ref_list[news_index]
_update_current_story(item)
try:
story = database.get_story(item['sid']).data
except AttributeError:
story = dict(id=item['sid'], ref=item['ref'], source=item['source'])
logging.info('Updating story: ' + str(story['ref']) + ', index: ' + str(news_index))
valid = feed.update_story(story)
if valid:
database.put_story(story)
search.put_story(story)
else:
database.del_ref(item['ref'])
logging.info('Removed ref {}'.format(item['ref']))
else:
logging.info('Skipping index: ' + str(news_index))
gevent.sleep(6) gevent.sleep(6)
news_index += 1
if news_index == FEED_LENGTH: news_index = 0
except KeyboardInterrupt: except KeyboardInterrupt:
logging.info('Ending feed thread...') logging.info('Ending feed thread...')
except ValueError as e: except ValueError as e:

View File

@ -1,8 +1,6 @@
# QotNews settings # QotNews settings
# edit this file and save it as settings.py # edit this file and save it as settings.py
MAX_STORY_AGE = 3*24*60*60
# Feed Lengths # Feed Lengths
# Number of top items from each site to pull # Number of top items from each site to pull
# set to 0 to disable that site # set to 0 to disable that site

View File

@ -72,6 +72,5 @@ export const logos = {
stuff: "data:image/png;base64,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", stuff: "data:image/png;base64,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",
substack: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAB80lEQVR4Ae3BwUtTcQAH8O/vt98L3/YYYm2TDusUZCBURlTHSV3yTzA8iHcVaYID50HQIWM3BY8P/QdaIAV2a2HIKDGhukgjtqEi7+3trb3X79c7jijbRr2fBz8fAk8sGIiVn0bL8FG/Xu2v1H9UKCSjkIzB43DhFCpOAT5yuHBw4Twg8PT10L6XTy6/go8evzh+dNLgJwwehRJl6Aq7Ax8plCjwUEjG4BECosnRhI+EgMCF84DAE1ZoOPswnIWPpt8Y04bDDQaPqhB1/IY6Dh/NvTPnDAcGhWQUklFIRiEZhWQUklFIRiEZQ5fKdV6e3zXnCQhZuKstxFQaQxcYOlR3RT37wcpm3lsZs8lNeDa/2JvJW6Hk1GBoKshIEB1gaBMX4PpnW0/tGKmSxUtoYTa5mdoxU2v71trivfDi6HV1lBJQtIGhDdvfmtszBWOmeOQUcYaSxUtjr0/HcntWbuVBeCVx9VICf8Fwho+nzkHybe1Z/rCRRweKR05x+Pnx8Mi1npHl+1rmZq8ygD9g+I2qzavp3Vp6/aC+7nLhokv5w0Z+6+v3rYmB4ER6SEtHVRrFLxha2C7s3J6VWyrWlgyHG/gHXC7c1X1rdeOTvTF7W5udHAxNqgwqWkXUQERP9OpxjcXxn8U1FtcTvXpEDUTg+QkFxcDjVd0KBQAAAABJRU5ErkJggg==", substack: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAB80lEQVR4Ae3BwUtTcQAH8O/vt98L3/YYYm2TDusUZCBURlTHSV3yTzA8iHcVaYID50HQIWM3BY8P/QdaIAV2a2HIKDGhukgjtqEi7+3trb3X79c7jijbRr2fBz8fAk8sGIiVn0bL8FG/Xu2v1H9UKCSjkIzB43DhFCpOAT5yuHBw4Twg8PT10L6XTy6/go8evzh+dNLgJwwehRJl6Aq7Ax8plCjwUEjG4BECosnRhI+EgMCF84DAE1ZoOPswnIWPpt8Y04bDDQaPqhB1/IY6Dh/NvTPnDAcGhWQUklFIRiEZhWQUklFIRiEZQ5fKdV6e3zXnCQhZuKstxFQaQxcYOlR3RT37wcpm3lsZs8lNeDa/2JvJW6Hk1GBoKshIEB1gaBMX4PpnW0/tGKmSxUtoYTa5mdoxU2v71trivfDi6HV1lBJQtIGhDdvfmtszBWOmeOQUcYaSxUtjr0/HcntWbuVBeCVx9VICf8Fwho+nzkHybe1Z/rCRRweKR05x+Pnx8Mi1npHl+1rmZq8ygD9g+I2qzavp3Vp6/aC+7nLhokv5w0Z+6+v3rYmB4ER6SEtHVRrFLxha2C7s3J6VWyrWlgyHG/gHXC7c1X1rdeOTvTF7W5udHAxNqgwqWkXUQERP9OpxjcXxn8U1FtcTvXpEDUTg+QkFxcDjVd0KBQAAAABJRU5ErkJggg==",
"the bulletin": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADwElEQVR4AcXBW2iWBRzH8e/v/z7vfH3du5rOU7p0w8PwkIlM2kIsSbSoGdhFXkRkh0sp6qLool0EddnJKIT0oqguVDDEUjRRYSbOssY2zWpbs3Ind3Dnd8+/HQij8H0f9WKfjwq27HImkTHJjElmTDLjlghHTBDXiZsVcFOccYJEzCjITzAlDkPD0N45QO+wY4wR4EQREJEAR2wqncuzm0tYu7yQRNyQwIGhdEh9Qyv7Tv3GZ4cv0j0QIkQ2ARHl5Bjv7yijomwJZsa/CUjEY9y7+C5WLZrN848uY8c7JzhZ04KZkYmRlRHivP3CGraUL8HMyESKMa/gTjaVFSKJbAKyCllZdAdPbliBZIxJj6T5/Fg9R84209M/zIxUghVF+TyxfhGz86ex+1ANb+w+hySyCYhgU+kCTGKcOx8d+InKPdWYGU7ImANVTby79zyPlS3gy28bcDeQk01ABEVzc8EBgcvZf+pXMEY5Qoxz6B1wvjjWADIQkRgRhCEIMc6haE4uLsa5O9cJZExwogjIwh1+vtyFA2LCW8+VEY8FHDvXTFvPEIZAjHLAESKqgCzc4WBVI69uKyUnCJCMgvwUO196kJGRkLauXhpbrvHL5aucudDK4e+aaO9JE1UsWVJRSQYSdFxLgw9SvnIeJiGEJGJmpJIJ5s/M457iWWwuXcBTm0sYHOqn+mI7ILKJJUsqKslCwOnaVppaOlhZPJ1UcgqS+C9JJOJxHlhdSHdvH9UX2kEik1iypKKSSERtQxe7D9Vx4sdm6ps6aGrppuvaAEEAuYkcxCgJSaxZOotPvq5nOB2SScBNGk5DVU0bp2taQYwShGnuXzaLXa9tpCCVCxJ5yanct7yAo2dbgJAbMW6BBEiAGKcYp2rb+PSbOpyQMZK4e2Yu4GRiROQ4IsRx/kcCE119wzjXuYtsjIie3riIj19Zz4y8OI7jDo5wHHCm5sSoKCvEZIxxD2m80kM2ARFsf2Qxb24vx8zYsLqQI9WNfH+pnZaOfgyxcG6Kx9cVs3T+dP7xV2cfVTV/AiKTgIyMVcV5VD5TTswMychLTmXruhK2ruOG0iMjvL7rBINDApGRkVHI+UtXefG9o7T19OEekk1P/yAvf3icA1V/4CKrgGxM7DvZzPEf9rLtocU8vHY+yxbOITklhgB3ETr8fqWTr840sOdgLU1tgxgiioCI2nvS7Nxfxwf764jHQmakEkxLGCHiavcgXX1pQIAwoguISEwQkB4xrnQO4ThjhADjVgTcBiFulzHJjElmTLK/AU9/SZ4HPrs9AAAAAElFTkSuQmCC", "the bulletin": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADwElEQVR4AcXBW2iWBRzH8e/v/z7vfH3du5rOU7p0w8PwkIlM2kIsSbSoGdhFXkRkh0sp6qLool0EddnJKIT0oqguVDDEUjRRYSbOssY2zWpbs3Ind3Dnd8+/HQij8H0f9WKfjwq27HImkTHJjElmTDLjlghHTBDXiZsVcFOccYJEzCjITzAlDkPD0N45QO+wY4wR4EQREJEAR2wqncuzm0tYu7yQRNyQwIGhdEh9Qyv7Tv3GZ4cv0j0QIkQ2ARHl5Bjv7yijomwJZsa/CUjEY9y7+C5WLZrN848uY8c7JzhZ04KZkYmRlRHivP3CGraUL8HMyESKMa/gTjaVFSKJbAKyCllZdAdPbliBZIxJj6T5/Fg9R84209M/zIxUghVF+TyxfhGz86ex+1ANb+w+hySyCYhgU+kCTGKcOx8d+InKPdWYGU7ImANVTby79zyPlS3gy28bcDeQk01ABEVzc8EBgcvZf+pXMEY5Qoxz6B1wvjjWADIQkRgRhCEIMc6haE4uLsa5O9cJZExwogjIwh1+vtyFA2LCW8+VEY8FHDvXTFvPEIZAjHLAESKqgCzc4WBVI69uKyUnCJCMgvwUO196kJGRkLauXhpbrvHL5aucudDK4e+aaO9JE1UsWVJRSQYSdFxLgw9SvnIeJiGEJGJmpJIJ5s/M457iWWwuXcBTm0sYHOqn+mI7ILKJJUsqKslCwOnaVppaOlhZPJ1UcgqS+C9JJOJxHlhdSHdvH9UX2kEik1iypKKSSERtQxe7D9Vx4sdm6ps6aGrppuvaAEEAuYkcxCgJSaxZOotPvq5nOB2SScBNGk5DVU0bp2taQYwShGnuXzaLXa9tpCCVCxJ5yanct7yAo2dbgJAbMW6BBEiAGKcYp2rb+PSbOpyQMZK4e2Yu4GRiROQ4IsRx/kcCE119wzjXuYtsjIie3riIj19Zz4y8OI7jDo5wHHCm5sSoKCvEZIxxD2m80kM2ARFsf2Qxb24vx8zYsLqQI9WNfH+pnZaOfgyxcG6Kx9cVs3T+dP7xV2cfVTV/AiKTgIyMVcV5VD5TTswMychLTmXruhK2ruOG0iMjvL7rBINDApGRkVHI+UtXefG9o7T19OEekk1P/yAvf3icA1V/4CKrgGxM7DvZzPEf9rLtocU8vHY+yxbOITklhgB3ETr8fqWTr840sOdgLU1tgxgiioCI2nvS7Nxfxwf764jHQmakEkxLGCHiavcgXX1pQIAwoguISEwQkB4xrnQO4ThjhADjVgTcBiFulzHJjElmTLK/AU9/SZ4HPrs9AAAAAElFTkSuQmCC",
tvnz: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAASAAAAEgARslrPgAABWVJREFUWMOVl1+MlNUZxn/PmYGFXSgw7kJbiPzZVVkBaaSicTclFWyMJjaxiUkTNd6ZEOMF8cZojIlR74xpb9pb7AW98KY3VAu0Wi0IasVVEQPpAqIBZgd2gF3izJzHi++bmW92/rg9yTeZ88133vd33vO87/eOmOf4cMcmbHJBLJdYL7FGaKkEEleBc0H8D8IVIG498Nm87KrXj4d/dTs2AMsEY5J2StwhsVYwKGmRBIIbEpckzggdlzggOGwoB2DzPyb+f4B/j90OMCB4UOJxiXHBCkmku0ZAY05yLwiESoj3BG9K/N1mZksXiDaAd+8dRQbDrRJ7JD2aOO7gtDcEEiVgn8TrNqdDgE1vT3QH+Oc9owRExGMSrwrGJYKkhvHkmjPvDRGBf0k8Z3NUgs3vTLQDHLh7Y33n9wbpDxLbsga7OsXgSAgBhUDrmgYEgqMST9scy0YiAHw4/gtihJq51fBKtLfZYENsXE6uGInVGrFWwxL5whADo1vJD67EMeJkE9TXG9fvbbd5RWLYhslHtgCQB7h8YxagX2gPsAOBbUjpnVoMCxfSN7SSgbUbGLhlI/3rNrD45vX0/XQ11z7/L2feeJlqqQghJGFwPc4GC4ldNs9IPHf1KjMA+f133gaJ/YeQH8WSACvdRmqpb+Uq1j75FMvv3E7f0Cpy/QNJjNOxZNNWFg79jErxYnpfbRBGEjxmcxD428T9W8hHgMgywWPAivTBZGEaCcXI0o2bWfXAb8n193dJaGGpXjea8BkIJ0YLiMcF7wLTIT2rMcN449zsxjk2FuYXJNLuMUyil6YO3KKJ2NTEfYa7DIRajLK906bQ8uBcMcVab+eu6yYrwFYIUkBwwWYspz4CqGC4o502Ub3TnVXKZWoz14mVCpUrJVytdgSJdtNpNqKZjaWRuKcSbxTyNuuBtWRFlzm3iJECV76Y4MRrLxHyORYsWcrw7j0sWFHoEIV0aZutNtvDwLq8YQ1msFGWOkAgqM5c58Khd6BWpbDtLhxjl2PIJk9PiEGJ1XnbS0GLmmruDqGQSzMsdBVhVrxttlojswizJJ/MnSb+j0Ek8TV0B0h1QyeIOXMDeUMZM4u8eF4QvQAyoktKaE+IWYmrAXPOUGyp2z1yuT7vCpB9bo4w58yLNueDYdLmTNvLowtE7BkF94ZoTdFTNpOhWvNl28c7vsE6QTiF6Oa841u0o60jZy9duxxCwIYDtkvzhei0/UaIaR5Ri63W8E/Z/uDnNw0Q0lWHbd5rP7cOEKmx9qHM7jtAtNo+aPgIIKThLBvetJlqPEgXCEOs1TLJ3lRgvSGBnhBFm721SDkawu9PnKo73G/Yl+hkjpgyEChw/dxZSp9+TKU8TWV6mkp5mtInx5j59jxWyDjOQCS2ou29hkMA4+9/mSTmICP8cRSAYcGfBLsafWC2x2v0d2bxylX0r1lDCAFsZr85y/dTl5LesGVNSxe9X7AbmNxx+ASQtmRFTuE4Qshx2uZ54CeY7Y3a3TjmtGJKzF68wOyF75oOQiAEEe2k0UwLkQWyCeg/wAvRTGYrea7+5a2pEr+7qUBYyHnXOI7YAKyj3hg2tZZ8pE6TTlhJs9XWrwggIt4Gnq3W/IkC7DzyVTsAwFvFEo8sKxByfGv4ILVwC7C4I0TLvA7W4r+I9GfgRcMJgvjN0a+yLrv/Nds3OoKhX7BL8ITEryUVOvb87X9QpgQHJfZKHAJmH/joZJfk7TH+snGEvgDRLEP8Umhc4m6JYcGQxKIUYlaiKHFKcETS+xIfS5SrFXj4s5NdffTuMjPjr6MjACEELResQ6wOYonASNcE30icCWLaEB/+9Ot52f0B/MOqaxJsqlAAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDktMjhUMjA6NDA6MjkrMDA6MDD37mKbAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE2LTA5LTI4VDIwOjQwOjI5KzAwOjAwhrPaJwAAAEZ0RVh0c29mdHdhcmUASW1hZ2VNYWdpY2sgNi43LjgtOSAyMDE0LTA1LTEyIFExNiBodHRwOi8vd3d3LmltYWdlbWFnaWNrLm9yZ9yG7QAAAAAYdEVYdFRodW1iOjpEb2N1bWVudDo6UGFnZXMAMaf/uy8AAAAYdEVYdFRodW1iOjpJbWFnZTo6aGVpZ2h0ADE5Mg8AcoUAAAAXdEVYdFRodW1iOjpJbWFnZTo6V2lkdGgAMTky06whCAAAABl0RVh0VGh1bWI6Ok1pbWV0eXBlAGltYWdlL3BuZz+yVk4AAAAXdEVYdFRodW1iOjpNVGltZQAxNDc1MDk1MjI5BqTtUAAAAA90RVh0VGh1bWI6OlNpemUAMEJClKI+7AAAAFZ0RVh0VGh1bWI6OlVSSQBmaWxlOi8vL21udGxvZy9mYXZpY29ucy8yMDE2LTA5LTI4LzgzZWFmZGYwYzNkNzQzZDY4YzI0NzE0ZTVhMjY4YWY2Lmljby5wbmcMVz3tAAAAAElFTkSuQmCC",
webworm: "data:image/png;base64,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", webworm: "data:image/png;base64,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",
}; };