iTunes Movie Release Lookup Swift Script

This Swift script searches the iTunes Store for a movie by title, provided as a command-line argument, and prints the release date of the first matching result. It uses the iTunes Search API and handles errors gracefully with appropriate exit codes

Click to view script…
#!/usr/bin/env swift

import Foundation

// Define structs to match the iTunes Search API response
struct SearchResponse: Codable {
    let resultCount: Int
    let results: [Movie]
}

struct Movie: Codable {
    let trackName: String
    let releaseDate: Date
}

// Check for command-line arguments
if CommandLine.arguments.count < 2 {
    print("Usage: \(CommandLine.arguments[0]) <movie title>")
    exit(1)
}

// Combine all arguments after the script name into a single movie title
let movieTitle = CommandLine.arguments[1...].joined(separator: " ")

// Construct the API URL
let baseURL = "https://itunes.apple.com/search"
let queryItems = [
    URLQueryItem(name: "term", value: movieTitle),
    URLQueryItem(name: "media", value: "movie"),
    URLQueryItem(name: "entity", value: "movie")
]
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  // Explicitly typed as Int32 to match exit() requirement

// 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 from API
        do {
            let searchResponse = try decoder.decode(SearchResponse.self, from: data)
            if searchResponse.resultCount > 0 {
                let movie = searchResponse.results[0] // Take the first result
                let dateFormatter = DateFormatter()
                dateFormatter.dateStyle = .long
                let formattedDate = dateFormatter.string(from: movie.releaseDate)
                print("Release date of \(movie.trackName): \(formattedDate)")
                exitCode = 0
            } else {
                print("No results found for \"\(movieTitle)\".")
                exitCode = 1
            }
        } catch {
            print("Error decoding JSON: \(error)")
            exitCode = 1
        }
    } else {
        print("No data received.")
        exitCode = 1
    }
    semaphore.signal() // Signal completion of the network task
}

// Start the task and wait for it to complete
task.resume()
semaphore.wait()
exit(exitCode)