Skip to content

Commit

Permalink
V2 API Route (#251)
Browse files Browse the repository at this point in the history
* Bring in new database changes for extra player stats.

* Fix Dockerfile to avoid potential COPY errors.

* Begin refactor for extra stats as playerstats is too large of a file.

* Update DB layout.

Begin extra stats documentation.

* Include new extra stats route and non-live gets.

* Finish CRUD operations. Move onto new API implementation for OnPlayerDeath?

* Bring in initial start of call for plugin.

Update database to use actual steam IDs and whatnot.

* Implement additional stat carry over. Needs to be tested.

* Include typescript generation for v2 api.

Remove extra player stats from legacy api since they were not finished.

Update serverrcon.js
- Breakout packet handling to its own function.
- Check version for 0.14 or higher. TBD if we can use 0.13.
- Set log and backup URLs and keys to use API keys.
- Fix formatting

Update prodrun to point to dist for compiled js.

* Update deps and include types from docs.

* Massive refactor of code to follow a better folder structure.

Everything mainly in src now, types in types, services (like db and various service calls to database) in services, etc.

Bring in start of finding API key and match id. These will be checked before being sent off to different cases.

* Continue on rewiring tests.

* Tests working, application not.

* Tests passing and app launching!

* OnSeriesResult implemented.

Removed OnSeriesInit as it is not needed.

Forfeits are not implemented, but may not be needed right now, can check on round end instead and update as needed.

* Fix up some comments.

Finish map and series finishing.

Start on pick/ban updates.

* Bring in team ID in the match configs since it's supported.

Update mapupdate to not use team ids from database.

Update various TS calls to user lowercase identifiers.

* Veto updates and side selection complete.

* Properly tag releases on push with version number as well.

* Finish series flow service.

Adjust imports on map flow service.

Update api.ts to include new cases for the series flow.

* OnGoingLive implemented.

* Update the player stat extras table.

Include OnPlayerDeath and OnMatchPaused and OnMatchUnpaused.

Update serverrcon to include demo, logs, and backups.

Update match creation to get version number if we select a server.

* Include bomb plant and defuse events from game server to API calls.

Since these are game specific, we will not create public API calls for this.

* Finish map and series flows.

Update github actions to deploy next and version tag.

Begin work on demo uploads.

* Change docker tags to use latest and next for now.

* Docker debugging.

Update package json version.

* Add in demo API.

Update leaderboard swagger to add success option.

Consider moving components to their own JS files for easier typing and location.

* Bring in remote backup API calls.

* Update JSDocs.

Include more docs for the MapFlowService.

* Fix error with incomplete packets call.

* Fix server rcon values not being respected in strings.

Fix match registering version numbers for get5.

* Delete match from database if we fail to load on the server.

This should fix the bug of multiple matches being generated with the same server.

Only update game server if the server is alive and available as well.

* Update README.md

* Update workflow to push next on any branch but version only on final release.

Update README.
  • Loading branch information
PhlexPlexico authored Jun 23, 2023
1 parent 3b4c815 commit c92bfb7
Show file tree
Hide file tree
Showing 96 changed files with 6,112 additions and 1,470 deletions.
21 changes: 16 additions & 5 deletions .github/workflows/ghcr.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
name: publish to ghcr
name: Publish to GHCR
on:
workflow_dispatch:
push:
branches:
- master
- '**'
jobs:
push:
name: "Create build and push to GHCR"
name: Create build and push to GHCR
runs-on: ubuntu-latest
strategy:
fail-fast: false
Expand All @@ -30,12 +30,23 @@ jobs:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- id: getversion
uses: Saionaro/[email protected]
- uses: docker/[email protected]
if: github.ref != 'refs/heads/master'
with:
context: .
file: Dockerfile
platforms: linux/amd64,linux/arm/v7,linux/arm64/v8
push: true
tags: |
ghcr.io/${{ steps.string.outputs.lowercase }}/g5api:latest
ghcr.io/${{ steps.string.outputs.lowercase }}/g5api:next
- uses: docker/[email protected]
if: github.ref == 'refs/heads/master'
with:
context: .
file: Dockerfile
platforms: linux/amd64,linux/arm/v7,linux/arm64/v8
push: true
tags: |
ghcr.io/${{ steps.string.outputs.lowercase }}/g5api:latest,ghcr.io/${{ steps.string.outputs.lowercase }}/g5api:${{ steps.getversion.outputs.version }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
dist/
node_modules/
config/production.json*
config/development.json*
Expand Down
6 changes: 2 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@ RUN apk add gettext python3 build-base
EXPOSE 3301
# clone and move into Get5API folder
WORKDIR /Get5API
COPY package*.json .
COPY yarn.lock .
RUN yarn

COPY . .
RUN yarn
RUN yarn build

# set config with env variables, build, and run application
CMD envsubst < /Get5API/config/production.json.template > /Get5API/config/production.json && \
Expand Down
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,18 @@ G5API is an API that will allow users to create, manage, and control Counter-Str

This API is complete enough to provide the most functionality out of [get5](https://github.com/splewis/get5).

For the plugin [G5WS](https://github.com/PhlexPlexico/G5WS), the routes currently put into place located in the `./routes/legacy/` and still point to `/match/` on this app.
<details closed>
<summary><b>Note:</b> While available for backwards compatibility, it is recommended you use the <i>latest</i> version of get5, as you will no longer need an additional plugin for enhanced reporting. The only extension needed is SteamWorks. </summary>
<br>


For the plugin [G5WS](https://github.com/PhlexPlexico/G5WS"), the routes currently put into place located in the `./src/routes/legacy/` and still point to `/match/` on this app.
</details>

Game server interaction will still take place under the `/matches/:match_id` directive, but the logic can be found under `./matches/matchserver.js`.

The webapi plugin for this can be downloaded from [here](https://github.com/PhlexPlexico/G5WS) to include the use of vetoes being recorded, as well as demoes being uploaded to the API server once the match is complete.
If you are using get5 0.14 or later, the G5WS plugin is **not** needed, and should be removed or disabled from your game server to avoid any conflicting actions. The new routes are located in `./src/routes/v2`, and the main logic can be found in their respective services under `./src/services`

Game server interaction will still take place under the `/matches/:match_id` directive, but the logic can be found under `./matches/matchserver.js`.

There is also Challonge integration within the API. If a user provides a tournament ID to create a season, it will auto-fill a season start date, empty teams, and will auto-update the brackets at the end of each match if the match exists under the Season/Tournament.

Expand Down Expand Up @@ -108,7 +115,7 @@ For more details on these variables, follow along with production.json.template
### Docs:
```yarn doc```

This will generate all the API information that I've created in the app, in the hopes of making it more readable and easier to pickup for anyone who wants to try more implementation, or even creating a front-end for this API. Swagger Express is also included, which can be accessed from `/api-docs` on application launch. This will house all the API calls, where JSDocs will show all the internal function calls in this application.
This will generate all the API information that I've created in the app, in the hopes of making it more readable and easier to pickup for anyone who wants to try implementing more actions, or even creating a front-end for this API. Swagger Express is also included, which can be accessed from `/api-docs` on application launch. This will house all the API calls, where JSDocs will show all the internal function calls in this application. All TypeScript functions will be shown in the JSDocs.

### Coverage Tests
Steam OAuth will be mocked in order to check if a user is "logged in", and create a temporary database (`get5test`) that will insert new values, and check various features of routes. If you wish to alter the "user" it authenticates as, you can edit `utility/mockProfile.js` to the values you prefer.
Expand Down
2 changes: 1 addition & 1 deletion __test__/users.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { agent } from 'supertest';
import app from '../app.js';
import app from '../app.js'
const request = agent(app);
let adminCheck = 0;

Expand Down
60 changes: 29 additions & 31 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,25 @@ import swaggerJSDoc from "swagger-jsdoc";
import { serve, setup } from "swagger-ui-express";

// Route Files
import indexRouter from "./routes/index.js";
import leaderboardRouter from "./routes/leaderboard.js";
import legacyAPICalls from "./routes/legacy/api.js";
import mapListRouter from "./routes/maps.js";
import mapstatsRouter from "./routes/mapstats.js";
import matchesRouter from "./routes/matches/matches.js";
import matchServerRouter from "./routes/matches/matchserver.js";
import playerstatsRouter from "./routes/playerstats.js";
import seasonsRouter from "./routes/seasons.js";
import serversRouter from "./routes/servers.js";
import teamsRouter from "./routes/teams.js";
import usersRouter from "./routes/users.js";
import vetoesRouter from "./routes/vetoes.js";
import vetosidesRouter from "./routes/vetosides.js";
import passport from "./utility/auth.js";
import indexRouter from "./src/routes/index.js";
import leaderboardRouter from "./src/routes/leaderboard.js";
import legacyAPICalls from "./src/routes/legacy/api.js";
import mapListRouter from "./src/routes/maps.js";
import mapstatsRouter from "./src/routes/mapstats.js";
import matchesRouter from "./src/routes/matches/matches.js";
import matchServerRouter from "./src/routes/matches/matchserver.js";
import playerstatsRouter from "./src/routes/playerstats/playerstats.js";
import playerstatsextraRouter from "./src/routes/playerstats/extrastats.js";
import seasonsRouter from "./src/routes/seasons.js";
import serversRouter from "./src/routes/servers.js";
import teamsRouter from "./src/routes/teams.js";
import usersRouter from "./src/routes/users.js";
import vetoesRouter from "./src/routes/vetoes.js";
import vetosidesRouter from "./src/routes/vetosides.js";
import passport from "./src/utility/auth.js";
import {router as v2Router} from "./src/routes/v2/api.js";
import {router as v2DemoRouter} from "./src/routes/v2/demoapi.js";
import { router as v2BackupRouter } from "./src/routes/v2/backupapi.js";
// End Route Files


Expand Down Expand Up @@ -112,25 +116,15 @@ const options = {
openapi: "3.0.0", // Specification (optional, defaults to swagger: '2.0')
info: {
title: "G5API", // Title (required)
version: "1.7.0", // Version (required)
},
version: "2.0.0" // Version (required)
}
},
// Path to the API docs
apis: [
"./routes/leaderboard.js",
"./routes/legacy/api.js",
"./routes/matches/matches.js",
"./routes/matches/matchserver.js",
"./routes/maps.js",
"./routes/mapstats.js",
"./routes/playerstats.js",
"./routes/seasons.js",
"./routes/servers.js",
"./routes/teams.js",
"./routes/users.js",
"./routes/vetoes.js",
"./routes/vetosides.js",
],
"./dist/src/routes/**/*.js",
"./dist/src/services/**/*.js",
"./dist/src/routes/*.js"
]
};
const swaggerSpec = swaggerJSDoc(options);

Expand All @@ -148,10 +142,14 @@ app.use("/vetosides", vetosidesRouter);
app.use("/matches", matchesRouter, matchServerRouter);
app.use("/mapstats", mapstatsRouter);
app.use("/playerstats", playerstatsRouter);
app.use("/playerstatsextra", playerstatsextraRouter);
app.use("/seasons", seasonsRouter);
app.use("/match", legacyAPICalls);
app.use("/leaderboard", leaderboardRouter);
app.use("/maps", mapListRouter);
app.use("/v2", v2Router);
app.use("/v2/demo", v2DemoRouter);
app.use("/v2/backup", v2BackupRouter);
// END ROUTES

// Steam API Calls.
Expand Down
5 changes: 5 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};
3 changes: 3 additions & 0 deletions jest_config/jest.gameservers.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// https://jestjs.io/docs/en/configuration.html
process.env.NODE_ENV = "test";
module.exports = {
preset: 'ts-jest/presets/js-with-ts-esm',
// A path to a custom resolver
resolver: "jest-ts-webcompat-resolver",
// All imported modules in your tests should be mocked automatically
// automock: false,

Expand Down
3 changes: 3 additions & 0 deletions jest_config/jest.maplist.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// https://jestjs.io/docs/en/configuration.html
process.env.NODE_ENV = "test";
module.exports = {
preset: 'ts-jest/presets/js-with-ts-esm',
// A path to a custom resolver
resolver: "jest-ts-webcompat-resolver",
// All imported modules in your tests should be mocked automatically
// automock: false,

Expand Down
3 changes: 3 additions & 0 deletions jest_config/jest.mapstats.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// https://jestjs.io/docs/en/configuration.html
process.env.NODE_ENV = "test";
module.exports = {
preset: 'ts-jest/presets/js-with-ts-esm',
// A path to a custom resolver
resolver: "jest-ts-webcompat-resolver",
// All imported modules in your tests should be mocked automatically
// automock: false,

Expand Down
3 changes: 3 additions & 0 deletions jest_config/jest.matches.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// https://jestjs.io/docs/en/configuration.html
process.env.NODE_ENV = "test";
module.exports = {
preset: 'ts-jest/presets/js-with-ts-esm',
// A path to a custom resolver
resolver: "jest-ts-webcompat-resolver",
// All imported modules in your tests should be mocked automatically
// automock: false,

Expand Down
3 changes: 3 additions & 0 deletions jest_config/jest.playerstats.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// https://jestjs.io/docs/en/configuration.html
process.env.NODE_ENV = "test";
module.exports = {
preset: 'ts-jest/presets/js-with-ts-esm',
// A path to a custom resolver
resolver: "jest-ts-webcompat-resolver",
// All imported modules in your tests should be mocked automatically
// automock: false,

Expand Down
3 changes: 3 additions & 0 deletions jest_config/jest.seasons.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// https://jestjs.io/docs/en/configuration.html
process.env.NODE_ENV = "test";
module.exports = {
preset: 'ts-jest/presets/js-with-ts-esm',
// A path to a custom resolver
resolver: "jest-ts-webcompat-resolver",
// All imported modules in your tests should be mocked automatically
// automock: false,

Expand Down
3 changes: 3 additions & 0 deletions jest_config/jest.teams.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// https://jestjs.io/docs/en/configuration.html
process.env.NODE_ENV = "test";
module.exports = {
preset: 'ts-jest/presets/js-with-ts-esm',
// A path to a custom resolver
resolver: "jest-ts-webcompat-resolver",
// All imported modules in your tests should be mocked automatically
// automock: false,

Expand Down
23 changes: 17 additions & 6 deletions jest_config/jest.users.config.cjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
// For a detailed explanation regarding each configuration property, visit:
// https://jestjs.io/docs/en/configuration.html
process.env.NODE_ENV = "test";
module.exports = {
preset: 'ts-jest/presets/js-with-ts-esm',
// A path to a custom resolver
resolver: "jest-ts-webcompat-resolver",
// All imported modules in your tests should be mocked automatically
// automock: false,

Expand Down Expand Up @@ -58,7 +62,9 @@ module.exports = {
globalTeardown: "./test-teardown-globals.cjs",

// A set of global variables that need to be available in all test environments
// globals: {},
// globals: {
// extensionsToTreatAsEsm: ['.ts', '.js']
// },

// The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
// maxWorkers: "50%",
Expand All @@ -71,11 +77,14 @@ module.exports = {
// An array of file extensions your modules use
moduleFileExtensions: [
"js",
"cjs"
"cjs",
"ts"
],

// A map from regular expressions to module names that allow to stub out resources with a single module
// moduleNameMapper: {},
moduleNameMapper: {

},

// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
// modulePathIgnorePatterns: [],
Expand All @@ -101,8 +110,6 @@ module.exports = {
// Reset the module registry before running each individual test
// resetModules: false,

// A path to a custom resolver
// resolver: undefined,

// Automatically restore mock state between every test
// restoreMocks: false,
Expand Down Expand Up @@ -162,7 +169,11 @@ module.exports = {
// timers: "real",

// A map from regular expressions to paths to transformers
// transform: undefined,
// transform: {'\\.[jt]sx?$': ['ts-jest', { useESM: true }] },
// moduleNameMapper: {
// '(.+)\\.js': '$1'
// },
// extensionsToTreatAsEsm: ['.ts'],

// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
// transformIgnorePatterns: [
Expand Down
3 changes: 3 additions & 0 deletions jest_config/jest.vetoes.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// https://jestjs.io/docs/en/configuration.html
process.env.NODE_ENV = "test";
module.exports = {
preset: 'ts-jest/presets/js-with-ts-esm',
// A path to a custom resolver
resolver: "jest-ts-webcompat-resolver",
// All imported modules in your tests should be mocked automatically
// automock: false,

Expand Down
3 changes: 3 additions & 0 deletions jest_config/jest.vetosides.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// https://jestjs.io/docs/en/configuration.html
process.env.NODE_ENV = "test";
module.exports = {
preset: 'ts-jest/presets/js-with-ts-esm',
// A path to a custom resolver
resolver: "jest-ts-webcompat-resolver",
// All imported modules in your tests should be mocked automatically
// automock: false,

Expand Down
2 changes: 1 addition & 1 deletion jsdoc.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"dictionaries": ["jsdoc","closure"]
},
"source": {
"include": ["routes"],
"include": ["dist/src"],
"includePattern": ".+\\.js(doc|x)?$",
"excludePattern": "(^|\\/|\\\\)_"
},
Expand Down
27 changes: 0 additions & 27 deletions migrations/20220907171148-get5db.js

This file was deleted.

Loading

0 comments on commit c92bfb7

Please sign in to comment.