├── .github └── workflows │ ├── jitpack-build.yml │ ├── publish.yml │ └── test.yml ├── .gitignore ├── LICENSE ├── README.md ├── build.gradle.kts ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── jitpack.yml ├── pull_request_template.md ├── settings.gradle.kts └── src ├── main └── kotlin │ └── com │ └── api │ └── igdb │ ├── apicalypse │ ├── APICalypse.kt │ └── Sort.kt │ ├── exceptions │ └── RequestException.kt │ ├── request │ ├── IGDBWrapper.kt │ ├── JsonRequest.kt │ ├── ProtoRequest.kt │ └── TwitchAuthenticator.kt │ └── utils │ ├── Endpoint.kt │ ├── Endpoints.kt │ ├── ImageBuilder.kt │ ├── ImageSize.kt │ ├── ImageType.kt │ └── TwitchToken.kt ├── resources └── com │ └── api │ └── igdb │ └── igdbproto.proto └── test ├── java └── com │ └── api │ └── igdb │ ├── TestJavaWrapper.java │ └── TestTwitchToken.java └── kotlin └── com └── api └── igdb ├── TestAPICalypseQueryParser.kt ├── TestIGDBWrapper.kt ├── TestImageBuilder.kt ├── TestProtobufRequest.kt ├── TestProxy.kt ├── TestRequestException.kt └── TestTwitchTokenKotlin.kt /.github/workflows/jitpack-build.yml: -------------------------------------------------------------------------------- 1 | name: jitpack-build 2 | 3 | on: [push] 4 | 5 | jobs: 6 | jitpack: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Branch Name 10 | run: echo running on branch ${BRANCH_NAME} 11 | env: 12 | BRANCH_NAME: ${{ github.head_ref || github.ref_name }} 13 | - name: Trigger Jitpack Build 14 | run: curl https://jitpack.io/com/github/husnjak/IGDB-API-JVM/${BRANCH_NAME}-SNAPSHOT/build.log -L | grep -o 'BUILD SUCCESSFUL' 15 | env: 16 | BRANCH_NAME: ${{ github.head_ref || github.ref_name }} 17 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Publish package 4 | 5 | # Controls when the action will run. Triggers the workflow on push or pull request 6 | # events but only for the master branch 7 | on: 8 | workflow_dispatch: 9 | inputs: 10 | packagePrefix: 11 | required: true 12 | default: 'SNAPSHOT' 13 | description: "Packages require a package version, Keep SNAPSHOT for snapshot upload. Replace SNAPSHOT for staging deploy." 14 | release: 15 | types: # This configuration does not affect the page_build event above 16 | - created 17 | 18 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 19 | jobs: 20 | # This workflow contains a single job called "build" 21 | build: 22 | # The type of runner that the job will run on 23 | runs-on: ubuntu-latest 24 | permissions: 25 | contents: read 26 | packages: write 27 | # Steps represent a sequence of tasks that will be executed as part of the job 28 | steps: 29 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 30 | - uses: actions/checkout@v4 31 | - name: Setup JDK 17 32 | uses: actions/setup-java@v3 33 | with: 34 | java-version: 17 35 | distribution: 'adopt' 36 | - name: Setup Gradle 37 | uses: gradle/gradle-build-action@v2.9.0 38 | - name: Extract branch name 39 | shell: bash 40 | run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})" 41 | id: extract_branch 42 | - if: github.event.release.tag_name == '' 43 | name: Publish SNAPSHOT package 44 | run: ./gradlew publish --no-daemon 45 | env: 46 | ORG_GRADLE_PROJECT_github_token: ${{ secrets.GITHUB_TOKEN }} 47 | ORG_GRADLE_PROJECT_github_actor: ${ GITHUB_ACTOR } 48 | ORG_GRADLE_PROJECT_sonatype_username: ${{ secrets.SONATYPE_USERNAME }} 49 | ORG_GRADLE_PROJECT_sonatype_password: ${{ secrets.SONATYPE_PASSWORD }} 50 | ORG_GRADLE_PROJECT_signingKey: ${{ secrets.PGP_KEY }} 51 | ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.PGP_PASSPHRASE }} 52 | ORG_GRADLE_PROJECT_version: ${{ steps.extract_branch.outputs.branch }}-${{ github.run_id }}-${{ github.event.inputs.packagePrefix }} 53 | - if: github.event.inputs.packagePrefix == '' 54 | name: Publish Release package 55 | run: ./gradlew publish --no-daemon 56 | env: 57 | ORG_GRADLE_PROJECT_github_token: ${{ secrets.GITHUB_TOKEN }} 58 | ORG_GRADLE_PROJECT_github_actor: ${ GITHUB_ACTOR } 59 | ORG_GRADLE_PROJECT_sonatype_username: ${{ secrets.SONATYPE_USERNAME }} 60 | ORG_GRADLE_PROJECT_sonatype_password: ${{ secrets.SONATYPE_PASSWORD }} 61 | ORG_GRADLE_PROJECT_signingKey: ${{ secrets.PGP_KEY }} 62 | ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.PGP_PASSPHRASE }} 63 | ORG_GRADLE_PROJECT_version: ${{ github.event.release.tag_name }} 64 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Java CI 3 | 4 | on: [push] 5 | 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | environment: apitesting 10 | steps: 11 | - uses: actions/checkout@v4 12 | - name: Setup JDK 17 13 | uses: actions/setup-java@v3 14 | with: 15 | java-version: 17 16 | distribution: 'adopt' 17 | - name: Setup Gradle 18 | uses: gradle/gradle-build-action@v2.9.0 19 | - name: Execute Gradle build 20 | run: ./gradlew build --no-daemon -x publish -x sign 21 | env: 22 | client_id: "${{ secrets.CLIENT_ID }}" 23 | client_secret: "${{ secrets.CLIENT_SECRET }}" 24 | bearer: "${{ secrets.BEARER_TOKEN }}" 25 | proxy_api_key: "${{ secrets.PROXY_KEY }}" 26 | proxy_url: "${{ secrets.PROXY_URL }}" 27 | ORG_GRADLE_PROJECT_version: Build-${{ github.run_id }}" 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # Package Files # 8 | *.jar 9 | *.war 10 | *.nar 11 | *.ear 12 | *.zip 13 | *.tar.gz 14 | *.tar 15 | *.rar 16 | 17 | # Gradle stuffs 18 | !gradle-wrapper.jar 19 | gradle.properties 20 | .gradle/ 21 | 22 | # IDEA stuffs 23 | .idea/shelf 24 | /ideaSDK 25 | /idea/testData/debugger/tinyApp/classes* 26 | /ultimate/dependencies 27 | /ultimate/ideaSDK 28 | /ultimate/out 29 | /ultimate/tmp 30 | .idea/libraries/Gradle*.xml 31 | .idea/libraries/Maven*.xml 32 | .idea/artifacts 33 | .idea/modules 34 | .idea/runConfigurations/JPS_*.xml 35 | .idea/libraries 36 | .idea/modules.xml 37 | .idea/gradle.xml 38 | .idea/compiler.xml 39 | .idea/inspectionProfiles/profiles_settings.xml 40 | .idea/.name 41 | /.idea 42 | .idea/**/gradle.xml 43 | .idea/**/libraries 44 | .DS_Store 45 | .idea/replstate.xml 46 | 47 | 48 | # IntelliJ 49 | out/ 50 | build/ 51 | /build 52 | !**/src/**/build 53 | !**/test/**/build 54 | 55 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 56 | hs_err_pid* 57 | .idea/workspace.xml 58 | *.DS_Store 59 | .gradle/* 60 | *.csv 61 | *.xlsx -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 husnjak 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Maven Central](https://img.shields.io/maven-central/v/io.github.husnjak/igdb-api-jvm?versionPrefix=1.3.1)](https://central.sonatype.com/artifact/io.github.husnjak/igdb-api-jvm/1.3.1) 2 | [![](https://jitpack.io/v/husnjak/IGDB-API-JVM.svg)](https://jitpack.io/#husnjak/IGDB-API-JVM) 3 | # IGDB API-JVM (V4) 4 | A Kotlin wrapper for the IGDB.com Video Game Database API. 5 | 6 | __IMPORTANT__ 7 | 8 | This wrapper is compatible with ONLY their newest release V4. 9 | 10 | ## About IGDB 11 | One of the principles behind IGDB.com is accessibility of data. We wish to share the data with anyone who wants to build cool video game oriented websites, apps and services. This means that the information you contribute to IGDB.com can be used by other projects as well. 12 | 13 | Thus, you are not only contributing to the value of this site but to thousands of other projects as well. We are looking forward to see what exciting game related projects you come up with. Happy coding! 14 | 15 | More info here: 16 | * [About the API](https://www.igdb.com/api) 17 | * [API Documentation](https://api-docs.igdb.com/) 18 | 19 | Information about the Querying language APICalypse: 20 | * [apicalypse.io](https://apicalypse.io/) 21 | 22 | ## About the wrapper 23 | This wrapper is written in Kotlin which uses the JVM and works with both Kotlin & Java projects. I have not tested it on other JVM languages but it should work for these languages as well. The examples below showcase this wrapper in both Kotlin and Java. 24 | 25 | Feel free to test it on other languages yourselves 😀 26 | 27 | The Wrapper can handle both the IGDB generated classes and JSON (Strings), I have chosen to make the API's Generated classes ([Protocol Buffers](https://developers.google.com/protocol-buffers/)) the standard way because it will make it easier to use as you don't have to create your own classes to hold the information. 28 | 29 | # Installation and setup 30 | 31 | __Maven__ 32 | 33 | ```xml 34 | 35 | io.github.husnjak 36 | igdb-api-jvm 37 | 1.3.1 38 | 39 | ``` 40 | 41 | __Gradle__ 42 | 43 | ``` gradle 44 | dependencies { 45 | implementation 'io.github.husnjak:igdb-api-jvm:1.3.1' 46 | } 47 | ``` 48 | 49 | Optional for Android (SDK: 19+). Add internet permissions in the manifest. 50 | ``` xml 51 | 52 | ``` 53 | 54 | ## Using your Twitch Developer Credentials 55 | * Create a new TwitchToken object 56 | ``` java 57 | // Java Example 58 | TwitchAuthenticator tAuth = TwitchAuthenticator.INSTANCE; 59 | TwitchToken token = tAuth.requestTwitchToken("CLIENT_ID", "CLIENT_SECRET"); 60 | 61 | // The instance stores the token in the object untill a new one is requested 62 | TwitchToken token = tAuth.getTwitchToken() 63 | 64 | ``` 65 | ``` kotlin 66 | // Kotlin example 67 | val token = TwitchAuthenticator.requestTwitchToken("CLIENT_ID", "CLIENT_SECRET") 68 | 69 | // The instance stores the token in the object untill a new one is requested 70 | TwitchAuthenticator.twitchToken 71 | ``` 72 | The `TwitchToken` object looks like this 73 | ``` json 74 | { 75 | "access_token": "ACCESS_TOKEN", 76 | "expires_in": 5135439, 77 | "token_type": "bearer" 78 | } 79 | ``` 80 | 81 | * Authenticating requests for the IGDB API 82 | ``` java 83 | // Java Example 84 | IGDBWrapper wrapper = IGDBWrapper.INSTANCE; 85 | wrapper.setCredentials("CLIENT_ID", "ACCESS_TOKEN") 86 | ``` 87 | ``` kotlin 88 | // Kotlin Example 89 | IGDBWrapper.setCredentials("CLIENT_ID", "ACCESS_TOKEN") 90 | ``` 91 | You can use the access_token from the token object. 92 | 93 | ### Android projects 94 | Do not use the `TwitchAuthenticator` in your Android applications, you don't want to create multiple access_tokens for each device. 95 | It is recommended to create your token on a server and then use a proxy api to call the IGDB api, where you append the Bearer token for each request. 96 | 97 | IGDB provides a [free AWS CloudFormation template](https://api-docs.igdb.com/#proxy) that you can deploy for this purpose with instructions on how to use it. 98 | * Create a new IGDBWrapper Object connected to the AWS Proxy server. 99 | ``` java 100 | // Java Example 101 | IGDBWrapper wrapper = IGDBWrapper.INSTANCE; 102 | Map proxyHeaders = new HashMap() {{ 103 | put("x-api-key", "PROXY_API_KEY"); 104 | }}; 105 | wrapper.setupProxy("PROXY_URL/v4", proxyHeaders); 106 | ``` 107 | ``` kotlin 108 | // Kotlin Example 109 | IGDBWrapper.setupProxy("PROXY_URL/v4", mapOf("x-api-key" to "PROXY_API_KEY")) 110 | ``` 111 | 112 | # How to use the wrapper 113 | The wrapper has two "wrapping" functions, and a lot of helper functions (one for each endpoint) 114 | The two main functions called `apiProtoRequest` and `apiJsonRequest` and they handle all the requests to the api. 115 | The class `APICalypse` handles the new querying language, so that you don't need to care about structure and syntax as much. 116 | 117 | * `apiProtoRequest` 118 | This method handles IGDB generated proto classes which returns an ByteArray to be used to fill the appropriate class. 119 | ```kotlin 120 | // Kotlin Example 121 | val bytes = apiProtoRequest(endpoint: Endpoints.GAMES, apicalypseQuery: "fields *;") 122 | val listOfGames: List = GamesResult.parseFrom(bytes).gamesList 123 | ``` 124 | ```java 125 | // Java Example 126 | byte[] bytes = wrapper.apiProtoRequest(endpoint: Endpoints.GAMES, apicalypseQuery: "fields *;"); 127 | List listOfGames = GameResult.parseFrom(bytes).getGamesList(); 128 | ``` 129 | returns a list of Game objects. 130 | 131 | * `apiJsonRequest` 132 | This method return raw JSON (String) from the API 133 | Example: 134 | ```kotlin 135 | // Kotlin Example 136 | val json: String = apiJsonRequest(endpoint: Endpoints.GAMES, APICalypseQuery: "fields *;") 137 | ``` 138 | ```java 139 | // Java Example 140 | String json = wrapper.apiJsonRequest(endpoint: Endpoints.GAMES, "fields *;"); 141 | ``` 142 | returns a String. 143 | 144 | * `APICalypse` 145 | ```kotlin 146 | // Kotlin Example 147 | val apicalypse = APICalypse() 148 | .fields("*") 149 | .exclude("*") 150 | .limit(10) 151 | .offset(0) 152 | .search("Halo") 153 | .sort("release_dates.date", Sort.ASCENDING) 154 | .where("platforms = 48") 155 | ``` 156 | ```java 157 | // Java Example 158 | APICalypse apicalypse = new APICalypse() 159 | .fields("*") 160 | .exclude("*") 161 | .limit(10) 162 | .offset(0) 163 | .search("Halo") 164 | .sort("release_dates.date", Sort.ASCENDING) 165 | .where("platforms = 48"); 166 | ``` 167 | Here are all the options, this creates a query for you. To get a String query from APICalypse just add `.buildQuery()`. 168 | 169 | __NOTE__ 170 | These examples above are only here to show you how to use the "manual" part of the wrapper. This wrapper comes with complete functions for each endpoint in the API, so you don't have to deal with the manual implementation. 171 | 172 | There are two functions for each endpoint, one for classes and one for json, for quick access. The difference between them is the name see the examples below: 173 | ```kotlin 174 | // Example of functions in Kotlin 175 | IGDBWrapper.games(APICalypse()) 176 | IGDBWrapper.platforms(APICalypse()) 177 | IGDBWrapper.genres(APICalypse()) 178 | ... 179 | IGDBWrapper.jsonGames(APICalypse()) 180 | IGDBWrapper.jsonPlatforms(APICalypse()) 181 | IGDBWrapper.jsonGenres(APICalypse()) 182 | ... 183 | ``` 184 | ```java 185 | // Example of functions in Java 186 | ProtoRequestKt.games(IGDBWrapper.INSTANCE, new APICalypse()) 187 | ProtoRequestKt.platforms(IGDBWrapper.INSTANCE, new APICalypse()) 188 | ProtoRequestKt.genres(IGDBWrapper.INSTANCE, new APICalypse()) 189 | ... 190 | JsonRequestKt.jsonGames(IGDBWrapper.INSTANCE, new APICalypse()) 191 | JsonRequestKt.jsonPlatforms(IGDBWrapper.INSTANCE, new APICalypse()) 192 | JsonRequestKt.jsonGenres(IGDBWrapper.INSTANCE, new APICalypse()) 193 | ... 194 | ``` 195 | 196 | ## ImageBuilder 197 | To simplify the process of building the image URLs for IGDBs images there is a function called `imageBuilder` which is a helping tool in requesting the perfect sized images for your project. The function requires you to get the `image_id` then set your desired size (resolution), set your desired image format (default is set to PNG). 198 | ```kotlin 199 | // Kotlin Example 200 | val image_id = "mnljdjtrh44x4snmierh" 201 | val imageURL = imageBuilder(image_id, ImageSize.SCREENSHOT_HUGE, ImageType.PNG) 202 | 203 | /* 204 | * Result: 205 | * imageURL = https://images.igdb.com/igdb/image/upload/t_screenshot_huge/mnljdjtrh44x4snmierh.png 206 | */ 207 | ``` 208 | 209 | ```java 210 | // Java Example 211 | String image_id = "mnljdjtrh44x4snmierh"; 212 | String imageURL = ImageBuilderKt.imageBuilder(image_id, ImageSize.SCREENSHOT_HUGE, ImageType.PNG) 213 | 214 | /* 215 | * Result: 216 | * imageURL = https://images.igdb.com/igdb/image/upload/t_screenshot_huge/mnljdjtrh44x4snmierh.png 217 | */ 218 | ``` 219 | More information about images can be found [here](https://api-docs.igdb.com/#images) 220 | ## Exceptions 221 | The wrapper throws an `RequestException` on every exception from the API. This exception hold three things: 222 | * HTTP status code 223 | * Request (The complete sent request for debugging) 224 | * Result (The response from the API) 225 | Request and Response come directly from the HTTP library [Fuel](https://github.com/kittinunf/Fuel) 226 | 227 | ## Code Examples 228 | * Request games from the API: 229 | ```kotlin 230 | // Kotlin 231 | IGDBWrapper.setCredentials("CLIENT_ID", "ACCESS_TOKEN") 232 | val apicalypse = APICalypse().fields("*").sort("release_dates.date", Sort.DESCENDING) 233 | try{ 234 | val games: List = IGDBWrapper.games(apicalypse) 235 | } catch(e: RequestException) { 236 | // Do something or error 237 | } 238 | ``` 239 | ```java 240 | // Java 241 | IGDBWrapper wrapper = IGDBWrapper.INSTANCE; 242 | wrapper.setCredentials("CLIENT_ID", "ACCESS_TOKEN") 243 | APICalypse apicalypse = new APICalypse().fields("*").sort("release_dates.date", Sort.DESCENDING); 244 | try{ 245 | List games = ProtoRequestKt.games(wrapper, apicalypse); 246 | } catch(RequestException e) { 247 | // Do something or error 248 | } 249 | ``` 250 | * Search in the API: 251 | __NOTE__ 252 | Search objects contain the objects from search ex: Characters, Collections, Games, Platforms, and Themes. 253 | Search does not work with Sorting! 254 | ```kotlin 255 | // Kotlin 256 | IGDBWrapper.setCredentials("CLIENT_ID", "ACCESS_TOKEN") 257 | val apicalypse = APICalypse().search("Halo").fields("*") 258 | try{ 259 | val searchResult: List = IGDBWrapper.search(apicalypse) 260 | } catch(e: RequestException) { 261 | // Do something or error 262 | } 263 | ``` 264 | ```java 265 | // Java 266 | IGDBWrapper wrapper = IGDBWrapper.INSTANCE; 267 | wrapper.setCredentials("CLIENT_ID", "ACCESS_TOKEN") 268 | APICalypse apicalypse = new APICalypse().search("Halo").fields("*") 269 | try{ 270 | List searchResult = ProtoRequestKt.search(wrapper, apicalypse); 271 | } catch(RequestException e) { 272 | // Do something or error 273 | } 274 | ``` 275 | * Request filtered results: 276 | ```kotlin 277 | // Kotlin 278 | IGDBWrapper.setCredentials("CLIENT_ID", "ACCESS_TOKEN") 279 | val apicalypse = APICalypse().fields("*") 280 | .sort("release_dates.date", Sort.DESCENDING).where("themes != 42") 281 | try{ 282 | val games: List = IGDBWrapper.games(apicalypse) 283 | } catch(e: RequestException) { 284 | // Do something or error 285 | } 286 | ``` 287 | ```java 288 | // Java 289 | IGDBWrapper wrapper = IGDBWrapper.INSTANCE; 290 | wrapper.setCredentials("CLIENT_ID", "ACCESS_TOKEN") 291 | APICalypse apicalypse = new APICalypse().fields("*") 292 | .sort("release_dates.date", Sort.DESCENDING).where("themes != 42"); 293 | try{ 294 | List games = ProtoRequestKt.games(wrapper, apicalypse); 295 | } catch(RequestException e) { 296 | // Do something or error 297 | } 298 | ``` 299 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.google.protobuf.gradle.GenerateProtoTask 2 | import de.undercouch.gradle.tasks.download.Download 3 | 4 | plugins { 5 | kotlin("jvm") version "2.1.10" 6 | id("org.jetbrains.dokka") version "1.9.20" 7 | id("maven-publish") 8 | id("signing") 9 | id("de.undercouch.download") version "5.6.0" 10 | id("com.google.protobuf") version "0.9.4" 11 | } 12 | 13 | group = "io.github.husnjak" 14 | version = findProperty("version") as String 15 | 16 | val fuelVersion = "2.3.1" 17 | val protobufJavaVersion = "4.29.3" 18 | val junitJupiterVersion = "5.12.0" 19 | val junitPlatformVersion = "1.12.0" 20 | val protobufPluginVersion = "0.9.4" 21 | 22 | repositories { 23 | mavenCentral() 24 | gradlePluginPortal() 25 | } 26 | 27 | dependencies { 28 | implementation(kotlin("stdlib")) 29 | // HTTP 30 | implementation("com.github.kittinunf.fuel:fuel:$fuelVersion") 31 | implementation("com.github.kittinunf.fuel:fuel-gson:$fuelVersion") 32 | implementation("com.github.kittinunf.fuel:fuel-android:$fuelVersion") 33 | // Protocol Buffers 34 | // set to api() to add protobuf to client classpath 35 | api("com.google.protobuf:protobuf-kotlin:$protobufJavaVersion") 36 | implementation("com.google.protobuf:protobuf-gradle-plugin:$protobufPluginVersion") 37 | // Tests 38 | testImplementation("org.junit.jupiter:junit-jupiter-api:$junitJupiterVersion") 39 | testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$junitJupiterVersion") 40 | testRuntimeOnly("org.junit.platform:junit-platform-launcher:$junitPlatformVersion") 41 | 42 | } 43 | 44 | sourceSets { 45 | main { 46 | resources { 47 | srcDirs("$projectDir/src/resources") // protofile 48 | } 49 | proto { 50 | srcDirs("$projectDir/src/resources") 51 | } 52 | } 53 | } 54 | 55 | tasks { 56 | dokkaJavadoc { 57 | outputDirectory.set(layout.buildDirectory.dir("javadoc")) 58 | dependsOn(getTasksByName("generateProto", true)) 59 | } 60 | withType { 61 | dependsOn("downloadProtoFiles") 62 | } 63 | processResources{ 64 | dependsOn(getTasksByName("generateProto", true)) 65 | duplicatesStrategy = DuplicatesStrategy.INCLUDE 66 | } 67 | } 68 | 69 | protobuf { 70 | protoc { 71 | artifact = "com.google.protobuf:protoc:$protobufJavaVersion" 72 | } 73 | } 74 | 75 | tasks.register("downloadProtoFiles",Download::class) { 76 | this.src("https://api.igdb.com/v4/igdbapi.proto") 77 | this.dest("$projectDir/src/resources/com/api/igdb/igdbproto.proto") 78 | this.overwrite(true) 79 | } 80 | 81 | val dokkaJar by tasks.registering(Jar::class) { 82 | group = JavaBasePlugin.DOCUMENTATION_GROUP 83 | description = "Assembles Kotlin docs with Dokka" 84 | archiveClassifier.set("javadoc") 85 | from(tasks.dokkaJavadoc) 86 | } 87 | 88 | val sourcesJar by tasks.registering(Jar::class) { 89 | dependsOn("generateProto") 90 | manifest { 91 | attributes("Main-Class" to "com.api.igdb.ApiRequesterKt") 92 | } 93 | group = JavaBasePlugin.DOCUMENTATION_GROUP 94 | description = "Assembles sources jar" 95 | archiveClassifier.set("sources") 96 | from(sourceSets["main"].allSource) 97 | } 98 | 99 | publishing { 100 | publications { 101 | create("maven") { 102 | from(components["kotlin"]) 103 | artifact(dokkaJar) 104 | artifact(sourcesJar) 105 | 106 | versionMapping { 107 | usage("java-api") { 108 | fromResolutionOf("runtimeClasspath") 109 | } 110 | usage("java-runtime") { 111 | fromResolutionResult() 112 | } 113 | } 114 | 115 | pom { 116 | name.set("igdb-api-jvm") 117 | description.set("Kotlin wrapper for the IGDB API compiled for the JVM.") 118 | url.set("https://github.com/husnjak/igdb-api-jvm.git") 119 | licenses { 120 | license { 121 | name.set("The MIT License (MIT)") 122 | url.set("https://mit-license.org") 123 | } 124 | } 125 | developers { 126 | developer { 127 | id.set("husnjak") 128 | } 129 | } 130 | scm { 131 | connection.set("scm:git:https://github.com/husnjak/IGDB-API-JVM.git") 132 | developerConnection.set("scm:git:git@github.com:husnjak/IGDB-API-JVM.git") 133 | url.set("https://github.com/husnjak/IGDB-API-JVM") 134 | } 135 | } 136 | } 137 | } 138 | repositories { 139 | maven { 140 | name = "GitHubPackages" 141 | url = uri("https://maven.pkg.github.com/husnjak/igdb-api-jvm") 142 | credentials { 143 | username = findProperty("github_actor") as String? 144 | password = findProperty("github_token") as String? 145 | } 146 | } 147 | maven { 148 | name = "Sonatype" 149 | val releasesRepoUrl = uri("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/") 150 | val snapshotsRepoUrl = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/") 151 | url = if (version.toString().contains("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl 152 | println("Sonatype release version: $version using: $url") 153 | credentials { 154 | username = findProperty("sonatype_username") as String? 155 | password = findProperty("sonatype_password") as String? 156 | } 157 | } 158 | } 159 | } 160 | 161 | signing { 162 | val isJitpack = System.getenv("JITPACK") ?: "" 163 | if (isJitpack == "true"){ 164 | return@signing 165 | } 166 | 167 | if (version.toString().contains("local")) { 168 | useGpgCmd() 169 | } else { 170 | val signingKey: String? by project 171 | val signingPassword: String? by project 172 | useInMemoryPgpKeys(signingKey, signingPassword) 173 | } 174 | sign(publishing.publications["maven"]) 175 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husnjak/IGDB-API-JVM/e62b531a4bb42e5031702c06ca377917560552a5/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto init 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto init 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :init 68 | @rem Get command-line arguments, handling Windows variants 69 | 70 | if not "%OS%" == "Windows_NT" goto win9xME_args 71 | 72 | :win9xME_args 73 | @rem Slurp the command line arguments. 74 | set CMD_LINE_ARGS= 75 | set _SKIP=2 76 | 77 | :win9xME_args_slurp 78 | if "x%~1" == "x" goto execute 79 | 80 | set CMD_LINE_ARGS=%* 81 | 82 | :execute 83 | @rem Setup the command line 84 | 85 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 86 | 87 | 88 | @rem Execute Gradle 89 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 90 | 91 | :end 92 | @rem End local scope for the variables with windows NT shell 93 | if "%ERRORLEVEL%"=="0" goto mainEnd 94 | 95 | :fail 96 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 97 | rem the _cmd.exe /c_ return code! 98 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 99 | exit /b 1 100 | 101 | :mainEnd 102 | if "%OS%"=="Windows_NT" endlocal 103 | 104 | :omega 105 | -------------------------------------------------------------------------------- /jitpack.yml: -------------------------------------------------------------------------------- 1 | jdk: 2 | - openjdk17 -------------------------------------------------------------------------------- /pull_request_template.md: -------------------------------------------------------------------------------- 1 | ### Change Summary 2 | _Describe your change_ 3 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "igdb-api-jvm" -------------------------------------------------------------------------------- /src/main/kotlin/com/api/igdb/apicalypse/APICalypse.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb.apicalypse 2 | 3 | /** 4 | * The ApiCalypse class uses it's functions to build out the query 5 | */ 6 | class APICalypse { 7 | private var search = "" 8 | private var fields = "" 9 | private var exclude = "" 10 | private var limit = "" 11 | private var offset = "" 12 | private var sort = "" 13 | private var where = "" 14 | 15 | /** 16 | * The ApiCalypse sort function 17 | * 18 | * @property field The field to sort by 19 | * @property order The sorting order; Ascending | Descending 20 | * @return ApiCalypse object with set sort query. 21 | */ 22 | fun sort(field: String, order: Sort): APICalypse { 23 | this.sort = "s $field ${order.apiName};" 24 | return this 25 | } 26 | 27 | /** 28 | * The ApiCalypse fields function 29 | * 30 | * @property fields The fields to select 31 | * @return ApiCalypse object with set field query. 32 | */ 33 | fun fields(fields: String): APICalypse { 34 | this.fields = "f $fields;" 35 | return this 36 | } 37 | 38 | /** 39 | * The ApiCalypse exclude function 40 | * 41 | * @property fields The fields to exclude 42 | * @return ApiCalypse object with set exclude query. 43 | */ 44 | fun exclude(fields: String): APICalypse { 45 | this.exclude = "x $fields;" 46 | return this 47 | } 48 | 49 | /** 50 | * The ApiCalypse limit function 51 | * 52 | * @property limit The number of items in the query 53 | * @return ApiCalypse object with set limit query. 54 | */ 55 | fun limit(limit: Int): APICalypse { 56 | this.limit = "l $limit;" 57 | return this 58 | } 59 | 60 | /** 61 | * The ApiCalypse offset function 62 | * 63 | * @property offset The number of items to offset in the query 64 | * @return ApiCalypse object with set offset query. 65 | */ 66 | fun offset(offset: Int): APICalypse { 67 | this.offset = "o $offset;" 68 | return this 69 | } 70 | 71 | /** 72 | * The ApiCalypse search function 73 | * 74 | * @property searchQuery The query to search for 75 | * @return ApiCalypse object with set search query. 76 | */ 77 | fun search(searchQuery: String): APICalypse { 78 | this.search = "search \"$searchQuery\";" 79 | return this 80 | } 81 | 82 | /** 83 | * The ApiCalypse where function 84 | * 85 | * @property where The logic to filter the request by 86 | * @return ApiCalypse object with set where query. 87 | */ 88 | fun where(where: String): APICalypse { 89 | if (where.contains("where ") || where.contains("w ")) { 90 | this.where = where 91 | } else { 92 | if (where.contains(";")) 93 | this.where = "w $where" 94 | else 95 | this.where = "w $where;" 96 | } 97 | return this 98 | } 99 | 100 | /** 101 | * The buildQuery function builds the ApiCalypse object to a String query. 102 | * 103 | * @return String query based on the ApiCalypse object. 104 | */ 105 | fun buildQuery(): String { 106 | var query = "" 107 | if (search.isNotBlank()) 108 | query += search 109 | if (fields.isNotBlank()) 110 | query += fields 111 | if (exclude.isNotBlank()) 112 | query += exclude 113 | if (limit.isNotBlank()) 114 | query += limit 115 | if (offset.isNotBlank()) 116 | query += offset 117 | if (sort.isNotBlank()) 118 | query += sort 119 | // TODO where 120 | if (where.isNotBlank()) 121 | query += where 122 | 123 | return query 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/main/kotlin/com/api/igdb/apicalypse/Sort.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb.apicalypse 2 | 3 | /** 4 | * The Sort Enum class maps the ApiCalypse sorting syntax to objects. 5 | */ 6 | enum class Sort(val apiName: String) { 7 | ASCENDING("asc"), DESCENDING("desc") 8 | } 9 | -------------------------------------------------------------------------------- /src/main/kotlin/com/api/igdb/exceptions/RequestException.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb.exceptions 2 | 3 | import com.github.kittinunf.fuel.core.FuelError 4 | import com.github.kittinunf.fuel.core.Request 5 | import com.github.kittinunf.result.Result 6 | 7 | /** 8 | * The Request exception class wrapps the Kotlin Fuel HTTP library exception. 9 | * 10 | * @property statucCode The status code from the API 11 | * @property request The Kotlin Fuel request object 12 | * @property result The Kotlin Fuel result object, holds the FuelError 13 | */ 14 | class RequestException(val statusCode: Int, val request: Request, val result: Result) : Exception() 15 | -------------------------------------------------------------------------------- /src/main/kotlin/com/api/igdb/request/IGDBWrapper.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb.request 2 | 3 | import com.api.igdb.exceptions.RequestException 4 | import com.api.igdb.utils.Endpoint 5 | import com.github.kittinunf.fuel.httpPost 6 | 7 | /** 8 | * The ApiRequester object holds the API Key and uses it to request the IGDB API. 9 | */ 10 | private var IGDB_API_URL = "https://api.igdb.com/v4" 11 | object IGDBWrapper { 12 | private var requestHeaders: Map = mapOf("x-user-agent" to "igdb-api-jvm") 13 | 14 | /** 15 | * The Set method for API Credentials 16 | * 17 | * @property clientID The IGDB ClientID 18 | * @property accessToken The IGDB AccessToken 19 | */ 20 | fun setCredentials(clientID: String, accessToken: String) { 21 | requestHeaders = mapOf( 22 | "client-id" to clientID, 23 | "authorization" to "Bearer $accessToken", 24 | "x-user-agent" to "igdb-api-jvm") 25 | } 26 | 27 | /** 28 | * The set method for Proxy credentials 29 | * 30 | * @property proxyURL The url of the Proxy Server 31 | * @property proxyHeaders The headers to send to the Proxy Server 32 | */ 33 | fun setupProxy(proxyURL: String, proxyHeaders: Map) { 34 | IGDB_API_URL = proxyURL 35 | proxyHeaders.toMutableMap()["x-user-agent"] = "igdb-api-jvm" 36 | requestHeaders = proxyHeaders.toMap() 37 | } 38 | 39 | /** 40 | * The Api request function for Protocol Buffers 41 | * 42 | * @property endpoint The endpoint the request 43 | * @property query The Api query to request with 44 | * @return The raw ByteArray to use with generated proto files 45 | */ 46 | @Throws(RequestException::class) 47 | fun apiProtoRequest(endpoint: Endpoint, query: String): ByteArray { 48 | val requestURL = "$IGDB_API_URL${endpoint.url()}.pb" 49 | val (request, response, result) = requestURL.httpPost() 50 | .header(requestHeaders).body(query).responseString() 51 | 52 | if (response.statusCode != 200) { 53 | throw RequestException(response.statusCode, request, result) 54 | } 55 | return response.data 56 | } 57 | 58 | /** 59 | * The Api request function for JSON 60 | * 61 | * @property endpoint The endpoint the request 62 | * @property query The Api query to request with 63 | * @return The raw String result from the request 64 | */ 65 | @Throws(RequestException::class) 66 | fun apiJsonRequest(endpoint: Endpoint, query: String): String { 67 | val requestURL = "$IGDB_API_URL${endpoint.url()}" 68 | val (request, response, result) = requestURL.httpPost() 69 | .header(requestHeaders).body(query).responseString() 70 | 71 | if (response.statusCode != 200) { 72 | throw RequestException(response.statusCode, request, result) 73 | } 74 | return result.get() 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/kotlin/com/api/igdb/request/JsonRequest.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb.request 2 | 3 | import com.api.igdb.apicalypse.APICalypse 4 | import com.api.igdb.exceptions.RequestException 5 | import com.api.igdb.utils.Endpoints 6 | 7 | @Throws(RequestException::class) 8 | fun IGDBWrapper.jsonAgeRatings(APICalypse: APICalypse): String { 9 | return apiJsonRequest(Endpoints.AGE_RATINGS, APICalypse.buildQuery()) 10 | } 11 | 12 | @Throws(RequestException::class) 13 | fun IGDBWrapper.jsonAgeRatingCategories(APICalypse: APICalypse): String { 14 | return apiJsonRequest(Endpoints.AGE_RATING_CATEGORIES, APICalypse.buildQuery()) 15 | } 16 | 17 | @Throws(RequestException::class) 18 | fun IGDBWrapper.jsonAgeRatingContentDescriptions(APICalypse: APICalypse): String { 19 | return apiJsonRequest(Endpoints.AGE_RATING_CONTENT_DESCRIPTIONS, APICalypse.buildQuery()) 20 | } 21 | 22 | @Throws(RequestException::class) 23 | fun IGDBWrapper.jsonAgeRatingContentDescriptionsV2(APICalypse: APICalypse): String { 24 | return apiJsonRequest(Endpoints.AGE_RATING_CONTENT_DESCRIPTIONS_V2, APICalypse.buildQuery()) 25 | } 26 | 27 | @Throws(RequestException::class) 28 | fun IGDBWrapper.jsonAgeRatingOrganizations(APICalypse: APICalypse): String { 29 | return apiJsonRequest(Endpoints.AGE_RATING_ORGANIZATIONS, APICalypse.buildQuery()) 30 | } 31 | 32 | @Throws(RequestException::class) 33 | fun IGDBWrapper.jsonAlternativeNames(APICalypse: APICalypse): String { 34 | return apiJsonRequest(Endpoints.ALTERNATIVE_NAMES, APICalypse.buildQuery()) 35 | } 36 | 37 | @Throws(RequestException::class) 38 | fun IGDBWrapper.jsonArtworks(APICalypse: APICalypse): String { 39 | return apiJsonRequest(Endpoints.ARTWORKS, APICalypse.buildQuery()) 40 | } 41 | 42 | @Throws(RequestException::class) 43 | fun IGDBWrapper.jsonCharacters(APICalypse: APICalypse): String { 44 | return apiJsonRequest(Endpoints.CHARACTERS, APICalypse.buildQuery()) 45 | } 46 | 47 | @Throws(RequestException::class) 48 | fun IGDBWrapper.jsonCharacterGenders(APICalypse: APICalypse): String { 49 | return apiJsonRequest(Endpoints.CHARACTER_GENDERS, APICalypse.buildQuery()) 50 | } 51 | 52 | @Throws(RequestException::class) 53 | fun IGDBWrapper.jsonCharacterSpecies(APICalypse: APICalypse): String { 54 | return apiJsonRequest(Endpoints.CHARACTER_SPECIES, APICalypse.buildQuery()) 55 | } 56 | 57 | @Throws(RequestException::class) 58 | fun IGDBWrapper.jsonCollections(APICalypse: APICalypse): String { 59 | return apiJsonRequest(Endpoints.COLLECTIONS, APICalypse.buildQuery()) 60 | } 61 | 62 | @Throws(RequestException::class) 63 | fun IGDBWrapper.jsonCharacterMugShots(APICalypse: APICalypse): String { 64 | return apiJsonRequest(Endpoints.CHARACTER_MUG_SHOTS, APICalypse.buildQuery()) 65 | } 66 | 67 | @Throws(RequestException::class) 68 | fun IGDBWrapper.jsonCompanies(APICalypse: APICalypse): String { 69 | return apiJsonRequest(Endpoints.COMPANIES, APICalypse.buildQuery()) 70 | } 71 | 72 | @Throws(RequestException::class) 73 | fun IGDBWrapper.jsonCompanyStatuses(APICalypse: APICalypse): String { 74 | return apiJsonRequest(Endpoints.COMPANY_STATUSES, APICalypse.buildQuery()) 75 | } 76 | 77 | @Throws(RequestException::class) 78 | fun IGDBWrapper.jsonCompanyWebsites(APICalypse: APICalypse): String { 79 | return apiJsonRequest(Endpoints.COMPANY_WEBSITES, APICalypse.buildQuery()) 80 | } 81 | 82 | @Throws(RequestException::class) 83 | fun IGDBWrapper.jsonCompanyLogos(APICalypse: APICalypse): String { 84 | return apiJsonRequest(Endpoints.COMPANY_LOGOS, APICalypse.buildQuery()) 85 | } 86 | 87 | @Throws(RequestException::class) 88 | fun IGDBWrapper.jsonCovers(APICalypse: APICalypse): String { 89 | return apiJsonRequest(Endpoints.COVERS, APICalypse.buildQuery()) 90 | } 91 | 92 | @Throws(RequestException::class) 93 | fun IGDBWrapper.jsonDateFormats(APICalypse: APICalypse): String { 94 | return apiJsonRequest(Endpoints.DATE_FORMATS, APICalypse.buildQuery()) 95 | } 96 | 97 | @Throws(RequestException::class) 98 | fun IGDBWrapper.jsonExternalGames(APICalypse: APICalypse): String { 99 | return apiJsonRequest(Endpoints.EXTERNAL_GAMES, APICalypse.buildQuery()) 100 | } 101 | 102 | @Throws(RequestException::class) 103 | fun IGDBWrapper.jsonExternalGameSources(APICalypse: APICalypse): String { 104 | return apiJsonRequest(Endpoints.EXTERNAL_GAME_SOURCES, APICalypse.buildQuery()) 105 | } 106 | 107 | @Throws(RequestException::class) 108 | fun IGDBWrapper.jsonFranchises(APICalypse: APICalypse): String { 109 | return apiJsonRequest(Endpoints.FRANCHISES, APICalypse.buildQuery()) 110 | } 111 | 112 | @Throws(RequestException::class) 113 | fun IGDBWrapper.jsonGames(APICalypse: APICalypse): String { 114 | return apiJsonRequest(Endpoints.GAMES, APICalypse.buildQuery()) 115 | } 116 | 117 | @Throws(RequestException::class) 118 | fun IGDBWrapper.jsonGameEngines(APICalypse: APICalypse): String { 119 | return apiJsonRequest(Endpoints.GAME_ENGINES, APICalypse.buildQuery()) 120 | } 121 | 122 | @Throws(RequestException::class) 123 | fun IGDBWrapper.jsonGameEngineLogos(APICalypse: APICalypse): String { 124 | return apiJsonRequest(Endpoints.GAME_ENGINE_LOGOS, APICalypse.buildQuery()) 125 | } 126 | 127 | @Throws(RequestException::class) 128 | fun IGDBWrapper.jsonGameLocalizations(APICalypse: APICalypse): String { 129 | return apiJsonRequest(Endpoints.GAME_LOCALIZATIONS, APICalypse.buildQuery()) 130 | } 131 | 132 | @Throws(RequestException::class) 133 | fun IGDBWrapper.jsonGameModes(APICalypse: APICalypse): String { 134 | return apiJsonRequest(Endpoints.GAME_MODES, APICalypse.buildQuery()) 135 | } 136 | 137 | @Throws(RequestException::class) 138 | fun IGDBWrapper.jsonGameReleaseFormats(APICalypse: APICalypse): String { 139 | return apiJsonRequest(Endpoints.GAME_RELEASE_FORMATS, APICalypse.buildQuery()) 140 | } 141 | 142 | @Throws(RequestException::class) 143 | fun IGDBWrapper.jsonGameStatuses(APICalypse: APICalypse): String { 144 | return apiJsonRequest(Endpoints.GAME_STATUSES, APICalypse.buildQuery()) 145 | } 146 | 147 | @Throws(RequestException::class) 148 | fun IGDBWrapper.jsonGameTimeToBeats(APICalypse: APICalypse): String { 149 | return apiJsonRequest(Endpoints.GAME_TIME_TO_BEATS, APICalypse.buildQuery()) 150 | } 151 | 152 | @Throws(RequestException::class) 153 | fun IGDBWrapper.jsonGameTypes(APICalypse: APICalypse): String { 154 | return apiJsonRequest(Endpoints.GAME_TYPES, APICalypse.buildQuery()) 155 | } 156 | 157 | @Throws(RequestException::class) 158 | fun IGDBWrapper.jsonGameVersion(APICalypse: APICalypse): String { 159 | return apiJsonRequest(Endpoints.GAME_VERSIONS, APICalypse.buildQuery()) 160 | } 161 | 162 | @Throws(RequestException::class) 163 | fun IGDBWrapper.jsonGameVersionFeatures(APICalypse: APICalypse): String { 164 | return apiJsonRequest(Endpoints.GAME_VERSION_FEATURES, APICalypse.buildQuery()) 165 | } 166 | 167 | @Throws(RequestException::class) 168 | fun IGDBWrapper.jsonGameVersionFeatureValues(APICalypse: APICalypse): String { 169 | return apiJsonRequest(Endpoints.GAME_VERSION_FEATURE_VALUES, APICalypse.buildQuery()) 170 | } 171 | 172 | @Throws(RequestException::class) 173 | fun IGDBWrapper.jsonGameVideos(APICalypse: APICalypse): String { 174 | return apiJsonRequest(Endpoints.GAME_VIDEOS, APICalypse.buildQuery()) 175 | } 176 | 177 | @Throws(RequestException::class) 178 | fun IGDBWrapper.jsonGenres(APICalypse: APICalypse): String { 179 | return apiJsonRequest(Endpoints.GENRES, APICalypse.buildQuery()) 180 | } 181 | 182 | @Throws(RequestException::class) 183 | fun IGDBWrapper.jsonInvolvedCompanies(APICalypse: APICalypse): String { 184 | return apiJsonRequest(Endpoints.INVOLVED_COMPANIES, APICalypse.buildQuery()) 185 | } 186 | 187 | @Throws(RequestException::class) 188 | fun IGDBWrapper.jsonKeywords(APICalypse: APICalypse): String { 189 | return apiJsonRequest(Endpoints.KEYWORDS, APICalypse.buildQuery()) 190 | } 191 | 192 | @Throws(RequestException::class) 193 | fun IGDBWrapper.jsonLanguages(APICalypse: APICalypse): String { 194 | return apiJsonRequest(Endpoints.LANGUAGES, APICalypse.buildQuery()) 195 | } 196 | 197 | @Throws(RequestException::class) 198 | fun IGDBWrapper.jsonLanguageSupports(APICalypse: APICalypse): String { 199 | return apiJsonRequest(Endpoints.LANGUAGE_SUPPORTS, APICalypse.buildQuery()) 200 | } 201 | 202 | @Throws(RequestException::class) 203 | fun IGDBWrapper.jsonLanguageSupportTypes(APICalypse: APICalypse): String { 204 | return apiJsonRequest(Endpoints.LANGUAGE_SUPPORT_TYPES, APICalypse.buildQuery()) 205 | } 206 | 207 | @Throws(RequestException::class) 208 | fun IGDBWrapper.jsonMultiplayerModes(APICalypse: APICalypse): String { 209 | return apiJsonRequest(Endpoints.MULTIPLAYER_MODES, APICalypse.buildQuery()) 210 | } 211 | 212 | @Throws(RequestException::class) 213 | fun IGDBWrapper.jsonPlatforms(APICalypse: APICalypse): String { 214 | return apiJsonRequest(Endpoints.PLATFORMS, APICalypse.buildQuery()) 215 | } 216 | 217 | @Throws(RequestException::class) 218 | fun IGDBWrapper.jsonPlatformLogos(APICalypse: APICalypse): String { 219 | return apiJsonRequest(Endpoints.PLATFORM_LOGOS, APICalypse.buildQuery()) 220 | } 221 | 222 | @Throws(RequestException::class) 223 | fun IGDBWrapper.jsonPlatformTypes(APICalypse: APICalypse): String { 224 | return apiJsonRequest(Endpoints.PLATFORM_TYPES, APICalypse.buildQuery()) 225 | } 226 | 227 | @Throws(RequestException::class) 228 | fun IGDBWrapper.jsonPlatformVersions(APICalypse: APICalypse): String { 229 | return apiJsonRequest(Endpoints.PLATFORM_VERSIONS, APICalypse.buildQuery()) 230 | } 231 | 232 | @Throws(RequestException::class) 233 | fun IGDBWrapper.jsonPlatformVersionCompanies(APICalypse: APICalypse): String { 234 | return apiJsonRequest(Endpoints.PLATFORM_VERSION_COMPANIES, APICalypse.buildQuery()) 235 | } 236 | 237 | @Throws(RequestException::class) 238 | fun IGDBWrapper.jsonRegions(APICalypse: APICalypse): String { 239 | return apiJsonRequest(Endpoints.REGIONS, APICalypse.buildQuery()) 240 | } 241 | 242 | @Throws(RequestException::class) 243 | fun IGDBWrapper.jsonPlatformVersionReleaseDates(APICalypse: APICalypse): String { 244 | return apiJsonRequest(Endpoints.PLATFORM_VERSION_RELEASE_DATES, APICalypse.buildQuery()) 245 | } 246 | 247 | @Throws(RequestException::class) 248 | fun IGDBWrapper.jsonPlatformWebsites(APICalypse: APICalypse): String { 249 | return apiJsonRequest(Endpoints.PLATFORM_WEBSITES, APICalypse.buildQuery()) 250 | } 251 | 252 | @Throws(RequestException::class) 253 | fun IGDBWrapper.jsonPlayerPerspectives(APICalypse: APICalypse): String { 254 | return apiJsonRequest(Endpoints.PLAYER_PERSPECTIVES, APICalypse.buildQuery()) 255 | } 256 | 257 | @Throws(RequestException::class) 258 | fun IGDBWrapper.jsonPlatformFamilies(APICalypse: APICalypse): String { 259 | return apiJsonRequest(Endpoints.PLATFORM_FAMILIES, APICalypse.buildQuery()) 260 | } 261 | 262 | @Throws(RequestException::class) 263 | fun IGDBWrapper.jsonReleaseDates(APICalypse: APICalypse): String { 264 | return apiJsonRequest(Endpoints.RELEASE_DATES, APICalypse.buildQuery()) 265 | } 266 | 267 | @Throws(RequestException::class) 268 | fun IGDBWrapper.jsonReleaseDateRegions(APICalypse: APICalypse): String { 269 | return apiJsonRequest(Endpoints.RELEASE_DATE_REGIONS, APICalypse.buildQuery()) 270 | } 271 | 272 | @Throws(RequestException::class) 273 | fun IGDBWrapper.jsonScreenshots(APICalypse: APICalypse): String { 274 | return apiJsonRequest(Endpoints.SCREENSHOTS, APICalypse.buildQuery()) 275 | } 276 | 277 | @Throws(RequestException::class) 278 | fun IGDBWrapper.jsonSearch(APICalypse: APICalypse): String { 279 | return apiJsonRequest(Endpoints.SEARCH, APICalypse.buildQuery()) 280 | } 281 | 282 | @Throws(RequestException::class) 283 | fun IGDBWrapper.jsonThemes(APICalypse: APICalypse): String { 284 | return apiJsonRequest(Endpoints.THEMES, APICalypse.buildQuery()) 285 | } 286 | 287 | @Throws(RequestException::class) 288 | fun IGDBWrapper.jsonWebsites(APICalypse: APICalypse): String { 289 | return apiJsonRequest(Endpoints.WEBSITES, APICalypse.buildQuery()) 290 | } 291 | 292 | @Throws(RequestException::class) 293 | fun IGDBWrapper.jsonWebsiteTypes(APICalypse: APICalypse): String { 294 | return apiJsonRequest(Endpoints.WEBSITE_TYPES, APICalypse.buildQuery()) 295 | } 296 | 297 | @Throws(RequestException::class) 298 | fun IGDBWrapper.jsonEvents(APICalypse: APICalypse): String { 299 | return apiJsonRequest(Endpoints.EVENTS, APICalypse.buildQuery()) 300 | } 301 | 302 | @Throws(RequestException::class) 303 | fun IGDBWrapper.jsonEventLogos(APICalypse: APICalypse): String { 304 | return apiJsonRequest(Endpoints.EVENT_LOGOS, APICalypse.buildQuery()) 305 | } 306 | 307 | @Throws(RequestException::class) 308 | fun IGDBWrapper.jsonEventNetworks(APICalypse: APICalypse): String { 309 | return apiJsonRequest(Endpoints.EVENT_NETWORKS, APICalypse.buildQuery()) 310 | } 311 | 312 | @Throws(RequestException::class) 313 | fun IGDBWrapper.jsonNetworkTypes(APICalypse: APICalypse): String { 314 | return apiJsonRequest(Endpoints.NETWORK_TYPES, APICalypse.buildQuery()) 315 | } 316 | 317 | @Throws(RequestException::class) 318 | fun IGDBWrapper.jsonCollectionRelations(APICalypse: APICalypse): String { 319 | return apiJsonRequest(Endpoints.COLLECTION_RELATIONS, APICalypse.buildQuery()) 320 | } 321 | 322 | @Throws(RequestException::class) 323 | fun IGDBWrapper.jsonCollectionRelationTypes(APICalypse: APICalypse): String { 324 | return apiJsonRequest(Endpoints.COLLECTION_RELATION_TYPES, APICalypse.buildQuery()) 325 | } 326 | 327 | @Throws(RequestException::class) 328 | fun IGDBWrapper.jsonCollectionTypes(APICalypse: APICalypse): String { 329 | return apiJsonRequest(Endpoints.COLLECTION_TYPES, APICalypse.buildQuery()) 330 | } 331 | 332 | @Throws(RequestException::class) 333 | fun IGDBWrapper.jsonCollectionMemberships(APICalypse: APICalypse): String { 334 | return apiJsonRequest(Endpoints.COLLECTION_MEMBERSHIPS, APICalypse.buildQuery()) 335 | } 336 | 337 | @Throws(RequestException::class) 338 | fun IGDBWrapper.jsonCollectionMembershipTypes(APICalypse: APICalypse): String { 339 | return apiJsonRequest(Endpoints.COLLECTION_MEMBERSHIP_TYPES, APICalypse.buildQuery()) 340 | } 341 | 342 | @Throws(RequestException::class) 343 | fun IGDBWrapper.jsonPopularityTypes(APICalypse: APICalypse): String { 344 | return apiJsonRequest(Endpoints.POPULARITY_TYPES, APICalypse.buildQuery()) 345 | } 346 | 347 | @Throws(RequestException::class) 348 | fun IGDBWrapper.jsonPopularityPrimitives(APICalypse: APICalypse): String { 349 | return apiJsonRequest(Endpoints.POPULARITY_PRIMITIVES, APICalypse.buildQuery()) 350 | } 351 | -------------------------------------------------------------------------------- /src/main/kotlin/com/api/igdb/request/ProtoRequest.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb.request 2 | 3 | import com.api.igdb.apicalypse.APICalypse 4 | import com.api.igdb.exceptions.RequestException 5 | import com.api.igdb.utils.Endpoints 6 | import proto.* 7 | import proto.Collection 8 | 9 | 10 | @Throws(RequestException::class) 11 | fun IGDBWrapper.ageRatings(APICalypse: APICalypse): List { 12 | val bytes = apiProtoRequest(Endpoints.AGE_RATINGS, APICalypse.buildQuery()) 13 | return AgeRatingResult.parseFrom(bytes).ageratingsList 14 | } 15 | 16 | @Throws(RequestException::class) 17 | fun IGDBWrapper.ageRatingCategories(APICalypse: APICalypse): List { 18 | val bytes = apiProtoRequest(Endpoints.AGE_RATING_CATEGORIES, APICalypse.buildQuery()) 19 | return AgeRatingCategoryResult.parseFrom(bytes).ageratingcategoriesList 20 | } 21 | 22 | @Throws(RequestException::class) 23 | @Deprecated("Use ageRatingContentDescriptionsV2 instead") 24 | fun IGDBWrapper.ageRatingContentDescriptions(APICalypse: APICalypse): List { 25 | val bytes = apiProtoRequest(Endpoints.AGE_RATING_CONTENT_DESCRIPTIONS, APICalypse.buildQuery()) 26 | return AgeRatingContentDescriptionResult.parseFrom(bytes).ageratingcontentdescriptionsList 27 | } 28 | 29 | @Throws(RequestException::class) 30 | fun IGDBWrapper.ageRatingContentDescriptionsV2(APICalypse: APICalypse): List { 31 | val bytes = apiProtoRequest(Endpoints.AGE_RATING_CONTENT_DESCRIPTIONS_V2, APICalypse.buildQuery()) 32 | return AgeRatingContentDescriptionV2Result.parseFrom(bytes).ageratingcontentdescriptionsv2List 33 | } 34 | 35 | @Throws(RequestException::class) 36 | fun IGDBWrapper.ageRatingOrganizations(APICalypse: APICalypse): List { 37 | val bytes = apiProtoRequest(Endpoints.AGE_RATING_ORGANIZATIONS, APICalypse.buildQuery()) 38 | return AgeRatingOrganizationResult.parseFrom(bytes).ageratingorganizationsList 39 | } 40 | 41 | @Throws(RequestException::class) 42 | fun IGDBWrapper.alternativeNames(APICalypse: APICalypse): List { 43 | val bytes = apiProtoRequest(Endpoints.ALTERNATIVE_NAMES, APICalypse.buildQuery()) 44 | return AlternativeNameResult.parseFrom(bytes).alternativenamesList 45 | } 46 | 47 | @Throws(RequestException::class) 48 | fun IGDBWrapper.artworks(APICalypse: APICalypse): List { 49 | val bytes = apiProtoRequest(Endpoints.ARTWORKS, APICalypse.buildQuery()) 50 | return ArtworkResult.parseFrom(bytes).artworksList 51 | } 52 | 53 | @Throws(RequestException::class) 54 | fun IGDBWrapper.characters(APICalypse: APICalypse): List { 55 | val bytes = apiProtoRequest(Endpoints.CHARACTERS, APICalypse.buildQuery()) 56 | return CharacterResult.parseFrom(bytes).charactersList 57 | } 58 | 59 | @Throws(RequestException::class) 60 | fun IGDBWrapper.characterGenders(APICalypse: APICalypse): List { 61 | val bytes = apiProtoRequest(Endpoints.CHARACTER_GENDERS, APICalypse.buildQuery()) 62 | return CharacterGenderResult.parseFrom(bytes).charactergendersList 63 | } 64 | 65 | @Throws(RequestException::class) 66 | fun IGDBWrapper.characterSpecies(APICalypse: APICalypse): List { 67 | val bytes = apiProtoRequest(Endpoints.CHARACTER_SPECIES, APICalypse.buildQuery()) 68 | return CharacterSpecieResult.parseFrom(bytes).characterspeciesList 69 | } 70 | 71 | @Throws(RequestException::class) 72 | fun IGDBWrapper.collections(APICalypse: APICalypse): List { 73 | val bytes = apiProtoRequest(Endpoints.COLLECTIONS, APICalypse.buildQuery()) 74 | return CollectionResult.parseFrom(bytes).collectionsList 75 | } 76 | 77 | @Throws(RequestException::class) 78 | fun IGDBWrapper.characterMugShots(APICalypse: APICalypse): List { 79 | val bytes = apiProtoRequest(Endpoints.CHARACTER_MUG_SHOTS, APICalypse.buildQuery()) 80 | return CharacterMugShotResult.parseFrom(bytes).charactermugshotsList 81 | } 82 | 83 | @Throws(RequestException::class) 84 | fun IGDBWrapper.companies(APICalypse: APICalypse): List { 85 | val bytes = apiProtoRequest(Endpoints.COMPANIES, APICalypse.buildQuery()) 86 | return CompanyResult.parseFrom(bytes).companiesList 87 | } 88 | 89 | @Throws(RequestException::class) 90 | fun IGDBWrapper.companyStatuses(APICalypse: APICalypse): List { 91 | val bytes = apiProtoRequest(Endpoints.COMPANY_STATUSES, APICalypse.buildQuery()) 92 | return CompanyStatusResult.parseFrom(bytes).companystatusesList 93 | } 94 | 95 | @Throws(RequestException::class) 96 | fun IGDBWrapper.companyWebsites(APICalypse: APICalypse): List { 97 | val bytes = apiProtoRequest(Endpoints.COMPANY_WEBSITES, APICalypse.buildQuery()) 98 | return CompanyWebsiteResult.parseFrom(bytes).companywebsitesList 99 | } 100 | 101 | @Throws(RequestException::class) 102 | fun IGDBWrapper.companyLogos(APICalypse: APICalypse): List { 103 | val bytes = apiProtoRequest(Endpoints.COMPANY_LOGOS, APICalypse.buildQuery()) 104 | return CompanyLogoResult.parseFrom(bytes).companylogosList 105 | } 106 | 107 | @Throws(RequestException::class) 108 | fun IGDBWrapper.covers(APICalypse: APICalypse): List { 109 | val bytes = apiProtoRequest(Endpoints.COVERS, APICalypse.buildQuery()) 110 | return CoverResult.parseFrom(bytes).coversList 111 | } 112 | 113 | @Throws(RequestException::class) 114 | fun IGDBWrapper.dateFormats(APICalypse: APICalypse): List { 115 | val bytes = apiProtoRequest(Endpoints.COVERS, APICalypse.buildQuery()) 116 | return DateFormatResult.parseFrom(bytes).dateformatsList 117 | } 118 | 119 | @Throws(RequestException::class) 120 | fun IGDBWrapper.externalGames(APICalypse: APICalypse): List { 121 | val bytes = apiProtoRequest(Endpoints.EXTERNAL_GAMES, APICalypse.buildQuery()) 122 | return ExternalGameResult.parseFrom(bytes).externalgamesList 123 | } 124 | 125 | @Throws(RequestException::class) 126 | fun IGDBWrapper.externalGameSources(APICalypse: APICalypse): List { 127 | val bytes = apiProtoRequest(Endpoints.EXTERNAL_GAME_SOURCES, APICalypse.buildQuery()) 128 | return ExternalGameSourceResult.parseFrom(bytes).externalgamesourcesList 129 | } 130 | 131 | @Throws(RequestException::class) 132 | fun IGDBWrapper.franchises(APICalypse: APICalypse): List { 133 | val bytes = apiProtoRequest(Endpoints.FRANCHISES, APICalypse.buildQuery()) 134 | return FranchiseResult.parseFrom(bytes).franchisesList 135 | } 136 | 137 | @Throws(RequestException::class) 138 | fun IGDBWrapper.games(APICalypse: APICalypse): List { 139 | val bytes = apiProtoRequest(Endpoints.GAMES, APICalypse.buildQuery()) 140 | return GameResult.parseFrom(bytes).gamesList 141 | } 142 | 143 | @Throws(RequestException::class) 144 | fun IGDBWrapper.gameEngines(APICalypse: APICalypse): List { 145 | val bytes = apiProtoRequest(Endpoints.GAME_ENGINES, APICalypse.buildQuery()) 146 | return GameEngineResult.parseFrom(bytes).gameenginesList 147 | } 148 | 149 | @Throws(RequestException::class) 150 | fun IGDBWrapper.gameEngineLogos(APICalypse: APICalypse): List { 151 | val bytes = apiProtoRequest(Endpoints.GAME_ENGINE_LOGOS, APICalypse.buildQuery()) 152 | return GameEngineLogoResult.parseFrom(bytes).gameenginelogosList 153 | } 154 | 155 | @Throws(RequestException::class) 156 | fun IGDBWrapper.gameLocalizations(APICalypse: APICalypse): List { 157 | val bytes = apiProtoRequest(Endpoints.GAME_LOCALIZATIONS, APICalypse.buildQuery()) 158 | return GameLocalizationResult.parseFrom(bytes).gamelocalizationsList 159 | } 160 | 161 | @Throws(RequestException::class) 162 | fun IGDBWrapper.gameModes(APICalypse: APICalypse): List { 163 | val bytes = apiProtoRequest(Endpoints.GAME_MODES, APICalypse.buildQuery()) 164 | return GameModeResult.parseFrom(bytes).gamemodesList 165 | } 166 | 167 | @Throws(RequestException::class) 168 | fun IGDBWrapper.gameReleaseFormats(APICalypse: APICalypse): List { 169 | val bytes = apiProtoRequest(Endpoints.GAME_RELEASE_FORMATS, APICalypse.buildQuery()) 170 | return GameReleaseFormatResult.parseFrom(bytes).gamereleaseformatsList 171 | } 172 | 173 | @Throws(RequestException::class) 174 | fun IGDBWrapper.gameStatuses(APICalypse: APICalypse): List { 175 | val bytes = apiProtoRequest(Endpoints.GAME_STATUSES, APICalypse.buildQuery()) 176 | return GameStatusResult.parseFrom(bytes).gamestatusesList 177 | } 178 | 179 | @Throws(RequestException::class) 180 | fun IGDBWrapper.gameTimeToBeats(APICalypse: APICalypse): List { 181 | val bytes = apiProtoRequest(Endpoints.GAME_TIME_TO_BEATS, APICalypse.buildQuery()) 182 | return GameTimeToBeatResult.parseFrom(bytes).gametimetobeatsList 183 | } 184 | 185 | @Throws(RequestException::class) 186 | fun IGDBWrapper.gameTypes(APICalypse: APICalypse): List { 187 | val bytes = apiProtoRequest(Endpoints.GAME_TYPES, APICalypse.buildQuery()) 188 | return GameTypeResult.parseFrom(bytes).gametypesList 189 | } 190 | 191 | @Throws(RequestException::class) 192 | fun IGDBWrapper.gameVersion(APICalypse: APICalypse): List { 193 | val bytes = apiProtoRequest(Endpoints.GAME_VERSIONS, APICalypse.buildQuery()) 194 | return GameVersionResult.parseFrom(bytes).gameversionsList 195 | } 196 | 197 | @Throws(RequestException::class) 198 | fun IGDBWrapper.gameVersionFeatures(APICalypse: APICalypse): List { 199 | val bytes = apiProtoRequest(Endpoints.GAME_VERSION_FEATURES, APICalypse.buildQuery()) 200 | return GameVersionFeatureResult.parseFrom(bytes).gameversionfeaturesList 201 | } 202 | 203 | @Throws(RequestException::class) 204 | fun IGDBWrapper.gameVersionFeatureValues(APICalypse: APICalypse): List { 205 | val bytes = apiProtoRequest(Endpoints.GAME_VERSION_FEATURE_VALUES, APICalypse.buildQuery()) 206 | return GameVersionFeatureValueResult.parseFrom(bytes).gameversionfeaturevaluesList 207 | } 208 | 209 | @Throws(RequestException::class) 210 | fun IGDBWrapper.gameVideos(APICalypse: APICalypse): List { 211 | val bytes = apiProtoRequest(Endpoints.GAME_VIDEOS, APICalypse.buildQuery()) 212 | return GameVideoResult.parseFrom(bytes).gamevideosList 213 | } 214 | 215 | @Throws(RequestException::class) 216 | fun IGDBWrapper.genres(APICalypse: APICalypse): List { 217 | val bytes = apiProtoRequest(Endpoints.GENRES, APICalypse.buildQuery()) 218 | return GenreResult.parseFrom(bytes).genresList 219 | } 220 | 221 | @Throws(RequestException::class) 222 | fun IGDBWrapper.involvedCompanies(APICalypse: APICalypse): List { 223 | val bytes = apiProtoRequest(Endpoints.INVOLVED_COMPANIES, APICalypse.buildQuery()) 224 | return InvolvedCompanyResult.parseFrom(bytes).involvedcompaniesList 225 | } 226 | 227 | @Throws(RequestException::class) 228 | fun IGDBWrapper.keywords(APICalypse: APICalypse): List { 229 | val bytes = apiProtoRequest(Endpoints.KEYWORDS, APICalypse.buildQuery()) 230 | return KeywordResult.parseFrom(bytes).keywordsList 231 | } 232 | 233 | @Throws(RequestException::class) 234 | fun IGDBWrapper.languages(APICalypse: APICalypse): List { 235 | val bytes = apiProtoRequest(Endpoints.LANGUAGES, APICalypse.buildQuery()) 236 | return LanguageResult.parseFrom(bytes).languagesList 237 | } 238 | 239 | @Throws(RequestException::class) 240 | fun IGDBWrapper.languageSupports(APICalypse: APICalypse): List { 241 | val bytes = apiProtoRequest(Endpoints.LANGUAGE_SUPPORTS, APICalypse.buildQuery()) 242 | return LanguageSupportResult.parseFrom(bytes).languagesupportsList 243 | } 244 | 245 | @Throws(RequestException::class) 246 | fun IGDBWrapper.languageSupportTypes(APICalypse: APICalypse): List { 247 | val bytes = apiProtoRequest(Endpoints.LANGUAGE_SUPPORT_TYPES, APICalypse.buildQuery()) 248 | return LanguageSupportTypeResult.parseFrom(bytes).languagesupporttypesList 249 | } 250 | 251 | @Throws(RequestException::class) 252 | fun IGDBWrapper.multiplayerModes(APICalypse: APICalypse): List { 253 | val bytes = apiProtoRequest(Endpoints.MULTIPLAYER_MODES, APICalypse.buildQuery()) 254 | return MultiplayerModeResult.parseFrom(bytes).multiplayermodesList 255 | } 256 | 257 | @Throws(RequestException::class) 258 | fun IGDBWrapper.platforms(APICalypse: APICalypse): List { 259 | val bytes = apiProtoRequest(Endpoints.PLATFORMS, APICalypse.buildQuery()) 260 | return PlatformResult.parseFrom(bytes).platformsList 261 | } 262 | 263 | @Throws(RequestException::class) 264 | fun IGDBWrapper.platformLogos(APICalypse: APICalypse): List { 265 | val bytes = apiProtoRequest(Endpoints.PLATFORM_LOGOS, APICalypse.buildQuery()) 266 | return PlatformLogoResult.parseFrom(bytes).platformlogosList 267 | } 268 | 269 | @Throws(RequestException::class) 270 | fun IGDBWrapper.platformTypes(APICalypse: APICalypse): List { 271 | val bytes = apiProtoRequest(Endpoints.PLATFORM_TYPES, APICalypse.buildQuery()) 272 | return PlatformTypeResult.parseFrom(bytes).platformtypesList 273 | } 274 | 275 | @Throws(RequestException::class) 276 | fun IGDBWrapper.platformVersions(APICalypse: APICalypse): List { 277 | val bytes = apiProtoRequest(Endpoints.PLATFORM_VERSIONS, APICalypse.buildQuery()) 278 | return PlatformVersionResult.parseFrom(bytes).platformversionsList 279 | } 280 | 281 | @Throws(RequestException::class) 282 | fun IGDBWrapper.platformVersionCompanies(APICalypse: APICalypse): List { 283 | val bytes = apiProtoRequest(Endpoints.PLATFORM_VERSION_COMPANIES, APICalypse.buildQuery()) 284 | return PlatformVersionCompanyResult.parseFrom(bytes).platformversioncompaniesList 285 | } 286 | 287 | @Throws(RequestException::class) 288 | fun IGDBWrapper.platformVersionReleaseDates(APICalypse: APICalypse): List { 289 | val bytes = apiProtoRequest(Endpoints.PLATFORM_VERSION_RELEASE_DATES, APICalypse.buildQuery()) 290 | return PlatformVersionReleaseDateResult.parseFrom(bytes).platformversionreleasedatesList 291 | } 292 | 293 | @Throws(RequestException::class) 294 | fun IGDBWrapper.platformWebsites(APICalypse: APICalypse): List { 295 | val bytes = apiProtoRequest(Endpoints.PLATFORM_WEBSITES, APICalypse.buildQuery()) 296 | return PlatformWebsiteResult.parseFrom(bytes).platformwebsitesList 297 | } 298 | 299 | @Throws(RequestException::class) 300 | fun IGDBWrapper.playerPerspectives(APICalypse: APICalypse): List { 301 | val bytes = apiProtoRequest(Endpoints.PLAYER_PERSPECTIVES, APICalypse.buildQuery()) 302 | return PlayerPerspectiveResult.parseFrom(bytes).playerperspectivesList 303 | } 304 | 305 | @Throws(RequestException::class) 306 | fun IGDBWrapper.platformFamilies(APICalypse: APICalypse): List { 307 | val bytes = apiProtoRequest(Endpoints.PLATFORM_FAMILIES, APICalypse.buildQuery()) 308 | return PlatformFamilyResult.parseFrom(bytes).platformfamiliesList 309 | } 310 | 311 | @Throws(RequestException::class) 312 | fun IGDBWrapper.regions(APICalypse: APICalypse): List { 313 | val bytes = apiProtoRequest(Endpoints.REGIONS, APICalypse.buildQuery()) 314 | return RegionResult.parseFrom(bytes).regionsList 315 | } 316 | 317 | @Throws(RequestException::class) 318 | fun IGDBWrapper.releaseDates(APICalypse: APICalypse): List { 319 | val bytes = apiProtoRequest(Endpoints.RELEASE_DATES, APICalypse.buildQuery()) 320 | return ReleaseDateResult.parseFrom(bytes).releasedatesList 321 | } 322 | 323 | @Throws(RequestException::class) 324 | fun IGDBWrapper.releaseDateRegions(APICalypse: APICalypse): List { 325 | val bytes = apiProtoRequest(Endpoints.RELEASE_DATE_REGIONS, APICalypse.buildQuery()) 326 | return ReleaseDateRegionResult.parseFrom(bytes).releasedateregionsList 327 | } 328 | 329 | @Throws(RequestException::class) 330 | fun IGDBWrapper.screenshots(APICalypse: APICalypse): List { 331 | val bytes = apiProtoRequest(Endpoints.SCREENSHOTS, APICalypse.buildQuery()) 332 | return ScreenshotResult.parseFrom(bytes).screenshotsList 333 | } 334 | 335 | @Throws(RequestException::class) 336 | fun IGDBWrapper.search(APICalypse: APICalypse): List { 337 | val bytes = apiProtoRequest(Endpoints.SEARCH, APICalypse.buildQuery()) 338 | return SearchResult.parseFrom(bytes).searchesList 339 | } 340 | 341 | @Throws(RequestException::class) 342 | fun IGDBWrapper.themes(APICalypse: APICalypse): List { 343 | val bytes = apiProtoRequest(Endpoints.THEMES, APICalypse.buildQuery()) 344 | return ThemeResult.parseFrom(bytes).themesList 345 | } 346 | 347 | @Throws(RequestException::class) 348 | fun IGDBWrapper.websites(APICalypse: APICalypse): List { 349 | val bytes = apiProtoRequest(Endpoints.WEBSITES, APICalypse.buildQuery()) 350 | return WebsiteResult.parseFrom(bytes).websitesList 351 | } 352 | 353 | @Throws(RequestException::class) 354 | fun IGDBWrapper.websiteTypes(APICalypse: APICalypse): List { 355 | val bytes = apiProtoRequest(Endpoints.WEBSITE_TYPES, APICalypse.buildQuery()) 356 | return WebsiteTypeResult.parseFrom(bytes).websitetypesList 357 | } 358 | 359 | @Throws(RequestException::class) 360 | fun IGDBWrapper.events(APICalypse: APICalypse): List { 361 | val bytes = apiProtoRequest(Endpoints.EVENTS, APICalypse.buildQuery()) 362 | return EventResult.parseFrom(bytes).eventsList 363 | } 364 | 365 | @Throws(RequestException::class) 366 | fun IGDBWrapper.eventLogos(APICalypse: APICalypse): List { 367 | val bytes = apiProtoRequest(Endpoints.EVENT_LOGOS, APICalypse.buildQuery()) 368 | return EventLogoResult.parseFrom(bytes).eventlogosList 369 | } 370 | 371 | @Throws(RequestException::class) 372 | fun IGDBWrapper.eventNetworks(APICalypse: APICalypse): List { 373 | val bytes = apiProtoRequest(Endpoints.EVENT_NETWORKS, APICalypse.buildQuery()) 374 | return EventNetworkResult.parseFrom(bytes).eventnetworksList 375 | } 376 | 377 | @Throws(RequestException::class) 378 | fun IGDBWrapper.networkTypes(APICalypse: APICalypse): List { 379 | val bytes = apiProtoRequest(Endpoints.NETWORK_TYPES, APICalypse.buildQuery()) 380 | return NetworkTypeResult.parseFrom(bytes).networktypesList 381 | } 382 | 383 | @Throws(RequestException::class) 384 | fun IGDBWrapper.collectionRelations(APICalypse: APICalypse): List { 385 | val bytes = apiProtoRequest(Endpoints.COLLECTION_RELATIONS, APICalypse.buildQuery()) 386 | return CollectionRelationResult.parseFrom(bytes).collectionrelationsList 387 | } 388 | 389 | @Throws(RequestException::class) 390 | fun IGDBWrapper.collectionRelationTypes(APICalypse: APICalypse): List { 391 | val bytes = apiProtoRequest(Endpoints.COLLECTION_RELATION_TYPES, APICalypse.buildQuery()) 392 | return CollectionRelationTypeResult.parseFrom(bytes).collectionrelationtypesList 393 | } 394 | 395 | @Throws(RequestException::class) 396 | fun IGDBWrapper.collectionTypes(APICalypse: APICalypse): List { 397 | val bytes = apiProtoRequest(Endpoints.COLLECTION_TYPES, APICalypse.buildQuery()) 398 | return CollectionTypeResult.parseFrom(bytes).collectiontypesList 399 | } 400 | 401 | @Throws(RequestException::class) 402 | fun IGDBWrapper.collectionMemberships(APICalypse: APICalypse): List { 403 | val bytes = apiProtoRequest(Endpoints.COLLECTION_MEMBERSHIPS, APICalypse.buildQuery()) 404 | return CollectionMembershipResult.parseFrom(bytes).collectionmembershipsList 405 | } 406 | 407 | @Throws(RequestException::class) 408 | fun IGDBWrapper.collectionMembershipTypes(APICalypse: APICalypse): List { 409 | val bytes = apiProtoRequest(Endpoints.COLLECTION_MEMBERSHIP_TYPES, APICalypse.buildQuery()) 410 | return CollectionMembershipTypeResult.parseFrom(bytes).collectionmembershiptypesList 411 | } 412 | 413 | @Throws(RequestException::class) 414 | fun IGDBWrapper.popularityTypes(APICalypse: APICalypse): List { 415 | val bytes = apiProtoRequest(Endpoints.POPULARITY_TYPES, APICalypse.buildQuery()) 416 | return PopularityTypeResult.parseFrom(bytes).popularitytypesList 417 | } 418 | 419 | @Throws(RequestException::class) 420 | fun IGDBWrapper.popularityPrimitives(APICalypse: APICalypse): List { 421 | val bytes = apiProtoRequest(Endpoints.POPULARITY_PRIMITIVES, APICalypse.buildQuery()) 422 | return PopularityPrimitiveResult.parseFrom(bytes).popularityprimitivesList 423 | } -------------------------------------------------------------------------------- /src/main/kotlin/com/api/igdb/request/TwitchAuthenticator.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb.request 2 | 3 | import com.api.igdb.utils.TwitchToken 4 | import com.github.kittinunf.fuel.gson.responseObject 5 | import com.github.kittinunf.fuel.httpPost 6 | import com.github.kittinunf.result.Result 7 | import java.io.Serializable 8 | import kotlin.properties.Delegates 9 | 10 | object TwitchAuthenticator { 11 | private const val twitchOauthTokenURL = "https://id.twitch.tv/oauth2/token" 12 | private const val twitchGrantType = "client_credentials" 13 | 14 | private var twitchClientID: String = "" 15 | private var twitchClientSecret: String = "" 16 | private var twitchToken: TwitchToken? = null 17 | 18 | /** 19 | * The Twitch OAuth request function 20 | * 21 | * @property clientID Your application client_id found in the Twitch Developer Portal 22 | * @property clientSecret Your application client_secret found in the Twitch Developer Portal 23 | * @return The Twitch token response object, if successful otherwise null 24 | */ 25 | fun requestTwitchToken(clientID: String, clientSecret: String): TwitchToken? { 26 | val parameters = listOf("client_id" to clientID, "client_secret" to clientSecret, 27 | "grant_type" to twitchGrantType) 28 | val (_, _, result) = twitchOauthTokenURL.httpPost(parameters) 29 | .responseObject() 30 | 31 | twitchToken = when (result) { 32 | is Result.Failure -> { 33 | null 34 | } 35 | is Result.Success -> { 36 | result.get() 37 | } 38 | } 39 | return twitchToken 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /src/main/kotlin/com/api/igdb/utils/Endpoint.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb.utils 2 | 3 | interface Endpoint { 4 | fun url(): String 5 | } 6 | -------------------------------------------------------------------------------- /src/main/kotlin/com/api/igdb/utils/Endpoints.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb.utils 2 | 3 | /** 4 | * The Public Endpoint Enum class holds all of the accessible IGDB API Endpoints 5 | */ 6 | enum class Endpoints : Endpoint { 7 | AGE_RATING_CATEGORIES, AGE_RATING_CONTENT_DESCRIPTIONS, AGE_RATING_CONTENT_DESCRIPTIONS_V2, AGE_RATING_ORGANIZATIONS, AGE_RATINGS, 8 | ALTERNATIVE_NAMES, ARTWORKS, CHARACTERS, CHARACTER_GENDERS, CHARACTER_MUG_SHOTS, CHARACTER_SPECIES, COLLECTION_MEMBERSHIPS, 9 | COLLECTION_MEMBERSHIP_TYPES, COLLECTION_RELATIONS, COLLECTION_RELATION_TYPES, COLLECTION_TYPES, COLLECTIONS, COMPANIES, 10 | COMPANY_LOGOS, COMPANY_STATUSES, COMPANY_WEBSITES, COVERS, DATE_FORMATS, EVENTS, EVENT_LOGOS, 11 | EVENT_NETWORKS, EXTERNAL_GAMES, EXTERNAL_GAME_SOURCES, FRANCHISES, GAMES, GAME_ENGINES, GAME_ENGINE_LOGOS, GAME_LOCALIZATIONS, 12 | GAME_MODES, GAME_RELEASE_FORMATS, GAME_STATUSES, GAME_TIME_TO_BEATS, GAME_TYPES, GAME_VERSIONS, GAME_VERSION_FEATURES, GAME_VERSION_FEATURE_VALUES, 13 | GAME_VIDEOS, GENRES, INVOLVED_COMPANIES, KEYWORDS, LANGUAGES, LANGUAGE_SUPPORTS, LANGUAGE_SUPPORT_TYPES, MULTIPLAYER_MODES, 14 | NETWORK_TYPES, PLATFORMS, PLATFORM_FAMILIES, PLATFORM_LOGOS, PLATFORM_TYPES, PLATFORM_VERSIONS, PLATFORM_VERSION_COMPANIES, 15 | PLATFORM_VERSION_RELEASE_DATES, PLATFORM_WEBSITES, PLAYER_PERSPECTIVES, POPULARITY_PRIMITIVES, POPULARITY_TYPES, REGIONS, 16 | RELEASE_DATES, RELEASE_DATE_REGIONS, SCREENSHOTS, SEARCH, THEMES, WEBSITES, WEBSITE_TYPES; 17 | 18 | override fun url(): String { 19 | return "/${this.name.lowercase()}" 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/kotlin/com/api/igdb/utils/ImageBuilder.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb.utils 2 | 3 | private const val IGDB_IMAGE_URL = "https://images.igdb.com/igdb/image/upload/" 4 | 5 | /** 6 | * The image builder function builds image urls 7 | * 8 | * @property imageID The image ID from the IGDB API 9 | * @property size The size of the image 10 | * @property imageType The file type of the image, default PNG 11 | * @return The complete image url in string 12 | */ 13 | fun imageBuilder(imageID: String, size: ImageSize, imageType: ImageType = ImageType.PNG): String { 14 | return "$IGDB_IMAGE_URL${size.tSize}/$imageID.${imageType.type}" 15 | } 16 | -------------------------------------------------------------------------------- /src/main/kotlin/com/api/igdb/utils/ImageSize.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb.utils 2 | 3 | /* 4 | * The image size options from the IGDB API 5 | * */ 6 | enum class ImageSize(val tSize: String) { 7 | MICRO("t_micro"), // 35 x 35 Thumb, Center gravity 8 | THUMB("t_thumb"), // 90 x 90 Thumb, Center gravity 9 | COVER_SMALL("t_cover_small"), // 90 x 128 Fit 10 | COVER_BIG("t_cover_big"), // 264 x 374 Fit 11 | LOGO_MEDIUM("t_logo_med"), // 284 x 160 Fit 12 | SCREENSHOT_MEDIUM("t_screenshot_med"), // 569 x 320 Lfill, Center gravity 13 | SCREENSHOT_BIG("t_screenshot_big"), // 889 x 500 Lfill, Center gravity 14 | SCREENSHOT_HUGE("t_screenshot_huge"), // 1280 x 720 Lfill, Center gravity 15 | HD("t_720p"), // 1280 x 720 Fit, Center gravity 16 | FHD("t_1080p") // 1920 x 1080 Fit, Center gravity 17 | } 18 | -------------------------------------------------------------------------------- /src/main/kotlin/com/api/igdb/utils/ImageType.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb.utils 2 | 3 | /* 4 | * The Image types offered by the IGDB API 5 | * */ 6 | enum class ImageType(val type: String) { 7 | JPEG("jpg"), 8 | PNG("png"), 9 | GIF("gif"), 10 | WEBP("webp") 11 | } 12 | -------------------------------------------------------------------------------- /src/main/kotlin/com/api/igdb/utils/TwitchToken.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb.utils 2 | 3 | import java.io.Serializable 4 | import kotlin.properties.Delegates 5 | 6 | /** 7 | * The Twitch OAuth object used to serialize the oauth response 8 | * 9 | * @property access_token Your Twitch Access Token 10 | * @property expires_in The token expiry time 11 | * @property token_type The token type 12 | */ 13 | data class TwitchToken( 14 | val access_token: String, 15 | val expires_in: Long, 16 | val token_type: String 17 | ): Serializable { 18 | private var expiresAt: Long 19 | 20 | init { 21 | val currentTime = System.currentTimeMillis() 22 | val expiresAtMillis = expires_in * 1000 23 | expiresAt = currentTime + expiresAtMillis 24 | } 25 | 26 | fun getExpiresUnix() = expiresAt 27 | } -------------------------------------------------------------------------------- /src/resources/com/api/igdb/igdbproto.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | 4 | package proto; 5 | 6 | import "google/protobuf/timestamp.proto"; 7 | 8 | option java_multiple_files = true; // Must be true because of private access in files. 9 | option optimize_for = CODE_SIZE; 10 | 11 | message Count { 12 | int64 count = 1; 13 | } 14 | 15 | message MultiQueryResult { 16 | string name = 1; 17 | repeated bytes results = 2; 18 | int64 count = 3; 19 | } 20 | 21 | message MultiQueryResultArray { 22 | repeated MultiQueryResult result = 1; 23 | } 24 | 25 | message AgeRatingResult { 26 | repeated AgeRating ageratings = 1; 27 | } 28 | 29 | message AgeRating { 30 | uint64 id = 1; 31 | AgeRatingCategoryEnum category = 2 [deprecated = true]; 32 | repeated AgeRatingContentDescription content_descriptions = 3; 33 | AgeRatingRatingEnum rating = 4 [deprecated = true]; 34 | string rating_cover_url = 5; 35 | string synopsis = 6; 36 | string checksum = 7; 37 | AgeRatingOrganization organization = 8; 38 | AgeRatingCategory rating_category = 9; 39 | repeated AgeRatingContentDescriptionV2 rating_content_descriptions = 10; 40 | } 41 | 42 | 43 | enum AgeRatingCategoryEnum { 44 | AGERATING_CATEGORY_NULL = 0 [deprecated = true]; 45 | ESRB = 1 [deprecated = true]; 46 | PEGI = 2 [deprecated = true]; 47 | CERO = 3 [deprecated = true]; 48 | USK = 4 [deprecated = true]; 49 | GRAC = 5 [deprecated = true]; 50 | CLASS_IND = 6 [deprecated = true]; 51 | ACB = 7 [deprecated = true]; 52 | } 53 | 54 | 55 | enum AgeRatingRatingEnum { 56 | AGERATING_RATING_NULL = 0 [deprecated = true]; 57 | THREE = 1 [deprecated = true]; 58 | SEVEN = 2 [deprecated = true]; 59 | TWELVE = 3 [deprecated = true]; 60 | SIXTEEN = 4 [deprecated = true]; 61 | EIGHTEEN = 5 [deprecated = true]; 62 | RP = 6 [deprecated = true]; 63 | EC = 7 [deprecated = true]; 64 | E = 8 [deprecated = true]; 65 | E10 = 9 [deprecated = true]; 66 | T = 10 [deprecated = true]; 67 | M = 11 [deprecated = true]; 68 | AO = 12 [deprecated = true]; 69 | CERO_A = 13 [deprecated = true]; 70 | CERO_B = 14 [deprecated = true]; 71 | CERO_C = 15 [deprecated = true]; 72 | CERO_D = 16 [deprecated = true]; 73 | CERO_Z = 17 [deprecated = true]; 74 | USK_0 = 18 [deprecated = true]; 75 | USK_6 = 19 [deprecated = true]; 76 | USK_12 = 20 [deprecated = true]; 77 | USK_16 = 21 [deprecated = true]; 78 | USK_18 = 22 [deprecated = true]; 79 | GRAC_ALL = 23 [deprecated = true]; 80 | GRAC_TWELVE = 24 [deprecated = true]; 81 | GRAC_FIFTEEN = 25 [deprecated = true]; 82 | GRAC_EIGHTEEN = 26 [deprecated = true]; 83 | GRAC_TESTING = 27 [deprecated = true]; 84 | CLASS_IND_L = 28 [deprecated = true]; 85 | CLASS_IND_TEN = 29 [deprecated = true]; 86 | CLASS_IND_TWELVE = 30 [deprecated = true]; 87 | CLASS_IND_FOURTEEN = 31 [deprecated = true]; 88 | CLASS_IND_SIXTEEN = 32 [deprecated = true]; 89 | CLASS_IND_EIGHTEEN = 33 [deprecated = true]; 90 | ACB_G = 34 [deprecated = true]; 91 | ACB_PG = 35 [deprecated = true]; 92 | ACB_M = 36 [deprecated = true]; 93 | ACB_MA15 = 37 [deprecated = true]; 94 | ACB_R18 = 38 [deprecated = true]; 95 | ACB_RC = 39 [deprecated = true]; 96 | } 97 | 98 | message AgeRatingCategoryResult { 99 | repeated AgeRatingCategory ageratingcategories = 1; 100 | } 101 | 102 | message AgeRatingCategory { 103 | uint64 id = 1; 104 | string rating = 2; 105 | AgeRatingOrganization organization = 3; 106 | google.protobuf.Timestamp created_at = 4; 107 | google.protobuf.Timestamp updated_at = 5; 108 | string checksum = 6; 109 | } 110 | 111 | message AgeRatingContentDescriptionResult { 112 | repeated AgeRatingContentDescription ageratingcontentdescriptions = 1; 113 | } 114 | 115 | message AgeRatingContentDescription { 116 | uint64 id = 1; 117 | AgeRatingContentDescriptionCategoryEnum category = 2 [deprecated = true]; 118 | string description = 3; 119 | string checksum = 4; 120 | } 121 | 122 | 123 | enum AgeRatingContentDescriptionCategoryEnum { 124 | AGERATINGCONTENTDESCRIPTION_CATEGORY_NULL = 0 [deprecated = true]; 125 | ESRB_ALCOHOL_REFERENCE = 1 [deprecated = true]; 126 | ESRB_ANIMATED_BLOOD = 2 [deprecated = true]; 127 | ESRB_BLOOD = 3 [deprecated = true]; 128 | ESRB_BLOOD_AND_GORE = 4 [deprecated = true]; 129 | ESRB_CARTOON_VIOLENCE = 5 [deprecated = true]; 130 | ESRB_COMIC_MISCHIEF = 6 [deprecated = true]; 131 | ESRB_CRUDE_HUMOR = 7 [deprecated = true]; 132 | ESRB_DRUG_REFERENCE = 8 [deprecated = true]; 133 | ESRB_FANTASY_VIOLENCE = 9 [deprecated = true]; 134 | ESRB_INTENSE_VIOLENCE = 10 [deprecated = true]; 135 | ESRB_LANGUAGE = 11 [deprecated = true]; 136 | ESRB_LYRICS = 12 [deprecated = true]; 137 | ESRB_MATURE_HUMOR = 13 [deprecated = true]; 138 | ESRB_NUDITY = 14 [deprecated = true]; 139 | ESRB_PARTIAL_NUDITY = 15 [deprecated = true]; 140 | ESRB_REAL_GAMBLING = 16 [deprecated = true]; 141 | ESRB_SEXUAL_CONTENT = 17 [deprecated = true]; 142 | ESRB_SEXUAL_THEMES = 18 [deprecated = true]; 143 | ESRB_SEXUAL_VIOLENCE = 19 [deprecated = true]; 144 | ESRB_SIMULATED_GAMBLING = 20 [deprecated = true]; 145 | ESRB_STRONG_LANGUAGE = 21 [deprecated = true]; 146 | ESRB_STRONG_LYRICS = 22 [deprecated = true]; 147 | ESRB_STRONG_SEXUAL_CONTENT = 23 [deprecated = true]; 148 | ESRB_SUGGESTIVE_THEMES = 24 [deprecated = true]; 149 | ESRB_TOBACCO_REFERENCE = 25 [deprecated = true]; 150 | ESRB_USE_OF_ALCOHOL = 26 [deprecated = true]; 151 | ESRB_USE_OF_DRUGS = 27 [deprecated = true]; 152 | ESRB_USE_OF_TOBACCO = 28 [deprecated = true]; 153 | ESRB_VIOLENCE = 29 [deprecated = true]; 154 | ESRB_VIOLENT_REFERENCES = 30 [deprecated = true]; 155 | ESRB_ANIMATED_VIOLENCE = 31 [deprecated = true]; 156 | ESRB_MILD_LANGUAGE = 32 [deprecated = true]; 157 | ESRB_MILD_VIOLENCE = 33 [deprecated = true]; 158 | ESRB_USE_OF_DRUGS_AND_ALCOHOL = 34 [deprecated = true]; 159 | ESRB_DRUG_AND_ALCOHOL_REFERENCE = 35 [deprecated = true]; 160 | ESRB_MILD_SUGGESTIVE_THEMES = 36 [deprecated = true]; 161 | ESRB_MILD_CARTOON_VIOLENCE = 37 [deprecated = true]; 162 | ESRB_MILD_BLOOD = 38 [deprecated = true]; 163 | ESRB_REALISTIC_BLOOD_AND_GORE = 39 [deprecated = true]; 164 | ESRB_REALISTIC_VIOLENCE = 40 [deprecated = true]; 165 | ESRB_ALCOHOL_AND_TOBACCO_REFERENCE = 41 [deprecated = true]; 166 | ESRB_MATURE_SEXUAL_THEMES = 42 [deprecated = true]; 167 | ESRB_MILD_ANIMATED_VIOLENCE = 43 [deprecated = true]; 168 | ESRB_MILD_SEXUAL_THEMES = 44 [deprecated = true]; 169 | ESRB_USE_OF_ALCOHOL_AND_TOBACCO = 45 [deprecated = true]; 170 | ESRB_ANIMATED_BLOOD_AND_GORE = 46 [deprecated = true]; 171 | ESRB_MILD_FANTASY_VIOLENCE = 47 [deprecated = true]; 172 | ESRB_MILD_LYRICS = 48 [deprecated = true]; 173 | ESRB_REALISTIC_BLOOD = 49 [deprecated = true]; 174 | PEGI_VIOLENCE = 50 [deprecated = true]; 175 | PEGI_SEX = 51 [deprecated = true]; 176 | PEGI_DRUGS = 52 [deprecated = true]; 177 | PEGI_FEAR = 53 [deprecated = true]; 178 | PEGI_DISCRIMINATION = 54 [deprecated = true]; 179 | PEGI_BAD_LANGUAGE = 55 [deprecated = true]; 180 | PEGI_GAMBLING = 56 [deprecated = true]; 181 | PEGI_ONLINE_GAMEPLAY = 57 [deprecated = true]; 182 | PEGI_IN_GAME_PURCHASES = 58 [deprecated = true]; 183 | CERO_LOVE = 59 [deprecated = true]; 184 | CERO_SEXUAL_CONTENT = 60 [deprecated = true]; 185 | CERO_VIOLENCE = 61 [deprecated = true]; 186 | CERO_HORROR = 62 [deprecated = true]; 187 | CERO_DRINKING_SMOKING = 63 [deprecated = true]; 188 | CERO_GAMBLING = 64 [deprecated = true]; 189 | CERO_CRIME = 65 [deprecated = true]; 190 | CERO_CONTROLLED_SUBSTANCES = 66 [deprecated = true]; 191 | CERO_LANGUAGES_AND_OTHERS = 67 [deprecated = true]; 192 | GRAC_SEXUALITY = 68 [deprecated = true]; 193 | GRAC_VIOLENCE = 69 [deprecated = true]; 194 | GRAC_FEAR_HORROR_THREATENING = 70 [deprecated = true]; 195 | GRAC_LANGUAGE = 71 [deprecated = true]; 196 | GRAC_ALCOHOL_TOBACCO_DRUG = 72 [deprecated = true]; 197 | GRAC_CRIME_ANTI_SOCIAL = 73 [deprecated = true]; 198 | GRAC_GAMBLING = 74 [deprecated = true]; 199 | CLASS_IND_VIOLENCIA = 75 [deprecated = true]; 200 | CLASS_IND_VIOLENCIA_EXTREMA = 76 [deprecated = true]; 201 | CLASS_IND_CONTEUDO_SEXUAL = 77 [deprecated = true]; 202 | CLASS_IND_NUDEZ = 78 [deprecated = true]; 203 | CLASS_IND_SEXO = 79 [deprecated = true]; 204 | CLASS_IND_SEXO_EXPLICITO = 80 [deprecated = true]; 205 | CLASS_IND_DROGAS = 81 [deprecated = true]; 206 | CLASS_IND_DROGAS_LICITAS = 82 [deprecated = true]; 207 | CLASS_IND_DROGAS_ILICITAS = 83 [deprecated = true]; 208 | CLASS_IND_LINGUAGEM_IMPROPRIA = 84 [deprecated = true]; 209 | CLASS_IND_ATOS_CRIMINOSOS = 85 [deprecated = true]; 210 | } 211 | 212 | message AgeRatingContentDescriptionV2Result { 213 | repeated AgeRatingContentDescriptionV2 ageratingcontentdescriptionsv2 = 1; 214 | } 215 | 216 | message AgeRatingContentDescriptionV2 { 217 | uint64 id = 1; 218 | string description = 2; 219 | AgeRatingOrganization organization = 3; 220 | google.protobuf.Timestamp created_at = 4; 221 | google.protobuf.Timestamp updated_at = 5; 222 | string checksum = 6; 223 | } 224 | 225 | message AgeRatingOrganizationResult { 226 | repeated AgeRatingOrganization ageratingorganizations = 1; 227 | } 228 | 229 | message AgeRatingOrganization { 230 | uint64 id = 1; 231 | string name = 2; 232 | google.protobuf.Timestamp created_at = 3; 233 | google.protobuf.Timestamp updated_at = 4; 234 | string checksum = 5; 235 | } 236 | 237 | message AlternativeNameResult { 238 | repeated AlternativeName alternativenames = 1; 239 | } 240 | 241 | message AlternativeName { 242 | uint64 id = 1; 243 | string comment = 2; 244 | Game game = 3; 245 | string name = 4; 246 | string checksum = 5; 247 | } 248 | 249 | message ArtworkResult { 250 | repeated Artwork artworks = 1; 251 | } 252 | 253 | message Artwork { 254 | uint64 id = 1; 255 | bool alpha_channel = 2; 256 | bool animated = 3; 257 | Game game = 4; 258 | int32 height = 5; 259 | string image_id = 6; 260 | string url = 7; 261 | int32 width = 8; 262 | string checksum = 9; 263 | } 264 | 265 | message CharacterResult { 266 | repeated Character characters = 1; 267 | } 268 | 269 | message Character { 270 | uint64 id = 1; 271 | repeated string akas = 2; 272 | string country_name = 3; 273 | google.protobuf.Timestamp created_at = 4; 274 | string description = 5; 275 | repeated Game games = 6; 276 | GenderGenderEnum gender = 7 [deprecated = true]; 277 | CharacterMugShot mug_shot = 8; 278 | string name = 9; 279 | string slug = 10; 280 | CharacterSpeciesEnum species = 11 [deprecated = true]; 281 | google.protobuf.Timestamp updated_at = 12; 282 | string url = 13; 283 | string checksum = 14; 284 | CharacterGender character_gender = 15; 285 | CharacterSpecie character_species = 16; 286 | } 287 | 288 | 289 | enum GenderGenderEnum { 290 | MALE = 0 [deprecated = true]; 291 | FEMALE = 1 [deprecated = true]; 292 | OTHER = 2 [deprecated = true]; 293 | } 294 | 295 | 296 | enum CharacterSpeciesEnum { 297 | CHARACTER_SPECIES_NULL = 0 [deprecated = true]; 298 | HUMAN = 1 [deprecated = true]; 299 | ALIEN = 2 [deprecated = true]; 300 | ANIMAL = 3 [deprecated = true]; 301 | ANDROID = 4 [deprecated = true]; 302 | UNKNOWN = 5 [deprecated = true]; 303 | } 304 | 305 | message CharacterGenderResult { 306 | repeated CharacterGender charactergenders = 1; 307 | } 308 | 309 | message CharacterGender { 310 | uint64 id = 1; 311 | string name = 2; 312 | google.protobuf.Timestamp created_at = 3; 313 | google.protobuf.Timestamp updated_at = 4; 314 | string checksum = 5; 315 | } 316 | 317 | message CharacterMugShotResult { 318 | repeated CharacterMugShot charactermugshots = 1; 319 | } 320 | 321 | message CharacterMugShot { 322 | uint64 id = 1; 323 | bool alpha_channel = 2; 324 | bool animated = 3; 325 | int32 height = 4; 326 | string image_id = 5; 327 | string url = 6; 328 | int32 width = 7; 329 | string checksum = 8; 330 | } 331 | 332 | message CharacterSpecieResult { 333 | repeated CharacterSpecie characterspecies = 1; 334 | } 335 | 336 | message CharacterSpecie { 337 | uint64 id = 1; 338 | string name = 2; 339 | google.protobuf.Timestamp created_at = 3; 340 | google.protobuf.Timestamp updated_at = 4; 341 | string checksum = 5; 342 | } 343 | 344 | message CollectionResult { 345 | repeated Collection collections = 1; 346 | } 347 | 348 | message Collection { 349 | uint64 id = 1; 350 | google.protobuf.Timestamp created_at = 2; 351 | repeated Game games = 3; 352 | string name = 4; 353 | string slug = 5; 354 | google.protobuf.Timestamp updated_at = 6; 355 | string url = 7; 356 | string checksum = 8; 357 | CollectionType type = 9; 358 | repeated CollectionRelation as_parent_relations = 10; 359 | repeated CollectionRelation as_child_relations = 11; 360 | } 361 | 362 | message CollectionMembershipResult { 363 | repeated CollectionMembership collectionmemberships = 1; 364 | } 365 | 366 | message CollectionMembership { 367 | uint64 id = 1; 368 | Game game = 2; 369 | Collection collection = 3; 370 | CollectionMembershipType type = 4; 371 | google.protobuf.Timestamp updated_at = 5; 372 | google.protobuf.Timestamp created_at = 6; 373 | string checksum = 7; 374 | } 375 | 376 | message CollectionMembershipTypeResult { 377 | repeated CollectionMembershipType collectionmembershiptypes = 1; 378 | } 379 | 380 | message CollectionMembershipType { 381 | uint64 id = 1; 382 | string name = 2; 383 | string description = 3; 384 | CollectionType allowed_collection_type = 4; 385 | google.protobuf.Timestamp updated_at = 5; 386 | google.protobuf.Timestamp created_at = 6; 387 | string checksum = 7; 388 | } 389 | 390 | message CollectionRelationResult { 391 | repeated CollectionRelation collectionrelations = 1; 392 | } 393 | 394 | message CollectionRelation { 395 | uint64 id = 1; 396 | Collection child_collection = 2; 397 | Collection parent_collection = 3; 398 | CollectionRelationType type = 4; 399 | google.protobuf.Timestamp updated_at = 5; 400 | google.protobuf.Timestamp created_at = 6; 401 | string checksum = 7; 402 | } 403 | 404 | message CollectionRelationTypeResult { 405 | repeated CollectionRelationType collectionrelationtypes = 1; 406 | } 407 | 408 | message CollectionRelationType { 409 | uint64 id = 1; 410 | string name = 2; 411 | string description = 3; 412 | CollectionType allowed_child_type = 4; 413 | CollectionType allowed_parent_type = 5; 414 | google.protobuf.Timestamp updated_at = 6; 415 | google.protobuf.Timestamp created_at = 7; 416 | string checksum = 8; 417 | } 418 | 419 | message CollectionTypeResult { 420 | repeated CollectionType collectiontypes = 1; 421 | } 422 | 423 | message CollectionType { 424 | uint64 id = 1; 425 | string name = 2; 426 | string description = 3; 427 | google.protobuf.Timestamp updated_at = 4; 428 | google.protobuf.Timestamp created_at = 5; 429 | string checksum = 6; 430 | } 431 | 432 | message CompanyResult { 433 | repeated Company companies = 1; 434 | } 435 | 436 | message Company { 437 | uint64 id = 1; 438 | google.protobuf.Timestamp change_date = 2; 439 | DateFormatChangeDateCategoryEnum change_date_category = 3 [deprecated = true]; 440 | Company changed_company_id = 4; 441 | int32 country = 5; 442 | google.protobuf.Timestamp created_at = 6; 443 | string description = 7; 444 | repeated Game developed = 8; 445 | CompanyLogo logo = 9; 446 | string name = 10; 447 | Company parent = 11; 448 | repeated Game published = 12; 449 | string slug = 13; 450 | google.protobuf.Timestamp start_date = 14; 451 | DateFormatChangeDateCategoryEnum start_date_category = 15 [deprecated = true]; 452 | google.protobuf.Timestamp updated_at = 16; 453 | string url = 17; 454 | repeated CompanyWebsite websites = 18; 455 | string checksum = 19; 456 | CompanyStatus status = 20; 457 | DateFormat start_date_format = 21; 458 | DateFormat change_date_format = 22; 459 | } 460 | 461 | 462 | enum DateFormatChangeDateCategoryEnum { 463 | YYYYMMMMDD = 0 [deprecated = true]; 464 | YYYYMMMM = 1 [deprecated = true]; 465 | YYYY = 2 [deprecated = true]; 466 | YYYYQ1 = 3 [deprecated = true]; 467 | YYYYQ2 = 4 [deprecated = true]; 468 | YYYYQ3 = 5 [deprecated = true]; 469 | YYYYQ4 = 6 [deprecated = true]; 470 | TBD = 7 [deprecated = true]; 471 | } 472 | 473 | message CompanyLogoResult { 474 | repeated CompanyLogo companylogos = 1; 475 | } 476 | 477 | message CompanyLogo { 478 | uint64 id = 1; 479 | bool alpha_channel = 2; 480 | bool animated = 3; 481 | int32 height = 4; 482 | string image_id = 5; 483 | string url = 6; 484 | int32 width = 7; 485 | string checksum = 8; 486 | } 487 | 488 | message CompanyStatusResult { 489 | repeated CompanyStatus companystatuses = 1; 490 | } 491 | 492 | message CompanyStatus { 493 | uint64 id = 1; 494 | string name = 2; 495 | google.protobuf.Timestamp created_at = 3; 496 | google.protobuf.Timestamp updated_at = 4; 497 | string checksum = 5; 498 | } 499 | 500 | message CompanyWebsiteResult { 501 | repeated CompanyWebsite companywebsites = 1; 502 | } 503 | 504 | message CompanyWebsite { 505 | uint64 id = 1; 506 | WebsiteCategoryEnum category = 2 [deprecated = true]; 507 | bool trusted = 3; 508 | string url = 4; 509 | string checksum = 5; 510 | WebsiteType type = 6; 511 | } 512 | 513 | 514 | enum WebsiteCategoryEnum { 515 | WEBSITE_CATEGORY_NULL = 0 [deprecated = true]; 516 | WEBSITE_OFFICIAL = 1 [deprecated = true]; 517 | WEBSITE_WIKIA = 2 [deprecated = true]; 518 | WEBSITE_WIKIPEDIA = 3 [deprecated = true]; 519 | WEBSITE_FACEBOOK = 4 [deprecated = true]; 520 | WEBSITE_TWITTER = 5 [deprecated = true]; 521 | WEBSITE_TWITCH = 6 [deprecated = true]; 522 | WEBSITE_INSTAGRAM = 8 [deprecated = true]; 523 | WEBSITE_YOUTUBE = 9 [deprecated = true]; 524 | WEBSITE_IPHONE = 10 [deprecated = true]; 525 | WEBSITE_IPAD = 11 [deprecated = true]; 526 | WEBSITE_ANDROID = 12 [deprecated = true]; 527 | WEBSITE_STEAM = 13 [deprecated = true]; 528 | WEBSITE_REDDIT = 14 [deprecated = true]; 529 | WEBSITE_ITCH = 15 [deprecated = true]; 530 | WEBSITE_EPICGAMES = 16 [deprecated = true]; 531 | WEBSITE_GOG = 17 [deprecated = true]; 532 | WEBSITE_DISCORD = 18 [deprecated = true]; 533 | WEBSITE_BLUESKY = 19 [deprecated = true]; 534 | } 535 | 536 | message CoverResult { 537 | repeated Cover covers = 1; 538 | } 539 | 540 | message Cover { 541 | uint64 id = 1; 542 | bool alpha_channel = 2; 543 | bool animated = 3; 544 | Game game = 4; 545 | int32 height = 5; 546 | string image_id = 6; 547 | string url = 7; 548 | int32 width = 8; 549 | string checksum = 9; 550 | GameLocalization game_localization = 10; 551 | } 552 | 553 | message DateFormatResult { 554 | repeated DateFormat dateformats = 1; 555 | } 556 | 557 | message DateFormat { 558 | uint64 id = 1; 559 | string format = 2; 560 | google.protobuf.Timestamp created_at = 3; 561 | google.protobuf.Timestamp updated_at = 4; 562 | string checksum = 5; 563 | } 564 | 565 | message EventResult { 566 | repeated Event events = 1; 567 | } 568 | 569 | message Event { 570 | uint64 id = 1; 571 | string name = 2; 572 | string description = 3; 573 | string slug = 4; 574 | EventLogo event_logo = 5; 575 | google.protobuf.Timestamp start_time = 6; 576 | string time_zone = 7; 577 | google.protobuf.Timestamp end_time = 8; 578 | string live_stream_url = 9; 579 | repeated Game games = 10; 580 | repeated GameVideo videos = 11; 581 | repeated EventNetwork event_networks = 12; 582 | google.protobuf.Timestamp created_at = 13; 583 | google.protobuf.Timestamp updated_at = 14; 584 | string checksum = 15; 585 | } 586 | 587 | message EventLogoResult { 588 | repeated EventLogo eventlogos = 1; 589 | } 590 | 591 | message EventLogo { 592 | uint64 id = 1; 593 | Event event = 2; 594 | bool alpha_channel = 3; 595 | bool animated = 4; 596 | int32 height = 5; 597 | string image_id = 6; 598 | string url = 7; 599 | int32 width = 8; 600 | google.protobuf.Timestamp created_at = 9; 601 | google.protobuf.Timestamp updated_at = 10; 602 | string checksum = 11; 603 | } 604 | 605 | message EventNetworkResult { 606 | repeated EventNetwork eventnetworks = 1; 607 | } 608 | 609 | message EventNetwork { 610 | uint64 id = 1; 611 | Event event = 2; 612 | string url = 3; 613 | NetworkType network_type = 4; 614 | google.protobuf.Timestamp created_at = 5; 615 | google.protobuf.Timestamp updated_at = 6; 616 | string checksum = 7; 617 | } 618 | 619 | message ExternalGameResult { 620 | repeated ExternalGame externalgames = 1; 621 | } 622 | 623 | message ExternalGame { 624 | uint64 id = 1; 625 | ExternalGameCategoryEnum category = 2 [deprecated = true]; 626 | google.protobuf.Timestamp created_at = 3; 627 | Game game = 4; 628 | string name = 5; 629 | string uid = 6; 630 | google.protobuf.Timestamp updated_at = 7; 631 | string url = 8; 632 | int32 year = 9; 633 | ExternalGameMediaEnum media = 10 [deprecated = true]; 634 | Platform platform = 11; 635 | repeated int32 countries = 12; 636 | string checksum = 13; 637 | ExternalGameSource external_game_source = 14; 638 | GameReleaseFormat game_release_format = 15; 639 | } 640 | 641 | 642 | enum ExternalGameCategoryEnum { 643 | EXTERNALGAME_CATEGORY_NULL = 0 [deprecated = true]; 644 | EXTERNALGAME_STEAM = 1 [deprecated = true]; 645 | EXTERNALGAME_GOG = 5 [deprecated = true]; 646 | EXTERNALGAME_YOUTUBE = 10 [deprecated = true]; 647 | EXTERNALGAME_MICROSOFT = 11 [deprecated = true]; 648 | EXTERNALGAME_APPLE = 13 [deprecated = true]; 649 | EXTERNALGAME_TWITCH = 14 [deprecated = true]; 650 | EXTERNALGAME_ANDROID = 15 [deprecated = true]; 651 | EXTERNALGAME_AMAZON_ASIN = 20 [deprecated = true]; 652 | EXTERNALGAME_AMAZON_LUNA = 22 [deprecated = true]; 653 | EXTERNALGAME_AMAZON_ADG = 23 [deprecated = true]; 654 | EXTERNALGAME_EPIC_GAME_STORE = 26 [deprecated = true]; 655 | EXTERNALGAME_OCULUS = 28 [deprecated = true]; 656 | EXTERNALGAME_UTOMIK = 29 [deprecated = true]; 657 | EXTERNALGAME_ITCH_IO = 30 [deprecated = true]; 658 | EXTERNALGAME_XBOX_MARKETPLACE = 31 [deprecated = true]; 659 | EXTERNALGAME_KARTRIDGE = 32 [deprecated = true]; 660 | EXTERNALGAME_PLAYSTATION_STORE_US = 36 [deprecated = true]; 661 | EXTERNALGAME_FOCUS_ENTERTAINMENT = 37 [deprecated = true]; 662 | EXTERNALGAME_XBOX_GAME_PASS_ULTIMATE_CLOUD = 54 [deprecated = true]; 663 | EXTERNALGAME_GAMEJOLT = 55 [deprecated = true]; 664 | } 665 | 666 | 667 | enum ExternalGameMediaEnum { 668 | EXTERNALGAME_MEDIA_NULL = 0 [deprecated = true]; 669 | EXTERNALGAME_DIGITAL = 1 [deprecated = true]; 670 | EXTERNALGAME_PHYSICAL = 2 [deprecated = true]; 671 | } 672 | 673 | message ExternalGameSourceResult { 674 | repeated ExternalGameSource externalgamesources = 1; 675 | } 676 | 677 | message ExternalGameSource { 678 | uint64 id = 1; 679 | string name = 2; 680 | google.protobuf.Timestamp created_at = 4; 681 | google.protobuf.Timestamp updated_at = 5; 682 | string checksum = 6; 683 | } 684 | 685 | message FranchiseResult { 686 | repeated Franchise franchises = 1; 687 | } 688 | 689 | message Franchise { 690 | uint64 id = 1; 691 | google.protobuf.Timestamp created_at = 2; 692 | repeated Game games = 3; 693 | string name = 4; 694 | string slug = 5; 695 | google.protobuf.Timestamp updated_at = 6; 696 | string url = 7; 697 | string checksum = 8; 698 | } 699 | 700 | message GameResult { 701 | repeated Game games = 1; 702 | } 703 | 704 | message Game { 705 | uint64 id = 1; 706 | repeated AgeRating age_ratings = 2; 707 | double aggregated_rating = 3; 708 | int32 aggregated_rating_count = 4; 709 | repeated AlternativeName alternative_names = 5; 710 | repeated Artwork artworks = 6; 711 | repeated Game bundles = 7; 712 | GameCategoryEnum category = 8 [deprecated = true]; 713 | Collection collection = 9 [deprecated = true]; 714 | Cover cover = 10; 715 | google.protobuf.Timestamp created_at = 11; 716 | repeated Game dlcs = 12; 717 | repeated Game expansions = 13; 718 | repeated ExternalGame external_games = 14; 719 | google.protobuf.Timestamp first_release_date = 15; 720 | int32 follows = 16 [deprecated = true]; 721 | Franchise franchise = 17; 722 | repeated Franchise franchises = 18; 723 | repeated GameEngine game_engines = 19; 724 | repeated GameMode game_modes = 20; 725 | repeated Genre genres = 21; 726 | int32 hypes = 22; 727 | repeated InvolvedCompany involved_companies = 23; 728 | repeated Keyword keywords = 24; 729 | repeated MultiplayerMode multiplayer_modes = 25; 730 | string name = 26; 731 | Game parent_game = 27; 732 | repeated Platform platforms = 28; 733 | repeated PlayerPerspective player_perspectives = 29; 734 | double rating = 30; 735 | int32 rating_count = 31; 736 | repeated ReleaseDate release_dates = 32; 737 | repeated Screenshot screenshots = 33; 738 | repeated Game similar_games = 34; 739 | string slug = 35; 740 | repeated Game standalone_expansions = 36; 741 | GameStatusEnum status = 37 [deprecated = true]; 742 | string storyline = 38; 743 | string summary = 39; 744 | repeated int32 tags = 40; 745 | repeated Theme themes = 41; 746 | double total_rating = 42; 747 | int32 total_rating_count = 43; 748 | google.protobuf.Timestamp updated_at = 44; 749 | string url = 45; 750 | Game version_parent = 46; 751 | string version_title = 47; 752 | repeated GameVideo videos = 48; 753 | repeated Website websites = 49; 754 | string checksum = 50; 755 | repeated Game remakes = 51; 756 | repeated Game remasters = 52; 757 | repeated Game expanded_games = 53; 758 | repeated Game ports = 54; 759 | repeated Game forks = 55; 760 | repeated LanguageSupport language_supports = 56; 761 | repeated GameLocalization game_localizations = 57; 762 | repeated Collection collections = 58; 763 | GameStatus game_status = 59; 764 | GameType game_type = 60; 765 | } 766 | 767 | 768 | enum GameCategoryEnum { 769 | MAIN_GAME = 0 [deprecated = true]; 770 | DLC_ADDON = 1 [deprecated = true]; 771 | EXPANSION = 2 [deprecated = true]; 772 | BUNDLE = 3 [deprecated = true]; 773 | STANDALONE_EXPANSION = 4 [deprecated = true]; 774 | MOD = 5 [deprecated = true]; 775 | EPISODE = 6 [deprecated = true]; 776 | SEASON = 7 [deprecated = true]; 777 | REMAKE = 8 [deprecated = true]; 778 | REMASTER = 9 [deprecated = true]; 779 | EXPANDED_GAME = 10 [deprecated = true]; 780 | PORT = 11 [deprecated = true]; 781 | FORK = 12 [deprecated = true]; 782 | PACK = 13 [deprecated = true]; 783 | UPDATE = 14 [deprecated = true]; 784 | } 785 | 786 | 787 | enum GameStatusEnum { 788 | RELEASED = 0 [deprecated = true]; 789 | ALPHA = 2 [deprecated = true]; 790 | BETA = 3 [deprecated = true]; 791 | EARLY_ACCESS = 4 [deprecated = true]; 792 | OFFLINE = 5 [deprecated = true]; 793 | CANCELLED = 6 [deprecated = true]; 794 | RUMORED = 7 [deprecated = true]; 795 | DELISTED = 8 [deprecated = true]; 796 | } 797 | 798 | message GameEngineResult { 799 | repeated GameEngine gameengines = 1; 800 | } 801 | 802 | message GameEngine { 803 | uint64 id = 1; 804 | repeated Company companies = 2; 805 | google.protobuf.Timestamp created_at = 3; 806 | string description = 4; 807 | GameEngineLogo logo = 5; 808 | string name = 6; 809 | repeated Platform platforms = 7; 810 | string slug = 8; 811 | google.protobuf.Timestamp updated_at = 9; 812 | string url = 10; 813 | string checksum = 11; 814 | } 815 | 816 | message GameEngineLogoResult { 817 | repeated GameEngineLogo gameenginelogos = 1; 818 | } 819 | 820 | message GameEngineLogo { 821 | uint64 id = 1; 822 | bool alpha_channel = 2; 823 | bool animated = 3; 824 | int32 height = 4; 825 | string image_id = 5; 826 | string url = 6; 827 | int32 width = 7; 828 | string checksum = 8; 829 | } 830 | 831 | message GameLocalizationResult { 832 | repeated GameLocalization gamelocalizations = 1; 833 | } 834 | 835 | message GameLocalization { 836 | uint64 id = 1; 837 | string name = 2; 838 | Cover cover = 3; 839 | Game game = 4; 840 | Region region = 5; 841 | google.protobuf.Timestamp created_at = 6; 842 | google.protobuf.Timestamp updated_at = 7; 843 | string checksum = 8; 844 | } 845 | 846 | message GameModeResult { 847 | repeated GameMode gamemodes = 1; 848 | } 849 | 850 | message GameMode { 851 | uint64 id = 1; 852 | google.protobuf.Timestamp created_at = 2; 853 | string name = 3; 854 | string slug = 4; 855 | google.protobuf.Timestamp updated_at = 5; 856 | string url = 6; 857 | string checksum = 7; 858 | } 859 | 860 | message GameReleaseFormatResult { 861 | repeated GameReleaseFormat gamereleaseformats = 1; 862 | } 863 | 864 | message GameReleaseFormat { 865 | uint64 id = 1; 866 | string format = 2; 867 | google.protobuf.Timestamp created_at = 3; 868 | google.protobuf.Timestamp updated_at = 4; 869 | string checksum = 5; 870 | } 871 | 872 | message GameStatusResult { 873 | repeated GameStatus gamestatuses = 1; 874 | } 875 | 876 | message GameStatus { 877 | uint64 id = 1; 878 | string status = 2; 879 | google.protobuf.Timestamp created_at = 3; 880 | google.protobuf.Timestamp updated_at = 4; 881 | string checksum = 5; 882 | } 883 | 884 | message GameTimeToBeatResult { 885 | repeated GameTimeToBeat gametimetobeats = 1; 886 | } 887 | 888 | message GameTimeToBeat { 889 | uint64 id = 1; 890 | int32 game_id = 2; 891 | int32 hastily = 3; 892 | int32 normally = 4; 893 | int32 completely = 5; 894 | int32 count = 6; 895 | google.protobuf.Timestamp created_at = 7; 896 | google.protobuf.Timestamp updated_at = 8; 897 | string checksum = 9; 898 | } 899 | 900 | message GameTypeResult { 901 | repeated GameType gametypes = 1; 902 | } 903 | 904 | message GameType { 905 | uint64 id = 1; 906 | string type = 2; 907 | google.protobuf.Timestamp created_at = 3; 908 | google.protobuf.Timestamp updated_at = 4; 909 | string checksum = 5; 910 | } 911 | 912 | message GameVersionResult { 913 | repeated GameVersion gameversions = 1; 914 | } 915 | 916 | message GameVersion { 917 | uint64 id = 1; 918 | google.protobuf.Timestamp created_at = 2; 919 | repeated GameVersionFeature features = 3; 920 | Game game = 4; 921 | repeated Game games = 5; 922 | google.protobuf.Timestamp updated_at = 6; 923 | string url = 7; 924 | string checksum = 8; 925 | } 926 | 927 | message GameVersionFeatureResult { 928 | repeated GameVersionFeature gameversionfeatures = 1; 929 | } 930 | 931 | message GameVersionFeature { 932 | uint64 id = 1; 933 | GameVersionFeatureCategoryEnum category = 2; 934 | string description = 3; 935 | int32 position = 4; 936 | string title = 5; 937 | repeated GameVersionFeatureValue values = 6; 938 | string checksum = 7; 939 | } 940 | 941 | 942 | enum GameVersionFeatureCategoryEnum { 943 | BOOLEAN = 0; 944 | DESCRIPTION = 1; 945 | } 946 | 947 | message GameVersionFeatureValueResult { 948 | repeated GameVersionFeatureValue gameversionfeaturevalues = 1; 949 | } 950 | 951 | message GameVersionFeatureValue { 952 | uint64 id = 1; 953 | Game game = 2; 954 | GameVersionFeature game_feature = 3; 955 | GameVersionFeatureValueIncludedFeatureEnum included_feature = 4; 956 | string note = 5; 957 | string checksum = 6; 958 | } 959 | 960 | 961 | enum GameVersionFeatureValueIncludedFeatureEnum { 962 | NOT_INCLUDED = 0; 963 | INCLUDED = 1; 964 | PRE_ORDER_ONLY = 2; 965 | } 966 | 967 | message GameVideoResult { 968 | repeated GameVideo gamevideos = 1; 969 | } 970 | 971 | message GameVideo { 972 | uint64 id = 1; 973 | Game game = 2; 974 | string name = 3; 975 | string video_id = 4; 976 | string checksum = 5; 977 | } 978 | 979 | message GenreResult { 980 | repeated Genre genres = 1; 981 | } 982 | 983 | message Genre { 984 | uint64 id = 1; 985 | google.protobuf.Timestamp created_at = 2; 986 | string name = 3; 987 | string slug = 4; 988 | google.protobuf.Timestamp updated_at = 5; 989 | string url = 6; 990 | string checksum = 7; 991 | } 992 | 993 | message InvolvedCompanyResult { 994 | repeated InvolvedCompany involvedcompanies = 1; 995 | } 996 | 997 | message InvolvedCompany { 998 | uint64 id = 1; 999 | Company company = 2; 1000 | google.protobuf.Timestamp created_at = 3; 1001 | bool developer = 4; 1002 | Game game = 5; 1003 | bool porting = 6; 1004 | bool publisher = 7; 1005 | bool supporting = 8; 1006 | google.protobuf.Timestamp updated_at = 9; 1007 | string checksum = 10; 1008 | } 1009 | 1010 | message KeywordResult { 1011 | repeated Keyword keywords = 1; 1012 | } 1013 | 1014 | message Keyword { 1015 | uint64 id = 1; 1016 | google.protobuf.Timestamp created_at = 2; 1017 | string name = 3; 1018 | string slug = 4; 1019 | google.protobuf.Timestamp updated_at = 5; 1020 | string url = 6; 1021 | string checksum = 7; 1022 | } 1023 | 1024 | message LanguageResult { 1025 | repeated Language languages = 1; 1026 | } 1027 | 1028 | message Language { 1029 | uint64 id = 1; 1030 | string name = 2; 1031 | string native_name = 3; 1032 | string locale = 4; 1033 | google.protobuf.Timestamp created_at = 5; 1034 | google.protobuf.Timestamp updated_at = 6; 1035 | string checksum = 7; 1036 | } 1037 | 1038 | message LanguageSupportResult { 1039 | repeated LanguageSupport languagesupports = 1; 1040 | } 1041 | 1042 | message LanguageSupport { 1043 | uint64 id = 1; 1044 | Game game = 2; 1045 | Language language = 3; 1046 | LanguageSupportType language_support_type = 4; 1047 | google.protobuf.Timestamp created_at = 5; 1048 | google.protobuf.Timestamp updated_at = 6; 1049 | string checksum = 7; 1050 | } 1051 | 1052 | message LanguageSupportTypeResult { 1053 | repeated LanguageSupportType languagesupporttypes = 1; 1054 | } 1055 | 1056 | message LanguageSupportType { 1057 | uint64 id = 1; 1058 | string name = 2; 1059 | google.protobuf.Timestamp created_at = 3; 1060 | google.protobuf.Timestamp updated_at = 4; 1061 | string checksum = 5; 1062 | } 1063 | 1064 | message MultiplayerModeResult { 1065 | repeated MultiplayerMode multiplayermodes = 1; 1066 | } 1067 | 1068 | message MultiplayerMode { 1069 | uint64 id = 1; 1070 | bool campaigncoop = 2; 1071 | bool dropin = 3; 1072 | Game game = 4; 1073 | bool lancoop = 5; 1074 | bool offlinecoop = 6; 1075 | int32 offlinecoopmax = 7; 1076 | int32 offlinemax = 8; 1077 | bool onlinecoop = 9; 1078 | int32 onlinecoopmax = 10; 1079 | int32 onlinemax = 11; 1080 | Platform platform = 12; 1081 | bool splitscreen = 13; 1082 | bool splitscreenonline = 14; 1083 | string checksum = 15; 1084 | } 1085 | 1086 | message NetworkTypeResult { 1087 | repeated NetworkType networktypes = 1; 1088 | } 1089 | 1090 | message NetworkType { 1091 | uint64 id = 1; 1092 | string name = 2; 1093 | repeated EventNetwork event_networks = 3; 1094 | google.protobuf.Timestamp created_at = 4; 1095 | google.protobuf.Timestamp updated_at = 5; 1096 | string checksum = 6; 1097 | } 1098 | 1099 | message PlatformResult { 1100 | repeated Platform platforms = 1; 1101 | } 1102 | 1103 | message Platform { 1104 | uint64 id = 1; 1105 | string abbreviation = 2; 1106 | string alternative_name = 3; 1107 | PlatformCategoryEnum category = 4 [deprecated = true]; 1108 | google.protobuf.Timestamp created_at = 5; 1109 | int32 generation = 6; 1110 | string name = 7; 1111 | PlatformLogo platform_logo = 8; 1112 | PlatformFamily platform_family = 9; 1113 | string slug = 10; 1114 | string summary = 11; 1115 | google.protobuf.Timestamp updated_at = 12; 1116 | string url = 13; 1117 | repeated PlatformVersion versions = 14; 1118 | repeated PlatformWebsite websites = 15; 1119 | string checksum = 16; 1120 | PlatformType platform_type = 17; 1121 | } 1122 | 1123 | 1124 | enum PlatformCategoryEnum { 1125 | PLATFORM_CATEGORY_NULL = 0 [deprecated = true]; 1126 | CONSOLE = 1 [deprecated = true]; 1127 | ARCADE = 2 [deprecated = true]; 1128 | PLATFORM = 3 [deprecated = true]; 1129 | OPERATING_SYSTEM = 4 [deprecated = true]; 1130 | PORTABLE_CONSOLE = 5 [deprecated = true]; 1131 | COMPUTER = 6 [deprecated = true]; 1132 | } 1133 | 1134 | message PlatformFamilyResult { 1135 | repeated PlatformFamily platformfamilies = 1; 1136 | } 1137 | 1138 | message PlatformFamily { 1139 | uint64 id = 1; 1140 | string name = 2; 1141 | string slug = 3; 1142 | string checksum = 4; 1143 | } 1144 | 1145 | message PlatformLogoResult { 1146 | repeated PlatformLogo platformlogos = 1; 1147 | } 1148 | 1149 | message PlatformLogo { 1150 | uint64 id = 1; 1151 | bool alpha_channel = 2; 1152 | bool animated = 3; 1153 | int32 height = 4; 1154 | string image_id = 5; 1155 | string url = 6; 1156 | int32 width = 7; 1157 | string checksum = 8; 1158 | } 1159 | 1160 | message PlatformTypeResult { 1161 | repeated PlatformType platformtypes = 1; 1162 | } 1163 | 1164 | message PlatformType { 1165 | uint64 id = 1; 1166 | string name = 2; 1167 | google.protobuf.Timestamp created_at = 3; 1168 | google.protobuf.Timestamp updated_at = 4; 1169 | string checksum = 5; 1170 | } 1171 | 1172 | message PlatformVersionResult { 1173 | repeated PlatformVersion platformversions = 1; 1174 | } 1175 | 1176 | message PlatformVersion { 1177 | uint64 id = 1; 1178 | repeated PlatformVersionCompany companies = 2; 1179 | string connectivity = 3; 1180 | string cpu = 4; 1181 | string graphics = 5; 1182 | PlatformVersionCompany main_manufacturer = 6; 1183 | string media = 7; 1184 | string memory = 8; 1185 | string name = 9; 1186 | string os = 11; 1187 | string output = 12; 1188 | PlatformLogo platform_logo = 13; 1189 | repeated PlatformVersionReleaseDate platform_version_release_dates = 14; 1190 | string resolutions = 15; 1191 | string slug = 16; 1192 | string sound = 17; 1193 | string storage = 18; 1194 | string summary = 19; 1195 | string url = 20; 1196 | string checksum = 21; 1197 | } 1198 | 1199 | message PlatformVersionCompanyResult { 1200 | repeated PlatformVersionCompany platformversioncompanies = 1; 1201 | } 1202 | 1203 | message PlatformVersionCompany { 1204 | uint64 id = 1; 1205 | string comment = 2; 1206 | Company company = 3; 1207 | bool developer = 4; 1208 | bool manufacturer = 5; 1209 | string checksum = 6; 1210 | } 1211 | 1212 | message PlatformVersionReleaseDateResult { 1213 | repeated PlatformVersionReleaseDate platformversionreleasedates = 1; 1214 | } 1215 | 1216 | message PlatformVersionReleaseDate { 1217 | uint64 id = 1; 1218 | DateFormatChangeDateCategoryEnum category = 2 [deprecated = true]; 1219 | google.protobuf.Timestamp created_at = 3; 1220 | google.protobuf.Timestamp date = 4; 1221 | string human = 5; 1222 | int32 m = 6; 1223 | PlatformVersion platform_version = 7; 1224 | RegionRegionEnum region = 8 [deprecated = true]; 1225 | google.protobuf.Timestamp updated_at = 9; 1226 | int32 y = 10; 1227 | string checksum = 11; 1228 | DateFormat date_format = 12; 1229 | ReleaseDateRegion release_region = 13; 1230 | } 1231 | 1232 | 1233 | enum RegionRegionEnum { 1234 | REGION_REGION_NULL = 0 [deprecated = true]; 1235 | EUROPE = 1 [deprecated = true]; 1236 | NORTH_AMERICA = 2 [deprecated = true]; 1237 | AUSTRALIA = 3 [deprecated = true]; 1238 | NEW_ZEALAND = 4 [deprecated = true]; 1239 | JAPAN = 5 [deprecated = true]; 1240 | CHINA = 6 [deprecated = true]; 1241 | ASIA = 7 [deprecated = true]; 1242 | WORLDWIDE = 8 [deprecated = true]; 1243 | KOREA = 9 [deprecated = true]; 1244 | BRAZIL = 10 [deprecated = true]; 1245 | } 1246 | 1247 | message PlatformWebsiteResult { 1248 | repeated PlatformWebsite platformwebsites = 1; 1249 | } 1250 | 1251 | message PlatformWebsite { 1252 | uint64 id = 1; 1253 | WebsiteCategoryEnum category = 2 [deprecated = true]; 1254 | bool trusted = 3; 1255 | string url = 4; 1256 | string checksum = 5; 1257 | WebsiteType type = 6; 1258 | } 1259 | 1260 | message PlayerPerspectiveResult { 1261 | repeated PlayerPerspective playerperspectives = 1; 1262 | } 1263 | 1264 | message PlayerPerspective { 1265 | uint64 id = 1; 1266 | google.protobuf.Timestamp created_at = 2; 1267 | string name = 3; 1268 | string slug = 4; 1269 | google.protobuf.Timestamp updated_at = 5; 1270 | string url = 6; 1271 | string checksum = 7; 1272 | } 1273 | 1274 | message PopularityPrimitiveResult { 1275 | repeated PopularityPrimitive popularityprimitives = 1; 1276 | } 1277 | 1278 | message PopularityPrimitive { 1279 | uint64 id = 1; 1280 | int32 game_id = 2; 1281 | PopularityType popularity_type = 3; 1282 | PopularitySourcePopularitySourceEnum popularity_source = 4 [deprecated = true]; 1283 | double value = 5; 1284 | google.protobuf.Timestamp calculated_at = 6; 1285 | google.protobuf.Timestamp created_at = 7; 1286 | google.protobuf.Timestamp updated_at = 8; 1287 | string checksum = 9; 1288 | ExternalGameSource external_popularity_source = 10; 1289 | } 1290 | 1291 | 1292 | enum PopularitySourcePopularitySourceEnum { 1293 | POPULARITYSOURCE_POPULARITY_SOURCE_NULL = 0 [deprecated = true]; 1294 | IGDB = 121 [deprecated = true]; 1295 | } 1296 | 1297 | message PopularityTypeResult { 1298 | repeated PopularityType popularitytypes = 1; 1299 | } 1300 | 1301 | message PopularityType { 1302 | uint64 id = 1; 1303 | PopularitySourcePopularitySourceEnum popularity_source = 2 [deprecated = true]; 1304 | string name = 3; 1305 | google.protobuf.Timestamp created_at = 4; 1306 | google.protobuf.Timestamp updated_at = 5; 1307 | string checksum = 6; 1308 | ExternalGameSource external_popularity_source = 7; 1309 | } 1310 | 1311 | message RegionResult { 1312 | repeated Region regions = 1; 1313 | } 1314 | 1315 | message Region { 1316 | uint64 id = 1; 1317 | string name = 2; 1318 | string category = 3; 1319 | string identifier = 4; 1320 | google.protobuf.Timestamp created_at = 5; 1321 | google.protobuf.Timestamp updated_at = 6; 1322 | string checksum = 7; 1323 | } 1324 | 1325 | message ReleaseDateResult { 1326 | repeated ReleaseDate releasedates = 1; 1327 | } 1328 | 1329 | message ReleaseDate { 1330 | uint64 id = 1; 1331 | DateFormatChangeDateCategoryEnum category = 2 [deprecated = true]; 1332 | google.protobuf.Timestamp created_at = 3; 1333 | google.protobuf.Timestamp date = 4; 1334 | Game game = 5; 1335 | string human = 6; 1336 | int32 m = 7; 1337 | Platform platform = 8; 1338 | RegionRegionEnum region = 9 [deprecated = true]; 1339 | google.protobuf.Timestamp updated_at = 10; 1340 | int32 y = 11; 1341 | string checksum = 12; 1342 | ReleaseDateStatus status = 13; 1343 | DateFormat date_format = 14; 1344 | ReleaseDateRegion release_region = 15; 1345 | } 1346 | 1347 | message ReleaseDateRegionResult { 1348 | repeated ReleaseDateRegion releasedateregions = 1; 1349 | } 1350 | 1351 | message ReleaseDateRegion { 1352 | uint64 id = 1; 1353 | string region = 2; 1354 | google.protobuf.Timestamp created_at = 3; 1355 | google.protobuf.Timestamp updated_at = 4; 1356 | string checksum = 5; 1357 | } 1358 | 1359 | message ReleaseDateStatusResult { 1360 | repeated ReleaseDateStatus releasedatestatuses = 1; 1361 | } 1362 | 1363 | message ReleaseDateStatus { 1364 | uint64 id = 1; 1365 | string name = 2; 1366 | string description = 3; 1367 | google.protobuf.Timestamp created_at = 4; 1368 | google.protobuf.Timestamp updated_at = 5; 1369 | string checksum = 6; 1370 | } 1371 | 1372 | message ScreenshotResult { 1373 | repeated Screenshot screenshots = 1; 1374 | } 1375 | 1376 | message Screenshot { 1377 | uint64 id = 1; 1378 | bool alpha_channel = 2; 1379 | bool animated = 3; 1380 | Game game = 4; 1381 | int32 height = 5; 1382 | string image_id = 6; 1383 | string url = 7; 1384 | int32 width = 8; 1385 | string checksum = 9; 1386 | } 1387 | 1388 | message SearchResult { 1389 | repeated Search searches = 1; 1390 | } 1391 | 1392 | message Search { 1393 | uint64 id = 1; 1394 | string alternative_name = 2; 1395 | Character character = 3; 1396 | Collection collection = 4; 1397 | Company company = 5; 1398 | string description = 6; 1399 | Game game = 7; 1400 | string name = 8; 1401 | Platform platform = 9; 1402 | google.protobuf.Timestamp published_at = 10; 1403 | TestDummy test_dummy = 11; 1404 | Theme theme = 12; 1405 | string checksum = 13; 1406 | } 1407 | 1408 | message TestDummyResult { 1409 | repeated TestDummy testdummies = 1; 1410 | } 1411 | 1412 | message TestDummy { 1413 | uint64 id = 1; 1414 | bool bool_value = 2; 1415 | google.protobuf.Timestamp created_at = 3; 1416 | TestDummyEnumTestEnum enum_test = 4; 1417 | double float_value = 5; 1418 | Game game = 6; 1419 | repeated int32 integer_array = 7; 1420 | int32 integer_value = 8; 1421 | string name = 9; 1422 | int32 new_integer_value = 10; 1423 | bool private = 11; 1424 | string slug = 12; 1425 | repeated string string_array = 13; 1426 | repeated TestDummy test_dummies = 14; 1427 | TestDummy test_dummy = 15; 1428 | google.protobuf.Timestamp updated_at = 16; 1429 | string url = 17; 1430 | string checksum = 18; 1431 | } 1432 | 1433 | 1434 | enum TestDummyEnumTestEnum { 1435 | TESTDUMMY_ENUM_TEST_NULL = 0; 1436 | ENUM1 = 1; 1437 | ENUM2 = 2; 1438 | } 1439 | 1440 | message ThemeResult { 1441 | repeated Theme themes = 1; 1442 | } 1443 | 1444 | message Theme { 1445 | uint64 id = 1; 1446 | google.protobuf.Timestamp created_at = 2; 1447 | string name = 3; 1448 | string slug = 4; 1449 | google.protobuf.Timestamp updated_at = 5; 1450 | string url = 6; 1451 | string checksum = 7; 1452 | } 1453 | 1454 | message WebsiteResult { 1455 | repeated Website websites = 1; 1456 | } 1457 | 1458 | message Website { 1459 | uint64 id = 1; 1460 | WebsiteCategoryEnum category = 2 [deprecated = true]; 1461 | Game game = 3; 1462 | bool trusted = 4; 1463 | string url = 5; 1464 | string checksum = 6; 1465 | WebsiteType type = 7; 1466 | } 1467 | 1468 | message WebsiteTypeResult { 1469 | repeated WebsiteType websitetypes = 1; 1470 | } 1471 | 1472 | message WebsiteType { 1473 | uint64 id = 1; 1474 | string type = 2; 1475 | google.protobuf.Timestamp created_at = 3; 1476 | google.protobuf.Timestamp updated_at = 4; 1477 | string checksum = 5; 1478 | } 1479 | -------------------------------------------------------------------------------- /src/test/java/com/api/igdb/TestJavaWrapper.java: -------------------------------------------------------------------------------- 1 | package com.api.igdb; 2 | 3 | import com.api.igdb.apicalypse.APICalypse; 4 | import com.api.igdb.apicalypse.Sort; 5 | import com.api.igdb.exceptions.RequestException; 6 | import com.api.igdb.request.IGDBWrapper; 7 | import com.api.igdb.request.JsonRequestKt; 8 | import com.api.igdb.request.ProtoRequestKt; 9 | import com.api.igdb.utils.ImageBuilderKt; 10 | import com.api.igdb.utils.ImageSize; 11 | import com.api.igdb.utils.ImageType; 12 | import org.junit.jupiter.api.Test; 13 | import proto.Cover; 14 | import proto.Game; 15 | import proto.Search; 16 | 17 | import java.util.List; 18 | 19 | class TestJavaWrapper { 20 | private final IGDBWrapper wrapper = IGDBWrapper.INSTANCE; 21 | 22 | TestJavaWrapper() { 23 | wrapper.setCredentials(System.getenv("client_id"), System.getenv("bearer")); 24 | } 25 | 26 | /* 27 | * The proto tests should cover the rest of the endpoints 28 | * */ 29 | 30 | @Test 31 | void testGetProtoGames() throws RequestException { 32 | List result = ProtoRequestKt.games(wrapper, new APICalypse()); 33 | assert(!result.isEmpty()); 34 | } 35 | 36 | @Test 37 | void testGetJsonGames() throws RequestException { 38 | String result = JsonRequestKt.jsonGames(wrapper, new APICalypse()); 39 | assert(!result.isEmpty()); 40 | } 41 | 42 | /* 43 | * Real-world test cases 44 | * */ 45 | 46 | //Get all Coming Soon PS4 games 47 | @Test 48 | void testComingSoonPS4Games() { 49 | String date = String.valueOf((System.currentTimeMillis() / 1000)); 50 | APICalypse query = new APICalypse() 51 | .fields("*") 52 | .where("platforms = 48 & release_dates.date > " + date) 53 | .sort("release_dates.date", Sort.ASCENDING); 54 | 55 | try { 56 | List ps4Games = ProtoRequestKt.games(wrapper, query); 57 | assert(!ps4Games.isEmpty()); 58 | } catch (RequestException e) { 59 | assert(false); 60 | } 61 | } 62 | 63 | //Get all Recently released PS4 games 64 | @Test 65 | void testRecentlyReleasedPS4Games() { 66 | String date = String.valueOf((System.currentTimeMillis() / 1000)); 67 | APICalypse query = new APICalypse() 68 | .fields("*") 69 | .where("platforms = 48 & release_dates.date < " + date) 70 | .sort("release_dates.date", Sort.DESCENDING); 71 | 72 | try { 73 | List ps4Games = ProtoRequestKt.games(wrapper, query); 74 | assert(!ps4Games.isEmpty()); 75 | } catch (RequestException e) { 76 | assert(false); 77 | } 78 | } 79 | 80 | //Get all Recently released PS4 games 81 | @Test 82 | void testSearch() { 83 | APICalypse query = new APICalypse() 84 | .search("Assassins Creed") 85 | .fields("game.name,game.involved_companies") 86 | .where("game != null & game.version_parent = null"); 87 | 88 | try { 89 | List result = ProtoRequestKt.search(wrapper, query); 90 | assert(!result.isEmpty()); 91 | } catch (RequestException e) { 92 | assert(false); 93 | } 94 | } 95 | 96 | //Get all Recently released PS4 games 97 | @Test 98 | void testPS4Exclusives() { 99 | APICalypse query = new APICalypse() 100 | .fields("name,category,platforms") 101 | .where("category = 0 & platforms = 48"); 102 | 103 | try { 104 | List result = ProtoRequestKt.games(wrapper, query); 105 | assert(!result.isEmpty()); 106 | } catch (RequestException e) { 107 | assert(false); 108 | } 109 | } 110 | 111 | @Test 112 | void testJPEGImg() { 113 | APICalypse query = new APICalypse() 114 | .fields("image_id") 115 | .where("image_id != n"); 116 | try { 117 | List covers = ProtoRequestKt.covers(wrapper, query); 118 | assert(!covers.isEmpty()); 119 | Cover firstCover = covers.get(0); 120 | String coverUrl = ImageBuilderKt.imageBuilder(firstCover.getImageId(), ImageSize.HD, ImageType.JPEG); 121 | assert(!coverUrl.isEmpty()); 122 | assert(coverUrl.endsWith("jpg")); 123 | 124 | } catch (RequestException e) { 125 | assert(false); 126 | } 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /src/test/java/com/api/igdb/TestTwitchToken.java: -------------------------------------------------------------------------------- 1 | package com.api.igdb; 2 | 3 | import com.api.igdb.request.TwitchAuthenticator; 4 | import com.api.igdb.utils.TwitchToken; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import java.time.Duration; 8 | 9 | import static org.junit.jupiter.api.Assertions.assertNotNull; 10 | import static org.junit.jupiter.api.Assertions.assertTrue; 11 | 12 | public class TestTwitchToken { 13 | 14 | @Test 15 | void testGetTwitchToken() { 16 | // Create the Twitch authenticator instance 17 | TwitchAuthenticator tAuth = TwitchAuthenticator.INSTANCE; 18 | // request a new Twitch Authentication token 19 | TwitchToken token = tAuth.requestTwitchToken(System.getenv("client_id"), System.getenv("client_secret")); 20 | 21 | assertNotNull(token); 22 | assertTrue(token.getExpires_in() > Duration.ofDays(57).toSeconds()); 23 | long tokenFutureDate = System.currentTimeMillis() + Duration.ofDays(57).toSeconds(); 24 | assertTrue(tokenFutureDate > token.getExpiresUnix()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/kotlin/com/api/igdb/TestAPICalypseQueryParser.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb 2 | 3 | import com.api.igdb.apicalypse.APICalypse 4 | import com.api.igdb.apicalypse.Sort 5 | import org.junit.jupiter.api.Assertions.assertEquals 6 | import org.junit.jupiter.api.Test 7 | 8 | class TestAPICalypseQueryParser { 9 | 10 | @Test 11 | fun testAllFields() { 12 | val apiCalypse = APICalypse().fields("*") 13 | assertEquals("f *;", apiCalypse.buildQuery()) 14 | } 15 | 16 | @Test 17 | fun testLimit() { 18 | val apiCalypse = APICalypse().fields("name").limit(10) 19 | assertEquals("f name;l 10;", apiCalypse.buildQuery()) 20 | } 21 | 22 | @Test 23 | fun testOffset() { 24 | val apiCalypse = APICalypse().fields("name").offset(10) 25 | assertEquals("f name;o 10;", apiCalypse.buildQuery()) 26 | } 27 | 28 | @Test 29 | fun testWhereNoCommaOrWhere() { 30 | val apiCalypse = APICalypse().fields("*").where("id = 1942") 31 | assertEquals("f *;w id = 1942;", apiCalypse.buildQuery()) 32 | } 33 | 34 | @Test 35 | fun testWhereNoWhere() { 36 | val apiCalypse = APICalypse().fields("*").where("id = 1942;") 37 | assertEquals("f *;w id = 1942;", apiCalypse.buildQuery()) 38 | } 39 | 40 | @Test 41 | fun testWhere() { 42 | val apiCalypse = APICalypse().fields("*").where("where id = 1942;") 43 | assertEquals("f *;where id = 1942;", apiCalypse.buildQuery()) 44 | } 45 | 46 | @Test 47 | fun testWhereW() { 48 | val apiCalypse = APICalypse().fields("*").where("w id = 1942;") 49 | assertEquals("f *;w id = 1942;", apiCalypse.buildQuery()) 50 | } 51 | 52 | @Test 53 | fun testExclude() { 54 | val apiCalypse = APICalypse().fields("*").exclude("name") 55 | assertEquals("f *;x name;", apiCalypse.buildQuery()) 56 | } 57 | 58 | @Test 59 | fun testSort() { 60 | val apiCalypse = APICalypse().fields("name,popularity").sort("popularity", Sort.DESCENDING) 61 | assertEquals("f name,popularity;s popularity desc;", apiCalypse.buildQuery()) 62 | } 63 | 64 | @Test 65 | fun testComingSoonGamesForPS4() { 66 | val apiCalypse = APICalypse().fields("*") 67 | .where("platform = 48 & date > 1538129354;") 68 | .sort("date", Sort.ASCENDING) 69 | assertEquals("f *;s date asc;w platform = 48 & date > 1538129354;", apiCalypse.buildQuery()) 70 | } 71 | 72 | @Test 73 | fun testRecentlyReleaseGamesPS4() { 74 | val apiCalypse = APICalypse().fields("*") 75 | .where("platform = 48 & date > 1538129354;") 76 | .sort("date", Sort.DESCENDING) 77 | assertEquals("f *;s date desc;w platform = 48 & date > 1538129354;", apiCalypse.buildQuery()) 78 | } 79 | 80 | @Test 81 | fun testSearch() { 82 | val apiCalypse = APICalypse().search("Halo") 83 | .where("game != n").fields("game.name,game.invloved_companies") 84 | assertEquals( 85 | "search \"Halo\";f game.name,game.invloved_companies;w game != n;", 86 | apiCalypse.buildQuery() 87 | ) 88 | } 89 | 90 | @Test 91 | fun testSearchWithExclude() { 92 | val apiCalypse = APICalypse().search("Assassins Creed") 93 | .fields("game.name,game.invloved_companies") 94 | .where("game != n & game.version_parent = n") 95 | assertEquals( 96 | "search \"Assassins Creed\";f game.name,game.invloved_companies;w game != n & game.version_parent = n;", 97 | apiCalypse.buildQuery() 98 | ) 99 | } 100 | 101 | @Test 102 | fun testGetVersions() { 103 | val apiCalypse = APICalypse() 104 | .fields("version_parent.*") 105 | .where("id = 39047") 106 | assertEquals("f version_parent.*;w id = 39047;", apiCalypse.buildQuery()) 107 | } 108 | 109 | @Test 110 | fun testGetAllPS4Exclusives() { 111 | val apiCalypse = APICalypse() 112 | .fields("name,category,platforms") 113 | .where("category = 0 & platforms = 48") 114 | assertEquals("f name,category,platforms;w category = 0 & platforms = 48;", apiCalypse.buildQuery()) 115 | } 116 | 117 | @Test 118 | fun testGetAllPS4ANDPCExclusives() { 119 | val apiCalypse = APICalypse() 120 | .fields("name,category,platforms") 121 | .where("category = 0 & platforms = {48,6}") 122 | assertEquals( 123 | "f name,category,platforms;w category = 0 & platforms = {48,6};", 124 | apiCalypse.buildQuery() 125 | ) 126 | } 127 | 128 | } -------------------------------------------------------------------------------- /src/test/kotlin/com/api/igdb/TestIGDBWrapper.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb 2 | 3 | import com.api.igdb.apicalypse.APICalypse 4 | import com.api.igdb.apicalypse.Sort 5 | import com.api.igdb.exceptions.RequestException 6 | import com.api.igdb.request.IGDBWrapper 7 | import com.api.igdb.request.games 8 | import com.api.igdb.request.search 9 | import org.junit.jupiter.api.BeforeEach 10 | import org.junit.jupiter.api.Test 11 | 12 | class TestIGDBWrapper { 13 | 14 | private val wrapper = IGDBWrapper 15 | 16 | @BeforeEach 17 | fun setup() { 18 | wrapper.setCredentials(System.getenv("client_id"), System.getenv("bearer")) 19 | } 20 | 21 | //Get all Coming Soon PS4 games 22 | @Test 23 | fun testComingSoonPS4Games() { 24 | val date = (System.currentTimeMillis() / 1000).toString() 25 | val query = APICalypse() 26 | .fields("*") 27 | .where("platforms = 48 & release_dates.date > $date") 28 | .sort("release_dates.date", Sort.ASCENDING) 29 | 30 | try { 31 | val ps4Games = wrapper.games(query) 32 | assert(ps4Games.isNotEmpty()) 33 | } catch (e: RequestException) { 34 | assert(false) 35 | } 36 | } 37 | 38 | //Get all Recently released PS4 games 39 | @Test 40 | fun testRecentlyReleasedPS4Games() { 41 | val date = (System.currentTimeMillis() / 1000).toString() 42 | val query = APICalypse() 43 | .fields("*") 44 | .where("platforms = 48 & release_dates.date < $date") 45 | .sort("release_dates.date", Sort.DESCENDING) 46 | 47 | try { 48 | val ps4Games = wrapper.games(query) 49 | assert(ps4Games.isNotEmpty()) 50 | } catch (e: RequestException) { 51 | assert(false) 52 | } 53 | } 54 | 55 | //Get all Recently released PS4 games 56 | @Test 57 | fun testSearch() { 58 | val query = APICalypse() 59 | .search("Assassins Creed") 60 | .fields("game.name,game.involved_companies") 61 | .where("game != null & game.version_parent = null") 62 | 63 | try { 64 | val result = wrapper.search(query) 65 | assert(result.isNotEmpty()) 66 | } catch (e: RequestException) { 67 | assert(false) 68 | } 69 | 70 | } 71 | 72 | //Get all Recently released PS4 games 73 | @Test 74 | fun testPS4Exclusives() { 75 | val query = APICalypse() 76 | .fields("name,category,platforms") 77 | .where("category = 0 & platforms = 48") 78 | 79 | try { 80 | val result = wrapper.games(query) 81 | assert(result.isNotEmpty()) 82 | } catch (e: RequestException) { 83 | assert(false) 84 | } 85 | 86 | } 87 | 88 | } -------------------------------------------------------------------------------- /src/test/kotlin/com/api/igdb/TestImageBuilder.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb 2 | 3 | import com.api.igdb.apicalypse.APICalypse 4 | import com.api.igdb.exceptions.RequestException 5 | import com.api.igdb.request.IGDBWrapper 6 | import com.api.igdb.request.covers 7 | import com.api.igdb.utils.ImageSize 8 | import com.api.igdb.utils.ImageType 9 | import com.api.igdb.utils.imageBuilder 10 | import org.junit.jupiter.api.BeforeEach 11 | import org.junit.jupiter.api.Test 12 | 13 | class TestImageBuilder { 14 | 15 | private val wrapper = IGDBWrapper 16 | 17 | @BeforeEach 18 | fun setup() { 19 | wrapper.setCredentials(System.getenv("client_id"), System.getenv("bearer")) 20 | } 21 | 22 | @Test 23 | fun testJPEGImg() { 24 | val query = APICalypse() 25 | .fields("image_id") 26 | .where("image_id != n") 27 | try { 28 | val covers = wrapper.covers(query) 29 | assert(covers.isNotEmpty()) 30 | val firstCover = covers.first() 31 | val coverUrl = imageBuilder(firstCover.imageId, ImageSize.HD, ImageType.JPEG) 32 | assert(coverUrl.isNotBlank()) 33 | assert(coverUrl.substringAfterLast(".") == "jpg") 34 | 35 | } catch (e: RequestException) { 36 | assert(false) 37 | } 38 | } 39 | 40 | @Test 41 | fun testPNGImg() { 42 | val query = APICalypse() 43 | .fields("image_id") 44 | .where("image_id != n") 45 | try { 46 | val covers = wrapper.covers(query) 47 | assert(covers.isNotEmpty()) 48 | val firstCover = covers.first() 49 | val coverUrl = imageBuilder(firstCover.imageId, ImageSize.THUMB, ImageType.PNG) 50 | assert(coverUrl.isNotBlank()) 51 | assert(coverUrl.substringAfterLast(".") == "png") 52 | 53 | } catch (e: RequestException) { 54 | assert(false) 55 | } 56 | } 57 | 58 | @Test 59 | fun testGIFImg() { 60 | val query = APICalypse() 61 | .fields("image_id") 62 | .where("image_id != n") 63 | try { 64 | val covers = wrapper.covers(query) 65 | assert(covers.isNotEmpty()) 66 | val firstCover = covers.first() 67 | val coverUrl = imageBuilder(firstCover.imageId, ImageSize.LOGO_MEDIUM, ImageType.GIF) 68 | assert(coverUrl.isNotBlank()) 69 | assert(coverUrl.substringAfterLast(".") == "gif") 70 | 71 | } catch (e: RequestException) { 72 | assert(false) 73 | } 74 | } 75 | 76 | @Test 77 | fun testWEBPImg() { 78 | val query = APICalypse() 79 | .fields("image_id") 80 | .where("image_id != n") 81 | try { 82 | val covers = wrapper.covers(query) 83 | assert(covers.isNotEmpty()) 84 | val firstCover = covers.first() 85 | val coverUrl = imageBuilder(firstCover.imageId, ImageSize.SCREENSHOT_HUGE, ImageType.WEBP) 86 | assert(coverUrl.isNotBlank()) 87 | assert(coverUrl.substringAfterLast(".") == "webp") 88 | 89 | } catch (e: RequestException) { 90 | assert(false) 91 | } 92 | } 93 | 94 | } -------------------------------------------------------------------------------- /src/test/kotlin/com/api/igdb/TestProtobufRequest.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb 2 | 3 | import com.api.igdb.apicalypse.APICalypse 4 | import com.api.igdb.request.IGDBWrapper 5 | import com.api.igdb.request.* 6 | import org.junit.jupiter.api.Assertions.assertEquals 7 | import org.junit.jupiter.api.Assertions.assertNotEquals 8 | import org.junit.jupiter.api.BeforeEach 9 | import org.junit.jupiter.api.Test 10 | 11 | class TestProtobufRequest { 12 | 13 | private val wrapper = IGDBWrapper 14 | 15 | private val apiCalypseQuery = APICalypse().fields("*") 16 | 17 | @BeforeEach 18 | fun setup() { 19 | wrapper.setCredentials(System.getenv("client_id"), System.getenv("bearer")) 20 | } 21 | 22 | @Test 23 | fun testAgeRating() { 24 | val result = wrapper.ageRatings(apiCalypseQuery) 25 | assert(result.isNotEmpty()) 26 | } 27 | 28 | @Test 29 | fun testAgeRatingCategories() { 30 | val result = wrapper.ageRatingCategories(apiCalypseQuery) 31 | assert(result.isNotEmpty()) 32 | } 33 | 34 | @Test 35 | fun testAgeRatingContentDescriptions() { 36 | val result = wrapper.ageRatingContentDescriptions(apiCalypseQuery) 37 | assert(result.isNotEmpty()) 38 | } 39 | 40 | @Test 41 | fun testAgeRatingContentDescriptionsV2() { 42 | val result = wrapper.ageRatingContentDescriptionsV2(apiCalypseQuery) 43 | assert(result.isNotEmpty()) 44 | } 45 | 46 | @Test 47 | fun testAgeRatingOrganizations() { 48 | val result = wrapper.ageRatingOrganizations(apiCalypseQuery) 49 | assert(result.isNotEmpty()) 50 | } 51 | 52 | @Test 53 | fun testAlternativeNames() { 54 | val result = wrapper.alternativeNames(apiCalypseQuery) 55 | assert(result.isNotEmpty()) 56 | } 57 | 58 | @Test 59 | fun testArtwork() { 60 | val result = wrapper.artworks(apiCalypseQuery) 61 | assert(result.isNotEmpty()) 62 | } 63 | 64 | @Test 65 | fun testCharactersGenders() { 66 | val result = wrapper.characterGenders(apiCalypseQuery) 67 | assert(result.isNotEmpty()) 68 | } 69 | 70 | @Test 71 | fun testCharacterSpecies() { 72 | val result = wrapper.characterSpecies(apiCalypseQuery) 73 | assert(result.isNotEmpty()) 74 | } 75 | 76 | @Test 77 | fun testCharacters() { 78 | val result = wrapper.characters(apiCalypseQuery) 79 | assert(result.isNotEmpty()) 80 | } 81 | 82 | @Test 83 | fun testCollections() { 84 | val result = wrapper.collections(apiCalypseQuery) 85 | assert(result.isNotEmpty()) 86 | } 87 | 88 | @Test 89 | fun testCharacterMugShots() { 90 | val result = wrapper.characterMugShots(apiCalypseQuery) 91 | assert(result.isNotEmpty()) 92 | } 93 | 94 | @Test 95 | fun testCompanies() { 96 | val result = wrapper.companies(apiCalypseQuery) 97 | assert(result.isNotEmpty()) 98 | } 99 | 100 | @Test 101 | fun testCompanyStatuses() { 102 | val result = wrapper.companyStatuses(apiCalypseQuery) 103 | assert(result.isNotEmpty()) 104 | } 105 | 106 | @Test 107 | fun testComapnyWebsites() { 108 | val result = wrapper.companyWebsites(apiCalypseQuery) 109 | assert(result.isNotEmpty()) 110 | } 111 | 112 | @Test 113 | fun testCompantLogos() { 114 | val result = wrapper.companyLogos(apiCalypseQuery) 115 | assert(result.isNotEmpty()) 116 | } 117 | 118 | @Test 119 | fun testCover() { 120 | val result = wrapper.covers(apiCalypseQuery) 121 | assert(result.isNotEmpty()) 122 | } 123 | 124 | @Test 125 | fun testDateFormats() { 126 | val result = wrapper.dateFormats(apiCalypseQuery) 127 | assert(result.isNotEmpty()) 128 | } 129 | 130 | @Test 131 | fun testExternalGames() { 132 | val result = wrapper.externalGames(apiCalypseQuery) 133 | assert(result.isNotEmpty()) 134 | } 135 | 136 | @Test 137 | fun testExternalGameSources() { 138 | val result = wrapper.externalGameSources(apiCalypseQuery) 139 | assert(result.isNotEmpty()) 140 | } 141 | 142 | @Test 143 | fun testFranschises() { 144 | val result = wrapper.franchises(apiCalypseQuery) 145 | assert(result.isNotEmpty()) 146 | } 147 | 148 | @Test 149 | fun testGames() { 150 | val result = wrapper.games(APICalypse() 151 | .fields("*, age_ratings.*, alternative_names.*, cover.*, external_games.*, franchises.*, genres.*, screenshots.*, videos.*") 152 | .where("id = 1942")) 153 | assert(result.isNotEmpty()) 154 | val game = result.first() 155 | assertEquals("The Witcher 3: Wild Hunt", game.name) 156 | assertEquals("the-witcher-3-wild-hunt", game.slug) 157 | assert(game.name.isNotEmpty()) 158 | assert(game.hasCreatedAt()) 159 | if (game.checksum.isNullOrBlank()) println("checksumField empty") else println(game.checksum) 160 | assertNotEquals(" ", game.checksum) 161 | 162 | val ageRatings = game.ageRatingsList 163 | val ageRating = ageRatings.first() 164 | assert(ageRating.contentDescriptionsList.isNotEmpty()) 165 | assert(ageRating.ratingContentDescriptionsList.isNotEmpty()) 166 | assert(ageRating.hasOrganization()) 167 | assert(ageRating.hasRatingCategory()) 168 | if (ageRating.checksum.isNullOrBlank()) println("checksumField empty") else println(ageRating.checksum) 169 | assertNotEquals(" ", ageRating.checksum) 170 | 171 | val alternativeNames = game.alternativeNamesList 172 | assert(alternativeNames.isNotEmpty()) 173 | if (alternativeNames.first().checksum.isNullOrBlank()) println("checksumField empty") else println(alternativeNames.first().checksum) 174 | assertNotEquals(" ", alternativeNames.first().checksum) 175 | 176 | val cover = game.cover 177 | assertNotEquals(" ", cover.imageId) 178 | if (cover.checksum.isNullOrBlank()) println("checksumField empty") else println(cover.checksum) 179 | assertNotEquals(" ", cover.checksum) 180 | 181 | val externalGames = game.externalGamesList 182 | assert(externalGames.isNotEmpty()) 183 | if (externalGames.first().checksum.isNullOrBlank()) println("checksumField empty") else println(externalGames.first().checksum) 184 | assertNotEquals(" ", externalGames.first().checksum) 185 | 186 | val franchises = game.franchisesList 187 | assert(franchises.first().id == 452L) 188 | assertEquals("the-witcher", franchises.first().slug) 189 | val franchiseGames = franchises.first().gamesList 190 | assert(franchiseGames.isNotEmpty()) 191 | 192 | val involvedCompany = game.involvedCompaniesList 193 | assert(involvedCompany.isNotEmpty()) 194 | 195 | val genres = game.genresList 196 | assert(genres.isNotEmpty()) 197 | 198 | val releaseDates = game.releaseDatesList 199 | assert(releaseDates.isNotEmpty()) 200 | 201 | val screenshots = game.screenshotsList 202 | assert(screenshots.isNotEmpty()) 203 | val screenshot = screenshots.first() 204 | assertNotEquals(" ", screenshot.imageId) 205 | assertNotEquals(" ", screenshot.checksum) 206 | 207 | val videos = game.videosList 208 | assert(videos.isNotEmpty()) 209 | val video = videos.first() 210 | assertNotEquals(" ", video.checksum) 211 | assertNotEquals(" ", video.videoId) 212 | } 213 | 214 | @Test 215 | fun testGameEngines() { 216 | val result = wrapper.gameEngines(apiCalypseQuery) 217 | assert(result.isNotEmpty()) 218 | } 219 | 220 | @Test 221 | fun testGameEngineLogos() { 222 | val result = wrapper.gameEngineLogos(apiCalypseQuery) 223 | assert(result.isNotEmpty()) 224 | } 225 | 226 | @Test 227 | fun testGameLocalizations() { 228 | val result = wrapper.gameLocalizations(apiCalypseQuery) 229 | assert(result.isNotEmpty()) 230 | } 231 | 232 | @Test 233 | fun testGameModes() { 234 | val result = wrapper.gameModes(apiCalypseQuery) 235 | assert(result.isNotEmpty()) 236 | } 237 | 238 | @Test 239 | fun testGameReleaseFormats() { 240 | val result = wrapper.gameReleaseFormats(apiCalypseQuery) 241 | assert(result.isNotEmpty()) 242 | } 243 | 244 | @Test 245 | fun testGameStatuses() { 246 | val result = wrapper.gameStatuses(apiCalypseQuery) 247 | assert(result.isNotEmpty()) 248 | } 249 | 250 | @Test 251 | fun testGameTimeToBeats() { 252 | val result = wrapper.gameTimeToBeats(apiCalypseQuery) 253 | assert(result.isNotEmpty()) 254 | } 255 | 256 | @Test 257 | fun testGameTypes() { 258 | val result = wrapper.gameTypes(apiCalypseQuery) 259 | assert(result.isNotEmpty()) 260 | } 261 | 262 | @Test 263 | fun testGameVersions() { 264 | val result = wrapper.gameVersion(apiCalypseQuery) 265 | assert(result.isNotEmpty()) 266 | } 267 | 268 | @Test 269 | fun testGameVersionFeatures() { 270 | val result = wrapper.gameVersionFeatures(apiCalypseQuery) 271 | assert(result.isNotEmpty()) 272 | } 273 | 274 | @Test 275 | fun testGameVersionFeatureValues() { 276 | val result = wrapper.gameVersionFeatureValues(apiCalypseQuery) 277 | assert(result.isNotEmpty()) 278 | } 279 | 280 | @Test 281 | fun testGameVideos() { 282 | val result = wrapper.gameVideos(apiCalypseQuery) 283 | assert(result.isNotEmpty()) 284 | } 285 | 286 | @Test 287 | fun testGenres() { 288 | val result = wrapper.genres(apiCalypseQuery) 289 | assert(result.isNotEmpty()) 290 | } 291 | 292 | @Test 293 | fun testInvolvedCompanies() { 294 | val result = wrapper.involvedCompanies(apiCalypseQuery) 295 | assert(result.isNotEmpty()) 296 | } 297 | 298 | @Test 299 | fun testKeywords() { 300 | val result = wrapper.keywords(apiCalypseQuery) 301 | assert(result.isNotEmpty()) 302 | } 303 | 304 | @Test 305 | fun testMultiplayerModes() { 306 | val result = wrapper.multiplayerModes(apiCalypseQuery) 307 | assert(result.isNotEmpty()) 308 | } 309 | 310 | @Test 311 | fun testPlatforms() { 312 | val result = wrapper.platforms(apiCalypseQuery) 313 | assert(result.isNotEmpty()) 314 | } 315 | 316 | @Test 317 | fun testPlatformLogos() { 318 | val result = wrapper.platformLogos(apiCalypseQuery) 319 | assert(result.isNotEmpty()) 320 | } 321 | 322 | @Test 323 | fun testPlatformTypes() { 324 | val result = wrapper.platformTypes(apiCalypseQuery) 325 | assert(result.isNotEmpty()) 326 | } 327 | 328 | @Test 329 | fun testPlatformVersions() { 330 | val result = wrapper.platformVersions(apiCalypseQuery) 331 | assert(result.isNotEmpty()) 332 | } 333 | 334 | @Test 335 | fun testPlatformVerisonCompanies() { 336 | val result = wrapper.platformVersionCompanies(apiCalypseQuery) 337 | assert(result.isNotEmpty()) 338 | } 339 | 340 | @Test 341 | fun testPlatformVersionReleaseDates() { 342 | val result = wrapper.platformVersionReleaseDates(apiCalypseQuery) 343 | assert(result.isNotEmpty()) 344 | } 345 | 346 | @Test 347 | fun testPlatformWebsites() { 348 | val result = wrapper.platformWebsites(apiCalypseQuery) 349 | assert(result.isNotEmpty()) 350 | } 351 | 352 | @Test 353 | fun testPlayerPerspectives() { 354 | val result = wrapper.playerPerspectives(apiCalypseQuery) 355 | assert(result.isNotEmpty()) 356 | } 357 | 358 | @Test 359 | fun testProductFamilies() { 360 | val result = wrapper.platformFamilies(apiCalypseQuery) 361 | assert(result.isNotEmpty()) 362 | } 363 | 364 | @Test 365 | fun testRegions() { 366 | val result = wrapper.regions(apiCalypseQuery) 367 | assert(result.isNotEmpty()) 368 | } 369 | 370 | @Test 371 | fun testReleaseDates() { 372 | val result = wrapper.releaseDates(apiCalypseQuery) 373 | assert(result.isNotEmpty()) 374 | } 375 | 376 | @Test 377 | fun testReleaseDateRegions() { 378 | val result = wrapper.releaseDateRegions(apiCalypseQuery) 379 | assert(result.isNotEmpty()) 380 | } 381 | 382 | @Test 383 | fun testScreenshots() { 384 | val result = wrapper.screenshots(apiCalypseQuery) 385 | assert(result.isNotEmpty()) 386 | } 387 | 388 | @Test 389 | fun testSearch() { 390 | val result = wrapper.search(apiCalypseQuery) 391 | assert(result.isNotEmpty()) 392 | } 393 | 394 | @Test 395 | fun testThemes() { 396 | val result = wrapper.themes(apiCalypseQuery) 397 | assert(result.isNotEmpty()) 398 | } 399 | 400 | @Test 401 | fun testWebsites() { 402 | val result = wrapper.websites(apiCalypseQuery) 403 | assert(result.isNotEmpty()) 404 | } 405 | 406 | @Test 407 | fun testWebsiteTypes() { 408 | val result = wrapper.websiteTypes(apiCalypseQuery) 409 | assert(result.isNotEmpty()) 410 | } 411 | 412 | @Test 413 | fun testEvents() { 414 | val result = wrapper.events(apiCalypseQuery) 415 | assert(result.isNotEmpty()) 416 | } 417 | 418 | @Test 419 | fun testEventLogos() { 420 | val result = wrapper.eventLogos(apiCalypseQuery) 421 | assert(result.isNotEmpty()) 422 | } 423 | 424 | @Test 425 | fun testEventNetworks() { 426 | val result = wrapper.eventNetworks(apiCalypseQuery) 427 | assert(result.isNotEmpty()) 428 | } 429 | 430 | @Test 431 | fun testNetworkTypes() { 432 | val result = wrapper.networkTypes(apiCalypseQuery) 433 | assert(result.isNotEmpty()) 434 | } 435 | 436 | @Test 437 | fun testCollectionRelations() { 438 | val result = wrapper.collectionRelations(apiCalypseQuery) 439 | assert(result.isNotEmpty()) 440 | } 441 | 442 | @Test 443 | fun testCollectionRelationTypes() { 444 | val result = wrapper.collectionRelationTypes(apiCalypseQuery) 445 | assert(result.isNotEmpty()) 446 | } 447 | 448 | @Test 449 | fun testCollectionTypes() { 450 | val result = wrapper.collectionTypes(apiCalypseQuery) 451 | assert(result.isNotEmpty()) 452 | } 453 | 454 | @Test 455 | fun testCollectionMemberships() { 456 | val result = wrapper.collectionMemberships(apiCalypseQuery) 457 | assert(result.isNotEmpty()) 458 | } 459 | 460 | @Test 461 | fun testCollectionMembershipTypes() { 462 | val result = wrapper.collectionMembershipTypes(apiCalypseQuery) 463 | assert(result.isNotEmpty()) 464 | } 465 | 466 | @Test 467 | fun testPopularityTypes() { 468 | val result = wrapper.popularityTypes(APICalypse().fields("*")) 469 | assert(result.isNotEmpty()) 470 | assert(result.first().hasExternalPopularitySource()) 471 | } 472 | 473 | @Test 474 | fun testPopularityPrimitives() { 475 | val result = wrapper.popularityPrimitives(APICalypse().fields("*")) 476 | assert(result.isNotEmpty()) 477 | assert(result.first().hasExternalPopularitySource()) 478 | assert(result.first().hasCalculatedAt()) 479 | assert(result.first().value > 0) 480 | } 481 | 482 | } 483 | -------------------------------------------------------------------------------- /src/test/kotlin/com/api/igdb/TestProxy.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb 2 | 3 | import com.api.igdb.apicalypse.APICalypse 4 | import com.api.igdb.apicalypse.Sort 5 | import com.api.igdb.exceptions.RequestException 6 | import com.api.igdb.request.IGDBWrapper 7 | import com.api.igdb.request.games 8 | import com.api.igdb.request.search 9 | import org.junit.jupiter.api.BeforeEach 10 | import org.junit.jupiter.api.Test 11 | 12 | class TestProxy { 13 | 14 | private val wrapper = IGDBWrapper 15 | 16 | @BeforeEach 17 | fun setup() { 18 | wrapper.setupProxy(proxyURL = System.getenv("proxy_url"), proxyHeaders = mapOf("x-api-key" to System.getenv("proxy_api_key"))) 19 | } 20 | 21 | //Get all Coming Soon PS4 games 22 | @Test 23 | fun testComingSoonPS4Games() { 24 | val date = (System.currentTimeMillis() / 1000).toString() 25 | val query = APICalypse() 26 | .fields("*") 27 | .where("platforms = 48 & release_dates.date > $date") 28 | .sort("release_dates.date", Sort.ASCENDING) 29 | 30 | try { 31 | val ps4Games = wrapper.games(query) 32 | assert(ps4Games.isNotEmpty()) 33 | } catch (e: RequestException) { 34 | assert(false) 35 | } 36 | } 37 | 38 | //Get all Recently released PS4 games 39 | @Test 40 | fun testRecentlyReleasedPS4Games() { 41 | val date = (System.currentTimeMillis() / 1000).toString() 42 | val query = APICalypse() 43 | .fields("*") 44 | .where("platforms = 48 & release_dates.date < $date") 45 | .sort("release_dates.date", Sort.DESCENDING) 46 | 47 | try { 48 | val ps4Games = wrapper.games(query) 49 | assert(ps4Games.isNotEmpty()) 50 | } catch (e: RequestException) { 51 | assert(false) 52 | } 53 | } 54 | 55 | //Get all Recently released PS4 games 56 | @Test 57 | fun testSearch() { 58 | val query = APICalypse() 59 | .search("Assassins Creed") 60 | .fields("game.name,game.involved_companies") 61 | .where("game != null & game.version_parent = null") 62 | 63 | try { 64 | val result = wrapper.search(query) 65 | assert(result.isNotEmpty()) 66 | } catch (e: RequestException) { 67 | assert(false) 68 | } 69 | 70 | } 71 | 72 | //Get all Recently released PS4 games 73 | @Test 74 | fun testPS4Exclusives() { 75 | val query = APICalypse() 76 | .fields("name,category,platforms") 77 | .where("category = 0 & platforms = 48") 78 | 79 | try { 80 | val result = wrapper.games(query) 81 | assert(result.isNotEmpty()) 82 | } catch (e: RequestException) { 83 | assert(false) 84 | } 85 | 86 | } 87 | 88 | } -------------------------------------------------------------------------------- /src/test/kotlin/com/api/igdb/TestRequestException.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb 2 | 3 | import com.api.igdb.apicalypse.APICalypse 4 | import com.api.igdb.exceptions.RequestException 5 | import com.api.igdb.request.IGDBWrapper 6 | import com.api.igdb.request.games 7 | import com.api.igdb.request.jsonGameModes 8 | import org.junit.jupiter.api.Assertions 9 | import org.junit.jupiter.api.BeforeAll 10 | import org.junit.jupiter.api.BeforeEach 11 | import org.junit.jupiter.api.Test 12 | import org.junit.jupiter.api.TestInstance 13 | import org.junit.jupiter.api.assertThrows 14 | 15 | @TestInstance(TestInstance.Lifecycle.PER_CLASS) 16 | class TestRequestExceptions { 17 | private val wrapper = IGDBWrapper 18 | 19 | @BeforeAll 20 | internal fun beforeAll() { 21 | wrapper.setCredentials("", "") 22 | } 23 | 24 | @Test 25 | fun testNoKeyException() { 26 | try { 27 | wrapper.games(APICalypse()) 28 | } catch (e: RequestException){ 29 | Assertions.assertEquals(401, e.statusCode) 30 | } 31 | } 32 | 33 | @Test 34 | fun testException() { 35 | assertThrows { 36 | wrapper.jsonGameModes(APICalypse()) 37 | } 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/test/kotlin/com/api/igdb/TestTwitchTokenKotlin.kt: -------------------------------------------------------------------------------- 1 | package com.api.igdb 2 | 3 | import com.api.igdb.request.TwitchAuthenticator 4 | import org.junit.jupiter.api.Test 5 | import java.time.Duration 6 | 7 | class TestTwitchTokenKotlin { 8 | @Test 9 | fun testGetTwitchToken() { 10 | // request a new Twitch Authentication token 11 | val token = TwitchAuthenticator.requestTwitchToken(System.getenv("client_id"), System.getenv("client_secret")) 12 | 13 | assert(token != null) 14 | assert(token!!.expires_in > Duration.ofDays(57).toSeconds()) 15 | val tokenFutureDate = System.currentTimeMillis() + Duration.ofDays(57).toSeconds() 16 | assert(tokenFutureDate > token.getExpiresUnix()) 17 | } 18 | } --------------------------------------------------------------------------------