From 84b2608615c0af00e3716e98a66e7f2e7f1b208c Mon Sep 17 00:00:00 2001 From: Hamad Fuad Date: Wed, 13 Apr 2022 12:56:01 +0300 Subject: [PATCH] Initial Commit --- Package.swift | 4 +- README.md | 35 +++++- .../AppStoreReviewsAPI.swift | 41 ++++++- .../Models/Author/Author.swift | 18 +++ .../Models/Entry/Entry.swift | 109 ++++++++++++++++++ Sources/AppStoreReviewsAPI/Models/ID/ID.swift | 13 +++ .../AppStoreReviewsAPI/Models/Icon/Icon.swift | 13 +++ .../AppStoreReviewsAPI/Models/Link/Link.swift | 20 ++++ .../Models/ReviewsFeed.swift | 25 ++++ .../Models/Rights/Rights.swift | 13 +++ .../Models/Title/Title.swift | 13 +++ .../Models/Updated/Updated.swift | 13 +++ .../AppStoreReviewsAPITests.swift | 24 +++- 13 files changed, 332 insertions(+), 9 deletions(-) create mode 100644 Sources/AppStoreReviewsAPI/Models/Author/Author.swift create mode 100644 Sources/AppStoreReviewsAPI/Models/Entry/Entry.swift create mode 100644 Sources/AppStoreReviewsAPI/Models/ID/ID.swift create mode 100644 Sources/AppStoreReviewsAPI/Models/Icon/Icon.swift create mode 100644 Sources/AppStoreReviewsAPI/Models/Link/Link.swift create mode 100644 Sources/AppStoreReviewsAPI/Models/ReviewsFeed.swift create mode 100644 Sources/AppStoreReviewsAPI/Models/Rights/Rights.swift create mode 100644 Sources/AppStoreReviewsAPI/Models/Title/Title.swift create mode 100644 Sources/AppStoreReviewsAPI/Models/Updated/Updated.swift diff --git a/Package.swift b/Package.swift index 8f7df35..d263263 100644 --- a/Package.swift +++ b/Package.swift @@ -5,6 +5,7 @@ import PackageDescription let package = Package( name: "AppStoreReviewsAPI", + platforms: [.iOS(.v15), .macOS(.v12), .tvOS(.v15)], products: [ // Products define the executables and libraries a package produces, and make them visible to other packages. .library( @@ -20,7 +21,8 @@ let package = Package( // Targets can depend on other targets in this package, and on products in packages this package depends on. .target( name: "AppStoreReviewsAPI", - dependencies: []), + dependencies: [], + path: "Sources"), .testTarget( name: "AppStoreReviewsAPITests", dependencies: ["AppStoreReviewsAPI"]), diff --git a/README.md b/README.md index bcc37fa..f45477d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,36 @@ +![swift workflow](https://github.com/ihamadfuad/AppStoreReviewsAPI/actions/workflows/swift.yml/badge.svg) [![codecov](https://codecov.io/gh/ihamadfuad/AppStoreReviewsAPI/branch/main/graph/badge.svg?token=W9KO1BG8S0)](https://codecov.io/gh/ihamadfuad/AppStoreReviewsAPI) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ![Issues](https://img.shields.io/github/issues/ihamadfuad/AppStoreReviewsAPI) ![Releases](https://img.shields.io/github/v/release/ihamadfuad/AppStoreReviewsAPI) + # AppStoreReviewsAPI -A description of this package. +A Swift 5.6 implementation of iTunes customer reviews. Retrieve customer reviews for your app and display most helpful +reviews. + +## Installation +### Swift Package Manager (SPM) + +You can use The Swift Package Manager to install SwiftEmailValidator by adding it to your Package.swift file: + + import PackageDescription + + let package = Package( + name: "MyApp", + targets: [], + dependencies: [ + .Package(url: "https://github.com/ekscrypto/SwiftEmailValidator.git", .upToNextMajor(from: "1.0.0")) + ] + ) + +### Usage + +```swift +let appStore = AppStoreReviewsAPI(appID: "310633997") // This app id belongs to WhatsApp +let reviews = try await appStore.reviews() + +reviews.feed.entry.forEach { + + print("Rating: ", $0.imRating.label) + print($0.title.label) + print($0.content.label) + print(" +---------------------------------------------------+ ") +} +``` diff --git a/Sources/AppStoreReviewsAPI/AppStoreReviewsAPI.swift b/Sources/AppStoreReviewsAPI/AppStoreReviewsAPI.swift index 570400d..a005118 100644 --- a/Sources/AppStoreReviewsAPI/AppStoreReviewsAPI.swift +++ b/Sources/AppStoreReviewsAPI/AppStoreReviewsAPI.swift @@ -1,6 +1,43 @@ +import Foundation + +extension String: Error { } + public struct AppStoreReviewsAPI { - public private(set) var text = "Hello, World!" - public init() { + public enum Sortby: String, Decodable { + + case mostHelpful = "mosthelpful" + case mostRecent = "mostrecent" + } + + var appID = String() + var page: String = "1" + var sortBy: Sortby = .mostHelpful + + private var url: String? + + public init(appID: String, page: String = "1", sortBy: Sortby = .mostHelpful) { + + self.appID = appID + self.page = page + self.sortBy = sortBy + + url = "https://itunes.apple.com/rss/customerreviews/page=" + page + "/id=" + appID + "/sortby=" + sortBy.rawValue + "/json?l=en&cc=gb" + } + + func reviews() async throws -> ReviewsFeed { + + guard let urlString = url, + let url = URL(string: urlString) + else { + throw "\(#function) Line: \(#line) - URL is nil" + } + + let (data, _) = try await URLSession.shared.data(for: URLRequest(url: url), delegate: nil) + + let decoder = JSONDecoder() + decoder.dateDecodingStrategy = .iso8601 + + return try decoder.decode(ReviewsFeed.self, from: data) } } diff --git a/Sources/AppStoreReviewsAPI/Models/Author/Author.swift b/Sources/AppStoreReviewsAPI/Models/Author/Author.swift new file mode 100644 index 0000000..c6473fd --- /dev/null +++ b/Sources/AppStoreReviewsAPI/Models/Author/Author.swift @@ -0,0 +1,18 @@ +// +// Author.swift +// +// +// Created by Hamad Ali on 13/04/2022. +// + +import Foundation + +struct Author: Decodable { + + let name, uri: URI +} + +struct URI: Decodable { + + let label: String +} diff --git a/Sources/AppStoreReviewsAPI/Models/Entry/Entry.swift b/Sources/AppStoreReviewsAPI/Models/Entry/Entry.swift new file mode 100644 index 0000000..2b14532 --- /dev/null +++ b/Sources/AppStoreReviewsAPI/Models/Entry/Entry.swift @@ -0,0 +1,109 @@ +// +// Entry.swift +// +// +// Created by Hamad Ali on 13/04/2022. +// + +import Foundation + +struct Entry: Decodable { + + let author: EntryAuthor + let updated: Updated + let imRating, imVersion, id: ID + let title: Title + let content: Content + let link: EntryLink + let imVoteSum: Vote + let imContentType: IMContentType + let imVoteCount: Vote + + enum CodingKeys: String, CodingKey { + + case author, updated + case imRating = "im:rating" + case imVersion = "im:version" + case id, title, content, link + case imVoteSum = "im:voteSum" + case imContentType = "im:contentType" + case imVoteCount = "im:voteCount" + } +} + +// MARK: - Author +struct EntryAuthor: Decodable { + + let uri, name: ID + let label: String +} + +// MARK: - Content +struct Content: Decodable { + + let label: String + let attributes: ContentAttributes +} + +// MARK: - ContentAttributes +struct ContentAttributes: Decodable { + + let type: TypeEnum +} + +enum TypeEnum: String, Decodable { + + case text = "text" +} + +// MARK: - Vote +struct Vote: Decodable { + + let label: String +} + +// MARK: - IMContentType +struct IMContentType: Decodable { + + let attributes: IMContentTypeAttributes +} + +// MARK: - IMContentTypeAttributes +struct IMContentTypeAttributes: Decodable { + + let term, label: Label +} + +enum Label: String, Decodable { + + case application = "Application" +} + +// MARK: - EntryLink +struct EntryLink: Decodable { + + let attributes: LinkAttributes +} + +// MARK: - LinkAttributes +struct LinkAttributes: Decodable { + + let rel: String + let href: String +} + + + + + + + + + + + + + + + + diff --git a/Sources/AppStoreReviewsAPI/Models/ID/ID.swift b/Sources/AppStoreReviewsAPI/Models/ID/ID.swift new file mode 100644 index 0000000..4b9fe0b --- /dev/null +++ b/Sources/AppStoreReviewsAPI/Models/ID/ID.swift @@ -0,0 +1,13 @@ +// +// ID.swift +// +// +// Created by Hamad Ali on 13/04/2022. +// + +import Foundation + +struct ID: Decodable { + + let label: String +} diff --git a/Sources/AppStoreReviewsAPI/Models/Icon/Icon.swift b/Sources/AppStoreReviewsAPI/Models/Icon/Icon.swift new file mode 100644 index 0000000..7678e26 --- /dev/null +++ b/Sources/AppStoreReviewsAPI/Models/Icon/Icon.swift @@ -0,0 +1,13 @@ +// +// Icon.swift +// +// +// Created by Hamad Ali on 13/04/2022. +// + +import Foundation + +struct Icon: Decodable { + + let label: String +} diff --git a/Sources/AppStoreReviewsAPI/Models/Link/Link.swift b/Sources/AppStoreReviewsAPI/Models/Link/Link.swift new file mode 100644 index 0000000..a33dfa3 --- /dev/null +++ b/Sources/AppStoreReviewsAPI/Models/Link/Link.swift @@ -0,0 +1,20 @@ +// +// Link.swift +// +// +// Created by Hamad Ali on 13/04/2022. +// + +import Foundation + +struct Link: Decodable { + + let attributes: Attributes +} + +struct Attributes: Decodable { + + let rel: String + let type: String? + let href: String +} diff --git a/Sources/AppStoreReviewsAPI/Models/ReviewsFeed.swift b/Sources/AppStoreReviewsAPI/Models/ReviewsFeed.swift new file mode 100644 index 0000000..a89e536 --- /dev/null +++ b/Sources/AppStoreReviewsAPI/Models/ReviewsFeed.swift @@ -0,0 +1,25 @@ +// +// ReviewsFeed.swift +// +// +// Created by Hamad Ali on 13/04/2022. +// + +import Foundation + +struct ReviewsFeed: Decodable { + + let feed: Feed +} + +struct Feed: Decodable { + + let id: ID + let author: Author + let entry: [Entry] + let updated: Updated + let rights: Rights + let title: Title + let icon: Icon + let link: [Link] +} diff --git a/Sources/AppStoreReviewsAPI/Models/Rights/Rights.swift b/Sources/AppStoreReviewsAPI/Models/Rights/Rights.swift new file mode 100644 index 0000000..a690e60 --- /dev/null +++ b/Sources/AppStoreReviewsAPI/Models/Rights/Rights.swift @@ -0,0 +1,13 @@ +// +// Rights.swift +// +// +// Created by Hamad Ali on 13/04/2022. +// + +import Foundation + +struct Rights: Decodable { + + let label: String +} diff --git a/Sources/AppStoreReviewsAPI/Models/Title/Title.swift b/Sources/AppStoreReviewsAPI/Models/Title/Title.swift new file mode 100644 index 0000000..d25a5f4 --- /dev/null +++ b/Sources/AppStoreReviewsAPI/Models/Title/Title.swift @@ -0,0 +1,13 @@ +// +// Title.swift +// +// +// Created by Hamad Ali on 13/04/2022. +// + +import Foundation + +struct Title: Decodable { + + let label: String +} diff --git a/Sources/AppStoreReviewsAPI/Models/Updated/Updated.swift b/Sources/AppStoreReviewsAPI/Models/Updated/Updated.swift new file mode 100644 index 0000000..e75ab4e --- /dev/null +++ b/Sources/AppStoreReviewsAPI/Models/Updated/Updated.swift @@ -0,0 +1,13 @@ +// +// Updated.swift +// +// +// Created by Hamad Ali on 13/04/2022. +// + +import Foundation + +struct Updated: Decodable { + + let label: Date +} diff --git a/Tests/AppStoreReviewsAPITests/AppStoreReviewsAPITests.swift b/Tests/AppStoreReviewsAPITests/AppStoreReviewsAPITests.swift index fc35272..74736f9 100644 --- a/Tests/AppStoreReviewsAPITests/AppStoreReviewsAPITests.swift +++ b/Tests/AppStoreReviewsAPITests/AppStoreReviewsAPITests.swift @@ -2,10 +2,24 @@ import XCTest @testable import AppStoreReviewsAPI final class AppStoreReviewsAPITests: XCTestCase { - func testExample() throws { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct - // results. - XCTAssertEqual(AppStoreReviewsAPI().text, "Hello, World!") + + func testAppStoreReviews() async throws { + + print("Get reviews") + + let appStore = AppStoreReviewsAPI(appID: "310633997") + let reviews = try await appStore.reviews() + + print("Reviews: ") + + reviews.feed.entry.forEach { + + print("Rating: ", $0.imRating.label) + print($0.title.label) + print($0.content.label) + print(" +---------------------------------------------------+ ") + } + + XCTAssertGreaterThanOrEqual(reviews.feed.entry.count, 0, "Success") } }