Create Feedbin module.
This commit is contained in:
parent
a51d161e35
commit
826ec7d413
@ -23,6 +23,7 @@ let package = Package(
|
|||||||
.package(path: "../ReaderAPI"),
|
.package(path: "../ReaderAPI"),
|
||||||
.package(path: "../CloudKitSync"),
|
.package(path: "../CloudKitSync"),
|
||||||
.package(path: "../NewsBlur"),
|
.package(path: "../NewsBlur"),
|
||||||
|
.package(path: "../Feedbin"),
|
||||||
.package(path: "../CommonErrors")
|
.package(path: "../CommonErrors")
|
||||||
],
|
],
|
||||||
targets: [
|
targets: [
|
||||||
@ -41,6 +42,7 @@ let package = Package(
|
|||||||
"ReaderAPI",
|
"ReaderAPI",
|
||||||
"NewsBlur",
|
"NewsBlur",
|
||||||
"CloudKitSync",
|
"CloudKitSync",
|
||||||
|
"Feedbin",
|
||||||
"CommonErrors"
|
"CommonErrors"
|
||||||
],
|
],
|
||||||
swiftSettings: [
|
swiftSettings: [
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import Web
|
import Web
|
||||||
import Secrets
|
import Secrets
|
||||||
|
import Feedbin
|
||||||
|
|
||||||
enum CreateSubscriptionResult {
|
enum CreateSubscriptionResult {
|
||||||
case created(FeedbinSubscription)
|
case created(FeedbinSubscription)
|
||||||
|
@ -14,6 +14,7 @@ import SyncDatabase
|
|||||||
import os.log
|
import os.log
|
||||||
import Secrets
|
import Secrets
|
||||||
import Core
|
import Core
|
||||||
|
import Feedbin
|
||||||
|
|
||||||
public enum FeedbinAccountDelegateError: String, Error {
|
public enum FeedbinAccountDelegateError: String, Error {
|
||||||
case invalidParameter = "There was an invalid parameter passed."
|
case invalidParameter = "There was an invalid parameter passed."
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
//
|
|
||||||
// FeedbinFeed.swift
|
|
||||||
// Account
|
|
||||||
//
|
|
||||||
// Created by Brent Simmons on 12/10/17.
|
|
||||||
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import Parser
|
|
||||||
|
|
||||||
struct FeedbinSubscription: Hashable, Codable {
|
|
||||||
|
|
||||||
let subscriptionID: Int
|
|
||||||
let feedID: Int
|
|
||||||
let name: String?
|
|
||||||
let url: String
|
|
||||||
let homePageURL: String?
|
|
||||||
let jsonFeed: FeedbinSubscriptionJSONFeed?
|
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
|
||||||
case subscriptionID = "id"
|
|
||||||
case feedID = "feed_id"
|
|
||||||
case name = "title"
|
|
||||||
case url = "feed_url"
|
|
||||||
case homePageURL = "site_url"
|
|
||||||
case jsonFeed = "json_feed"
|
|
||||||
}
|
|
||||||
|
|
||||||
public func hash(into hasher: inout Hasher) {
|
|
||||||
hasher.combine(subscriptionID)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func == (lhs: FeedbinSubscription, rhs: FeedbinSubscription) -> Bool {
|
|
||||||
return lhs.subscriptionID == rhs.subscriptionID
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FeedbinSubscriptionJSONFeed: Codable {
|
|
||||||
let favicon: String?
|
|
||||||
let icon: String?
|
|
||||||
enum CodingKeys: String, CodingKey {
|
|
||||||
case favicon = "favicon"
|
|
||||||
case icon = "icon"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FeedbinCreateSubscription: Codable {
|
|
||||||
let feedURL: String
|
|
||||||
enum CodingKeys: String, CodingKey {
|
|
||||||
case feedURL = "feed_url"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FeedbinUpdateSubscription: Codable {
|
|
||||||
let title: String
|
|
||||||
enum CodingKeys: String, CodingKey {
|
|
||||||
case title
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FeedbinSubscriptionChoice: Codable {
|
|
||||||
|
|
||||||
let name: String?
|
|
||||||
let url: String
|
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
|
||||||
case name = "title"
|
|
||||||
case url = "feed_url"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -37,7 +37,7 @@ public extension URLRequest {
|
|||||||
]
|
]
|
||||||
httpBody = postData.enhancedPercentEncodedQuery?.data(using: .utf8)
|
httpBody = postData.enhancedPercentEncodedQuery?.data(using: .utf8)
|
||||||
case .newsBlurSessionId:
|
case .newsBlurSessionId:
|
||||||
setValue("\(NewsBlurAPICaller.SessionIdCookie)=\(credentials.secret)", forHTTPHeaderField: "Cookie")
|
setValue("\(NewsBlurAPICaller.sessionIDCookieKey)=\(credentials.secret)", forHTTPHeaderField: "Cookie")
|
||||||
httpShouldHandleCookies = true
|
httpShouldHandleCookies = true
|
||||||
case .readerBasic:
|
case .readerBasic:
|
||||||
setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
|
setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
|
||||||
|
8
Feedbin/.gitignore
vendored
Normal file
8
Feedbin/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
.DS_Store
|
||||||
|
/.build
|
||||||
|
/Packages
|
||||||
|
xcuserdata/
|
||||||
|
DerivedData/
|
||||||
|
.swiftpm/configuration/registries.json
|
||||||
|
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||||
|
.netrc
|
31
Feedbin/Package.swift
Normal file
31
Feedbin/Package.swift
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// swift-tools-version: 5.10
|
||||||
|
|
||||||
|
import PackageDescription
|
||||||
|
|
||||||
|
let package = Package(
|
||||||
|
name: "Feedbin",
|
||||||
|
platforms: [.macOS(.v14), .iOS(.v17)],
|
||||||
|
products: [
|
||||||
|
.library(
|
||||||
|
name: "Feedbin",
|
||||||
|
targets: ["Feedbin"]),
|
||||||
|
],
|
||||||
|
dependencies: [
|
||||||
|
.package(path: "../Parser"),
|
||||||
|
],
|
||||||
|
|
||||||
|
targets: [
|
||||||
|
.target(
|
||||||
|
name: "Feedbin",
|
||||||
|
dependencies: [
|
||||||
|
"Parser"
|
||||||
|
],
|
||||||
|
swiftSettings: [
|
||||||
|
.enableExperimentalFeature("StrictConcurrency")
|
||||||
|
]
|
||||||
|
),
|
||||||
|
.testTarget(
|
||||||
|
name: "FeedbinTests",
|
||||||
|
dependencies: ["Feedbin"]),
|
||||||
|
]
|
||||||
|
)
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct FeedbinDate {
|
public struct FeedbinDate {
|
||||||
|
|
||||||
public static let formatter: DateFormatter = {
|
public static let formatter: DateFormatter = {
|
||||||
let formatter = DateFormatter()
|
let formatter = DateFormatter()
|
||||||
@ -17,5 +17,4 @@ struct FeedbinDate {
|
|||||||
formatter.timeZone = TimeZone(abbreviation: "GMT")
|
formatter.timeZone = TimeZone(abbreviation: "GMT")
|
||||||
return formatter
|
return formatter
|
||||||
}()
|
}()
|
||||||
|
|
||||||
}
|
}
|
@ -9,24 +9,24 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import Parser
|
import Parser
|
||||||
|
|
||||||
final class FeedbinEntry: Decodable {
|
public final class FeedbinEntry: Decodable, @unchecked Sendable {
|
||||||
|
|
||||||
let articleID: Int
|
public let articleID: Int
|
||||||
let feedID: Int
|
public let feedID: Int
|
||||||
let title: String?
|
public let title: String?
|
||||||
let url: String?
|
public let url: String?
|
||||||
let authorName: String?
|
public let authorName: String?
|
||||||
let contentHTML: String?
|
public let contentHTML: String?
|
||||||
let summary: String?
|
public let summary: String?
|
||||||
let datePublished: String?
|
public let datePublished: String?
|
||||||
let dateArrived: String?
|
public let dateArrived: String?
|
||||||
let jsonFeed: FeedbinEntryJSONFeed?
|
public let jsonFeed: FeedbinEntryJSONFeed?
|
||||||
|
|
||||||
// Feedbin dates can't be decoded by the JSONDecoding 8601 decoding strategy. Feedbin
|
// Feedbin dates can't be decoded by the JSONDecoding 8601 decoding strategy. Feedbin
|
||||||
// requires a very specific date formatter to work and even then it fails occasionally.
|
// requires a very specific date formatter to work and even then it fails occasionally.
|
||||||
// Rather than loose all the entries we only lose the one date by decoding as a string
|
// Rather than loose all the entries we only lose the one date by decoding as a string
|
||||||
// and letting the one date fail when parsed.
|
// and letting the one date fail when parsed.
|
||||||
lazy var parsedDatePublished: Date? = {
|
public lazy var parsedDatePublished: Date? = {
|
||||||
if let datePublished = datePublished {
|
if let datePublished = datePublished {
|
||||||
return RSDateWithString(datePublished)
|
return RSDateWithString(datePublished)
|
||||||
}
|
}
|
||||||
@ -49,9 +49,10 @@ final class FeedbinEntry: Decodable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FeedbinEntryJSONFeed: Decodable {
|
public struct FeedbinEntryJSONFeed: Decodable, Sendable {
|
||||||
let jsonFeedAuthor: FeedbinEntryJSONFeedAuthor?
|
|
||||||
let jsonFeedExternalURL: String?
|
public let jsonFeedAuthor: FeedbinEntryJSONFeedAuthor?
|
||||||
|
public let jsonFeedExternalURL: String?
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case jsonFeedAuthor = "author"
|
case jsonFeedAuthor = "author"
|
||||||
@ -74,9 +75,11 @@ struct FeedbinEntryJSONFeed: Decodable {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FeedbinEntryJSONFeedAuthor: Decodable {
|
public struct FeedbinEntryJSONFeedAuthor: Decodable, Sendable {
|
||||||
let url: String?
|
|
||||||
let avatarURL: String?
|
public let url: String?
|
||||||
|
public let avatarURL: String?
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case url = "url"
|
case url = "url"
|
||||||
case avatarURL = "avatar"
|
case avatarURL = "avatar"
|
@ -8,10 +8,10 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct FeedbinImportResult: Codable {
|
public struct FeedbinImportResult: Codable, Sendable {
|
||||||
|
|
||||||
let importResultID: Int
|
public let importResultID: Int
|
||||||
let complete: Bool
|
public let complete: Bool
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case importResultID = "id"
|
case importResultID = "id"
|
@ -8,12 +8,16 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct FeedbinStarredEntry: Codable {
|
public struct FeedbinStarredEntry: Codable, Sendable {
|
||||||
|
|
||||||
let starredEntries: [Int]
|
public let starredEntries: [Int]
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case starredEntries = "starred_entries"
|
case starredEntries = "starred_entries"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(starredEntries: [Int]) {
|
||||||
|
|
||||||
|
self.starredEntries = starredEntries
|
||||||
|
}
|
||||||
}
|
}
|
89
Feedbin/Sources/Feedbin/FeedbinSubscription.swift
Normal file
89
Feedbin/Sources/Feedbin/FeedbinSubscription.swift
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
//
|
||||||
|
// FeedbinFeed.swift
|
||||||
|
// Account
|
||||||
|
//
|
||||||
|
// Created by Brent Simmons on 12/10/17.
|
||||||
|
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Parser
|
||||||
|
|
||||||
|
public struct FeedbinSubscription: Hashable, Codable, Sendable {
|
||||||
|
|
||||||
|
public let subscriptionID: Int
|
||||||
|
public let feedID: Int
|
||||||
|
public let name: String?
|
||||||
|
public let url: String
|
||||||
|
public let homePageURL: String?
|
||||||
|
public let jsonFeed: FeedbinSubscriptionJSONFeed?
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case subscriptionID = "id"
|
||||||
|
case feedID = "feed_id"
|
||||||
|
case name = "title"
|
||||||
|
case url = "feed_url"
|
||||||
|
case homePageURL = "site_url"
|
||||||
|
case jsonFeed = "json_feed"
|
||||||
|
}
|
||||||
|
|
||||||
|
public func hash(into hasher: inout Hasher) {
|
||||||
|
hasher.combine(subscriptionID)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func == (lhs: FeedbinSubscription, rhs: FeedbinSubscription) -> Bool {
|
||||||
|
return lhs.subscriptionID == rhs.subscriptionID
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct FeedbinSubscriptionJSONFeed: Codable, Sendable {
|
||||||
|
|
||||||
|
public let favicon: String?
|
||||||
|
public let icon: String?
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case favicon = "favicon"
|
||||||
|
case icon = "icon"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct FeedbinCreateSubscription: Codable, Sendable {
|
||||||
|
|
||||||
|
public let feedURL: String
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case feedURL = "feed_url"
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(feedURL: String) {
|
||||||
|
|
||||||
|
self.feedURL = feedURL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct FeedbinUpdateSubscription: Codable, Sendable {
|
||||||
|
|
||||||
|
public let title: String
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case title
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(title: String) {
|
||||||
|
|
||||||
|
self.title = title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct FeedbinSubscriptionChoice: Codable, Sendable {
|
||||||
|
|
||||||
|
public let name: String?
|
||||||
|
public let url: String
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case name = "title"
|
||||||
|
case url = "feed_url"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -8,36 +8,39 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct FeedbinTag: Codable {
|
public struct FeedbinTag: Codable, Sendable {
|
||||||
|
|
||||||
let tagID: Int
|
public let tagID: Int
|
||||||
let name: String
|
public let name: String
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case tagID = "id"
|
case tagID = "id"
|
||||||
case name = "name"
|
case name = "name"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FeedbinRenameTag: Codable {
|
public struct FeedbinRenameTag: Codable, Sendable {
|
||||||
|
|
||||||
let oldName: String
|
public let oldName: String
|
||||||
let newName: String
|
public let newName: String
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case oldName = "old_name"
|
case oldName = "old_name"
|
||||||
case newName = "new_name"
|
case newName = "new_name"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(oldName: String, newName: String) {
|
||||||
|
|
||||||
|
self.oldName = oldName
|
||||||
|
self.newName = newName
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FeedbinDeleteTag: Codable {
|
public struct FeedbinDeleteTag: Codable, Sendable {
|
||||||
|
|
||||||
let name: String
|
public let name: String
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case name
|
case name
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -8,28 +8,32 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct FeedbinTagging: Codable {
|
public struct FeedbinTagging: Codable, Sendable {
|
||||||
|
|
||||||
let taggingID: Int
|
public let taggingID: Int
|
||||||
let feedID: Int
|
public let feedID: Int
|
||||||
let name: String
|
public let name: String
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case taggingID = "id"
|
case taggingID = "id"
|
||||||
case feedID = "feed_id"
|
case feedID = "feed_id"
|
||||||
case name = "name"
|
case name = "name"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FeedbinCreateTagging: Codable {
|
public struct FeedbinCreateTagging: Codable, Sendable {
|
||||||
|
|
||||||
let feedID: Int
|
public let feedID: Int
|
||||||
let name: String
|
public let name: String
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case feedID = "feed_id"
|
case feedID = "feed_id"
|
||||||
case name = "name"
|
case name = "name"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(feedID: Int, name: String) {
|
||||||
|
|
||||||
|
self.feedID = feedID
|
||||||
|
self.name = name
|
||||||
|
}
|
||||||
}
|
}
|
@ -8,12 +8,16 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct FeedbinUnreadEntry: Codable {
|
public struct FeedbinUnreadEntry: Codable, Sendable {
|
||||||
|
|
||||||
let unreadEntries: [Int]
|
public let unreadEntries: [Int]
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case unreadEntries = "unread_entries"
|
case unreadEntries = "unread_entries"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init(unreadEntries: [Int]) {
|
||||||
|
|
||||||
|
self.unreadEntries = unreadEntries
|
||||||
|
}
|
||||||
}
|
}
|
12
Feedbin/Tests/FeedbinTests/FeedbinTests.swift
Normal file
12
Feedbin/Tests/FeedbinTests/FeedbinTests.swift
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import XCTest
|
||||||
|
@testable import Feedbin
|
||||||
|
|
||||||
|
final class FeedbinTests: XCTestCase {
|
||||||
|
func testExample() throws {
|
||||||
|
// XCTest Documentation
|
||||||
|
// https://developer.apple.com/documentation/xctest
|
||||||
|
|
||||||
|
// Defining Test Cases and Test Methods
|
||||||
|
// https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods
|
||||||
|
}
|
||||||
|
}
|
@ -1466,6 +1466,7 @@
|
|||||||
84F9EAE2213660A100CF2DE4 /* establishMainWindowStartingState.applescript */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.applescript; path = establishMainWindowStartingState.applescript; sourceTree = "<group>"; };
|
84F9EAE2213660A100CF2DE4 /* establishMainWindowStartingState.applescript */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.applescript; path = establishMainWindowStartingState.applescript; sourceTree = "<group>"; };
|
||||||
84F9EAE4213660A100CF2DE4 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
84F9EAE4213660A100CF2DE4 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
84FB9FAC2BC33AFE00B7AFC3 /* NewsBlur */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = NewsBlur; sourceTree = "<group>"; };
|
84FB9FAC2BC33AFE00B7AFC3 /* NewsBlur */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = NewsBlur; sourceTree = "<group>"; };
|
||||||
|
84FB9FAD2BC344F800B7AFC3 /* Feedbin */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Feedbin; sourceTree = "<group>"; };
|
||||||
84FF69B01FC3793300DC198E /* FaviconURLFinder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FaviconURLFinder.swift; sourceTree = "<group>"; };
|
84FF69B01FC3793300DC198E /* FaviconURLFinder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FaviconURLFinder.swift; sourceTree = "<group>"; };
|
||||||
B24E9ABA245AB88300DA5718 /* NSAttributedString+NetNewsWire.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+NetNewsWire.swift"; sourceTree = "<group>"; };
|
B24E9ABA245AB88300DA5718 /* NSAttributedString+NetNewsWire.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+NetNewsWire.swift"; sourceTree = "<group>"; };
|
||||||
B24EFD482330FF99006C6242 /* NetNewsWire-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NetNewsWire-Bridging-Header.h"; sourceTree = "<group>"; };
|
B24EFD482330FF99006C6242 /* NetNewsWire-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NetNewsWire-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
@ -2358,6 +2359,7 @@
|
|||||||
849C64611ED37A5D003D8FC0 /* Products */,
|
849C64611ED37A5D003D8FC0 /* Products */,
|
||||||
51C452B22265141B00C03939 /* Frameworks */,
|
51C452B22265141B00C03939 /* Frameworks */,
|
||||||
51CD32C624D2DEF9009ABAEF /* Account */,
|
51CD32C624D2DEF9009ABAEF /* Account */,
|
||||||
|
84FB9FAD2BC344F800B7AFC3 /* Feedbin */,
|
||||||
84FB9FAC2BC33AFE00B7AFC3 /* NewsBlur */,
|
84FB9FAC2BC33AFE00B7AFC3 /* NewsBlur */,
|
||||||
84CC98D92BC1DD25006A05C9 /* ReaderAPI */,
|
84CC98D92BC1DD25006A05C9 /* ReaderAPI */,
|
||||||
845F3D2B2BC268FE00AEBB68 /* CloudKitSync */,
|
845F3D2B2BC268FE00AEBB68 /* CloudKitSync */,
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
// swift-tools-version: 5.10
|
// swift-tools-version: 5.10
|
||||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
|
||||||
|
|
||||||
import PackageDescription
|
import PackageDescription
|
||||||
|
|
||||||
@ -7,7 +6,6 @@ let package = Package(
|
|||||||
name: "NewsBlur",
|
name: "NewsBlur",
|
||||||
platforms: [.macOS(.v14), .iOS(.v17)],
|
platforms: [.macOS(.v14), .iOS(.v17)],
|
||||||
products: [
|
products: [
|
||||||
// Products define the executables and libraries a package produces, making them visible to other packages.
|
|
||||||
.library(
|
.library(
|
||||||
name: "NewsBlur",
|
name: "NewsBlur",
|
||||||
targets: ["NewsBlur"]),
|
targets: ["NewsBlur"]),
|
||||||
@ -18,8 +16,6 @@ let package = Package(
|
|||||||
.package(path: "../Parser"),
|
.package(path: "../Parser"),
|
||||||
],
|
],
|
||||||
targets: [
|
targets: [
|
||||||
// Targets are the basic building blocks of a package, defining a module or a test suite.
|
|
||||||
// Targets can depend on other targets in this package and products from dependencies.
|
|
||||||
.target(
|
.target(
|
||||||
name: "NewsBlur",
|
name: "NewsBlur",
|
||||||
dependencies: [
|
dependencies: [
|
||||||
|
@ -12,7 +12,7 @@ import Secrets
|
|||||||
|
|
||||||
@MainActor public final class NewsBlurAPICaller: NSObject {
|
@MainActor public final class NewsBlurAPICaller: NSObject {
|
||||||
|
|
||||||
public static let SessionIdCookie = "newsblur_sessionid"
|
public static let sessionIDCookieKey = "newsblur_sessionid"
|
||||||
|
|
||||||
let baseURL = URL(string: "https://www.newsblur.com/")!
|
let baseURL = URL(string: "https://www.newsblur.com/")!
|
||||||
var transport: Transport!
|
var transport: Transport!
|
||||||
@ -55,7 +55,7 @@ import Secrets
|
|||||||
}
|
}
|
||||||
|
|
||||||
let cookies = HTTPCookie.cookies(withResponseHeaderFields: headerFields, for: url)
|
let cookies = HTTPCookie.cookies(withResponseHeaderFields: headerFields, for: url)
|
||||||
for cookie in cookies where cookie.name == Self.SessionIdCookie {
|
for cookie in cookies where cookie.name == Self.sessionIDCookieKey {
|
||||||
let credentials = Credentials(type: .newsBlurSessionId, username: username, secret: cookie.value)
|
let credentials = Credentials(type: .newsBlurSessionId, username: username, secret: cookie.value)
|
||||||
completion(.success(credentials))
|
completion(.success(credentials))
|
||||||
return
|
return
|
||||||
|
@ -36,7 +36,7 @@ public extension URLRequest {
|
|||||||
|
|
||||||
} else if credentialsType == .newsBlurSessionId {
|
} else if credentialsType == .newsBlurSessionId {
|
||||||
|
|
||||||
setValue("\(NewsBlurAPICaller.SessionIdCookie)=\(credentials.secret)", forHTTPHeaderField: "Cookie")
|
setValue("\(NewsBlurAPICaller.sessionIDCookieKey)=\(credentials.secret)", forHTTPHeaderField: "Cookie")
|
||||||
httpShouldHandleCookies = true
|
httpShouldHandleCookies = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import Foundation
|
|||||||
|
|
||||||
public struct FeedParserError: Error, Sendable {
|
public struct FeedParserError: Error, Sendable {
|
||||||
|
|
||||||
public enum FeedParserErrorType {
|
public enum FeedParserErrorType: Sendable {
|
||||||
|
|
||||||
case rssChannelNotFound
|
case rssChannelNotFound
|
||||||
case rssItemsNotFound
|
case rssItemsNotFound
|
||||||
|
Loading…
x
Reference in New Issue
Block a user