Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEATURE: Movie external IDs #131

Merged
merged 6 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Sources/TMDb/Models/ExternalLink.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Foundation

///
/// An interface for an external link.
///
/// e.g. to a Movie's IMDb page.
///
public protocol ExternalLink: Equatable, Hashable {

///
/// The external site's item identifier.
///
var id: String { get }

///
/// The URL of the external site's item page.
///
var url: URL { get }

}
53 changes: 53 additions & 0 deletions Sources/TMDb/Models/FacebookLink.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import Foundation

///
/// An Facebook external link.
///
/// e.g. to a movie's Facebook profile.
///
public struct FacebookLink: ExternalLink {

///
/// Facebook profile identifier.
///
public let id: String

///
/// URL of the Facebook profile page.
///
public let url: URL

///
/// Creates a Facebook link object using a Facebook profile identifier.
///
/// - Parameter facebookID: The Facebook profile identifier.
///
public init?(facebookID: String?) {
guard
let facebookID,
let url = Self.facebookURL(for: facebookID)
else {
return nil
}

self.init(id: facebookID, url: url)
}

}

extension FacebookLink {

private init(id: String, url: URL) {
self.id = id
self.url = url
}

}

extension FacebookLink {

private static func facebookURL(for facebookID: String) -> URL? {
URL(string: "https://www.facebook.com/\(facebookID)")
}

}
77 changes: 77 additions & 0 deletions Sources/TMDb/Models/IMDbLink.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import Foundation

///
/// An IMDb external link.
///
/// e.g. to a movie's IMDb page.
///
public struct IMDbLink: ExternalLink {

///
/// IMDb identifier.
///
public let id: String

///
/// URL of the IMDb web page.
///
public let url: URL

///
/// Creates an IMDb link object using an IMDb title identifier.
///
/// e.g. for a movie or TV show.
///
/// - Parameter imdbTitleID: The IMDb movie or TV show identifier.
///
public init?(imdbTitleID: String?) {
guard
let imdbTitleID,
let url = Self.imdbURL(forTitle: imdbTitleID)
else {
return nil
}

self.init(id: imdbTitleID, url: url)
}

///
/// Creates an IMDb link object using an IMDb name identifier.
///
/// e.g. for a person.
///
/// - Parameter imdbNameID: The IMDb person identifier.
///
public init?(imdbNameID: String?) {
guard
let imdbNameID,
let url = Self.imdbURL(forName: imdbNameID)
else {
return nil
}

self.init(id: imdbNameID, url: url)
}

}

extension IMDbLink {

private init(id: String, url: URL) {
self.id = id
self.url = url
}

}

extension IMDbLink {

private static func imdbURL(forTitle imdbTitleID: String) -> URL? {
URL(string: "https://www.imdb.com/title/\(imdbTitleID)/")
}

private static func imdbURL(forName nameID: String) -> URL? {
URL(string: "https://www.imdb.com/name/\(nameID)/")
}

}
53 changes: 53 additions & 0 deletions Sources/TMDb/Models/InstagramLink.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import Foundation

///
/// An Instagram external link.
///
/// e.g. to a movie's Instagram profile.
///
public struct InstagramLink: ExternalLink {

///
/// Instagram profile identifier.
///
public let id: String

///
/// URL of the Instagram profile page.
///
public let url: URL

///
/// Creates an Instagram link object using an Instagram profile identifier.
///
/// - Parameter instagramID: The Instagram profile identifier.
///
public init?(instagramID: String?) {
guard
let instagramID,
let url = Self.instagramURL(for: instagramID)
else {
return nil
}

self.init(id: instagramID, url: url)
}

}

extension InstagramLink {

private init(id: String, url: URL) {
self.id = id
self.url = url
}

}

extension InstagramLink {

private static func instagramURL(for instagramID: String) -> URL? {
URL(string: "https://www.instagram.com/\(instagramID)")
}

}
134 changes: 134 additions & 0 deletions Sources/TMDb/Models/MovieExternalLinksCollection.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import Foundation

