1+ package org .codeoverflow .chatoverflow .service .twitch
2+
3+ import org .apache .http .HttpEntity
4+ import org .apache .http .client .methods .HttpGet
5+ import org .apache .http .client .utils .URIBuilder
6+ import org .apache .http .util .EntityUtils
7+ import org .apache .log4j .Logger
8+ import org .codeoverflow .chatoverflow .configuration .Credentials
9+ import org .codeoverflow .chatoverflow .framework .HttpClientActor
10+
11+ import scala .concurrent .Await
12+ import scala .concurrent .duration ._
13+
14+ /**
15+ * The twitch api connector
16+ *
17+ * @param sourceIdentifier the name to the twitch account
18+ * @param credentials the credentials to log into the twitch api
19+ */
20+ class TwitchAPIConnector (override val sourceIdentifier : String , credentials : Credentials ) extends Connector (sourceIdentifier, credentials) {
21+ private val logger = Logger .getLogger(this .getClass)
22+ private val API_FORMAT : String = " application/vnd.twitchtv.v5+json"
23+ private val BASE_URL : String = " https://api.twitch.tv/helix/"
24+ private val BASE_URL_v5 : String = " https://api.twitch.tv/kraken/"
25+ private val actorSystem = ActorSystem (" TwitchAPIActorSystem" )
26+ private val actor : ActorRef = actorSystem.actorOf(Props [HttpClientActor ])
27+ private var clientID = " "
28+ private var oauth = " "
29+
30+ override def getUniqueTypeString : String = this .getClass.getName
31+
32+ /**
33+ * Returns true, if the connector has been already instantiated and is running.
34+ */
35+ override def isRunning : Boolean = true
36+
37+ /**
38+ * Initializes the connector, e.g. creates a connection with its platform.
39+ */
40+ override def init (): Unit = {
41+ val oauth = credentials.getValue(TwitchAPIConnector .credentialsOauthKey)
42+ val clientID = credentials.getValue(TwitchAPIConnector .credentialsClientID)
43+
44+ if (clientID.isEmpty) {
45+ logger warn s " key ' ${TwitchAPIConnector .credentialsClientID}' not found in credentials for ' $sourceIdentifier'. "
46+ } else {
47+ this .clientID = clientID.get
48+ if (oauth.isEmpty) {
49+ logger warn s " key ' ${TwitchAPIConnector .credentialsOauthKey}' not found in credentials for ' $sourceIdentifier'. "
50+ } else {
51+ this .oauth = oauth.get
52+ }
53+ }
54+ }
55+
56+ def getSubscriptions (channelID : String , offset : Int = 0 , newestFirst : Boolean = true ) = {
57+ get(" channels/" + channelID + " /subscriptions" , true , true , Seq ((" limit" , " 100" ), (" offset" , String .valueOf(offset)), (" direction" , if (newestFirst) " desc" else " asc" )))
58+ }
59+
60+ def getUser (userLogin : String ) = {
61+ get(" users" , false , false , Seq ((" login" , userLogin)))
62+ }
63+
64+ def get (uri : String , auth : Boolean , oldAPI : Boolean , queryParams : Seq [(String , String )]) = {
65+ val httpGet = if (auth) getUrlAuth(uri, oldAPI) else getURL(uri, oldAPI)
66+ val urlBuilder = new URIBuilder (httpGet.getURI)
67+ queryParams.foreach(param => urlBuilder.addParameter(param._1, param._2))
68+ httpGet.setURI(urlBuilder.build())
69+ implicit val timeout : Timeout = Timeout (5 seconds)
70+ val entity = Await .result(actor ? httpGet, timeout.duration).asInstanceOf [HttpEntity ]
71+ if (entity != null ) {
72+ EntityUtils .toString(entity, " UTF-8" );
73+ }
74+ else " "
75+ }
76+
77+ def getUrlAuth (uri : String , oldAPI : Boolean ) = {
78+ val get = getURL(uri, oldAPI)
79+ get.setHeader(" Authorization" , oauth)
80+ get
81+ }
82+
83+ def getURL (uri : String , oldAPI : Boolean ) = {
84+ val baseUrl = if (oldAPI) BASE_URL_v5 else BASE_URL
85+ new HttpGet (baseUrl + uri) {
86+ setHeader(" Accept" , API_FORMAT )
87+ setHeader(" Client-ID" , clientID)
88+ }
89+ }
90+
91+ def getFollowers (userID : String ) = {
92+ get(" users/follows" , false , false , Seq ((" to_id" , userID)))
93+ }
94+
95+ /**
96+ * Shuts down the connector, closes its platform connection.
97+ */
98+ override def shutdown (): Unit = ???
99+ }
100+
101+ object TwitchAPIConnector {
102+ val credentialsOauthKey = " oauth"
103+ val credentialsClientID = " clientid"
104+ }
0 commit comments