Commit 7eb54a69 by Dmitry Stepanets

Started implementing GraphQL integration

parent ce28bbd2
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
<Workspace <Workspace
version = "1.0"> version = "1.0">
<FileRef <FileRef
location = "group:InMobiGraphQLSource/InMobiGraphQLSource.xcodeproj">
</FileRef>
<FileRef
location = "group:InMobiShortsSource/InMobiShortsSource.xcodeproj"> location = "group:InMobiShortsSource/InMobiShortsSource.xcodeproj">
</FileRef> </FileRef>
<FileRef <FileRef
......
//
// InMobiGraphQLSource.h
// InMobiGraphQLSource
//
// Created by Dmitry Stepanets on 24.09.2021.
//
#import <Foundation/Foundation.h>
//! Project version number for InMobiGraphQLSource.
FOUNDATION_EXPORT double InMobiGraphQLSourceVersionNumber;
//! Project version string for InMobiGraphQLSource.
FOUNDATION_EXPORT const unsigned char InMobiGraphQLSourceVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <InMobiGraphQLSource/PublicHeader.h>
//
// InMobiGraphQLSource.swift
// InMobiGraphQLSource
//
// Created by Dmitry Stepanets on 24.09.2021.
//
import Foundation
import OneWeatherCore
import OneWeatherAnalytics
public enum InMobiGraphQLSourceError: Error {
case badUrl
case invalidIds
case networkError(Error?)
case badServerResponse(Error?)
case dataEncodingError(String)
}
public class InMobiGraphQLSource: ShortSource {
private let log = Logger(componentName: "InMobiGraphQLSource")
private let baseURL = "https://graphql.contentful.com/content/v1/spaces/f2vk0k553nc3/environments/master"
private let token = "oxH_tXQAzlST37BSR_IGFZUNht65YUZEYLsiFl8OXJQ"
private let formatter: DateFormatter = {
let fmt = DateFormatter()
fmt.dateFormat = "yyyy-MM-dd'T'hh:mm:ss.sssZ"
return fmt
}()
public init() {}
public func updateShorts(completion: @escaping ShortsSourceCompletion) {
guard let url = URL(string: baseURL) else {
completion(nil, InMobiGraphQLSourceError.badUrl)
return
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
let dateString = formatter.string(from: Date())
let graphQLString = """
{"query {
weatherCardObjectCollection(where: {
AND: [ { expiredAt_gte: "\(dateString)" } ],
}) {
items {
shortsCategories,
sourceUrl,
buttonText,
publishedAt
mediaArrayObjectCollection {
items {
... on WImageObject {
title,
summary
image
}
}
}
sys {
id
}
}
}
}
"""
guard let bodyData = graphQLString.data(using: .utf8) else {
completion(nil, InMobiGraphQLSourceError.dataEncodingError("Invalid GraphQL body"))
return
}
request.httpBody = bodyData
let dataTask = URLSession.shared.dataTask(with: request) { data, response, error in
guard error == nil else {
self.log.debug("Network response: error \(String(describing: error))")
completion(nil, InMobiGraphQLSourceError.networkError(error))
return
}
guard let data = data else {
self.log.debug("Network response: error Invalid data")
completion(nil, InMobiGraphQLSourceError.dataEncodingError("Invalid data"))
return
}
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .useDefaultKeys
do {
let graphQLResponse = try decoder.decode(GrapQLResponse.self, from: data)
}
catch {
}
}
dataTask.resume()
}
private func toAppModel(item: WeatherCardItem) -> ShortsItem {
ShortsItem(id: UUID().uuidString,
images: <#T##[ShortsItemImage]#>,
overlayImages: <#T##[ShortsItemImage]#>,
updatedAtInSecs: <#T##TimeInterval#>,
startsAtInSecs: <#T##TimeInterval#>,
endsAtInSecs: <#T##TimeInterval#>,
shareURL: <#T##URL?#>,
title: <#T##String#>,
summaryText: <#T##String#>,
sourceName: <#T##String#>,
heartCount: <#T##Int#>,
shortURL: <#T##URL?#>,
ctaText: <#T##String#>,
ctaURL: <#T##URL?#>,
likeCount: <#T##Int#>,
shareCount: <#T##Int#>)
}
}
//
// GraphQLResponse.swift
// InMobiGraphQLSource
//
// Created by Dmitry Stepanets on 24.09.2021.
//
import Foundation
private struct Data: Codable {
let weatherCardObjectCollection: WeatherCardObjectCollection
}
private struct WeatherCardObjectCollection: Codable {
let items: [WeatherCardItem]
}
struct GrapQLResponse: Codable {
private let data: Data
var weatherItems: [WeatherCardItem] {
return data.weatherCardObjectCollection.items
}
}
//
// MediaArrayObjectCollection.swift
// InMobiGraphQLSource
//
// Created by Dmitry Stepanets on 24.09.2021.
//
import Foundation
struct MediaArrayObjectCollection: Codable {
}
//
// MediaObjectImage.swift
// InMobiGraphQLSource
//
// Created by Dmitry Stepanets on 24.09.2021.
//
import Foundation
struct MediaObjectImageItem: Codable {
let lowresolution: URL
let highresolution: URL
}
struct MediaObjectImage: Codable {
let baseImage: [MediaObjectImageItem]
let overlayImage: [MediaObjectImageItem]
}
//
// MediaObjectItem.swift
// InMobiGraphQLSource
//
// Created by Dmitry Stepanets on 24.09.2021.
//
import Foundation
struct MediaObjectItem: Codable {
let title: String
let summary: String
let image: MediaObjectImage
}
//
// WeatherCardItem.swift
// InMobiGraphQLSource
//
// Created by Dmitry Stepanets on 24.09.2021.
//
import Foundation
struct WeatherCardItem: Codable {
let shortsCategores: String
let sourceUrl: URL
let buttonText: String
let publishedAt: Date
let mediaArrayObjectCollection: MediaArrayObjectCollection
}
//
// InMobiGraphQLSourceTests.swift
// InMobiGraphQLSourceTests
//
// Created by Dmitry Stepanets on 24.09.2021.
//
import XCTest
@testable import InMobiGraphQLSource
class InMobiGraphQLSourceTests: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
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.
}
func testPerformanceExample() throws {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment