Add nodeinfo request and InstanceFeatures

This commit is contained in:
Shadowfacts 2022-01-23 23:26:42 -05:00
parent 6879acbe02
commit 072e68e97b
7 changed files with 109 additions and 2 deletions

View File

@ -109,7 +109,9 @@ public class Client {
var urlRequest = URLRequest(url: url, timeoutInterval: timeoutInterval)
urlRequest.httpMethod = request.method.name
urlRequest.httpBody = request.body.data
urlRequest.setValue(request.body.mimeType, forHTTPHeaderField: "Content-Type")
if let mimeType = request.body.mimeType {
urlRequest.setValue(mimeType, forHTTPHeaderField: "Content-Type")
}
if let accessToken = accessToken {
urlRequest.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
}
@ -150,6 +152,24 @@ public class Client {
}
}
public func nodeInfo(completion: @escaping Callback<NodeInfo>) {
let wellKnown = Request<WellKnown>(method: .get, path: "/.well-known/nodeinfo")
run(wellKnown) { result in
switch result {
case let .failure(error):
completion(.failure(error))
case let .success(wellKnown, _):
if let url = wellKnown.links.first(where: { $0.rel == "http://nodeinfo.diaspora.software/ns/schema/2.0" }),
let components = URLComponents(string: url.href),
components.host == self.baseURL.host {
let nodeInfo = Request<NodeInfo>(method: .get, path: components.path)
self.run(nodeInfo, completion: completion)
}
}
}
}
// MARK: - Self
public static func getSelfAccount() -> Request<Account> {
return Request<Account>(method: .get, path: "/api/v1/accounts/verify_credentials")

View File

@ -0,0 +1,19 @@
//
// NodeInfo.swift
// Pachyderm
//
// Created by Shadowfacts on 1/22/22.
// Copyright © 2022 Shadowfacts. All rights reserved.
//
import Foundation
public struct NodeInfo: Decodable {
public let version: String
public let software: Software
public struct Software: Decodable {
public let name: String
public let version: String
}
}

View File

@ -0,0 +1,18 @@
//
// WellKnown.swift
// Pachyderm
//
// Created by Shadowfacts on 1/22/22.
// Copyright © 2022 Shadowfacts. All rights reserved.
//
import Foundation
struct WellKnown: Decodable {
let links: [Link]
struct Link: Decodable {
let href: String
let rel: String
}
}

View File

@ -116,8 +116,11 @@
D62D2422217AA7E1005076CC /* UserActivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62D2421217AA7E1005076CC /* UserActivityManager.swift */; };
D62D2424217ABF3F005076CC /* NSUserActivity+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62D2423217ABF3F005076CC /* NSUserActivity+Extensions.swift */; };
D62D2426217ABF63005076CC /* UserActivityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62D2425217ABF63005076CC /* UserActivityType.swift */; };
D62E9981279C691F00C26176 /* NodeInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62E9980279C691F00C26176 /* NodeInfo.swift */; };
D62E9983279C69D400C26176 /* WellKnown.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62E9982279C69D400C26176 /* WellKnown.swift */; };
D62E9985279CA23900C26176 /* URLSession+Development.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62E9984279CA23900C26176 /* URLSession+Development.swift */; };
D62E9987279D094F00C26176 /* StatusMetaIndicatorsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62E9986279D094F00C26176 /* StatusMetaIndicatorsView.swift */; };
D62E9989279DB2D100C26176 /* InstanceFeatures.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62E9988279DB2D100C26176 /* InstanceFeatures.swift */; };
D62FF04823D7CDD700909D6E /* AttributedStringHelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62FF04723D7CDD700909D6E /* AttributedStringHelperTests.swift */; };
D6311C5025B3765B00B27539 /* ImageDataCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6311C4F25B3765B00B27539 /* ImageDataCache.swift */; };
D6333B372137838300CE884A /* AttributedString+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6333B362137838300CE884A /* AttributedString+Helpers.swift */; };
@ -523,8 +526,11 @@
D62D2421217AA7E1005076CC /* UserActivityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserActivityManager.swift; sourceTree = "<group>"; };
D62D2423217ABF3F005076CC /* NSUserActivity+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSUserActivity+Extensions.swift"; sourceTree = "<group>"; };
D62D2425217ABF63005076CC /* UserActivityType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserActivityType.swift; sourceTree = "<group>"; };
D62E9980279C691F00C26176 /* NodeInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeInfo.swift; sourceTree = "<group>"; };
D62E9982279C69D400C26176 /* WellKnown.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WellKnown.swift; sourceTree = "<group>"; };
D62E9984279CA23900C26176 /* URLSession+Development.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URLSession+Development.swift"; sourceTree = "<group>"; };
D62E9986279D094F00C26176 /* StatusMetaIndicatorsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusMetaIndicatorsView.swift; sourceTree = "<group>"; };
D62E9988279DB2D100C26176 /* InstanceFeatures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceFeatures.swift; sourceTree = "<group>"; };
D62FF04723D7CDD700909D6E /* AttributedStringHelperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringHelperTests.swift; sourceTree = "<group>"; };
D6311C4F25B3765B00B27539 /* ImageDataCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageDataCache.swift; sourceTree = "<group>"; };
D6333B362137838300CE884A /* AttributedString+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AttributedString+Helpers.swift"; sourceTree = "<group>"; };
@ -905,6 +911,7 @@
D61099F02145686D00432DC2 /* List.swift */,
D6109A062145756700432DC2 /* LoginSettings.swift */,
D61099F22145688600432DC2 /* Mention.swift */,
D62E9980279C691F00C26176 /* NodeInfo.swift */,
D61099F4214568C300432DC2 /* Notification.swift */,
D623A53E2635F6910095BD04 /* Poll.swift */,
D61099F62145693500432DC2 /* PushSubscription.swift */,
@ -916,6 +923,7 @@
D61099FE21456A4C00432DC2 /* Status.swift */,
D6285B4E21EA695800FE4B39 /* StatusContentType.swift */,
D6109A10214607D500432DC2 /* Timeline.swift */,
D62E9982279C69D400C26176 /* WellKnown.swift */,
);
path = Model;
sourceTree = "<group>";
@ -1590,6 +1598,7 @@
D6945C2E23AC47C3005C403C /* SavedDataManager.swift */,
D6C693EE216192C2007D6A6D /* TuskerNavigationDelegate.swift */,
D6DFC69F242C4CCC00ACC392 /* WeakArray.swift */,
D62E9988279DB2D100C26176 /* InstanceFeatures.swift */,
D6D4DDD6212518A200E1C4BB /* Assets.xcassets */,
D6AEBB3F2321640F00E5038B /* Activities */,
D6F1F84E2193B9BE00F5FE67 /* Caching */,
@ -1999,6 +2008,7 @@
files = (
D61099E5214561AB00432DC2 /* Application.swift in Sources */,
D667383C23299340000A2373 /* InstanceType.swift in Sources */,
D62E9983279C69D400C26176 /* WellKnown.swift in Sources */,
D61099FF21456A4C00432DC2 /* Status.swift in Sources */,
D61099E32144C38900432DC2 /* Emoji.swift in Sources */,
D6109A0D214599E100432DC2 /* RequestRange.swift in Sources */,
@ -2026,6 +2036,7 @@
D6109A032145722C00432DC2 /* RegisteredApplication.swift in Sources */,
D6109A0921458C4A00432DC2 /* Empty.swift in Sources */,
D6285B4F21EA695800FE4B39 /* StatusContentType.swift in Sources */,
D62E9981279C691F00C26176 /* NodeInfo.swift in Sources */,
D6A3BC7923218E9200FD64D5 /* NotificationGroup.swift in Sources */,
D61099DF2144C11400432DC2 /* MastodonError.swift in Sources */,
D6A3BC7723218E1300FD64D5 /* TimelineSegment.swift in Sources */,
@ -2080,6 +2091,7 @@
D6969E9E240C81B9002843CE /* NSTextAttachment+Emoji.swift in Sources */,
D6BC9DB3232D4C07002CA326 /* WellnessPrefsView.swift in Sources */,
D64BC18F23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.swift in Sources */,
D62E9989279DB2D100C26176 /* InstanceFeatures.swift in Sources */,
D693DE5923FE24310061E07D /* InteractivePushTransition.swift in Sources */,
D69693FA25859A8000F4E116 /* ComposeSceneDelegate.swift in Sources */,
D6A3BC8A2321F79B00FD64D5 /* AccountTableViewCell.swift in Sources */,

View File

@ -44,6 +44,8 @@ class MastodonController: ObservableObject {
@Published private(set) var account: Account!
@Published private(set) var instance: Instance!
@Published private(set) var nodeInfo: NodeInfo!
@Published private(set) var instanceFeatures = InstanceFeatures()
private(set) var customEmojis: [Emoji]?
private var pendingOwnInstanceRequestCallbacks = [(Instance) -> Void]()
@ -161,6 +163,7 @@ class MastodonController: ObservableObject {
DispatchQueue.main.async {
self.ownInstanceRequest = nil
self.instance = instance
self.instanceFeatures.update(instance: instance, nodeInfo: self.nodeInfo)
for completion in self.pendingOwnInstanceRequestCallbacks {
completion(instance)
@ -169,6 +172,21 @@ class MastodonController: ObservableObject {
}
}
}
client.nodeInfo { result in
switch result {
case let .failure(error):
print("Unable to get node info: \(error)")
case let .success(nodeInfo, _):
DispatchQueue.main.async {
self.nodeInfo = nodeInfo
if let instance = self.instance {
self.instanceFeatures.update(instance: instance, nodeInfo: nodeInfo)
}
}
}
}
}
}
}

View File

@ -0,0 +1,20 @@
//
// InstanceFeatures.swift
// Tusker
//
// Created by Shadowfacts on 1/23/22.
// Copyright © 2022 Shadowfacts. All rights reserved.
//
import Foundation
import Pachyderm
struct InstanceFeatures {
private(set) var maxStatusChars = 500
private(set) var localOnlyPosts = false
mutating func update(instance: Instance, nodeInfo: NodeInfo?) {
maxStatusChars = instance.maxStatusCharacters ?? 500
localOnlyPosts = nodeInfo?.software.name == "hometown"
}
}

View File

@ -28,7 +28,7 @@ struct ComposeView: View {
}
var charactersRemaining: Int {
let limit = mastodonController.instance?.maxStatusCharacters ?? 500
let limit = mastodonController.instanceFeatures.maxStatusChars
let cwCount = draft.contentWarningEnabled ? draft.contentWarning.count : 0
return limit - (cwCount + CharacterCounter.count(text: draft.text, for: mastodonController.instance))
}