Exemple #1
0
def dbm_denormalize_activity(asobj, db):
    as_json = asobj.json()

    def maybe_denormalize(key):
        val = as_json.get(key)
        # If there's no specific val,
        # it's not a string, or it's not in the database,
        # just leave it!
        if val is None or not isinstance(val, str) or val not in db:
            return

        # Otherwise, looks like that value *is* in the database... hey!
        # Let's pull it out and set it as the key.
        as_json[key] = db[val]

    maybe_denormalize("actor")
    maybe_denormalize("object")
    maybe_denormalize("target")
    return core.ASObj(as_json, asobj.env)
Exemple #2
0
    def maybe_normalize(key):
        val = as_json.get(key)
        # Skip if not a dictionary with a "@type"
        if not isinstance(val, dict) or not "@type" in val:
            return

        val_asobj = core.ASObj(val, asobj.env)
        # yup, time to normalize
        if asobj.env.is_astype(val_asobj, vocab.Object, inherit=True):
            # If there's no id, then okay, don't normalize
            if val_asobj.id is None:
                return

            if val_asobj.id not in db:
                # save to the database
                asobj.env.asobj_run_method(val_asobj, dbm_save_method, db)

            # and set the key to be the .id
            as_json[key] = val_asobj.id
Exemple #3
0
def dbm_fetch(id, db, env):
    return core.ASObj(db[id], env)
Exemple #4
0
 def fetch_asobj(self, env):
     return core.ASObj(self[id], env)
Exemple #5
0
def as_asobj(obj):
    return core.ASObj(obj)
Exemple #6
0
def feed_post(handle):
    """
    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:
        if r['object']['@type'] != 'Note':
            print(str(r))
            print('not a note')
            return Response(status=403)

        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']:
            mongo.db.posts.update({'@id': r['object']['@id']},
                                  {'$push': {
                                      'likes': u['acct']
                                  }})
    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)
Exemple #7
0
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)
Exemple #8
0
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)
Exemple #9
0
    "object": {
        "@type": "Note",
        "@id": "http://tsyesika.co.uk/chat/sup-yo/",
        "content": "Up for some root beer floats?"
    }
}

ROOT_BEER_NOTE_MIXED_ASOBJ = {
    "@type":
    "Create",
    "@id":
    "http://tsyesika.co.uk/act/foo-id-here/",
    "actor":
    core.ASObj({
        "@type": "Person",
        "@id": "http://tsyesika.co.uk/",
        "displayName": "Jessica Tallon"
    }),
    "to": [
        "acct:[email protected]", "acct:[email protected]",
        "acct:[email protected]"
    ],
    "object":
    core.ASObj({
        "@type": "Note",
        "@id": "http://tsyesika.co.uk/chat/sup-yo/",
        "content": "Up for some root beer floats?"
    })
}

ROOT_BEER_NOTE_VOCAB = vocab.Create(
Exemple #10
0
def mongo_fetch(id, db, env):
        return core.ASObj(db[id], env)