Files
gronod 019caca1b3
Build and publish / Test and build (darwin) (pull_request) Successful in 1m54s
Build and publish / Test and build (linux) (pull_request) Successful in 2m14s
Build and publish / Test and build (windows) (pull_request) Successful in 3m6s
Build and publish / Build and publish Docker image (pull_request) Successful in 1m54s
Build and publish / Test and build (darwin) (push) Successful in 1m44s
Build and publish / Test and build (windows) (push) Successful in 3m4s
Build and publish / Test and build (linux) (push) Successful in 2m4s
Build and publish / Build and publish Docker image (push) Successful in 1m58s
Fix M4 discover browse and search contracts
2026-09-19 10:07:10 +01:00

270 lines
8.9 KiB
Go

package ombi
import "encoding/json"
// Wire types for upstream request bodies and small typed responses.
// Field names match the RAML wire spellings exactly — including
// upstream quirks such as is4kRequest vs is4K. Optional fields use
// pointers/omitempty so omitted values are never sent.
// --- Request creation bodies ---
// MovieRequestViewModel — POST /api/v1/Request/movie
type MovieRequestViewModel struct {
TheMovieDbID int `json:"theMovieDbId"`
LanguageCode string `json:"languageCode,omitempty"`
Is4KRequest bool `json:"is4kRequest"`
RequestOnBehalf string `json:"requestOnBehalf,omitempty"`
RootFolderOverride *int `json:"rootFolderOverride,omitempty"`
QualityPathOverride *int `json:"qualityPathOverride,omitempty"`
}
// TvRequestViewModel — POST /api/v1/Request/tv (TVDB provider)
type TvRequestViewModel struct {
TvDbID int `json:"tvDbId"`
RequestAll bool `json:"requestAll"`
LatestSeason bool `json:"latestSeason"`
FirstSeason bool `json:"firstSeason"`
Seasons []SeasonsViewModel `json:"seasons,omitempty"`
LanguageProfile *int `json:"languageProfile,omitempty"`
RequestOnBehalf string `json:"requestOnBehalf,omitempty"`
RootFolderOverride *int `json:"rootFolderOverride,omitempty"`
QualityPathOverride *int `json:"qualityPathOverride,omitempty"`
}
// TvRequestViewModelV2 — POST /api/v2/Requests/tv (TMDB provider)
type TvRequestViewModelV2 struct {
TheMovieDbID int `json:"theMovieDbId"`
LanguageCode string `json:"languageCode,omitempty"`
RequestAll bool `json:"requestAll"`
LatestSeason bool `json:"latestSeason"`
FirstSeason bool `json:"firstSeason"`
Seasons []SeasonsViewModel `json:"seasons,omitempty"`
LanguageProfile *int `json:"languageProfile,omitempty"`
RequestOnBehalf string `json:"requestOnBehalf,omitempty"`
RootFolderOverride *int `json:"rootFolderOverride,omitempty"`
QualityPathOverride *int `json:"qualityPathOverride,omitempty"`
}
type SeasonsViewModel struct {
SeasonNumber int `json:"seasonNumber"`
Episodes []EpisodesViewModel `json:"episodes"`
}
type EpisodesViewModel struct {
EpisodeNumber int `json:"episodeNumber"`
}
// MusicAlbumRequestViewModel — POST /api/v1/request/music
type MusicAlbumRequestViewModel struct {
ForeignAlbumID string `json:"foreignAlbumId"`
RequestedByAlias string `json:"requestedByAlias,omitempty"`
}
// --- Moderation bodies ---
// MovieUpdateModel — POST Request/movie/{approve|available|unavailable}
type MovieUpdateModel struct {
ID int `json:"id"`
Is4K bool `json:"is4K"`
}
// TvUpdateModel / AlbumUpdateModel — POST Request/tv|request/music/*
type UpdateModelID struct {
ID int `json:"id"`
}
// DenyMovieModel — PUT Request/movie/deny
type DenyMovieModel struct {
Reason string `json:"reason"`
ID int `json:"id"`
Is4K bool `json:"is4K"`
}
// DenyTvModel / DenyAlbumModel — PUT Request/tv|request/music/deny
type DenyModel struct {
Reason string `json:"reason"`
ID int `json:"id"`
}
// MediaAdvancedOptions — POST /api/v2/Requests/{movie|tv}/advancedoptions
type MediaAdvancedOptions struct {
RequestID int `json:"requestId"`
RootPathOverride *int `json:"rootPathOverride,omitempty"`
QualityOverride *int `json:"qualityOverride,omitempty"`
LanguageProfile *int `json:"languageProfile,omitempty"`
}
// --- Issue bodies ---
// IssueCreateBody — POST /api/v1/Issues (minimal editable projection)
type IssueCreateBody struct {
Title string `json:"title"`
Subject string `json:"subject,omitempty"`
Description string `json:"description"`
IssueCategoryID int `json:"issueCategoryId"`
RequestType int `json:"requestType"`
RequestID *int `json:"requestId,omitempty"`
ProviderID string `json:"providerId,omitempty"`
}
// NewIssueCommentViewModel — POST /api/v1/Issues/comments
type NewIssueCommentViewModel struct {
Comment string `json:"comment"`
IssueID int `json:"issueId"`
}
// IssueStateViewModel — POST /api/v1/Issues/status
type IssueStateViewModel struct {
IssueID int `json:"issueId"`
Status int `json:"status"`
}
// IssueCategoryBody — POST /api/v1/Issues/categories
type IssueCategoryBody struct {
Value string `json:"value"`
}
// --- Search / discovery bodies ---
// MultiSearchFilter — POST /api/v2/Search/multi/{searchTerm}
type MultiSearchFilter struct {
Movies bool `json:"movies"`
TvShows bool `json:"tvShows"`
Music bool `json:"music"`
People bool `json:"people"`
}
// SearchMovieRefineModel — POST /api/v1/Search/movie
type SearchMovieRefineModel struct {
SearchTerm string `json:"searchTerm"`
Year *int `json:"year,omitempty"`
LanguageCode string `json:"languageCode,omitempty"`
}
// SearchActorModel — POST /api/v1/Search/movie/actor
type SearchActorModel struct {
SearchTerm string `json:"searchTerm"`
LanguageCode string `json:"languageCode,omitempty"`
}
// SimilarMoviesRefineModel — POST /api/v2/Search/movie/similar
type SimilarMoviesRefineModel struct {
TheMovieDbID int `json:"theMovieDbId"`
LanguageCode string `json:"languageCode,omitempty"`
}
// SearchMovieExtraInfoRefineModel — POST /api/v1/Search/movie/info
type SearchMovieExtraInfoRefineModel struct {
TheMovieDbID int `json:"theMovieDbId"`
LanguageCode string `json:"languageCode"`
}
// DiscoverModel — POST /api/v2/Search/advancedSearch/movie/{pos}/{amt}.
// Ombi uses Type to choose its downstream TMDB discover route; omitting it
// produces an empty result set.
type DiscoverModel struct {
Type string `json:"type"`
ReleaseYear *int `json:"releaseYear,omitempty"`
Decade *int `json:"decade,omitempty"`
GenreIDs []int `json:"genreIds,omitempty"`
KeywordIDs []int `json:"keywordIds,omitempty"`
WatchProviders []int `json:"watchProviders,omitempty"`
}
// --- User / admin bodies ---
// UserLanguage — POST /api/v1/Identity/language
type UserLanguage struct {
Lang string `json:"lang"`
}
// CountryStreamingPreference — POST /api/v1/Identity/streamingcountry
type CountryStreamingPreference struct {
Code string `json:"code"`
}
// CronViewModelBody — POST /api/v1/Settings/testcron
type CronViewModelBody struct {
Expression string `json:"expression"`
}
// FeatureEnablement — POST /api/v2/Features/{enable|disable}
type FeatureEnablement struct {
Name string `json:"name"`
Enabled bool `json:"enabled"`
}
// MassEmailModel — POST /api/v1/Notifications/massemail
type MassEmailModel struct {
Subject string `json:"subject"`
Body string `json:"body"`
Bcc bool `json:"bcc"`
Users []MassEmailUser `json:"users"`
}
// MassEmailUser is the minimal verified recipient entity resolved
// internally from a saved user record — never model-supplied JSON.
type MassEmailUser struct {
ID string `json:"id"`
UserName string `json:"userName,omitempty"`
Email string `json:"email,omitempty"`
}
// --- Typed small responses ---
// EngineResult is the shared shape of RequestEngineResult and
// VoteEngineResult upstream responses.
type EngineResult struct {
Result *bool `json:"result"`
Message string `json:"message"`
IsError *bool `json:"isError"`
ErrorMessage string `json:"errorMessage"`
ErrorCode json.RawMessage `json:"errorCode"`
RequestID *int `json:"requestId"`
}
// ErrorCodeValue returns the upstream errorCode as an int when it is
// numeric and as a string otherwise. Ombi versions disagree on the
// wire shape: some emit the enum as a number, others as a name.
func (e *EngineResult) ErrorCodeValue() (*int, string) {
if len(e.ErrorCode) == 0 || string(e.ErrorCode) == "null" {
return nil, ""
}
var n int
if json.Unmarshal(e.ErrorCode, &n) == nil {
return &n, ""
}
var s string
if json.Unmarshal(e.ErrorCode, &s) == nil {
return nil, s
}
return nil, ""
}
// IdentityResult — DELETE Identity/{userId} and other identity writes
type IdentityResult struct {
Errors []string `json:"errors"`
Successful *bool `json:"successful"`
}
// TesterResultModel — Tester/{radarr|sonarr|lidarr} responses
type TesterResultModel struct {
IsValid *bool `json:"isValid"`
Version string `json:"version"`
ExpectedSubDir string `json:"expectedSubDir"`
AdditionalInformation string `json:"additionalInformation"`
}
// CronTestModel — Settings/testcron response
type CronTestModel struct {
Success *bool `json:"success"`
Message string `json:"message"`
}
// JobSettingsViewModel — Settings/jobs POST response
type JobSettingsViewModel struct {
Result *bool `json:"result"`
Message string `json:"message"`
}