deep-linking-sample/Apps/Wikipedia/Command Line Tools/Update Languages/WikipediaLanguageCommandLineUtility.swift
Javier Cicchelli 9bcdaa697b [Setup] Basic project structure (#1)
This PR contains all the work related to setting up this project as required to implement the [Assignment](https://repo.rock-n-code.com/rock-n-code/deep-linking-assignment/wiki/Assignment) on top, as intended.

To summarise this work:
- [x] created a new **Xcode** project;
- [x] cloned the `Wikipedia` app and inserted it into the **Xcode** project;
- [x] created the `Locations` app and also, its `Libraries` package;
- [x] created the `Shared` package to share dependencies between the apps;
- [x] added a `Makefile` file and implemented some **environment** and **help** commands.

Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Reviewed-on: rock-n-code/deep-linking-assignment#1
2023-04-08 18:37:13 +00:00

107 lines
4.4 KiB
Swift

import Foundation
import Combine
/// Command line tool for updating prebuilt language lists and lookup tables used in the app
class WikipediaLanguageCommandLineUtility {
let pathComponents: [String]
let api = WikipediaLanguageCommandLineUtilityAPI()
/// - Parameter path: the path to the wikipedia-ios project folder
init(path: String) {
pathComponents = path.components(separatedBy: "/")
}
var cancellable: AnyCancellable?
/// Generates all the necessary files
func run(_ completion: @escaping () -> Void) {
cancellable = api.getSites().sink(receiveCompletion: { (result) in
switch result {
case .failure(let error):
print("Error fetching sites: \(error)")
abort()
default:
break
}
}) { (sites) in
let sortedSites = sites.sorted { (a, b) -> Bool in
return a.languageCode < b.languageCode
}
self.writeCodable(sortedSites, to: ["Wikipedia", "Code", "wikipedia-languages.json"])
self.cancellable = self.writeNamespaceFiles(with: sites) {
self.cancellable = self.writeCodemirrorConfig(with: sites, completion: {
completion()
})
}
}
}
private func getOutputFileURL(with components: [String]) -> URL {
let outputComponents = pathComponents + components
let outputPath = outputComponents.joined(separator: "/")
return URL(fileURLWithPath: outputPath)
}
private func writeCodable<T: Codable>(_ codable: T, to pathComponents: [String]) {
do {
let encoder = JSONEncoder()
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
let data = try encoder.encode(codable)
let outputFileURL = getOutputFileURL(with: pathComponents)
try data.write(to: outputFileURL)
} catch let error {
print("Error writing to file: \(error)")
}
}
private func writeCodemirrorConfig(with sites: [Wikipedia], completion: @escaping () -> Void) -> AnyCancellable {
Publishers.MergeMany(sites.map { site in
api.getCodeMirrorConfigJSON(for: site.languageCode)
.map { ($0, site) }
})
.sink(receiveCompletion: { (result) in
switch result {
case .finished:
break
case .failure(let error):
print("Error writing codemirror config: \(error)")
}
completion()
}) { (value) in
let outputURL = self.getOutputFileURL(with: ["Wikipedia", "assets", "codemirror", "config", "codemirror-config-\(value.1.languageCode).json"])
try! value.0.write(to: outputURL, atomically: true, encoding: .utf8)
}
}
private func writeNamespaceFiles(with sites: [Wikipedia], completion: @escaping () -> Void) -> AnyCancellable? {
return Publishers.MergeMany(sites.map { site in
api.getSiteInfo(with: site.languageCode)
.map { ($0, site) }
})
.map {
(self.getSiteInfoLookup(with: $0.0), $0.1)
}
.sink(receiveCompletion: { (result) in
completion()
}) { (siteInfoTuple) in
self.writeCodable(siteInfoTuple.0, to: ["Wikipedia", "Code", "wikipedia-namespaces", "\(siteInfoTuple.1.languageCode).json"])
}
}
private func getSiteInfoLookup(with siteInfo: SiteInfo) -> WikipediaSiteInfoLookup {
var namespaces = [String: PageNamespace].init(minimumCapacity: siteInfo.query.namespaces.count + siteInfo.query.namespacealiases.count)
for (_, namespace) in siteInfo.query.namespaces {
namespaces[namespace.name.uppercased()] = PageNamespace(rawValue: namespace.id)
guard let canonical = namespace.canonical else {
continue
}
namespaces[canonical.uppercased()] = PageNamespace(rawValue: namespace.id)
}
for namespaceAlias in siteInfo.query.namespacealiases {
namespaces[namespaceAlias.alias.uppercased()] = PageNamespace(rawValue: namespaceAlias.id)
}
return WikipediaSiteInfoLookup(namespace: namespaces, mainpage: siteInfo.query.general.mainpage.uppercased())
}
}