Swift 中用于与 Patreon API 交互的缺失库。
由于我需要在我们的某个项目中展示 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
函数。
不幸的是,当我尝试检索有关创作者活动的所有数据时,我遇到了一个奇怪的情况,即返回的数据具有相同的名称,没有任何区分能力,我需要使用本地 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
。