class Person(BaseModel): # Details from row with subid 1 (i.e. most recent updates) name = ndb.StringProperty() country = ndb.KeyProperty(kind=Country) gender = ndb.StringProperty() # The person's state, if they're a US resident. This isn't computed during # the database import. state = ndb.KeyProperty(kind=State) def ParseFromDict(self, row): self.name = row['name'] self.country = ndb.Key(Country, row['countryId']) self.gender = row['gender'] @staticmethod def Filter(): return lambda row: int(row['subid']) == 1 @staticmethod def ColumnsUsed(): return ['name', 'countryId', 'gender'] def GetWCALink(self): return 'https://worldcubeassociation.org/persons/%s' % self.key.id()
class RankBase(BaseModel): person = ndb.KeyProperty(kind=Person) event = ndb.KeyProperty(kind=Event) best = ndb.IntegerProperty() state = ndb.ComputedProperty(lambda self: self.GetState()) def GetState(self): if not self.person or not self.person.get(): return None return self.person.get().state @staticmethod def GetId(row): return '%s_%s' % (row['personId'], row['eventId']) def ParseFromDict(self, row): self.person = ndb.Key(Person, row['personId']) self.event = ndb.Key(Event, row['eventId']) self.best = int(row['best']) @staticmethod def ColumnsUsed(): return ['personId', 'eventId', 'best'] def ObjectsToGet(self): return [self.person]
class Championship(ndb.Model): national_championship = ndb.BooleanProperty() region = ndb.KeyProperty(kind=Region) state = ndb.KeyProperty(kind=State) competition = ndb.KeyProperty(kind=Competition) year = ndb.ComputedProperty(lambda self: self.competition.get().year) residency_deadline = ndb.DateTimeProperty() residency_timezone = ndb.StringProperty() @staticmethod def NationalsId(year): return str(year) @staticmethod def RegionalsId(year, region): return '%s_%d' % (region.key.id(), year) @staticmethod def StateChampionshipId(year, state): return '%s_%d' % (state.key.id(), year) def GetEligibleStateKeys(self): if self.state: return [self.state] if self.region: return State.query(State.region == self.region).fetch( keys_only=True) # National championships are not based on residence, they're based on # citizenship. return None
class Album(ndb.Model): data_set = ndb.StringProperty() genre = ndb.KeyProperty(kind=Genre) artist = ndb.KeyProperty(kind=Artist) period = ndb.KeyProperty(kind=Period) album_name = ndb.StringProperty() created = ndb.DateTimeProperty(auto_now_add=True)
class Love(ndb.Model): """Models an instance of sent love.""" message = ndb.TextProperty() recipient_key = ndb.KeyProperty(kind=Employee) secret = ndb.BooleanProperty(default=False) sender_key = ndb.KeyProperty(kind=Employee) timestamp = ndb.DateTimeProperty(auto_now_add=True) @property def seconds_since_epoch(self): return int(mktime(self.timestamp.timetuple()))
class ChannelUrl(ndb.Model): # Reference to Channel & Url channel = ndb.KeyProperty(kind=Channel) url = ndb.KeyProperty(kind=Url) # System stuff idate = ndb.DateTimeProperty(auto_now_add=True) udate = ndb.DateTimeProperty(auto_now=True) def rating(self): value = 0 rates = Rate.query(Rate.channelurl == self.key) for rate in rates: value = value + rate.value return value def extras(self, plain=False): xtra = '' extras = Extra.query(Extra.channelurl == self.key) for extra in extras: if extra.comment: xtra = xtra + ' ' + extra.comment if extra.tag: if plain: xtra = xtra + extra.tag elif extra.tag == 'WTF': xtra = xtra + ' <span class="label label-danger">' + extra.tag + '</span>' elif extra.tag == 'NSFW': xtra = xtra + ' <span class="label label-warning">' + extra.tag + '</span>' else: xtra = xtra + ' <span class="label label-primary">' + extra.tag + '</span>' if extra.related: if plain: xtra = xtra + extra.related else: xtra = xtra + ' <span class="label label-info">' + extra.related + '</span>' return xtra.strip() def posts(self): chl = self.channel.get() msg = '' msgs = [] posts = Post.query(Post.channelurl == self.key) for post in posts: msgs.append('%s/%s @ %s' % (post.user, chl.name, post.date)) return ', '.join(msgs) def __unicode__(self): return unicode(self.key.id()) def __str__(self): return unicode(self).encode('utf-8')
class Champion(ndb.Model): championship = ndb.KeyProperty(kind=Championship) event = ndb.KeyProperty(kind=Event) champions = ndb.KeyProperty(kind=Result, repeated=True) national_champion = ndb.ComputedProperty( lambda e: e.championship.get().national_championship) region = ndb.ComputedProperty(lambda e: e.championship.get().region) state = ndb.ComputedProperty(lambda e: e.championship.get().state) year = ndb.ComputedProperty(lambda e: e.championship.get().year) @staticmethod def Id(championship_id, event_id): return '%s_%s' % (championship_id, event_id)
class ArticleEntity(ndb.Model): @classmethod def _get_kind(cls): return 'BlogPost' slug = ndb.StringProperty() title = ndb.StringProperty() content = ndb.StringProperty() summary = ndb.StringProperty(default="") is_published = ndb.BooleanProperty(default=False) created_date = ndb.DateTimeProperty(auto_now_add=True) modified_date = ndb.DateTimeProperty(auto_now=True) published_date = ndb.DateTimeProperty(indexed=True) categories = ndb.KeyProperty(repeated=True) primary_media_image = ndb.KeyProperty(kind=MediaEntity)
class Subscription(ndb.Model): """Models a webhook subscription.""" request_method = ndb.StringProperty(required=True, default='post') request_format = ndb.StringProperty(required=True, default=CONTENT_TYPE_JSON) request_url = ndb.StringProperty(required=True) active = ndb.BooleanProperty(required=True, default=False) event = ndb.StringProperty(required=True) secret = ndb.StringProperty(required=True) timestamp = ndb.DateTimeProperty(auto_now_add=True) owner_key = ndb.KeyProperty(kind=Employee) @classmethod def create_from_dict(cls, d, persist=True): new_subscription = cls() new_subscription.owner_key = Employee.get_current_employee().key new_subscription.request_url = d['request_url'] new_subscription.active = d['active'] new_subscription.event = d['event'] new_subscription.secret = d['secret'] if persist is True: new_subscription.put() return new_subscription @classmethod def all_active_for_event(cls, event): return cls.query( cls.active == True, # noqa cls.event == event, )
class Extra(ndb.Model): user = ndb.StringProperty() related = ndb.StringProperty() tag = ndb.StringProperty() comment = ndb.StringProperty() # Reference to Post channelurl = ndb.KeyProperty(kind=ChannelUrl) # System stuff idate = ndb.DateTimeProperty(auto_now_add=True) udate = ndb.DateTimeProperty(auto_now=True) def __unicode__(self): retval = '' if self.comment: retval += ' ' + self.comment if self.tag: retval += ' <a href="/url/tag/' + self.tag + '/"><span class="label ' if self.tag == 'WTF': retval += 'label-danger' elif self.tag == 'NSFW': retval += 'label-warning' else: retval += 'label-primary' retval += '">' + self.tag + '</span></a>' if self.related: retval += ' <a href="/url/view/' + self.related + '/"><span class="label label-info">' + self.related + '</span></a>' return retval.strip() def __str__(self): return unicode(self).encode('utf-8')
class Site(ndb.Model): """Defines a site.""" name = ndb.StringProperty() url = ndb.StringProperty() created_by = ndb.KeyProperty(kind=User) last_edited_by = ndb.KeyProperty(kind=User) created_on = ndb.DateTimeProperty(auto_now_add=True) last_modified_on = ndb.DateTimeProperty(auto_now=True) @classmethod def to_compact(cls, site): return { 'name': site.name, 'url': site.url, 'id': site.key.urlsafe().decode('utf-8'), }
class Publish(ndb.Model): """A comment, like, repost, or RSVP published into a silo. Child of a :class:`PublishedPage` entity. """ STATUSES = ('new', 'complete', 'failed', 'deleted') # Turn off instance and memcache caching. See Source for details. _use_cache = False _use_memcache = False type = ndb.StringProperty(choices=PUBLISH_TYPES) status = ndb.StringProperty(choices=STATUSES, default='new') source = ndb.KeyProperty() html = ndb.TextProperty() # raw HTML fetched from source published = ndb.JsonProperty(compressed=True) created = ndb.DateTimeProperty(auto_now_add=True) updated = ndb.DateTimeProperty(auto_now=True) def type_label(self): """Returns silo-specific string type, e.g. 'favorite' instead of 'like'.""" for cls in sources.values(): # global if cls.__name__ == self.source.kind(): return cls.TYPE_LABELS.get(self.type, self.type) return self.type
class MastodonAuth(BaseAuth): """An authenticated Mastodon user. Provides methods that return information about this user and make OAuth-signed requests to the Mastodon REST API. Stores OAuth credentials in the datastore. See models.BaseAuth for usage details. Key name is the fully qualified actor address, ie @[email protected]. Implements get() and post() but not urlopen() or api(). """ app = ndb.KeyProperty() access_token_str = ndb.TextProperty(required=True) user_json = ndb.TextProperty() def site_name(self): return 'Mastodon' def user_display_name(self): """Returns the user's full ActivityPub address, eg @[email protected].""" return self.key.id() def instance(self): """Returns the instance base URL, eg https://mastodon.social/.""" return self.app.get().instance def username(self): """Returns the user's username, eg ryan.""" return json_loads(self.user_json).get('username') def user_id(self): """Returns the user's id, eg 123.""" return json_loads(self.user_json).get('id') def access_token(self): """Returns the OAuth access token string.""" return self.access_token_str def get(self, *args, **kwargs): """Wraps requests.get() and adds instance base URL and Bearer token header.""" url = urljoin(self.instance(), args[0]) return self._requests_call(util.requests_get, url, *args[1:], **kwargs) def post(self, *args, **kwargs): """Wraps requests.post() and adds the Bearer token header.""" return self._requests_call(util.requests_post, *args, **kwargs) def _requests_call(self, fn, *args, **kwargs): headers = kwargs.setdefault('headers', {}) headers['Authorization'] = 'Bearer ' + self.access_token_str resp = fn(*args, **kwargs) try: resp.raise_for_status() except BaseException as e: util.interpret_http_exception(e) raise return resp
class LastUpdatedPicture(StringIdModel): """Stores the last user in a given silo that we updated profile picture for. Key id is the silo's SHORT_NAME. """ last = ndb.KeyProperty() created = ndb.DateTimeProperty(auto_now_add=True, required=True, tzinfo=timezone.utc) updated = ndb.DateTimeProperty(auto_now=True, tzinfo=timezone.utc)
class Activity(StringIdModel): """An activity with responses to be propagated. The key name is the activity id as a tag URI. Currently only used for posts sent to us by the browser extension. """ source = ndb.KeyProperty() created = ndb.DateTimeProperty(auto_now_add=True) updated = ndb.DateTimeProperty(auto_now=True) activity_json = ndb.TextProperty()
class Book(ndb.Model): isbn = ndb.IntegerProperty() name = ndb.StringProperty() author = ndb.StringProperty() taken = ndb.BooleanProperty(default=False) taken_by = ndb.KeyProperty() def get_dict(self): data = {**self.to_dict(), **{'id': self.key.id()}} if 'taken_by' in data and data['taken_by'] is not None: data['taken_by'] = data['taken_by'].id() return data
class Domain(StringIdModel): """A domain owned by a user. Ownership is proven via IndieAuth. Supports secret tokens associated with each domain. Clients can include a token with requests that operate on a given domain, eg sending posts and responses from the browser extension. Key id is the string domain, eg 'example.com'. """ tokens = ndb.StringProperty(repeated=True) auth = ndb.KeyProperty(IndieAuth) created = ndb.DateTimeProperty(auto_now_add=True, tzinfo=timezone.utc) updated = ndb.DateTimeProperty(auto_now=True, tzinfo=timezone.utc)
class Country(BaseModel): name = ndb.StringProperty() continent = ndb.KeyProperty(kind=Continent) iso2 = ndb.StringProperty() def ParseFromDict(self, row): self.name = row['name'] self.continent = ndb.Key(Continent, row['continentId']) self.iso2 = row['iso2'] @staticmethod def ColumnsUsed(): return ['name', 'continentId', 'iso2']
class User(ndb.Model): wca_person = ndb.KeyProperty(kind=Person) name = ndb.StringProperty() email = ndb.StringProperty() roles = ndb.StringProperty(repeated=True) city = ndb.StringProperty() state = ndb.KeyProperty(kind=State) latitude = ndb.IntegerProperty() longitude = ndb.IntegerProperty() last_login = ndb.DateTimeProperty() updates = ndb.StructuredProperty(UserLocationUpdate, repeated=True) regional_eligibilities = ndb.StructuredProperty(RegionalChampionshipEligibility, repeated=True) state_eligibilities = ndb.StructuredProperty(StateChampionshipEligibility, repeated=True) def HasAnyRole(self, roles): for role in self.roles: if role in roles: return True return False
class Rate(ndb.Model): user = ndb.StringProperty() value = ndb.IntegerProperty() # Reference to ChannelUrl channelurl = ndb.KeyProperty(kind=ChannelUrl) # System stuff idate = ndb.DateTimeProperty(auto_now_add=True) udate = ndb.DateTimeProperty(auto_now=True) def __unicode__(self): return '%s %+d' % (self.user, self.value) def __str__(self): return unicode(self).encode('utf-8')
class User(ndb.Model): name = ndb.StringProperty() password = ndb.StringProperty() member_id = ndb.KeyProperty() def get_dict(self): data = { **self.to_dict(), **{ 'id': self.key.id(), 'email': self.key.id() } } if 'member_id' in data and data['member_id'] is not None: data['member_id'] = data['member_id'].id() return data
class Post(ndb.Model): user = ndb.StringProperty() date = ndb.DateTimeProperty() # Reference to ChannelUrl channelurl = ndb.KeyProperty(kind=ChannelUrl) # System stuff idate = ndb.DateTimeProperty(auto_now_add=True) udate = ndb.DateTimeProperty(auto_now=True) def __unicode__(self): return unicode(self.key.id()) def __str__(self): return unicode(self).encode('utf-8')
class Panel(ndb.Model): count = ndb.IntegerProperty() nick = ndb.StringProperty() face = ndb.StringProperty() msg = ndb.StringProperty() rage = ndb.KeyProperty(kind=Rage) # System stuff idate = ndb.DateTimeProperty(auto_now_add=True) udate = ndb.DateTimeProperty(auto_now=True) def __unicode__(self): return self.msg def __str__(self): return unicode(self).encode('utf-8')
class State(ndb.Model): name = ndb.StringProperty() region = ndb.KeyProperty(kind=Region) is_state = ndb.BooleanProperty() @staticmethod def get_state(state_name): global states_by_name if state_name in states_by_name: return states_by_name[state_name] # Check if this is the state ID (two-letter abbreviation) maybe_state = State.get_by_id( state_name.replace('.', '').replace(' ', '').lower()) if not maybe_state: # Or maybe it's the name. maybe_state = State.query(State.name == state_name).get() if maybe_state: states_by_name[state_name] = maybe_state return maybe_state
class Report(ndb.Model): """Defines a report for a given site.""" site = ndb.KeyProperty(kind=Site) created_on = ndb.DateTimeProperty(auto_now_add=True) accessibility_score = ndb.FloatProperty() best_practices_score = ndb.FloatProperty() desktop_performance_score = ndb.FloatProperty() mobile_performance_score = ndb.FloatProperty() pwa_score = ndb.FloatProperty() seo_score = ndb.FloatProperty() @classmethod def to_dict(cls, report): return { 'accessibility_score': report.accessibility_score, 'best_practices_score': report.best_practices_score, 'desktop_performance_score': report.desktop_performance_score, 'mobile_performance_score': report.mobile_performance_score, 'seo_score': report.seo_score, 'pwa_score': report.pwa_score, }
class SomeKind(ndb.Model): foo = ndb.KeyProperty(kind="Whatevs") bar = ndb.KeyProperty(kind="Whatevs")
class Collab(ndb.Model): authors = ndb.KeyProperty(kind=Author, repeated=True)
class Book(ndb.Model): author = ndb.KeyProperty(kind=Author)
class SomeKind(ndb.Model): foo = ndb.StringProperty() ref = ndb.KeyProperty()
class SomeKind(ndb.Model): foo = ndb.KeyProperty()