예제 #1
0
class Subscription(CachingModel):
    """this represents a topic, usually a stream, that a subscriber
     (usually an inbox) would like to receive updates to
  """
    topic = models.StringProperty()  # ref - the stream being subscribed to
    subscriber = models.StringProperty()  # ref - the subscriber (actor)
    target = models.StringProperty()  # where to dump this
    state = models.StringProperty()  # The status of remote subs, see XEP-0060
    # sect 4.2. The 'pending' state is ignored if
    # the target of the subscription is used.
    # The design is for performance: on public
    # entries
    # the state is ignored and listing the
    # subscriptions is a single query; for
    # contacts-only entries the state is used but
    # it is also kept up-to-date regarding buddy
    # relationships, so a single query for
    # state='subscribed' can again be used.
    extra = properties.DictProperty()  # holds a bunch of stuff
    created_at = properties.DateTimeProperty(auto_now_add=True)
    # for ordering someday
    key_template = '%(topic)s/%(target)s'

    def is_subscribed(self):
        # LEGACY COMPAT: the 'or' here is for legacy compat
        return (self.state == 'subscribed' or self.state == None)
예제 #2
0
class Presence(CachingModel):
    """This represents all the presence data for an actor at a moment in time.
  extra:
    status - string; message (like an "away message")
    location - string; TODO(tyler): Consider gps / cell / structured data
    availability - string; TODO(tyler): Define structure
  """
    actor = models.StringProperty()  # The actor whose presence this is
    updated_at = properties.DateTimeProperty(auto_now_add=True)
    # The moment we got the update
    uuid = models.StringProperty()
    extra = properties.DictProperty()  # All the rich presence
예제 #3
0
class Task(CachingModel):
  actor = models.StringProperty()     # ref - the owner of this queue item
  action = models.StringProperty()    # api call we are iterating through
  action_id = models.StringProperty() # unique identifier for this queue item
  args = models.StringListProperty()  # *args
  kw = properties.DictProperty()      # *kw
  expire = properties.DateTimeProperty()
                                      # when our lock will expire
  progress = models.StringProperty()  # a string representing the offset to 
                                      # which we've progressed so far
  created_at = properties.DateTimeProperty(auto_now_add=True)
  
  key_template = 'task/%(actor)s/%(action)s/%(action_id)s'
예제 #4
0
class Stream(DeletedMarkerModel):
    """
  extra:  see api.stream_create()
  """
    owner = models.StringProperty()  # ref
    title = models.StringProperty()
    type = models.StringProperty()
    slug = models.StringProperty()
    read = models.IntegerProperty()  # TODO: document this
    write = models.IntegerProperty()
    extra = properties.DictProperty()

    key_template = 'stream/%(owner)s/%(slug)s'

    def is_public(self):
        return self.read == PRIVACY_PUBLIC

    def is_restricted(self):
        return self.read == PRIVACY_CONTACTS

    def keyname(self):
        """Returns the key name"""
        return self.key().name()
예제 #5
0
class StreamEntry(DeletedMarkerModel):
    """
  extra :
    title - 
    location - 
    icon - 
    content - 
    entry_stream - 
    entry_stream_type - 
    entry_title - 
    entry_uuid - 
    comment_count - 
  """
    stream = models.StringProperty()  # ref - the stream this belongs to
    owner = models.StringProperty()  # ref - the actor who owns the stream
    actor = models.StringProperty()  # ref - the actor who wrote this
    entry = models.StringProperty()  # ref - the parent of this,
    #       should it be a comment
    uuid = models.StringProperty()
    created_at = properties.DateTimeProperty(auto_now_add=True)
    extra = properties.DictProperty()

    key_template = '%(stream)s/%(uuid)s'

    def url(self, with_anchor=True, request=None, mobile=False):
        if self.entry:
            # TODO bad?
            slug = self.entry.split("/")[-1]
            anchor = "#c-%s" % self.uuid
        else:
            # TODO(termie): add slug property
            slug = self.uuid
            anchor = ""
        path = "/%s/%s" % ('presence', slug)
        if with_anchor:
            path = "%s%s" % (path, anchor)
        return actor_url(_get_actor_urlnick_from_nick(self.owner),
                         _get_actor_type_from_nick(self.owner),
                         path=path,
                         request=request,
                         mobile=mobile)

    def keyname(self):
        """Returns the key name"""
        return self.key().name()

    def title(self):
        """ build a title for this entry, for a presence entry it will just be
    the title, but for a comment it will look like:

    Comment from [commenter nick] on [entry title] by [nick]

    Comment from [commenter nick] on [entry title] by [nick] to #[channel name]
    """

        if not self.is_comment():
            return self.extra.get('title')

        template = "Comment from %(actor)s on %(entry_title)s by %(entry_actor)s"
        actor = _get_actor_urlnick_from_nick(self.actor)
        entry_title = self.extra.get('entry_title')
        entry_actor = _get_actor_urlnick_from_nick(
            self.extra.get('entry_actor'))
        entry_owner_nick = util.get_user_from_topic(self.entry)
        entry_type = _get_actor_type_from_nick(entry_owner_nick)

        v = {
            'actor': actor,
            'entry_title': entry_title,
            'entry_actor': entry_actor,
        }

        if entry_type == 'channel':
            template += ' to #%(channel)s'
            channel = _get_actor_urlnick_from_nick(entry_owner_nick)
            v['channel'] = channel

        return template % v

    def is_comment(self):
        return (self.entry != None)

    def is_channel(self):
        return self.owner.startswith('#')

    def entry_actor(self):
        if self.entry:
            return util.get_user_from_topic(self.entry)
        return None
