summaryrefslogtreecommitdiff
path: root/Providers
diff options
context:
space:
mode:
authorRuben Beltran del Rio <git@r.bdr.sh>2025-09-08 21:49:49 +0200
committerRuben Beltran del Rio <git@r.bdr.sh>2025-09-08 21:49:49 +0200
commit2d247ab64b84cf80d1beedb9521d7488bcb99f18 (patch)
tree6cfb3ec812446133d439a19a0fa07939f4d16648 /Providers
parent848982f156a86038438918e3a51cc0f04be9c78c (diff)
Apply formatting
Diffstat (limited to 'Providers')
-rw-r--r--Providers/QSDeliciousAPIProvider.h21
-rw-r--r--Providers/QSDeliciousAPIProvider.m360
-rw-r--r--Providers/QSLinkdingProvider.h9
-rw-r--r--Providers/QSLinkdingProvider.m348
4 files changed, 432 insertions, 306 deletions
diff --git a/Providers/QSDeliciousAPIProvider.h b/Providers/QSDeliciousAPIProvider.h
index 7979812..310b00b 100644
--- a/Providers/QSDeliciousAPIProvider.h
+++ b/Providers/QSDeliciousAPIProvider.h
@@ -6,17 +6,26 @@
// Used by Delicious, Magnolia, and Pinboard
//
-#import <Foundation/Foundation.h>
#import "QSBookmarkProvider.h"
+#import <Foundation/Foundation.h>
-@interface QSDeliciousAPIProvider : NSObject <QSBookmarkProvider, NSXMLParserDelegate>
+@interface QSDeliciousAPIProvider
+ : NSObject <QSBookmarkProvider, NSXMLParserDelegate>
-@property (nonatomic, strong) NSMutableArray *posts;
+@property(nonatomic, strong) NSMutableArray *posts;
// Subclasses can override these methods
- (NSString *)apiURLForSite:(SocialSite)site andHost:(NSString *)host;
-- (NSURL *)requestURLForSite:(SocialSite)site username:(NSString *)username password:(NSString *)password host:(NSString *)host;
-- (NSData *)cachedBookmarkDataForSite:(SocialSite)site username:(NSString *)username host:(NSString *)host;
-- (void)cacheBookmarkData:(NSData *)data forSite:(SocialSite)site username:(NSString *)username host:(NSString *)host;
+- (NSURL *)requestURLForSite:(SocialSite)site
+ username:(NSString *)username
+ password:(NSString *)password
+ host:(NSString *)host;
+- (NSData *)cachedBookmarkDataForSite:(SocialSite)site
+ username:(NSString *)username
+ host:(NSString *)host;
+- (void)cacheBookmarkData:(NSData *)data
+ forSite:(SocialSite)site
+ username:(NSString *)username
+ host:(NSString *)host;
@end
diff --git a/Providers/QSDeliciousAPIProvider.m b/Providers/QSDeliciousAPIProvider.m
index 0c37a43..03991c1 100644
--- a/Providers/QSDeliciousAPIProvider.m
+++ b/Providers/QSDeliciousAPIProvider.m
@@ -4,202 +4,264 @@
//
#import "QSDeliciousAPIProvider.h"
-#import "SocialSite.h"
#import "Constants.h"
+#import "SocialSite.h"
#import <QSCore/QSCore.h>
@implementation QSDeliciousAPIProvider
-- (BOOL)canHandleSite:(SocialSite)site username:(NSString *)username password:(NSString *)password host:(NSString *)host {
- return (
- site == SocialSiteDelicious ||
- site == SocialSiteMagnolia ||
- site == SocialSitePinboard ||
- site == SocialSiteSelfHostedDeliciousCompatible
- ) &&
- username.length > 0 &&
- password.length > 0 &&
- (site != SocialSiteSelfHostedDeliciousCompatible || host.length > 0);
+- (BOOL)canHandleSite:(SocialSite)site
+ username:(NSString *)username
+ password:(NSString *)password
+ host:(NSString *)host {
+ return (site == SocialSiteDelicious || site == SocialSiteMagnolia ||
+ site == SocialSitePinboard ||
+ site == SocialSiteSelfHostedDeliciousCompatible) &&
+ username.length > 0 && password.length > 0 &&
+ (site != SocialSiteSelfHostedDeliciousCompatible || host.length > 0);
}
- (NSString *)apiURLForSite:(SocialSite)site andHost:(NSString *)host {
- switch (site) {
- case SocialSiteDelicious:
- return @"api.del.icio.us/v1";
- case SocialSiteMagnolia:
- return @"ma.gnolia.com/api/mirrord/v1";
- case SocialSitePinboard:
- return @"https://api.pinboard.in/v1";
- case SocialSiteSelfHostedDeliciousCompatible:
- return [NSString stringWithFormat:@"%@/v1", host];
- default:
- return nil;
- }
+ switch (site) {
+ case SocialSiteDelicious:
+ return @"api.del.icio.us/v1";
+ case SocialSiteMagnolia:
+ return @"ma.gnolia.com/api/mirrord/v1";
+ case SocialSitePinboard:
+ return @"https://api.pinboard.in/v1";
+ case SocialSiteSelfHostedDeliciousCompatible:
+ return [NSString stringWithFormat:@"%@/v1", host];
+ default:
+ return nil;
+ }
}
- (BOOL)usesAuthToken:(SocialSite)site {
- switch (site) {
- case SocialSitePinboard:
- case SocialSiteSelfHostedDeliciousCompatible:
- return YES;
- default:
- return NO;
- }
+ switch (site) {
+ case SocialSitePinboard:
+ case SocialSiteSelfHostedDeliciousCompatible:
+ return YES;
+ default:
+ return NO;
+ }
}
-- (NSURL *)requestURLForSite:(SocialSite)site username:(NSString *)username password:(NSString *)password host:(NSString *)host {
- NSString *apiURL = [self apiURLForSite:site andHost: host];
- if (!apiURL) return nil;
-
+- (NSURL *)requestURLForSite:(SocialSite)site
+ username:(NSString *)username
+ password:(NSString *)password
+ host:(NSString *)host {
+ NSString *apiURL = [self apiURLForSite:site andHost:host];
+ if (!apiURL)
+ return nil;
+
NSString *urlString;
if ([self usesAuthToken:site]) {
// Pinboard and pinboard compatible sites require an
// auth token rather than a password.
- urlString = [NSString stringWithFormat:@"%@/posts/all?auth_token=%@", apiURL, password];
+ urlString = [NSString
+ stringWithFormat:@"%@/posts/all?auth_token=%@", apiURL, password];
} else {
- urlString = [NSString stringWithFormat:@"https://%@:%@@%@/posts/all?", username, password, apiURL];
+ urlString = [NSString stringWithFormat:@"https://%@:%@@%@/posts/all?",
+ username, password, apiURL];
}
- return [NSURL URLWithString:urlString];
+ return [NSURL URLWithString:urlString];
}
-# pragma mark - Cache
+#pragma mark - Cache
+
+- (NSString *)cachePathForSite:(SocialSite)site
+ username:(NSString *)username
+ host:(NSString *)host
+ create:(BOOL)create {
-- (NSString *)cachePathForSite:(SocialSite)site username:(NSString *)username host:(NSString *)host create:(BOOL) create {
-
NSString *siteURL = [SocialSiteHelper cacheKeyForSite:site];
- NSString *safeHost = [[host componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]] componentsJoinedByString:@"-"];
- return [QSApplicationSupportSubPath([NSString stringWithFormat:@"Caches/%@/", siteURL], create) stringByAppendingPathComponent:[NSString stringWithFormat:@"%@-%@.xml", safeHost, username]];
+ NSString *safeHost =
+ [[host componentsSeparatedByCharactersInSet:[[NSCharacterSet
+ alphanumericCharacterSet]
+ invertedSet]]
+ componentsJoinedByString:@"-"];
+ return [QSApplicationSupportSubPath(
+ [NSString stringWithFormat:@"Caches/%@/", siteURL], create)
+ stringByAppendingPathComponent:[NSString stringWithFormat:@"%@-%@.xml",
+ safeHost,
+ username]];
}
-
-- (NSData *)cachedBookmarkDataForSite:(SocialSite)site username:(NSString *)username host:(NSString *)host {
- NSString *cachePath = [self cachePathForSite: site username: username host: host create: NO];
+- (NSData *)cachedBookmarkDataForSite:(SocialSite)site
+ username:(NSString *)username
+ host:(NSString *)host {
+ NSString *cachePath = [self cachePathForSite:site
+ username:username
+ host:host
+ create:NO];
return [NSData dataWithContentsOfFile:cachePath];
}
-- (void)cacheBookmarkData:(NSData *)data forSite:(SocialSite)site username:(NSString *)username host:(NSString *)host {
- NSString *cachePath = [self cachePathForSite: site username: username host: host create: YES];
- [data writeToFile:cachePath atomically:NO];
+- (void)cacheBookmarkData:(NSData *)data
+ forSite:(SocialSite)site
+ username:(NSString *)username
+ host:(NSString *)host {
+ NSString *cachePath = [self cachePathForSite:site
+ username:username
+ host:host
+ create:YES];
+ [data writeToFile:cachePath atomically:NO];
}
-- (NSArray *)fetchBookmarksForSite:(SocialSite)site username:(NSString *)username password:(NSString *)password identifier:(NSString *)identifier host:(NSString *)host includeTags:(BOOL)includeTags {
-
- // Try cached data first
- NSData *data = [self cachedBookmarkDataForSite:site username:username host:host];
+- (NSArray *)fetchBookmarksForSite:(SocialSite)site
+ username:(NSString *)username
+ password:(NSString *)password
+ identifier:(NSString *)identifier
+ host:(NSString *)host
+ includeTags:(BOOL)includeTags {
- // If no cached data, fetch from API
- if (![data length]) {
- NSURL *requestURL = [self requestURLForSite:site username:username password:password host:host];
- if (!requestURL) return @[];
-
- NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:requestURL
- cachePolicy:NSURLRequestUseProtocolCachePolicy
- timeoutInterval:60.0];
- [theRequest setHTTPMethod:@"GET"];
- [theRequest setValue:@"text/xml" forHTTPHeaderField:@"Content-type"];
- [theRequest setValue:@"Quicksilver (Blacktree,MacOSX)" forHTTPHeaderField:@"User-Agent"];
-
- NSError *error = nil;
- data = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:nil error:&error];
-
- if (error) {
- NSLog(@"Error fetching bookmarks: %@", error.localizedDescription);
- return @[];
- }
-
- // Cache the data
- [self cacheBookmarkData:data forSite:site username:username host:host];
+ // Try cached data first
+ NSData *data = [self cachedBookmarkDataForSite:site
+ username:username
+ host:host];
+
+ // If no cached data, fetch from API
+ if (![data length]) {
+ NSURL *requestURL = [self requestURLForSite:site
+ username:username
+ password:password
+ host:host];
+ if (!requestURL)
+ return @[];
+
+ NSMutableURLRequest *theRequest =
+ [NSMutableURLRequest requestWithURL:requestURL
+ cachePolicy:NSURLRequestUseProtocolCachePolicy
+ timeoutInterval:60.0];
+ [theRequest setHTTPMethod:@"GET"];
+ [theRequest setValue:@"text/xml" forHTTPHeaderField:@"Content-type"];
+ [theRequest setValue:@"Quicksilver (Blacktree,MacOSX)"
+ forHTTPHeaderField:@"User-Agent"];
+
+ NSError *error = nil;
+ data = [NSURLConnection sendSynchronousRequest:theRequest
+ returningResponse:nil
+ error:&error];
+
+ if (error) {
+ NSLog(@"Error fetching bookmarks: %@", error.localizedDescription);
+ return @[];
}
-
- // Parse XML data
- NSXMLParser *postParser = [[NSXMLParser alloc] initWithData:data];
- [postParser setDelegate:self];
-
- self.posts = [NSMutableArray arrayWithCapacity:1];
- [postParser parse];
-
- NSMutableArray *objects = [NSMutableArray arrayWithCapacity:1];
- NSMutableSet *tagSet = [NSMutableSet set];
-
- // Create bookmark objects
- for (NSDictionary *post in self.posts) {
- QSObject *newObject = [self objectForPost:post];
- if (newObject) {
- [objects addObject:newObject];
-
- // Collect tags if requested
- if (includeTags) {
- NSString *tagString = [post objectForKey:@"tag"];
- if (tagString.length > 0) {
- [tagSet addObjectsFromArray:[tagString componentsSeparatedByString:@" "]];
- }
- }
+
+ // Cache the data
+ [self cacheBookmarkData:data forSite:site username:username host:host];
+ }
+
+ // Parse XML data
+ NSXMLParser *postParser = [[NSXMLParser alloc] initWithData:data];
+ [postParser setDelegate:self];
+
+ self.posts = [NSMutableArray arrayWithCapacity:1];
+ [postParser parse];
+
+ NSMutableArray *objects = [NSMutableArray arrayWithCapacity:1];
+ NSMutableSet *tagSet = [NSMutableSet set];
+
+ // Create bookmark objects
+ for (NSDictionary *post in self.posts) {
+ QSObject *newObject = [self objectForPost:post];
+ if (newObject) {
+ [objects addObject:newObject];
+
+ // Collect tags if requested
+ if (includeTags) {
+ NSString *tagString = [post objectForKey:@"tag"];
+ if (tagString.length > 0) {
+ [tagSet
+ addObjectsFromArray:[tagString componentsSeparatedByString:@" "]];
}
+ }
}
-
- // Create tag objects if requested
- if (includeTags) {
- for (NSString *tag in tagSet) {
- if (tag.length > 0) {
- QSObject *tagObject = [QSObject makeObjectWithIdentifier:[NSString stringWithFormat:@"[%@ tag]:%@", [SocialSiteHelper displayNameForSite:site], tag]];
+ }
- [tagObject setObject:tag forType:kTagType];
- [tagObject setObject:@(site) forMeta:kTagSiteField];
- [tagObject setObject:username forMeta:kTagUsernameField];
- [tagObject setObject:host forMeta:kTagHostField];
- [tagObject setObject:identifier forMeta:kTagIdentifierField];
- [tagObject setName:tag];
- [tagObject setPrimaryType:kTagType];
- [objects addObject:tagObject];
- }
- }
+ // Create tag objects if requested
+ if (includeTags) {
+ for (NSString *tag in tagSet) {
+ if (tag.length > 0) {
+ QSObject *tagObject = [QSObject
+ makeObjectWithIdentifier:
+ [NSString
+ stringWithFormat:@"[%@ tag]:%@",
+ [SocialSiteHelper displayNameForSite:site],
+ tag]];
+
+ [tagObject setObject:tag forType:kTagType];
+ [tagObject setObject:@(site) forMeta:kTagSiteField];
+ [tagObject setObject:username forMeta:kTagUsernameField];
+ [tagObject setObject:host forMeta:kTagHostField];
+ [tagObject setObject:identifier forMeta:kTagIdentifierField];
+ [tagObject setName:tag];
+ [tagObject setPrimaryType:kTagType];
+ [objects addObject:tagObject];
+ }
}
-
- return objects;
+ }
+
+ return objects;
}
-- (NSArray *)fetchBookmarksForTag:(NSString *)tag site:(SocialSite)site username:(NSString *)username password:(NSString *)password host:(NSString *)host {
- NSData *data = [self cachedBookmarkDataForSite:site username:username host:host];
- if (!data) return @[];
-
- NSXMLParser *postParser = [[NSXMLParser alloc] initWithData:data];
- [postParser setDelegate:self];
- self.posts = [NSMutableArray arrayWithCapacity:1];
- [postParser parse];
-
- NSMutableArray *objects = [NSMutableArray arrayWithCapacity:1];
-
- for (NSDictionary *post in self.posts) {
- NSString *postTags = [post objectForKey:@"tag"];
- if ([postTags rangeOfString:tag].location != NSNotFound) {
- QSObject *newObject = [self objectForPost:post];
- if (newObject) {
- [objects addObject:newObject];
- }
- }
+- (NSArray *)fetchBookmarksForTag:(NSString *)tag
+ site:(SocialSite)site
+ username:(NSString *)username
+ password:(NSString *)password
+ host:(NSString *)host {
+ NSData *data = [self cachedBookmarkDataForSite:site
+ username:username
+ host:host];
+ if (!data)
+ return @[];
+
+ NSXMLParser *postParser = [[NSXMLParser alloc] initWithData:data];
+ [postParser setDelegate:self];
+ self.posts = [NSMutableArray arrayWithCapacity:1];
+ [postParser parse];
+
+ NSMutableArray *objects = [NSMutableArray arrayWithCapacity:1];
+
+ for (NSDictionary *post in self.posts) {
+ NSString *postTags = [post objectForKey:@"tag"];
+ if ([postTags rangeOfString:tag].location != NSNotFound) {
+ QSObject *newObject = [self objectForPost:post];
+ if (newObject) {
+ [objects addObject:newObject];
+ }
}
-
- return objects;
+ }
+
+ return objects;
}
- (QSObject *)objectForPost:(NSDictionary *)post {
- QSObject *newObject = [QSObject makeObjectWithIdentifier:[post objectForKey:@"hash"]];
- [newObject setObject:[post objectForKey:@"href"] forType:QSURLType];
- [newObject setName:[post objectForKey:@"description"]];
- [newObject setDetails:[post objectForKey:@"extended"]];
- [newObject setPrimaryType:QSURLType];
- return newObject;
+ QSObject *newObject =
+ [QSObject makeObjectWithIdentifier:[post objectForKey:@"hash"]];
+ [newObject setObject:[post objectForKey:@"href"] forType:QSURLType];
+ [newObject setName:[post objectForKey:@"description"]];
+ [newObject setDetails:[post objectForKey:@"extended"]];
+ [newObject setPrimaryType:QSURLType];
+ return newObject;
}
#pragma mark - NSXMLParserDelegate
-- (void)parser:(NSXMLParser*)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
- if ([elementName isEqualToString:@"post"] && attributeDict) {
- [self.posts addObject:attributeDict];
- }
+- (void)parser:(NSXMLParser *)parser
+ didStartElement:(NSString *)elementName
+ namespaceURI:(NSString *)namespaceURI
+ qualifiedName:(NSString *)qName
+ attributes:(NSDictionary *)attributeDict {
+ if ([elementName isEqualToString:@"post"] && attributeDict) {
+ [self.posts addObject:attributeDict];
+ }
}
-- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
- // Implementation if needed
+- (void)parser:(NSXMLParser *)parser
+ didEndElement:(NSString *)elementName
+ namespaceURI:(NSString *)namespaceURI
+ qualifiedName:(NSString *)qName {
+ // Implementation if needed
}
@end
diff --git a/Providers/QSLinkdingProvider.h b/Providers/QSLinkdingProvider.h
index 28807e8..0537a0c 100644
--- a/Providers/QSLinkdingProvider.h
+++ b/Providers/QSLinkdingProvider.h
@@ -5,12 +5,15 @@
// Provider for Linkding API (JSON-based with API key)
//
-#import <Foundation/Foundation.h>
#import "QSBookmarkProvider.h"
+#import <Foundation/Foundation.h>
@interface QSLinkdingProvider : NSObject <QSBookmarkProvider>
-- (NSData *)cachedBookmarkDataForHost:(NSString *)host username:(NSString *)username;
-- (void)cacheBookmarkData:(NSData *)data forHost:(NSString *)host username:(NSString *)username;
+- (NSData *)cachedBookmarkDataForHost:(NSString *)host
+ username:(NSString *)username;
+- (void)cacheBookmarkData:(NSData *)data
+ forHost:(NSString *)host
+ username:(NSString *)username;
@end \ No newline at end of file
diff --git a/Providers/QSLinkdingProvider.m b/Providers/QSLinkdingProvider.m
index c7bf33f..378ae6f 100644
--- a/Providers/QSLinkdingProvider.m
+++ b/Providers/QSLinkdingProvider.m
@@ -4,178 +4,230 @@
//
#import "QSLinkdingProvider.h"
-#import "SocialSite.h"
#import "Constants.h"
+#import "SocialSite.h"
#import <QSCore/QSCore.h>
@implementation QSLinkdingProvider
-- (BOOL)canHandleSite:(SocialSite)site username:(NSString *)username password:(NSString *)password host:(NSString *)host {
- return (site == SocialSiteLinkding) &&
- username.length > 0 &&
- password.length > 0 && // password is API token for Linkding
- host.length > 0;
+- (BOOL)canHandleSite:(SocialSite)site
+ username:(NSString *)username
+ password:(NSString *)password
+ host:(NSString *)host {
+ return (site == SocialSiteLinkding) && username.length > 0 &&
+ password.length > 0 && // password is API token for Linkding
+ host.length > 0;
}
-- (NSData *)cachedBookmarkDataForHost:(NSString *)host username:(NSString *)username {
- // Create a safe filename from host
- NSString *safeHost = [[host componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]] componentsJoinedByString:@"-"];
- NSString *cachePath = [QSApplicationSupportSubPath([NSString stringWithFormat:@"Caches/linkding/"], NO) stringByAppendingPathComponent:[NSString stringWithFormat:@"%@-%@.json", safeHost, username]];
- return [NSData dataWithContentsOfFile:cachePath];
+- (NSData *)cachedBookmarkDataForHost:(NSString *)host
+ username:(NSString *)username {
+ // Create a safe filename from host
+ NSString *safeHost =
+ [[host componentsSeparatedByCharactersInSet:[[NSCharacterSet
+ alphanumericCharacterSet]
+ invertedSet]]
+ componentsJoinedByString:@"-"];
+ NSString *cachePath = [QSApplicationSupportSubPath(
+ [NSString stringWithFormat:@"Caches/linkding/"], NO)
+ stringByAppendingPathComponent:[NSString stringWithFormat:@"%@-%@.json",
+ safeHost,
+ username]];
+ return [NSData dataWithContentsOfFile:cachePath];
}
-- (void)cacheBookmarkData:(NSData *)data forHost:(NSString *)host username:(NSString *)username {
- // Create a safe filename from host
- NSString *safeHost = [[host componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]] componentsJoinedByString:@"-"];
- NSString *cachePath = [QSApplicationSupportSubPath([NSString stringWithFormat:@"Caches/linkding/"], YES) stringByAppendingPathComponent:[NSString stringWithFormat:@"%@-%@.json", safeHost, username]];
- [data writeToFile:cachePath atomically:NO];
+- (void)cacheBookmarkData:(NSData *)data
+ forHost:(NSString *)host
+ username:(NSString *)username {
+ // Create a safe filename from host
+ NSString *safeHost =
+ [[host componentsSeparatedByCharactersInSet:[[NSCharacterSet
+ alphanumericCharacterSet]
+ invertedSet]]
+ componentsJoinedByString:@"-"];
+ NSString *cachePath = [QSApplicationSupportSubPath(
+ [NSString stringWithFormat:@"Caches/linkding/"], YES)
+ stringByAppendingPathComponent:[NSString stringWithFormat:@"%@-%@.json",
+ safeHost,
+ username]];
+ [data writeToFile:cachePath atomically:NO];
}
-- (NSArray *)fetchBookmarksForSite:(SocialSite)site username:(NSString *)username password:(NSString *)password identifier:(NSString *)identifier host:(NSString *)host includeTags:(BOOL)includeTags {
-
- if (![self canHandleSite:site username:username password:password host:host]) {
- return @[];
+- (NSArray *)fetchBookmarksForSite:(SocialSite)site
+ username:(NSString *)username
+ password:(NSString *)password
+ identifier:(NSString *)identifier
+ host:(NSString *)host
+ includeTags:(BOOL)includeTags {
+
+ if (![self canHandleSite:site
+ username:username
+ password:password
+ host:host]) {
+ return @[];
+ }
+
+ // Try cached data first
+ NSData *data = [self cachedBookmarkDataForHost:host username:username];
+
+ // If no cached data, fetch from API
+ if (![data length]) {
+ // Construct Linkding API URL
+ NSString *baseURL = host;
+ if (![baseURL hasPrefix:@"http://"] && ![baseURL hasPrefix:@"https://"]) {
+ baseURL = [NSString stringWithFormat:@"https://%@", baseURL];
}
-
- // Try cached data first
- NSData *data = [self cachedBookmarkDataForHost:host username:username];
-
- // If no cached data, fetch from API
- if (![data length]) {
- // Construct Linkding API URL
- NSString *baseURL = host;
- if (![baseURL hasPrefix:@"http://"] && ![baseURL hasPrefix:@"https://"]) {
- baseURL = [NSString stringWithFormat:@"https://%@", baseURL];
- }
- if ([baseURL hasSuffix:@"/"]) {
- baseURL = [baseURL substringToIndex:[baseURL length] - 1];
- }
-
- NSString *urlString = [NSString stringWithFormat:@"%@/api/bookmarks/", baseURL];
- NSURL *requestURL = [NSURL URLWithString:urlString];
-
- if (!requestURL) {
- NSLog(@"Invalid Linkding host URL: %@", host);
- return @[];
- }
-
- NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:requestURL
- cachePolicy:NSURLRequestUseProtocolCachePolicy
- timeoutInterval:60.0];
- [theRequest setHTTPMethod:@"GET"];
- [theRequest setValue:@"application/json" forHTTPHeaderField:@"Accept"];
- [theRequest setValue:[NSString stringWithFormat:@"Token %@", password] forHTTPHeaderField:@"Authorization"];
- [theRequest setValue:@"Quicksilver (Blacktree,MacOSX)" forHTTPHeaderField:@"User-Agent"];
-
- NSError *error = nil;
- data = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:nil error:&error];
-
- if (error) {
- NSLog(@"Error fetching Linkding bookmarks: %@", error.localizedDescription);
- return @[];
- }
-
- // Cache the data
- [self cacheBookmarkData:data forHost:host username:username];
+ if ([baseURL hasSuffix:@"/"]) {
+ baseURL = [baseURL substringToIndex:[baseURL length] - 1];
}
-
- // Parse JSON data
- NSError *jsonError = nil;
- NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
-
- if (jsonError) {
- NSLog(@"Error parsing Linkding JSON: %@", jsonError.localizedDescription);
- return @[];
+
+ NSString *urlString =
+ [NSString stringWithFormat:@"%@/api/bookmarks/", baseURL];
+ NSURL *requestURL = [NSURL URLWithString:urlString];
+
+ if (!requestURL) {
+ NSLog(@"Invalid Linkding host URL: %@", host);
+ return @[];
}
-
- NSArray *results = [jsonResponse objectForKey:@"results"];
- if (!results || ![results isKindOfClass:[NSArray class]]) {
- NSLog(@"Invalid Linkding response format");
- return @[];
+
+ NSMutableURLRequest *theRequest =
+ [NSMutableURLRequest requestWithURL:requestURL
+ cachePolicy:NSURLRequestUseProtocolCachePolicy
+ timeoutInterval:60.0];
+ [theRequest setHTTPMethod:@"GET"];
+ [theRequest setValue:@"application/json" forHTTPHeaderField:@"Accept"];
+ [theRequest setValue:[NSString stringWithFormat:@"Token %@", password]
+ forHTTPHeaderField:@"Authorization"];
+ [theRequest setValue:@"Quicksilver (Blacktree,MacOSX)"
+ forHTTPHeaderField:@"User-Agent"];
+
+ NSError *error = nil;
+ data = [NSURLConnection sendSynchronousRequest:theRequest
+ returningResponse:nil
+ error:&error];
+
+ if (error) {
+ NSLog(@"Error fetching Linkding bookmarks: %@",
+ error.localizedDescription);
+ return @[];
}
-
- NSMutableArray *objects = [NSMutableArray arrayWithCapacity:1];
- NSMutableSet *tagSet = [NSMutableSet set];
-
- // Create bookmark objects
- for (NSDictionary *bookmark in results) {
- QSObject *newObject = [self objectForLinkdingBookmark:bookmark];
- if (newObject) {
- [objects addObject:newObject];
-
- // Collect tags if requested
- if (includeTags) {
- NSArray *tags = [bookmark objectForKey:@"tag_names"];
- if (tags && [tags isKindOfClass:[NSArray class]]) {
- [tagSet addObjectsFromArray:tags];
- }
- }
+
+ // Cache the data
+ [self cacheBookmarkData:data forHost:host username:username];
+ }
+
+ // Parse JSON data
+ NSError *jsonError = nil;
+ NSDictionary *jsonResponse =
+ [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
+
+ if (jsonError) {
+ NSLog(@"Error parsing Linkding JSON: %@", jsonError.localizedDescription);
+ return @[];
+ }
+
+ NSArray *results = [jsonResponse objectForKey:@"results"];
+ if (!results || ![results isKindOfClass:[NSArray class]]) {
+ NSLog(@"Invalid Linkding response format");
+ return @[];
+ }
+
+ NSMutableArray *objects = [NSMutableArray arrayWithCapacity:1];
+ NSMutableSet *tagSet = [NSMutableSet set];
+
+ // Create bookmark objects
+ for (NSDictionary *bookmark in results) {
+ QSObject *newObject = [self objectForLinkdingBookmark:bookmark];
+ if (newObject) {
+ [objects addObject:newObject];
+
+ // Collect tags if requested
+ if (includeTags) {
+ NSArray *tags = [bookmark objectForKey:@"tag_names"];
+ if (tags && [tags isKindOfClass:[NSArray class]]) {
+ [tagSet addObjectsFromArray:tags];
}
+ }
}
-
- // Create tag objects if requested
- if (includeTags) {
- for (NSString *tag in tagSet) {
- if (tag.length > 0) {
- QSObject *tagObject = [QSObject makeObjectWithIdentifier:[NSString stringWithFormat:@"[Linkding tag]:%@", tag]];
- [tagObject setObject:tag forType:kTagType];
- [tagObject setObject:@(site) forMeta:kTagSiteField];
- [tagObject setObject:username forMeta:kTagUsernameField];
- [tagObject setObject:host forMeta:kTagHostField];
- // We need the identifier to be able to fetch the keychain password
- [tagObject setObject:identifier forMeta:kTagIdentifierField];
- [tagObject setName:tag];
- [tagObject setPrimaryType:kTagType];
- [objects addObject:tagObject];
- }
- }
+ }
+
+ // Create tag objects if requested
+ if (includeTags) {
+ for (NSString *tag in tagSet) {
+ if (tag.length > 0) {
+ QSObject *tagObject = [QSObject
+ makeObjectWithIdentifier:[NSString
+ stringWithFormat:@"[Linkding tag]:%@",
+ tag]];
+ [tagObject setObject:tag forType:kTagType];
+ [tagObject setObject:@(site) forMeta:kTagSiteField];
+ [tagObject setObject:username forMeta:kTagUsernameField];
+ [tagObject setObject:host forMeta:kTagHostField];
+ // We need the identifier to be able to fetch the keychain password
+ [tagObject setObject:identifier forMeta:kTagIdentifierField];
+ [tagObject setName:tag];
+ [tagObject setPrimaryType:kTagType];
+ [objects addObject:tagObject];
+ }
}
-
- return objects;
+ }
+
+ return objects;
}
-- (NSArray *)fetchBookmarksForTag:(NSString *)tag site:(SocialSite)site username:(NSString *)username password:(NSString *)password host:(NSString *)host {
- NSData *data = [self cachedBookmarkDataForHost:host username:username];
- if (!data) return @[];
-
- NSError *jsonError;
- NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
-
- if (jsonError) return @[];
-
- NSArray *results = [jsonResponse objectForKey:@"results"];
- if (!results || ![results isKindOfClass:[NSArray class]]) return @[];
-
- NSMutableArray *objects = [NSMutableArray arrayWithCapacity:1];
-
- for (NSDictionary *bookmark in results) {
- NSArray *tags = [bookmark objectForKey:@"tag_names"];
- if (tags && [tags isKindOfClass:[NSArray class]] && [tags containsObject:tag]) {
- QSObject *newObject = [self objectForLinkdingBookmark:bookmark];
- if (newObject) {
- [objects addObject:newObject];
- }
- }
+- (NSArray *)fetchBookmarksForTag:(NSString *)tag
+ site:(SocialSite)site
+ username:(NSString *)username
+ password:(NSString *)password
+ host:(NSString *)host {
+ NSData *data = [self cachedBookmarkDataForHost:host username:username];
+ if (!data)
+ return @[];
+
+ NSError *jsonError;
+ NSDictionary *jsonResponse =
+ [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
+
+ if (jsonError)
+ return @[];
+
+ NSArray *results = [jsonResponse objectForKey:@"results"];
+ if (!results || ![results isKindOfClass:[NSArray class]])
+ return @[];
+
+ NSMutableArray *objects = [NSMutableArray arrayWithCapacity:1];
+
+ for (NSDictionary *bookmark in results) {
+ NSArray *tags = [bookmark objectForKey:@"tag_names"];
+ if (tags && [tags isKindOfClass:[NSArray class]] &&
+ [tags containsObject:tag]) {
+ QSObject *newObject = [self objectForLinkdingBookmark:bookmark];
+ if (newObject) {
+ [objects addObject:newObject];
+ }
}
-
- return objects;
+ }
+
+ return objects;
}
- (QSObject *)objectForLinkdingBookmark:(NSDictionary *)bookmark {
- NSNumber *bookmarkId = [bookmark objectForKey:@"id"];
- NSString *url = [bookmark objectForKey:@"url"];
- NSString *title = [bookmark objectForKey:@"title"];
- NSString *description = [bookmark objectForKey:@"description"];
-
- if (!bookmarkId || !url) return nil;
-
- QSObject *newObject = [QSObject makeObjectWithIdentifier:[NSString stringWithFormat:@"linkding-%@", bookmarkId]];
- [newObject setObject:url forType:QSURLType];
- [newObject setName:title.length > 0 ? title : url];
- [newObject setDetails:description.length > 0 ? description : @""];
- [newObject setPrimaryType:QSURLType];
-
- return newObject;
+ NSNumber *bookmarkId = [bookmark objectForKey:@"id"];
+ NSString *url = [bookmark objectForKey:@"url"];
+ NSString *title = [bookmark objectForKey:@"title"];
+ NSString *description = [bookmark objectForKey:@"description"];
+
+ if (!bookmarkId || !url)
+ return nil;
+
+ QSObject *newObject = [QSObject
+ makeObjectWithIdentifier:[NSString stringWithFormat:@"linkding-%@",
+ bookmarkId]];
+ [newObject setObject:url forType:QSURLType];
+ [newObject setName:title.length > 0 ? title : url];
+ [newObject setDetails:description.length > 0 ? description : @""];
+ [newObject setPrimaryType:QSURLType];
+
+ return newObject;
}
@end