def create(endpoint, username):
    ns = Namespace(username)

    for name, desc in (
        (HACKERNEWS_TOP100_TAG_NAME, 'Hacker News top 100 Tweeter.'),
        (HACKERNEWS_RATIO_TAG_NAME, 'Hacker News top Tweeter followers %.'),
        ):
        d = ns.createTag(endpoint, name, desc, False)
        addCallbacks(d, 'Created tag %r.' % name)
        yield d
예제 #2
0
파일: ftwitter.py 프로젝트: jkakar/Tickery
def addUserByScreenname(cache, endpoint, userJob):
    # We must at least create the user.
    userJob.workToDo = WORK_TO_CREATE_A_FRIEND
    userJob.workDone = 0
    screenname = userJob.screenname
    log.msg('Adding user %r' % screenname)

    def catchUnknownScreenname(fail):
        fail.trap(error.Error)
        if int(fail.value.status) != http.NOT_FOUND:
            return fail
        return defer.fail(UnknownScreenname(screenname))

    def catchProtectedScreenname(fail):
        fail.trap(error.Error)
        if int(fail.value.status) != http.UNAUTHORIZED:
            return fail
        return defer.fail(ProtectedScreenname(screenname))

    d = cache.friendsIdCache[screenname]
    d.addErrback(catchUnknownScreenname)
    d.addErrback(catchProtectedScreenname)
    friendUids = yield d
    log.msg('Got %d friends for user %r' % (len(friendUids), screenname))

    # Make a tag for this new user to mark their friends with.
    ns = Namespace(TWITTER_USERNAME, TWITTER_FRIENDS_NAMESPACE_NAME)
    d = ns.createTag(endpoint, screenname.lower(),
        "A tag used to mark %s's Twitter friends." % screenname, False)
    # TODO: check the X-FluidDB-Error-Class header in the errback to make
    # sure it really got a namespace already exists error.
    d.addErrback(_ignoreHTTPStatus, http.PRECONDITION_FAILED)
    yield d
    # Note: the call to createTag (above) will return a Tag instance when
    # txFluidDB gets fixed.
    friendTag = Tag(TWITTER_USERNAME, TWITTER_FRIENDS_NAMESPACE_NAME,
                    screenname.lower())
    friendTagPath = friendTag.getPath()
    log.msg('Created Twitter friends tag %s' % friendTagPath)

    def _madeUserDone(userObject, user):
        userJob.workDone += WORK_TO_CREATE_A_FRIEND
        cache.extraTwitterTagsPool.add(
            addExtraTwitterTags(endpoint, userObject, user))
        return userObject

    def _madeUserErr(failure):
        userJob.workDone += WORK_TO_CREATE_A_FRIEND
        return failure

    def _tagFriendDone():
        userJob.workDone += WORK_TO_TAG_A_FRIEND

    def makeUser(user, thisIndex=None, totalToAdd=None):
        newName = user['screen_name']
        if thisIndex is not None:
            log.msg('Making user %r, friend %d/%d of %r.' %
                    (newName, thisIndex, totalToAdd, screenname))
        else:
            log.msg('Making user %r.' % newName)
        d = cache.oidUidScreennameCache.objectByUid(user['id'], newName)
        d.addCallbacks(_madeUserDone, _madeUserErr, callbackArgs=(user,))
        return d

    def _ignore404uid(fail, uid):
        fail.trap(error.Error)
        if int(fail.value.status) == http.NOT_FOUND:
            log.msg('Twitter uid %d is no longer found (404). Ignoring.' % uid)
            cache.userCache.removeUid(uid)
            cache.oidUidScreennameCache.removeUid(uid)
        else:
            log.msg('Failure fetching Twitter uid %d:' % uid)
            log.err(fail)

    def makeCreateUserJobs(friendsToAdd):
        nToAdd = len(friendsToAdd)
        for i, friendUid in enumerate(friendsToAdd):
            if userJob.canceled():
                log.msg('Detected cancelation of screenname %r.' % screenname)
                raise StopIteration
            d = cache.userCache.userByUid(friendUid)
            d.addCallbacks(makeUser, _ignore404uid,
                           callbackArgs=(i + 1, nToAdd),
                           errbackArgs=(friendUid,))
            yield d

    @defer.inlineCallbacks
    def addFriend(friendName, thisIndex, totalToAdd):
        log.msg('About to mark user %r as a friend %d/%d of %r.' %
                (friendName, thisIndex, totalToAdd, screenname))
        d = cache.oidUidScreennameCache.objectIdByScreenname(friendName)
        d.addErrback(log.err)
        objectId = yield d
        log.msg('Marking user %r as a friend %d/%d of %r' %
                (friendName, thisIndex, totalToAdd, screenname))
        if objectId is not None:
            o = Object(objectId)
            yield o.set(endpoint, friendTag, None)
            log.msg('Marked user %r as a friend %d/%d of %r' %
                    (friendName, thisIndex, totalToAdd, screenname))
        _tagFriendDone()

    def makeTagFriendsJobs():
        nFriendUids = len(friendUids)
        for i, friendUid in enumerate(friendUids):
            if userJob.canceled():
                log.msg('Detected cancelation of screenname %r.' % screenname)
                raise StopIteration
            d = cache.userCache.screennameByUid(friendUid)
            d.addCallbacks(addFriend, _ignore404uid,
                           callbackArgs=(i + 1, nFriendUids),
                           errbackArgs=(friendUid,))
            yield d

    # Get screename's id and add them as a Twitter user.
    user = yield cache.userCache.userByScreenname(screenname)
    userObject = yield makeUser(user)
    log.msg('User object for %r is %r' % (screenname, userObject))

    # Add the amount of work will it be to tag all friends.
    userJob.workToDo += (len(friendUids) * WORK_TO_TAG_A_FRIEND)

    # Figure out the work will it be to create whatever friends are needed.
    friendsToAdd = [fid for fid in friendUids
                    if not cache.oidUidScreennameCache.knownUid(fid)]
    nFriendsToAdd = len(friendsToAdd)
    log.msg('Must create %d new user objects as friends of %r.' %
            (nFriendsToAdd, screenname))

    if nFriendsToAdd and not userJob.canceled():
        userJob.workToDo += (nFriendsToAdd * WORK_TO_CREATE_A_FRIEND)
        start = time.time()

        # Create Fluidinfo objects for all the friends that we don't yet know
        # about.
        jobs = makeCreateUserJobs(friendsToAdd)
        deferreds = []
        coop = task.Cooperator()
        for i in xrange(MAX_SIMULTANEOUS_REQUESTS):
            d = coop.coiterate(jobs)
            d.addErrback(log.err)
            deferreds.append(d)
        yield defer.DeferredList(deferreds)

        if not userJob.canceled():
            elapsed = time.time() - start
            log.msg('Created %d new friend (of %r) objects in %.2f seconds. '
                    'Mean %.4f' % (nFriendsToAdd, screenname, elapsed,
                                   float(elapsed / nFriendsToAdd)))

    if friendUids and not userJob.canceled():
        # Tag all friends.
        start = time.time()
        jobs = makeTagFriendsJobs()
        deferreds = []
        coop = task.Cooperator()
        for i in xrange(MAX_SIMULTANEOUS_REQUESTS):
            d = coop.coiterate(jobs)
            d.addErrback(log.err)
            deferreds.append(d)
        log.msg('About to yield friend tagging DL for %r' % screenname)
        yield defer.DeferredList(deferreds)
        log.msg('Friend tagging DL finished for %r' % screenname)

        if not userJob.canceled():
            elapsed = time.time() - start
            nFriendsUids = len(friendUids)
            log.msg('Tagged %d objects as being a friend of %r in %.2f '
                    'seconds. Mean = %.4f' % (nFriendsUids, screenname,
                    elapsed, float(elapsed / nFriendsUids)))

    if userJob.canceled():
        log.msg('Canceled addUserByScreenname for %r.' % screenname)
        raise Canceled(screenname)
    else:
        # Add the updated tag to the user's object.
        log.msg('Adding updated tag to user object for %r' % screenname)
        yield userObject.set(endpoint, updatedTag, int(time.time()))
        log.msg('Successfully added screenname %r.' % (screenname,))

    userJob.workDone = userJob.workToDo