diff --git a/src/main/scala/Main.scala b/src/main/scala/Main.scala
index 92e6fb0..23cb31f 100644
--- a/src/main/scala/Main.scala
+++ b/src/main/scala/Main.scala
@@ -1,30 +1,37 @@
/*
- UNIT_CA5 - Stream management bot
- Copyright (C) 2024 digimint
+ UNIT_CA5 - Stream management bot
+ Copyright (C) 2024 digimint
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
*/
-package unit_ca5
-import slick.jdbc.PostgresProfile.api._
+import db.DatabaseLayer
+
+import twitch.api.UserAuthenticationCredential
+
+import slick.jdbc.PostgresProfile
+import slick.jdbc.H2Profile
import scala.concurrent.Await
import scala.concurrent.duration.Duration
import com.typesafe.config.ConfigFactory
import com.typesafe.config.Config
import java.time.Instant
+import twitch.api.TokenScope
-@main def hello(): Unit =
+import scala.concurrent.ExecutionContext.Implicits.global
+
+@main def main(): Unit =
println("Hello world!")
println(msg)
@@ -33,71 +40,107 @@ import java.time.Instant
println(s"Test config key: ${test_key}")
- Await.result(DBConnection.doSetup, Duration.Inf)
- println("Database initialized")
+ println("Initializing database")
+ val dbLayer = Await.result(
+ DatabaseLayer.setup(
+ PostgresProfile,
+ "db_conf"
+ ),
+ Duration.Inf
+ )
- Await.result(DBConnection.doTestInserts, Duration.Inf)
- println("Test values inserted")
+ println("Performing some test inserts...")
+
+ val query = dbLayer.uac.api.create(
+ UserAuthenticationCredential(
+ "digimint",
+ "asdfasdfasdfasdf",
+ "asdfasdfasdfasdf",
+ Instant.MAX,
+ List(
+ TokenScope.AnalyticsReadExtensions,
+ TokenScope.BitsRead,
+ TokenScope.ChannelManagePolls
+ )
+ )
+ )
+
+ Await.result(dbLayer.exec.execute(query), Duration.Inf)
+
+ println("Querying result...")
+
+ val q2 = dbLayer.uac.api.retrieve("digimint")
+
+ val res = Await.result(dbLayer.exec.execute(q2), Duration.Inf)
+
+ println(res)
+
+
+ // Await.result(DBConnection.doSetup, Duration.Inf)
+ // println("Database initialized")
+
+ // Await.result(DBConnection.doTestInserts, Duration.Inf)
+ // println("Test values inserted")
def msg = "I was compiled by Scala 3. :)"
-class UserTokens(tag: Tag) extends Table[(Int, String, String, String, Instant, Int)](tag, "USER_TOKENS"):
- def id = column[Int]("TKN_ID", O.PrimaryKey, O.AutoInc)
- def userId = column[String]("USER_ID")
- def accessToken = column[String]("ACCESS_TKN")
- def refreshToken = column[String]("REFRESH_TKN")
- def expires = column[Instant]("EXPIRES")
+// class UserTokens(tag: Tag) extends Table[(Int, String, String, String, Instant, Int)](tag, "USER_TOKENS"):
+// def id = column[Int]("TKN_ID", O.PrimaryKey, O.AutoInc)
+// def userId = column[String]("USER_ID")
+// def accessToken = column[String]("ACCESS_TKN")
+// def refreshToken = column[String]("REFRESH_TKN")
+// def expires = column[Instant]("EXPIRES")
- // Compact representation of the scopes granted to this token. If a version
- // update changes the set of required scopes, the "current" SCOPES_VERSION
- // is incremented. This then gets mapped to a set of actual scopes, which
- // other functions can check.
- def scopes_version = column[Int]("SCOPES_VERSION")
+// // Compact representation of the scopes granted to this token. If a version
+// // update changes the set of required scopes, the "current" SCOPES_VERSION
+// // is incremented. This then gets mapped to a set of actual scopes, which
+// // other functions can check.
+// def scopes_version = column[Int]("SCOPES_VERSION")
- def * = (id, userId, accessToken, refreshToken, expires, scopes_version)
+// def * = (id, userId, accessToken, refreshToken, expires, scopes_version)
- def user = foreignKey("USER_FK", userId, authUsers)(_.userId)
+// def user = foreignKey("USER_FK", userId, authUsers)(_.userId)
-val userTokens = TableQuery[UserTokens]
+// val userTokens = TableQuery[UserTokens]
-class AuthUsers(tag: Tag) extends Table[(String, String)](tag, "USERS"):
- def userId = column[String]("USER_ID", O.PrimaryKey)
- def name = column[String]("TWITCH_USERNAME")
+// class AuthUsers(tag: Tag) extends Table[(String, String)](tag, "USERS"):
+// def userId = column[String]("USER_ID", O.PrimaryKey)
+// def name = column[String]("TWITCH_USERNAME")
- def * = (userId, name)
+// def * = (userId, name)
-val authUsers = TableQuery[AuthUsers]
+// val authUsers = TableQuery[AuthUsers]
-object DBConnection{
- val db = Database.forConfig("db_conf")
+// object DBConnection{
+// val db = Database.forConfig("db_conf")
- val setup = DBIO.seq(
- (authUsers.schema ++ userTokens.schema).createIfNotExists
- )
+// val setup = DBIO.seq(
+// (authUsers.schema ++ userTokens.schema).createIfNotExists
+// )
- def doSetup =
- db.run(setup)
+// def doSetup =
+// db.run(setup)
- def doTestInserts =
- val testInserts = DBIO.seq(
- authUsers ++= Seq(
- ("a", "digimint"),
- ("b", "PancakeDragoness")
- ),
+// def doTestInserts =
+// val testInserts = DBIO.seq(
+// authUsers ++= Seq(
+// ("a", "digimint"),
+// ("b", "PancakeDragoness")
+// ),
- userTokens ++= Seq(
- (1, "a", "coolAccessToken", "coolRefreshToken", Instant.now, 1),
- (2, "b", "hotAccessToken", "hotRefreshToken", Instant.now, 1)
- )
- )
+// userTokens ++= Seq(
+// (1, "a", "coolAccessToken", "coolRefreshToken", Instant.now, 1),
+// (2, "b", "hotAccessToken", "hotRefreshToken", Instant.now, 1)
+// )
+// )
- db.run(testInserts)
- // val userInserts: DBIO[Option[Int]] = authUsers ++= Seq (
- // ("a", "digimint"),
- // ("b", "PancakeDragoness")
- // )
+// db.run(testInserts)
+// // val userInserts: DBIO[Option[Int]] = authUsers ++= Seq (
+// // ("a", "digimint"),
+// // ("b", "PancakeDragoness")
+// // )
- // val tokensInserts: DBIO[Option[Int]] = userTokens ++= Seq (
- // ()
- // )
-}
\ No newline at end of file
+// // val tokensInserts: DBIO[Option[Int]] = userTokens ++= Seq (
+// // ()
+// // )
+// }
\ No newline at end of file
diff --git a/src/main/scala/db/DatabaseLayer.scala b/src/main/scala/db/DatabaseLayer.scala
new file mode 100644
index 0000000..d304f84
--- /dev/null
+++ b/src/main/scala/db/DatabaseLayer.scala
@@ -0,0 +1,41 @@
+package db
+
+import modules.uac.UACModule
+import modules.executor.ExecutorModule
+
+import scala.concurrent.Future
+import slick.jdbc.JdbcProfile
+import scala.concurrent.ExecutionContext
+
+class DatabaseLayer(
+ val uac: UACModule,
+ val exec: ExecutorModule
+)
+
+
+object DatabaseLayer:
+ def setup(
+ profile: JdbcProfile,
+ config_loc: String = "db_conf"
+ )(implicit ec: ExecutionContext): Future[DatabaseLayer] =
+ import profile.api._
+ val database = Database.forConfig(config_loc)
+
+ // Construct and initialize modules
+ val uacModule = UACModule(profile, database)
+ val uacSetupActions = uacModule.setup
+
+ val executorModule = ExecutorModule(profile, database)
+ val executorSetupOptions = executorModule.setup
+
+ // Run initialization actions
+ val initActions = DBIO.seq(
+ uacSetupActions,
+ executorSetupOptions
+ )
+
+ database.run(initActions).map(_ =>
+ DatabaseLayer(uacModule, executorModule)
+ )
+
+
diff --git a/src/main/scala/db/internal/NotFoundException.scala b/src/main/scala/db/internal/NotFoundException.scala
new file mode 100644
index 0000000..34d95e5
--- /dev/null
+++ b/src/main/scala/db/internal/NotFoundException.scala
@@ -0,0 +1,3 @@
+package db.internal
+
+class NotFoundException extends Throwable
diff --git a/src/main/scala/db/modules/DatabaseModule.scala b/src/main/scala/db/modules/DatabaseModule.scala
new file mode 100644
index 0000000..fd3da75
--- /dev/null
+++ b/src/main/scala/db/modules/DatabaseModule.scala
@@ -0,0 +1,7 @@
+package db.modules
+
+import slick.dbio.DBIO
+import slick.jdbc.JdbcProfile
+
+trait DatabaseModule:
+ def setup: DBIO[Unit]
diff --git a/src/main/scala/db/modules/executor/ExecutorModule.scala b/src/main/scala/db/modules/executor/ExecutorModule.scala
new file mode 100644
index 0000000..31caf4e
--- /dev/null
+++ b/src/main/scala/db/modules/executor/ExecutorModule.scala
@@ -0,0 +1,16 @@
+package db.modules.executor
+
+import slick.jdbc.JdbcProfile
+import db.modules.DatabaseModule
+import scala.concurrent.Future
+
+class ExecutorModule(
+ profile: JdbcProfile,
+ database: profile.backend.Database
+) extends DatabaseModule:
+ import profile.api._
+
+ def execute[A](query: DBIO[A]): Future[A] =
+ database.run(query)
+
+ def setup: DBIO[Unit] = DBIO.successful(None)
\ No newline at end of file
diff --git a/src/main/scala/db/modules/uac/UACAPI.scala b/src/main/scala/db/modules/uac/UACAPI.scala
new file mode 100644
index 0000000..fe791b0
--- /dev/null
+++ b/src/main/scala/db/modules/uac/UACAPI.scala
@@ -0,0 +1,129 @@
+package db.modules.uac
+
+import db.internal.NotFoundException
+import db.modules.uac.{UACSchema, UACQueries}
+import twitch.api.{TwitchUID, UserAuthenticationCredential, TokenScope}
+
+import scala.concurrent.Future
+import slick.jdbc.JdbcProfile
+import scala.concurrent.ExecutionContext
+
+class UACAPI(
+ val profile: JdbcProfile,
+ val queries: UACQueries,
+ val database: profile.backend.Database
+):
+ import profile.api._
+
+ def setup: DBIO[Unit] =
+ DBIO.seq(
+ (queries.UACBase.schema ++ queries.tokenScopeBase.schema).createIfNotExists
+ )
+
+ def create(cred: UserAuthenticationCredential)(implicit ec: ExecutionContext): DBIO[Option[Int]] =
+ queries.UACBase.returning(queries.UACBase.map(_.id)).+=(
+ queries.schema.RawUAC(
+ 0,
+ cred.userId,
+ cred.accessToken,
+ cred.refreshToken,
+ cred.expires
+ )
+ ).flatMap(uacId =>
+ queries.tokenScopeBase.++=(
+ cred.scopes.map(scope =>
+ queries.schema.UACTokenScope(
+ uacId,
+ scope.uid
+ )
+ )
+ )
+ )
+
+ def retrieve(user: TwitchUID)(implicit ec: ExecutionContext): DBIO[UserAuthenticationCredential] =
+ // Construct query for base UAC data
+ queries.UACBase.filter(
+ _.userId === user
+ ).take(1)
+ .result.headOption // Take only the first UAC that matches (there should never be more than one)
+ .flatMap(res => // With the result of that query:
+ res match
+ case None => slick.dbio.FailureAction(NotFoundException()) // Don't attempt to retrieve scopes if there's no matching UAC
+ case Some(uac) =>
+ // Construct a query to retrieve relevant scopes
+ queries.tokenScopeBase.filter( scope =>
+ scope.tokenId === uac.id
+ ).result.map(res =>
+ val convertedScopes = res.map(scope =>
+ // Convert UIDs to TokenScope enums
+ TokenScope.fromUid(scope.scopeId)
+ ).filter(mappedScope =>
+ // Filter any UIDs that didn't match TokenScopes.
+ mappedScope match
+ case None => false
+ case _ => true
+ ).map(convertedScope =>
+ // Strip the Options.
+ convertedScope.get
+ )
+
+ UserAuthenticationCredential(
+ uac.userId,
+ uac.accessToken,
+ uac.refreshToken,
+ uac.expires,
+ convertedScopes.toList
+ )
+ )
+ )
+
+ // val action = database.run(query).flatMap( res =>
+ // res match
+ // case None => Future{None}
+ // case Some(uac) =>
+ // // Construct query for
+ // val scopesQuery = queries.tokenScopeBase.filter( scope =>
+ // scope.tokenId === uac.id
+ // ).result.map(res =>
+ // res.map(scope =>
+ // // Convert UIDs to TokenScope enums
+ // TokenScope.fromUid(scope.scopeId)
+ // ).filter(mappedScope =>
+ // // Filter any UIDs that didn't match TokenScopes.
+ // mappedScope match
+ // case None => false
+ // case _ => true
+ // ).map(convertedScope =>
+ // // Strip the Options.
+ // convertedScope.get
+ // )
+ // )
+
+ // database.run(scopesQuery).map(res =>
+ // UserAuthenticationCredential(
+ // uac.userId,
+ // uac.accessToken,
+ // uac.refreshToken,
+ // uac.expires,
+ // res.toList
+ // )
+ // )
+ // )
+
+ // .map((res) =>
+ // val queryResult: Option[queries.schema.RawUAC] =
+ // if res.length > 0 then Some(res[0]) else None
+
+ // if queryResult == None then
+ // throw Exception
+
+ // val scopesQuery = queries.tokenScopeBase.filter(
+ // _.tokenId === queryResult.accessToken
+ // ).take(1).result
+ // )
+
+ // action
+
+ def delete(user: TwitchUID): Future[Unit] = ???
+
+
\ No newline at end of file
diff --git a/src/main/scala/db/modules/uac/UACModule.scala b/src/main/scala/db/modules/uac/UACModule.scala
new file mode 100644
index 0000000..d354fad
--- /dev/null
+++ b/src/main/scala/db/modules/uac/UACModule.scala
@@ -0,0 +1,18 @@
+package db.modules.uac
+
+import db.modules.DatabaseModule
+import db.modules.uac.{UACAPI, UACQueries, UACSchema}
+
+import slick.jdbc.JdbcProfile
+import slick.dbio.DBIO
+
+class UACModule(
+ val profile: JdbcProfile,
+ val database: profile.backend.Database
+) extends DatabaseModule:
+ val schema = UACSchema(profile)
+ val queries = UACQueries(profile, schema)
+ val api = UACAPI(profile, queries, database)
+
+ def setup: DBIO[Unit] =
+ api.setup
diff --git a/src/main/scala/db/modules/uac/UACQueries.scala b/src/main/scala/db/modules/uac/UACQueries.scala
new file mode 100644
index 0000000..49daac5
--- /dev/null
+++ b/src/main/scala/db/modules/uac/UACQueries.scala
@@ -0,0 +1,13 @@
+package db.modules.uac
+
+import db.modules.uac.UACSchema
+
+import slick.jdbc.JdbcProfile
+
+class UACQueries(
+ val profile: JdbcProfile,
+ val schema: UACSchema
+):
+ import profile.api._
+ val UACBase = schema._uacTable
+ val tokenScopeBase = schema._uacTokenScopeTable
\ No newline at end of file
diff --git a/src/main/scala/db/modules/uac/UACSchema.scala b/src/main/scala/db/modules/uac/UACSchema.scala
new file mode 100644
index 0000000..7c76b1c
--- /dev/null
+++ b/src/main/scala/db/modules/uac/UACSchema.scala
@@ -0,0 +1,88 @@
+/*
+ UNIT_CA5 - Stream management bot
+ Copyright (C) 2024 digimint
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+ */
+package db.modules.uac
+
+import twitch.api.TwitchUID
+import twitch.api.AccessToken
+import twitch.api.RefreshToken
+
+import java.time.Instant
+import slick.jdbc.JdbcProfile
+
+class UACSchema(val profile: JdbcProfile):
+ import profile.api._
+ case class RawUAC(
+ id: Long = 0,
+ userId: TwitchUID,
+ accessToken: AccessToken,
+ refreshToken: RefreshToken,
+ expires: Instant
+ )
+
+ case class UACTokenScope(
+ tokenId: Long,
+ scopeId: Long
+ )
+
+ class UACTable(tag: Tag) extends Table[RawUAC](tag, "USER_TOKENS"):
+ def id = column[Long]("TKN_ID", O.PrimaryKey, O.AutoInc)
+ def userId = column[TwitchUID]("USER_ID")
+ def accessToken = column[AccessToken]("ACCESS_TKN")
+ def refreshToken = column[RefreshToken]("REFRESH_TKN")
+ def expires = column[Instant]("EXPIRES")
+
+ def * = (id, userId, accessToken, refreshToken, expires).mapTo[RawUAC]
+
+ val _uacTable = TableQuery[UACTable]
+
+
+ class UACTokenScopeTable(tag: Tag) extends Table[UACTokenScope](tag, "USER_TOKEN_SCOPES"):
+ def tokenId = column[Long]("TKN_ID")
+ def scopeId = column[Long]("SCOPE")
+
+ def token = foreignKey(
+ "TKN",
+ tokenId,
+ _uacTable
+ )(
+ _.id,
+ onDelete=ForeignKeyAction.Cascade
+ )
+
+ def * = (tokenId, scopeId).mapTo[UACTokenScope]
+
+ val _uacTokenScopeTable = TableQuery[UACTokenScopeTable]
+ // object api:
+ // def setup: DBIO[Unit] =
+ // DBIO.seq(
+ // (queries.UACBase.schema ++ queries.tokenScopeBase.schema).createIfNotExists
+ // )
+
+
+
+ // val queryScopesForCredential =
+ // tokenScopesQuery.join(rawUACs).on(_.tokenId === _.id)
+ // .groupBy(
+ // (token, cred) => cred.userId
+ // )
+ // .map(
+ // (userId, group) => userId -> group.map(
+ // (scope, user) => scope.scopeId
+ // )
+ // )
+
\ No newline at end of file
diff --git a/src/main/scala/db/schema/ScopesVersion.scala b/src/main/scala/db/schema/ScopesVersion.scala
deleted file mode 100644
index 0e48f4b..0000000
--- a/src/main/scala/db/schema/ScopesVersion.scala
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- UNIT_CA5 - Stream management bot
- Copyright (C) 2024 digimint
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
- */
-package unit_ca5.db.schema
-
-import unit_ca5.twitch.TokenScope
-
-trait ScopesVersion:
- val scopes: List[TokenScope]
- val version: Int
-
- def toScopes(): List[TokenScope] = scopes
-
- def toInt(): Int = version
-
- def matches(version: Int): Boolean =
- this.version == version
-
- def matches(scopes: List[TokenScope]): Boolean =
- this.scopes == scopes
-
-
-object ScopesVersion:
- val allScopesVersions: List[ScopesVersion] = List(
- scopesVersion1
- )
-
- // Construct from a list of scopes
- def apply(scopes: List[TokenScope]): Option[ScopesVersion] =
- allScopesVersions.find(
- (candidate: ScopesVersion) =>
- candidate.matches(scopes)
- )
-
- // Construct from a version number
- def apply(version: Int): Option[ScopesVersion] =
- allScopesVersions.find(
- (candidate: ScopesVersion) =>
- candidate.matches(version)
- )
-
-val scopesVersion1: ScopesVersion =
- new ScopesVersion:
- val scopes = List(
- TokenScope.UserReadChat,
- TokenScope.BitsRead,
- TokenScope.ChannelManageRaids
- )
- val version = 1
-
-
\ No newline at end of file
diff --git a/src/main/scala/db/schema/UserToken.scala b/src/main/scala/db/schema/UserToken.scala
deleted file mode 100644
index 68e63a4..0000000
--- a/src/main/scala/db/schema/UserToken.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- UNIT_CA5 - Stream management bot
- Copyright (C) 2024 digimint
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
- */
-package unit_ca5.db.schema
-
-import slick.jdbc.PostgresProfile.api._
-
-import unit_ca5.twitch.UserAuthenticationCredential
-import unit_ca5.twitch.TokenScope
-import java.time.Instant
-
-class UserAuthenticationCredentialTable(tag: Tag) extends Table[UserAuthenticationCredential](tag, "USER_TOKENS"):
- def id = column[Int]("TKN_ID", O.PrimaryKey, O.AutoInc)
- def userId = column[String]("USER_ID")
- def accessToken = column[String]("ACCESS_TKN")
- def refreshToken = column[String]("REFRESH_TKN")
- def expires = column[Instant]("EXPIRES")
-
- // Compact representation of the scopes granted to this token. If a version
- // update changes the set of required scopes, the "current" SCOPES_VERSION
- // is incremented. This then gets mapped to a set of actual scopes, which
- // other functions can check.
- def scopes_version = column[Int]("SCOPES_VERSION")
-
- def * = ???
\ No newline at end of file
diff --git a/src/main/scala/twitch/api/TokenScope.scala b/src/main/scala/twitch/api/TokenScope.scala
index 983d114..5836521 100644
--- a/src/main/scala/twitch/api/TokenScope.scala
+++ b/src/main/scala/twitch/api/TokenScope.scala
@@ -15,7 +15,7 @@
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
-package unit_ca5.twitch
+package twitch.api
/**
* Enumeration of all scopes currently supported by the Twitch API
@@ -24,7 +24,7 @@ package unit_ca5.twitch
* tokens with scopes in the database. The ordering of scopes within this enum
* is unimportant, as long as each scope's UID is unique and does not change.
*/
-enum TokenScope(val uid: Int):
+enum TokenScope(val uid: Long):
// API Scopes
case AnalyticsReadExtensions extends TokenScope(0x0000)
case AnalyticsReadGames extends TokenScope(0x0001)
@@ -105,4 +105,10 @@ enum TokenScope(val uid: Int):
case UserWriteChat extends TokenScope(0x7022)
case WhispersRead extends TokenScope(0x7030)
- case WhispersEdit extends TokenScope(0x7031)
\ No newline at end of file
+ case WhispersEdit extends TokenScope(0x7031)
+
+object TokenScope:
+ def fromUid(uid: Long): Option[TokenScope] =
+ TokenScope.values.foldLeft(None)(
+ (z, thisScope) => if(thisScope.uid == uid) Some(thisScope) else z
+ )
diff --git a/src/main/scala/twitch/api/UserAuthenticationCredential.scala b/src/main/scala/twitch/api/UserAuthenticationCredential.scala
index af944bb..b193e4b 100644
--- a/src/main/scala/twitch/api/UserAuthenticationCredential.scala
+++ b/src/main/scala/twitch/api/UserAuthenticationCredential.scala
@@ -1,36 +1,36 @@
/*
- UNIT_CA5 - Stream management bot
- Copyright (C) 2024 digimint
+ UNIT_CA5 - Stream management bot
+ Copyright (C) 2024 digimint
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
*/
-package unit_ca5.twitch
+package twitch.api
import java.time.Instant
-import unit_ca5.twitch.TokenScope
+import twitch.api.TokenScope
type TwitchUID = String
type AccessToken = String
type RefreshToken = String
case class UserAuthenticationCredential(
- userId: TwitchUID,
- accessToken: AccessToken,
- refreshToken: RefreshToken,
- expires: Instant,
- scopes: List[TokenScope]
+ userId : TwitchUID,
+ accessToken : AccessToken,
+ refreshToken : RefreshToken,
+ expires : Instant,
+ scopes : List[TokenScope]
):
def is_expired(now: Instant): Boolean =
now.isAfter(expires)
@@ -39,4 +39,6 @@ case class UserAuthenticationCredential(
scopes.contains(scope)
def supportsAll(scopeList: List[TokenScope]): Boolean =
-
\ No newline at end of file
+ scopeList.forall(
+ scopes.contains
+ )
\ No newline at end of file