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,8 +144,14 @@ def static_story(sid):
http_server = WSGIServer(('', 33842), flask_app) http_server = WSGIServer(('', 33842), flask_app)
def _add_new_refs(): def feed_thread():
for ref, source in feed.get_list(): global news_index
try:
while True:
# onboard new stories
if news_index == 0:
for ref, source in feed.list():
if database.get_story_by_ref(ref): if database.get_story_by_ref(ref):
continue continue
try: try:
@ -155,13 +161,18 @@ def _add_new_refs():
except database.IntegrityError: except database.IntegrityError:
continue continue
def _update_current_story(item): ref_list = database.get_reflist(FEED_LENGTH)
# update current stories
if news_index < len(ref_list):
item = ref_list[news_index]
try: try:
story = database.get_story(item['sid']).data story = database.get_story(item['sid']).data
except AttributeError: except AttributeError:
story = dict(id=item['sid'], ref=item['ref'], source=item['source']) story = dict(id=item['sid'], ref=item['ref'], source=item['source'])
logging.info('Updating story: {}'.format(str(story['ref']))) logging.info('Updating story: ' + str(story['ref']) + ', index: ' + str(news_index))
valid = feed.update_story(story) valid = feed.update_story(story)
if valid: if valid:
@ -170,23 +181,14 @@ def _update_current_story(item):
else: else:
database.del_ref(item['ref']) database.del_ref(item['ref'])
logging.info('Removed ref {}'.format(item['ref'])) logging.info('Removed ref {}'.format(item['ref']))
else:
def feed_thread(): logging.info('Skipping index: ' + str(news_index))
ref_list = []
try:
while True:
# onboard new stories
if not len(ref_list):
_add_new_refs()
ref_list = database.get_reflist()
# update current stories
if len(ref_list):
item = ref_list.pop(0)
_update_current_story(item)
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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",
}; };