Skip to content

Profile

profile

This module defines the profile_router of the Mirumoji API

Covers a profile's LLM template, saved clips, files, transcripts, and Anki deck export, all scoped to the active profile via X-Profile-ID

Attributes:

Name Type Description
LOGGER Logger

Module's logging object

profile_router APIRouter

The FastAPI router object

delete_clip(clip_id, profile_id=Depends(ensure_profile_exists)) async

Deletes one of the active profile's saved clips and its file

Parameters:

Name Type Description Default
clip_id UUID

Id of the clip to delete

required
profile_id str

Validated profile id

Depends(ensure_profile_exists)

Returns:

Type Description
dict[str, Any]

A confirmation payload

Raises:

Type Description
RecordNotFoundError

If the clip doesn't exist or isn't owned by the profile

StorageError

If deleting the clip file fails

DatabaseError

If the deletion fails

delete_file(file_id, profile_id=Depends(ensure_profile_exists), manager=Depends(get_job_manager)) async

Deletes one of the active profile's files

Source Of Truth
  • Files are the single source of truth for a profile's artifacts. A job that used or produced this file is meaningless without it, so those jobs are cascade-deleted first (a batch parent takes its children)

  • Deleting a file also cascades (via foreign keys) to any transcripts or clips that reference it

Parameters:

Name Type Description Default
file_id UUID

Id of the file to delete

required
profile_id str

Validated profile id

Depends(ensure_profile_exists)
manager JobQueueManager

The job worker

Depends(get_job_manager)

Returns:

Type Description
dict[str, Any]

A confirmation payload

Raises:

Type Description
HTTPException

If a job still being run by the worker uses this file

RecordNotFoundError

If the file doesn't exist or isn't owned by the profile

StorageError

If deleting the file fails

DatabaseError

If the deletion fails

delete_template(profile_id=Depends(ensure_profile_exists)) async

Deletes the active profile's LLM template

Parameters:

Name Type Description Default
profile_id str

Validated profile id

Depends(ensure_profile_exists)

Returns:

Type Description
dict[str, Any]

A confirmation payload

Raises:

Type Description
RecordNotFoundError

If the profile has no template

DatabaseError

If the deletion fails

delete_transcript(transcript_id, profile_id=Depends(ensure_profile_exists), manager=Depends(get_job_manager)) async

Deletes one of the active profile's transcripts

A transcribe job that produced this transcript is meaningless without it, so those jobs are cascade-deleted first

Parameters:

Name Type Description Default
transcript_id UUID

Id of the transcript to delete

required
profile_id str

Validated profile id

Depends(ensure_profile_exists)
manager JobQueueManager

The job worker

Depends(get_job_manager)

Returns:

Type Description
dict[str, Any]

A confirmation payload

Raises:

Type Description
HTTPException

If a job still being run by the worker produced this transcript

RecordNotFoundError

If the transcript doesn't exist or isn't owned by the profile

DatabaseError

If the deletion fails

export_anki_deck(profile_id=Depends(ensure_profile_exists)) async

Exports the active profile's saved clips as an Anki deck

Builds one card per saved clip from its stored breakdown payload (focus word, meanings, sentence, and explanation), bundles the clip media, and writes the .apkg under the profile

Parameters:

Name Type Description Default
profile_id str

Validated profile id

Depends(ensure_profile_exists)

Returns:

Type Description
AnkiExportResponse

The media URL serving the exported Anki deck

Raises:

Type Description
DatabaseError

If reading the clips fails

StorageError

If writing the deck fails

get_template(profile_id=Depends(ensure_profile_exists)) async

Retrieves the active profile's LLM template

Parameters:

Name Type Description Default
profile_id str

Validated profile id

Depends(ensure_profile_exists)

Returns:

Type Description
LlmTemplateResponse

The profile's saved LLM template

Raises:

Type Description
RecordNotFoundError

If the profile has no template

DatabaseError

If the lookup fails

list_clips(profile_id=Depends(ensure_profile_exists)) async

Lists the active profile's saved clips

Parameters:

Name Type Description Default
profile_id str

Validated profile id

Depends(ensure_profile_exists)

Returns:

