class SlackInstallation(BaseModel): """Keep track of each installation of Slack integration""" __tablename__ = "slack_installation" def __repr__(self): # pragma: no cover return f"<SlackInstallation: {self.workspace_name}>" # Attributes access_token = db.Column(EncryptedType(db.String, SECRET_KEY, AesEngine, "pkcs5"), nullable=False) authorizing_user_id = db.Column(db.String(300), nullable=False) bot_access_token = db.Column(EncryptedType(db.String, SECRET_KEY, AesEngine, "pkcs5"), nullable=False) bot_user_id = db.Column(EncryptedType(db.String, SECRET_KEY, AesEngine, "pkcs5"), nullable=False) scope = db.Column(db.String(800), nullable=False) workspace_id = db.Column(db.String(20), index=True, nullable=False) workspace_name = db.Column(db.String(255), nullable=False) state = db.Column(db.String(20), nullable=False, default="installed") auth_response = db.Column("auth_response", db.JSON) # Relationships github_summary_users = db.relationship("GitHubSummaryUser", back_populates="installation") github_summary_config = db.relationship( "GitHubSummaryConfiguration", back_populates="slack_installation", uselist=False)
class SyncEventDatabaseTask(Task): __tablename__ = "sync_event_database_task" # Attributes id = db.Column(db.Integer, db.ForeignKey("task.id"), primary_key=True) data = db.Column("data", db.JSON) __mapper_args__ = {"polymorphic_identity": "sync_event_database"} def __repr__(self): # pragma: no cover return f"<SyncEventDatabaseTask: {self.data}>"
class PostTweetTask(Task): __tablename__ = "post_tweet_task" # Attributes id = db.Column(db.Integer, db.ForeignKey("task.id"), primary_key=True) data = db.Column("data", db.JSON) __mapper_args__ = {"polymorphic_identity": "post_tweet"} def __repr__(self): # pragma: no cover return f"<PostTweetTask: {self.data}>"
class PostGitHubSummaryTask(Task): __tablename__ = "post_github_summary_task" # Attributes id = db.Column(db.Integer, db.ForeignKey("task.id"), primary_key=True) data = db.Column("data", db.JSON) __mapper_args__ = {"polymorphic_identity": "post_github_summary"} def __repr__(self): return f"<PostGitHubSummaryTask: {self.data}>"
class KeyValueStore(BaseModel): """Key Value store by slack workspace id Keeps track of required values for each workspace""" __tablename__ = "key_value_store" def __repr__(self): return f"<KeyValueStore: {self.key} {self.value}>" # Attributes # TODO add slack workspace id once when we start being more than single tenant key = db.Column(db.String(255), nullable=False, unique=True) value = db.Column(db.LargeBinary(), nullable=False)
class ApiUser(BaseModel): """API User table""" __tablename__ = "api_user" def __repr__(self): return f"<API: {self.username}>" # Attributes username = db.Column(db.String(255), nullable=False) token = db.Column(db.String(255), nullable=False) role = db.Column(db.String(255), nullable=False, default="user") # Relationships tasks = db.relationship("Task", back_populates="user")
class User(BaseModel): """User table""" __tablename__ = "user" def __repr__(self): return f"<User slack: {self.slack_id} github: {self.github_username}>" # Attributes slack_id = db.Column(db.String(300), nullable=False) github_id = db.Column(db.String(300), nullable=True) github_username = db.Column(db.String(300), nullable=True) github_state = db.Column(db.String(36), nullable=True) github_access_token = db.Column(db.String(100), nullable=True)
class BaseModel(db.Model): __abstract__ = True id = db.Column(db.Integer, primary_key=True) date_created = db.Column(db.DateTime, default=db.func.current_timestamp()) date_modified = db.Column( db.DateTime, onupdate=db.func.current_timestamp(), default=db.func.current_timestamp(), ) @declared_attr def __tablename__(cls): return cls.__name__.lower() def patch(self, data: dict): for key, value in data.items(): setattr(self, key, value)
class GitHubSummaryConfiguration(BaseModel): __tablename__ = "github_summary_configuration" def __repr__(self): # pragma: no cover return f"<GitHubSummaryConfiguration>" installation_id = db.Column( db.Integer, db.ForeignKey("slack_installation.id", name="fk_installation_id"), nullable=False, ) channel = db.Column(db.String(20), nullable=False) time_to_post = db.Column(db.String(20), nullable=True) timezone_info = db.Column(db.JSON) # Relationships slack_installation = db.relationship( "SlackInstallation", back_populates="github_summary_config" )
class SlackAppHomeOpened(BaseModel): """Track number of times App Home is opened For bot onboarding """ __tablename__ = "slack_app_home_opened" installation_id = db.Column( db.Integer, db.ForeignKey("slack_installation.id", name="fk_installation_id"), index=True, nullable=False, ) slack_id = db.Column(db.String(30), index=True, nullable=False) count = db.Column(db.Integer, nullable=False, default=1) # Relationships installation = db.relationship("SlackInstallation")
class YouTubeVideo(BaseModel): """Store all YouTube videos that have been posted""" __tablename__ = "youtube_video" def __repr__(self): # pragma: no cover return f"<YouTubeVideo({self.youtube_id})>" # Attributes youtube_id = db.Column(db.String(300), nullable=False) title = db.Column(db.String(300), nullable=False) published_at = db.Column(db.DateTime, nullable=True) description = db.Column(db.String(1000), nullable=False) @staticmethod def date_str_to_datetime(date_str: str) -> datetime: """For converting string 'publishedAt'.""" date_format = "%Y-%m-%dT%H:%M:%S" return datetime.strptime(date_str.split(".")[0], date_format)
class GitHubSummaryUser(BaseModel): """GitHub Summary User table TODO: GitHubSummaryUser should really be related to GitHubSummaryConfiguration versus SlackInstallation """ __tablename__ = "github_summary_user" def __repr__(self): # pragma: no cover return f"<User slack: {self.slack_id} github: {self.github_username}>" # Attributes installation_id = db.Column( db.Integer, db.ForeignKey("slack_installation.id", name="fk_installation_id"), nullable=False, ) slack_id = db.Column(db.String(300), nullable=False) github_id = db.Column(db.String(300), nullable=True) github_username = db.Column(db.String(300), nullable=True) github_state = db.Column(db.String(36), nullable=True) github_access_token = db.Column(db.String(100), nullable=True) # Relationships installation = db.relationship( "SlackInstallation", back_populates="github_summary_users" )
class GitHubSummaryUser(BaseModel): # TODO # add a field for workspace_id # add a relationship for the ORM """GitHub Summary User table""" __tablename__ = "github_summary_user" def __repr__(self): # pragma: no cover return f"<User slack: {self.slack_id} github: {self.github_username}>" # Attributes installation_id = db.Column( db.Integer, db.ForeignKey("slack_installation.id", name="fk_installation_id"), nullable=False, ) slack_id = db.Column(db.String(300), nullable=False) github_id = db.Column(db.String(300), nullable=True) github_username = db.Column(db.String(300), nullable=True) github_state = db.Column(db.String(36), nullable=True) github_access_token = db.Column(db.String(100), nullable=True) # Relationships installation = db.relationship("SlackInstallation", back_populates="github_summary_users")
class Event(BaseModel): """Event table for storing information about past and future meetups""" __tablename__ = "event" def __repr__(self): # pragma: no cover return f"<Event: {self.name}>" # Attributes remote_id = db.Column(db.String(255), nullable=False, index=True) name = db.Column(db.String(255), nullable=False) url = db.Column(db.String(500), nullable=False) venue = db.Column(db.String(255), nullable=False) start_epoch = db.Column(db.Integer, nullable=False) end_epoch = db.Column(db.Integer, nullable=False)
class Task(BaseModel): """Task Base Table""" __tablename__ = "task" # Attributes job_id = db.Column(db.String(36), index=True) name = db.Column(db.String(128), index=True) description = db.Column(db.String(128)) failed = db.Column(db.Boolean, default=False) complete = db.Column(db.Boolean, default=False) user_id = db.Column(db.Integer, db.ForeignKey("api_user.id", name="fk_task_user_id")) type = db.Column(db.String(55)) __mapper_args__ = { "polymorphic_identity": "task", "polymorphic_on": "type" } # Relationships user = db.relationship("ApiUser", back_populates="tasks") def get_rq_job(self): try: rq_job = Job.fetch(self.job_id, rq.connection) except (RedisError, NoSuchJobError): return None return rq_job def get_progress(self): job = self.get_rq_job() return job.meta.get("progress", 0) if job is not None else 100 def __repr__(self): # pragma: no cover return f"<Task: {self.job_id}-{self.name}>"