def get_objects(self, handle): """ Get the collection of user Follows """ user = current_app.db.fetch( self.user_url(handle=handle)) return vocab.OrderedCollection([ vocab.Follow({ "@id": follow.id, "actor": user, "object": follow.object }) for follow in user.follow_collection])
def inbox_get(handle=None): """ think of this as the "Home" feed on mastodon. returns all Objects addressed to the user. this should require authentication """ u = find_user(handle) items = list(mongo.db.posts.find({'to': u['@id']}, {'_id': False}).sort('published', -1)) resp = vocab.OrderedCollection( u['inbox'], totalItems=len(items), orderedItems=items) return Response(json.dumps(resp.json()), headers=content_headers(u))
def feed_get(handle): """ per AP spec, returns a reverse-chronological OrderedCollection of items in the outbox, pending privacy settings """ print('feed get') u = find_user(handle) items = list(mongo.db.posts.find({'object.attributedTo': u['@id']}, {'_id': False}).sort('published', -1)) resp = vocab.OrderedCollection( u['outbox'], totalItems=len(items), orderedItems=items) return Response(json.dumps(resp.json()), headers=content_headers(u))
def inbox(handle): if request.method == 'GET': """ think of this as the "Home" feed on mastodon. returns all Objects addressed to the user. this should require authentication """ u = find_user(handle) items = list( mongo.db.posts.find({ 'to': u['@id'] }, { '_id': False }).sort('published', -1)) resp = vocab.OrderedCollection(u['inbox'], totalItems=len(items), orderedItems=items) return Response(resp, headers=content_headers(find_user(handle))) if request.method == 'POST': """ deduplicates requests, and adds them to the database. in some cases (e.g. Follow requests) it automatically responds, pending fuller API and UI implementation """ print('inbox post') u = find_user(handle) r = core.ASObj(request.get_json()) if 'Create' in r.types: # this needs more stuff, like creating a user if necessary if mongo.db.posts.find({'@id': r['@id']}) is not None: try: r.update(dict(origin=request.environ['HTTP_ORIGIN'])) mongo.db.posts.insert_one(r) return Response(status=201) except: return Response(status=500) elif 'Update' in r.types: if 'Actor' in r.types: time = get_time() r['updated'] = time try: mongo.db.users.find_one_and_replace({'@id': r['@id']}, r.json(), {'upsert': True}) return Response(status=201) except: return Response(status=500) elif ('Object' or 'Activity') in r.types: try: mongo.db.posts.find_one_and_replace({'@id': r['@id']}, r.json(), {'upsert': True}) return Response(status=201) except: return Response(status=500) elif 'Delete' in r.types: time = get_time() tombstone = vocab.Tombstone(r['@id'], published=r['published'], updated=time, deleted=time) if 'Actor' in r.types: try: mongo.db.users.find_one_and_replace({'@id': r['@id']}, tombstone.json()) return Response(status=201) except: return Response(status=500) elif ('Object' or 'Activity') in r.types: try: mongo.db.posts.find_one_and_replace({'@id': r['@id']}, tombstone.json()) return Response(status=201) except: return Response(status=500) return Response(status=501) elif 'Follow' in r.types: if u.get('followers_coll'): if u['followers_coll'].get('actor'): return 400 mongo.db.users.update_one( {'id': u['@id']}, {'$push': { 'followers_coll': r['actor'] }}, upsert=True) to = requests.get(r['actor'], headers=accept_headers(u)).json()['inbox'] accept = vocab.accept(to=to, object=r.get_json()).json() headers = content_headers(u) try: requests.post(to, json=accept, headers=headers) return Response(status=201) except: return Response(status=500) elif 'Accept' in r.types: print('received Accept') try: mongo.db.users.update_one( {'id': u['@id']}, {'$push': { 'following_coll': r['object']['actor'] }}, upsert=True) return Response(status=201) except: return Response(status=501) elif 'Reject' in r.types: return Response(status=200) elif 'Add' in r.types: return Response(status=501) elif 'Remove' in r.types: return Response(status=501) elif 'Like' in r.types: try: mongo.db.posts.update_one( {'id': r['object']}, {'$push': { 'object.liked_coll': r['actor'] }}, upsert=True) return Response(status=201) except: return Response(status=500) elif 'Announce' in r.types: try: mongo.db.posts.update_one( {'id': r['object']}, {'$push': { 'object.shared_coll': r['actor'] }}, upsert=True) return Response(status=201) except: return Response(status=500) elif 'Undo' in r.types: # this requires maybe a lot of stuff for implementing? # i'll think about it later return Response(status=501) else: print('other type') print(r) abort(400)
def feed(handle): if request.method == 'GET': """ per AP spec, returns a reverse-chronological OrderedCollection of items in the outbox, pending privacy settings """ print('feed get') u = find_user(handle) items = list( mongo.db.posts.find({ 'object.attributedTo': u['@id'] }, { '_id': False }).sort('published', -1)) resp = vocab.OrderedCollection(u['outbox'], totalItems=len(items), orderedItems=items) return Response(json.dumps(resp.json()), headers=content_headers(u)) if request.method == 'POST': """ adds objects that it receives to mongodb and sends them along to appropriate Actor inboxes """ r = core.ASObj(request.get_json(), vocab.BasicEnv) u = find_user(handle) # if it's a note it turns it into a Create object if 'Note' in r.types: obj = r.get_json() r = vocab.Create(obj['@id'] + '/activity', actor=u['@id'], published=obj['published'], to=obj['to'], bto=obj['bto'], cc=obj['cc'], bcc=obj['bcc'], audience=obj['audience'], obj=obj) if 'Create' in r.types: mongo.db.users.update({'acct': u['acct']}, {'$inc': { 'metrics.post_count': 1 }}) elif 'Update' in r.types: return Response(status=501) elif 'Delete' in r.types: return Response(status=501) elif 'Follow' in r.types: return Response(status=501) elif 'Accept' in r.types: return Response(status=501) elif 'Reject' in r.types: return Response(status=501) elif 'Add' in r.types: return Response(status=501) elif 'Remove' in r.types: return Response(status=501) elif 'Like' in r.types: if u['acct'] not in mongo.db.posts.find( {'@id': r['object']['@id']})['likes']: try: mongo.db.posts.update({'@id': r['object']['@id']}, {'$push': { 'likes': u['acct'] }}) return Response(status=201) except: return Response(status=500) elif 'Announce' in r.types: return Response(status=501) elif 'Undo' in r.types: return Response(status=501) recipients = [] r = r.json() for group in ['to', 'bto', 'cc', 'bcc', 'audience']: addresses = r.get(group, []) recipients.extend(addresses) for address in addresses: requests.post(address, json=r, headers=content_headers(u)) try: mongo.db.posts.insert_one(r) return Response(status=201) except: return Response(status=500)