Type Description
list[ClipResponse]

The profile's saved clips, newest first

Raises:

Type Description
DatabaseError

If the query fails

list_files(profile_id=Depends(ensure_profile_exists)) async

Lists the active profile's saved files

Parameters:

Name Type Description Default
profile_id str

Validated profile id

Depends(ensure_profile_exists)

Returns:

Type Description
list[ProfileFileResponse]

The profile's saved files, newest first

Raises:

Type Description
DatabaseError

If the query fails

list_transcripts(profile_id=Depends(ensure_profile_exists)) async

Lists the active profile's transcripts

Parameters:

Name Type Description Default
profile_id str

Validated profile id

Depends(ensure_profile_exists)

Returns:

Type Description
list[ProfileTranscriptResponse]

The profile's transcripts, newest first

Raises:

Type Description
DatabaseError

If the query fails

save_clip(clip_file=File(...), start_time=Form(...), end_time=Form(...), breakdown=Form(...), profile_id=Depends(ensure_profile_exists)) async

Saves an uploaded video clip for the active profile

Receives the clip and its metadata as a single multipart/form-data request (the clip is the file part, the rest are form fields), converts it to WebM for Anki compatibility, stores it under the profile, and persists a file + clip record

Parameters:

Name Type Description Default
clip_file UploadFile

The recorded clip (multipart file part)

File(...)
start_time float

Clip start time in seconds

Form(...)
end_time float

Clip end time in seconds

Form(...)
breakdown str

JSON-encoded breakdown payload

Form(...)
profile_id str

Validated profile id

Depends(ensure_profile_exists)

Returns:

Type Description
SaveClipResponse

The saved clip's id, its file id, and its media URL

Raises:

Type Description
HTTPException

If the breakdown payload is not valid JSON

FFmpegError

If the WebM conversion fails

StorageError

If storing the clip fails

DatabaseError

If persistence fails

save_subtitles(req, profile_id=Depends(ensure_profile_exists)) async

Persists SRT content under the active profile

Used by the player's "Fix SRT" action: when file_id points at an existing SRT file owned by the profile, its content is overwritten in place; otherwise a new SRT file is stored

Parameters:

Name Type Description Default
req SaveSubtitlesRequest

The SRT content (+ optional file id / name)

required
profile_id str

Validated profile id

Depends(ensure_profile_exists)

Returns:

Type Description
ProfileFileResponse

The stored SRT file's id, name, media URL, type, and timestamp

Raises:

Type Description
StorageError

If writing the SRT fails

DatabaseError

If persistence fails

upload_file(request, file_name=Header(..., alias='X-File-Name'), file_type=Query(None, alias='type'), folder=Query(None, alias='folder'), profile_id=Depends(ensure_profile_exists)) async

Streams an upload and stores it as a profile file (no processing)

Usage
  • This is the upload-once entry point for the job system

  • The returned file id is then passed to POST /jobs if an operation on it is requested

  • Avoids re-uploading the file

Folder
  • ?folder= tags files uploaded together (e.g. from a picked directory) with a shared group label so that the file list can group them

  • It is a query param rather than a header so a non-ASCII group name never has to be encoded into a latin-1 header

Parameters:

Name Type Description Default
request Request

The FastAPI.Request object (the body is the file)

required
file_name str

The original file name (X-File-Name)

Header(..., alias='X-File-Name')
file_type str | None

Optional file-type tag (?type=)

Query(None, alias='type')
folder str | None

Optional group label (?folder=)

Query(None, alias='folder')
profile_id str

Validated profile id

Depends(ensure_profile_exists)

Returns:

Type Description
ProfileFileResponse

The stored file's id, name, media URL, type, and folder

Raises:

Type Description
UploadError

If the upload fails

DatabaseError

If persistence fails

upsert_template(req, profile_id=Depends(ensure_profile_exists)) async

Creates or updates the active profile's LLM template

Parameters:

Name Type Description Default
req LlmTemplateRequest

The template data

required
profile_id str

Validated profile id

Depends(ensure_profile_exists)

Returns:

Type Description
LlmTemplateResponse

The created or updated LLM template

Raises:

Type Description
DatabaseError

If the upsert fails