예제 #6
0
class Actor(DeletedMarkerModel):
    """
  extra:
    contact_count - int; number of contacts
    follower_count - int; number of followers
    icon - string; avatar path
    bg_image - string; image for background (takes precedence over bg_color)
    bg_color - string; color for background
    bg_repeat - whether to repeat bg_image
    description [channel] - string; Channel description
    external_url [channel] - string; External url related ot channel
    member_count [channel] - int; number of members
    admin_count [channel] - int; number of admins
    email_notify [user] - boolean; does the user want email notifications?
    given_name [user] - string; First name
    family_name [user] - string; Last Name
    comments_hide [user] - boolean; Whether comments should be hidden on 
                             overview
  """
    nick = models.StringProperty()
    # the appengine datastore is case-sensitive whereas human brains are not,
    # Paul is not different from paul to regular people so we need a way to
    # prevent duplicate names from cropping up, this adds an additional indexed
    # property to support that
    normalized_nick = models.StringProperty()
    password = models.StringProperty()
    privacy = models.IntegerProperty()
    type = models.StringProperty()
    extra = properties.DictProperty()
    # avatar_updated_at is used by DJabberd to get a list of changed avatar. We
    # set the default to a date before the launch so that initial avatars have an
    # updated_at that is less than any real changes.
    avatar_updated_at = properties.DateTimeProperty(
        default=datetime.datetime(2009, 01, 01))

    key_template = 'actor/%(nick)s'

    def url(self, path="", request=None, mobile=False):
        """ returns a url, with optional path appended
    
    NOTE: if appending a path, it should start with '/'
    """
        return actor_url(_get_actor_urlnick_from_nick(self.nick),
                         self.type,
                         path=path,
                         request=request,
                         mobile=mobile)

    def shortnick(self):
        return _get_actor_urlnick_from_nick(self.nick)

    def display_nick(self):
        return self.nick.split("@")[0]
        return _get_actor_urlnick_from_nick(self.nick)

    def to_api(self):
        rv = super(Actor, self).to_api()
        del rv['password']
        del rv['normalized_nick']
        extra = {}
        for k, v in rv['extra'].iteritems():
            if k in ACTOR_ALLOWED_EXTRA:
                extra[k] = v
        rv['extra'] = extra
        return rv

    def to_api_limited(self):
        rv = self.to_api()
        extra = {}
        for k, v in rv['extra'].iteritems():
            if k in ACTOR_LIMITED_EXTRA:
                extra[k] = v
        rv['extra'] = extra
        return rv

    def is_channel(self):
        return self.type == 'channel'

    def is_public(self):
        return self.privacy == PRIVACY_PUBLIC

    def is_restricted(self):
        return self.privacy == PRIVACY_CONTACTS

    def __repr__(self):
        # Get all properties, but not directly as property objects, because
        # constructor requires values to be passed in.
        d = dict([(k, self.__getattribute__(k))
                  for k in self.properties().keys()])
        return "%s(**%s)" % (self.__class__.__name__, repr(d))