summaryrefslogtreecommitdiffstats
path: root/MusicConverter/helpers/MusicKITApi.swift
diff options
context:
space:
mode:
Diffstat (limited to 'MusicConverter/helpers/MusicKITApi.swift')
-rw-r--r--MusicConverter/helpers/MusicKITApi.swift148
1 files changed, 144 insertions, 4 deletions
diff --git a/MusicConverter/helpers/MusicKITApi.swift b/MusicConverter/helpers/MusicKITApi.swift
index 0b394a3..e47241a 100644
--- a/MusicConverter/helpers/MusicKITApi.swift
+++ b/MusicConverter/helpers/MusicKITApi.swift
@@ -72,7 +72,7 @@ class AppleMusicApi: ObservableObject {
do {
let decodedData = try JSONDecoder().decode(musicData<StoreFront>.self, from: data!)
- self.storeFront = decodedData.data.first
+ self.storeFront = decodedData.data!.first
guard self.storeFront != nil else {
completion(.failure(MusicKitError.NoStoreFront))
return
@@ -80,6 +80,7 @@ class AppleMusicApi: ObservableObject {
completion(.success(self.storeFront!.id))
} catch {
print("data: \(String(decoding: data!, as: UTF8.self))")
+ print("error decoding: \(error)")
completion(.failure(error))
return
}
@@ -112,9 +113,10 @@ class AppleMusicApi: ObservableObject {
do {
let decodedData = try JSONDecoder().decode(musicData<Song>.self, from: data!)
- completion(.success(decodedData.data))
+ completion(.success(decodedData.data!))
} catch {
print("data: \(String(decoding: data!, as: UTF8.self))")
+ print("error song: \(error)")
completion(.failure(error))
return
}
@@ -207,6 +209,8 @@ class AppleMusicApi: ObservableObject {
}
pos += 1;
self.fetchForIsrc(isrc: isrc!, completion: callback)
+ } else {
+ completion(nil)
}
}
}
@@ -226,8 +230,144 @@ class AppleMusicApi: ObservableObject {
self.fetchForIsrc(isrc: isrc!, completion: callback)
}
+ public func createPlaylistAPI(name: String, tracks: [LibraryPlaylistRequestTrack]? = nil, description: String? = nil, completion: @escaping (Result<[LibraryPlaylist], Error>) -> Void) {
+ let request = LibraryPlaylistCreationRequest(name: name, tracks: tracks, description: description)
+ createPlaylistAPI(creationRequest: request, completion: completion)
+ }
+
+ public func createPlaylistAPI(creationRequest: LibraryPlaylistCreationRequest, completion: @escaping (Result<[LibraryPlaylist], Error>) -> Void) {
+
+
+ guard let url = URL(string: "https://api.music.apple.com/v1/me/library/playlists") else {
+ completion(.failure(MusicKitError.InvalidUrl))
+ return
+ }
+ var playlistRequest = self.buildRequest(url: url)
+ playlistRequest.httpMethod = "POST"
+ playlistRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
+ do {
+ playlistRequest.httpBody = try JSONEncoder().encode(creationRequest)
+ let str = String(data: playlistRequest.httpBody!, encoding: .utf8)
+ print("request: \(str!)")
+ } catch {
+ completion(.failure(error))
+ return
+ }
+
+ URLSession.shared.dataTask(with: playlistRequest) { (data, response, error) in
+ guard error == nil else {
+ completion(.failure(error!))
+ return
+ }
+
+ do {
+ let decodedData = try JSONDecoder().decode(musicData<LibraryPlaylist>.self, from: data!)
+ if decodedData.hasError {
+ decodedData.printErrors()
+ completion(.failure(decodedData.errors!.first!))
+ return
+ }
+ completion(.success(decodedData.data!))
+ } catch {
+ print("error playlistCreationRequest: \(error)")
+ print("json response: \(String(data: data!, encoding: .utf8) ?? "error")")
+ completion(.failure(error))
+ return
+ }
+ //completion(.success())
+ }
+ .resume()
+ }
+
+ // TODO: https://developer.apple.com/documentation/applemusicapi/responseroot
struct musicData<T: Decodable>: Decodable {
- var data: [T]
+ var data: [T]?
+ var errors: [ResposeError]?
+
+ var hasError: Bool {
+ return errors != nil && errors?.count ?? 0 > 0
+ }
+
+ func printErrors() {
+ for error in errors ?? [] {
+ print("error: \(error)")
+ }
+ }
+
+ public struct ResposeError: Codable, Error {
+ var code: String
+ var detail: String?
+ var id: String
+ // var source
+ var status: String
+ var title: String
+ }
+ }
+
+ public struct LibraryPlaylistCreationRequest: Codable {
+ var attributes: Attributes
+ var relationships: Relationships?
+
+ init(name: String, tracks: [LibraryPlaylistRequestTrack]? = nil, description: String? = nil) {
+ self.attributes = Attributes(name: name, description: description)
+
+ if let tracks = tracks {
+ self.relationships = Relationships(tracks: Relationships.TracksData(data: tracks))
+ }
+ }
+
+ public struct Attributes: Codable {
+ var name: String
+ var description: String?
+ }
+
+ public struct Relationships: Codable {
+ var tracks: TracksData
+
+ public struct TracksData: Codable {
+ var data: [LibraryPlaylistRequestTrack]
+ }
+ }
+ }
+
+ public struct LibraryPlaylistRequestTrack: Codable, Identifiable {
+ var id: String
+ var type: TrackType = .songs
+
+ public enum TrackType: String, Codable {
+ case songs = "songs"
+ case music_videos = "music-videos"
+ case library_songs = "library-songs"
+ case library_music_videos = "library-music-videos"
+ }
+ }
+
+ public struct LibraryPlaylist: Decodable {
+ var attributes: Attributes?
+ //var relationships: Relationships?
+ var type: String
+ var id: String
+
+ /*var id: String? {
+ attributes?.playParams?.id
+ }*/
+
+ var name: String? {
+ attributes?.name
+ }
+
+ public struct Attributes: Decodable {
+ var artwork: Song.Attributes.Artwork?
+ //var description: String?
+ var name: String
+ var playParams: Song.Attributes.PlayParameters?
+ var canEdit: Bool
+ }
+
+ // TODO
+ public struct Relationships: Decodable {
+
+ }
}
public struct StoreFront: Decodable {
@@ -289,7 +429,7 @@ class AppleMusicApi: ObservableObject {
var genreNames: [String]
var isrc: String
var name: String
- var playParams: PlayParameters
+ var playParams: PlayParameters?
// var previews: [Preview] (required)
var releaseDate: String
/// (Required) The number of the song in the album’s track list.