-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4b1a71a
commit 3522679
Showing
8 changed files
with
347 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import Foundation | ||
import Mocker | ||
import TwitchIRC | ||
|
||
@testable import Twitch | ||
|
||
ISO8601DateFormatter().date(from: "2019-02-15T21:19:50.380833Z") | ||
|
||
struct Test: Codable { let test: DateInterval } | ||
|
||
let test = Test(test: DateInterval(start: Date(), end: Date())) | ||
|
||
print(String(data: try JSONEncoder().encode(test), encoding: .utf8)!) | ||
|
||
print(Date().formatted(.iso8601)) | ||
|
||
// let configuration = URLSessionConfiguration.default | ||
// configuration.protocolClasses = [MockingURLProtocol.self] | ||
// let mockingURLSession = URLSession(configuration: configuration) | ||
|
||
let helix = try Helix( | ||
authentication: .init( | ||
oAuth: "g9p64vxsopd4cy3qer8niqkaf6xtsv", clientID: "gp762nuuoqcoxypju8c569th9wz7q5", | ||
userId: "101676978")) | ||
|
||
let streams = try await helix.getFollowedStreams() | ||
|
||
// let url = URL(string: "https://api.twitch.tv/helix/invalid")! | ||
// Mock(url: url, contentType: .json, statusCode: 500, data: [.get: "".data(using: .utf8)!]) | ||
// .register() | ||
|
||
// let _: [Broadcaster] = try await helix.request(.get("invalid")) | ||
|
||
// _ = try await helix.getAdSchedule(broadcasterId: "101676978") | ||
|
||
let cc = ChatClient(.anonymous) | ||
|
||
print("Connecting...") | ||
let clock = ContinuousClock() | ||
|
||
var stream: AsyncThrowingStream<IncomingMessage, Error>? | ||
let elapsed = try await clock.measure { stream = try await cc.connect() } | ||
|
||
print("Took \(elapsed)") | ||
print("Joining channel...") | ||
do { try await cc.join(to: "forsen") } catch { print("you are fucked") } | ||
|
||
var count = 10 | ||
|
||
print("Listening...") | ||
guard let stream else { throw HelixError.missingClientID } | ||
for try await message in stream { | ||
print("Received message: \(message)") | ||
if case .privateMessage(let privmsg) = message { | ||
print(privmsg.message) | ||
count -= 1 | ||
} | ||
|
||
if count == 0 { | ||
try await cc.part(from: "forsen") | ||
count = 10 | ||
|
||
try await Task.sleep(nanoseconds: UInt64(5 * Double(NSEC_PER_SEC))) | ||
try await cc.join(to: "forsen") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import Foundation | ||
|
||
#if canImport(FoundationNetworking) | ||
import FoundationNetworking | ||
#endif | ||
|
||
extension Helix { | ||
public func checkUserSubscription(to channelId: String) async throws -> Subscription? { | ||
let queryItems = self.makeQueryItems( | ||
("broadcaster_id", channelId), ("user_id", self.authenticatedUserId)) | ||
|
||
let (rawResponse, result): (_, HelixData<Subscription>?) = try await self.request( | ||
.get("subscriptions/user"), with: queryItems) | ||
|
||
guard let result else { throw HelixError.invalidResponse(rawResponse: rawResponse) } | ||
|
||
return result.data.first | ||
} | ||
} | ||
|
||
public struct Subscription: Decodable { | ||
let broadcasterId: String | ||
let broadcasterLogin: String | ||
let broadcasterName: String | ||
|
||
let gifter: SubGifter? | ||
|
||
let tier: SubTier | ||
|
||
enum CodingKeys: String, CodingKey { | ||
case broadcasterId = "broadcaster_id" | ||
case broadcasterLogin = "broadcaster_login" | ||
case broadcasterName = "broadcaster_name" | ||
|
||
case isGift = "is_gift" | ||
case gifterId = "gifter_id" | ||
case gifterLogin = "gifter_login" | ||
case gifterName = "gifter_name" | ||
|
||
case tier | ||
} | ||
|
||
public init(from decoder: Decoder) throws { | ||
let container = try decoder.container(keyedBy: CodingKeys.self) | ||
|
||
self.broadcasterId = try container.decode(String.self, forKey: .broadcasterId) | ||
self.broadcasterLogin = try container.decode(String.self, forKey: .broadcasterLogin) | ||
self.broadcasterName = try container.decode(String.self, forKey: .broadcasterName) | ||
|
||
if try container.decode(Bool.self, forKey: .isGift) { | ||
self.gifter = .init( | ||
id: try container.decode(String.self, forKey: .gifterId), | ||
login: try container.decode(String.self, forKey: .gifterLogin), | ||
name: try container.decode(String.self, forKey: .gifterName)) | ||
} else { | ||
self.gifter = nil | ||
} | ||
|
||
self.tier = try container.decode(SubTier.self, forKey: .tier) | ||
} | ||
} | ||
|
||
public enum SubTier: String, Decodable { | ||
case tier1 = "1000" | ||
case tier2 = "2000" | ||
case tier3 = "3000" | ||
} | ||
|
||
public struct SubGifter: Decodable { | ||
let id: String | ||
let login: String | ||
let name: String | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import Foundation | ||
|
||
#if canImport(FoundationNetworking) | ||
import FoundationNetworking | ||
#endif | ||
|
||
extension Helix { | ||
public func getBroadcasterSubscribers( | ||
userIDs: [String]? = nil, limit: Int? = nil, after startCursor: String? = nil, | ||
before endCursor: String? = nil | ||
) async throws -> ( | ||
(total: Int, points: Int), subscribers: [Subscriber], cursor: String? | ||
) { | ||
var queryItems = self.makeQueryItems( | ||
("broadcaster_id", self.authenticatedUserId), ("first", limit.map(String.init)), | ||
("after", startCursor), ("before", endCursor)) | ||
|
||
queryItems.append( | ||
contentsOf: userIDs?.map { URLQueryItem(name: "user_id", value: $0) } ?? []) | ||
|
||
let (rawResponse, result): (_, HelixData<Subscriber>?) = try await self.request( | ||
.get("subscriptions"), with: queryItems) | ||
|
||
guard let result else { throw HelixError.invalidResponse(rawResponse: rawResponse) } | ||
guard let total = result.total, let points = result.points else { | ||
throw HelixError.invalidResponse(rawResponse: rawResponse) | ||
} | ||
|
||
return ((total, points), result.data, result.pagination?.cursor) | ||
} | ||
} | ||
|
||
public struct Subscriber: Decodable { | ||
let userId: String | ||
let userLogin: String | ||
let userName: String | ||
|
||
let broadcasterId: String | ||
let broadcasterLogin: String | ||
let broadcasterName: String | ||
|
||
let gifter: SubGifter? | ||
|
||
let planName: String | ||
let tier: SubTier | ||
|
||
enum CodingKeys: String, CodingKey { | ||
case userId = "user_id" | ||
case userLogin = "user_login" | ||
case userName = "user_name" | ||
|
||
case broadcasterId = "broadcaster_id" | ||
case broadcasterLogin = "broadcaster_login" | ||
case broadcasterName = "broadcaster_name" | ||
|
||
case isGift = "is_gift" | ||
case gifterId = "gifter_id" | ||
case gifterLogin = "gifter_login" | ||
case gifterName = "gifter_name" | ||
|
||
case planName = "plan_name" | ||
case tier | ||
} | ||
|
||
public init(from decoder: Decoder) throws { | ||
let container = try decoder.container(keyedBy: CodingKeys.self) | ||
|
||
self.userId = try container.decode(String.self, forKey: .userId) | ||
self.userLogin = try container.decode(String.self, forKey: .userLogin) | ||
self.userName = try container.decode(String.self, forKey: .userName) | ||
|
||
self.broadcasterId = try container.decode(String.self, forKey: .broadcasterId) | ||
self.broadcasterLogin = try container.decode(String.self, forKey: .broadcasterLogin) | ||
self.broadcasterName = try container.decode(String.self, forKey: .broadcasterName) | ||
|
||
if try container.decode(Bool.self, forKey: .isGift) { | ||
self.gifter = .init( | ||
id: try container.decode(String.self, forKey: .gifterId), | ||
login: try container.decode(String.self, forKey: .gifterLogin), | ||
name: try container.decode(String.self, forKey: .gifterName)) | ||
} else { | ||
self.gifter = nil | ||
} | ||
|
||
self.planName = try container.decode(String.self, forKey: .planName) | ||
self.tier = try container.decode(SubTier.self, forKey: .tier) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import Foundation | ||
import Mocker | ||
import XCTest | ||
|
||
@testable import Twitch | ||
|
||
#if canImport(FoundationNetworking) | ||
import FoundationNetworking | ||
#endif | ||
|
||
final class SubscriptionsTests: XCTestCase { | ||
private var helix: Helix! | ||
|
||
override func setUpWithError() throws { | ||
let configuration = URLSessionConfiguration.default | ||
configuration.protocolClasses = [MockingURLProtocol.self] | ||
let urlSession = URLSession(configuration: configuration) | ||
|
||
helix = try Helix( | ||
authentication: .init( | ||
oAuth: "1234567989", clientID: "abcdefghijkl", userId: "1234"), | ||
urlSession: urlSession) | ||
} | ||
|
||
func testGetBroadcasterSubscribers() async throws { | ||
let url = URL( | ||
string: "https://api.twitch.tv/helix/subscriptions?broadcaster_id=1234&first=2")! | ||
|
||
Mock( | ||
url: url, contentType: .json, statusCode: 200, | ||
data: [.get: MockedData.getBroadcasterSubscriptionsJSON] | ||
).register() | ||
|
||
let ((total, points), subscribers, cursor) = | ||
try await helix.getBroadcasterSubscribers(limit: 2) | ||
|
||
XCTAssertEqual(total, 13) | ||
XCTAssertEqual(points, 13) | ||
|
||
XCTAssertEqual(cursor, "jnksdfyg7is8do7fv7yuwbisudg") | ||
|
||
XCTAssertEqual(subscribers.count, 2) | ||
XCTAssertNotNil(subscribers.first?.gifter) | ||
XCTAssertEqual(subscribers.first?.gifter?.id, "12826") | ||
XCTAssertEqual(subscribers.first?.gifter?.login, "twitch") | ||
XCTAssertEqual(subscribers.first?.gifter?.name, "Twitch") | ||
XCTAssertNil(subscribers.last?.gifter) | ||
} | ||
|
||
func testCheckUserSubscription() async throws { | ||
let url = URL( | ||
string: | ||
"https://api.twitch.tv/helix/subscriptions/user?broadcaster_id=1234&user_id=1234")! | ||
|
||
Mock( | ||
url: url, contentType: .json, statusCode: 200, | ||
data: [.get: MockedData.checkUserSubscriptionJSON] | ||
).register() | ||
|
||
let subscription = try await helix.checkUserSubscription(to: "1234") | ||
|
||
XCTAssertEqual(subscription?.broadcasterId, "141981764") | ||
XCTAssertEqual(subscription?.gifter?.id, "12826") | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
Tests/TwitchTests/API/MockResources/Endpoints/Subscriptions/checkUserSubscription.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"data": [ | ||
{ | ||
"broadcaster_id": "141981764", | ||
"broadcaster_login": "twitchdev", | ||
"broadcaster_name": "TwitchDev", | ||
"gifter_id": "12826", | ||
"gifter_login": "twitch", | ||
"gifter_name": "Twitch", | ||
"is_gift": true, | ||
"tier": "1000" | ||
} | ||
] | ||
} |
34 changes: 34 additions & 0 deletions
34
Tests/TwitchTests/API/MockResources/Endpoints/Subscriptions/getBroadcasterSubscriptions.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
{ | ||
"data": [ | ||
{ | ||
"broadcaster_id": "141981764", | ||
"broadcaster_login": "twitchdev", | ||
"broadcaster_name": "TwitchDev", | ||
"gifter_id": "12826", | ||
"gifter_login": "twitch", | ||
"gifter_name": "Twitch", | ||
"is_gift": true, | ||
"tier": "1000", | ||
"plan_name": "Channel Subscription (twitchdev)", | ||
"user_id": "527115020", | ||
"user_name": "twitchgaming", | ||
"user_login": "twitchgaming" | ||
}, | ||
{ | ||
"broadcaster_id": "141981764", | ||
"broadcaster_login": "twitchdev", | ||
"broadcaster_name": "TwitchDev", | ||
"is_gift": false, | ||
"tier": "1000", | ||
"plan_name": "Channel Subscription (twitchdev)", | ||
"user_id": "527115020", | ||
"user_name": "twitchgaming", | ||
"user_login": "twitchgaming" | ||
} | ||
], | ||
"pagination": { | ||
"cursor": "jnksdfyg7is8do7fv7yuwbisudg" | ||
}, | ||
"total": 13, | ||
"points": 13 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters