示例#1
0
class Body(Model):
    """
    A meeting body. This can be full council, a subcommittee, or "off-council" matters
    such as election debates.
    """

    id = fields.IDField()
    name = fields.TextField(required=True)
    description = fields.TextField()
    start_datetime = fields.DateTime(required=True)
    end_datetime = fields.DateTime()
    is_active = fields.BooleanField(required=True)
    external_source_id = fields.TextField()

    class Meta:
        ignore_none_field = False

    @classmethod
    def Example(cls) -> Model:
        body = cls()
        body.name = "Full Council"
        body.is_active = True
        body.start_datetime = datetime.utcnow()
        return body

    _PRIMARY_KEYS = ("name", )
    _INDEXES = ()
示例#2
0
class Role(Model):
    """
    A role is a person's job for a period of time in the city council. A person can
    (and generally does) have many roles. For example: a person has two terms as city
    council member for district four then a term as city council member for a citywide
    seat. Roles can also be tied to committee chairs. For example: a council member
    spends a term on the transportation committee and then spends a term on the finance
    committee.
    """

    title = fields.TextField(required=True)
    person_ref = fields.ReferenceField(Person, required=True)
    body_ref = fields.ReferenceField(Body)
    seat_ref = fields.ReferenceField(Seat, required=True)
    start_datetime = fields.DateTime(required=True)
    end_datetime = fields.DateTime()
    external_source_id = fields.TextField()

    @classmethod
    def Example(cls) -> Model:
        role = cls()
        role.title = "Council President"
        role.person_ref = Person.Example()
        role.body_ref = Body.Example()
        role.seat_ref = Seat.Example()
        role.start_datetime = datetime.utcnow()
        return role

    _PRIMARY_KEYS = ("title", "person_ref", "body_ref", "seat_ref")
    _INDEXES = ()
示例#3
0
class Transcript(Model):
    """
    A transcript is a document per-session.
    """

    session_ref = fields.ReferenceField(Session, required=True)
    file_ref = fields.ReferenceField(File, required=True)
    confidence = fields.NumberField(required=True)
    created = fields.DateTime(required=True)

    @classmethod
    def Example(cls) -> Model:
        transcript = cls()
        transcript.session_ref = Session.Example()
        transcript.file_ref = File.Example()
        transcript.confidence = 0.943
        transcript.created = datetime.utcnow()
        return transcript

    _PRIMARY_KEYS = ("session_ref", "file_ref")
    _INDEXES = (
        IndexedFieldSet((
            IndexedField(name="session_ref", order=Order.ASCENDING),
            IndexedField(name="created", order=Order.DESCENDING),
        )),
        IndexedFieldSet((
            IndexedField(name="session_ref", order=Order.ASCENDING),
            IndexedField(name="confidence", order=Order.DESCENDING),
        )),
    )
示例#4
0
class Session(Model):
    """
    A session is a working period for an event.
    For example, An event could have a morning and afternoon session.
    """

    event_ref = fields.ReferenceField(Event, required=True)
    session_datetime = fields.DateTime(required=True)
    session_index = fields.NumberField(required=True)
    video_uri = fields.TextField(required=True,
                                 validator=validators.resource_exists)
    caption_uri = fields.TextField(validator=validators.resource_exists)
    external_source_id = fields.TextField()

    @classmethod
    def Example(cls) -> Model:
        session = cls()
        session.event_ref = Event.Example()
        session.session_index = 0
        session.video_uri = (
            "https://video.seattle.gov/media/council/brief_072219_2011957V.mp4"
        )
        return session

    _PRIMARY_KEYS = ("event_ref", "video_uri")
    _INDEXES = ()
