Skip to content

Commit

Permalink
Add content set and report
Browse files Browse the repository at this point in the history
Signed-off-by: Robert Cronin <[email protected]>
  • Loading branch information
robert-cronin committed Aug 31, 2024
1 parent 971d68b commit c76ace5
Show file tree
Hide file tree
Showing 19 changed files with 944 additions and 83 deletions.
1 change: 0 additions & 1 deletion modules/odr_core/odr_core/crud/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
httpurl_to_str,
)
from typing import List, Optional
from sqlalchemy import Enum as SQLAlchemyEnum
from loguru import logger
from datetime import datetime, timezone
from sqlalchemy.exc import IntegrityError
Expand Down
40 changes: 40 additions & 0 deletions modules/odr_core/odr_core/crud/content_report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from sqlalchemy.orm import Session
from odr_core.models.content import ContentReport
from odr_core.schemas.content_report import ContentReportCreate, ContentReportUpdate
from typing import List, Optional


def create_content_report(db: Session, report: ContentReportCreate) -> ContentReport:
db_report = ContentReport(**report.model_dump())
db.add(db_report)
db.commit()
db.refresh(db_report)
return db_report


def get_content_report(db: Session, report_id: int) -> Optional[ContentReport]:
return db.query(ContentReport).filter(ContentReport.id == report_id).first()


def get_content_reports(db: Session, skip: int = 0, limit: int = 100) -> List[ContentReport]:
return db.query(ContentReport).offset(skip).limit(limit).all()


def update_content_report(db: Session, report_id: int, report: ContentReportUpdate) -> Optional[ContentReport]:
db_report = db.query(ContentReport).filter(ContentReport.id == report_id).first()
if db_report:
update_data = report.model_dump(exclude_unset=True)
for key, value in update_data.items():
setattr(db_report, key, value)
db.commit()
db.refresh(db_report)
return db_report


def delete_content_report(db: Session, report_id: int) -> bool:
db_report = db.query(ContentReport).filter(ContentReport.id == report_id).first()
if db_report:
db.delete(db_report)
db.commit()
return True
return False
69 changes: 69 additions & 0 deletions modules/odr_core/odr_core/crud/content_set.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from sqlalchemy.orm import Session
from odr_core.models.content import ContentSet, ContentSetItem, Content
from odr_core.schemas.content_set import ContentSetCreate, ContentSetUpdate
from typing import List, Optional


def create_content_set(db: Session, content_set: ContentSetCreate) -> ContentSet:
db_content_set = ContentSet(**content_set.model_dump())
db.add(db_content_set)
db.commit()
db.refresh(db_content_set)
return db_content_set


def get_content_set(db: Session, content_set_id: int) -> Optional[ContentSet]:
return db.query(ContentSet).filter(ContentSet.id == content_set_id).first()


def get_content_sets(db: Session, skip: int = 0, limit: int = 100) -> List[ContentSet]:
return db.query(ContentSet).offset(skip).limit(limit).all()


def update_content_set(db: Session, content_set_id: int, content_set: ContentSetUpdate) -> Optional[ContentSet]:
db_content_set = db.query(ContentSet).filter(ContentSet.id == content_set_id).first()
if db_content_set:
update_data = content_set.model_dump(exclude_unset=True)
for key, value in update_data.items():
setattr(db_content_set, key, value)
db.commit()
db.refresh(db_content_set)
return db_content_set


def delete_content_set(db: Session, content_set_id: int) -> bool:
db_content_set = db.query(ContentSet).filter(ContentSet.id == content_set_id).first()
if db_content_set:
db.delete(db_content_set)
db.commit()
return True
return False


def add_content_to_set(db: Session, content_set_id: int, content_id: int) -> bool:
db_content_set_item = ContentSetItem(content_set_id=content_set_id, content_id=content_id)
db.add(db_content_set_item)
try:
db.commit()
return True
except: # noqa
db.rollback()
return False


def remove_content_from_set(db: Session, content_set_id: int, content_id: int) -> bool:
db_content_set_item = db.query(ContentSetItem).filter(
ContentSetItem.content_set_id == content_set_id,
ContentSetItem.content_id == content_id
).first()
if db_content_set_item:
db.delete(db_content_set_item)
db.commit()
return True
return False


