diff --git a/Frameworks/Account/Account.xcodeproj/project.pbxproj b/Frameworks/Account/Account.xcodeproj/project.pbxproj index 70f38d9b3..3659abf65 100644 --- a/Frameworks/Account/Account.xcodeproj/project.pbxproj +++ b/Frameworks/Account/Account.xcodeproj/project.pbxproj @@ -70,6 +70,7 @@ 51B3630F244B6CB9000DEF2A /* TwitterExtendedEntities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B3630E244B6CB9000DEF2A /* TwitterExtendedEntities.swift */; }; 51B36311244B6CFB000DEF2A /* TwitterMedia.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B36310244B6CFA000DEF2A /* TwitterMedia.swift */; }; 51B36313244B8B5E000DEF2A /* TwitterVideo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B36312244B8B5E000DEF2A /* TwitterVideo.swift */; }; + 51B36315244BCCA4000DEF2A /* TwitterSearchResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B36314244BCCA4000DEF2A /* TwitterSearchResult.swift */; }; 51BB7B84233531BC008E8144 /* AccountBehaviors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BB7B83233531BC008E8144 /* AccountBehaviors.swift */; }; 51BC8FCC237EC055004F8B56 /* Feed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BC8FCB237EC055004F8B56 /* Feed.swift */; }; 51BFDECE238B508D00216323 /* ContainerIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BFDECD238B508D00216323 /* ContainerIdentifier.swift */; }; @@ -319,6 +320,7 @@ 51B3630E244B6CB9000DEF2A /* TwitterExtendedEntities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwitterExtendedEntities.swift; sourceTree = ""; }; 51B36310244B6CFA000DEF2A /* TwitterMedia.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwitterMedia.swift; sourceTree = ""; }; 51B36312244B8B5E000DEF2A /* TwitterVideo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwitterVideo.swift; sourceTree = ""; }; + 51B36314244BCCA4000DEF2A /* TwitterSearchResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwitterSearchResult.swift; sourceTree = ""; }; 51BB7B83233531BC008E8144 /* AccountBehaviors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountBehaviors.swift; sourceTree = ""; }; 51BC8FCB237EC055004F8B56 /* Feed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Feed.swift; sourceTree = ""; }; 51BFDECD238B508D00216323 /* ContainerIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerIdentifier.swift; sourceTree = ""; }; @@ -588,6 +590,7 @@ 51B36306244B6234000DEF2A /* TwitterHashtag.swift */, 51B36310244B6CFA000DEF2A /* TwitterMedia.swift */, 51B3630A244B634A000DEF2A /* TwitterMention.swift */, + 51B36314244BCCA4000DEF2A /* TwitterSearchResult.swift */, 5132DE822449306F00806ADE /* TwitterStatus.swift */, 51B3630C244B6428000DEF2A /* TwitterSymbol.swift */, 51B36308244B62A5000DEF2A /* TwitterURL.swift */, @@ -1186,6 +1189,7 @@ 9E1773D7234575AB0056A5A8 /* FeedlyTag.swift in Sources */, 3B826DAB2385C81C00FC1ADB /* FeedWranglerConfig.swift in Sources */, 515E4EB62324FF8C0057B0E7 /* URLRequest+RSWeb.swift in Sources */, + 51B36315244BCCA4000DEF2A /* TwitterSearchResult.swift in Sources */, 9EB1D576238E6A3900A753D7 /* FeedlyAddNewFeedOperation.swift in Sources */, 3B826DA82385C81C00FC1ADB /* FeedWranglerFeedItem.swift in Sources */, 9E672396236F7E68000BE141 /* OAuthAcessTokenRefreshing.swift in Sources */, diff --git a/Frameworks/Account/FeedProvider/Twitter/TwitterFeedProvider.swift b/Frameworks/Account/FeedProvider/Twitter/TwitterFeedProvider.swift index 8fba12679..c6e24cc1f 100644 --- a/Frameworks/Account/FeedProvider/Twitter/TwitterFeedProvider.swift +++ b/Frameworks/Account/FeedProvider/Twitter/TwitterFeedProvider.swift @@ -155,10 +155,17 @@ public struct TwitterFeedProvider: FeedProvider { let api: String var parameters = [String: Any]() + var isSearch = false switch urlComponents.path { case "/", "/home": api = "statuses/home_timeline.json" + case "/search": + api = "search/tweets.json" + if let query = urlComponents.queryItems?.first(where: { $0.name == "q" })?.value { + parameters["q"] = query + } + isSearch = true default: api = "statuses/user_timeline.json" parameters["exclude_replies"] = true @@ -170,7 +177,7 @@ public struct TwitterFeedProvider: FeedProvider { } } - retrieveTweets(api: api, parameters: parameters) { result in + retrieveTweets(api: api, parameters: parameters, isSearch: isSearch) { result in switch result { case .success(let tweets): let parsedItems = self.makeParsedItems(webFeed.url, tweets) @@ -234,7 +241,7 @@ private extension TwitterFeedProvider { } } - func retrieveTweets(api: String, parameters: [String: Any], completion: @escaping (Result<[TwitterStatus], Error>) -> Void) { + func retrieveTweets(api: String, parameters: [String: Any], isSearch: Bool, completion: @escaping (Result<[TwitterStatus], Error>) -> Void) { let url = "\(Self.apiBase)\(api)" var expandedParameters = parameters expandedParameters["tweet_mode"] = "extended" @@ -246,14 +253,24 @@ private extension TwitterFeedProvider { let dateFormatter = DateFormatter() dateFormatter.dateFormat = Self.dateFormat decoder.dateDecodingStrategy = .formatted(dateFormatter) - let jsonString = String(data: response.data, encoding: .utf8) - - let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("twitter.json") - print("******** writing to: \(url.path)") - try? jsonString?.write(toFile: url.path, atomically: true, encoding: .utf8) + +// let jsonString = String(data: response.data, encoding: .utf8) +// let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("twitter.json") +// print("******** writing to: \(url.path)") +// try? jsonString?.write(toFile: url.path, atomically: true, encoding: .utf8) do { - let tweets = try decoder.decode([TwitterStatus].self, from: response.data) + let tweets: [TwitterStatus] + if isSearch { + let searchResult = try decoder.decode(TwitterSearchResult.self, from: response.data) + if let statuses = searchResult.statuses { + tweets = statuses + } else { + tweets = [TwitterStatus]() + } + } else { + tweets = try decoder.decode([TwitterStatus].self, from: response.data) + } completion(.success(tweets)) } catch { completion(.failure(error)) diff --git a/Frameworks/Account/FeedProvider/Twitter/TwitterSearchResult.swift b/Frameworks/Account/FeedProvider/Twitter/TwitterSearchResult.swift new file mode 100644 index 000000000..6a8a1373f --- /dev/null +++ b/Frameworks/Account/FeedProvider/Twitter/TwitterSearchResult.swift @@ -0,0 +1,19 @@ +// +// TwitterSearchResult.swift +// Account +// +// Created by Maurice Parker on 4/18/20. +// Copyright © 2020 Ranchero Software, LLC. All rights reserved. +// + +import Foundation + +struct TwitterSearchResult: Codable { + + let statuses: [TwitterStatus]? + + enum CodingKeys: String, CodingKey { + case statuses = "statuses" + } +} +