Mercurial > code > home > repos > href
view lookup.py @ 42:530650b3bc40 default tip
something changed in pom to break pyjwt. switched to jwskate
author | drewp@bigasterisk.com |
---|---|
date | Wed, 14 Dec 2022 22:07:19 -0800 |
parents | 293a694304b8 |
children |
line wrap: on
line source
""" serve some queries over bookmarks: /user /user/tag+tag+tag and the add-bookmark stuff """ import datetime import json import logging import os import time import urllib.error import urllib.parse import urllib.request from collections import defaultdict import bottle from bottle import static_file from dateutil.tz import tzlocal from prometheus_client.exposition import generate_latest from prometheus_client.registry import REGISTRY from get_agent import bottleGetAgent from jadestache import Renderer from link import Links, NotFound from mongo_required import die_on_mongo_connection_errors, open_mongo_or_die from pagetitle import PageTitle db = open_mongo_or_die()['href'] pageTitle = PageTitle(db) links = Links(db) renderer = Renderer(search_dirs=['template'], debug=bottle.DEBUG) logging.basicConfig(level=logging.DEBUG) log = logging.getLogger() def getUser(): try: agent = bottleGetAgent() username = db['user'].find_one({'_id': str(agent)})['username'] if agent else None except KeyError: username = agent = None return username, agent def siteRoot(): return 'https://bigasterisk.com/href' @bottle.route('/static/<path:path>') def server_static(path): return static_file(path, root='static') def recentLinks(user, tags, allowEdit): out = {'links': []} t1 = time.time() spec = {'user': user} if tags: spec['extracted.tags'] = {'$all': tags} for doc in db['links'].find(spec, sort=[('t', -1)], limit=50): link = links.forDisplay(doc) link['allowEdit'] = allowEdit out['links'].append(link) out['stats'] = {'queryTimeMs': round((time.time() - t1) * 1000, 2)} return out def allTags(user, withTags=[]): """withTags limits results to other tags that have been used with those tags""" withTags = set(withTags) count = defaultdict(lambda: 0) # tag : count for doc in db['links'].find({'user': user}, projection=['extracted.tags']): docTags = set(doc.get('extracted', {}).get('tags', [])) if withTags and not withTags.issubset(docTags): continue for t in docTags.difference(withTags): count[t] = count[t] + 1 byFreq = [(n, t) for t, n in count.items()] byFreq.sort(key=lambda n_t: (-n_t[0], n_t[1])) return [{'label': t, 'count': n} for n, t in byFreq] def renderWithTime(name, data): t1 = time.time() rendered = renderer.render_name(name, data) dt = (time.time() - t1) * 1000 rendered = rendered.replace('TEMPLATETIME', "%.02f ms" % dt) return rendered @bottle.route('/addLink') def addLink(): out = { 'toRoot': siteRoot(), 'absRoot': siteRoot(), 'user': getUser()[0], 'withKnockout': True, 'fillHrefJson': json.dumps(bottle.request.params.get('url', '')), } return renderWithTime('add.jade', out) @bottle.route('/addOverlay') def addOverlay(): p = bottle.request.params return "" @bottle.route('/addLink/proposedUri') def proposedUri(): uri = bottle.request.params.uri user, _ = getUser() try: prevDoc = links.find(uri, user) except NotFound: prevDoc = None return { 'description': prevDoc['description'] if prevDoc else pageTitle.pageTitle(uri), 'tag': prevDoc['tag'] if prevDoc else '', 'extended': prevDoc['extended'] if prevDoc else '', 'shareWith': prevDoc.get('shareWith', []) if prevDoc else [], 'suggestedTags': ['tag1', 'tag2'], 'existed': prevDoc is not None, } # proposal check existing links, get page title (stuff that in db), get tags from us and other serviecs. maybe the deferred ones ater @bottle.route('/tags') def tagFilterComplete(): params = bottle.request.params haveTags = [_f for _f in params['have'].split(',') if _f] if haveTags and len(haveTags[-1]) > 0: haveTags, partialTerm = haveTags[:-1], haveTags[-1] else: partialTerm = "" out = [] for t in allTags(params.user, withTags=haveTags): if partialTerm and partialTerm not in t['label']: continue out.append({'id': t['label'], 'text': "%s (%s%s)" % (t['label'], t['count'], " left" if haveTags else "")}) return {'tags': out} @bottle.route('/<user>/') def userSlash(user): bottle.redirect(siteRoot() + "/%s" % urllib.parse.quote(user)) @bottle.route('/<user>.json', method='GET') def userAllJson(user): data = recentLinks(user, [], allowEdit=getUser()[0] == user) data['toRoot'] = siteRoot() return json.dumps(data) @bottle.route('/<user>', method='GET') def userAll(user): return userLinks(user, "") @bottle.route('/<user>', method='POST') def userAddLink(user): u = getUser()[0] if u is None: raise ValueError('not logged in') if u != user: raise ValueError("not logged in as %s" % user) print(repr(bottle.request.params.__dict__)) doc = links.fromPostdata(bottle.request.params, user, datetime.datetime.now(tzlocal())) links.insertOrUpdate(doc) print("notify about sharing to", repr(doc['shareWith'])) bottle.redirect(siteRoot() + '/' + user) def parseTags(tagComponent): # the %20 is coming from davis.js, not me :( return [_f for _f in tagComponent.replace("%20", "+").split('+') if _f] @bottle.route('/<user>/<tags:re:.*>.json') def userLinksJson(user, tags): tags = parseTags(tags) data = recentLinks(user, tags, allowEdit=getUser()[0] == user) data['toRoot'] = siteRoot() return json.dumps(data) @bottle.route('/<user>/<tags>') @die_on_mongo_connection_errors() def userLinks(user, tags): tags = parseTags(tags) log.info('userLinks user=%r tags=%r', user, tags) data = recentLinks(user, tags, allowEdit=getUser()[0] == user) data['desc'] = ("%s's recent links" % user) + (" tagged %s" % (tags,) if tags else "") data['toRoot'] = siteRoot() data['allTags'] = allTags(user) data['user'] = user data['showPrivateData'] = (user == getUser()[0]) data['pageTags'] = [{"word": t} for t in tags] data['stats']['template'] = 'TEMPLATETIME' return renderWithTime('links.jade', data) @bottle.route('/templates') def templates(): return json.dumps({'linklist': renderer.load_template("linklist.jade")}) @bottle.route('/metrics') def metrics(): bottle.response.content_type = "text/plain" return generate_latest(REGISTRY) @bottle.route('/') def root(): data = { 'toRoot': siteRoot(), 'stats': { 'template': 'TEMPLATETIME' }, 'users': [{ 'user': doc['username'] } for doc in db['user'].find()], } return renderWithTime('index.jade', data) if __name__ == '__main__': logging.basicConfig(level=logging.INFO) bottle.run(server='gunicorn', host='0.0.0.0', port=10002, workers=1)