mirror of
https://github.com/Ranchero-Software/NetNewsWire.git
synced 2024-12-23 08:09:41 +01:00
Make ArticleExtractor MainActor; make it forget about SecretsProvider and the Secrets module.
This commit is contained in:
parent
1c9452a1c5
commit
6e8eecb6a9
@ -1259,7 +1259,8 @@ private extension MainWindowController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func startArticleExtractorForCurrentLink() {
|
func startArticleExtractorForCurrentLink() {
|
||||||
if let link = currentLink, let extractor = ArticleExtractor(link, secretsProvider: Secrets()) {
|
let secrets = Secrets()
|
||||||
|
if let link = currentLink, let extractor = ArticleExtractor(link, clientID: secrets.mercuryClientId, clientSecret: secrets.mercuryClientSecret) {
|
||||||
extractor.delegate = self
|
extractor.delegate = self
|
||||||
extractor.process()
|
extractor.process()
|
||||||
articleExtractor = extractor
|
articleExtractor = extractor
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import Account
|
import FoundationExtras
|
||||||
import Secrets
|
|
||||||
|
|
||||||
public enum ArticleExtractorState {
|
public enum ArticleExtractorState {
|
||||||
case ready
|
case ready
|
||||||
@ -24,23 +23,23 @@ protocol ArticleExtractorDelegate {
|
|||||||
@MainActor func articleExtractionDidComplete(extractedArticle: ExtractedArticle)
|
@MainActor func articleExtractionDidComplete(extractedArticle: ExtractedArticle)
|
||||||
}
|
}
|
||||||
|
|
||||||
final class ArticleExtractor {
|
@MainActor final class ArticleExtractor {
|
||||||
|
|
||||||
private var dataTask: URLSessionDataTask? = nil
|
private var dataTask: URLSessionDataTask? = nil
|
||||||
|
|
||||||
var state: ArticleExtractorState!
|
var state: ArticleExtractorState!
|
||||||
var article: ExtractedArticle?
|
var article: ExtractedArticle?
|
||||||
var delegate: ArticleExtractorDelegate?
|
var delegate: ArticleExtractorDelegate?
|
||||||
var articleLink: String?
|
let articleLink: String?
|
||||||
|
|
||||||
private var url: URL!
|
private let url: URL!
|
||||||
|
|
||||||
public init?(_ articleLink: String, secretsProvider: SecretsProvider) {
|
public init?(_ articleLink: String, clientID: String, clientSecret: String) {
|
||||||
self.articleLink = articleLink
|
self.articleLink = articleLink
|
||||||
|
|
||||||
let clientURL = "https://extract.feedbin.com/parser"
|
let clientURL = "https://extract.feedbin.com/parser"
|
||||||
let username = secretsProvider.mercuryClientId
|
let username = clientID
|
||||||
let signature = articleLink.hmacUsingSHA1(key: secretsProvider.mercuryClientSecret)
|
let signature = articleLink.hmacUsingSHA1(key: clientSecret)
|
||||||
|
|
||||||
if let base64URL = articleLink.data(using: .utf8)?.base64EncodedString() {
|
if let base64URL = articleLink.data(using: .utf8)?.base64EncodedString() {
|
||||||
let fullURL = "\(clientURL)/\(username)/\(signature)?base64_url=\(base64URL)"
|
let fullURL = "\(clientURL)/\(username)/\(signature)?base64_url=\(base64URL)"
|
||||||
@ -55,58 +54,69 @@ final class ArticleExtractor {
|
|||||||
|
|
||||||
public func process() {
|
public func process() {
|
||||||
|
|
||||||
state = .processing
|
state = .processing
|
||||||
|
|
||||||
dataTask = URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
|
dataTask = URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
|
||||||
|
|
||||||
guard let self = self else { return }
|
Task { @MainActor [weak self] in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if let error = error {
|
if let error {
|
||||||
self.state = .failedToParse
|
self.noteDidFail(error: error)
|
||||||
DispatchQueue.main.async {
|
return
|
||||||
self.delegate?.articleExtractionDidFail(with: error)
|
}
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let data = data else {
|
guard let data else {
|
||||||
self.state = .failedToParse
|
self.noteDidFail(error: URLError(.cannotDecodeContentData))
|
||||||
DispatchQueue.main.async {
|
return
|
||||||
self.delegate?.articleExtractionDidFail(with: URLError(.cannotDecodeContentData))
|
}
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let decoder = JSONDecoder()
|
let article = try decodeArticle(data: data)
|
||||||
decoder.dateDecodingStrategy = .iso8601
|
self.article = article
|
||||||
self.article = try decoder.decode(ExtractedArticle.self, from: data)
|
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
if article.content == nil {
|
||||||
if self.article?.content == nil {
|
self.noteDidFail(error: URLError(.cannotDecodeContentData))
|
||||||
self.state = .failedToParse
|
|
||||||
self.delegate?.articleExtractionDidFail(with: URLError(.cannotDecodeContentData))
|
|
||||||
} else {
|
} else {
|
||||||
self.state = .complete
|
self.noteDidComplete(article: article)
|
||||||
self.delegate?.articleExtractionDidComplete(extractedArticle: self.article!)
|
|
||||||
}
|
}
|
||||||
}
|
} catch {
|
||||||
} catch {
|
self.noteDidFail(error: error)
|
||||||
self.state = .failedToParse
|
}
|
||||||
DispatchQueue.main.async {
|
}
|
||||||
self.delegate?.articleExtractionDidFail(with: error)
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
dataTask!.resume()
|
dataTask!.resume()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func cancel() {
|
public func cancel() {
|
||||||
state = .cancelled
|
state = .cancelled
|
||||||
dataTask?.cancel()
|
dataTask?.cancel()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension ArticleExtractor {
|
||||||
|
|
||||||
|
func decodeArticle(data: Data) throws -> ExtractedArticle {
|
||||||
|
|
||||||
|
let decoder = JSONDecoder()
|
||||||
|
decoder.dateDecodingStrategy = .iso8601
|
||||||
|
|
||||||
|
let article = try decoder.decode(ExtractedArticle.self, from: data)
|
||||||
|
return article
|
||||||
|
}
|
||||||
|
|
||||||
|
func noteDidFail(error: Error) {
|
||||||
|
|
||||||
|
state = .failedToParse
|
||||||
|
delegate?.articleExtractionDidFail(with: error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func noteDidComplete(article: ExtractedArticle) {
|
||||||
|
|
||||||
|
state = .complete
|
||||||
|
delegate?.articleExtractionDidComplete(extractedArticle: article)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -657,7 +657,8 @@ private extension WebViewController {
|
|||||||
|
|
||||||
func startArticleExtractor() {
|
func startArticleExtractor() {
|
||||||
guard articleExtractor == nil else { return }
|
guard articleExtractor == nil else { return }
|
||||||
if let link = article?.preferredLink, let extractor = ArticleExtractor(link, secretsProvider: Secrets()) {
|
let secrets = Secrets()
|
||||||
|
if let link = article?.preferredLink, let extractor = ArticleExtractor(link, clientID: secrets.mercuryClientId, clientSecret: secrets.mercuryClientSecret) {
|
||||||
extractor.delegate = self
|
extractor.delegate = self
|
||||||
extractor.process()
|
extractor.process()
|
||||||
articleExtractor = extractor
|
articleExtractor = extractor
|
||||||
|
Loading…
Reference in New Issue
Block a user