diff --git a/Documentation/X-Callback-URL.md b/Documentation/X-Callback-URL.md index e147342a..6a12e09d 100644 --- a/Documentation/X-Callback-URL.md +++ b/Documentation/X-Callback-URL.md @@ -52,10 +52,12 @@ Dates in responses are encoded as Unix timestamps. ## Requests - [Accounts](#accounts) + - [`showAccount`](#showaccount) - [`getCurrentUser`](#getcurrentuser) - [`getAccount`](#getaccount) - [`followUser`](#followuser) - [Statuses](#statuses) + - [`showStatus`](#showstatus) - [`getStatus`](#getstatus) - [`postStatus`](#poststatus) - [`favoriteStatus`](#favoritestatus) @@ -70,6 +72,22 @@ Dates in responses are encoded as Unix timestamps. ### Accounts +#### `showAccount` + +Presents the given account in Tusker. + +##### Request + +| Parameter (type) | Description | Optional | +| -------------------- | ------------------------------------------------------------ | -------- | +| `accountID` (string) | The instance-local ID of the account | Yes | +| `accountURL` (URL) | The URL of the remote account | Yes | +| `acct` (string) | The [qualified username](#qualifiedusernames) of the account | Yes | + +##### Response + +No data if successful. + #### `getCurrentUser` Retrieves the currently logged-in user. @@ -136,6 +154,21 @@ Follows the given account from the logged-in user's account. One of `accountID`, ### Statuses +#### `showStatus` + +Presents the given status in Tusker. + +##### Request + +| Parameter (type) | Description | Optional | +| ------------------- | ----------------------------------- | -------- | +| `statusID` (string) | The instance-local ID of the status | Yes | +| `statusURL` (URL) | The URL of a remote status | Yes | + +##### Response + +No data if successful. + #### `getStatus` Retrieves the given status details. One of `statusID` or `statusURL` must be provided. diff --git a/Tusker/XCallbackURL/XCBActionType.swift b/Tusker/XCallbackURL/XCBActionType.swift index d05f7252..56f23c62 100644 --- a/Tusker/XCallbackURL/XCBActionType.swift +++ b/Tusker/XCallbackURL/XCBActionType.swift @@ -10,10 +10,12 @@ import Foundation enum XCBActionType: String { // Statuses + case showStatus case postStatus case favoriteStatus case reblogStatus // Accounts + case showAccount case getCurrentUser case followUser diff --git a/Tusker/XCallbackURL/XCBActions.swift b/Tusker/XCallbackURL/XCBActions.swift index c7572101..2bed567b 100644 --- a/Tusker/XCallbackURL/XCBActions.swift +++ b/Tusker/XCallbackURL/XCBActions.swift @@ -22,7 +22,101 @@ struct XCBActions { navController.pushViewController(vc, animated: animated) } + static func getStatus(from url: XCallbackURL, session: XCBSession, completion: @escaping (Status) -> Void) { + if let id = url.arguments["statusID"] { + MastodonCache.status(for: id) { (status) in + if let status = status { + completion(status) + } else { + session.complete(with: .error, additionalData: [ + "error": "Could not get status with ID \(id)" + ]) + } + } + } else if let searchQuery = url.arguments["statusURL"] { + let request = MastodonController.shared.client.search(query: searchQuery) + MastodonController.shared.client.run(request) { (response) in + if case let .success(results, _) = response, + let status = results.statuses.first { + MastodonCache.add(status: status) + completion(status) + } else { + session.complete(with: .error, additionalData: [ + "error": "Could not find status by searching '\(searchQuery)'" + ]) + } + } + } else { + session.complete(with: .error, additionalData: [ + "error": "No status provided. Specify either instance-local statusID or remote statusURL." + ]) + } + } + + static func getAccount(from url: XCallbackURL, session: XCBSession, completion: @escaping (Account) -> Void) { + if let id = url.arguments["accountID"] { + MastodonCache.account(for: id) { (account) in + if let account = account { + completion(account) + } else { + session.complete(with: .error, additionalData: [ + "error": "Could not get account with ID \(id)" + ]) + } + } + } else if let searchQuery = url.arguments["accountURL"] { + let request = MastodonController.shared.client.search(query: searchQuery) + MastodonController.shared.client.run(request) { (response) in + if case let .success(results, _) = response { + if let account = results.accounts.first { + MastodonCache.add(account: account) + completion(account) + } else { + session.complete(with: .error, additionalData: [ + "error": "Could not find account by searching '\(searchQuery)'" + ]) + } + } else if case let .failure(error) = response { + session.complete(with: .error, additionalData: [ + "error": error.localizedDescription + ]) + } + } + } else if let acct = url.arguments["acct"] { + let request = MastodonController.shared.client.searchForAccount(query: acct) + MastodonController.shared.client.run(request) { (response) in + if case let .success(accounts, _) = response { + if let account = accounts.first { + MastodonCache.add(account: account) + completion(account) + } else { + session.complete(with: .error, additionalData: [ + "error": "Could not find account \(acct)" + ]) + } + } else if case let .failure(error) = response { + session.complete(with: .error, additionalData: [ + "error": error.localizedDescription + ]) + } + } + } else { + session.complete(with: .error, additionalData: [ + "error": "No status provided. Specify either instance-local ID, account URL, or qualified username." + ]) + } + } + // MARK: - Statuses + static func showStatus(_ url: XCallbackURL, _ session: XCBSession, _ silent: Bool?) { + getStatus(from: url, session: session) { (status) in + let vc = ConversationViewController.create(for: status.id) + DispatchQueue.main.async { + presentNav(vc, animated: true) + } + } + } + static func postStatus(_ url: XCallbackURL, _ session: XCBSession, _ silent: Bool?) { let mentioning = url.arguments["mentioning"] let text = url.arguments["text"] @@ -101,36 +195,19 @@ struct XCBActions { } } - if let id = url.arguments["statusID"] { - MastodonCache.status(for: id) { (status) in - if let status = status { - favorite(status) - } else { - session.complete(with: .error, additionalData: [ - "error": "Could not get status with ID \(id)" - ]) - } - } - } else if let searchQuery = url.arguments["statusURL"] { - let request = MastodonController.shared.client.search(query: searchQuery) - MastodonController.shared.client.run(request) { (response) in - if case let .success(results, _) = response, - let status = results.statuses.first { - favorite(status) - } else { - session.complete(with: .error, additionalData: [ - "error": "Could not find status by searching '\(searchQuery)'" - ]) - } - } - } else { - session.complete(with: .error, additionalData: [ - "error": "No status provided. Specify either instance-local statusID or remote statusURL" - ]) - } + getStatus(from: url, session: session, completion: favorite) } // MARK: - Accounts + static func showAccount(_ url: XCallbackURL, _ session: XCBSession, _ silent: Bool?) { + getAccount(from: url, session: session) { (account) in + let vc = ProfileTableViewController.create(for: account.id) + DispatchQueue.main.async { + presentNav(vc, animated: true) + } + } + } + static func getCurrentUser(_ url: XCallbackURL, _ session: XCBSession, _ silent: Bool?) { let account = MastodonController.shared.account! session.complete(with: .success, additionalData: [ @@ -183,50 +260,6 @@ struct XCBActions { } } - if let id = url.arguments["accountID"] { - MastodonCache.account(for: id) { (account) in - if let account = account { - follow(account) - } else { - session.complete(with: .error, additionalData: [ - "error": "Could not get account with ID \(id)" - ]) - } - } - } else if let searchQuery = url.arguments["accountURL"] { - let request = MastodonController.shared.client.search(query: searchQuery) - MastodonController.shared.client.run(request) { (response) in - if case let .success(results, _) = response { - if let account = results.accounts.first { - follow(account) - } else { - session.complete(with: .error, additionalData: [ - "error": "Could not find account by searching '\(searchQuery)'" - ]) - } - } else if case let .failure(error) = response { - session.complete(with: .error, additionalData: [ - "error": error.localizedDescription - ]) - } - } - } else if let acct = url.arguments["acct"] { - let request = MastodonController.shared.client.searchForAccount(query: acct) - MastodonController.shared.client.run(request) { (response) in - if case let .success(accounts, _) = response { - if let account = accounts.first { - follow(account) - } else { - session.complete(with: .error, additionalData: [ - "error": "Could not find account \(acct)" - ]) - } - } else if case let .failure(error) = response { - session.complete(with: .error, additionalData: [ - "error": error.localizedDescription - ]) - } - } - } + getAccount(from: url, session: session, completion: follow) } } diff --git a/Tusker/XCallbackURL/XCBManager.swift b/Tusker/XCallbackURL/XCBManager.swift index eae30361..22db0e56 100644 --- a/Tusker/XCallbackURL/XCBManager.swift +++ b/Tusker/XCallbackURL/XCBManager.swift @@ -12,10 +12,12 @@ class XCBManager { static var specs: [XCallbackURLSpec] = [ // Statuses + XCallbackURLSpec(type: .showStatus, arguments: ["statusID": true, "statusURL": true], canRunSilently: false, action: XCBActions.showStatus), XCallbackURLSpec(type: .postStatus, arguments: ["mentioning": true, "text": true], canRunSilently: true, action: XCBActions.postStatus), XCallbackURLSpec(type: .favoriteStatus, arguments: ["statusID": true, "statusURL": true], canRunSilently: true, action: XCBActions.favoriteStatus), XCallbackURLSpec(type: .reblogStatus, arguments: ["statusID": true, "statusURL": true], canRunSilently: true, action: XCBActions.reblogStatus), // Accounts + XCallbackURLSpec(type: .showAccount, arguments: ["accountID": true, "accountURL": true, "acct": true], canRunSilently: false, action: XCBActions.showAccount), XCallbackURLSpec(type: .getCurrentUser, arguments: [:], canRunSilently: false, action: XCBActions.getCurrentUser), XCallbackURLSpec(type: .followUser, arguments: ["accountID": true, "accountURL": true, "acct": true], canRunSilently: true, action: XCBActions.followUser) ]