示例#5
0
class Event(Model):
    """
    An event can be a normally scheduled meeting, a special event such as a press
    conference or election debate, and, can be upcoming or historical.
    """

    id = fields.IDField()
    body_ref = fields.ReferenceField(Body, required=True, auto_load=False)
    event_datetime = fields.DateTime(required=True)
    static_thumbnail_ref = fields.ReferenceField(File, auto_load=False)
    hover_thumbnail_ref = fields.ReferenceField(File, auto_load=False)
    agenda_uri = fields.TextField(validator=validators.resource_exists)
    minutes_uri = fields.TextField(validator=validators.resource_exists)
    external_source_id = fields.TextField()

    class Meta:
        ignore_none_field = False

    def set_validator_kwargs(self, kwargs: Dict) -> None:
        field = fields.TextField(validator=validators.resource_exists,
                                 validator_kwargs=kwargs)

        field.contribute_to_model(Event, "agenda_uri")
        field.contribute_to_model(Event, "minutes_uri")

    @classmethod
    def Example(cls) -> Model:
        event = cls()
        event.body_ref = Body.Example()
        event.event_datetime = datetime.utcnow()
        event.agenda_uri = (
            "http://legistar2.granicus.com/seattle/meetings/2019/11/"
            "4169_A_Select_Budget_Committee_19-11-01_Committee_Agenda.pdf")
        event.minutes_uri = (
            "http://legistar2.granicus.com/seattle/meetings/2019/7/"
            "4041_M_Council_Briefing_19-07-22_Committee_Minutes.pdf")
        return event

    _PRIMARY_KEYS = ("body_ref", "event_datetime")
    _INDEXES = (
        IndexedFieldSet((
            IndexedField(name="body_ref", order=Order.ASCENDING),
            IndexedField(name="event_datetime", order=Order.ASCENDING),
        )),
        IndexedFieldSet((
            IndexedField(name="body_ref", order=Order.ASCENDING),
            IndexedField(name="event_datetime", order=Order.DESCENDING),
        )),
    )
示例#6
0
class MatterStatus(Model):
    """
    A matter status is the status of a matter at any given time. Useful for tracking
    the timelines of matters. I.E. Return me a timeline of matter x.

    The same matter will have multiple matter statuses.
    1. MatterStatus of submitted
    2. MatterStatus of passed
    3. MatterStatus of signed
    4. etc.
    """

    id = fields.IDField()
    matter_ref = fields.ReferenceField(Matter, required=True, auto_load=False)
    # Optional because status can be updated out of event
    # i.e. Signed by Mayor
    event_minutes_item_ref = fields.ReferenceField(EventMinutesItem,
                                                   auto_load=False)
    status = fields.TextField(
        required=True,
        validator=validators.create_constant_value_validator(
            MatterStatusDecision, True),
    )
    update_datetime = fields.DateTime(required=True)
    external_source_id = fields.TextField()

    class Meta:
        ignore_none_field = False

    @classmethod
    def Example(cls) -> Model:
        matter_status = cls()
        matter_status.matter_ref = Matter.Example()
        matter_status.status = MatterStatusDecision.ADOPTED
        matter_status.update_datetime = datetime.utcnow()
        return matter_status

    _PRIMARY_KEYS = ("matter_ref", "status", "update_datetime")
    _INDEXES = (
        IndexedFieldSet((
            IndexedField(name="matter_ref", order=Order.ASCENDING),
            IndexedField(name="update_datetime", order=Order.ASCENDING),
        ), ),
        IndexedFieldSet((
            IndexedField(name="matter_ref", order=Order.ASCENDING),
            IndexedField(name="update_datetime", order=Order.DESCENDING),
        ), ),
    )
示例#7
0
class Session(Model):
    """
    A session is a working period for an event.
    For example, An event could have a morning and afternoon session.
    """

    id = fields.IDField()
    event_ref = fields.ReferenceField(Event, required=True, auto_load=False)
    session_datetime = fields.DateTime(required=True)
    session_index = fields.NumberField(required=True)
    session_content_hash = fields.TextField(required=True)
    video_uri = fields.TextField(required=True,
                                 validator=validators.resource_exists)
    caption_uri = fields.TextField(validator=validators.resource_exists)
    external_source_id = fields.TextField()

    class Meta:
        ignore_none_field = False

    def set_validator_kwargs(self, kwargs: Dict) -> None:
        field = fields.TextField(required=True,
                                 validator=validators.resource_exists,
                                 validator_kwargs=kwargs)

        field.contribute_to_model(Session, "video_uri")

    @classmethod
    def Example(cls) -> Model:
        session = cls()
        session.event_ref = Event.Example()
        session.session_index = 0
        session.video_uri = (
            "https://video.seattle.gov/media/council/brief_072219_2011957V.mp4"
        )
        session.session_content_hash = (
            "05bd857af7f70bf51b6aac1144046973bf3325c9101a554bc27dc9607dbbd8f5")
        return session

    _PRIMARY_KEYS = ("event_ref", "video_uri")
    _INDEXES = (IndexedFieldSet((
        IndexedField(name="event_ref", order=Order.ASCENDING),
        IndexedField(name="session_index", order=Order.ASCENDING),
    )), )
