PatreonAPI-Swift

Swift 中用于与 Patreon API 交互的缺失库。

Swift Version License

由于我需要在我们的某个项目中展示 Patreon 活动,但没有 Swift Package 或 Swift 中 Patreon API 的基础代码,所以我需要自己编写。我认为社区也需要这个东西,所以我把它做成了一个 package,以便让其他开发者更容易,因为这个 API 简直是个噩梦!

安装

将此项目添加到您的 Package.swift 文件中

import PackageDescription

let package = Package(
    dependencies: [
        .package(url: "https://github.com/amirsaam/PatreonAPI-Swift.git", from: "0.9.00"),
    ]
)

使用示例

首先导入该 package

import PatreonAPI

初始化类

let patreonAPI = PatreonAPI(clientID: "YOUR CLIENT ID",
                            clientSecret: "YOUR CLIENT SECRET",
                            creatorAccessToken: "YOUR CREATOR'S ACCESS TOKEN",
                            creatorRefreshToken: "YOUR CREATOR'S REFRESH TOKEN",
                            redirectURI: "YOUR CLIENT REDIRECT URL",
                            campaignID: "YOUR CAMPAIGN ID")

使用内置函数

// For Authentication: 
patreonAPI.doOAuth() // Uses Client ID and Redirect URI from Initialiser
var oauthData = await patreonAPI.getOAuthTokens(callbackCode: "CALLBACK CODE FROM doOAuth()") // Uses Client ID, Client Secret and Redirect URI from Initialiser
oauthData = await patreonAPI.refreshOAuthTokens(userRefreshToken: oauthData?.refresh_token ?? "") // Uses Client Secret and Redirect URI from Initialiser

// For Retrieving Data:
let userIdentity = await patreonAPI.getUserIdentity(userAccessToken: oauthData?.access_token ?? "")
let userCampaigns = await patreonAPI.getUserOwnedCampaigns(userAccessToken: oauthData?.access_token ?? "")
let creatorCampaign = await patreonAPI.getDataForCampaign() // Uses Creator Access Token and Campaign ID from Initialiser
let creatorCampaignMembersList = await patreonAPI.getMembersForCampaign() // Uses Creator Access Token and Campaign ID from Initialiser
let specificMemberFromCreatorCampaign = await patreonAPI.getMemberForCampaignByID(memberID: "MEMBER OF CAMPAIGN ID") // Uses Creator Access Token from Initialiser. `memberID` should be retrieved from `membersList`

处理 doOAuth()

extension URL {
    func params() -> [String : Any] {
        var dict = [String : Any]()
        if let components = URLComponents(url: self, resolvingAgainstBaseURL: false) {
            if let queryItems = components.queryItems {
                for item in queryItems {
                    dict[item.name] = item.value!
                }
            }
            return dict
        } else {
            return [:]
        }
    }
}

将来可以这样使用

.onOpenURL { url in
  let callback = url.params()
  if callback.isEmpty {
      // handle callback being unsuccessful
  } else {
      let patreonCallbackCode = callback["code"] as! String
      let patreonCallbackState = callback["state"] as! String
  }
}

然后,您可以将 patreonCallbackCode 传递给 getOAuthTokens 函数。

Patreon API 中的一个问题

不幸的是,当我尝试检索有关创作者活动的所有数据时,我遇到了一个奇怪的情况,即返回的数据具有相同的名称,没有任何区分能力,我需要使用本地 Swift 体验来解码结构体。所以我创建了一个名为 CodableAny 的东西(它在这个 package 的依赖项中)来解决我自己的问题。基本上,当我们调用 getDataForCampaign 函数时,我们将返回

public struct PatreonCampaignInfo: Codable {
    public let data: CampaignData
    public let included: [CampaignIncludedAny]
    public let links: SelfLink
}

CampaignIncludedAny

public struct CampaignIncludedAny: Codable {
    public let attributes: [String: CodableAny]
    public let id: String
    public let type: String
}

因此,我们在一个网络调用中检索了 API 调用的 Included 部分中的任何数据,但它没有被解码,因此需要额外的本地步骤!在您的 Patreon ViewModel 中,您可以使用这样的东西来解码 Included 部分,具体取决于它是 Tier 数据还是 Benefit 数据。

@Published var campaignTiers: [CampaignIncludedTier] = []
@Published var campaignBenefits: [CampaignIncludedBenefit] = []
@Published var patreonCampaign: PatreonCampaignInfo? {
    didSet {
        if let campaign = patreonCampaign {
            campaignTiers = extractCampaignTiers(from: campaign.included)
            campaignBenefits = extractCampaignBenefits(from: campaign.included)
        } else {
            campaignTiers = []
            campaignBenefits = []
        }
    }
}

func extractCampaignTiers(from campaign: [CampaignIncludedAny]) -> [CampaignIncludedTier] {
    var decodedArray = [CampaignIncludedTier]()
    for campaignIncluded in campaign {
        if campaignIncluded.type == "tier" {
            let decoded = try? JSONDecoder().decode(CampaignIncludedTier.self, from: try JSONEncoder().encode(campaignIncluded))
            if let decoded = decoded {
                decodedArray.append(decoded)
            }
        }
    }
    return decodedArray
}

func extractCampaignBenefits(from campaign: [CampaignIncludedAny]) -> [CampaignIncludedBenefit] {
    var decodedArray = [CampaignIncludedBenefit]()
    for campaignIncluded in campaign {
        if campaignIncluded.type == "benefit" {
            let decoded = try? JSONDecoder().decode(CampaignIncludedBenefit.self, from: try JSONEncoder().encode(campaignIncluded))
            if let decoded = decoded {
                decodedArray.append(decoded)
            }
        }
    }
    return decodedArray
}

有关解码结构的更多信息,请访问 此目录

待办事项

依赖项

元数据

Amir Mohammadi – @amirsaam – amirsaam [at] me [dot] com

根据 MIT 许可证分发。 有关更多信息,请参见 LICENSE

https://github.com/amirsaam/PatreonAPI-Swift/