Skip to content

Commit

Permalink
Query different languages and release tracks
Browse files Browse the repository at this point in the history
  • Loading branch information
bilaalrashid committed Jun 4, 2024
1 parent 79e27cb commit 1484bed
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 16 deletions.
72 changes: 56 additions & 16 deletions Sources/BbcNews/BbcNews.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ public struct BbcNews {
/// The hostname at which the API is hosted at.
public static let hostname = "news-app.api.bbc.co.uk"

/// The value of `clientName` in API network requests.
private static let clientName = "Chrysalis"

/// The value of `clientVersion` in API network requests.
private static let clientVersion = "pre-7"

Expand All @@ -52,18 +49,25 @@ public struct BbcNews {

/// Converts a BBC News webpage URL to a native API URL that returns a JSON representation, if one exists.
///
/// - Parameter urlString: The web URL to convert.
/// - Parameters:
/// - urlString: The language that results should be localised for.
/// - language: The language that results should be localised for.
/// - release: The release track of the API version.
/// - Returns: The native API URL, if successful.
public static func convertWebUrlToApi(urlString: String) -> String? {
public static func convertWebUrlToApi(urlString: String, language: Language = .english, release: ReleaseTrack? = nil) -> String? {
guard let url = URL(string: urlString) else { return nil }
return BbcNews.convertWebUrlToApi(url: url)?.absoluteString
let result = BbcNews.convertWebUrlToApi(url: url, language: language, release: release)
return result?.absoluteString
}

/// Converts a BBC News webpage URL to a native API URL that returns a JSON representation, if one exists.
///
/// - Parameter url: The web URL to convert.
/// - Parameters:
/// - urlString: The language that results should be localised for.
/// - language: The language that results should be localised for.
/// - release: The release track of the API version.
/// - Returns: The native API URL, if successful.
public static func convertWebUrlToApi(url: URL) -> URL? {
public static func convertWebUrlToApi(url: URL, language: Language = .english, release: ReleaseTrack? = nil) -> URL? {
let regex = #/https?:\/\/(www\.)?bbc\.co(m|\.uk)\/news\/(\w|\-|\/)+(\.app)?$/#

// swiftlint:disable:next unused_optional_binding
Expand All @@ -76,11 +80,15 @@ public struct BbcNews {
components.host = "news-app.api.bbc.co.uk"
components.path = "/fd/app-article-api"
components.queryItems = [
URLQueryItem(name: "clientName", value: self.clientName),
URLQueryItem(name: "clientName", value: language.clientName),
URLQueryItem(name: "clientVersion", value: self.clientVersion),
URLQueryItem(name: "page", value: url.absoluteString)
]

if let release = release {
components.queryItems?.append(URLQueryItem(name: "release", value: release.rawValue))
}

return components.url
}

Expand All @@ -89,6 +97,12 @@ public struct BbcNews {
/// The session to perform network requests from.
private let session: URLSession

/// The language that API results should be localised for.
private let language: Language

/// The release track of the API version.
private let releaseTrack: ReleaseTrack?

// MARK: - Instance methods

#if canImport(UIKit)
Expand All @@ -101,7 +115,9 @@ public struct BbcNews {
/// - modelIdentifier: The model identifier of the device e.g. iPhone15,2,
/// - systemName: The name of the operating system e.g. iOS.
/// - systemVersion: The version of the operating system e.g. 16.6.
public init() {
/// - language: The language that results should be localised for.
/// - release: The release track of the API version.
public init(language: Language = .english, release: ReleaseTrack? = nil) {
self.init(
modelIdentifier: UIDevice.current.modelIdentifier,
systemName: UIDevice.current.systemName,
Expand All @@ -118,17 +134,28 @@ public struct BbcNews {
/// - modelIdentifier: The model identifier of the device e.g. iPhone15,2,
/// - systemName: The name of the operating system e.g. iOS.
/// - systemVersion: The version of the operating system e.g. 16.6.
public init(modelIdentifier: String, systemName: String, systemVersion: String) {
/// - language: The language that results should be localised for.
/// - release: The release track of the API version.
public init(
modelIdentifier: String,
systemName: String,
systemVersion: String,
language: Language = .english,
release: ReleaseTrack? = nil
) {
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = [
// Pretend to be the BBC News app
// Example: BBCNews/25339 (iPhone15,2; iOS 16.6) BBCHTTPClient/9.0.0
"User-Agent": "BBCNews/25625 (\(modelIdentifier); \(systemName) \(systemVersion)) BBCHTTPClient/10.0.0"
]

self.session = URLSession(configuration: configuration)
self.language = language
self.releaseTrack = nil
}

/// Fetches the main discovery page of the BBC News app i.e. the page shown in the Home tab
/// Fetches the main discovery page of the BBC News app i.e. the page shown in the Home tab.
///
/// - Parameter postcode: The first part of the user's UK postcode e.g. W1A.
/// - Returns: The index discovery page.
Expand All @@ -138,13 +165,21 @@ public struct BbcNews {
components.host = BbcNews.hostname
components.path = "/fd/abl"
components.queryItems = [
URLQueryItem(name: "clientName", value: BbcNews.clientName),
URLQueryItem(name: "clientName", value: self.language.clientName),
URLQueryItem(name: "clientVersion", value: BbcNews.clientVersion),
URLQueryItem(name: "page", value: "chrysalis_discovery"),
URLQueryItem(name: "service", value: "news"),
URLQueryItem(name: "service", value: self.language.service),
URLQueryItem(name: "type", value: "index")
]

if let postcode = postcode {
components.queryItems?.append(URLQueryItem(name: "clientLoc", value: postcode))
}

if let release = self.releaseTrack {
components.queryItems?.append(URLQueryItem(name: "release", value: release.rawValue))
}

if let url = components.url {
return try await self.fetch(url: url)
}
Expand All @@ -160,7 +195,8 @@ public struct BbcNews {
var results = [FDResult]()

for topicId in topicIds {
results.append(try await self.fetchTopicDiscoveryPage(for: topicId))
let result = try await self.fetchTopicDiscoveryPage(for: topicId)
results.append(result)
}

return results
Expand All @@ -176,12 +212,16 @@ public struct BbcNews {
components.host = BbcNews.hostname
components.path = "/fd/abl"
components.queryItems = [
URLQueryItem(name: "clientName", value: BbcNews.clientName),
URLQueryItem(name: "clientName", value: self.language.clientName),
URLQueryItem(name: "clientVersion", value: BbcNews.clientVersion),
URLQueryItem(name: "page", value: topicId),
URLQueryItem(name: "type", value: "topic")
]

if let release = self.releaseTrack {
components.queryItems?.append(URLQueryItem(name: "release", value: release.rawValue))
}

if let url = components.url {
return try await self.fetch(url: url)
}
Expand Down
65 changes: 65 additions & 0 deletions Sources/BbcNews/Models/Request/Language.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// Language.swift
// BbcNews
//
// Created by Bilaal Rashid on 04/06/2024.
//

import Foundation

/// A language supported by the API.
public enum Language: Codable, Equatable, Hashable {
/// The Arabic language.
case arabic

Check failure on line 14 in Sources/BbcNews/Models/Request/Language.swift

View workflow job for this annotation

GitHub Actions / Lint

Lines should not have trailing whitespace (trailing_whitespace)
/// The Cymru language.
case cymru

Check failure on line 17 in Sources/BbcNews/Models/Request/Language.swift

View workflow job for this annotation

GitHub Actions / Lint

Lines should not have trailing whitespace (trailing_whitespace)
/// The English language.
case english

/// The Hindi language.
case hindi

/// The Mundo language.
case mundo

/// The Russian language.
case russian

/// The value of the `clientName` URL parameter to use when calling the API for this language.
var clientName: String {
switch self {
case .arabic:
return "Arabic"
case .cymru:
return "Cymru"
case .english:
return "Chrysalis"
case .hindi:
return "Hindi"
case .mundo:
return "Mundo"
case .russian:
return "Russian"
}
}

/// The value of the `service` URL parameter to use when calling the API for this language.
var service: String {
switch self {
case .arabic:
return "arabic"
case .cymru:
return "cymrufyw"
case .english:
return "news"
case .hindi:
return "hindi"
case .mundo:
return "mundo"
case .russian:
return "russian"
}
}
}
17 changes: 17 additions & 0 deletions Sources/BbcNews/Models/Request/ReleaseTrack.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// ReleaseTrack.swift
// BbcNews
//
// Created by Bilaal Rashid on 04/06/2024.
//

import Foundation

/// A release track for the API.
public enum ReleaseTrack: String, Codable, Equatable, Hashable {
/// The `public-alpha` release track.
case publicAlpha = "public-alpha"

/// The `team` release track.
case team = "team"
}

0 comments on commit 1484bed

Please sign in to comment.