Skip to content

Commit 03c6406

Browse files
adamayoungclaude
andauthored
✨ Add Movie Service missing endpoints and models (#259)
* 🔧 Add .worktrees/ to .gitignore Add worktree directory to .gitignore to prevent accidentally committing worktree contents when working on multiple features in parallel. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * ✨ Add Movie Service missing endpoints and models Implement Plan 1: Movie Service Additions - adds 9 missing endpoints to achieve 100% API coverage for Movie Service. **New Models:** - AccountStates - User rating, favorite, and watchlist state - AlternativeTitle - Alternative titles by country - Translation<T> - Generic translation model - MovieTranslationData - Movie-specific translation data - Change models - Change tracking for sync/caching - AnyCodable - Type-erased codable for dynamic JSON values **New Methods:** - accountStates(forMovie:session:) - Get user interaction state - addRating(_:toMovie:session:) - Add movie rating - deleteRating(forMovie:session:) - Delete movie rating - alternativeTitles(forMovie:country:language:) - Get alternative titles - translations(forMovie:) - Get movie translations - lists(forMovie:page:language:) - Get lists containing movie - changes(forMovie:startDate:endDate:page:) - Get movie change history - latest() - Get latest movie added to TMDb - changes(startDate:endDate:page:) - Get changed movie IDs **Tests:** - Added comprehensive model tests with JSON fixtures - All 1530 unit tests pass - Uses #require() instead of force unwrapping **Documentation:** - Updated MovieService.md with new method groups - Added all new models to TMDb.md - Documentation builds without warnings **API Coverage:** - Before: 15/24 endpoints (63%) - After: 24/24 endpoints (100%) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * 🐛 Fix linting issues in Movie Service - Fix opening brace spacing in Translation.swift (lines 14 and 84) - Disable type_body_length warning for TMDbMovieService (302 lines with 24+ methods) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * 🎨 Apply code formatting and fix linting issues Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * Add missing tests * Fix integration tests --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 89bc29f commit 03c6406

48 files changed

Lines changed: 2641 additions & 3 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,7 @@ default.profraw
1212
junit-swift-testing.xml
1313

1414
# Claude
15-
.claude/settings.local.json
15+
.claude/settings.local.json
16+
17+
# Git worktrees
18+
.worktrees/

Package.resolved

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Sources/TMDb/Domain/APIClient/APIRequestQueryItem.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,8 @@ extension APIRequestQueryItem.Name {
5656
static let apiKey = APIRequestQueryItem.Name("api_key")
5757
static let externalSource = APIRequestQueryItem.Name("external_source")
5858
static let timezone = APIRequestQueryItem.Name("timezone")
59+
static let country = APIRequestQueryItem.Name("country")
60+
static let startDate = APIRequestQueryItem.Name("start_date")
61+
static let endDate = APIRequestQueryItem.Name("end_date")
5962

6063
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//
2+
// AccountStates.swift
3+
// TMDb
4+
//
5+
// Copyright © 2026 Adam Young.
6+
//
7+
8+
import Foundation
9+
10+
///
11+
/// A model representing the account state for a media item.
12+
///
13+
/// Provides information about whether the media has been rated, added to a watchlist, or marked as favorite
14+
/// by the authenticated user.
15+
///
16+
public struct AccountStates: Codable, Equatable, Hashable, Sendable {
17+
18+
///
19+
/// The media item identifier.
20+
///
21+
public let id: Int
22+
23+
///
24+
/// Indicates if the media is marked as a favorite.
25+
///
26+
public let favorite: Bool
27+
28+
///
29+
/// The user's rating for the media.
30+
///
31+
/// `nil` if the media has not been rated.
32+
///
33+
public let rated: RatedValue?
34+
35+
///
36+
/// Indicates if the media is on the user's watchlist.
37+
///
38+
public let watchlist: Bool
39+
40+
///
41+
/// Creates an account states object.
42+
///
43+
/// - Parameters:
44+
/// - id: The media item identifier.
45+
/// - favorite: Indicates if the media is marked as a favorite.
46+
/// - rated: The user's rating for the media.
47+
/// - watchlist: Indicates if the media is on the user's watchlist.
48+
///
49+
public init(id: Int, favorite: Bool, rated: RatedValue?, watchlist: Bool) {
50+
self.id = id
51+
self.favorite = favorite
52+
self.rated = rated
53+
self.watchlist = watchlist
54+
}
55+
56+
}
57+
58+
public extension AccountStates {
59+
60+
///
61+
/// A model representing a rating value.
62+
///
63+
struct RatedValue: Codable, Equatable, Hashable, Sendable {
64+
65+
///
66+
/// The rating value.
67+
///
68+
/// Valid range: 0.5 to 10.0 in increments of 0.5.
69+
///
70+
public let value: Double
71+
72+
///
73+
/// Creates a rated value object.
74+
///
75+
/// - Parameter value: The rating value.
76+
///
77+
public init(value: Double) {
78+
self.value = value
79+
}
80+
81+
}
82+
83+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//
2+
// AlternativeTitle.swift
3+
// TMDb
4+
//
5+
// Copyright © 2026 Adam Young.
6+
//
7+
8+
import Foundation
9+
10+
///
11+
/// A model representing an alternative title for a media item.
12+
///
13+
public struct AlternativeTitle: Codable, Equatable, Hashable, Sendable {
14+
15+
///
16+
/// The ISO 3166-1 country code.
17+
///
18+
public let countryCode: String
19+
20+
///
21+
/// The alternative title.
22+
///
23+
public let title: String
24+
25+
///
26+
/// The type of alternative title.
27+
///
28+
/// Examples include "Alternative Title", "Working Title", etc.
29+
///
30+
public let type: String?
31+
32+
///
33+
/// Creates an alternative title object.
34+
///
35+
/// - Parameters:
36+
/// - countryCode: The ISO 3166-1 country code.
37+
/// - title: The alternative title.
38+
/// - type: The type of alternative title.
39+
///
40+
public init(countryCode: String, title: String, type: String? = nil) {
41+
self.countryCode = countryCode
42+
self.title = title
43+
self.type = type
44+
}
45+
46+
}
47+
48+
extension AlternativeTitle {
49+
50+
private enum CodingKeys: String, CodingKey {
51+
case countryCode = "iso31661"
52+
case title
53+
case type
54+
}
55+
56+
}
57+
58+
///
59+
/// A model representing a collection of alternative titles.
60+
///
61+
public struct AlternativeTitleCollection: Codable, Equatable, Hashable, Sendable {
62+
63+
///
64+
/// The media item identifier.
65+
///
66+
public let id: Int
67+
68+
///
69+
/// The list of alternative titles.
70+
///
71+
public let titles: [AlternativeTitle]
72+
73+
///
74+
/// Creates an alternative title collection object.
75+
///
76+
/// - Parameters:
77+
/// - id: The media item identifier.
78+
/// - titles: The list of alternative titles.
79+
///
80+
public init(id: Int, titles: [AlternativeTitle]) {
81+
self.id = id
82+
self.titles = titles
83+
}
84+
85+
}

0 commit comments

Comments
 (0)