Skip to content

Commit

Permalink
Work around duplicate data in the Pinboard API (#81)
Browse files Browse the repository at this point in the history
Unfortunately it looks like the Pinboard posts/all API is returning duplicate data, meaning that we're seeing some URLs (and therefore hashes) more than once. Since we're using these for identifiers in the SwiftUI list, it's leading to crashes as it has no idea how to handle duplicate elements. This change pre-filters the data when it's returned from the Pinboard API to ensure bad data never leaks into the app.

This also includes a drive-by fix to clean up the Pinboard class (used for managing the Pinboard API) in advance of adding additional methods.
  • Loading branch information
jbmorley authored Apr 10, 2021
1 parent 187499a commit d4544ae
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 6 deletions.
9 changes: 7 additions & 2 deletions core/BookmarksCore/Common/Updater.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,26 @@ public class Updater {
}

public func start() {
Pinboard(token: self.token).fetch { [weak self] (result) in
Pinboard(token: self.token).posts_all { [weak self] (result) in
switch (result) {
case .failure(let error):
print("Failed to fetch the posts with error \(error)")
case .success(let posts):
guard let self = self else {
return
}
// Pinboard seems to give us duplicate data so we maintain a set of hashes we've seen to ensure we
// only return one of each.
var identifiers = Set<String>()
var items: [Item] = []
for post in posts {
guard
let url = post.href,
let date = post.time else {
let date = post.time,
!identifiers.contains(post.hash) else {
continue
}
identifiers.insert(post.hash)
items.append(Item(identifier: post.hash,
title: post.description ?? "",
url: url,
Expand Down
11 changes: 7 additions & 4 deletions core/BookmarksCore/Pinboard/Pinboard.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,26 @@ public class Pinboard {
case inconsistentState(message: String)
}

let baseURL = "https://api.pinboard.in/v1/"
let postsAll = "posts/all"
fileprivate let baseURL = "https://api.pinboard.in/v1/"

fileprivate enum Path: String {
case posts_all = "posts/all"
}

let token: String

public init(token: String) {
self.token = token
}

public func fetch(completion: @escaping (Result<[Post], Swift.Error>) -> Void) {
public func posts_all(completion: @escaping (Result<[Post], Swift.Error>) -> Void) {
guard let base = URL(string: baseURL) else {
DispatchQueue.global(qos: .default).async {
completion(.failure(Error.invalidURL(message: "Unable to construct parse base URL")))
}
return
}
let posts = base.appendingPathComponent(postsAll)
let posts = base.appendingPathComponent(Path.posts_all.rawValue)
guard var components = URLComponents(string: posts.absoluteString) else {
DispatchQueue.global(qos: .default).async {
completion(.failure(Error.invalidURL(message: "Unable to parse URL components")))
Expand Down

0 comments on commit d4544ae

Please sign in to comment.