def get_contents_in_set(db: Session, content_set_id: int, skip: int = 0, limit: int = 100) -> List[Content]:
return db.query(Content).join(ContentSetItem).filter(
ContentSetItem.content_set_id == content_set_id
).offset(skip).limit(limit).all()
54 changes: 54 additions & 0 deletions modules/odr_core/odr_core/enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from enum import Enum


class ContentType(str, Enum):
IMAGE = "image"
VIDEO = "video"
VOICE = "voice"
MUSIC = "music"
TEXT = "text"


class ContentStatus(str, Enum):
PENDING = "PENDING"
AVAILABLE = "AVAILABLE"
UNAVAILABLE = "UNAVAILABLE"
DELISTED = "DELISTED"


class ContentSourceType(str, Enum):
URL = "url"
PATH = "path"
HUGGING_FACE = "hugging_face"


class ReportStatus(str, Enum):
PENDING = "pending"
REVIEWED = "reviewed"
RESOLVED = "resolved"


class AnnotationSourceType(str, Enum):
CONTENT_DESCRIPTION = "content_description"
SPATIAL_ANALYSIS = "spatial_analysis"
TAGS = "tags"
OTHER = "other"


class ReportType(str, Enum):
ILLEGAL_CONTENT = "illegal_content"
MALICIOUS_ANNOTATION = "malicious_annotation"
OTHER = "other"


class EmbeddingEngineType(str, Enum):
IMAGE = "image"
VIDEO = "video"
VOICE = "voice"
MUSIC = "music"
TEXT = "text"


class UserType(str, Enum):
user = "user"
bot = "bot"
67 changes: 43 additions & 24 deletions modules/odr_core/odr_core/models/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,7 @@
from sqlalchemy.sql import func
from odr_core.models.base import Base
from sqlalchemy import Enum as SQLAlchemyEnum
import enum


class ContentType(enum.Enum):
IMAGE = "IMAGE"
VIDEO = "VIDEO"
VOICE = "VOICE"
MUSIC = "MUSIC"
TEXT = "TEXT"


class ContentStatus(enum.Enum):
PENDING = "PENDING"
AVAILABLE = "AVAILABLE"
UNAVAILABLE = "UNAVAILABLE"
DELISTED = "DELISTED"


class ContentSourceType(enum.Enum):
URL = "url"
PATH = "path"
HUGGING_FACE = "hugging_face"
from odr_core.enums import ContentType, ContentStatus, ContentSourceType, ReportStatus


class Content(Base):
Expand Down Expand Up @@ -66,11 +45,13 @@ class Content(Base):

from_user = relationship("User", back_populates="contents")
from_team = relationship("Team", back_populates="contents")
content_authors = relationship("ContentAuthor", back_populates="content")
annotations = relationship("Annotation", back_populates="content")
embeddings = relationship("ContentEmbedding", back_populates="content")
sources = relationship("ContentSource", back_populates="content", cascade="all,delete-orphan")
events = relationship("ContentEvents", back_populates="content")
reports = relationship("ContentReport", back_populates="content")
content_authors = relationship("ContentAuthor", back_populates="content")
content_sets = relationship("ContentSet", secondary="content_set_items", back_populates="contents")


class ContentAuthor(Base):
Expand All @@ -91,7 +72,7 @@ class ContentSource(Base):

id = Column(Integer, primary_key=True, index=True)
content_id = Column(Integer, ForeignKey("contents.id"))
type = Column(Enum(ContentSourceType))
type = Column(SQLAlchemyEnum(ContentSourceType))
value = Column(String, unique=True)
source_metadata = Column(String, nullable=True) # JSON
created_at = Column(DateTime(timezone=True), server_default=func.now())
Expand All @@ -113,3 +94,41 @@ class ContentEvents(Base):

content = relationship("Content", back_populates="events")
user = relationship("User", back_populates="content_events")


class ContentReport(Base):
__tablename__ = "content_reports"

id = Column(Integer, primary_key=True, index=True)
content_id = Column(Integer, ForeignKey("contents.id"), nullable=False)
reporter_id = Column(Integer, ForeignKey("users.id"), nullable=False)
reason = Column(String, nullable=False)
description = Column(String)
status = Column(Enum(ReportStatus), default=ReportStatus.PENDING)
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now(), nullable=False, server_default=func.now())