///
/// A model representing a collection of media databases and social IDs and links for a movie.
///
public struct MovieExternalLinksCollection: Identifiable, Codable, Equatable, Hashable {

///
/// The TMDb movie identifier.
///
public let id: Movie.ID

///
/// IMDb link.
///
public let imdb: IMDbLink?

///
/// WikiData link.
///
public let wikiData: WikiDataLink?

///
/// Facebook link.
///
public let facebook: FacebookLink?

///
/// Instagram link.
///
public let instagram: InstagramLink?

///
/// Twitter link.
///
public let twitter: TwitterLink?

///
/// Creates an external links collection for a movie.
///
/// - Parameters:
/// - id: The TMDb movie identifier.
/// - imdb: IMDb link.
/// - wikiData: WikiData link.
/// - facebook: Facebook link.
/// - instagram: Instagram link.
/// - twitter: Twitter link.
///
public init(
id: Movie.ID,
imdb: IMDbLink? = nil,
wikiData: WikiDataLink? = nil,
facebook: FacebookLink? = nil,
instagram: InstagramLink? = nil,
twitter: TwitterLink? = nil
) {
self.id = id
self.imdb = imdb
self.wikiData = wikiData
self.facebook = facebook
self.instagram = instagram
self.twitter = twitter
}

public func hash(into hasher: inout Hasher) {
hasher.combine(id)
hasher.combine(imdb?.id)
hasher.combine(wikiData?.id)
hasher.combine(facebook?.id)
hasher.combine(instagram?.id)
hasher.combine(twitter?.id)
}

public static func == (lhs: MovieExternalLinksCollection, rhs: MovieExternalLinksCollection) -> Bool {
lhs.id == rhs.id
&& lhs.imdb?.id == rhs.imdb?.id
&& lhs.wikiData?.id == rhs.wikiData?.id
&& lhs.facebook?.id == rhs.facebook?.id
&& lhs.instagram?.id == rhs.instagram?.id
&& lhs.twitter?.id == rhs.twitter?.id
}

}

extension MovieExternalLinksCollection {

private enum CodingKeys: String, CodingKey {
case id
case imdbID = "imdbId"
case wikiDataID = "wikidataId"
case facebookID = "facebookId"
case instagramID = "instagramId"
case twitterID = "twitterId"
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)

let id = try container.decode(Movie.ID.self, forKey: .id)

let imdbID = try container.decodeIfPresent(String.self, forKey: .imdbID)
let wikiDataID = try container.decodeIfPresent(String.self, forKey: .wikiDataID)
let facebookID = try container.decodeIfPresent(String.self, forKey: .facebookID)
let instagramID = try container.decodeIfPresent(String.self, forKey: .instagramID)
let twitterID = try container.decodeIfPresent(String.self, forKey: .twitterID)

let imdbLink = IMDbLink(imdbTitleID: imdbID)
let wikiDataLink = WikiDataLink(wikiDataID: wikiDataID)
let facebookLink = FacebookLink(facebookID: facebookID)
let instagramLink = InstagramLink(instagramID: instagramID)
let twitterLink = TwitterLink(twitterID: twitterID)

self.init(
id: id,
imdb: imdbLink,
wikiData: wikiDataLink,
facebook: facebookLink,
instagram: instagramLink,
twitter: twitterLink
)
}

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)

try container.encode(id, forKey: .id)
try container.encodeIfPresent(imdb?.id, forKey: .imdbID)
try container.encodeIfPresent(wikiData?.id, forKey: .wikiDataID)
try container.encodeIfPresent(facebook?.id, forKey: .facebookID)
try container.encodeIfPresent(instagram?.id, forKey: .instagramID)
try container.encodeIfPresent(twitter?.id, forKey: .twitterID)
}

}
53 changes: 53 additions & 0 deletions Sources/TMDb/Models/TwitterLink.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import Foundation

///
/// A Twitter external link.
///
/// e.g. to a movie's Twitter profile.
///
public struct TwitterLink: ExternalLink {

///
/// Twitter profile identifier.
///
public let id: String

///
/// URL of the Twitter profile page.
///
public let url: URL

///
/// Creates a Twitter link object using a Twitter profile identifier.
///
/// - Parameter twitterID: The Twitter profile identifier.
///
public init?(twitterID: String?) {
guard
let twitterID,
let url = Self.twitterURL(for: twitterID)
else {
return nil
}

self.init(id: twitterID, url: url)
}

}

extension TwitterLink {

private init(id: String, url: URL) {
self.id = id
self.url = url
}

}

extension TwitterLink {

private static func twitterURL(for twitterID: String) -> URL? {
URL(string: "https://www.twitter.com/\(twitterID)")
}

}
Loading