Skip to content

Commit

Permalink
Misskey Api Test + v13.8.1 Support
Browse files Browse the repository at this point in the history
  • Loading branch information
Lakr233 committed Mar 1, 2023
1 parent 3dc8ba6 commit b2d3742
Show file tree
Hide file tree
Showing 30 changed files with 1,554 additions and 37 deletions.
1 change: 1 addition & 0 deletions Foundation/Source/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ DerivedData/
.swiftpm/config/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
Package.resolved
5 changes: 5 additions & 0 deletions Foundation/Source/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ let package = Package(
platforms: [
.iOS(.v14),
.macCatalyst(.v14),
.macOS(.v10_15),
],
products: [.library(name: "Source", targets: ["Source"])],
dependencies: [
Expand Down Expand Up @@ -41,5 +42,9 @@ let package = Package(
"Module",
"NetworkModule",
]),

.testTarget(name: "SourceTest", dependencies: [
"Source",
]),
]
)
4 changes: 2 additions & 2 deletions Foundation/Source/Sources/Module/Post.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public class Post: Equatable, Hashable {
}
}

public enum Visibility: String, Codable, Equatable, Hashable {
public enum Visibility: String, Codable, Equatable, Hashable, CaseIterable {
case `public`
case home
case followers
Expand All @@ -94,7 +94,7 @@ public class Post: Equatable, Hashable {
cw: String? = nil,
localOnly: Bool = false,
visibility: Visibility = .public,
visibleUserIds: [NoteID] = []
visibleUserIds: [UserID] = []
) {
self.text = text
self.attachments = attachments
Expand Down
9 changes: 6 additions & 3 deletions Foundation/Source/Sources/Network/Network.swift
Original file line number Diff line number Diff line change
Expand Up @@ -215,12 +215,15 @@ extension Network {
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
}

func cleaningJsonObjectByDeletingNullKeyValue(object: inout [AnyHashable: Any?]) {
func cleaningJsonObjectByDeletingSpecialEmptyKeyValue(
object: inout [AnyHashable: Any?]
) {
var result = [AnyHashable: Any?]()
for (key, value) in object {
guard var value else { continue }
if let value = value as? String, value.isEmpty { continue }
if var deep = value as? [AnyHashable: Any?] {
cleaningJsonObjectByDeletingNullKeyValue(object: &deep)
cleaningJsonObjectByDeletingSpecialEmptyKeyValue(object: &deep)
value = deep
}
result[key] = value
Expand All @@ -242,7 +245,7 @@ extension Network {
options: .fragmentsAllowed
) as? [AnyHashable: Any?]
{
cleaningJsonObjectByDeletingNullKeyValue(object: &object)
cleaningJsonObjectByDeletingSpecialEmptyKeyValue(object: &object)
if let newData = try? JSONSerialization.data(withJSONObject: object, options: .fragmentsAllowed) {
request.httpBody = newData
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public extension Network {
}

public extension Network {
func requestForHashtagsNotes(tag: String, limit: Int = 20, untilId: String?) -> NoteFetchResult<[NMNote]>? {
func requestForHashtagsNotes(tag: String, limit: Int = 20, untilId: String? = nil) -> NoteFetchResult<[NMNote]>? {
var tag = tag.trimmingCharacters(in: .whitespacesAndNewlines)
if tag.hasPrefix("#") { tag.removeFirst() }

Expand Down
16 changes: 0 additions & 16 deletions Foundation/Source/Sources/Network/Request/Request+Notes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -133,22 +133,6 @@ public extension Network {
return requestForNote(with: noteId)
}

func requestForReactionDetails(with noteId: String, reaction: String) -> [NMNoteReaction]? {
var request = prepareRequest(for: .notes_reactions_delete)
injectBodyForPost(for: &request, with: [
"noteId": noteId,
"limit": 64,
"type": reaction,
])
var ans: [NMNoteReaction]?
makeRequest(with: request) { data in
if let ret = try? decoder.decode([NMNoteReaction].self, from: data) {
ans = ret
}
}
return ans
}

/// get replies for this note
/// - Parameter noteId: id
/// - Returns: replies and extracted notes for cache
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

import Foundation
import SwiftDate

public extension Network {
/// 请求时间线的数据
Expand Down Expand Up @@ -45,12 +46,12 @@ public extension Network {
injectBodyForPost(for: &request, with: ["limit": limit])
if let sinceDate {
injectBodyForPost(for: &request, with: [
"sinceDate": String(Int(sinceDate.timeIntervalSince1970)),
"sinceDate": Int(sinceDate.timeIntervalSince1970) * 1000,
])
}
if let untilDate {
injectBodyForPost(for: &request, with: [
"untilDate": String(Int(untilDate.timeIntervalSince1970)),
"untilDate": Int(untilDate.timeIntervalSince1970) * 1000,
])
}
if let sinceId {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public extension Network {
return searchNoteWithUserDetailed(data: responseData)
}

enum UserNoteFetchType {
enum UserNoteFetchType: CaseIterable {
case notes
case replies
case attachments
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ public struct LoginChallenge {
public let requestSession: String
public let requestRecipeCheck: URLRequest

public init(requestHost: String, requestURL: URL, requestSession: String, requestRecipeCheck: URLRequest) {
self.requestHost = requestHost
self.requestURL = requestURL
self.requestSession = requestSession
self.requestRecipeCheck = requestRecipeCheck
}

public init?(host: String) {
let session = "AAA6969A-85A9-49CE-92F3-5815E52B88F5-" + UUID().uuidString
// let's use a magic here
Expand Down
18 changes: 11 additions & 7 deletions Foundation/Source/Sources/Source/Source.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ public class Source: ObservableObject, Identifiable, Equatable {

public let storeRoot: URL

internal let network: Network
public let network: Network
public private(set) var req: NetworkWrapper!

internal let database: Connection
internal let spider: Spider

public let properties: Properties

public private(set) var req: NetworkWrapper!

public let notes: KVStorage<Note>
public let notesChange = PassthroughSubject<Note.ID, Never>()
public let users: KVStorage<User>
Expand Down Expand Up @@ -69,16 +69,20 @@ public class Source: ObservableObject, Identifiable, Equatable {

public var cancellable = Set<AnyCancellable>()

public init(withLoginChallengeRecipe receipt: LoginChallengeReceipt, storageLocation: URL) {
public convenience init(withLoginChallengeRecipe receipt: LoginChallengeReceipt, storageLocation: URL) {
guard let base = URL(string: "https://\(receipt.host)") else {
fatalError()
}
self.init(withLoginChallengeRecipe: receipt, baseEndpoint: base, storageLocation: storageLocation)
}

public init(withLoginChallengeRecipe receipt: LoginChallengeReceipt, baseEndpoint base: URL, storageLocation: URL) {
assert(Thread.isMainThread)

print("[*] initializing source for \(receipt.universalIdentifier)")

self.receipt = receipt

guard let base = URL(string: "https://\(receipt.host)") else {
fatalError()
}
network = .init(base: base, credential: receipt.token)

let storage = Self.storeRoot(forReceipt: receipt, atRoot: storageLocation)
Expand Down
2 changes: 1 addition & 1 deletion Foundation/Source/Sources/Storage/KVStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public class KVStorage<T: Codable & Identifiable & Equatable> where T.ID == Stri
let data = try encoder.encode(object)
try db.run(table.insert(or: .replace, id <- object.id, content <- data))
} catch {
assertionFailure(error.localizedDescription)
print(error.localizedDescription)
return
}
publisher?.send(object.id)
Expand Down
66 changes: 66 additions & 0 deletions Foundation/Source/Tests/SourceTest/Extension/Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//
// File.swift
//
//
// Created by QAQ on 2023/3/1.
//

import Foundation
import XCTest

func dispatchAndWait(_ block: @escaping () throws -> Void) {
let sem = DispatchSemaphore(value: 0)
DispatchQueue.global().async {
do {
try block()
} catch {
XCTFail(error.localizedDescription)
}
sem.signal()
}
sem.wait()
}

func requestAndWait(url: String, allowFailure: Bool = false, data: Data? = nil, method: String = "GET", result: @escaping (Data?) -> Void) {
guard let url = URL(string: url) else {
XCTFail("failed to create URL with string \(url)")
result(nil)
return
}
let sem = DispatchSemaphore(value: 0)
DispatchQueue.global().async {
var request = URLRequest(
url: url,
cachePolicy: .reloadIgnoringLocalAndRemoteCacheData,
timeoutInterval: 10
)
request.httpMethod = method
if let data {
request.httpBody = data
if (try? JSONSerialization.jsonObject(with: data)) != nil {
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
}
}
URLSession.shared.dataTask(with: request) { data, _, error in
defer { sem.signal() }
if let err = error?.localizedDescription {
let message = "[i] networking failed on \(url) with \(err)"
if allowFailure {
print(message)
} else {
XCTFail(message)
}
}
result(data)
}.resume()
}
sem.wait()
}

func unwrapOrFail<T>(_ input: T?, execute: ((T) -> Void)? = nil) {
guard let input else {
XCTFail("failed with nil")
return
}
if let execute { execute(input) }
}
104 changes: 104 additions & 0 deletions Foundation/Source/Tests/SourceTest/SourceTest+Meta.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//
// Reminder.swift
//
//
// Created by QAQ on 2023/3/1.
//
import Foundation
import Network
import XCTest

extension SourceTest {
func checkNetworkEndpointMetadata(network: Network) {
var brokenEndpoint: [String] = []
for endpoint in Network.RequestTarget.allCases {
if let info = network.endpointInfo[endpoint] {
print(
"""
[+] validated endpoint \(endpoint.rawValue): \(info.method.rawValue) -> \(info.path)
"""
)
} else {
brokenEndpoint.append(endpoint.rawValue)
}
}
for item in brokenEndpoint {
XCTFail("endpoint \(item) failed to check test assignments")
}
}

func checkNetworkEndpointTestCasesFullFilled() {
var brokenEndpoint: [String] = []
for item in Network.RequestTarget.allCases {
if let testCase = item.underlyingTestCase {
print("[+] endpoint \(item.rawValue) assigned to \(testCase)")
} else {
brokenEndpoint.append(item.rawValue)
}
}
for item in brokenEndpoint {
XCTFail("endpoint \(item) failed to check test assignments")
}
}
}

private extension Network.RequestTarget {
var underlyingTestCase: Any? {
switch self {
case .meta: return SourceTest.test_200_api_instance.self
case .emojis: return SourceTest.test_200_api_instance.self

case .account_i: return SourceTest.test_201_api_user.self

case .i_favorites: return SourceTest.test_202_api_i_favorites.self
case .i_notification: return SourceTest.test_203_api_i_notification.self

case .following_create: return SourceTest.test_204_api_following.self
case .following_delete: return SourceTest.test_204_api_following.self
case .following_requests_accept: return SourceTest.test_204_api_following.self
case .following_requests_reject: return SourceTest.test_204_api_following.self
case .following_requests_cancel: return SourceTest.test_204_api_following.self
case .following_invalidate: return SourceTest.test_204_api_following.self

case .users: return SourceTest.test_204_api_following.self
case .user_show: return SourceTest.test_204_api_following.self
case .users_followers: return SourceTest.test_204_api_following.self
case .users_following: return SourceTest.test_204_api_following.self

case .user_notes: return SourceTest.test_205_api_user.self

case .blocking_create: return SourceTest.test_206_api_block.self
case .blocking_delete: return SourceTest.test_206_api_block.self

case .notes_create: return SourceTest.test_207_notes_create_delete.self
case .notes_delete: return SourceTest.test_207_notes_create_delete.self

case .notes_show: return SourceTest.test_208_notes_status.self
case .notes_state: return SourceTest.test_208_notes_status.self

case .notes_reactions: return SourceTest.test_208_notes_status.self
case .notes_reactions_create: return SourceTest.test_208_notes_status.self
case .notes_reactions_delete: return SourceTest.test_208_notes_status.self
case .notes_favorites_create: return SourceTest.test_208_notes_status.self
case .notes_favorites_delete: return SourceTest.test_208_notes_status.self

case .notes_timeline: return SourceTest.test_209_timeline.self
case .notes_global_timeline: return SourceTest.test_209_timeline.self
case .notes_hybrid_timeline: return SourceTest.test_209_timeline.self
case .notes_local_timeline: return SourceTest.test_209_timeline.self

case .notes_replies: return SourceTest.test_210_notes_replies.self
case .notes_search_by_tag: return SourceTest.test_211_notes_search.self
case .notes_polls_vote: return SourceTest.test_212_notes_polls_vote.self
case .notes_search: return SourceTest.test_211_notes_search.self

case .hashtags_trend: return SourceTest.test_212_hashtag_trand.self

case .drive_files: return SourceTest.test_213_drive_file.self
case .drive_files_create: return SourceTest.test_213_drive_file.self
case .drive_files_update: return SourceTest.test_213_drive_file.self

// @unknown default: return nil
}
}
}
Loading

0 comments on commit b2d3742

Please sign in to comment.