content = relationship("Content", back_populates="reports")
reporter = relationship("User", back_populates="content_reports")


class ContentSet(Base):
__tablename__ = "content_sets"

id = Column(Integer, primary_key=True, index=True)
name = Column(String, nullable=False)
description = Column(String)
created_by_id = Column(Integer, ForeignKey("users.id"), nullable=False)
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now(), nullable=False, server_default=func.now())

created_by = relationship("User", back_populates="content_sets")
contents = relationship("Content", secondary="content_set_items", back_populates="content_sets")


class ContentSetItem(Base):
__tablename__ = "content_set_items"

content_set_id = Column(Integer, ForeignKey("content_sets.id"), primary_key=True)
content_id = Column(Integer, ForeignKey("contents.id"), primary_key=True)
added_at = Column(DateTime(timezone=True), server_default=func.now())
2 changes: 2 additions & 0 deletions modules/odr_core/odr_core/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class User(Base):
user_type = Column(Enum(UserType), default=UserType.user)

content_events = relationship("ContentEvents", back_populates="user")
content_reports = relationship("ContentReport", back_populates="reporter")
content_sets = relationship("ContentSet", back_populates="created_by")

def __repr__(self):
return f"<User(id={self.id}, username={self.username}, email={self.email})>"
Expand Down
17 changes: 2 additions & 15 deletions modules/odr_core/odr_core/schemas/annotation.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from pydantic import BaseModel, Field, field_serializer
from pydantic import BaseModel, Field
from typing import List, Optional, Dict, Any
from datetime import datetime
from enum import Enum
from odr_core.enums import AnnotationSourceType, ReportType


class AnnotationBase(BaseModel):
Expand Down Expand Up @@ -82,12 +82,6 @@ class Config:
from_attributes = True


class ReportType(str, Enum):
ILLEGAL_CONTENT = "illegal_content"
MALICIOUS_ANNOTATION = "malicious_annotation"
OTHER = "other"


class AnnotationReportBase(BaseModel):
type: ReportType
description: Optional[str] = None
Expand All @@ -108,13 +102,6 @@ class Config:
from_attributes = True


class AnnotationSourceType(str, Enum):
CONTENT_DESCRIPTION = "content_description"
SPATIAL_ANALYSIS = "spatial_analysis"
TAGS = "tags"
OTHER = "other"


class AnnotationSourceBase(BaseModel):
name: str
ecosystem: Optional[str] = None
Expand Down
23 changes: 1 addition & 22 deletions modules/odr_core/odr_core/schemas/content.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,7 @@
from pydantic import BaseModel, HttpUrl
from typing import List, Optional
from datetime import datetime
from enum import Enum


class ContentType(str, Enum):
IMAGE = "IMAGE"
VIDEO = "VIDEO"
VOICE = "VOICE"
MUSIC = "MUSIC"
TEXT = "TEXT"


class ContentStatus(str, Enum):
PENDING = "PENDING"
AVAILABLE = "AVAILABLE"
UNAVAILABLE = "UNAVAILABLE"
DELISTED = "DELISTED"


class ContentSourceType(str, Enum):
URL = "URL"
PATH = "PATH"
HUGGING_FACE = "HUGGING_FACE"
from odr_core.enums import ContentStatus, ContentType, ContentSourceType


class ContentAuthorBase(BaseModel):
Expand Down
31 changes: 31 additions & 0 deletions modules/odr_core/odr_core/schemas/content_report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from pydantic import BaseModel
from typing import Optional
from datetime import datetime
from odr_core.enums import ReportStatus


class ContentReportBase(BaseModel):
content_id: int
reporter_id: int
reason: str
description: Optional[str] = None


class ContentReportCreate(ContentReportBase):
pass


class ContentReportUpdate(BaseModel):
reason: Optional[str] = None
description: Optional[str] = None
status: Optional[ReportStatus] = None


class ContentReport(ContentReportBase):
id: int
status: ReportStatus
created_at: datetime
updated_at: datetime

class Config:
from_attributes = True
Loading

0 comments on commit c76ace5

Please sign in to comment.