This Swift script lets you search for a TV show by title from the macOS Terminal, displaying its initial release date and a chronological list of seasons with their release dates, all pulled from the iTunes Store API. Perfect for TV enthusiasts wanting quick access to show timelines!
Click to view script…
#!/usr/bin/env swift
import Foundation
// Define structs to match the iTunes Search API response for TV seasons
struct SearchResponse: Codable {
let resultCount: Int
let results: [TVSeason]
}
struct TVSeason: Codable {
let artistName: String // The TV show's name
let collectionName: String // The season's name
let releaseDate: Date // The season's release date
}
// Check for command-line arguments
if CommandLine.arguments.count < 2 {
print("Usage: \(CommandLine.arguments[0]) <tv show title>")
exit(1)
}
// Combine all arguments after the script name into a single TV show title
let tvShowTitle = CommandLine.arguments[1...].joined(separator: " ")
// Construct the API URL for searching TV seasons
let baseURL = "https://itunes.apple.com/search"
let queryItems = [
URLQueryItem(name: "term", value: tvShowTitle),
URLQueryItem(name: "media", value: "tvShow"),
URLQueryItem(name: "entity", value: "tvSeason"),
URLQueryItem(name: "country", value: "us")
]
var urlComponents = URLComponents(string: baseURL)!
urlComponents.queryItems = queryItems
guard let url = urlComponents.url else {
print("Invalid URL.")
exit(1)
}
// Set up semaphore to handle asynchronous URLSession task
let semaphore = DispatchSemaphore(value: 0)
var exitCode: Int32 = 0 // Exit code for the script
// Perform the network request
let session = URLSession.shared
let task = session.dataTask(with: url) { data, response, error in
if let error = error {
print("Error: \(error.localizedDescription)")
exitCode = 1
} else if let data = data {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601 // Handle ISO 8601 date format
do {
let searchResponse = try decoder.decode(SearchResponse.self, from: data)
if searchResponse.resultCount > 0 {
let seasons = searchResponse.results
let showName = seasons[0].artistName
// Sort seasons by release date
let sortedSeasons = seasons.sorted { $0.releaseDate < $1.releaseDate }
// Display show info and initial release date
if let firstReleaseDate = sortedSeasons.first?.releaseDate {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
let formattedDate = dateFormatter.string(from: firstReleaseDate)
print("TV Show: \(showName)")
print("Initial Release Date: \(formattedDate)")
} else {
print("TV Show: \(showName)")
print("Release date not available.")
}
// List all seasons
print("Seasons:")
for season in sortedSeasons {
let seasonDateFormatter = DateFormatter()
seasonDateFormatter.dateStyle = .long
let seasonFormattedDate = seasonDateFormatter.string(from: season.releaseDate)
print("- \(season.collectionName): \(seasonFormattedDate)")
}
exitCode = 0
} else {
print("No TV show found for \"\(tvShowTitle)\".")
exitCode = 1
}
} catch {
print("Error decoding JSON: \(error)")
exitCode = 1
}
} else {
print("No data received.")
exitCode = 1
}
semaphore.signal() // Signal completion
}
// Start the task and wait for it to complete
task.resume()
semaphore.wait()
exit(exitCode)