Ejemplo n.º 1
0
    def broadcast(self, message):
        """
        Sends a broadcast message to all online followers. It will resolve
        each guid before sending the broadcast. Messages must be less than
        140 characters. Returns the number of followers the broadcast reached.
        """

        if len(message) > 140:
            return defer.succeed(0)

        def send(nodes):
            def how_many_reached(responses):
                count = 0
                for resp in responses:
                    if resp[1][0] and resp[1][1][0] == "True":
                        count += 1
                return count

            ds = []
            signature = self.signing_key.sign(str(message))[:64]
            for n in nodes:
                if n[1] is not None:
                    ds.append(
                        self.protocol.callBroadcast(n[1], message, signature))
            return defer.DeferredList(ds).addCallback(how_many_reached)

        dl = []
        f = objects.Followers()
        f.ParseFromString(self.db.FollowData().get_followers())
        for follower in f.followers:
            dl.append(self.kserver.resolve(follower.guid))
        self.log.info("broadcasting %s to followers" % message)
        return defer.DeferredList(dl).addCallback(send)
Ejemplo n.º 2
0
 def get_response(response):
     # Verify the signature on the response
     f = objects.Followers()
     try:
         pubkey = node_to_ask.signed_pubkey[64:]
         verify_key = nacl.signing.VerifyKey(pubkey)
         verify_key.verify(response[1][1] + response[1][0])
         f.ParseFromString(response[1][0])
     except Exception:
         return None
     # Verify the signature and guid of each follower.
     for follower in f.followers:
         try:
             v_key = nacl.signing.VerifyKey(follower.signed_pubkey[64:])
             signature = follower.signature
             follower.ClearField("signature")
             v_key.verify(follower.SerializeToString(), signature)
             h = nacl.hash.sha512(follower.signed_pubkey)
             pow_hash = h[64:128]
             if int(pow_hash[:6],
                    16) >= 50 or follower.guid.encode("hex") != h[:40]:
                 raise Exception('Invalid GUID')
             if follower.following != node_to_ask.id:
                 raise Exception('Invalid follower')
         except Exception:
             f.followers.remove(follower)
     return f
Ejemplo n.º 3
0
    def get_followers(self, request):
        def parse_followers(followers):
            if followers is not None:
                response = {"followers": []}
                for f in followers.followers:
                    follower_json = {
                        "guid": f.guid.encode("hex"),
                        "handle": f.metadata.handle,
                        "name": f.metadata.name,
                        "avatar_hash": f.metadata.avatar_hash.encode("hex"),
                        "nsfw": f.metadata.nsfw
                    }
                    response["followers"].append(follower_json)
                request.setHeader('content-type', "application/json")
                request.write(json.dumps(response, indent=4))
                request.finish()
            else:
                request.write(json.dumps({}))
                request.finish()

        if "guid" in request.args:

            def get_node(node):
                if node is not None:
                    self.mserver.get_followers(node).addCallback(
                        parse_followers)
                else:
                    request.write(json.dumps({}))
                    request.finish()

            self.kserver.resolve(unhexlify(
                request.args["guid"][0])).addCallback(get_node)
        else:
            ser = self.db.FollowData().get_followers()
            if ser is not None:
                f = objects.Followers()
                f.ParseFromString(ser)
                parse_followers(f)
            else:
                parse_followers(None)
        return server.NOT_DONE_YET
Ejemplo n.º 4
0
def migrate(database_path):
    print "migrating to db version 3"
    conn = sqlite3.connect(database_path)
    conn.text_factory = str
    cursor = conn.cursor()
    # read followers from db
    cursor.execute('''SELECT serializedFollowers FROM followers WHERE id=1''')
    followers = cursor.fetchone()

    # delete follower table
    cursor.execute('''DROP TABLE followers''')

    # create new table
    cursor.execute(
        '''CREATE TABLE followers(guid TEXT UNIQUE, serializedFollower TEXT)'''
    )
    cursor.execute(
        '''CREATE INDEX index_followers ON followers(serializedFollower);''')

    # write followers back into db

    if followers is not None:
        f = objects.Followers()
        f.ParseFromString(followers[0])
        for follower in f.followers:
            cursor.execute(
                '''INSERT INTO followers(guid, serializedFollower) VALUES (?,?)''',
                (
                    follower.guid.encode("hex"),
                    follower.SerializeToString().encode("hex"),
                ))

    # update version
    cursor.execute('''PRAGMA user_version = 3''')
    conn.commit()
    conn.close()