TwitchSystemComponent.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/Serialization/SerializeContext.h>
  9. #include <AzCore/Serialization/EditContext.h>
  10. #include <AzCore/std/time.h>
  11. #include "TwitchSystemComponent.h"
  12. #include "TwitchReflection.h"
  13. #include <Twitch_Traits_Platform.h>
  14. namespace Twitch
  15. {
  16. TwitchSystemComponent::TwitchSystemComponent()
  17. : m_receiptCounter(0)
  18. {
  19. }
  20. void TwitchSystemComponent::OnSystemTick()
  21. {
  22. if( m_twitchREST != nullptr)
  23. m_twitchREST->FlushEvents();
  24. }
  25. void TwitchSystemComponent::Reflect(AZ::ReflectContext* context)
  26. {
  27. if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
  28. {
  29. serialize->Class<TwitchSystemComponent, AZ::Component>()
  30. ->Version(1);
  31. if (AZ::EditContext* ec = serialize->GetEditContext())
  32. {
  33. ec->Class<TwitchSystemComponent>("Twitch", "Provides access to Twitch \"Friends\", \"Rich Presence\" APIs")
  34. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  35. // ->Attribute(AZ::Edit::Attributes::Category, "") Set a category
  36. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  37. ;
  38. }
  39. }
  40. if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  41. {
  42. Internal::Reflect(*behaviorContext);
  43. }
  44. }
  45. void TwitchSystemComponent::SetApplicationID(const AZStd::string& twitchApplicationID)
  46. {
  47. /*
  48. ** THIS CAN ONLY BE SET ONCE!!!!!!
  49. */
  50. if (m_applicationID.empty())
  51. {
  52. if (IsValidTwitchAppID(twitchApplicationID))
  53. {
  54. m_applicationID = twitchApplicationID;
  55. }
  56. else
  57. {
  58. AZ_Warning("TwitchSystemComponent::SetApplicationID", false, "Invalid Twitch Application ID! Request ignored!");
  59. }
  60. }
  61. else
  62. {
  63. AZ_Warning("TwitchSystemComponent::SetApplicationID", false, "Twitch Application ID is already set! Request ignored!");
  64. }
  65. }
  66. AZStd::string TwitchSystemComponent::GetApplicationID() const
  67. {
  68. return m_applicationID;
  69. }
  70. AZStd::string TwitchSystemComponent::GetSessionID() const
  71. {
  72. return m_cachedSessionID;
  73. }
  74. AZStd::string TwitchSystemComponent::GetUserID() const
  75. {
  76. return m_cachedClientID;
  77. }
  78. AZStd::string TwitchSystemComponent::GetOAuthToken() const
  79. {
  80. return m_cachedOAuthToken;
  81. }
  82. void TwitchSystemComponent::SetUserID(ReceiptID& receipt, const AZStd::string& userId)
  83. {
  84. // always return a receipt.
  85. receipt.SetID(GetReceipt());
  86. ResultCode rc(ResultCode::InvalidParam);
  87. if (IsValidFriendID(userId))
  88. {
  89. m_cachedClientID = userId;
  90. rc = ResultCode::Success;
  91. }
  92. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::UserIDNotify, StringValue(userId, receipt, rc));
  93. }
  94. void TwitchSystemComponent::SetOAuthToken(ReceiptID& receipt, const AZStd::string& token)
  95. {
  96. // always return a receipt.
  97. receipt.SetID(GetReceipt());
  98. ResultCode rc(ResultCode::InvalidParam);
  99. if (IsValidOAuthToken(token))
  100. {
  101. m_cachedOAuthToken = token;
  102. rc = ResultCode::Success;
  103. }
  104. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::OAuthTokenNotify, StringValue(token, receipt, rc));
  105. }
  106. void TwitchSystemComponent::RequestUserID(ReceiptID& receipt)
  107. {
  108. // always return a receipt.
  109. receipt.SetID(GetReceipt());
  110. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::UserIDNotify, StringValue(m_cachedClientID, receipt, ResultCode::Success));
  111. }
  112. void TwitchSystemComponent::RequestOAuthToken(ReceiptID& receipt)
  113. {
  114. // always return a receipt.
  115. receipt.SetID(GetReceipt());
  116. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::OAuthTokenNotify, StringValue(m_cachedOAuthToken, receipt, ResultCode::Success));
  117. }
  118. void TwitchSystemComponent::GetUser(ReceiptID& receipt)
  119. {
  120. receipt.SetID(GetReceipt());
  121. if (m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  122. {
  123. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::GetUser, UserInfoValue(UserInfo(), receipt, ResultCode::TwitchRESTError));
  124. }
  125. else
  126. {
  127. m_twitchREST->GetUser(receipt);
  128. }
  129. }
  130. void TwitchSystemComponent::ResetFriendsNotificationCount(ReceiptID& receipt, const AZStd::string& friendID)
  131. {
  132. receipt.SetID(GetReceipt());
  133. ResultCode rc(ResultCode::Success);
  134. if (m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  135. {
  136. rc = ResultCode::TwitchRESTError;
  137. }
  138. else if (!IsValidFriendID(friendID))
  139. {
  140. rc = ResultCode::InvalidParam;
  141. }
  142. if (rc != ResultCode::Success)
  143. {
  144. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::ResetFriendsNotificationCountNotify, Int64Value(0, receipt, rc));
  145. }
  146. else
  147. {
  148. m_twitchREST->ResetFriendsNotificationCount(receipt, friendID);
  149. }
  150. }
  151. void TwitchSystemComponent::GetFriendNotificationCount(ReceiptID& receipt, const AZStd::string& friendID)
  152. {
  153. receipt.SetID(GetReceipt());
  154. ResultCode rc(ResultCode::Success);
  155. if (m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  156. {
  157. rc = ResultCode::TwitchRESTError;
  158. }
  159. else if (!IsValidFriendID(friendID))
  160. {
  161. rc = ResultCode::InvalidParam;
  162. }
  163. if (rc != ResultCode::Success)
  164. {
  165. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::GetFriendNotificationCount, Int64Value(0, receipt, rc));
  166. }
  167. else
  168. {
  169. m_twitchREST->GetFriendNotificationCount(receipt, friendID);
  170. }
  171. }
  172. void TwitchSystemComponent::GetFriendRecommendations(ReceiptID& receipt, const AZStd::string& friendID)
  173. {
  174. receipt.SetID(GetReceipt());
  175. ResultCode rc(ResultCode::Success);
  176. if (m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  177. {
  178. rc = ResultCode::TwitchRESTError;
  179. }
  180. else if (!IsValidFriendID(friendID))
  181. {
  182. rc = ResultCode::InvalidParam;
  183. }
  184. if (rc != ResultCode::Success)
  185. {
  186. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::GetFriendRecommendations, FriendRecommendationValue(FriendRecommendationList(), receipt, rc));
  187. }
  188. else
  189. {
  190. m_twitchREST->GetFriendRecommendations(receipt, friendID);
  191. }
  192. }
  193. void TwitchSystemComponent::GetFriends(ReceiptID& receipt, const AZStd::string& friendID, const AZStd::string& cursor)
  194. {
  195. receipt.SetID(GetReceipt());
  196. ResultCode rc(ResultCode::Success);
  197. if (m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  198. {
  199. rc = ResultCode::TwitchRESTError;
  200. }
  201. else if (!IsValidFriendID(friendID))
  202. {
  203. rc = ResultCode::InvalidParam;
  204. }
  205. if (rc != ResultCode::Success)
  206. {
  207. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::GetFriends, GetFriendValue(GetFriendReturn(), receipt, rc));
  208. }
  209. else
  210. {
  211. m_twitchREST->GetFriends(receipt, friendID, cursor);
  212. }
  213. }
  214. void TwitchSystemComponent::GetFriendStatus(ReceiptID& receipt, const AZStd::string& sourceFriendID, const AZStd::string& targetFriendID)
  215. {
  216. receipt.SetID(GetReceipt());
  217. ResultCode rc(ResultCode::Success);
  218. if (m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  219. {
  220. rc = ResultCode::TwitchRESTError;
  221. }
  222. else if ((!sourceFriendID.empty() && !IsValidFriendID(sourceFriendID)) || !IsValidFriendID(targetFriendID))
  223. {
  224. rc = ResultCode::InvalidParam;
  225. }
  226. if(rc != ResultCode::Success)
  227. {
  228. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::GetFriendStatus, FriendStatusValue(FriendStatus(), receipt, rc));
  229. }
  230. else
  231. {
  232. m_twitchREST->GetFriendStatus(receipt, sourceFriendID, targetFriendID);
  233. }
  234. }
  235. void TwitchSystemComponent::AcceptFriendRequest(ReceiptID& receipt, const AZStd::string& friendID)
  236. {
  237. receipt.SetID(GetReceipt());
  238. ResultCode rc(ResultCode::Success);
  239. if (m_cachedClientID.empty() || m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  240. {
  241. rc = ResultCode::TwitchRESTError;
  242. }
  243. else if (!IsValidFriendID(friendID))
  244. {
  245. rc = ResultCode::InvalidParam;
  246. }
  247. if (rc != ResultCode::Success)
  248. {
  249. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::AcceptFriendRequest, Int64Value(0, receipt, rc));
  250. }
  251. else
  252. {
  253. m_twitchREST->AcceptFriendRequest(receipt, friendID);
  254. }
  255. }
  256. void TwitchSystemComponent::GetFriendRequests(ReceiptID& receipt, const AZStd::string& cursor)
  257. {
  258. receipt.SetID(GetReceipt());
  259. if (m_cachedClientID.empty() || m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  260. {
  261. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::GetFriendRequests, FriendRequestValue(FriendRequestResult(), receipt, ResultCode::TwitchRESTError));
  262. }
  263. else
  264. {
  265. m_twitchREST->GetFriendRequests(receipt, cursor);
  266. }
  267. }
  268. void TwitchSystemComponent::CreateFriendRequest(ReceiptID& receipt, const AZStd::string& friendID)
  269. {
  270. receipt.SetID(GetReceipt());
  271. ResultCode rc(ResultCode::Success);
  272. if (m_cachedClientID.empty() || m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  273. {
  274. rc = ResultCode::TwitchRESTError;
  275. }
  276. else if (!IsValidFriendID(friendID))
  277. {
  278. rc = ResultCode::InvalidParam;
  279. }
  280. if (rc != ResultCode::Success)
  281. {
  282. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::CreateFriendRequest, Int64Value(0, receipt, rc));
  283. }
  284. else
  285. {
  286. m_twitchREST->CreateFriendRequest(receipt, friendID);
  287. }
  288. }
  289. void TwitchSystemComponent::DeclineFriendRequest(ReceiptID& receipt, const AZStd::string& friendID)
  290. {
  291. receipt.SetID(GetReceipt());
  292. ResultCode rc(ResultCode::Success);
  293. if (m_cachedClientID.empty() || m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  294. {
  295. rc = ResultCode::TwitchRESTError;
  296. }
  297. else if (!IsValidFriendID(friendID))
  298. {
  299. rc = ResultCode::InvalidParam;
  300. }
  301. if (rc != ResultCode::Success)
  302. {
  303. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::DeclineFriendRequest, Int64Value(0, receipt, rc));
  304. }
  305. else
  306. {
  307. m_twitchREST->DeclineFriendRequest(receipt, friendID);
  308. }
  309. }
  310. void TwitchSystemComponent::UpdatePresenceStatus(ReceiptID& receipt, PresenceAvailability availability, PresenceActivityType activityType, const AZStd::string& gameContext)
  311. {
  312. receipt.SetID(GetReceipt());
  313. ResultCode rc(ResultCode::Success);
  314. if (m_cachedClientID.empty() || m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  315. {
  316. rc = ResultCode::TwitchRESTError;
  317. }
  318. else if ((activityType == PresenceActivityType::Playing) && !m_twitchREST->IsValidGameContext(gameContext) )
  319. {
  320. rc = ResultCode::InvalidParam;
  321. }
  322. if (rc != ResultCode::Success)
  323. {
  324. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::UpdatePresenceStatus, Int64Value(0, receipt, rc));
  325. }
  326. else
  327. {
  328. m_twitchREST->UpdatePresenceStatus(receipt, availability, activityType, gameContext);
  329. }
  330. }
  331. void TwitchSystemComponent::GetPresenceStatusofFriends(ReceiptID& receipt)
  332. {
  333. receipt.SetID(GetReceipt());
  334. if (m_cachedClientID.empty() || m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  335. {
  336. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::GetPresenceStatusofFriends, PresenceStatusValue(PresenceStatusList(), receipt, ResultCode::TwitchRESTError));
  337. }
  338. else
  339. {
  340. m_twitchREST->GetPresenceStatusofFriends(receipt);
  341. }
  342. }
  343. void TwitchSystemComponent::GetPresenceSettings(ReceiptID& receipt)
  344. {
  345. receipt.SetID(GetReceipt());
  346. if (m_cachedClientID.empty() || m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  347. {
  348. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::GetPresenceSettings, PresenceSettingsValue(PresenceSettings(), receipt, ResultCode::TwitchRESTError));
  349. }
  350. else
  351. {
  352. m_twitchREST->GetPresenceSettings(receipt);
  353. }
  354. }
  355. void TwitchSystemComponent::UpdatePresenceSettings(ReceiptID& receipt, bool isInvisible, bool shareActivity)
  356. {
  357. receipt.SetID(GetReceipt());
  358. if (m_cachedClientID.empty() || m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  359. {
  360. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::UpdatePresenceSettings, PresenceSettingsValue(PresenceSettings(), receipt, ResultCode::TwitchRESTError));
  361. }
  362. else
  363. {
  364. m_twitchREST->UpdatePresenceSettings(receipt, isInvisible, shareActivity);
  365. }
  366. }
  367. void TwitchSystemComponent::GetChannel(ReceiptID& receipt)
  368. {
  369. receipt.SetID(GetReceipt());
  370. if (m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  371. {
  372. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::GetChannel, ChannelInfoValue(ChannelInfo(), receipt, ResultCode::TwitchRESTError));
  373. }
  374. else
  375. {
  376. m_twitchREST->GetChannel(receipt);
  377. }
  378. }
  379. void TwitchSystemComponent::GetChannelbyID(ReceiptID& receipt, const AZStd::string& channelID)
  380. {
  381. receipt.SetID(GetReceipt());
  382. ResultCode rc(ResultCode::Success);
  383. if (m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  384. {
  385. rc = ResultCode::TwitchRESTError;
  386. }
  387. else if (!IsValidChannelID(channelID))
  388. {
  389. rc = ResultCode::InvalidParam;
  390. }
  391. if (rc != ResultCode::Success)
  392. {
  393. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::GetChannelbyID, ChannelInfoValue(ChannelInfo(), receipt, rc));
  394. }
  395. else
  396. {
  397. m_twitchREST->GetChannelbyID(receipt, channelID);
  398. }
  399. }
  400. void TwitchSystemComponent::UpdateChannel(ReceiptID& receipt, const ChannelUpdateInfo & channelUpdateInfo)
  401. {
  402. receipt.SetID(GetReceipt());
  403. if (m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  404. {
  405. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::UpdateChannel, ChannelInfoValue(ChannelInfo(), receipt, ResultCode::TwitchRESTError));
  406. }
  407. else
  408. {
  409. m_twitchREST->UpdateChannel(receipt, channelUpdateInfo);
  410. }
  411. }
  412. void TwitchSystemComponent::GetChannelEditors(ReceiptID& receipt, const AZStd::string& channelID)
  413. {
  414. receipt.SetID(GetReceipt());
  415. ResultCode rc(ResultCode::Success);
  416. if (m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  417. {
  418. rc = ResultCode::TwitchRESTError;
  419. }
  420. else if (!IsValidChannelID(channelID))
  421. {
  422. rc = ResultCode::InvalidParam;
  423. }
  424. if (rc != ResultCode::Success)
  425. {
  426. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::GetChannelEditors, UserInfoListValue(UserInfoList(), receipt, rc));
  427. }
  428. else
  429. {
  430. m_twitchREST->GetChannelEditors(receipt, channelID);
  431. }
  432. }
  433. void TwitchSystemComponent::GetChannelFollowers(ReceiptID& receipt, const AZStd::string& channelID, const AZStd::string& cursor, AZ::u64 offset)
  434. {
  435. receipt.SetID(GetReceipt());
  436. ResultCode rc(ResultCode::Success);
  437. if (m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  438. {
  439. rc = ResultCode::TwitchRESTError;
  440. }
  441. else if (!IsValidChannelID(channelID))
  442. {
  443. rc = ResultCode::InvalidParam;
  444. }
  445. if (rc != ResultCode::Success)
  446. {
  447. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::GetChannelFollowers, FollowerResultValue(FollowerResult(), receipt, rc));
  448. }
  449. else
  450. {
  451. m_twitchREST->GetChannelFollowers(receipt, channelID, cursor, offset);
  452. }
  453. }
  454. void TwitchSystemComponent::GetChannelTeams(ReceiptID& receipt, const AZStd::string& channelID)
  455. {
  456. receipt.SetID(GetReceipt());
  457. ResultCode rc(ResultCode::Success);
  458. if (m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  459. {
  460. rc = ResultCode::TwitchRESTError;
  461. }
  462. else if (!IsValidChannelID(channelID))
  463. {
  464. rc = ResultCode::InvalidParam;
  465. }
  466. if (rc != ResultCode::Success)
  467. {
  468. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::GetChannelTeams, ChannelTeamValue(TeamInfoList(), receipt, rc));
  469. }
  470. else
  471. {
  472. m_twitchREST->GetChannelTeams(receipt, channelID);
  473. }
  474. }
  475. void TwitchSystemComponent::GetChannelSubscribers(ReceiptID& receipt, const AZStd::string& channelID, AZ::u64 offset)
  476. {
  477. receipt.SetID(GetReceipt());
  478. ResultCode rc(ResultCode::Success);
  479. if (m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  480. {
  481. rc = ResultCode::TwitchRESTError;
  482. }
  483. else if (!IsValidChannelID(channelID))
  484. {
  485. rc = ResultCode::InvalidParam;
  486. }
  487. if (rc != ResultCode::Success)
  488. {
  489. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::GetChannelSubscribers, SubscriberValue(Subscription(), receipt, rc));
  490. }
  491. else
  492. {
  493. m_twitchREST->GetChannelSubscribers(receipt, channelID, offset);
  494. }
  495. }
  496. void TwitchSystemComponent::CheckChannelSubscriptionbyUser(ReceiptID& receipt, const AZStd::string& channelID, const AZStd::string& userID)
  497. {
  498. receipt.SetID(GetReceipt());
  499. ResultCode rc(ResultCode::Success);
  500. if (m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  501. {
  502. rc = ResultCode::TwitchRESTError;
  503. }
  504. else if (!IsValidChannelID(channelID) || !IsValidFriendID(userID))
  505. {
  506. rc = ResultCode::InvalidParam;
  507. }
  508. if (rc != ResultCode::Success)
  509. {
  510. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::CheckChannelSubscriptionbyUser, SubscriberbyUserValue(SubscriberInfo(), receipt, rc));
  511. }
  512. else
  513. {
  514. m_twitchREST->CheckChannelSubscriptionbyUser(receipt, channelID, userID);
  515. }
  516. }
  517. void TwitchSystemComponent::GetChannelVideos(ReceiptID& receipt, const AZStd::string& channelID, BroadCastType boradcastType, const AZStd::string& language, AZ::u64 offset)
  518. {
  519. receipt.SetID(GetReceipt());
  520. ResultCode rc(ResultCode::Success);
  521. if (m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  522. {
  523. rc = ResultCode::TwitchRESTError;
  524. }
  525. else if (!IsValidChannelID(channelID))
  526. {
  527. rc = ResultCode::InvalidParam;
  528. }
  529. if (rc != ResultCode::Success)
  530. {
  531. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::GetChannelVideos, VideoReturnValue(VideoReturn(), receipt, rc));
  532. }
  533. else
  534. {
  535. m_twitchREST->GetChannelVideos(receipt, channelID, boradcastType, language, offset);
  536. }
  537. }
  538. void TwitchSystemComponent::StartChannelCommercial(ReceiptID& receipt, const AZStd::string& channelID, CommercialLength length)
  539. {
  540. receipt.SetID(GetReceipt());
  541. ResultCode rc(ResultCode::Success);
  542. if (m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  543. {
  544. rc = ResultCode::TwitchRESTError;
  545. }
  546. else if (!IsValidChannelID(channelID))
  547. {
  548. rc = ResultCode::InvalidParam;
  549. }
  550. if (rc != ResultCode::Success)
  551. {
  552. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::StartChannelCommercial, StartChannelCommercialValue(StartChannelCommercialResult(), receipt, rc));
  553. }
  554. else
  555. {
  556. m_twitchREST->StartChannelCommercial(receipt, channelID, length);
  557. }
  558. }
  559. void TwitchSystemComponent::ResetChannelStreamKey(ReceiptID& receipt, const AZStd::string& channelID)
  560. {
  561. receipt.SetID(GetReceipt());
  562. ResultCode rc(ResultCode::Success);
  563. if (m_cachedOAuthToken.empty() || m_twitchREST == nullptr)
  564. {
  565. rc = ResultCode::TwitchRESTError;
  566. }
  567. else if (!IsValidChannelID(channelID))
  568. {
  569. rc = ResultCode::InvalidParam;
  570. }
  571. if (rc != ResultCode::Success)
  572. {
  573. TwitchNotifyBus::QueueBroadcast(&TwitchNotifyBus::Events::ResetChannelStreamKey, ChannelInfoValue(ChannelInfo(), receipt, rc));
  574. }
  575. else
  576. {
  577. m_twitchREST->ResetChannelStreamKey(receipt, channelID);
  578. }
  579. }
  580. void TwitchSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
  581. {
  582. provided.push_back(AZ_CRC("TwitchService"));
  583. }
  584. void TwitchSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
  585. {
  586. incompatible.push_back(AZ_CRC("TwitchService"));
  587. }
  588. void TwitchSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
  589. {
  590. (void)required;
  591. }
  592. void TwitchSystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
  593. {
  594. (void)dependent;
  595. }
  596. void TwitchSystemComponent::Init()
  597. {
  598. #if AZ_TRAIT_TWITCH_INITIALIZE_SDK
  599. // You must define the Twitch Application Client ID
  600. m_twitchREST = ITwitchREST::Alloc();
  601. // each time we create a interface we need a new session id, however this should not change during the life span of this object.
  602. AZ::Uuid sessionid(AZ::Uuid::Create());
  603. char temp[128];
  604. sessionid.ToString(temp, 128, false, false);
  605. m_cachedSessionID = AZStd::string(temp);
  606. #endif // AZ_TRAIT_TWITCH_INITIALIZE_SDK
  607. }
  608. void TwitchSystemComponent::Activate()
  609. {
  610. TwitchRequestBus::Handler::BusConnect();
  611. AZ::SystemTickBus::Handler::BusConnect();
  612. }
  613. void TwitchSystemComponent::Deactivate()
  614. {
  615. AZ::SystemTickBus::Handler::BusDisconnect();
  616. TwitchRequestBus::Handler::BusDisconnect();
  617. }
  618. AZ::u64 TwitchSystemComponent::GetReceipt()
  619. {
  620. return ++m_receiptCounter;
  621. }
  622. bool TwitchSystemComponent::IsValidString(const AZStd::string& str, AZStd::size_t minLength, AZStd::size_t maxLength) const
  623. {
  624. bool isValid = false;
  625. /*
  626. ** From Twitch (Chris Adoretti <[email protected]>) 3/14/17:
  627. ** I think its a safe bet though to make sure the string is alpha-numeric + dashes
  628. ** for now if that helps (0-9, a-f, A-F, -). We don't have a max length yet.
  629. ** The minimum length is 1.
  630. */
  631. if ((str.size() >= minLength) && (str.size() < maxLength))
  632. {
  633. AZStd::size_t found = str.find_first_not_of("0123456789abcdefABCDEF-");
  634. if (found == AZStd::string::npos)
  635. {
  636. isValid = true;
  637. }
  638. }
  639. return isValid;
  640. }
  641. bool TwitchSystemComponent::IsValidTwitchAppID(const AZStd::string& twitchAppID) const
  642. {
  643. static const AZStd::size_t kMinIDLength = 24; // min id length
  644. static const AZStd::size_t kMaxIDLength = 64; // max id length
  645. bool isValid = false;
  646. if ((twitchAppID.size() >= kMinIDLength) && (twitchAppID.size() < kMaxIDLength))
  647. {
  648. AZStd::size_t found = twitchAppID.find_first_not_of("0123456789abcdefghijklmnopqrstuvwxyz");
  649. if (found == AZStd::string::npos)
  650. {
  651. isValid = true;
  652. }
  653. }
  654. return isValid;
  655. }
  656. bool TwitchSystemComponent::IsValidFriendID(const AZStd::string& friendID) const
  657. {
  658. // The min id length should be 1
  659. // The max id length will be huge, since there is no official max length, this will allow for a large id.
  660. return IsValidString(friendID, 1, 256);
  661. }
  662. bool TwitchSystemComponent::IsValidOAuthToken(const AZStd::string& oAuthToken) const
  663. {
  664. // Twitch OAuth tokens are exactly length 30
  665. if (oAuthToken.size() == 30)
  666. {
  667. AZStd::size_t found = oAuthToken.find_first_not_of("0123456789abcdefghijklmnopqrstuvwxyz");
  668. if (found == AZStd::string::npos)
  669. {
  670. return true;
  671. }
  672. }
  673. return false;
  674. }
  675. bool TwitchSystemComponent::IsValidSyncToken(const AZStd::string& syncToken) const
  676. {
  677. // sync tokens are either empty of a opaque token of a min length of 8, but no longer than 64
  678. return syncToken.empty() ? true : IsValidString(syncToken, 8, 64);
  679. }
  680. }