示例#8
0
class Transcript(Model):
    """
    A transcript is a document per-session.
    """

    id = fields.IDField()
    session_ref = fields.ReferenceField(Session,
                                        required=True,
                                        auto_load=False)
    file_ref = fields.ReferenceField(File, required=True, auto_load=False)
    generator = fields.TextField(required=True)
    confidence = fields.NumberField(required=True)
    created = fields.DateTime(required=True)

    class Meta:
        ignore_none_field = False

    @classmethod
    def Example(cls) -> Model:
        transcript = cls()
        transcript.session_ref = Session.Example()
        transcript.file_ref = File.Example()
        transcript.generator = "FakeGen -- v0.1.0"
        transcript.confidence = 0.943
        transcript.created = datetime.utcnow()
        return transcript

    _PRIMARY_KEYS = ("session_ref", "file_ref")
    _INDEXES = (
        IndexedFieldSet((
            IndexedField(name="session_ref", order=Order.ASCENDING),
            IndexedField(name="created", order=Order.DESCENDING),
        )),
        IndexedFieldSet((
            IndexedField(name="session_ref", order=Order.ASCENDING),
            IndexedField(name="confidence", order=Order.DESCENDING),
        )),
    )
示例#9
0
class Picture(Model):
    image_id = fields.TextField()
    date_added = fields.DateTime()
    file_name = fields.TextField()
    blob_name = fields.TextField()
    user_id = fields.TextField()

    def __init__(self, image_id="", file_name="", blob_name="", user_id=""):
        self.image_id = image_id
        self.date_added = datetime.datetime.now()
        self.file_name = file_name
        self.blob_name = blob_name
        self.user_id = user_id

    def add_image(self, image_object, user_id):
        try:
            bucket = storage_client.get_bucket(CLOUD_STORAGE_BUCKET)
            # In case users upload pictures with the same file name, concatenate user's id with file name
            blob = bucket.blob(user_id + "_" + self.file_name)
            blob.upload_from_string(
                image_object.read(), content_type=image_object.content_type
            )
            self.blob_name = blob.name
            self.user_id = user_id
            logger.info("Successfully uploaded image to Google Cloud Bucket")

            # Store object in Firestore to keep track of ID's
            db.collection("Images").document(self.image_id).set(self.__dict__)
            logger.info(
                "Successfully stored document with image_id: {} in Firestore".format(
                    self.image_id
                )
            )
            return True
        except Exception as e:
            logger.error(str(e))
            return False

    def delete_image(self, image_id, user_id):
        # Find Firestore document using image_id
        image = db.collection("Images").document(image_id)
        bucket = storage_client.get_bucket(CLOUD_STORAGE_BUCKET)
        image_dict = image.get().to_dict()

        # Check if the user credentials match the uploaded picture they wish to delete
        if image_dict["user_id"] != user_id:
            logger.error("This user does not have permission to delete the image")
            return False
        try:
            # Delete blob from Google Cloud bucket
            bucket.delete_blob(image_dict["blob_name"])
            logger.debug("Deleted Blob: {}".format(image_dict["blob_name"]))

            # Delete Firestore
            image.delete()
            logger.debug(
                "Firestore document deleted for image_id: {}".format(
                    image_dict["image_id"]
                )
            )
            return True
        except Exception as e:
            logger.debug(str(e))
            logger.error("Cannot find blob in the bucket")
            return False

    def bulk_delete(self, user_id):
        images = db.collection("Images").stream()
        count = 0
        try:
            for image in images:
                is_deleted = self.delete_image(image.get("image_id"), user_id)
                if is_deleted:
                    db.collection("Images").document(image.get("image_id")).delete()
                    count += 1
                    logger.debug("Deleted {} images".format(count))
            return True
        except Exception as e:
            logger.error("Bulk-Delete Exception: {}".format(str(e)))
            return False
示例#10
0
class Base(Model):
    created = fields.DateTime(auto=True)
    modified = AutoModifiedDateTime(auto=True)

    class Meta:
        abstract = True