Compare commits
65 Commits
v1.7.1
...
branch-v1.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9922e61b44 | ||
![]() |
98a09c32f8 | ||
![]() |
81b58e9b9f | ||
![]() |
928a1538ea | ||
![]() |
f4a8892cbb | ||
![]() |
c4435628e0 | ||
![]() |
933c624885 | ||
![]() |
06e344c74a | ||
![]() |
9150ce7377 | ||
![]() |
08a40e3dd9 | ||
![]() |
d7fca42057 | ||
![]() |
1672520a29 | ||
![]() |
3366d926f4 | ||
![]() |
6d7f6f63c6 | ||
![]() |
590a7829b1 | ||
![]() |
ae75fc1490 | ||
![]() |
0c645d04aa | ||
![]() |
13b3764fcf | ||
![]() |
57d4fe7cf9 | ||
![]() |
8519d4c745 | ||
![]() |
822a40b61b | ||
![]() |
b463bb6064 | ||
![]() |
3e8696e6e8 | ||
![]() |
d1f157ac08 | ||
![]() |
30be179367 | ||
![]() |
787bb47bd3 | ||
![]() |
ccf9afd561 | ||
![]() |
c7b6233ad6 | ||
![]() |
afb72c3d74 | ||
![]() |
299e24793f | ||
![]() |
de9b9bf706 | ||
![]() |
28bc50a82e | ||
![]() |
f9f65f3ffb | ||
![]() |
87f3a1aa89 | ||
![]() |
b3e7696292 | ||
![]() |
29c685c791 | ||
![]() |
f0020e5b1f | ||
![]() |
3897ed65ef | ||
![]() |
cebab38dd6 | ||
![]() |
fd7b354571 | ||
![]() |
be1d53b3b1 | ||
![]() |
e0cff36819 | ||
![]() |
cea654692e | ||
![]() |
c82ffb6c97 | ||
![]() |
7400a8c040 | ||
![]() |
eda171efa1 | ||
![]() |
f881459c0b | ||
![]() |
69da6ee346 | ||
![]() |
f85109abd2 | ||
![]() |
59173d8ae5 | ||
![]() |
178f70cb98 | ||
![]() |
080a823cda | ||
![]() |
60dbaf85a4 | ||
![]() |
8a80274030 | ||
![]() |
7e8679151b | ||
![]() |
123239cf58 | ||
![]() |
04419383aa | ||
![]() |
0bef298abf | ||
![]() |
a4d581b369 | ||
![]() |
16cb0c89dc | ||
![]() |
95b52c47dd | ||
![]() |
b1056299b8 | ||
![]() |
14c5761959 | ||
![]() |
d7b3711be6 | ||
![]() |
111c501911 |
@@ -1,6 +1,10 @@
|
|||||||
FROM mcr.microsoft.com/devcontainers/dotnet:1-8.0-bookworm
|
FROM mcr.microsoft.com/devcontainers/dotnet:1-8.0-bookworm
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y p7zip-full
|
# update apt-get
|
||||||
RUN mkdir -p /workspace/gaseous-server/wwwroot/emulators/EmulatorJS
|
RUN apt-get update
|
||||||
RUN wget https://cdn.emulatorjs.org/releases/4.0.11.7z
|
|
||||||
RUN 7z x -y -o/workspace/gaseous-server/wwwroot/emulators/EmulatorJS 4.0.11.7z
|
# download and unzip EmulatorJS from CDN
|
||||||
|
RUN apt-get install -y p7zip-full
|
||||||
|
RUN mkdir -p out/wwwroot/emulators/EmulatorJS
|
||||||
|
RUN wget https://cdn.emulatorjs.org/releases/4.1.1.7z
|
||||||
|
RUN 7z x -y -oout/wwwroot/emulators/EmulatorJS 4.1.1.7z
|
@@ -9,9 +9,14 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
docker:
|
docker:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
packages: write
|
||||||
|
contents: read
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: 'true'
|
submodules: 'true'
|
||||||
- name: Install dotnet tool
|
- name: Install dotnet tool
|
||||||
@@ -21,18 +26,37 @@ jobs:
|
|||||||
- name: Sign in to Nuget
|
- name: Sign in to Nuget
|
||||||
run: dotnet nuget add source --username michael-j-green --password ${{ secrets.NUGETKEY }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/gaseous-project/index.json"
|
run: dotnet nuget add source --username michael-j-green --password ${{ secrets.NUGETKEY }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/gaseous-project/index.json"
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v2
|
uses: docker/setup-qemu-action@v3
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v3
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
- name: Build and push
|
- name: Login to GitHub Package Registry
|
||||||
uses: docker/build-push-action@v4
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Build and push standard image
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
|
file: ./build/Dockerfile
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
push: true
|
push: true
|
||||||
tags: gaseousgames/gaseousserver:${{ github.ref_name}}
|
tags: |
|
||||||
|
gaseousgames/gaseousserver:${{ github.ref_name}}
|
||||||
|
ghcr.io/gaseous-project/gaseousserver:${{ github.ref_name}}
|
||||||
|
- name: Build and push image with embedded mariadb
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./build/Dockerfile-EmbeddedDB
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
gaseousgames/gaseousserver:${{ github.ref_name}}-embeddeddb
|
||||||
|
ghcr.io/gaseous-project/gaseousserver:${{ github.ref_name}}-embeddeddb
|
||||||
|
42
.github/workflows/BuildDockerOnTag-Release.yml
vendored
42
.github/workflows/BuildDockerOnTag-Release.yml
vendored
@@ -8,9 +8,14 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
docker:
|
docker:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
packages: write
|
||||||
|
contents: read
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: 'true'
|
submodules: 'true'
|
||||||
- name: Install dotnet tool
|
- name: Install dotnet tool
|
||||||
@@ -20,18 +25,41 @@ jobs:
|
|||||||
- name: Sign in to Nuget
|
- name: Sign in to Nuget
|
||||||
run: dotnet nuget add source --username michael-j-green --password ${{ secrets.NUGETKEY }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/gaseous-project/index.json"
|
run: dotnet nuget add source --username michael-j-green --password ${{ secrets.NUGETKEY }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/gaseous-project/index.json"
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v2
|
uses: docker/setup-qemu-action@v3
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v3
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
- name: Build and push
|
- name: Login to GitHub Package Registry
|
||||||
uses: docker/build-push-action@v4
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Build and push standard image
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
|
file: ./build/Dockerfile
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
push: true
|
push: true
|
||||||
tags: gaseousgames/gaseousserver:latest,gaseousgames/gaseousserver:${{ github.ref_name}}
|
tags: |
|
||||||
|
gaseousgames/gaseousserver:latest
|
||||||
|
gaseousgames/gaseousserver:${{ github.ref_name}}
|
||||||
|
ghcr.io/gaseous-project/gaseousserver:latest
|
||||||
|
ghcr.io/gaseous-project/gaseousserver:${{ github.ref_name}}
|
||||||
|
- name: Build and push image with embedded mariadb
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./build/Dockerfile-EmbeddedDB
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
gaseousgames/gaseousserver:latest-embeddeddb
|
||||||
|
gaseousgames/gaseousserver:${{ github.ref_name}}-embeddeddb
|
||||||
|
ghcr.io/gaseous-project/gaseousserver:latest-embeddeddb
|
||||||
|
ghcr.io/gaseous-project/gaseousserver:${{ github.ref_name}}-embeddeddb
|
||||||
|
13
.github/workflows/BuildOnTestBranch.yml
vendored
13
.github/workflows/BuildOnTestBranch.yml
vendored
@@ -27,10 +27,19 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
- name: Build and push
|
- name: Build and push standard image
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
|
file: ./build/Dockerfile
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
push: true
|
push: true
|
||||||
tags: gaseousgames/test:latest
|
tags: gaseousgames/test:latest
|
||||||
|
- name: Build and push image with embedded mariadb
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./build/Dockerfile-EmbeddedDB
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: gaseousgames/test:latest-embeddeddb
|
85
.github/workflows/codeql.yml
vendored
85
.github/workflows/codeql.yml
vendored
@@ -1,85 +0,0 @@
|
|||||||
# For most projects, this workflow file will not need changing; you simply need
|
|
||||||
# to commit it to your repository.
|
|
||||||
#
|
|
||||||
# You may wish to alter this file to override the set of languages analyzed,
|
|
||||||
# or to provide custom queries or build logic.
|
|
||||||
#
|
|
||||||
# ******** NOTE ********
|
|
||||||
# We have attempted to detect the languages in your repository. Please check
|
|
||||||
# the `language` matrix defined below to confirm you have the correct set of
|
|
||||||
# supported CodeQL languages.
|
|
||||||
#
|
|
||||||
name: "CodeQL"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "main", "branch-v*.*.*" ]
|
|
||||||
pull_request:
|
|
||||||
# The branches below must be a subset of the branches above
|
|
||||||
branches: [ "main" ]
|
|
||||||
schedule:
|
|
||||||
- cron: '21 11 * * 2'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
analyze:
|
|
||||||
name: Analyze
|
|
||||||
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
|
||||||
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
|
||||||
# - https://gh.io/supported-runners-and-hardware-resources
|
|
||||||
# - https://gh.io/using-larger-runners
|
|
||||||
# Consider using larger runners for possible analysis time improvements.
|
|
||||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
|
||||||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
contents: read
|
|
||||||
security-events: write
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
language: [ 'csharp', 'javascript' ]
|
|
||||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ]
|
|
||||||
# Use only 'java' to analyze code written in Java, Kotlin or both
|
|
||||||
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
|
|
||||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Sign in to Nuget
|
|
||||||
run: dotnet nuget add source --username michael-j-green --password ${{ secrets.NUGETKEY }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/gaseous-project/index.json"
|
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@v2
|
|
||||||
with:
|
|
||||||
languages: ${{ matrix.language }}
|
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
|
||||||
# By default, queries listed here will override any specified in a config file.
|
|
||||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
|
||||||
|
|
||||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
|
||||||
# queries: security-extended,security-and-quality
|
|
||||||
|
|
||||||
|
|
||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
|
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
|
||||||
- name: Autobuild
|
|
||||||
uses: github/codeql-action/autobuild@v2
|
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
|
||||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
|
||||||
|
|
||||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
|
||||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
|
||||||
|
|
||||||
# - run: |
|
|
||||||
# echo "Run, Build Application using script"
|
|
||||||
# ./location_of_script_within_repo/buildscript.sh
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@v2
|
|
||||||
with:
|
|
||||||
category: "/language:${{matrix.language}}"
|
|
3
.vscode/launch.json
vendored
3
.vscode/launch.json
vendored
@@ -24,7 +24,8 @@
|
|||||||
},
|
},
|
||||||
"sourceFileMap": {
|
"sourceFileMap": {
|
||||||
"/Views": "${workspaceFolder}/Views"
|
"/Views": "${workspaceFolder}/Views"
|
||||||
}
|
},
|
||||||
|
"enableStepFiltering": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": ".NET Core Attach",
|
"name": ".NET Core Attach",
|
||||||
|
20
Gaseous.sln
20
Gaseous.sln
@@ -1,4 +1,4 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 16
|
# Visual Studio Version 16
|
||||||
VisualStudioVersion = 25.0.1704.4
|
VisualStudioVersion = 25.0.1704.4
|
||||||
@@ -27,30 +27,18 @@ Global
|
|||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{08699C93-15CD-4E39-9053-D3C8056CE938}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{08699C93-15CD-4E39-9053-D3C8056CE938}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{08699C93-15CD-4E39-9053-D3C8056CE938}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{08699C93-15CD-4E39-9053-D3C8056CE938}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{FFCEC386-033F-4772-A45B-D33579F2E5EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{FFCEC386-033F-4772-A45B-D33579F2E5EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{FFCEC386-033F-4772-A45B-D33579F2E5EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{FFCEC386-033F-4772-A45B-D33579F2E5EE}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
{A01D2EFF-C82E-473B-84D7-7C25E736F5D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{B07A4655-A003-416B-A790-ADAA5B548E1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{B07A4655-A003-416B-A790-ADAA5B548E1A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{B07A4655-A003-416B-A790-ADAA5B548E1A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{B07A4655-A003-416B-A790-ADAA5B548E1A}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {979BF092-AFBC-4F19-B55F-32E73959BD1A}
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{F1A847C7-57BC-4DA9-8F83-CD060A7F5122} = {17FA6F12-8532-420C-9489-CB8FDE42137C}
|
{F1A847C7-57BC-4DA9-8F83-CD060A7F5122} = {17FA6F12-8532-420C-9489-CB8FDE42137C}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {979BF092-AFBC-4F19-B55F-32E73959BD1A}
|
||||||
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
149
LICENSE
149
LICENSE
@@ -1,5 +1,5 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
Version 3, 29 June 2007
|
Version 3, 19 November 2007
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
@@ -7,17 +7,15 @@
|
|||||||
|
|
||||||
Preamble
|
Preamble
|
||||||
|
|
||||||
The GNU General Public License is a free, copyleft license for
|
The GNU Affero General Public License is a free, copyleft license for
|
||||||
software and other kinds of works.
|
software and other kinds of works, specifically designed to ensure
|
||||||
|
cooperation with the community in the case of network server software.
|
||||||
|
|
||||||
The licenses for most software and other practical works are designed
|
The licenses for most software and other practical works are designed
|
||||||
to take away your freedom to share and change the works. By contrast,
|
to take away your freedom to share and change the works. By contrast,
|
||||||
the GNU General Public License is intended to guarantee your freedom to
|
our General Public Licenses are intended to guarantee your freedom to
|
||||||
share and change all versions of a program--to make sure it remains free
|
share and change all versions of a program--to make sure it remains free
|
||||||
software for all its users. We, the Free Software Foundation, use the
|
software for all its users.
|
||||||
GNU General Public License for most of our software; it applies also to
|
|
||||||
any other work released this way by its authors. You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
When we speak of free software, we are referring to freedom, not
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
@@ -26,44 +24,34 @@ them if you wish), that you receive source code or can get it if you
|
|||||||
want it, that you can change the software or use pieces of it in new
|
want it, that you can change the software or use pieces of it in new
|
||||||
free programs, and that you know you can do these things.
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
To protect your rights, we need to prevent others from denying you
|
Developers that use our General Public Licenses protect your rights
|
||||||
these rights or asking you to surrender the rights. Therefore, you have
|
with two steps: (1) assert copyright on the software, and (2) offer
|
||||||
certain responsibilities if you distribute copies of the software, or if
|
you this License which gives you legal permission to copy, distribute
|
||||||
you modify it: responsibilities to respect the freedom of others.
|
and/or modify the software.
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
A secondary benefit of defending all users' freedom is that
|
||||||
gratis or for a fee, you must pass on to the recipients the same
|
improvements made in alternate versions of the program, if they
|
||||||
freedoms that you received. You must make sure that they, too, receive
|
receive widespread use, become available for other developers to
|
||||||
or can get the source code. And you must show them these terms so they
|
incorporate. Many developers of free software are heartened and
|
||||||
know their rights.
|
encouraged by the resulting cooperation. However, in the case of
|
||||||
|
software used on network servers, this result may fail to come about.
|
||||||
|
The GNU General Public License permits making a modified version and
|
||||||
|
letting the public access it on a server without ever releasing its
|
||||||
|
source code to the public.
|
||||||
|
|
||||||
Developers that use the GNU GPL protect your rights with two steps:
|
The GNU Affero General Public License is designed specifically to
|
||||||
(1) assert copyright on the software, and (2) offer you this License
|
ensure that, in such cases, the modified source code becomes available
|
||||||
giving you legal permission to copy, distribute and/or modify it.
|
to the community. It requires the operator of a network server to
|
||||||
|
provide the source code of the modified version running there to the
|
||||||
|
users of that server. Therefore, public use of a modified version, on
|
||||||
|
a publicly accessible server, gives the public access to the source
|
||||||
|
code of the modified version.
|
||||||
|
|
||||||
For the developers' and authors' protection, the GPL clearly explains
|
An older license, called the Affero General Public License and
|
||||||
that there is no warranty for this free software. For both users' and
|
published by Affero, was designed to accomplish similar goals. This is
|
||||||
authors' sake, the GPL requires that modified versions be marked as
|
a different license, not a version of the Affero GPL, but Affero has
|
||||||
changed, so that their problems will not be attributed erroneously to
|
released a new version of the Affero GPL which permits relicensing under
|
||||||
authors of previous versions.
|
this license.
|
||||||
|
|
||||||
Some devices are designed to deny users access to install or run
|
|
||||||
modified versions of the software inside them, although the manufacturer
|
|
||||||
can do so. This is fundamentally incompatible with the aim of
|
|
||||||
protecting users' freedom to change the software. The systematic
|
|
||||||
pattern of such abuse occurs in the area of products for individuals to
|
|
||||||
use, which is precisely where it is most unacceptable. Therefore, we
|
|
||||||
have designed this version of the GPL to prohibit the practice for those
|
|
||||||
products. If such problems arise substantially in other domains, we
|
|
||||||
stand ready to extend this provision to those domains in future versions
|
|
||||||
of the GPL, as needed to protect the freedom of users.
|
|
||||||
|
|
||||||
Finally, every program is threatened constantly by software patents.
|
|
||||||
States should not allow patents to restrict development and use of
|
|
||||||
software on general-purpose computers, but in those that do, we wish to
|
|
||||||
avoid the special danger that patents applied to a free program could
|
|
||||||
make it effectively proprietary. To prevent this, the GPL assures that
|
|
||||||
patents cannot be used to render the program non-free.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
The precise terms and conditions for copying, distribution and
|
||||||
modification follow.
|
modification follow.
|
||||||
@@ -72,7 +60,7 @@ modification follow.
|
|||||||
|
|
||||||
0. Definitions.
|
0. Definitions.
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU General Public License.
|
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
works, such as semiconductor masks.
|
works, such as semiconductor masks.
|
||||||
@@ -549,35 +537,45 @@ to collect a royalty for further conveying from those to whom you convey
|
|||||||
the Program, the only way you could satisfy both those terms and this
|
the Program, the only way you could satisfy both those terms and this
|
||||||
License would be to refrain entirely from conveying the Program.
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
13. Use with the GNU Affero General Public License.
|
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, if you modify the
|
||||||
|
Program, your modified version must prominently offer all users
|
||||||
|
interacting with it remotely through a computer network (if your version
|
||||||
|
supports such interaction) an opportunity to receive the Corresponding
|
||||||
|
Source of your version by providing access to the Corresponding Source
|
||||||
|
from a network server at no charge, through some standard or customary
|
||||||
|
means of facilitating copying of software. This Corresponding Source
|
||||||
|
shall include the Corresponding Source for any work covered by version 3
|
||||||
|
of the GNU General Public License that is incorporated pursuant to the
|
||||||
|
following paragraph.
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
Notwithstanding any other provision of this License, you have
|
||||||
permission to link or combine any covered work with a work licensed
|
permission to link or combine any covered work with a work licensed
|
||||||
under version 3 of the GNU Affero General Public License into a single
|
under version 3 of the GNU General Public License into a single
|
||||||
combined work, and to convey the resulting work. The terms of this
|
combined work, and to convey the resulting work. The terms of this
|
||||||
License will continue to apply to the part which is the covered work,
|
License will continue to apply to the part which is the covered work,
|
||||||
but the special requirements of the GNU Affero General Public License,
|
but the work with which it is combined will remain governed by version
|
||||||
section 13, concerning interaction through a network will apply to the
|
3 of the GNU General Public License.
|
||||||
combination as such.
|
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
the GNU General Public License from time to time. Such new versions will
|
the GNU Affero General Public License from time to time. Such new versions
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
will be similar in spirit to the present version, but may differ in detail to
|
||||||
address new problems or concerns.
|
address new problems or concerns.
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
Each version is given a distinguishing version number. If the
|
||||||
Program specifies that a certain numbered version of the GNU General
|
Program specifies that a certain numbered version of the GNU Affero General
|
||||||
Public License "or any later version" applies to it, you have the
|
Public License "or any later version" applies to it, you have the
|
||||||
option of following the terms and conditions either of that numbered
|
option of following the terms and conditions either of that numbered
|
||||||
version or of any later version published by the Free Software
|
version or of any later version published by the Free Software
|
||||||
Foundation. If the Program does not specify a version number of the
|
Foundation. If the Program does not specify a version number of the
|
||||||
GNU General Public License, you may choose any version ever published
|
GNU Affero General Public License, you may choose any version ever published
|
||||||
by the Free Software Foundation.
|
by the Free Software Foundation.
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
If the Program specifies that a proxy can decide which future
|
||||||
versions of the GNU General Public License can be used, that proxy's
|
versions of the GNU Affero General Public License can be used, that proxy's
|
||||||
public statement of acceptance of a version permanently authorizes you
|
public statement of acceptance of a version permanently authorizes you
|
||||||
to choose that version for the Program.
|
to choose that version for the Program.
|
||||||
|
|
||||||
@@ -631,44 +629,33 @@ to attach them to the start of each source file to most effectively
|
|||||||
state the exclusion of warranty; and each file should have at least
|
state the exclusion of warranty; and each file should have at least
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
Gaseous
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
Copyright (C) 2023 Gaseous
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU Affero General Public License as published
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
by the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
If the program does terminal interaction, make it output a short
|
If your software can interact with users remotely through a computer
|
||||||
notice like this when it starts in an interactive mode:
|
network, you should also make sure that it provides a way for users to
|
||||||
|
get its source. For example, if your program is a web application, its
|
||||||
<program> Copyright (C) 2023 Gaseous
|
interface could display a "Source" link that leads users to an archive
|
||||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
of the code. There are many ways you could offer source, and different
|
||||||
This is free software, and you are welcome to redistribute it
|
solutions will be better for different programs; see section 13 for the
|
||||||
under certain conditions; type `show c' for details.
|
specific requirements.
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, your program's commands
|
|
||||||
might be different; for a GUI interface, you would use an "about box".
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
For more information on this, and how to apply and follow the GNU GPL, see
|
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||||
<https://www.gnu.org/licenses/>.
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
The GNU General Public License does not permit incorporating your program
|
|
||||||
into proprietary programs. If your program is a subroutine library, you
|
|
||||||
may consider it more useful to permit linking proprietary applications with
|
|
||||||
the library. If this is what you want to do, use the GNU Lesser General
|
|
||||||
Public License instead of this License. But first, please read
|
|
||||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
|
@@ -8,21 +8,32 @@ RUN echo "Target: $TARGETARCH"
|
|||||||
RUN echo "Build: $BUILDPLATFORM"
|
RUN echo "Build: $BUILDPLATFORM"
|
||||||
|
|
||||||
# Copy everything
|
# Copy everything
|
||||||
COPY . ./
|
COPY .. ./
|
||||||
# Restore as distinct layers
|
# Restore as distinct layers
|
||||||
RUN dotnet restore "gaseous-server/gaseous-server.csproj" -a $TARGETARCH
|
RUN dotnet restore "gaseous-server/gaseous-server.csproj" -a $TARGETARCH
|
||||||
# Build and publish a release
|
# Build and publish a release
|
||||||
RUN dotnet publish "gaseous-server/gaseous-server.csproj" --use-current-runtime --self-contained true -c Release -o out -a $TARGETARCH
|
RUN dotnet publish "gaseous-server/gaseous-server.csproj" --use-current-runtime --self-contained true -c Release -o out -a $TARGETARCH
|
||||||
|
|
||||||
|
# update apt-get
|
||||||
|
RUN apt-get update
|
||||||
|
|
||||||
# download and unzip EmulatorJS from CDN
|
# download and unzip EmulatorJS from CDN
|
||||||
RUN apt-get update && apt-get install -y p7zip-full
|
RUN apt-get install -y p7zip-full
|
||||||
RUN mkdir -p out/wwwroot/emulators/EmulatorJS
|
RUN mkdir -p out/wwwroot/emulators/EmulatorJS
|
||||||
RUN wget https://cdn.emulatorjs.org/releases/4.0.11.7z
|
RUN wget https://cdn.emulatorjs.org/releases/4.1.1.7z
|
||||||
RUN 7z x -y -oout/wwwroot/emulators/EmulatorJS 4.0.11.7z
|
RUN 7z x -y -oout/wwwroot/emulators/EmulatorJS 4.1.1.7z
|
||||||
|
|
||||||
|
# clean up apt-get
|
||||||
|
RUN apt-get clean && rm -rf /var/lib/apt/lists
|
||||||
|
|
||||||
# Build runtime image
|
# Build runtime image
|
||||||
FROM mcr.microsoft.com/dotnet/aspnet:8.0
|
FROM mcr.microsoft.com/dotnet/aspnet:8.0
|
||||||
ENV INDOCKER=1
|
ENV INDOCKER=1
|
||||||
WORKDIR /App
|
WORKDIR /App
|
||||||
COPY --from=build-env /App/out .
|
COPY --from=build-env /App/out .
|
||||||
|
|
||||||
|
# Configure healthcheck
|
||||||
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 CMD curl --fail http://localhost:80/healthCheck || exit 1
|
||||||
|
|
||||||
|
# start gaseous-server
|
||||||
ENTRYPOINT ["dotnet", "gaseous-server.dll"]
|
ENTRYPOINT ["dotnet", "gaseous-server.dll"]
|
76
build/Dockerfile-EmbeddedDB
Normal file
76
build/Dockerfile-EmbeddedDB
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env
|
||||||
|
ARG TARGETARCH
|
||||||
|
ARG BUILDPLATFORM
|
||||||
|
WORKDIR /App
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
RUN echo "Target: $TARGETARCH"
|
||||||
|
RUN echo "Build: $BUILDPLATFORM"
|
||||||
|
|
||||||
|
# Copy everything
|
||||||
|
COPY .. ./
|
||||||
|
# Restore as distinct layers
|
||||||
|
RUN dotnet restore "gaseous-server/gaseous-server.csproj" -a $TARGETARCH
|
||||||
|
# Build and publish a release
|
||||||
|
RUN dotnet publish "gaseous-server/gaseous-server.csproj" --use-current-runtime --self-contained true -c Release -o out -a $TARGETARCH
|
||||||
|
|
||||||
|
# update apt-get
|
||||||
|
RUN apt-get update
|
||||||
|
|
||||||
|
# download and unzip EmulatorJS from CDN
|
||||||
|
RUN apt-get install -y p7zip-full
|
||||||
|
RUN mkdir -p out/wwwroot/emulators/EmulatorJS
|
||||||
|
RUN wget https://cdn.emulatorjs.org/releases/4.1.1.7z
|
||||||
|
RUN 7z x -y -oout/wwwroot/emulators/EmulatorJS 4.1.1.7z
|
||||||
|
|
||||||
|
RUN wget --recursive --no-parent https://cdn.emulatorjs.org/latest/
|
||||||
|
RUN mkdir -p out/wwwroot/emulators/EmulatorJS
|
||||||
|
RUN cp -fr cdn.emulatorjs.org/latest/* out/wwwroot/emulators/EmulatorJS
|
||||||
|
RUN rm -Rf cdn.emulatorjs.org
|
||||||
|
|
||||||
|
# Build runtime image
|
||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:8.0
|
||||||
|
ENV INDOCKER=1
|
||||||
|
WORKDIR /App
|
||||||
|
COPY --from=build-env /App/out .
|
||||||
|
|
||||||
|
# variables
|
||||||
|
ARG PUID=1000
|
||||||
|
ARG PGID=1000
|
||||||
|
ARG dbhost=localhost
|
||||||
|
ARG dbuser=root
|
||||||
|
ARG dbpass=gaseous
|
||||||
|
ARG MARIADB_ROOT_PASSWORD=$dbpass
|
||||||
|
|
||||||
|
ENV PUID=${PUID}
|
||||||
|
ENV PGID=${PGID}
|
||||||
|
ENV dbhost=${dbhost}
|
||||||
|
ENV dbuser=${dbuser}
|
||||||
|
ENV dbpass=${dbpass}
|
||||||
|
ENV MARIADB_ROOT_PASSWORD=${dbpass}
|
||||||
|
|
||||||
|
# install mariadb
|
||||||
|
RUN DEBIAN_FRONTEND=noninteractive && \
|
||||||
|
apt-get update && apt-get install -y mariadb-server
|
||||||
|
RUN mkdir -p /run/mysqld
|
||||||
|
COPY ../build/mariadb.sh /usr/sbin/start-mariadb.sh
|
||||||
|
RUN chmod +x /usr/sbin/start-mariadb.sh
|
||||||
|
|
||||||
|
# install supervisord
|
||||||
|
RUN apt-get install -y supervisor
|
||||||
|
COPY ../build/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||||
|
RUN mkdir -p /var/run/supervisord
|
||||||
|
RUN mkdir -p /var/log/supervisord
|
||||||
|
|
||||||
|
# clean up apt-get
|
||||||
|
RUN apt-get clean && rm -rf /var/lib/apt/lists
|
||||||
|
|
||||||
|
# copy entrypoint
|
||||||
|
COPY ../build/entrypoint.sh /usr/sbin/entrypoint.sh
|
||||||
|
RUN chmod +x /usr/sbin/entrypoint.sh
|
||||||
|
|
||||||
|
# volumes
|
||||||
|
VOLUME /home/gaseous/.gaseous-server /var/lib/mysql
|
||||||
|
|
||||||
|
# start services
|
||||||
|
ENTRYPOINT [ "/usr/sbin/entrypoint.sh" ]
|
13
build/entrypoint.sh
Normal file
13
build/entrypoint.sh
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# create the user
|
||||||
|
echo "Creating user gaseous with UID ${PUID} and GID ${PGID}"
|
||||||
|
groupadd -g ${PGID} gaseous
|
||||||
|
useradd -u ${PUID} -g ${PGID} -m gaseous -d /home/gaseous -G sudo
|
||||||
|
usermod -p "*" gaseous
|
||||||
|
mkdir -p /home/gaseous/.gaseous-server /var/lib/mysql /var/log/mariadb /run/mysqld
|
||||||
|
chown -R ${PUID} /App /home/gaseous/.gaseous-server /var/lib/mysql /var/log/mariadb /run/mysqld
|
||||||
|
chgrp -R ${PGID} /App /home/gaseous/.gaseous-server /var/lib/mysql /var/log/mariadb /run/mysqld
|
||||||
|
|
||||||
|
# Start supervisord and services
|
||||||
|
/usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
|
20
build/mariadb.sh
Normal file
20
build/mariadb.sh
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# install the database
|
||||||
|
/usr/bin/mariadb-install-db --datadir=/var/lib/mysql --user=gaseous
|
||||||
|
|
||||||
|
# start the database server without network or grant tables
|
||||||
|
/usr/sbin/mariadbd --datadir=/var/lib/mysql --skip-grant-tables --skip-networking &
|
||||||
|
|
||||||
|
# wait for the server to start
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
# change the root password
|
||||||
|
mariadb -u root -e "FLUSH PRIVILEGES; ALTER USER 'root'@'localhost' IDENTIFIED BY '$MARIADB_ROOT_PASSWORD'; ALTER USER 'gaseous'@'localhost' IDENTIFIED BY '$MARIADB_ROOT_PASSWORD'; FLUSH PRIVILEGES; SHUTDOWN;"
|
||||||
|
|
||||||
|
# stop the server
|
||||||
|
sleep 5
|
||||||
|
killall mariadbd
|
||||||
|
|
||||||
|
# start the server normally
|
||||||
|
/usr/sbin/mariadbd --datadir=/var/lib/mysql
|
37
build/supervisord.conf
Normal file
37
build/supervisord.conf
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
[supervisord]
|
||||||
|
user=root
|
||||||
|
nodaemon=true
|
||||||
|
logfile=/var/log/supervisord/supervisord.log
|
||||||
|
logfile_maxbytes=50
|
||||||
|
logfile_backups=5
|
||||||
|
pidfile=/var/run/supervisord/supervisord.pid
|
||||||
|
loglevel = info
|
||||||
|
|
||||||
|
[unix_http_server]
|
||||||
|
file=/var/run/supervisord/supervisor.sock
|
||||||
|
chmod=0700
|
||||||
|
|
||||||
|
[rpcinterface:supervisor]
|
||||||
|
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
|
||||||
|
|
||||||
|
[supervisorctl]
|
||||||
|
serverurl=unix:///var/run/supervisord/supervisor.sock
|
||||||
|
|
||||||
|
[program:mariadb]
|
||||||
|
user=gaseous
|
||||||
|
command=bash -c "/usr/sbin/start-mariadb.sh"
|
||||||
|
autostart=true
|
||||||
|
autorestart=true
|
||||||
|
redirect_stderr=true
|
||||||
|
stdout_logfile=/dev/fd/1
|
||||||
|
stdout_logfile_maxbytes=0
|
||||||
|
|
||||||
|
[program:gaseous-server]
|
||||||
|
user=gaseous
|
||||||
|
command=dotnet /App/gaseous-server.dll
|
||||||
|
environment=HOME="/home/gaseous",USER="gaseous"
|
||||||
|
autostart=true
|
||||||
|
autorestart=true
|
||||||
|
redirect_stderr=true
|
||||||
|
stdout_logfile=/dev/fd/1
|
||||||
|
stdout_logfile_maxbytes=0
|
@@ -1,5 +1,6 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using System.Data;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
@@ -19,7 +20,8 @@ namespace gaseous_server.Classes
|
|||||||
if (ObjectToCheck == null || ObjectToCheck == System.DBNull.Value)
|
if (ObjectToCheck == null || ObjectToCheck == System.DBNull.Value)
|
||||||
{
|
{
|
||||||
return IfNullValue;
|
return IfNullValue;
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
return ObjectToCheck;
|
return ObjectToCheck;
|
||||||
}
|
}
|
||||||
@@ -27,10 +29,10 @@ namespace gaseous_server.Classes
|
|||||||
|
|
||||||
static public DateTime ConvertUnixToDateTime(double UnixTimeStamp)
|
static public DateTime ConvertUnixToDateTime(double UnixTimeStamp)
|
||||||
{
|
{
|
||||||
DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
|
DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
|
||||||
dateTime = dateTime.AddSeconds(UnixTimeStamp).ToLocalTime();
|
dateTime = dateTime.AddSeconds(UnixTimeStamp).ToLocalTime();
|
||||||
return dateTime;
|
return dateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class hashObject
|
public class hashObject
|
||||||
{
|
{
|
||||||
@@ -41,21 +43,23 @@ namespace gaseous_server.Classes
|
|||||||
|
|
||||||
public hashObject(string FileName)
|
public hashObject(string FileName)
|
||||||
{
|
{
|
||||||
var xmlStream = File.OpenRead(FileName);
|
var xmlStream = File.OpenRead(FileName);
|
||||||
|
|
||||||
var md5 = MD5.Create();
|
Logging.Log(Logging.LogType.Information, "Hash File", "Generating MD5 hash for file: " + FileName);
|
||||||
byte[] md5HashByte = md5.ComputeHash(xmlStream);
|
var md5 = MD5.Create();
|
||||||
string md5Hash = BitConverter.ToString(md5HashByte).Replace("-", "").ToLowerInvariant();
|
byte[] md5HashByte = md5.ComputeHash(xmlStream);
|
||||||
|
string md5Hash = BitConverter.ToString(md5HashByte).Replace("-", "").ToLowerInvariant();
|
||||||
_md5hash = md5Hash;
|
_md5hash = md5Hash;
|
||||||
|
|
||||||
var sha1 = SHA1.Create();
|
Logging.Log(Logging.LogType.Information, "Hash File", "Generating SHA1 hash for file: " + FileName);
|
||||||
|
var sha1 = SHA1.Create();
|
||||||
xmlStream.Position = 0;
|
xmlStream.Position = 0;
|
||||||
byte[] sha1HashByte = sha1.ComputeHash(xmlStream);
|
byte[] sha1HashByte = sha1.ComputeHash(xmlStream);
|
||||||
string sha1Hash = BitConverter.ToString(sha1HashByte).Replace("-", "").ToLowerInvariant();
|
string sha1Hash = BitConverter.ToString(sha1HashByte).Replace("-", "").ToLowerInvariant();
|
||||||
_sha1hash = sha1Hash;
|
_sha1hash = sha1Hash;
|
||||||
|
|
||||||
xmlStream.Close();
|
xmlStream.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
string _md5hash = "";
|
string _md5hash = "";
|
||||||
string _sha1hash = "";
|
string _sha1hash = "";
|
||||||
@@ -85,29 +89,29 @@ namespace gaseous_server.Classes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long DirSize(DirectoryInfo d)
|
public static long DirSize(DirectoryInfo d)
|
||||||
{
|
{
|
||||||
long size = 0;
|
long size = 0;
|
||||||
// Add file sizes.
|
// Add file sizes.
|
||||||
FileInfo[] fis = d.GetFiles();
|
FileInfo[] fis = d.GetFiles();
|
||||||
foreach (FileInfo fi in fis)
|
foreach (FileInfo fi in fis)
|
||||||
{
|
{
|
||||||
size += fi.Length;
|
size += fi.Length;
|
||||||
}
|
}
|
||||||
// Add subdirectory sizes.
|
// Add subdirectory sizes.
|
||||||
DirectoryInfo[] dis = d.GetDirectories();
|
DirectoryInfo[] dis = d.GetDirectories();
|
||||||
foreach (DirectoryInfo di in dis)
|
foreach (DirectoryInfo di in dis)
|
||||||
{
|
{
|
||||||
size += DirSize(di);
|
size += DirSize(di);
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string[] SkippableFiles = {
|
public static string[] SkippableFiles = {
|
||||||
".DS_STORE",
|
".DS_STORE",
|
||||||
"desktop.ini"
|
"desktop.ini"
|
||||||
};
|
};
|
||||||
|
|
||||||
public static string NormalizePath(string path)
|
public static string NormalizePath(string path)
|
||||||
{
|
{
|
||||||
return Path.GetFullPath(new Uri(path).LocalPath)
|
return Path.GetFullPath(new Uri(path).LocalPath)
|
||||||
@@ -155,30 +159,74 @@ namespace gaseous_server.Classes
|
|||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public static int GetLookupByCode(LookupTypes LookupType, string Code)
|
||||||
|
{
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "SELECT Id FROM " + LookupType.ToString() + " WHERE Code = @code";
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>{
|
||||||
|
{ "code", Code }
|
||||||
|
};
|
||||||
|
|
||||||
|
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||||
|
if (data.Rows.Count == 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (int)data.Rows[0]["Id"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetLookupByValue(LookupTypes LookupType, string Value)
|
||||||
|
{
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "SELECT Id FROM " + LookupType.ToString() + " WHERE Value = @value";
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>{
|
||||||
|
{ "value", Value }
|
||||||
|
};
|
||||||
|
|
||||||
|
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||||
|
if (data.Rows.Count == 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (int)data.Rows[0]["Id"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum LookupTypes
|
||||||
|
{
|
||||||
|
Country,
|
||||||
|
Language
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides a way to set contextual data that flows with the call and
|
/// Provides a way to set contextual data that flows with the call and
|
||||||
/// async context of a test or invocation.
|
/// async context of a test or invocation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class CallContext
|
public static class CallContext
|
||||||
{
|
{
|
||||||
static ConcurrentDictionary<string, AsyncLocal<object>> state = new ConcurrentDictionary<string, AsyncLocal<object>>();
|
static ConcurrentDictionary<string, AsyncLocal<object>> state = new ConcurrentDictionary<string, AsyncLocal<object>>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stores a given object and associates it with the specified name.
|
/// Stores a given object and associates it with the specified name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">The name with which to associate the new item in the call context.</param>
|
/// <param name="name">The name with which to associate the new item in the call context.</param>
|
||||||
/// <param name="data">The object to store in the call context.</param>
|
/// <param name="data">The object to store in the call context.</param>
|
||||||
public static void SetData(string name, object data) =>
|
public static void SetData(string name, object data) =>
|
||||||
state.GetOrAdd(name, _ => new AsyncLocal<object>()).Value = data;
|
state.GetOrAdd(name, _ => new AsyncLocal<object>()).Value = data;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves an object with the specified name from the <see cref="CallContext"/>.
|
/// Retrieves an object with the specified name from the <see cref="CallContext"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">The name of the item in the call context.</param>
|
/// <param name="name">The name of the item in the call context.</param>
|
||||||
/// <returns>The object in the call context associated with the specified name, or <see langword="null"/> if not found.</returns>
|
/// <returns>The object in the call context associated with the specified name, or <see langword="null"/> if not found.</returns>
|
||||||
public static object GetData(string name) =>
|
public static object GetData(string name) =>
|
||||||
state.TryGetValue(name, out AsyncLocal<object> data) ? data.Value : null;
|
state.TryGetValue(name, out AsyncLocal<object> data) ? data.Value : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -80,7 +80,8 @@ namespace gaseous_server.Classes
|
|||||||
get
|
get
|
||||||
{
|
{
|
||||||
string logPath = Path.Combine(ConfigurationPath, "Logs");
|
string logPath = Path.Combine(ConfigurationPath, "Logs");
|
||||||
if (!Directory.Exists(logPath)) {
|
if (!Directory.Exists(logPath))
|
||||||
|
{
|
||||||
Directory.CreateDirectory(logPath);
|
Directory.CreateDirectory(logPath);
|
||||||
}
|
}
|
||||||
return logPath;
|
return logPath;
|
||||||
@@ -92,7 +93,7 @@ namespace gaseous_server.Classes
|
|||||||
get
|
get
|
||||||
{
|
{
|
||||||
string logFileExtension = "txt";
|
string logFileExtension = "txt";
|
||||||
|
|
||||||
string logPathName = Path.Combine(LogPath, "Server Log " + DateTime.Now.ToUniversalTime().ToString("yyyyMMdd") + "." + logFileExtension);
|
string logPathName = Path.Combine(LogPath, "Server Log " + DateTime.Now.ToUniversalTime().ToString("yyyyMMdd") + "." + logFileExtension);
|
||||||
return logPathName;
|
return logPathName;
|
||||||
}
|
}
|
||||||
@@ -131,7 +132,7 @@ namespace gaseous_server.Classes
|
|||||||
_config.DatabaseConfiguration.DatabaseName = (string)Common.GetEnvVar("dbname", _config.DatabaseConfiguration.DatabaseName);
|
_config.DatabaseConfiguration.DatabaseName = (string)Common.GetEnvVar("dbname", _config.DatabaseConfiguration.DatabaseName);
|
||||||
_config.DatabaseConfiguration.Port = int.Parse((string)Common.GetEnvVar("dbport", _config.DatabaseConfiguration.Port.ToString()));
|
_config.DatabaseConfiguration.Port = int.Parse((string)Common.GetEnvVar("dbport", _config.DatabaseConfiguration.Port.ToString()));
|
||||||
_config.MetadataConfiguration.MetadataSource = (HasheousClient.Models.MetadataModel.MetadataSources)Enum.Parse(typeof(HasheousClient.Models.MetadataModel.MetadataSources), (string)Common.GetEnvVar("metadatasource", _config.MetadataConfiguration.MetadataSource.ToString()));
|
_config.MetadataConfiguration.MetadataSource = (HasheousClient.Models.MetadataModel.MetadataSources)Enum.Parse(typeof(HasheousClient.Models.MetadataModel.MetadataSources), (string)Common.GetEnvVar("metadatasource", _config.MetadataConfiguration.MetadataSource.ToString()));
|
||||||
_config.MetadataConfiguration.SignatureSource = (HasheousClient.Models.MetadataModel.SignatureSources)Enum.Parse(typeof(HasheousClient.Models.MetadataModel.SignatureSources), (string)Common.GetEnvVar("signaturesource", _config.MetadataConfiguration.SignatureSource.ToString()));;
|
_config.MetadataConfiguration.SignatureSource = (HasheousClient.Models.MetadataModel.SignatureSources)Enum.Parse(typeof(HasheousClient.Models.MetadataModel.SignatureSources), (string)Common.GetEnvVar("signaturesource", _config.MetadataConfiguration.SignatureSource.ToString())); ;
|
||||||
_config.MetadataConfiguration.MaxLibraryScanWorkers = int.Parse((string)Common.GetEnvVar("maxlibraryscanworkers", _config.MetadataConfiguration.MaxLibraryScanWorkers.ToString()));
|
_config.MetadataConfiguration.MaxLibraryScanWorkers = int.Parse((string)Common.GetEnvVar("maxlibraryscanworkers", _config.MetadataConfiguration.MaxLibraryScanWorkers.ToString()));
|
||||||
_config.MetadataConfiguration.HasheousHost = (string)Common.GetEnvVar("hasheoushost", _config.MetadataConfiguration.HasheousHost);
|
_config.MetadataConfiguration.HasheousHost = (string)Common.GetEnvVar("hasheoushost", _config.MetadataConfiguration.HasheousHost);
|
||||||
_config.IGDBConfiguration.ClientId = (string)Common.GetEnvVar("igdbclientid", _config.IGDBConfiguration.ClientId);
|
_config.IGDBConfiguration.ClientId = (string)Common.GetEnvVar("igdbclientid", _config.IGDBConfiguration.ClientId);
|
||||||
@@ -196,13 +197,18 @@ namespace gaseous_server.Classes
|
|||||||
{
|
{
|
||||||
string SettingName = (string)dataRow["Setting"];
|
string SettingName = (string)dataRow["Setting"];
|
||||||
|
|
||||||
|
if (SettingName.StartsWith("LastRun_"))
|
||||||
|
{
|
||||||
|
Console.WriteLine("Break");
|
||||||
|
}
|
||||||
|
|
||||||
if (AppSettings.ContainsKey(SettingName))
|
if (AppSettings.ContainsKey(SettingName))
|
||||||
{
|
{
|
||||||
AppSettings.Remove(SettingName);
|
AppSettings.Remove(SettingName);
|
||||||
}
|
}
|
||||||
|
|
||||||
Logging.Log(Logging.LogType.Information, "Load Settings", "Loading setting " + SettingName + " from database");
|
Logging.Log(Logging.LogType.Information, "Load Settings", "Loading setting " + SettingName + " from database");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (Database.schema_version >= 1016)
|
if (Database.schema_version >= 1016)
|
||||||
@@ -270,7 +276,7 @@ namespace gaseous_server.Classes
|
|||||||
if (Database.schema_version >= 1016)
|
if (Database.schema_version >= 1016)
|
||||||
{
|
{
|
||||||
sql = "SELECT Value, ValueDate FROM Settings WHERE Setting = @SettingName";
|
sql = "SELECT Value, ValueDate FROM Settings WHERE Setting = @SettingName";
|
||||||
|
|
||||||
dbResponse = db.ExecuteCMD(sql, dbDict);
|
dbResponse = db.ExecuteCMD(sql, dbDict);
|
||||||
Type type = typeof(T);
|
Type type = typeof(T);
|
||||||
if (dbResponse.Rows.Count == 0)
|
if (dbResponse.Rows.Count == 0)
|
||||||
@@ -296,7 +302,7 @@ namespace gaseous_server.Classes
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
sql = "SELECT Value FROM Settings WHERE Setting = @SettingName";
|
sql = "SELECT Value FROM Settings WHERE Setting = @SettingName";
|
||||||
|
|
||||||
dbResponse = db.ExecuteCMD(sql, dbDict);
|
dbResponse = db.ExecuteCMD(sql, dbDict);
|
||||||
Type type = typeof(T);
|
Type type = typeof(T);
|
||||||
if (dbResponse.Rows.Count == 0)
|
if (dbResponse.Rows.Count == 0)
|
||||||
@@ -350,30 +356,43 @@ namespace gaseous_server.Classes
|
|||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
string sql;
|
string sql;
|
||||||
Dictionary<string, object> dbDict;
|
Dictionary<string, object> dbDict;
|
||||||
|
|
||||||
if (Database.schema_version >= 1016)
|
if (Database.schema_version >= 1016)
|
||||||
{
|
{
|
||||||
sql = "REPLACE INTO Settings (Setting, ValueType, Value, ValueDate) VALUES (@SettingName, @ValueType, @Value, @ValueDate)";
|
sql = "REPLACE INTO Settings (Setting, ValueType, Value, ValueDate) VALUES (@SettingName, @ValueType, @Value, @ValueDate)";
|
||||||
Type type = typeof(T);
|
Type type = typeof(T);
|
||||||
if (type.ToString() == "System.DateTime")
|
|
||||||
|
switch (type.ToString())
|
||||||
{
|
{
|
||||||
dbDict = new Dictionary<string, object>
|
case "System.DateTime":
|
||||||
{
|
dbDict = new Dictionary<string, object>
|
||||||
{ "SettingName", SettingName },
|
{
|
||||||
{ "ValueType", 1 },
|
{ "SettingName", SettingName },
|
||||||
{ "Value", null },
|
{ "ValueType", 1 },
|
||||||
{ "ValueDate", Value }
|
{ "Value", null },
|
||||||
};
|
{ "ValueDate", Value }
|
||||||
}
|
};
|
||||||
else
|
break;
|
||||||
{
|
|
||||||
dbDict = new Dictionary<string, object>
|
case "System.Collections.Generic.List`1[gaseous_server.Classes.Metadata.Games+SearchType]":
|
||||||
{
|
dbDict = new Dictionary<string, object>
|
||||||
{ "SettingName", SettingName },
|
{
|
||||||
{ "ValueType", 0 },
|
{ "SettingName", SettingName },
|
||||||
{ "Value", Value },
|
{ "ValueType", 2 },
|
||||||
{ "ValueDate", null }
|
{ "Value", JsonConvert.SerializeObject(Value) },
|
||||||
};
|
{ "ValueDate", null }
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
dbDict = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "SettingName", SettingName },
|
||||||
|
{ "ValueType", 0 },
|
||||||
|
{ "Value", Value },
|
||||||
|
{ "ValueDate", null }
|
||||||
|
};
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -422,7 +441,8 @@ namespace gaseous_server.Classes
|
|||||||
|
|
||||||
public class Database
|
public class Database
|
||||||
{
|
{
|
||||||
private static string _DefaultHostName {
|
private static string _DefaultHostName
|
||||||
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("dbhost")))
|
if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("dbhost")))
|
||||||
|
@@ -9,8 +9,21 @@ namespace gaseous_server.Classes
|
|||||||
{
|
{
|
||||||
public class Database
|
public class Database
|
||||||
{
|
{
|
||||||
public static int schema_version = 0;
|
private static int _schema_version { get; set; } = 0;
|
||||||
|
public static int schema_version
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
//Logging.Log(Logging.LogType.Information, "Database Schema", "Schema version is " + _schema_version);
|
||||||
|
return _schema_version;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
//Logging.Log(Logging.LogType.Information, "Database Schema", "Setting schema version " + _schema_version);
|
||||||
|
_schema_version = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Database()
|
public Database()
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -80,7 +93,16 @@ namespace gaseous_server.Classes
|
|||||||
ExecuteCMD(sql, dbDict);
|
ExecuteCMD(sql, dbDict);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 1000; i < 10000; i++)
|
sql = "SELECT schema_version FROM schema_version;";
|
||||||
|
dbDict = new Dictionary<string, object>();
|
||||||
|
DataTable SchemaVersion = ExecuteCMD(sql, dbDict);
|
||||||
|
int OuterSchemaVer = (int)SchemaVersion.Rows[0][0];
|
||||||
|
if (OuterSchemaVer == 0)
|
||||||
|
{
|
||||||
|
OuterSchemaVer = 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = OuterSchemaVer; i < 10000; i++)
|
||||||
{
|
{
|
||||||
string resourceName = "gaseous_server.Support.Database.MySQL.gaseous-" + i + ".sql";
|
string resourceName = "gaseous_server.Support.Database.MySQL.gaseous-" + i + ".sql";
|
||||||
string dbScript = "";
|
string dbScript = "";
|
||||||
@@ -96,7 +118,7 @@ namespace gaseous_server.Classes
|
|||||||
// apply script
|
// apply script
|
||||||
sql = "SELECT schema_version FROM schema_version;";
|
sql = "SELECT schema_version FROM schema_version;";
|
||||||
dbDict = new Dictionary<string, object>();
|
dbDict = new Dictionary<string, object>();
|
||||||
DataTable SchemaVersion = ExecuteCMD(sql, dbDict);
|
SchemaVersion = ExecuteCMD(sql, dbDict);
|
||||||
if (SchemaVersion.Rows.Count == 0)
|
if (SchemaVersion.Rows.Count == 0)
|
||||||
{
|
{
|
||||||
// something is broken here... where's the table?
|
// something is broken here... where's the table?
|
||||||
@@ -107,6 +129,8 @@ namespace gaseous_server.Classes
|
|||||||
{
|
{
|
||||||
int SchemaVer = (int)SchemaVersion.Rows[0][0];
|
int SchemaVer = (int)SchemaVersion.Rows[0][0];
|
||||||
Logging.Log(Logging.LogType.Information, "Database", "Schema version is " + SchemaVer);
|
Logging.Log(Logging.LogType.Information, "Database", "Schema version is " + SchemaVer);
|
||||||
|
// update schema version variable
|
||||||
|
Database.schema_version = SchemaVer;
|
||||||
if (SchemaVer < i)
|
if (SchemaVer < i)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@@ -4,11 +4,11 @@ using System.Reflection;
|
|||||||
|
|
||||||
namespace gaseous_server.Classes
|
namespace gaseous_server.Classes
|
||||||
{
|
{
|
||||||
public static class DatabaseMigration
|
public static class DatabaseMigration
|
||||||
{
|
{
|
||||||
public static List<int> BackgroundUpgradeTargetSchemaVersions = new List<int>();
|
public static List<int> BackgroundUpgradeTargetSchemaVersions = new List<int>();
|
||||||
|
|
||||||
public static void PreUpgradeScript(int TargetSchemaVersion, Database.databaseType? DatabaseType)
|
public static void PreUpgradeScript(int TargetSchemaVersion, Database.databaseType? DatabaseType)
|
||||||
{
|
{
|
||||||
// load resources
|
// load resources
|
||||||
var assembly = Assembly.GetExecutingAssembly();
|
var assembly = Assembly.GetExecutingAssembly();
|
||||||
@@ -20,14 +20,14 @@ namespace gaseous_server.Classes
|
|||||||
|
|
||||||
Logging.Log(Logging.LogType.Information, "Database", "Checking for pre-upgrade for schema version " + TargetSchemaVersion);
|
Logging.Log(Logging.LogType.Information, "Database", "Checking for pre-upgrade for schema version " + TargetSchemaVersion);
|
||||||
|
|
||||||
switch(DatabaseType)
|
switch (DatabaseType)
|
||||||
{
|
{
|
||||||
case Database.databaseType.MySql:
|
case Database.databaseType.MySql:
|
||||||
switch (TargetSchemaVersion)
|
switch (TargetSchemaVersion)
|
||||||
{
|
{
|
||||||
case 1005:
|
case 1005:
|
||||||
Logging.Log(Logging.LogType.Information, "Database", "Running pre-upgrade for schema version " + TargetSchemaVersion);
|
Logging.Log(Logging.LogType.Information, "Database", "Running pre-upgrade for schema version " + TargetSchemaVersion);
|
||||||
|
|
||||||
// there was a mistake at dbschema version 1004-1005
|
// there was a mistake at dbschema version 1004-1005
|
||||||
// the first preview release of v1.7 reused dbschema version 1004
|
// the first preview release of v1.7 reused dbschema version 1004
|
||||||
// if table "Relation_Game_AgeRatings" exists - then we need to apply the gaseous-fix-1005.sql script before applying the standard 1005 script
|
// if table "Relation_Game_AgeRatings" exists - then we need to apply the gaseous-fix-1005.sql script before applying the standard 1005 script
|
||||||
@@ -62,14 +62,16 @@ namespace gaseous_server.Classes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PostUpgradeScript(int TargetSchemaVersion, Database.databaseType? DatabaseType)
|
public static void PostUpgradeScript(int TargetSchemaVersion, Database.databaseType? DatabaseType)
|
||||||
{
|
{
|
||||||
|
var assembly = Assembly.GetExecutingAssembly();
|
||||||
|
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
string sql = "";
|
string sql = "";
|
||||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
DataTable data;
|
DataTable data;
|
||||||
|
|
||||||
switch(DatabaseType)
|
switch (DatabaseType)
|
||||||
{
|
{
|
||||||
case Database.databaseType.MySql:
|
case Database.databaseType.MySql:
|
||||||
switch (TargetSchemaVersion)
|
switch (TargetSchemaVersion)
|
||||||
@@ -78,7 +80,7 @@ namespace gaseous_server.Classes
|
|||||||
// this is a safe background task
|
// this is a safe background task
|
||||||
BackgroundUpgradeTargetSchemaVersions.Add(1002);
|
BackgroundUpgradeTargetSchemaVersions.Add(1002);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1004:
|
case 1004:
|
||||||
// needs to run on start up
|
// needs to run on start up
|
||||||
|
|
||||||
@@ -103,6 +105,48 @@ namespace gaseous_server.Classes
|
|||||||
sql = "DELETE FROM Settings WHERE Setting LIKE 'LastRun_%';";
|
sql = "DELETE FROM Settings WHERE Setting LIKE 'LastRun_%';";
|
||||||
db.ExecuteNonQuery(sql);
|
db.ExecuteNonQuery(sql);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 1023:
|
||||||
|
// load country list
|
||||||
|
Logging.Log(Logging.LogType.Information, "Database Upgrade", "Adding country look up table contents");
|
||||||
|
|
||||||
|
string countryResourceName = "gaseous_server.Support.Country.txt";
|
||||||
|
using (Stream stream = assembly.GetManifestResourceStream(countryResourceName))
|
||||||
|
using (StreamReader reader = new StreamReader(stream))
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
string[] line = reader.ReadLine().Split("|");
|
||||||
|
|
||||||
|
sql = "INSERT INTO Country (Code, Value) VALUES (@code, @value);";
|
||||||
|
dbDict = new Dictionary<string, object>{
|
||||||
|
{ "code", line[0] },
|
||||||
|
{ "value", line[1] }
|
||||||
|
};
|
||||||
|
db.ExecuteNonQuery(sql, dbDict);
|
||||||
|
} while (reader.EndOfStream == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// load language list
|
||||||
|
Logging.Log(Logging.LogType.Information, "Database Upgrade", "Adding language look up table contents");
|
||||||
|
|
||||||
|
string languageResourceName = "gaseous_server.Support.Language.txt";
|
||||||
|
using (Stream stream = assembly.GetManifestResourceStream(languageResourceName))
|
||||||
|
using (StreamReader reader = new StreamReader(stream))
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
string[] line = reader.ReadLine().Split("|");
|
||||||
|
|
||||||
|
sql = "INSERT INTO Language (Code, Value) VALUES (@code, @value);";
|
||||||
|
dbDict = new Dictionary<string, object>{
|
||||||
|
{ "code", line[0] },
|
||||||
|
{ "value", line[1] }
|
||||||
|
};
|
||||||
|
db.ExecuteNonQuery(sql, dbDict);
|
||||||
|
} while (reader.EndOfStream == false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -121,7 +165,8 @@ namespace gaseous_server.Classes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void MySql_1002_MigrateMetadataVersion() {
|
public static void MySql_1002_MigrateMetadataVersion()
|
||||||
|
{
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
string sql = "";
|
string sql = "";
|
||||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
@@ -134,7 +179,7 @@ namespace gaseous_server.Classes
|
|||||||
Logging.Log(Logging.LogType.Information, "Signature Ingestor - Database Update", "Updating " + data.Rows.Count + " database entries");
|
Logging.Log(Logging.LogType.Information, "Signature Ingestor - Database Update", "Updating " + data.Rows.Count + " database entries");
|
||||||
int Counter = 0;
|
int Counter = 0;
|
||||||
int LastCounterCheck = 0;
|
int LastCounterCheck = 0;
|
||||||
foreach (DataRow row in data.Rows)
|
foreach (DataRow row in data.Rows)
|
||||||
{
|
{
|
||||||
List<string> Flags = Newtonsoft.Json.JsonConvert.DeserializeObject<List<string>>((string)Common.ReturnValueIfNull(row["flags"], "[]"));
|
List<string> Flags = Newtonsoft.Json.JsonConvert.DeserializeObject<List<string>>((string)Common.ReturnValueIfNull(row["flags"], "[]"));
|
||||||
List<KeyValuePair<string, object>> Attributes = new List<KeyValuePair<string, object>>();
|
List<KeyValuePair<string, object>> Attributes = new List<KeyValuePair<string, object>>();
|
||||||
@@ -207,7 +252,7 @@ namespace gaseous_server.Classes
|
|||||||
dbDict.Add("id", (int)row["Id"]);
|
dbDict.Add("id", (int)row["Id"]);
|
||||||
db.ExecuteCMD(updateSQL, dbDict);
|
db.ExecuteCMD(updateSQL, dbDict);
|
||||||
|
|
||||||
if ((Counter - LastCounterCheck) > 10)
|
if ((Counter - LastCounterCheck) > 10)
|
||||||
{
|
{
|
||||||
LastCounterCheck = Counter;
|
LastCounterCheck = Counter;
|
||||||
Logging.Log(Logging.LogType.Information, "Signature Ingestor - Database Update", "Updating " + Counter + " / " + data.Rows.Count + " database entries");
|
Logging.Log(Logging.LogType.Information, "Signature Ingestor - Database Update", "Updating " + Counter + " / " + data.Rows.Count + " database entries");
|
||||||
|
@@ -31,7 +31,7 @@ namespace gaseous_server.Classes
|
|||||||
if (!Directory.Exists(ExtractPath)) { Directory.CreateDirectory(ExtractPath); }
|
if (!Directory.Exists(ExtractPath)) { Directory.CreateDirectory(ExtractPath); }
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
switch(ImportedFileExtension)
|
switch (ImportedFileExtension)
|
||||||
{
|
{
|
||||||
case ".zip":
|
case ".zip":
|
||||||
Logging.Log(Logging.LogType.Information, "Get Signature", "Decompressing using zip");
|
Logging.Log(Logging.LogType.Information, "Get Signature", "Decompressing using zip");
|
||||||
@@ -105,7 +105,7 @@ namespace gaseous_server.Classes
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logging.Log(Logging.LogType.Information, "Get Signature", "Processing decompressed files for signature matches");
|
Logging.Log(Logging.LogType.Information, "Get Signature", "Processing decompressed files for signature matches");
|
||||||
// loop through contents until we find the first signature match
|
// loop through contents until we find the first signature match
|
||||||
List<ArchiveData> archiveFiles = new List<ArchiveData>();
|
List<ArchiveData> archiveFiles = new List<ArchiveData>();
|
||||||
@@ -116,12 +116,13 @@ namespace gaseous_server.Classes
|
|||||||
{
|
{
|
||||||
FileInfo zfi = new FileInfo(file);
|
FileInfo zfi = new FileInfo(file);
|
||||||
Common.hashObject zhash = new Common.hashObject(file);
|
Common.hashObject zhash = new Common.hashObject(file);
|
||||||
|
|
||||||
Logging.Log(Logging.LogType.Information, "Get Signature", "Checking signature of decompressed file " + file);
|
Logging.Log(Logging.LogType.Information, "Get Signature", "Checking signature of decompressed file " + file);
|
||||||
|
|
||||||
if (zfi != null)
|
if (zfi != null)
|
||||||
{
|
{
|
||||||
ArchiveData archiveData = new ArchiveData{
|
ArchiveData archiveData = new ArchiveData
|
||||||
|
{
|
||||||
FileName = Path.GetFileName(file),
|
FileName = Path.GetFileName(file),
|
||||||
FilePath = zfi.Directory.FullName.Replace(ExtractPath, ""),
|
FilePath = zfi.Directory.FullName.Replace(ExtractPath, ""),
|
||||||
Size = zfi.Length,
|
Size = zfi.Length,
|
||||||
@@ -138,7 +139,7 @@ namespace gaseous_server.Classes
|
|||||||
if (zDiscoveredSignature.Score > discoveredSignature.Score)
|
if (zDiscoveredSignature.Score > discoveredSignature.Score)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
zDiscoveredSignature.Rom.SignatureSource == gaseous_server.Models.Signatures_Games.RomItem.SignatureSourceType.MAMEArcade ||
|
zDiscoveredSignature.Rom.SignatureSource == gaseous_server.Models.Signatures_Games.RomItem.SignatureSourceType.MAMEArcade ||
|
||||||
zDiscoveredSignature.Rom.SignatureSource == gaseous_server.Models.Signatures_Games.RomItem.SignatureSourceType.MAMEMess
|
zDiscoveredSignature.Rom.SignatureSource == gaseous_server.Models.Signatures_Games.RomItem.SignatureSourceType.MAMEMess
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -195,7 +196,7 @@ namespace gaseous_server.Classes
|
|||||||
{
|
{
|
||||||
// signature retrieved from Hasheous
|
// signature retrieved from Hasheous
|
||||||
Logging.Log(Logging.LogType.Information, "Import Game", "Signature retrieved from Hasheous for game: " + dbSignature.Game.Name);
|
Logging.Log(Logging.LogType.Information, "Import Game", "Signature retrieved from Hasheous for game: " + dbSignature.Game.Name);
|
||||||
|
|
||||||
discoveredSignature = dbSignature;
|
discoveredSignature = dbSignature;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -203,7 +204,7 @@ namespace gaseous_server.Classes
|
|||||||
// construct a signature from file data
|
// construct a signature from file data
|
||||||
dbSignature = _GetFileSignatureFromFileData(hash, ImageName, ImageExtension, ImageSize, GameFileImportPath);
|
dbSignature = _GetFileSignatureFromFileData(hash, ImageName, ImageExtension, ImageSize, GameFileImportPath);
|
||||||
Logging.Log(Logging.LogType.Information, "Import Game", "Signature generated from provided file for game: " + dbSignature.Game.Name);
|
Logging.Log(Logging.LogType.Information, "Import Game", "Signature generated from provided file for game: " + dbSignature.Game.Name);
|
||||||
|
|
||||||
discoveredSignature = dbSignature;
|
discoveredSignature = dbSignature;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,8 +217,8 @@ namespace gaseous_server.Classes
|
|||||||
return discoveredSignature;
|
return discoveredSignature;
|
||||||
}
|
}
|
||||||
|
|
||||||
private gaseous_server.Models.Signatures_Games? _GetFileSignatureFromDatabase(Common.hashObject hash, string ImageName, string ImageExtension, long ImageSize, string GameFileImportPath)
|
private gaseous_server.Models.Signatures_Games? _GetFileSignatureFromDatabase(Common.hashObject hash, string ImageName, string ImageExtension, long ImageSize, string GameFileImportPath)
|
||||||
{
|
{
|
||||||
Logging.Log(Logging.LogType.Information, "Get Signature", "Checking local database for MD5: " + hash.md5hash);
|
Logging.Log(Logging.LogType.Information, "Get Signature", "Checking local database for MD5: " + hash.md5hash);
|
||||||
|
|
||||||
// check 1: do we have a signature for it?
|
// check 1: do we have a signature for it?
|
||||||
@@ -264,37 +265,47 @@ namespace gaseous_server.Classes
|
|||||||
if (Config.MetadataConfiguration.SignatureSource == HasheousClient.Models.MetadataModel.SignatureSources.Hasheous)
|
if (Config.MetadataConfiguration.SignatureSource == HasheousClient.Models.MetadataModel.SignatureSources.Hasheous)
|
||||||
{
|
{
|
||||||
HasheousClient.Hasheous hasheous = new HasheousClient.Hasheous();
|
HasheousClient.Hasheous hasheous = new HasheousClient.Hasheous();
|
||||||
SignatureLookupItem? HasheousResult = hasheous.RetrieveFromHasheousAsync(new HashLookupModel{
|
SignatureLookupItem? HasheousResult = null;
|
||||||
MD5 = hash.md5hash,
|
|
||||||
SHA1 = hash.sha1hash
|
|
||||||
});
|
|
||||||
|
|
||||||
if (HasheousResult != null)
|
try
|
||||||
{
|
{
|
||||||
if (HasheousResult.Signature != null)
|
HasheousResult = hasheous.RetrieveFromHasheousAsync(new HashLookupModel
|
||||||
{
|
{
|
||||||
gaseous_server.Models.Signatures_Games signature = new Models.Signatures_Games();
|
MD5 = hash.md5hash,
|
||||||
signature.Game = HasheousResult.Signature.Game;
|
SHA1 = hash.sha1hash
|
||||||
signature.Rom = HasheousResult.Signature.Rom;
|
});
|
||||||
|
|
||||||
if (HasheousResult.MetadataResults != null)
|
if (HasheousResult != null)
|
||||||
|
{
|
||||||
|
if (HasheousResult.Signature != null)
|
||||||
{
|
{
|
||||||
if (HasheousResult.MetadataResults.Count > 0)
|
gaseous_server.Models.Signatures_Games signature = new Models.Signatures_Games();
|
||||||
|
signature.Game = HasheousResult.Signature.Game;
|
||||||
|
signature.Rom = HasheousResult.Signature.Rom;
|
||||||
|
|
||||||
|
if (HasheousResult.MetadataResults != null)
|
||||||
{
|
{
|
||||||
foreach (SignatureLookupItem.MetadataResult metadataResult in HasheousResult.MetadataResults)
|
if (HasheousResult.MetadataResults.Count > 0)
|
||||||
{
|
{
|
||||||
if (metadataResult.Source == MetadataModel.MetadataSources.IGDB)
|
foreach (SignatureLookupItem.MetadataResult metadataResult in HasheousResult.MetadataResults)
|
||||||
{
|
{
|
||||||
signature.Flags.IGDBPlatformId = (long)metadataResult.PlatformId;
|
if (metadataResult.Source == MetadataModel.MetadataSources.IGDB)
|
||||||
signature.Flags.IGDBGameId = (long)metadataResult.GameId;
|
{
|
||||||
|
signature.Flags.IGDBPlatformId = (long)metadataResult.PlatformId;
|
||||||
|
signature.Flags.IGDBGameId = (long)metadataResult.GameId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return signature;
|
return signature;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.Log(Logging.LogType.Warning, "Get Signature", "Error retrieving signature from Hasheous", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@@ -16,48 +16,49 @@ using HasheousClient.Models;
|
|||||||
|
|
||||||
namespace gaseous_server.Classes
|
namespace gaseous_server.Classes
|
||||||
{
|
{
|
||||||
public class ImportGame : QueueItemStatus
|
public class ImportGame : QueueItemStatus
|
||||||
{
|
{
|
||||||
public void ProcessDirectory(string ImportPath)
|
public void ProcessDirectory(string ImportPath)
|
||||||
{
|
{
|
||||||
if (Directory.Exists(ImportPath))
|
if (Directory.Exists(ImportPath))
|
||||||
{
|
{
|
||||||
string[] importContents = Directory.GetFiles(ImportPath, "*.*", SearchOption.AllDirectories);
|
string[] importContents = Directory.GetFiles(ImportPath, "*.*", SearchOption.AllDirectories);
|
||||||
|
|
||||||
Logging.Log(Logging.LogType.Information, "Import Games", "Found " + importContents.Length + " files to process in import directory: " + ImportPath);
|
Logging.Log(Logging.LogType.Information, "Import Games", "Found " + importContents.Length + " files to process in import directory: " + ImportPath);
|
||||||
|
|
||||||
// import files first
|
// import files first
|
||||||
int importCount = 1;
|
int importCount = 1;
|
||||||
foreach (string importContent in importContents) {
|
foreach (string importContent in importContents)
|
||||||
|
{
|
||||||
SetStatus(importCount, importContents.Length, "Importing file: " + importContent);
|
SetStatus(importCount, importContents.Length, "Importing file: " + importContent);
|
||||||
|
|
||||||
ImportGameFile(importContent, null);
|
ImportGameFile(importContent, null);
|
||||||
|
|
||||||
importCount += 1;
|
importCount += 1;
|
||||||
}
|
}
|
||||||
ClearStatus();
|
ClearStatus();
|
||||||
|
|
||||||
DeleteOrphanedDirectories(ImportPath);
|
DeleteOrphanedDirectories(ImportPath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Logging.Log(Logging.LogType.Critical, "Import Games", "The import directory " + ImportPath + " does not exist.");
|
Logging.Log(Logging.LogType.Critical, "Import Games", "The import directory " + ImportPath + " does not exist.");
|
||||||
throw new DirectoryNotFoundException("Invalid path: " + ImportPath);
|
throw new DirectoryNotFoundException("Invalid path: " + ImportPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ImportGameFile(string GameFileImportPath, IGDB.Models.Platform? OverridePlatform)
|
public void ImportGameFile(string GameFileImportPath, IGDB.Models.Platform? OverridePlatform)
|
||||||
{
|
{
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
string sql = "";
|
string sql = "";
|
||||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
|
|
||||||
if (Common.SkippableFiles.Contains<string>(Path.GetFileName(GameFileImportPath), StringComparer.OrdinalIgnoreCase))
|
if (Common.SkippableFiles.Contains<string>(Path.GetFileName(GameFileImportPath), StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logging.Log(Logging.LogType.Debug, "Import Game", "Skipping item " + GameFileImportPath);
|
Logging.Log(Logging.LogType.Debug, "Import Game", "Skipping item " + GameFileImportPath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FileInfo fi = new FileInfo(GameFileImportPath);
|
FileInfo fi = new FileInfo(GameFileImportPath);
|
||||||
Common.hashObject hash = new Common.hashObject(GameFileImportPath);
|
Common.hashObject hash = new Common.hashObject(GameFileImportPath);
|
||||||
|
|
||||||
@@ -87,7 +88,7 @@ namespace gaseous_server.Classes
|
|||||||
}
|
}
|
||||||
File.Move(GameFileImportPath, targetPathWithFileName, true);
|
File.Move(GameFileImportPath, targetPathWithFileName, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// import source was the upload directory
|
// import source was the upload directory
|
||||||
if (GameFileImportPath.StartsWith(Config.LibraryConfiguration.LibraryUploadDirectory))
|
if (GameFileImportPath.StartsWith(Config.LibraryConfiguration.LibraryUploadDirectory))
|
||||||
{
|
{
|
||||||
@@ -146,8 +147,8 @@ namespace gaseous_server.Classes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IGDB.Models.Game SearchForGame(gaseous_server.Models.Signatures_Games Signature, long PlatformId, bool FullDownload)
|
public static IGDB.Models.Game SearchForGame(gaseous_server.Models.Signatures_Games Signature, long PlatformId, bool FullDownload)
|
||||||
{
|
{
|
||||||
@@ -173,14 +174,20 @@ namespace gaseous_server.Classes
|
|||||||
string GameName = Signature.Game.Name;
|
string GameName = Signature.Game.Name;
|
||||||
|
|
||||||
List<string> SearchCandidates = GetSearchCandidates(GameName);
|
List<string> SearchCandidates = GetSearchCandidates(GameName);
|
||||||
|
|
||||||
foreach (string SearchCandidate in SearchCandidates)
|
foreach (string SearchCandidate in SearchCandidates)
|
||||||
{
|
{
|
||||||
bool GameFound = false;
|
bool GameFound = false;
|
||||||
|
|
||||||
Logging.Log(Logging.LogType.Information, "Import Game", " Searching for title: " + SearchCandidate);
|
Logging.Log(Logging.LogType.Information, "Import Game", " Searching for title: " + SearchCandidate);
|
||||||
|
|
||||||
foreach (Metadata.Games.SearchType searchType in Enum.GetValues(typeof(Metadata.Games.SearchType)))
|
List<Metadata.Games.SearchType> allowedSearchTypes = Config.ReadSetting<List<Metadata.Games.SearchType>>("DefaultSearchMethods", new List<gaseous_server.Classes.Metadata.Games.SearchType>() {
|
||||||
|
Games.SearchType.where,
|
||||||
|
Games.SearchType.wherefuzzy,
|
||||||
|
Games.SearchType.search,
|
||||||
|
Games.SearchType.searchNoPlatform
|
||||||
|
});
|
||||||
|
foreach (Metadata.Games.SearchType searchType in allowedSearchTypes)
|
||||||
{
|
{
|
||||||
Logging.Log(Logging.LogType.Information, "Import Game", " Search type: " + searchType.ToString());
|
Logging.Log(Logging.LogType.Information, "Import Game", " Search type: " + searchType.ToString());
|
||||||
IGDB.Models.Game[] games = Metadata.Games.SearchForGame(SearchCandidate, PlatformId, searchType);
|
IGDB.Models.Game[] games = Metadata.Games.SearchForGame(SearchCandidate, PlatformId, searchType);
|
||||||
@@ -197,8 +204,10 @@ namespace gaseous_server.Classes
|
|||||||
Logging.Log(Logging.LogType.Information, "Import Game", " " + games.Length + " search results found");
|
Logging.Log(Logging.LogType.Information, "Import Game", " " + games.Length + " search results found");
|
||||||
|
|
||||||
// quite likely we've found sequels and alternate types
|
// quite likely we've found sequels and alternate types
|
||||||
foreach (Game game in games) {
|
foreach (Game game in games)
|
||||||
if (game.Name == SearchCandidate) {
|
{
|
||||||
|
if (game.Name == SearchCandidate)
|
||||||
|
{
|
||||||
// found game title matches the search candidate
|
// found game title matches the search candidate
|
||||||
determinedGame = Metadata.Games.GetGame((long)games[0].Id, false, false, false);
|
determinedGame = Metadata.Games.GetGame((long)games[0].Id, false, false, false);
|
||||||
Logging.Log(Logging.LogType.Information, "Import Game", "Found exact match!");
|
Logging.Log(Logging.LogType.Information, "Import Game", "Found exact match!");
|
||||||
@@ -236,7 +245,13 @@ namespace gaseous_server.Classes
|
|||||||
|
|
||||||
foreach (string SearchCandidate in SearchCandidates)
|
foreach (string SearchCandidate in SearchCandidates)
|
||||||
{
|
{
|
||||||
foreach (Metadata.Games.SearchType searchType in Enum.GetValues(typeof(Metadata.Games.SearchType)))
|
List<Metadata.Games.SearchType> allowedSearchTypes = Config.ReadSetting<List<Metadata.Games.SearchType>>("DefaultSearchMethods", new List<gaseous_server.Classes.Metadata.Games.SearchType>() {
|
||||||
|
Games.SearchType.where,
|
||||||
|
Games.SearchType.wherefuzzy,
|
||||||
|
Games.SearchType.search,
|
||||||
|
Games.SearchType.searchNoPlatform
|
||||||
|
});
|
||||||
|
foreach (Metadata.Games.SearchType searchType in allowedSearchTypes)
|
||||||
{
|
{
|
||||||
if ((PlatformId == 0 && searchType == SearchType.searchNoPlatform) || (PlatformId != 0 && searchType != SearchType.searchNoPlatform))
|
if ((PlatformId == 0 && searchType == SearchType.searchNoPlatform) || (PlatformId != 0 && searchType != SearchType.searchNoPlatform))
|
||||||
{
|
{
|
||||||
@@ -273,7 +288,8 @@ namespace gaseous_server.Classes
|
|||||||
|
|
||||||
// assumption: no games have () in their titles so we'll remove them
|
// assumption: no games have () in their titles so we'll remove them
|
||||||
int idx = GameName.IndexOf('(');
|
int idx = GameName.IndexOf('(');
|
||||||
if (idx >= 0) {
|
if (idx >= 0)
|
||||||
|
{
|
||||||
GameName = GameName.Substring(0, idx);
|
GameName = GameName.Substring(0, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,7 +321,8 @@ namespace gaseous_server.Classes
|
|||||||
if (UpdateId == 0)
|
if (UpdateId == 0)
|
||||||
{
|
{
|
||||||
sql = "INSERT INTO Games_Roms (PlatformId, GameId, Name, Size, CRC, MD5, SHA1, DevelopmentStatus, Attributes, RomType, RomTypeMedia, MediaLabel, Path, MetadataSource, MetadataGameName, MetadataVersion, LibraryId) VALUES (@platformid, @gameid, @name, @size, @crc, @md5, @sha1, @developmentstatus, @Attributes, @romtype, @romtypemedia, @medialabel, @path, @metadatasource, @metadatagamename, @metadataversion, @libraryid); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
sql = "INSERT INTO Games_Roms (PlatformId, GameId, Name, Size, CRC, MD5, SHA1, DevelopmentStatus, Attributes, RomType, RomTypeMedia, MediaLabel, Path, MetadataSource, MetadataGameName, MetadataVersion, LibraryId) VALUES (@platformid, @gameid, @name, @size, @crc, @md5, @sha1, @developmentstatus, @Attributes, @romtype, @romtypemedia, @medialabel, @path, @metadatasource, @metadatagamename, @metadataversion, @libraryid); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
sql = "UPDATE Games_Roms SET PlatformId=@platformid, GameId=@gameid, Name=@name, Size=@size, DevelopmentStatus=@developmentstatus, Attributes=@Attributes, RomType=@romtype, RomTypeMedia=@romtypemedia, MediaLabel=@medialabel, MetadataSource=@metadatasource, MetadataGameName=@metadatagamename, MetadataVersion=@metadataversion WHERE Id=@id;";
|
sql = "UPDATE Games_Roms SET PlatformId=@platformid, GameId=@gameid, Name=@name, Size=@size, DevelopmentStatus=@developmentstatus, Attributes=@Attributes, RomType=@romtype, RomTypeMedia=@romtypemedia, MediaLabel=@medialabel, MetadataSource=@metadatasource, MetadataGameName=@metadatagamename, MetadataVersion=@metadataversion WHERE Id=@id;";
|
||||||
dbDict.Add("id", UpdateId);
|
dbDict.Add("id", UpdateId);
|
||||||
@@ -348,7 +365,8 @@ namespace gaseous_server.Classes
|
|||||||
if (UpdateId == 0)
|
if (UpdateId == 0)
|
||||||
{
|
{
|
||||||
romId = (long)romInsert.Rows[0][0];
|
romId = (long)romInsert.Rows[0][0];
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
romId = UpdateId;
|
romId = UpdateId;
|
||||||
}
|
}
|
||||||
@@ -362,73 +380,70 @@ namespace gaseous_server.Classes
|
|||||||
return romId;
|
return romId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ComputeROMPath(long RomId)
|
public static string ComputeROMPath(long RomId)
|
||||||
{
|
{
|
||||||
Classes.Roms.GameRomItem rom = Classes.Roms.GetRom(RomId);
|
|
||||||
|
|
||||||
// get metadata
|
|
||||||
IGDB.Models.Platform platform = gaseous_server.Classes.Metadata.Platforms.GetPlatform(rom.PlatformId);
|
|
||||||
IGDB.Models.Game game = gaseous_server.Classes.Metadata.Games.GetGame(rom.GameId, false, false, false);
|
|
||||||
|
|
||||||
// build path
|
|
||||||
string platformSlug = "Unknown Platform";
|
|
||||||
if (platform != null)
|
|
||||||
{
|
|
||||||
platformSlug = platform.Slug;
|
|
||||||
}
|
|
||||||
string gameSlug = "Unknown Title";
|
|
||||||
if (game != null)
|
|
||||||
{
|
|
||||||
gameSlug = game.Slug;
|
|
||||||
}
|
|
||||||
string DestinationPath = Path.Combine(GameLibrary.GetDefaultLibrary.Path, gameSlug, platformSlug);
|
|
||||||
if (!Directory.Exists(DestinationPath))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(DestinationPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
string DestinationPathName = Path.Combine(DestinationPath, rom.Name);
|
|
||||||
|
|
||||||
return DestinationPathName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool MoveGameFile(long RomId)
|
|
||||||
{
|
|
||||||
Classes.Roms.GameRomItem rom = Classes.Roms.GetRom(RomId);
|
Classes.Roms.GameRomItem rom = Classes.Roms.GetRom(RomId);
|
||||||
string romPath = rom.Path;
|
|
||||||
|
// get metadata
|
||||||
|
IGDB.Models.Platform platform = gaseous_server.Classes.Metadata.Platforms.GetPlatform(rom.PlatformId);
|
||||||
|
IGDB.Models.Game game = gaseous_server.Classes.Metadata.Games.GetGame(rom.GameId, false, false, false);
|
||||||
|
|
||||||
|
// build path
|
||||||
|
string platformSlug = "Unknown Platform";
|
||||||
|
if (platform != null)
|
||||||
|
{
|
||||||
|
platformSlug = platform.Slug;
|
||||||
|
}
|
||||||
|
string gameSlug = "Unknown Title";
|
||||||
|
if (game != null)
|
||||||
|
{
|
||||||
|
gameSlug = game.Slug;
|
||||||
|
}
|
||||||
|
string DestinationPath = Path.Combine(GameLibrary.GetDefaultLibrary.Path, gameSlug, platformSlug);
|
||||||
|
if (!Directory.Exists(DestinationPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(DestinationPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
string DestinationPathName = Path.Combine(DestinationPath, rom.Name);
|
||||||
|
|
||||||
|
return DestinationPathName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool MoveGameFile(long RomId)
|
||||||
|
{
|
||||||
|
Classes.Roms.GameRomItem rom = Classes.Roms.GetRom(RomId);
|
||||||
|
string romPath = rom.Path;
|
||||||
|
|
||||||
if (File.Exists(romPath))
|
if (File.Exists(romPath))
|
||||||
{
|
{
|
||||||
string DestinationPath = ComputeROMPath(RomId);
|
string DestinationPath = ComputeROMPath(RomId);
|
||||||
|
|
||||||
if (romPath == DestinationPath)
|
if (romPath == DestinationPath)
|
||||||
{
|
{
|
||||||
Logging.Log(Logging.LogType.Debug, "Move Game ROM", "Destination path is the same as the current path - aborting");
|
Logging.Log(Logging.LogType.Debug, "Move Game ROM", "Destination path is the same as the current path - aborting");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Logging.Log(Logging.LogType.Information, "Move Game ROM", "Moving " + romPath + " to " + DestinationPath);
|
Logging.Log(Logging.LogType.Information, "Move Game ROM", "Moving " + romPath + " to " + DestinationPath);
|
||||||
if (File.Exists(DestinationPath))
|
if (File.Exists(DestinationPath))
|
||||||
{
|
{
|
||||||
Logging.Log(Logging.LogType.Information, "Move Game ROM", "A file with the same name exists at the destination - aborting");
|
Logging.Log(Logging.LogType.Information, "Move Game ROM", "A file with the same name exists at the destination - overwriting");
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
File.Move(romPath, DestinationPath);
|
|
||||||
|
|
||||||
// update the db
|
File.Move(romPath, DestinationPath, true);
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
|
||||||
string sql = "UPDATE Games_Roms SET Path=@path WHERE Id=@id";
|
|
||||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
|
||||||
dbDict.Add("id", RomId);
|
|
||||||
dbDict.Add("path", DestinationPath);
|
|
||||||
db.ExecuteCMD(sql, dbDict);
|
|
||||||
|
|
||||||
return true;
|
// update the db
|
||||||
}
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
}
|
string sql = "UPDATE Games_Roms SET Path=@path WHERE Id=@id";
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
|
dbDict.Add("id", RomId);
|
||||||
|
dbDict.Add("path", DestinationPath);
|
||||||
|
db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -437,8 +452,8 @@ namespace gaseous_server.Classes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OrganiseLibrary()
|
public void OrganiseLibrary()
|
||||||
{
|
{
|
||||||
Logging.Log(Logging.LogType.Information, "Organise Library", "Starting default library organisation");
|
Logging.Log(Logging.LogType.Information, "Organise Library", "Starting default library organisation");
|
||||||
|
|
||||||
GameLibrary.LibraryItem library = GameLibrary.GetDefaultLibrary;
|
GameLibrary.LibraryItem library = GameLibrary.GetDefaultLibrary;
|
||||||
@@ -451,19 +466,19 @@ namespace gaseous_server.Classes
|
|||||||
DataTable romDT = db.ExecuteCMD(sql, dbDict);
|
DataTable romDT = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
if (romDT.Rows.Count > 0)
|
if (romDT.Rows.Count > 0)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < romDT.Rows.Count; i++)
|
for (int i = 0; i < romDT.Rows.Count; i++)
|
||||||
{
|
{
|
||||||
SetStatus(i, romDT.Rows.Count, "Processing file " + romDT.Rows[i]["name"]);
|
SetStatus(i, romDT.Rows.Count, "Processing file " + romDT.Rows[i]["name"]);
|
||||||
Logging.Log(Logging.LogType.Information, "Organise Library", "(" + i + "/" + romDT.Rows.Count + ") Processing ROM " + romDT.Rows[i]["name"]);
|
Logging.Log(Logging.LogType.Information, "Organise Library", "(" + i + "/" + romDT.Rows.Count + ") Processing ROM " + romDT.Rows[i]["name"]);
|
||||||
long RomId = (long)romDT.Rows[i]["id"];
|
long RomId = (long)romDT.Rows[i]["id"];
|
||||||
MoveGameFile(RomId);
|
MoveGameFile(RomId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ClearStatus();
|
ClearStatus();
|
||||||
|
|
||||||
// clean up empty directories
|
// clean up empty directories
|
||||||
DeleteOrphanedDirectories(GameLibrary.GetDefaultLibrary.Path);
|
DeleteOrphanedDirectories(GameLibrary.GetDefaultLibrary.Path);
|
||||||
|
|
||||||
Logging.Log(Logging.LogType.Information, "Organise Library", "Finsihed default library organisation");
|
Logging.Log(Logging.LogType.Information, "Organise Library", "Finsihed default library organisation");
|
||||||
}
|
}
|
||||||
@@ -476,7 +491,7 @@ namespace gaseous_server.Classes
|
|||||||
|
|
||||||
string[] files = Directory.GetFiles(directory);
|
string[] files = Directory.GetFiles(directory);
|
||||||
string[] directories = Directory.GetDirectories(directory);
|
string[] directories = Directory.GetDirectories(directory);
|
||||||
|
|
||||||
if (files.Length == 0 &&
|
if (files.Length == 0 &&
|
||||||
directories.Length == 0)
|
directories.Length == 0)
|
||||||
{
|
{
|
||||||
@@ -563,7 +578,7 @@ namespace gaseous_server.Classes
|
|||||||
|
|
||||||
public void LibrarySpecificScan(GameLibrary.LibraryItem library)
|
public void LibrarySpecificScan(GameLibrary.LibraryItem library)
|
||||||
{
|
{
|
||||||
|
|
||||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Starting scan of library: " + library.Name);
|
Logging.Log(Logging.LogType.Information, "Library Scan", "Starting scan of library: " + library.Name);
|
||||||
|
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
@@ -632,7 +647,7 @@ namespace gaseous_server.Classes
|
|||||||
{
|
{
|
||||||
// file is not in database - process it
|
// file is not in database - process it
|
||||||
Logging.Log(Logging.LogType.Information, "Library Scan", "Orphaned file found in library: " + LibraryFile);
|
Logging.Log(Logging.LogType.Information, "Library Scan", "Orphaned file found in library: " + LibraryFile);
|
||||||
|
|
||||||
Common.hashObject hash = new Common.hashObject(LibraryFile);
|
Common.hashObject hash = new Common.hashObject(LibraryFile);
|
||||||
FileInfo fi = new FileInfo(LibraryFile);
|
FileInfo fi = new FileInfo(LibraryFile);
|
||||||
|
|
||||||
@@ -644,8 +659,8 @@ namespace gaseous_server.Classes
|
|||||||
// get discovered platform
|
// get discovered platform
|
||||||
long PlatformId;
|
long PlatformId;
|
||||||
IGDB.Models.Platform determinedPlatform;
|
IGDB.Models.Platform determinedPlatform;
|
||||||
|
|
||||||
if (sig.Flags.IGDBPlatformId == null || sig.Flags.IGDBPlatformId == 0 )
|
if (sig.Flags.IGDBPlatformId == null || sig.Flags.IGDBPlatformId == 0)
|
||||||
{
|
{
|
||||||
// no platform discovered in the signature
|
// no platform discovered in the signature
|
||||||
PlatformId = library.DefaultPlatformId;
|
PlatformId = library.DefaultPlatformId;
|
||||||
@@ -770,8 +785,8 @@ namespace gaseous_server.Classes
|
|||||||
// get discovered platform
|
// get discovered platform
|
||||||
long PlatformId;
|
long PlatformId;
|
||||||
IGDB.Models.Platform determinedPlatform;
|
IGDB.Models.Platform determinedPlatform;
|
||||||
|
|
||||||
if (sig.Flags.IGDBPlatformId == null || sig.Flags.IGDBPlatformId == 0 )
|
if (sig.Flags.IGDBPlatformId == null || sig.Flags.IGDBPlatformId == 0)
|
||||||
{
|
{
|
||||||
// no platform discovered in the signature
|
// no platform discovered in the signature
|
||||||
PlatformId = library.DefaultPlatformId;
|
PlatformId = library.DefaultPlatformId;
|
||||||
|
@@ -5,7 +5,7 @@ using Microsoft.VisualStudio.Web.CodeGeneration;
|
|||||||
|
|
||||||
namespace gaseous_server.Classes
|
namespace gaseous_server.Classes
|
||||||
{
|
{
|
||||||
public class Maintenance : QueueItemStatus
|
public class Maintenance : QueueItemStatus
|
||||||
{
|
{
|
||||||
const int MaxFileAge = 30;
|
const int MaxFileAge = 30;
|
||||||
|
|
||||||
@@ -16,6 +16,7 @@ namespace gaseous_server.Classes
|
|||||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
|
|
||||||
// remove any entries from the library that have an invalid id
|
// remove any entries from the library that have an invalid id
|
||||||
|
Logging.Log(Logging.LogType.Information, "Maintenance", "Removing any entries from the library that have an invalid id");
|
||||||
string LibraryWhereClause = "";
|
string LibraryWhereClause = "";
|
||||||
foreach (GameLibrary.LibraryItem library in GameLibrary.GetLibraries)
|
foreach (GameLibrary.LibraryItem library in GameLibrary.GetLibraries)
|
||||||
{
|
{
|
||||||
@@ -33,9 +34,27 @@ namespace gaseous_server.Classes
|
|||||||
}
|
}
|
||||||
|
|
||||||
// delete old logs
|
// delete old logs
|
||||||
sql = "DELETE FROM ServerLogs WHERE EventTime < @EventRetentionDate;";
|
Logging.Log(Logging.LogType.Information, "Maintenance", "Removing logs older than " + Config.LoggingConfiguration.LogRetention + " days");
|
||||||
|
long deletedCount = 1;
|
||||||
|
long deletedEventCount = 0;
|
||||||
|
long maxLoops = 1000;
|
||||||
|
sql = "DELETE FROM ServerLogs WHERE EventTime < @EventRetentionDate LIMIT 1000; SELECT ROW_COUNT() AS Count;";
|
||||||
dbDict.Add("EventRetentionDate", DateTime.UtcNow.AddDays(Config.LoggingConfiguration.LogRetention * -1));
|
dbDict.Add("EventRetentionDate", DateTime.UtcNow.AddDays(Config.LoggingConfiguration.LogRetention * -1));
|
||||||
db.ExecuteCMD(sql, dbDict);
|
while (deletedCount > 0)
|
||||||
|
{
|
||||||
|
DataTable deletedCountTable = db.ExecuteCMD(sql, dbDict);
|
||||||
|
deletedCount = (long)deletedCountTable.Rows[0][0];
|
||||||
|
deletedEventCount += deletedCount;
|
||||||
|
|
||||||
|
// check if we've hit the limit
|
||||||
|
maxLoops -= 1;
|
||||||
|
if (maxLoops <= 0)
|
||||||
|
{
|
||||||
|
Logging.Log(Logging.LogType.Warning, "Maintenance", "Hit the maximum number of loops for deleting logs. Stopping.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Logging.Log(Logging.LogType.Information, "Maintenance", "Deleted " + deletedEventCount + " log entries");
|
||||||
|
|
||||||
// delete files and directories older than 7 days in PathsToClean
|
// delete files and directories older than 7 days in PathsToClean
|
||||||
List<string> PathsToClean = new List<string>();
|
List<string> PathsToClean = new List<string>();
|
||||||
@@ -87,7 +106,7 @@ namespace gaseous_server.Classes
|
|||||||
SetStatus(StatusCounter, tables.Rows.Count, "Optimising table " + row[0].ToString());
|
SetStatus(StatusCounter, tables.Rows.Count, "Optimising table " + row[0].ToString());
|
||||||
|
|
||||||
sql = "OPTIMIZE TABLE " + row[0].ToString();
|
sql = "OPTIMIZE TABLE " + row[0].ToString();
|
||||||
DataTable response = db.ExecuteCMD(sql);
|
DataTable response = db.ExecuteCMD(sql, new Dictionary<string, object>(), 240);
|
||||||
foreach (DataRow responseRow in response.Rows)
|
foreach (DataRow responseRow in response.Rows)
|
||||||
{
|
{
|
||||||
string retVal = "";
|
string retVal = "";
|
||||||
|
@@ -7,7 +7,7 @@ using Microsoft.CodeAnalysis.Elfie.Model.Strings;
|
|||||||
|
|
||||||
namespace gaseous_server.Classes.Metadata
|
namespace gaseous_server.Classes.Metadata
|
||||||
{
|
{
|
||||||
public class Covers
|
public class Covers
|
||||||
{
|
{
|
||||||
const string fieldList = "fields alpha_channel,animated,checksum,game,game_localization,height,image_id,url,width;";
|
const string fieldList = "fields alpha_channel,animated,checksum,game,game_localization,height,image_id,url,width;";
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
returnValue = await GetObjectFromServer(WhereClause, ImagePath);
|
returnValue = await GetObjectFromServer(WhereClause, ImagePath);
|
||||||
Storage.NewCacheValue(returnValue);
|
Storage.NewCacheValue(returnValue);
|
||||||
forceImageDownload = true;
|
forceImageDownload = true;
|
||||||
break;
|
break;
|
||||||
case Storage.CacheStatus.Expired:
|
case Storage.CacheStatus.Expired:
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -135,6 +135,6 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,9 +5,9 @@ using IGDB.Models;
|
|||||||
|
|
||||||
namespace gaseous_server.Classes.Metadata
|
namespace gaseous_server.Classes.Metadata
|
||||||
{
|
{
|
||||||
public class Games
|
public class Games
|
||||||
{
|
{
|
||||||
const string fieldList = "fields age_ratings,aggregated_rating,aggregated_rating_count,alternative_names,artworks,bundles,category,checksum,collection,collections,cover,created_at,dlcs,expanded_games,expansions,external_games,first_release_date,follows,forks,franchise,franchises,game_engines,game_localizations,game_modes,genres,hypes,involved_companies,keywords,language_supports,multiplayer_modes,name,parent_game,platforms,player_perspectives,ports,rating,rating_count,release_dates,remakes,remasters,screenshots,similar_games,slug,standalone_expansions,status,storyline,summary,tags,themes,total_rating,total_rating_count,updated_at,url,version_parent,version_title,videos,websites;";
|
const string fieldList = "fields age_ratings,aggregated_rating,aggregated_rating_count,alternative_names,artworks,bundles,category,checksum,collections,cover,created_at,dlcs,expanded_games,expansions,external_games,first_release_date,follows,forks,franchise,franchises,game_engines,game_localizations,game_modes,genres,hypes,involved_companies,keywords,language_supports,multiplayer_modes,name,parent_game,platforms,player_perspectives,ports,rating,rating_count,release_dates,remakes,remasters,screenshots,similar_games,slug,standalone_expansions,status,storyline,summary,tags,themes,total_rating,total_rating_count,updated_at,url,version_parent,version_title,videos,websites;";
|
||||||
|
|
||||||
public Games()
|
public Games()
|
||||||
{
|
{
|
||||||
@@ -15,9 +15,9 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class InvalidGameId : Exception
|
public class InvalidGameId : Exception
|
||||||
{
|
{
|
||||||
public InvalidGameId(long Id) : base("Unable to find Game by id " + Id)
|
public InvalidGameId(long Id) : base("Unable to find Game by id " + Id)
|
||||||
{}
|
{ }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Game? GetGame(long Id, bool getAllMetadata, bool followSubGames, bool forceRefresh)
|
public static Game? GetGame(long Id, bool getAllMetadata, bool followSubGames, bool forceRefresh)
|
||||||
@@ -78,15 +78,17 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
if (cacheStatus == Storage.CacheStatus.Current) { cacheStatus = Storage.CacheStatus.Expired; }
|
if (cacheStatus == Storage.CacheStatus.Current) { cacheStatus = Storage.CacheStatus.Expired; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// set up where clause
|
|
||||||
string WhereClause = "";
|
string WhereClause = "";
|
||||||
|
string searchField = "";
|
||||||
switch (searchUsing)
|
switch (searchUsing)
|
||||||
{
|
{
|
||||||
case SearchUsing.id:
|
case SearchUsing.id:
|
||||||
WhereClause = "where id = " + searchValue;
|
WhereClause = "where id = " + searchValue;
|
||||||
|
searchField = "id";
|
||||||
break;
|
break;
|
||||||
case SearchUsing.slug:
|
case SearchUsing.slug:
|
||||||
WhereClause = "where slug = " + searchValue;
|
WhereClause = "where slug = \"" + searchValue + "\"";
|
||||||
|
searchField = "slug";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Exception("Invalid search type");
|
throw new Exception("Invalid search type");
|
||||||
@@ -110,11 +112,11 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||||
returnValue = Storage.GetCacheValue<Game>(returnValue, "id", (long)searchValue);
|
returnValue = Storage.GetCacheValue<Game>(returnValue, searchField, searchValue);
|
||||||
}
|
}
|
||||||
return returnValue;
|
return returnValue;
|
||||||
case Storage.CacheStatus.Current:
|
case Storage.CacheStatus.Current:
|
||||||
returnValue = Storage.GetCacheValue<Game>(returnValue, "id", (long)searchValue);
|
returnValue = Storage.GetCacheValue<Game>(returnValue, searchField, searchValue);
|
||||||
UpdateSubClasses(returnValue, false, false, false);
|
UpdateSubClasses(returnValue, false, false, false);
|
||||||
return returnValue;
|
return returnValue;
|
||||||
default:
|
default:
|
||||||
@@ -125,17 +127,17 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
private static void UpdateSubClasses(Game Game, bool getAllMetadata, bool followSubGames, bool forceRefresh)
|
private static void UpdateSubClasses(Game Game, bool getAllMetadata, bool followSubGames, bool forceRefresh)
|
||||||
{
|
{
|
||||||
// required metadata
|
// required metadata
|
||||||
if (Game.Cover != null)
|
// if (Game.Cover != null)
|
||||||
{
|
// {
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
Cover GameCover = Covers.GetCover(Game.Cover.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game), forceRefresh);
|
// Cover GameCover = Covers.GetCover(Game.Cover.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game), forceRefresh);
|
||||||
}
|
// }
|
||||||
catch (Exception ex)
|
// catch (Exception ex)
|
||||||
{
|
// {
|
||||||
Logging.Log(Logging.LogType.Critical, "Game Metadata", "Unable to fetch cover artwork.", ex);
|
// Logging.Log(Logging.LogType.Critical, "Game Metadata", "Unable to fetch cover artwork.", ex);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (Game.Genres != null)
|
if (Game.Genres != null)
|
||||||
{
|
{
|
||||||
@@ -285,7 +287,7 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Screenshot GameScreenshot = Screenshots.GetScreenshot(ScreenshotId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game), forceRefresh);
|
Screenshot GameScreenshot = Screenshots.GetScreenshot(ScreenshotId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(Game), forceRefresh);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -347,7 +349,7 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
|
|
||||||
// get missing metadata from parent if this is a port
|
// get missing metadata from parent if this is a port
|
||||||
if (result.Category == Category.Port)
|
if (result.Category == Category.Port)
|
||||||
{
|
{
|
||||||
if (result.Summary == null)
|
if (result.Summary == null)
|
||||||
{
|
{
|
||||||
if (result.ParentGame != null)
|
if (result.ParentGame != null)
|
||||||
@@ -364,7 +366,7 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AssignAllGamesToPlatformIdZero()
|
public static void AssignAllGamesToPlatformIdZero()
|
||||||
{
|
{
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
@@ -428,7 +430,7 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
}
|
}
|
||||||
|
|
||||||
string sql = "SELECT Game.Id, Game.`Name`, Game.Slug, Relation_Game_Platforms.PlatformsId AS PlatformsId, Game.Summary FROM gaseous.Game JOIN Relation_Game_Platforms ON Game.Id = Relation_Game_Platforms.GameId WHERE " + whereClause + ";";
|
string sql = "SELECT Game.Id, Game.`Name`, Game.Slug, Relation_Game_Platforms.PlatformsId AS PlatformsId, Game.Summary FROM gaseous.Game JOIN Relation_Game_Platforms ON Game.Id = Relation_Game_Platforms.GameId WHERE " + whereClause + ";";
|
||||||
|
|
||||||
|
|
||||||
// get Game metadata
|
// get Game metadata
|
||||||
Game[]? results = new Game[0];
|
Game[]? results = new Game[0];
|
||||||
@@ -439,7 +441,8 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||||
foreach (DataRow row in data.Rows)
|
foreach (DataRow row in data.Rows)
|
||||||
{
|
{
|
||||||
Game game = new Game{
|
Game game = new Game
|
||||||
|
{
|
||||||
Id = (long)row["Id"],
|
Id = (long)row["Id"],
|
||||||
Name = (string)Common.ReturnValueIfNull(row["Name"], ""),
|
Name = (string)Common.ReturnValueIfNull(row["Name"], ""),
|
||||||
Slug = (string)Common.ReturnValueIfNull(row["Slug"], ""),
|
Slug = (string)Common.ReturnValueIfNull(row["Slug"], ""),
|
||||||
@@ -476,12 +479,12 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
searchBody = "where platforms = (" + PlatformId + ") & name ~ \"" + SearchString + "\";";
|
searchBody = "where platforms = (" + PlatformId + ") & name ~ \"" + SearchString + "\";";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check search cache
|
// check search cache
|
||||||
Game[]? games = Communications.GetSearchCache<Game[]?>(searchFields, searchBody);
|
Game[]? games = Communications.GetSearchCache<Game[]?>(searchFields, searchBody);
|
||||||
|
|
||||||
if (games == null)
|
if (games == null)
|
||||||
{
|
{
|
||||||
// cache miss
|
// cache miss
|
||||||
// get Game metadata
|
// get Game metadata
|
||||||
Communications comms = new Communications();
|
Communications comms = new Communications();
|
||||||
@@ -513,7 +516,7 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
foreach (DataRow row in data.Rows)
|
foreach (DataRow row in data.Rows)
|
||||||
{
|
{
|
||||||
KeyValuePair<long, string> valuePair = new KeyValuePair<long, string>((long)row["PlatformId"], (string)row["Name"]);
|
KeyValuePair<long, string> valuePair = new KeyValuePair<long, string>((long)row["PlatformId"], (string)row["Name"]);
|
||||||
platforms.Add(valuePair);
|
platforms.Add(valuePair);
|
||||||
}
|
}
|
||||||
|
|
||||||
return platforms;
|
return platforms;
|
||||||
@@ -533,7 +536,7 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MinimalGameItem(Game gameObject)
|
public MinimalGameItem(Game gameObject)
|
||||||
{
|
{
|
||||||
this.Id = gameObject.Id;
|
this.Id = gameObject.Id;
|
||||||
@@ -561,6 +564,7 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
}
|
}
|
||||||
|
|
||||||
public long? Id { get; set; }
|
public long? Id { get; set; }
|
||||||
|
public long Index { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string Slug { get; set; }
|
public string Slug { get; set; }
|
||||||
public double? TotalRating { get; set; }
|
public double? TotalRating { get; set; }
|
||||||
|
@@ -5,15 +5,15 @@ using IGDB.Models;
|
|||||||
|
|
||||||
namespace gaseous_server.Classes.Metadata
|
namespace gaseous_server.Classes.Metadata
|
||||||
{
|
{
|
||||||
public class PlatformVersions
|
public class PlatformVersions
|
||||||
{
|
{
|
||||||
const string fieldList = "fields checksum,companies,connectivity,cpu,graphics,main_manufacturer,media,memory,name,online,os,output,platform_logo,platform_version_release_dates,resolutions,slug,sound,storage,summary,url;";
|
const string fieldList = "fields checksum,companies,connectivity,cpu,graphics,main_manufacturer,media,memory,name,online,os,output,platform_logo,platform_version_release_dates,resolutions,slug,sound,storage,summary,url;";
|
||||||
|
|
||||||
public PlatformVersions()
|
public PlatformVersions()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PlatformVersion? GetPlatformVersion(long Id, Platform ParentPlatform)
|
public static PlatformVersion? GetPlatformVersion(long Id, Platform ParentPlatform, bool GetImages = false)
|
||||||
{
|
{
|
||||||
if (Id == 0)
|
if (Id == 0)
|
||||||
{
|
{
|
||||||
@@ -21,18 +21,18 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Task<PlatformVersion> RetVal = _GetPlatformVersion(SearchUsing.id, Id, ParentPlatform);
|
Task<PlatformVersion> RetVal = _GetPlatformVersion(SearchUsing.id, Id, ParentPlatform, GetImages);
|
||||||
return RetVal.Result;
|
return RetVal.Result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PlatformVersion GetPlatformVersion(string Slug, Platform ParentPlatform)
|
public static PlatformVersion GetPlatformVersion(string Slug, Platform ParentPlatform, bool GetImages)
|
||||||
{
|
{
|
||||||
Task<PlatformVersion> RetVal = _GetPlatformVersion(SearchUsing.slug, Slug, ParentPlatform);
|
Task<PlatformVersion> RetVal = _GetPlatformVersion(SearchUsing.slug, Slug, ParentPlatform, GetImages);
|
||||||
return RetVal.Result;
|
return RetVal.Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<PlatformVersion> _GetPlatformVersion(SearchUsing searchUsing, object searchValue, Platform ParentPlatform)
|
private static async Task<PlatformVersion> _GetPlatformVersion(SearchUsing searchUsing, object searchValue, Platform ParentPlatform, bool GetImages)
|
||||||
{
|
{
|
||||||
// check database first
|
// check database first
|
||||||
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
|
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
|
||||||
@@ -67,7 +67,7 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
if (returnValue != null)
|
if (returnValue != null)
|
||||||
{
|
{
|
||||||
Storage.NewCacheValue(returnValue);
|
Storage.NewCacheValue(returnValue);
|
||||||
UpdateSubClasses(ParentPlatform, returnValue);
|
UpdateSubClasses(ParentPlatform, returnValue, GetImages);
|
||||||
}
|
}
|
||||||
return returnValue;
|
return returnValue;
|
||||||
case Storage.CacheStatus.Expired:
|
case Storage.CacheStatus.Expired:
|
||||||
@@ -75,7 +75,7 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
{
|
{
|
||||||
returnValue = await GetObjectFromServer(WhereClause);
|
returnValue = await GetObjectFromServer(WhereClause);
|
||||||
Storage.NewCacheValue(returnValue, true);
|
Storage.NewCacheValue(returnValue, true);
|
||||||
UpdateSubClasses(ParentPlatform, returnValue);
|
UpdateSubClasses(ParentPlatform, returnValue, GetImages);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -90,17 +90,20 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UpdateSubClasses(Platform ParentPlatform, PlatformVersion platformVersion)
|
private static void UpdateSubClasses(Platform ParentPlatform, PlatformVersion platformVersion, bool GetImages)
|
||||||
{
|
{
|
||||||
if (platformVersion.PlatformLogo != null)
|
if (GetImages == true)
|
||||||
{
|
{
|
||||||
try
|
if (platformVersion.PlatformLogo != null)
|
||||||
{
|
{
|
||||||
PlatformLogo platformLogo = PlatformLogos.GetPlatformLogo(platformVersion.PlatformLogo.Id, Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Platform(ParentPlatform), "Versions", platformVersion.Slug));
|
try
|
||||||
}
|
{
|
||||||
catch (Exception ex)
|
PlatformLogo platformLogo = PlatformLogos.GetPlatformLogo(platformVersion.PlatformLogo.Id, Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Platform(ParentPlatform), "Versions", platformVersion.Slug));
|
||||||
{
|
}
|
||||||
Logging.Log(Logging.LogType.Warning, "Platform Update", "Unable to fetch platform logo", ex);
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.Log(Logging.LogType.Warning, "Platform Update", "Unable to fetch platform logo", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,16 +7,16 @@ using IGDB.Models;
|
|||||||
namespace gaseous_server.Classes.Metadata
|
namespace gaseous_server.Classes.Metadata
|
||||||
{
|
{
|
||||||
public class Platforms
|
public class Platforms
|
||||||
{
|
{
|
||||||
const string fieldList = "fields abbreviation,alternative_name,category,checksum,created_at,generation,name,platform_family,platform_logo,slug,summary,updated_at,url,versions,websites;";
|
const string fieldList = "fields abbreviation,alternative_name,category,checksum,created_at,generation,name,platform_family,platform_logo,slug,summary,updated_at,url,versions,websites;";
|
||||||
|
|
||||||
public Platforms()
|
public Platforms()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Platform? GetPlatform(long Id, bool forceRefresh = false)
|
public static Platform? GetPlatform(long Id, bool forceRefresh = false, bool GetImages = false)
|
||||||
{
|
{
|
||||||
if (Id == 0)
|
if (Id == 0)
|
||||||
{
|
{
|
||||||
Platform returnValue = new Platform();
|
Platform returnValue = new Platform();
|
||||||
@@ -41,10 +41,10 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Task<Platform> RetVal = _GetPlatform(SearchUsing.id, Id, forceRefresh);
|
Task<Platform> RetVal = _GetPlatform(SearchUsing.id, Id, forceRefresh, GetImages);
|
||||||
return RetVal.Result;
|
return RetVal.Result;
|
||||||
}
|
}
|
||||||
catch(Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.Log(Logging.LogType.Warning, "Metadata", "An error occurred fetching Platform Id " + Id, ex);
|
Logging.Log(Logging.LogType.Warning, "Metadata", "An error occurred fetching Platform Id " + Id, ex);
|
||||||
return null;
|
return null;
|
||||||
@@ -52,14 +52,14 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Platform GetPlatform(string Slug, bool forceRefresh = false)
|
public static Platform GetPlatform(string Slug, bool forceRefresh = false, bool GetImages = false)
|
||||||
{
|
{
|
||||||
Task<Platform> RetVal = _GetPlatform(SearchUsing.slug, Slug, forceRefresh);
|
Task<Platform> RetVal = _GetPlatform(SearchUsing.slug, Slug, forceRefresh, GetImages);
|
||||||
return RetVal.Result;
|
return RetVal.Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<Platform> _GetPlatform(SearchUsing searchUsing, object searchValue, bool forceRefresh)
|
private static async Task<Platform> _GetPlatform(SearchUsing searchUsing, object searchValue, bool forceRefresh, bool GetImages)
|
||||||
{
|
{
|
||||||
// check database first
|
// check database first
|
||||||
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
|
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
|
||||||
if (searchUsing == SearchUsing.id)
|
if (searchUsing == SearchUsing.id)
|
||||||
@@ -78,13 +78,16 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
|
|
||||||
// set up where clause
|
// set up where clause
|
||||||
string WhereClause = "";
|
string WhereClause = "";
|
||||||
|
string searchField = "";
|
||||||
switch (searchUsing)
|
switch (searchUsing)
|
||||||
{
|
{
|
||||||
case SearchUsing.id:
|
case SearchUsing.id:
|
||||||
WhereClause = "where id = " + searchValue;
|
WhereClause = "where id = " + searchValue;
|
||||||
|
searchField = "id";
|
||||||
break;
|
break;
|
||||||
case SearchUsing.slug:
|
case SearchUsing.slug:
|
||||||
WhereClause = "where slug = " + searchValue;
|
WhereClause = "where slug = \"" + searchValue + "\"";
|
||||||
|
searchField = "slug";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Exception("Invalid search type");
|
throw new Exception("Invalid search type");
|
||||||
@@ -96,7 +99,7 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
case Storage.CacheStatus.NotPresent:
|
case Storage.CacheStatus.NotPresent:
|
||||||
returnValue = await GetObjectFromServer(WhereClause);
|
returnValue = await GetObjectFromServer(WhereClause);
|
||||||
Storage.NewCacheValue(returnValue);
|
Storage.NewCacheValue(returnValue);
|
||||||
UpdateSubClasses(returnValue);
|
UpdateSubClasses(returnValue, GetImages);
|
||||||
AddPlatformMapping(returnValue);
|
AddPlatformMapping(returnValue);
|
||||||
return returnValue;
|
return returnValue;
|
||||||
case Storage.CacheStatus.Expired:
|
case Storage.CacheStatus.Expired:
|
||||||
@@ -104,23 +107,23 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
{
|
{
|
||||||
returnValue = await GetObjectFromServer(WhereClause);
|
returnValue = await GetObjectFromServer(WhereClause);
|
||||||
Storage.NewCacheValue(returnValue, true);
|
Storage.NewCacheValue(returnValue, true);
|
||||||
UpdateSubClasses(returnValue);
|
UpdateSubClasses(returnValue, GetImages);
|
||||||
AddPlatformMapping(returnValue);
|
AddPlatformMapping(returnValue);
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
Logging.Log(Logging.LogType.Warning, "Metadata: " + returnValue.GetType().Name, "An error occurred while connecting to IGDB. WhereClause: " + WhereClause, ex);
|
||||||
return Storage.GetCacheValue<Platform>(returnValue, "id", (long)searchValue);
|
return Storage.GetCacheValue<Platform>(returnValue, searchField, searchValue);
|
||||||
}
|
}
|
||||||
case Storage.CacheStatus.Current:
|
case Storage.CacheStatus.Current:
|
||||||
return Storage.GetCacheValue<Platform>(returnValue, "id", (long)searchValue);
|
return Storage.GetCacheValue<Platform>(returnValue, searchField, searchValue);
|
||||||
default:
|
default:
|
||||||
throw new Exception("How did you get here?");
|
throw new Exception("How did you get here?");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UpdateSubClasses(Platform platform)
|
private static void UpdateSubClasses(Platform platform, bool GetImages)
|
||||||
{
|
{
|
||||||
if (platform.Versions != null)
|
if (platform.Versions != null)
|
||||||
{
|
{
|
||||||
@@ -130,15 +133,18 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (platform.PlatformLogo != null)
|
if (GetImages == true)
|
||||||
{
|
{
|
||||||
try
|
if (platform.PlatformLogo != null)
|
||||||
{
|
{
|
||||||
PlatformLogo platformLogo = PlatformLogos.GetPlatformLogo(platform.PlatformLogo.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Platform(platform));
|
try
|
||||||
}
|
{
|
||||||
catch (Exception ex)
|
PlatformLogo platformLogo = PlatformLogos.GetPlatformLogo(platform.PlatformLogo.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Platform(platform));
|
||||||
{
|
}
|
||||||
Logging.Log(Logging.LogType.Warning, "Platform Update", "Unable to fetch platform logo", ex);
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.Log(Logging.LogType.Warning, "Platform Update", "Unable to fetch platform logo", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,11 +164,12 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
{
|
{
|
||||||
Logging.Log(Logging.LogType.Information, "Platform Map", "Importing " + platform.Name + " from predefined data.");
|
Logging.Log(Logging.LogType.Information, "Platform Map", "Importing " + platform.Name + " from predefined data.");
|
||||||
// doesn't exist - add it
|
// doesn't exist - add it
|
||||||
item = new Models.PlatformMapping.PlatformMapItem{
|
item = new Models.PlatformMapping.PlatformMapItem
|
||||||
|
{
|
||||||
IGDBId = (long)platform.Id,
|
IGDBId = (long)platform.Id,
|
||||||
IGDBName = platform.Name,
|
IGDBName = platform.Name,
|
||||||
IGDBSlug = platform.Slug,
|
IGDBSlug = platform.Slug,
|
||||||
AlternateNames = new List<string>{ platform.AlternativeName }
|
AlternateNames = new List<string> { platform.AlternativeName }
|
||||||
};
|
};
|
||||||
Models.PlatformMapping.WritePlatformMap(item, false, true);
|
Models.PlatformMapping.WritePlatformMap(item, false, true);
|
||||||
}
|
}
|
||||||
|
@@ -7,19 +7,19 @@ using Microsoft.Extensions.Caching.Memory;
|
|||||||
|
|
||||||
namespace gaseous_server.Classes.Metadata
|
namespace gaseous_server.Classes.Metadata
|
||||||
{
|
{
|
||||||
public class Storage
|
public class Storage
|
||||||
{
|
{
|
||||||
public enum CacheStatus
|
public enum CacheStatus
|
||||||
{
|
{
|
||||||
NotPresent,
|
NotPresent,
|
||||||
Current,
|
Current,
|
||||||
Expired
|
Expired
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CacheStatus GetCacheStatus(string Endpoint, string Slug)
|
public static CacheStatus GetCacheStatus(string Endpoint, string Slug)
|
||||||
{
|
{
|
||||||
return _GetCacheStatus(Endpoint, "slug", Slug);
|
return _GetCacheStatus(Endpoint, "slug", Slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CacheStatus GetCacheStatus(string Endpoint, long Id)
|
public static CacheStatus GetCacheStatus(string Endpoint, long Id)
|
||||||
{
|
{
|
||||||
@@ -47,124 +47,124 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static CacheStatus _GetCacheStatus(string Endpoint, string SearchField, object SearchValue)
|
private static CacheStatus _GetCacheStatus(string Endpoint, string SearchField, object SearchValue)
|
||||||
{
|
{
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
|
||||||
string sql = "SELECT lastUpdated FROM " + Endpoint + " WHERE " + SearchField + " = @" + SearchField;
|
string sql = "SELECT lastUpdated FROM " + Endpoint + " WHERE " + SearchField + " = @" + SearchField;
|
||||||
|
|
||||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
dbDict.Add("Endpoint", Endpoint);
|
dbDict.Add("Endpoint", Endpoint);
|
||||||
dbDict.Add(SearchField, SearchValue);
|
dbDict.Add(SearchField, SearchValue);
|
||||||
|
|
||||||
DataTable dt = db.ExecuteCMD(sql, dbDict);
|
DataTable dt = db.ExecuteCMD(sql, dbDict);
|
||||||
if (dt.Rows.Count == 0)
|
if (dt.Rows.Count == 0)
|
||||||
{
|
{
|
||||||
// no data stored for this item, or lastUpdated
|
// no data stored for this item, or lastUpdated
|
||||||
return CacheStatus.NotPresent;
|
return CacheStatus.NotPresent;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DateTime CacheExpiryTime = DateTime.UtcNow.AddHours(-168);
|
DateTime CacheExpiryTime = DateTime.UtcNow.AddHours(-168);
|
||||||
if ((DateTime)dt.Rows[0]["lastUpdated"] < CacheExpiryTime)
|
if ((DateTime)dt.Rows[0]["lastUpdated"] < CacheExpiryTime)
|
||||||
{
|
{
|
||||||
return CacheStatus.Expired;
|
return CacheStatus.Expired;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return CacheStatus.Current;
|
return CacheStatus.Current;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void NewCacheValue(object ObjectToCache, bool UpdateRecord = false)
|
public static void NewCacheValue(object ObjectToCache, bool UpdateRecord = false)
|
||||||
{
|
{
|
||||||
// get the object type name
|
// get the object type name
|
||||||
string ObjectTypeName = ObjectToCache.GetType().Name;
|
string ObjectTypeName = ObjectToCache.GetType().Name;
|
||||||
|
|
||||||
// build dictionary
|
// build dictionary
|
||||||
string objectJson = Newtonsoft.Json.JsonConvert.SerializeObject(ObjectToCache);
|
string objectJson = Newtonsoft.Json.JsonConvert.SerializeObject(ObjectToCache);
|
||||||
Dictionary<string, object?> objectDict = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object?>>(objectJson);
|
Dictionary<string, object?> objectDict = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object?>>(objectJson);
|
||||||
objectDict.Add("dateAdded", DateTime.UtcNow);
|
objectDict.Add("dateAdded", DateTime.UtcNow);
|
||||||
objectDict.Add("lastUpdated", DateTime.UtcNow);
|
objectDict.Add("lastUpdated", DateTime.UtcNow);
|
||||||
|
|
||||||
// generate sql
|
// generate sql
|
||||||
string fieldList = "";
|
string fieldList = "";
|
||||||
string valueList = "";
|
string valueList = "";
|
||||||
string updateFieldValueList = "";
|
string updateFieldValueList = "";
|
||||||
foreach (KeyValuePair<string, object?> key in objectDict)
|
foreach (KeyValuePair<string, object?> key in objectDict)
|
||||||
{
|
{
|
||||||
if (fieldList.Length > 0)
|
if (fieldList.Length > 0)
|
||||||
{
|
{
|
||||||
fieldList = fieldList + ", ";
|
fieldList = fieldList + ", ";
|
||||||
valueList = valueList + ", ";
|
valueList = valueList + ", ";
|
||||||
}
|
}
|
||||||
fieldList = fieldList + key.Key;
|
fieldList = fieldList + key.Key;
|
||||||
valueList = valueList + "@" + key.Key;
|
valueList = valueList + "@" + key.Key;
|
||||||
if ((key.Key != "id") && (key.Key != "dateAdded"))
|
if ((key.Key != "id") && (key.Key != "dateAdded"))
|
||||||
{
|
{
|
||||||
if (updateFieldValueList.Length > 0)
|
if (updateFieldValueList.Length > 0)
|
||||||
{
|
{
|
||||||
updateFieldValueList = updateFieldValueList + ", ";
|
updateFieldValueList = updateFieldValueList + ", ";
|
||||||
}
|
}
|
||||||
updateFieldValueList += key.Key + " = @" + key.Key;
|
updateFieldValueList += key.Key + " = @" + key.Key;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check property type
|
// check property type
|
||||||
Type objectType = ObjectToCache.GetType();
|
Type objectType = ObjectToCache.GetType();
|
||||||
if (objectType != null)
|
if (objectType != null)
|
||||||
{
|
{
|
||||||
PropertyInfo objectProperty = objectType.GetProperty(key.Key);
|
PropertyInfo objectProperty = objectType.GetProperty(key.Key);
|
||||||
if (objectProperty != null)
|
if (objectProperty != null)
|
||||||
{
|
{
|
||||||
string compareName = objectProperty.PropertyType.Name.ToLower().Split("`")[0];
|
string compareName = objectProperty.PropertyType.Name.ToLower().Split("`")[0];
|
||||||
var objectValue = objectProperty.GetValue(ObjectToCache);
|
var objectValue = objectProperty.GetValue(ObjectToCache);
|
||||||
if (objectValue != null)
|
if (objectValue != null)
|
||||||
{
|
{
|
||||||
string newObjectValue;
|
string newObjectValue;
|
||||||
Dictionary<string, object> newDict;
|
Dictionary<string, object> newDict;
|
||||||
switch (compareName)
|
switch (compareName)
|
||||||
{
|
{
|
||||||
case "identityorvalue":
|
case "identityorvalue":
|
||||||
newObjectValue = Newtonsoft.Json.JsonConvert.SerializeObject(objectValue);
|
newObjectValue = Newtonsoft.Json.JsonConvert.SerializeObject(objectValue);
|
||||||
newDict = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(newObjectValue);
|
newDict = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(newObjectValue);
|
||||||
objectDict[key.Key] = newDict["Id"];
|
objectDict[key.Key] = newDict["Id"];
|
||||||
break;
|
break;
|
||||||
case "identitiesorvalues":
|
case "identitiesorvalues":
|
||||||
newObjectValue = Newtonsoft.Json.JsonConvert.SerializeObject(objectValue);
|
newObjectValue = Newtonsoft.Json.JsonConvert.SerializeObject(objectValue);
|
||||||
newDict = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(newObjectValue);
|
newDict = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(newObjectValue);
|
||||||
newObjectValue = Newtonsoft.Json.JsonConvert.SerializeObject(newDict["Ids"]);
|
newObjectValue = Newtonsoft.Json.JsonConvert.SerializeObject(newDict["Ids"]);
|
||||||
objectDict[key.Key] = newObjectValue;
|
objectDict[key.Key] = newObjectValue;
|
||||||
|
|
||||||
StoreRelations(ObjectTypeName, key.Key, (long)objectDict["Id"], newObjectValue);
|
StoreRelations(ObjectTypeName, key.Key, (long)objectDict["Id"], newObjectValue);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case "int32[]":
|
case "int32[]":
|
||||||
newObjectValue = Newtonsoft.Json.JsonConvert.SerializeObject(objectValue);
|
newObjectValue = Newtonsoft.Json.JsonConvert.SerializeObject(objectValue);
|
||||||
objectDict[key.Key] = newObjectValue;
|
objectDict[key.Key] = newObjectValue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string sql = "";
|
string sql = "";
|
||||||
if (UpdateRecord == false)
|
if (UpdateRecord == false)
|
||||||
{
|
{
|
||||||
sql = "INSERT INTO " + ObjectTypeName + " (" + fieldList + ") VALUES (" + valueList + ")";
|
sql = "INSERT INTO " + ObjectTypeName + " (" + fieldList + ") VALUES (" + valueList + ")";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sql = "UPDATE " + ObjectTypeName + " SET " + updateFieldValueList + " WHERE Id = @Id";
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
sql = "UPDATE " + ObjectTypeName + " SET " + updateFieldValueList + " WHERE Id = @Id";
|
|
||||||
}
|
|
||||||
|
|
||||||
// execute sql
|
// execute sql
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
db.ExecuteCMD(sql, objectDict);
|
db.ExecuteCMD(sql, objectDict);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T GetCacheValue<T>(T EndpointType, string SearchField, object SearchValue)
|
public static T GetCacheValue<T>(T EndpointType, string SearchField, object SearchValue)
|
||||||
{
|
{
|
||||||
string Endpoint = EndpointType.GetType().Name;
|
string Endpoint = EndpointType.GetType().Name;
|
||||||
|
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
@@ -178,20 +178,20 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
DataTable dt = db.ExecuteCMD(sql, dbDict);
|
DataTable dt = db.ExecuteCMD(sql, dbDict);
|
||||||
if (dt.Rows.Count == 0)
|
if (dt.Rows.Count == 0)
|
||||||
{
|
{
|
||||||
// no data stored for this item
|
// no data stored for this item
|
||||||
throw new Exception("No record found that matches endpoint " + Endpoint + " with search value " + SearchValue);
|
throw new Exception("No record found that matches endpoint " + Endpoint + " with search value " + SearchValue);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DataRow dataRow = dt.Rows[0];
|
DataRow dataRow = dt.Rows[0];
|
||||||
object returnObject = BuildCacheObject<T>(EndpointType, dataRow);
|
object returnObject = BuildCacheObject<T>(EndpointType, dataRow);
|
||||||
|
|
||||||
return (T)returnObject;
|
return (T)returnObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T BuildCacheObject<T>(T EndpointType, DataRow dataRow)
|
public static T BuildCacheObject<T>(T EndpointType, DataRow dataRow)
|
||||||
{
|
{
|
||||||
foreach (PropertyInfo property in EndpointType.GetType().GetProperties())
|
foreach (PropertyInfo property in EndpointType.GetType().GetProperties())
|
||||||
{
|
{
|
||||||
if (dataRow.Table.Columns.Contains(property.Name))
|
if (dataRow.Table.Columns.Contains(property.Name))
|
||||||
@@ -428,11 +428,35 @@ namespace gaseous_server.Classes.Metadata
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void CreateRelationsTables<T>()
|
||||||
|
{
|
||||||
|
string PrimaryTable = typeof(T).Name;
|
||||||
|
foreach (PropertyInfo property in typeof(T).GetProperties())
|
||||||
|
{
|
||||||
|
string SecondaryTable = property.Name;
|
||||||
|
|
||||||
|
if (property.PropertyType.Name == "IdentitiesOrValues`1")
|
||||||
|
{
|
||||||
|
|
||||||
|
string TableName = "Relation_" + PrimaryTable + "_" + SecondaryTable;
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "SELECT * FROM information_schema.tables WHERE table_schema = '" + Config.DatabaseConfiguration.DatabaseName + "' AND table_name = '" + TableName + "';";
|
||||||
|
DataTable data = db.ExecuteCMD(sql);
|
||||||
|
if (data.Rows.Count == 0)
|
||||||
|
{
|
||||||
|
// table doesn't exist, create it
|
||||||
|
sql = "CREATE TABLE `" + Config.DatabaseConfiguration.DatabaseName + "`.`" + TableName + "` (`" + PrimaryTable + "Id` BIGINT NOT NULL, `" + SecondaryTable + "Id` BIGINT NOT NULL, PRIMARY KEY (`" + PrimaryTable + "Id`, `" + SecondaryTable + "Id`), INDEX `idx_PrimaryColumn` (`" + PrimaryTable + "Id` ASC) VISIBLE);";
|
||||||
|
db.ExecuteCMD(sql);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class MemoryCacheObject
|
private class MemoryCacheObject
|
||||||
{
|
{
|
||||||
public object Object { get; set; }
|
public object Object { get; set; }
|
||||||
public DateTime CreationTime { get; } = DateTime.UtcNow;
|
public DateTime CreationTime { get; } = DateTime.UtcNow;
|
||||||
public DateTime ExpiryTime
|
public DateTime ExpiryTime
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@@ -5,6 +5,9 @@ using Microsoft.VisualBasic;
|
|||||||
using IGDB.Models;
|
using IGDB.Models;
|
||||||
using gaseous_server.Classes.Metadata;
|
using gaseous_server.Classes.Metadata;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
|
using SharpCompress.Archives;
|
||||||
|
using SharpCompress.Common;
|
||||||
|
using gaseous_server.Models;
|
||||||
|
|
||||||
namespace gaseous_server.Classes
|
namespace gaseous_server.Classes
|
||||||
{
|
{
|
||||||
@@ -259,6 +262,7 @@ namespace gaseous_server.Classes
|
|||||||
{
|
{
|
||||||
Game GameObject = Games.GetGame(mediaGroupItem.GameId, false, false, false);
|
Game GameObject = Games.GetGame(mediaGroupItem.GameId, false, false, false);
|
||||||
Platform PlatformObject = Platforms.GetPlatform(mediaGroupItem.PlatformId, false);
|
Platform PlatformObject = Platforms.GetPlatform(mediaGroupItem.PlatformId, false);
|
||||||
|
PlatformMapping.PlatformMapItem platformMapItem = PlatformMapping.GetPlatformMap(mediaGroupItem.PlatformId);
|
||||||
|
|
||||||
Logging.Log(Logging.LogType.Information, "Media Group", "Beginning build of media group: " + GameObject.Name + " for platform " + PlatformObject.Name);
|
Logging.Log(Logging.LogType.Information, "Media Group", "Beginning build of media group: " + GameObject.Name + " for platform " + PlatformObject.Name);
|
||||||
|
|
||||||
@@ -293,10 +297,124 @@ namespace gaseous_server.Classes
|
|||||||
foreach (long RomId in mediaGroupItem.RomIds)
|
foreach (long RomId in mediaGroupItem.RomIds)
|
||||||
{
|
{
|
||||||
Roms.GameRomItem rom = Roms.GetRom(RomId);
|
Roms.GameRomItem rom = Roms.GetRom(RomId);
|
||||||
|
bool fileNameFound = false;
|
||||||
if (File.Exists(rom.Path))
|
if (File.Exists(rom.Path))
|
||||||
{
|
{
|
||||||
Logging.Log(Logging.LogType.Information, "Media Group", "Copying ROM: " + rom.Name);
|
string romExt = Path.GetExtension(rom.Path);
|
||||||
File.Copy(rom.Path, Path.Combine(ZipFileTempPath, Path.GetFileName(rom.Path)));
|
if (new string[]{ ".zip", ".rar", ".7z" }.Contains(romExt))
|
||||||
|
{
|
||||||
|
Logging.Log(Logging.LogType.Information, "Media Group", "Decompressing ROM: " + rom.Name);
|
||||||
|
|
||||||
|
// is compressed
|
||||||
|
switch (romExt)
|
||||||
|
{
|
||||||
|
case ".zip":
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var archive = SharpCompress.Archives.Zip.ZipArchive.Open(rom.Path))
|
||||||
|
{
|
||||||
|
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||||
|
{
|
||||||
|
Logging.Log(Logging.LogType.Information, "Media Group", "Extracting file: " + entry.Key);
|
||||||
|
if (fileNameFound == false)
|
||||||
|
{
|
||||||
|
//check if extension is in valid extensions
|
||||||
|
if (platformMapItem.Extensions.SupportedFileExtensions.Contains(Path.GetExtension(entry.Key), StringComparer.InvariantCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
// update rom file name
|
||||||
|
rom.Name = entry.Key;
|
||||||
|
fileNameFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entry.WriteToDirectory(ZipFileTempPath, new ExtractionOptions()
|
||||||
|
{
|
||||||
|
ExtractFullPath = true,
|
||||||
|
Overwrite = true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception zipEx)
|
||||||
|
{
|
||||||
|
Logging.Log(Logging.LogType.Warning, "Media Group", "Unzip error", zipEx);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ".rar":
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var archive = SharpCompress.Archives.Rar.RarArchive.Open(rom.Path))
|
||||||
|
{
|
||||||
|
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||||
|
{
|
||||||
|
Logging.Log(Logging.LogType.Information, "Media Group", "Extracting file: " + entry.Key);
|
||||||
|
if (fileNameFound == false)
|
||||||
|
{
|
||||||
|
//check if extension is in valid extensions
|
||||||
|
if (platformMapItem.Extensions.SupportedFileExtensions.Contains(Path.GetExtension(entry.Key), StringComparer.InvariantCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
// update rom file name
|
||||||
|
rom.Name = entry.Key;
|
||||||
|
fileNameFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entry.WriteToDirectory(ZipFileTempPath, new ExtractionOptions()
|
||||||
|
{
|
||||||
|
ExtractFullPath = true,
|
||||||
|
Overwrite = true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception zipEx)
|
||||||
|
{
|
||||||
|
Logging.Log(Logging.LogType.Warning, "Media Group", "Unrar error", zipEx);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ".7z":
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var archive = SharpCompress.Archives.SevenZip.SevenZipArchive.Open(rom.Path))
|
||||||
|
{
|
||||||
|
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||||
|
{
|
||||||
|
Logging.Log(Logging.LogType.Information, "Media Group", "Extracting file: " + entry.Key);
|
||||||
|
if (fileNameFound == false)
|
||||||
|
{
|
||||||
|
//check if extension is in valid extensions
|
||||||
|
if (platformMapItem.Extensions.SupportedFileExtensions.Contains(Path.GetExtension(entry.Key), StringComparer.InvariantCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
// update rom file name
|
||||||
|
rom.Name = entry.Key;
|
||||||
|
fileNameFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entry.WriteToDirectory(ZipFileTempPath, new ExtractionOptions()
|
||||||
|
{
|
||||||
|
ExtractFullPath = true,
|
||||||
|
Overwrite = true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception zipEx)
|
||||||
|
{
|
||||||
|
Logging.Log(Logging.LogType.Warning, "Media Group", "7z error", zipEx);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// is uncompressed
|
||||||
|
Logging.Log(Logging.LogType.Information, "Media Group", "Copying ROM: " + rom.Name);
|
||||||
|
File.Copy(rom.Path, Path.Combine(ZipFileTempPath, Path.GetFileName(rom.Path)));
|
||||||
|
}
|
||||||
|
|
||||||
romItems.Add(rom);
|
romItems.Add(rom);
|
||||||
}
|
}
|
||||||
|
@@ -10,23 +10,29 @@ namespace gaseous_server.Classes
|
|||||||
public class Roms
|
public class Roms
|
||||||
{
|
{
|
||||||
public class InvalidRomId : Exception
|
public class InvalidRomId : Exception
|
||||||
{
|
{
|
||||||
public InvalidRomId(long Id) : base("Unable to find ROM by id " + Id)
|
public InvalidRomId(long Id) : base("Unable to find ROM by id " + Id)
|
||||||
{}
|
{ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class InvalidRomHash : Exception
|
||||||
|
{
|
||||||
|
public InvalidRomHash(String Hash) : base("Unable to find ROM by hash " + Hash)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
public static GameRomObject GetRoms(long GameId, long PlatformId = -1, string NameSearch = "", int pageNumber = 0, int pageSize = 0, string userid = "")
|
public static GameRomObject GetRoms(long GameId, long PlatformId = -1, string NameSearch = "", int pageNumber = 0, int pageSize = 0, string userid = "")
|
||||||
{
|
{
|
||||||
GameRomObject GameRoms = new GameRomObject();
|
GameRomObject GameRoms = new GameRomObject();
|
||||||
|
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
string sql = "";
|
string sql = "";
|
||||||
string sqlCount = "";
|
string sqlCount = "";
|
||||||
string sqlPlatform = "";
|
string sqlPlatform = "";
|
||||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
dbDict.Add("id", GameId);
|
dbDict.Add("id", GameId);
|
||||||
dbDict.Add("userid", userid);
|
dbDict.Add("userid", userid);
|
||||||
|
|
||||||
string NameSearchWhere = "";
|
string NameSearchWhere = "";
|
||||||
if (NameSearch.Length > 0)
|
if (NameSearch.Length > 0)
|
||||||
{
|
{
|
||||||
@@ -37,13 +43,16 @@ namespace gaseous_server.Classes
|
|||||||
// platform query
|
// platform query
|
||||||
sqlPlatform = "SELECT DISTINCT Games_Roms.PlatformId, Platform.`Name` FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE GameId = @id ORDER BY Platform.`Name`;";
|
sqlPlatform = "SELECT DISTINCT Games_Roms.PlatformId, Platform.`Name` FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE GameId = @id ORDER BY Platform.`Name`;";
|
||||||
|
|
||||||
if (PlatformId == -1) {
|
if (PlatformId == -1)
|
||||||
|
{
|
||||||
// data query
|
// data query
|
||||||
sql = "SELECT DISTINCT Games_Roms.*, Platform.`Name` AS platformname, GameState.RomId AS SavedStateRomId FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id LEFT JOIN GameState ON (Games_Roms.Id = GameState.RomId AND GameState.UserId = @userid AND GameState.IsMediaGroup = 0) WHERE Games_Roms.GameId = @id" + NameSearchWhere + " ORDER BY Platform.`Name`, Games_Roms.`Name` LIMIT 1000;";
|
sql = "SELECT DISTINCT Games_Roms.*, Platform.`Name` AS platformname, GameState.RomId AS SavedStateRomId FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id LEFT JOIN GameState ON (Games_Roms.Id = GameState.RomId AND GameState.UserId = @userid AND GameState.IsMediaGroup = 0) WHERE Games_Roms.GameId = @id" + NameSearchWhere + " ORDER BY Platform.`Name`, Games_Roms.`Name` LIMIT 1000;";
|
||||||
|
|
||||||
// count query
|
// count query
|
||||||
sqlCount = "SELECT COUNT(Games_Roms.Id) AS RomCount FROM Games_Roms WHERE Games_Roms.GameId = @id" + NameSearchWhere + ";";
|
sqlCount = "SELECT COUNT(Games_Roms.Id) AS RomCount FROM Games_Roms WHERE Games_Roms.GameId = @id" + NameSearchWhere + ";";
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// data query
|
// data query
|
||||||
sql = "SELECT DISTINCT Games_Roms.*, Platform.`Name` AS platformname, GameState.RomId AS SavedStateRomId FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id LEFT JOIN GameState ON (Games_Roms.Id = GameState.RomId AND GameState.UserId = @userid AND GameState.IsMediaGroup = 0) WHERE Games_Roms.GameId = @id AND Games_Roms.PlatformId = @platformid" + NameSearchWhere + " ORDER BY Platform.`Name`, Games_Roms.`Name` LIMIT 1000;";
|
sql = "SELECT DISTINCT Games_Roms.*, Platform.`Name` AS platformname, GameState.RomId AS SavedStateRomId FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id LEFT JOIN GameState ON (Games_Roms.Id = GameState.RomId AND GameState.UserId = @userid AND GameState.IsMediaGroup = 0) WHERE Games_Roms.GameId = @id AND Games_Roms.PlatformId = @platformid" + NameSearchWhere + " ORDER BY Platform.`Name`, Games_Roms.`Name` LIMIT 1000;";
|
||||||
|
|
||||||
@@ -52,12 +61,12 @@ namespace gaseous_server.Classes
|
|||||||
|
|
||||||
dbDict.Add("platformid", PlatformId);
|
dbDict.Add("platformid", PlatformId);
|
||||||
}
|
}
|
||||||
DataTable romDT = db.ExecuteCMD(sql, dbDict);
|
DataTable romDT = db.ExecuteCMD(sql, dbDict);
|
||||||
Dictionary<string, object> rowCount = db.ExecuteCMDDict(sqlCount, dbDict)[0];
|
Dictionary<string, object> rowCount = db.ExecuteCMDDict(sqlCount, dbDict)[0];
|
||||||
DataTable platformDT = db.ExecuteCMD(sqlPlatform, dbDict);
|
DataTable platformDT = db.ExecuteCMD(sqlPlatform, dbDict);
|
||||||
|
|
||||||
if (romDT.Rows.Count > 0)
|
if (romDT.Rows.Count > 0)
|
||||||
{
|
{
|
||||||
// set count of roms
|
// set count of roms
|
||||||
GameRoms.Count = int.Parse((string)rowCount["RomCount"]);
|
GameRoms.Count = int.Parse((string)rowCount["RomCount"]);
|
||||||
|
|
||||||
@@ -73,12 +82,12 @@ namespace gaseous_server.Classes
|
|||||||
}
|
}
|
||||||
|
|
||||||
return GameRoms;
|
return GameRoms;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new Games.InvalidGameId(GameId);
|
throw new Games.InvalidGameId(GameId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GameRomItem GetRom(long RomId)
|
public static GameRomItem GetRom(long RomId)
|
||||||
{
|
{
|
||||||
@@ -100,6 +109,26 @@ namespace gaseous_server.Classes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static GameRomItem GetRom(string MD5)
|
||||||
|
{
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "SELECT Games_Roms.*, Platform.`Name` AS platformname FROM Games_Roms LEFT JOIN Platform ON Games_Roms.PlatformId = Platform.Id WHERE Games_Roms.MD5 = @id";
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
|
dbDict.Add("id", MD5);
|
||||||
|
DataTable romDT = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
|
if (romDT.Rows.Count > 0)
|
||||||
|
{
|
||||||
|
DataRow romDR = romDT.Rows[0];
|
||||||
|
GameRomItem romItem = BuildRom(romDR);
|
||||||
|
return romItem;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidRomHash(MD5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static GameRomItem UpdateRom(long RomId, long PlatformId, long GameId)
|
public static GameRomItem UpdateRom(long RomId, long PlatformId, long GameId)
|
||||||
{
|
{
|
||||||
// ensure metadata for platformid is present
|
// ensure metadata for platformid is present
|
||||||
@@ -108,10 +137,10 @@ namespace gaseous_server.Classes
|
|||||||
// ensure metadata for gameid is present
|
// ensure metadata for gameid is present
|
||||||
IGDB.Models.Game game = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
IGDB.Models.Game game = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||||
|
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
string sql = "UPDATE Games_Roms SET PlatformId=@platformid, GameId=@gameid WHERE Id = @id";
|
string sql = "UPDATE Games_Roms SET PlatformId=@platformid, GameId=@gameid WHERE Id = @id";
|
||||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
dbDict.Add("id", RomId);
|
dbDict.Add("id", RomId);
|
||||||
dbDict.Add("platformid", PlatformId);
|
dbDict.Add("platformid", PlatformId);
|
||||||
dbDict.Add("gameid", GameId);
|
dbDict.Add("gameid", GameId);
|
||||||
db.ExecuteCMD(sql, dbDict);
|
db.ExecuteCMD(sql, dbDict);
|
||||||
@@ -119,7 +148,7 @@ namespace gaseous_server.Classes
|
|||||||
GameRomItem rom = GetRom(RomId);
|
GameRomItem rom = GetRom(RomId);
|
||||||
|
|
||||||
return rom;
|
return rom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DeleteRom(long RomId)
|
public static void DeleteRom(long RomId)
|
||||||
{
|
{
|
||||||
@@ -137,7 +166,7 @@ namespace gaseous_server.Classes
|
|||||||
dbDict.Add("id", RomId);
|
dbDict.Add("id", RomId);
|
||||||
db.ExecuteCMD(sql, dbDict);
|
db.ExecuteCMD(sql, dbDict);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static GameRomItem BuildRom(DataRow romDR)
|
private static GameRomItem BuildRom(DataRow romDR)
|
||||||
{
|
{
|
||||||
@@ -151,27 +180,27 @@ namespace gaseous_server.Classes
|
|||||||
}
|
}
|
||||||
|
|
||||||
GameRomItem romItem = new GameRomItem
|
GameRomItem romItem = new GameRomItem
|
||||||
{
|
{
|
||||||
Id = (long)romDR["id"],
|
Id = (long)romDR["id"],
|
||||||
PlatformId = (long)romDR["platformid"],
|
PlatformId = (long)romDR["platformid"],
|
||||||
Platform = (string)romDR["platformname"],
|
Platform = (string)romDR["platformname"],
|
||||||
GameId = (long)romDR["gameid"],
|
GameId = (long)romDR["gameid"],
|
||||||
Name = (string)romDR["name"],
|
Name = (string)romDR["name"],
|
||||||
Size = (long)romDR["size"],
|
Size = (long)romDR["size"],
|
||||||
Crc = ((string)romDR["crc"]).ToLower(),
|
Crc = ((string)romDR["crc"]).ToLower(),
|
||||||
Md5 = ((string)romDR["md5"]).ToLower(),
|
Md5 = ((string)romDR["md5"]).ToLower(),
|
||||||
Sha1 = ((string)romDR["sha1"]).ToLower(),
|
Sha1 = ((string)romDR["sha1"]).ToLower(),
|
||||||
DevelopmentStatus = (string)romDR["developmentstatus"],
|
DevelopmentStatus = (string)romDR["developmentstatus"],
|
||||||
Attributes = Newtonsoft.Json.JsonConvert.DeserializeObject<List<KeyValuePair<string, object>>>((string)Common.ReturnValueIfNull(romDR["attributes"], "[ ]")),
|
Attributes = Newtonsoft.Json.JsonConvert.DeserializeObject<List<KeyValuePair<string, object>>>((string)Common.ReturnValueIfNull(romDR["attributes"], "[ ]")),
|
||||||
RomType = (HasheousClient.Models.LookupResponseModel.RomItem.RomTypes)(int)romDR["romtype"],
|
RomType = (HasheousClient.Models.LookupResponseModel.RomItem.RomTypes)(int)romDR["romtype"],
|
||||||
RomTypeMedia = (string)romDR["romtypemedia"],
|
RomTypeMedia = (string)romDR["romtypemedia"],
|
||||||
MediaLabel = (string)romDR["medialabel"],
|
MediaLabel = (string)romDR["medialabel"],
|
||||||
Path = (string)romDR["path"],
|
Path = (string)romDR["path"],
|
||||||
SignatureSource = (gaseous_server.Models.Signatures_Games.RomItem.SignatureSourceType)(Int32)romDR["metadatasource"],
|
SignatureSource = (gaseous_server.Models.Signatures_Games.RomItem.SignatureSourceType)(Int32)romDR["metadatasource"],
|
||||||
SignatureSourceGameTitle = (string)Common.ReturnValueIfNull(romDR["MetadataGameName"], ""),
|
SignatureSourceGameTitle = (string)Common.ReturnValueIfNull(romDR["MetadataGameName"], ""),
|
||||||
HasSaveStates = hasSaveStates,
|
HasSaveStates = hasSaveStates,
|
||||||
Library = GameLibrary.GetLibrary((int)romDR["LibraryId"])
|
Library = GameLibrary.GetLibrary((int)romDR["LibraryId"])
|
||||||
};
|
};
|
||||||
|
|
||||||
// check for a web emulator and update the romItem
|
// check for a web emulator and update the romItem
|
||||||
foreach (Models.PlatformMapping.PlatformMapItem platformMapping in Models.PlatformMapping.PlatformMap)
|
foreach (Models.PlatformMapping.PlatformMapItem platformMapping in Models.PlatformMapping.PlatformMap)
|
||||||
@@ -185,8 +214,8 @@ namespace gaseous_server.Classes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return romItem;
|
return romItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class GameRomObject
|
public class GameRomObject
|
||||||
{
|
{
|
||||||
@@ -198,13 +227,12 @@ namespace gaseous_server.Classes
|
|||||||
{
|
{
|
||||||
public long PlatformId { get; set; }
|
public long PlatformId { get; set; }
|
||||||
public string Platform { get; set; }
|
public string Platform { get; set; }
|
||||||
public Models.PlatformMapping.PlatformMapItem.WebEmulatorItem? Emulator { get; set; }
|
public Models.PlatformMapping.PlatformMapItem.WebEmulatorItem? Emulator { get; set; }
|
||||||
public long GameId { get; set; }
|
public long GameId { get; set; }
|
||||||
public string? Path { get; set; }
|
public string? Path { get; set; }
|
||||||
public string? SignatureSourceGameTitle { get; set;}
|
public string? SignatureSourceGameTitle { get; set; }
|
||||||
public bool HasSaveStates { get; set; } = false;
|
public bool HasSaveStates { get; set; } = false;
|
||||||
public GameLibrary.LibraryItem Library { get; set; }
|
public GameLibrary.LibraryItem Library { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@@ -8,21 +8,49 @@ namespace gaseous_server.SignatureIngestors.XML
|
|||||||
{
|
{
|
||||||
public class XMLIngestor : QueueItemStatus
|
public class XMLIngestor : QueueItemStatus
|
||||||
{
|
{
|
||||||
public void Import(string SearchPath, gaseous_signature_parser.parser.SignatureParser XMLType)
|
public void Import(string SearchPath, string ProcessedDirectory, gaseous_signature_parser.parser.SignatureParser XMLType)
|
||||||
{
|
{
|
||||||
// connect to database
|
// connect to database
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
|
||||||
|
string? XMLDBSearchPath = null;
|
||||||
|
string? XMLDBProcessedDirectory = null;
|
||||||
|
if (XMLType == gaseous_signature_parser.parser.SignatureParser.NoIntro)
|
||||||
|
{
|
||||||
|
XMLDBSearchPath = Path.Combine(SearchPath, "DB");
|
||||||
|
XMLDBProcessedDirectory = Path.Combine(ProcessedDirectory, "DB");
|
||||||
|
SearchPath = Path.Combine(SearchPath, "DAT");
|
||||||
|
ProcessedDirectory = Path.Combine(ProcessedDirectory, "DAT");
|
||||||
|
}
|
||||||
|
|
||||||
// process provided files
|
// process provided files
|
||||||
Logging.Log(Logging.LogType.Information, "Signature Ingestor - XML", "Importing from " + SearchPath);
|
|
||||||
if (!Directory.Exists(SearchPath))
|
if (!Directory.Exists(SearchPath))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(SearchPath);
|
Directory.CreateDirectory(SearchPath);
|
||||||
}
|
}
|
||||||
|
if (!Directory.Exists(ProcessedDirectory))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(ProcessedDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
string[] PathContents = Directory.GetFiles(SearchPath);
|
string[] PathContents = Directory.GetFiles(SearchPath);
|
||||||
Array.Sort(PathContents);
|
Array.Sort(PathContents);
|
||||||
|
|
||||||
|
string[]? DBPathContents = null;
|
||||||
|
if (XMLDBSearchPath != null)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(XMLDBSearchPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(XMLDBSearchPath);
|
||||||
|
}
|
||||||
|
if (!Directory.Exists(XMLDBProcessedDirectory))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(XMLDBProcessedDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
DBPathContents = Directory.GetFiles(XMLDBSearchPath);
|
||||||
|
}
|
||||||
|
|
||||||
string sql = "";
|
string sql = "";
|
||||||
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
Dictionary<string, object> dbDict = new Dictionary<string, object>();
|
||||||
System.Data.DataTable sigDB;
|
System.Data.DataTable sigDB;
|
||||||
@@ -33,226 +61,380 @@ namespace gaseous_server.SignatureIngestors.XML
|
|||||||
|
|
||||||
SetStatus(i + 1, PathContents.Length, "Processing signature file: " + XMLFile);
|
SetStatus(i + 1, PathContents.Length, "Processing signature file: " + XMLFile);
|
||||||
|
|
||||||
if (Common.SkippableFiles.Contains(Path.GetFileName(XMLFile), StringComparer.OrdinalIgnoreCase))
|
Logging.Log(Logging.LogType.Information, "Signature Ingest", "(" + (i + 1) + " / " + PathContents.Length + ") Processing " + XMLType.ToString() + " DAT file: " + XMLFile);
|
||||||
{
|
|
||||||
Logging.Log(Logging.LogType.Information, "Signature Ingestor - XML", "Skipping file: " + XMLFile);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// check xml file md5
|
|
||||||
Common.hashObject hashObject = new Common.hashObject(XMLFile);
|
|
||||||
sql = "SELECT * FROM Signatures_Sources WHERE SourceMD5=@sourcemd5";
|
|
||||||
dbDict = new Dictionary<string, object>();
|
|
||||||
dbDict.Add("sourcemd5", hashObject.md5hash);
|
|
||||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
|
||||||
|
|
||||||
if (sigDB.Rows.Count == 0)
|
string? DBFile = null;
|
||||||
|
if (XMLDBSearchPath != null)
|
||||||
|
{
|
||||||
|
switch (XMLType)
|
||||||
{
|
{
|
||||||
try
|
case gaseous_signature_parser.parser.SignatureParser.NoIntro:
|
||||||
{
|
for (UInt16 x = 0; x < DBPathContents.Length; x++)
|
||||||
Logging.Log(Logging.LogType.Information, "Signature Ingestor - XML", "Importing file: " + XMLFile);
|
|
||||||
|
|
||||||
// start parsing file
|
|
||||||
gaseous_signature_parser.parser Parser = new gaseous_signature_parser.parser();
|
|
||||||
RomSignatureObject Object = Parser.ParseSignatureDAT(XMLFile, XMLType);
|
|
||||||
|
|
||||||
// store in database
|
|
||||||
string[] flipNameAndDescription = {
|
|
||||||
"MAMEArcade",
|
|
||||||
"MAMEMess"
|
|
||||||
};
|
|
||||||
|
|
||||||
// store source object
|
|
||||||
bool processGames = false;
|
|
||||||
if (Object.SourceMd5 != null)
|
|
||||||
{
|
{
|
||||||
sql = "SELECT * FROM Signatures_Sources WHERE SourceMD5=@sourcemd5";
|
string tempDBFileName = Path.GetFileNameWithoutExtension(DBPathContents[x].Replace(" (DB Export)", ""));
|
||||||
dbDict = new Dictionary<string, object>();
|
if (tempDBFileName == Path.GetFileNameWithoutExtension(XMLFile))
|
||||||
string sourceUriStr = "";
|
|
||||||
if (Object.Url != null)
|
|
||||||
{
|
{
|
||||||
sourceUriStr = Object.Url.ToString();
|
DBFile = DBPathContents[x];
|
||||||
|
Logging.Log(Logging.LogType.Information, "Signature Ingest", "Using DB file: " + DBFile);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
dbDict.Add("name", Common.ReturnValueIfNull(Object.Name, ""));
|
}
|
||||||
dbDict.Add("description", Common.ReturnValueIfNull(Object.Description, ""));
|
break;
|
||||||
dbDict.Add("category", Common.ReturnValueIfNull(Object.Category, ""));
|
}
|
||||||
dbDict.Add("version", Common.ReturnValueIfNull(Object.Version, ""));
|
}
|
||||||
dbDict.Add("author", Common.ReturnValueIfNull(Object.Author, ""));
|
|
||||||
dbDict.Add("email", Common.ReturnValueIfNull(Object.Email, ""));
|
// check xml file md5
|
||||||
dbDict.Add("homepage", Common.ReturnValueIfNull(Object.Homepage, ""));
|
Common.hashObject hashObject = new Common.hashObject(XMLFile);
|
||||||
dbDict.Add("uri", sourceUriStr);
|
sql = "SELECT * FROM Signatures_Sources WHERE SourceMD5=@sourcemd5";
|
||||||
dbDict.Add("sourcetype", Common.ReturnValueIfNull(Object.SourceType, ""));
|
dbDict = new Dictionary<string, object>();
|
||||||
dbDict.Add("sourcemd5", Object.SourceMd5);
|
dbDict.Add("sourcemd5", hashObject.md5hash);
|
||||||
dbDict.Add("sourcesha1", Object.SourceSHA1);
|
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
|
if (sigDB.Rows.Count == 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// start parsing file
|
||||||
|
gaseous_signature_parser.parser Parser = new gaseous_signature_parser.parser();
|
||||||
|
RomSignatureObject Object = Parser.ParseSignatureDAT(XMLFile, DBFile, XMLType);
|
||||||
|
|
||||||
|
// store in database
|
||||||
|
string[] flipNameAndDescription = {
|
||||||
|
"MAMEArcade",
|
||||||
|
"MAMEMess"
|
||||||
|
};
|
||||||
|
|
||||||
|
// store source object
|
||||||
|
bool processGames = false;
|
||||||
|
if (Object.SourceMd5 != null)
|
||||||
|
{
|
||||||
|
int sourceId = 0;
|
||||||
|
|
||||||
|
sql = "SELECT * FROM Signatures_Sources WHERE `SourceMD5`=@sourcemd5";
|
||||||
|
dbDict = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "name", Common.ReturnValueIfNull(Object.Name, "") },
|
||||||
|
{ "description", Common.ReturnValueIfNull(Object.Description, "") },
|
||||||
|
{ "category", Common.ReturnValueIfNull(Object.Category, "") },
|
||||||
|
{ "version", Common.ReturnValueIfNull(Object.Version, "") },
|
||||||
|
{ "author", Common.ReturnValueIfNull(Object.Author, "") },
|
||||||
|
{ "email", Common.ReturnValueIfNull(Object.Email, "") },
|
||||||
|
{ "homepage", Common.ReturnValueIfNull(Object.Homepage, "") }
|
||||||
|
};
|
||||||
|
if (Object.Url == null)
|
||||||
|
{
|
||||||
|
dbDict.Add("uri", "");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dbDict.Add("uri", Common.ReturnValueIfNull(Object.Url.ToString(), ""));
|
||||||
|
}
|
||||||
|
dbDict.Add("sourcetype", Common.ReturnValueIfNull(Object.SourceType, ""));
|
||||||
|
dbDict.Add("sourcemd5", Object.SourceMd5);
|
||||||
|
dbDict.Add("sourcesha1", Object.SourceSHA1);
|
||||||
|
|
||||||
|
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||||
|
if (sigDB.Rows.Count == 0)
|
||||||
|
{
|
||||||
|
// entry not present, insert it
|
||||||
|
sql = "INSERT INTO Signatures_Sources (`Name`, `Description`, `Category`, `Version`, `Author`, `Email`, `Homepage`, `Url`, `SourceType`, `SourceMD5`, `SourceSHA1`) VALUES (@name, @description, @category, @version, @author, @email, @homepage, @uri, @sourcetype, @sourcemd5, @sourcesha1); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||||
|
|
||||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||||
if (sigDB.Rows.Count == 0)
|
|
||||||
|
sourceId = Convert.ToInt32(sigDB.Rows[0][0]);
|
||||||
|
|
||||||
|
processGames = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processGames == true)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < Object.Games.Count; ++x)
|
||||||
{
|
{
|
||||||
// entry not present, insert it
|
RomSignatureObject.Game gameObject = Object.Games[x];
|
||||||
sql = "INSERT INTO Signatures_Sources (Name, Description, Category, Version, Author, Email, Homepage, Url, SourceType, SourceMD5, SourceSHA1) VALUES (@name, @description, @category, @version, @author, @email, @homepage, @uri, @sourcetype, @sourcemd5, @sourcesha1)";
|
|
||||||
|
|
||||||
db.ExecuteCMD(sql, dbDict);
|
// set up game dictionary
|
||||||
|
dbDict = new Dictionary<string, object>();
|
||||||
processGames = true;
|
if (flipNameAndDescription.Contains(Object.SourceType))
|
||||||
}
|
|
||||||
|
|
||||||
if (processGames == true)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < Object.Games.Count; ++x)
|
|
||||||
{
|
{
|
||||||
RomSignatureObject.Game gameObject = Object.Games[x];
|
dbDict.Add("name", Common.ReturnValueIfNull(gameObject.Description, ""));
|
||||||
|
dbDict.Add("description", Common.ReturnValueIfNull(gameObject.Name, ""));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dbDict.Add("name", Common.ReturnValueIfNull(gameObject.Name, ""));
|
||||||
|
dbDict.Add("description", Common.ReturnValueIfNull(gameObject.Description, ""));
|
||||||
|
}
|
||||||
|
dbDict.Add("year", Common.ReturnValueIfNull(gameObject.Year, ""));
|
||||||
|
dbDict.Add("publisher", Common.ReturnValueIfNull(gameObject.Publisher, ""));
|
||||||
|
dbDict.Add("demo", (int)gameObject.Demo);
|
||||||
|
dbDict.Add("system", Common.ReturnValueIfNull(gameObject.System, ""));
|
||||||
|
dbDict.Add("platform", Common.ReturnValueIfNull(gameObject.System, ""));
|
||||||
|
dbDict.Add("systemvariant", Common.ReturnValueIfNull(gameObject.SystemVariant, ""));
|
||||||
|
dbDict.Add("video", Common.ReturnValueIfNull(gameObject.Video, ""));
|
||||||
|
|
||||||
// set up game dictionary
|
List<int> gameCountries = new List<int>();
|
||||||
dbDict = new Dictionary<string, object>();
|
if (
|
||||||
if (flipNameAndDescription.Contains(Object.SourceType))
|
gameObject.Country != null &&
|
||||||
|
gameObject.Country != "Unknown"
|
||||||
|
)
|
||||||
|
{
|
||||||
|
string[] countries = gameObject.Country.Split(",");
|
||||||
|
foreach (string country in countries)
|
||||||
{
|
{
|
||||||
dbDict.Add("name", Common.ReturnValueIfNull(gameObject.Description, ""));
|
int countryId = -1;
|
||||||
dbDict.Add("description", Common.ReturnValueIfNull(gameObject.Name, ""));
|
countryId = Common.GetLookupByCode(Common.LookupTypes.Country, (string)Common.ReturnValueIfNull(country.Trim(), ""));
|
||||||
}
|
if (countryId == -1)
|
||||||
else
|
|
||||||
{
|
|
||||||
dbDict.Add("name", Common.ReturnValueIfNull(gameObject.Name, ""));
|
|
||||||
dbDict.Add("description", Common.ReturnValueIfNull(gameObject.Description, ""));
|
|
||||||
}
|
|
||||||
dbDict.Add("year", Common.ReturnValueIfNull(gameObject.Year, ""));
|
|
||||||
dbDict.Add("publisher", Common.ReturnValueIfNull(gameObject.Publisher, ""));
|
|
||||||
dbDict.Add("demo", (int)gameObject.Demo);
|
|
||||||
dbDict.Add("system", Common.ReturnValueIfNull(gameObject.System, ""));
|
|
||||||
dbDict.Add("platform", Common.ReturnValueIfNull(gameObject.System, ""));
|
|
||||||
dbDict.Add("systemvariant", Common.ReturnValueIfNull(gameObject.SystemVariant, ""));
|
|
||||||
dbDict.Add("video", Common.ReturnValueIfNull(gameObject.Video, ""));
|
|
||||||
dbDict.Add("country", Common.ReturnValueIfNull(gameObject.Country, ""));
|
|
||||||
dbDict.Add("language", Common.ReturnValueIfNull(gameObject.Language, ""));
|
|
||||||
dbDict.Add("copyright", Common.ReturnValueIfNull(gameObject.Copyright, ""));
|
|
||||||
|
|
||||||
// store platform
|
|
||||||
int gameSystem = 0;
|
|
||||||
if (gameObject.System != null)
|
|
||||||
{
|
|
||||||
sql = "SELECT Id FROM Signatures_Platforms WHERE Platform=@platform";
|
|
||||||
|
|
||||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
|
||||||
if (sigDB.Rows.Count == 0)
|
|
||||||
{
|
{
|
||||||
// entry not present, insert it
|
countryId = Common.GetLookupByValue(Common.LookupTypes.Country, (string)Common.ReturnValueIfNull(country.Trim(), ""));
|
||||||
sql = "INSERT INTO Signatures_Platforms (Platform) VALUES (@platform); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
|
||||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
|
||||||
|
|
||||||
gameSystem = Convert.ToInt32(sigDB.Rows[0][0]);
|
if (countryId == -1)
|
||||||
|
{
|
||||||
|
Logging.Log(Logging.LogType.Warning, "Signature Ingest", "Unable to locate country id for " + country.Trim());
|
||||||
|
sql = "INSERT INTO Country (`Code`, `Value`) VALUES (@code, @name); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||||
|
Dictionary<string, object> countryDict = new Dictionary<string, object>{
|
||||||
|
{ "code", country.Trim() },
|
||||||
|
{ "name", country.Trim() }
|
||||||
|
};
|
||||||
|
countryId = int.Parse(db.ExecuteCMD(sql, countryDict).Rows[0][0].ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (countryId > 0)
|
||||||
{
|
{
|
||||||
gameSystem = (int)sigDB.Rows[0][0];
|
gameCountries.Add(countryId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dbDict.Add("systemid", gameSystem);
|
}
|
||||||
|
|
||||||
// store publisher
|
List<int> gameLanguages = new List<int>();
|
||||||
int gamePublisher = 0;
|
if (
|
||||||
if (gameObject.Publisher != null)
|
gameObject.Language != null &&
|
||||||
|
gameObject.Language != "nolang"
|
||||||
|
)
|
||||||
|
{
|
||||||
|
string[] languages = gameObject.Language.Split(",");
|
||||||
|
foreach (string language in languages)
|
||||||
{
|
{
|
||||||
sql = "SELECT * FROM Signatures_Publishers WHERE Publisher=@publisher";
|
int languageId = -1;
|
||||||
|
languageId = Common.GetLookupByCode(Common.LookupTypes.Language, (string)Common.ReturnValueIfNull(language.Trim(), ""));
|
||||||
|
if (languageId == -1)
|
||||||
|
{
|
||||||
|
languageId = Common.GetLookupByValue(Common.LookupTypes.Language, (string)Common.ReturnValueIfNull(language.Trim(), ""));
|
||||||
|
|
||||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
if (languageId == -1)
|
||||||
if (sigDB.Rows.Count == 0)
|
{
|
||||||
{
|
Logging.Log(Logging.LogType.Warning, "Signature Ingest", "Unable to locate language id for " + language.Trim());
|
||||||
// entry not present, insert it
|
sql = "INSERT INTO Language (`Code`, `Value`) VALUES (@code, @name); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||||
sql = "INSERT INTO Signatures_Publishers (Publisher) VALUES (@publisher); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
Dictionary<string, object> langDict = new Dictionary<string, object>{
|
||||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
{ "code", language.Trim() },
|
||||||
gamePublisher = Convert.ToInt32(sigDB.Rows[0][0]);
|
{ "name", language.Trim() }
|
||||||
|
};
|
||||||
|
languageId = int.Parse(db.ExecuteCMD(sql, langDict).Rows[0][0].ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (languageId > 0)
|
||||||
{
|
{
|
||||||
gamePublisher = (int)sigDB.Rows[0][0];
|
gameLanguages.Add(languageId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dbDict.Add("publisherid", gamePublisher);
|
}
|
||||||
|
|
||||||
// store game
|
dbDict.Add("copyright", Common.ReturnValueIfNull(gameObject.Copyright, ""));
|
||||||
int gameId = 0;
|
|
||||||
sql = "SELECT * FROM Signatures_Games WHERE Name=@name AND Year=@year AND Publisherid=@publisher AND Systemid=@systemid AND Country=@country AND Language=@language";
|
// store platform
|
||||||
|
int gameSystem = 0;
|
||||||
|
if (gameObject.System != null)
|
||||||
|
{
|
||||||
|
sql = "SELECT `Id` FROM Signatures_Platforms WHERE `Platform`=@platform";
|
||||||
|
|
||||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||||
if (sigDB.Rows.Count == 0)
|
if (sigDB.Rows.Count == 0)
|
||||||
{
|
{
|
||||||
// entry not present, insert it
|
// entry not present, insert it
|
||||||
sql = "INSERT INTO Signatures_Games " +
|
sql = "INSERT INTO Signatures_Platforms (`Platform`) VALUES (@platform); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||||
"(Name, Description, Year, PublisherId, Demo, SystemId, SystemVariant, Video, Country, Language, Copyright) VALUES " +
|
|
||||||
"(@name, @description, @year, @publisherid, @demo, @systemid, @systemvariant, @video, @country, @language, @copyright); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
|
||||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
gameId = Convert.ToInt32(sigDB.Rows[0][0]);
|
gameSystem = Convert.ToInt32(sigDB.Rows[0][0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gameId = (int)sigDB.Rows[0][0];
|
gameSystem = (int)sigDB.Rows[0][0];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
dbDict.Add("systemid", gameSystem);
|
||||||
|
|
||||||
// store rom
|
// store publisher
|
||||||
foreach (RomSignatureObject.Game.Rom romObject in gameObject.Roms)
|
int gamePublisher = 0;
|
||||||
|
if (gameObject.Publisher != null)
|
||||||
|
{
|
||||||
|
sql = "SELECT * FROM Signatures_Publishers WHERE `Publisher`=@publisher";
|
||||||
|
|
||||||
|
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||||
|
if (sigDB.Rows.Count == 0)
|
||||||
{
|
{
|
||||||
if (romObject.Md5 != null || romObject.Sha1 != null)
|
// entry not present, insert it
|
||||||
|
sql = "INSERT INTO Signatures_Publishers (`Publisher`) VALUES (@publisher); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||||
|
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||||
|
gamePublisher = Convert.ToInt32(sigDB.Rows[0][0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gamePublisher = (int)sigDB.Rows[0][0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbDict.Add("publisherid", gamePublisher);
|
||||||
|
|
||||||
|
// store game
|
||||||
|
long gameId = 0;
|
||||||
|
sql = "SELECT * FROM Signatures_Games WHERE `Name`=@name AND `Year`=@year AND `PublisherId`=@publisherid AND `SystemId`=@systemid";
|
||||||
|
|
||||||
|
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||||
|
if (sigDB.Rows.Count == 0)
|
||||||
|
{
|
||||||
|
// entry not present, insert it
|
||||||
|
sql = "INSERT INTO Signatures_Games " +
|
||||||
|
"(`Name`, `Description`, `Year`, `PublisherId`, `Demo`, `SystemId`, `SystemVariant`, `Video`, `Copyright`) VALUES " +
|
||||||
|
"(@name, @description, @year, @publisherid, @demo, @systemid, @systemvariant, @video, @copyright); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||||
|
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
|
gameId = Convert.ToInt32(sigDB.Rows[0][0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gameId = (int)sigDB.Rows[0][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert countries
|
||||||
|
foreach (int gameCountry in gameCountries)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sql = "SELECT * FROM Signatures_Games_Countries WHERE GameId = @gameid AND CountryId = @Countryid";
|
||||||
|
Dictionary<string, object> countryDict = new Dictionary<string, object>{
|
||||||
|
{ "gameid", gameId },
|
||||||
|
{ "Countryid", gameCountry }
|
||||||
|
};
|
||||||
|
if (db.ExecuteCMD(sql, countryDict).Rows.Count == 0)
|
||||||
{
|
{
|
||||||
int romId = 0;
|
sql = "INSERT INTO Signatures_Games_Countries (GameId, CountryId) VALUES (@gameid, @Countryid)";
|
||||||
sql = "SELECT * FROM Signatures_Roms WHERE GameId=@gameid AND MD5=@md5";
|
db.ExecuteCMD(sql, countryDict);
|
||||||
dbDict = new Dictionary<string, object>();
|
}
|
||||||
dbDict.Add("gameid", gameId);
|
}
|
||||||
dbDict.Add("name", Common.ReturnValueIfNull(romObject.Name, ""));
|
catch
|
||||||
dbDict.Add("size", Common.ReturnValueIfNull(romObject.Size, ""));
|
{
|
||||||
dbDict.Add("crc", Common.ReturnValueIfNull(romObject.Crc, "").ToString().ToLower());
|
Console.WriteLine("Game id: " + gameId + " with Country " + gameCountry);
|
||||||
dbDict.Add("md5", Common.ReturnValueIfNull(romObject.Md5, "").ToString().ToLower());
|
}
|
||||||
dbDict.Add("sha1", Common.ReturnValueIfNull(romObject.Sha1, "").ToString().ToLower());
|
}
|
||||||
dbDict.Add("developmentstatus", Common.ReturnValueIfNull(romObject.DevelopmentStatus, ""));
|
|
||||||
|
|
||||||
if (romObject.Attributes != null)
|
// insert languages
|
||||||
|
foreach (int gameLanguage in gameLanguages)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sql = "SELECT * FROM Signatures_Games_Languages WHERE GameId = @gameid AND LanguageId = @languageid";
|
||||||
|
Dictionary<string, object> langDict = new Dictionary<string, object>{
|
||||||
|
{ "gameid", gameId },
|
||||||
|
{ "languageid", gameLanguage }
|
||||||
|
};
|
||||||
|
if (db.ExecuteCMD(sql, langDict).Rows.Count == 0)
|
||||||
|
{
|
||||||
|
sql = "INSERT INTO Signatures_Games_Languages (GameId, LanguageId) VALUES (@gameid, @languageid)";
|
||||||
|
db.ExecuteCMD(sql, langDict);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Console.WriteLine("Game id: " + gameId + " with language " + gameLanguage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// store rom
|
||||||
|
foreach (RomSignatureObject.Game.Rom romObject in gameObject.Roms)
|
||||||
|
{
|
||||||
|
if (romObject.Md5 != null || romObject.Sha1 != null)
|
||||||
|
{
|
||||||
|
long romId = 0;
|
||||||
|
sql = "SELECT * FROM Signatures_Roms WHERE `GameId`=@gameid AND (`MD5`=@md5 OR `SHA1`=@sha1)";
|
||||||
|
dbDict = new Dictionary<string, object>();
|
||||||
|
dbDict.Add("gameid", gameId);
|
||||||
|
dbDict.Add("name", Common.ReturnValueIfNull(romObject.Name, ""));
|
||||||
|
dbDict.Add("size", Common.ReturnValueIfNull(romObject.Size, ""));
|
||||||
|
dbDict.Add("crc", Common.ReturnValueIfNull(romObject.Crc, "").ToString().ToLower());
|
||||||
|
dbDict.Add("md5", Common.ReturnValueIfNull(romObject.Md5, "").ToString().ToLower());
|
||||||
|
dbDict.Add("sha1", Common.ReturnValueIfNull(romObject.Sha1, "").ToString().ToLower());
|
||||||
|
dbDict.Add("developmentstatus", Common.ReturnValueIfNull(romObject.DevelopmentStatus, ""));
|
||||||
|
|
||||||
|
if (romObject.Attributes != null)
|
||||||
|
{
|
||||||
|
if (romObject.Attributes.Count > 0)
|
||||||
{
|
{
|
||||||
if (romObject.Attributes.Count > 0)
|
dbDict.Add("attributes", Newtonsoft.Json.JsonConvert.SerializeObject(romObject.Attributes));
|
||||||
{
|
|
||||||
dbDict.Add("attributes", Newtonsoft.Json.JsonConvert.SerializeObject(romObject.Attributes));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dbDict.Add("attributes", "[ ]");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dbDict.Add("attributes", "[ ]");
|
dbDict.Add("attributes", "");
|
||||||
}
|
}
|
||||||
dbDict.Add("romtype", (int)romObject.RomType);
|
}
|
||||||
dbDict.Add("romtypemedia", Common.ReturnValueIfNull(romObject.RomTypeMedia, ""));
|
else
|
||||||
dbDict.Add("medialabel", Common.ReturnValueIfNull(romObject.MediaLabel, ""));
|
{
|
||||||
dbDict.Add("metadatasource", romObject.SignatureSource);
|
dbDict.Add("attributes", "");
|
||||||
dbDict.Add("ingestorversion", 2);
|
}
|
||||||
|
dbDict.Add("romtype", (int)romObject.RomType);
|
||||||
|
dbDict.Add("romtypemedia", Common.ReturnValueIfNull(romObject.RomTypeMedia, ""));
|
||||||
|
dbDict.Add("medialabel", Common.ReturnValueIfNull(romObject.MediaLabel, ""));
|
||||||
|
dbDict.Add("metadatasource", romObject.SignatureSource);
|
||||||
|
dbDict.Add("ingestorversion", 2);
|
||||||
|
|
||||||
|
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||||
|
if (sigDB.Rows.Count == 0)
|
||||||
|
{
|
||||||
|
// entry not present, insert it
|
||||||
|
sql = "INSERT INTO Signatures_Roms (`GameId`, `Name`, `Size`, `CRC`, `MD5`, `SHA1`, `DevelopmentStatus`, `Attributes`, `RomType`, `RomTypeMedia`, `MediaLabel`, `MetadataSource`, `IngestorVersion`) VALUES (@gameid, @name, @size, @crc, @md5, @sha1, @developmentstatus, @attributes, @romtype, @romtypemedia, @medialabel, @metadatasource, @ingestorversion); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
||||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||||
if (sigDB.Rows.Count == 0)
|
|
||||||
{
|
|
||||||
// entry not present, insert it
|
|
||||||
sql = "INSERT INTO Signatures_Roms (GameId, Name, Size, CRC, MD5, SHA1, DevelopmentStatus, Attributes, RomType, RomTypeMedia, MediaLabel, MetadataSource, IngestorVersion) VALUES (@gameid, @name, @size, @crc, @md5, @sha1, @developmentstatus, @attributes, @romtype, @romtypemedia, @medialabel, @metadatasource, @ingestorversion); SELECT CAST(LAST_INSERT_ID() AS SIGNED);";
|
|
||||||
sigDB = db.ExecuteCMD(sql, dbDict);
|
|
||||||
|
|
||||||
|
romId = Convert.ToInt32(sigDB.Rows[0][0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
romId = (int)sigDB.Rows[0][0];
|
||||||
|
}
|
||||||
|
|
||||||
romId = Convert.ToInt32(sigDB.Rows[0][0]);
|
// map the rom to the source
|
||||||
}
|
sql = "SELECT * FROM Signatures_RomToSource WHERE SourceId=@sourceid AND RomId=@romid;";
|
||||||
else
|
dbDict.Add("romid", romId);
|
||||||
{
|
dbDict.Add("sourceId", sourceId);
|
||||||
romId = (int)sigDB.Rows[0][0];
|
|
||||||
}
|
sigDB = db.ExecuteCMD(sql, dbDict);
|
||||||
|
if (sigDB.Rows.Count == 0)
|
||||||
|
{
|
||||||
|
sql = "INSERT INTO Signatures_RomToSource (`SourceId`, `RomId`) VALUES (@sourceid, @romid);";
|
||||||
|
db.ExecuteCMD(sql, dbDict);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
|
File.Move(XMLFile, Path.Combine(ProcessedDirectory, Path.GetFileName(XMLFile)));
|
||||||
|
if (DBFile != null)
|
||||||
{
|
{
|
||||||
Logging.Log(Logging.LogType.Warning, "Signature Ingestor - XML", "Invalid import file: " + XMLFile, ex);
|
File.Move(DBFile, Path.Combine(XMLDBProcessedDirectory, Path.GetFileName(DBFile)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.Log(Logging.LogType.Debug, "Signature Ingestor - XML", "Rejecting already imported file: " + XMLFile);
|
Logging.Log(Logging.LogType.Warning, "Signature Ingest", "Error ingesting " + XMLType.ToString() + " file: " + XMLFile, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logging.Log(Logging.LogType.Information, "Signature Ingest", "Rejecting already imported " + XMLType.ToString() + " file: " + XMLFile);
|
||||||
|
File.Move(XMLFile, Path.Combine(ProcessedDirectory, Path.GetFileName(XMLFile)));
|
||||||
|
if (DBFile != null)
|
||||||
|
{
|
||||||
|
File.Move(DBFile, Path.Combine(XMLDBProcessedDirectory, Path.GetFileName(DBFile)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using System.Data;
|
using System.Data;
|
||||||
|
using gaseous_server.Models;
|
||||||
using gaseous_signature_parser.models.RomSignatureObject;
|
using gaseous_signature_parser.models.RomSignatureObject;
|
||||||
|
|
||||||
namespace gaseous_server.Classes
|
namespace gaseous_server.Classes
|
||||||
@@ -10,7 +11,8 @@ namespace gaseous_server.Classes
|
|||||||
if (md5.Length > 0)
|
if (md5.Length > 0)
|
||||||
{
|
{
|
||||||
return _GetSignature("Signatures_Roms.md5 = @searchstring", md5);
|
return _GetSignature("Signatures_Roms.md5 = @searchstring", md5);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
return _GetSignature("Signatures_Roms.sha1 = @searchstring", sha1);
|
return _GetSignature("Signatures_Roms.sha1 = @searchstring", sha1);
|
||||||
}
|
}
|
||||||
@@ -21,7 +23,8 @@ namespace gaseous_server.Classes
|
|||||||
if (TosecName.Length > 0)
|
if (TosecName.Length > 0)
|
||||||
{
|
{
|
||||||
return _GetSignature("Signatures_Roms.name = @searchstring", TosecName);
|
return _GetSignature("Signatures_Roms.name = @searchstring", TosecName);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -53,8 +56,8 @@ namespace gaseous_server.Classes
|
|||||||
System = (string)sigDbRow["Platform"],
|
System = (string)sigDbRow["Platform"],
|
||||||
SystemVariant = (string)sigDbRow["SystemVariant"],
|
SystemVariant = (string)sigDbRow["SystemVariant"],
|
||||||
Video = (string)sigDbRow["Video"],
|
Video = (string)sigDbRow["Video"],
|
||||||
Country = (string)sigDbRow["Country"],
|
Country = "",
|
||||||
Language = (string)sigDbRow["Language"],
|
Language = "",
|
||||||
Copyright = (string)sigDbRow["Copyright"]
|
Copyright = (string)sigDbRow["Copyright"]
|
||||||
},
|
},
|
||||||
Rom = new gaseous_server.Models.Signatures_Games.RomItem
|
Rom = new gaseous_server.Models.Signatures_Games.RomItem
|
||||||
@@ -66,16 +69,66 @@ namespace gaseous_server.Classes
|
|||||||
Md5 = ((string)sigDbRow["MD5"]).ToLower(),
|
Md5 = ((string)sigDbRow["MD5"]).ToLower(),
|
||||||
Sha1 = ((string)sigDbRow["SHA1"]).ToLower(),
|
Sha1 = ((string)sigDbRow["SHA1"]).ToLower(),
|
||||||
DevelopmentStatus = (string)sigDbRow["DevelopmentStatus"],
|
DevelopmentStatus = (string)sigDbRow["DevelopmentStatus"],
|
||||||
Attributes = Newtonsoft.Json.JsonConvert.DeserializeObject<List<KeyValuePair<string, object>>>((string)Common.ReturnValueIfNull(sigDbRow["Attributes"], "[]")),
|
|
||||||
RomType = (gaseous_server.Models.Signatures_Games.RomItem.RomTypes)(int)sigDbRow["RomType"],
|
RomType = (gaseous_server.Models.Signatures_Games.RomItem.RomTypes)(int)sigDbRow["RomType"],
|
||||||
RomTypeMedia = (string)sigDbRow["RomTypeMedia"],
|
RomTypeMedia = (string)sigDbRow["RomTypeMedia"],
|
||||||
MediaLabel = (string)sigDbRow["MediaLabel"],
|
MediaLabel = (string)sigDbRow["MediaLabel"],
|
||||||
SignatureSource = (gaseous_server.Models.Signatures_Games.RomItem.SignatureSourceType)(Int32)sigDbRow["MetadataSource"]
|
SignatureSource = (gaseous_server.Models.Signatures_Games.RomItem.SignatureSourceType)(Int32)sigDbRow["MetadataSource"]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
string attributeValues = (string)Common.ReturnValueIfNull(sigDbRow["Attributes"], "[]");
|
||||||
|
Dictionary<string, object> attributesDict = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(attributeValues);
|
||||||
|
if (attributesDict != null)
|
||||||
|
{
|
||||||
|
gameItem.Rom.Attributes = [.. attributesDict];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gameItem.Rom.Attributes = new List<KeyValuePair<string, object>>();
|
||||||
|
}
|
||||||
GamesList.Add(gameItem);
|
GamesList.Add(gameItem);
|
||||||
}
|
}
|
||||||
return GamesList;
|
return GamesList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Signatures_Sources> GetSources()
|
||||||
|
{
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "SELECT * FROM Signatures_Sources ORDER BY `SourceType`, `Name`;";
|
||||||
|
DataTable sigDb = db.ExecuteCMD(sql);
|
||||||
|
|
||||||
|
List<Signatures_Sources> SourcesList = new List<Signatures_Sources>();
|
||||||
|
|
||||||
|
foreach (DataRow sigDbRow in sigDb.Rows)
|
||||||
|
{
|
||||||
|
Signatures_Sources sourceItem = new Signatures_Sources
|
||||||
|
{
|
||||||
|
Id = (int)sigDbRow["Id"],
|
||||||
|
Name = (string)sigDbRow["Name"],
|
||||||
|
Description = (string)sigDbRow["Description"],
|
||||||
|
URL = (string)sigDbRow["URL"],
|
||||||
|
Category = (string)sigDbRow["Category"],
|
||||||
|
Version = (string)sigDbRow["Version"],
|
||||||
|
Author = (string)sigDbRow["Author"],
|
||||||
|
Email = (string)sigDbRow["Email"],
|
||||||
|
Homepage = (string)sigDbRow["Homepage"],
|
||||||
|
SourceType = (gaseous_signature_parser.parser.SignatureParser)Enum.Parse(typeof(gaseous_signature_parser.parser.SignatureParser), sigDbRow["SourceType"].ToString()),
|
||||||
|
MD5 = (string)sigDbRow["SourceMD5"],
|
||||||
|
SHA1 = (string)sigDbRow["SourceSHA1"]
|
||||||
|
};
|
||||||
|
SourcesList.Add(sourceItem);
|
||||||
|
}
|
||||||
|
return SourcesList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteSource(int sourceId)
|
||||||
|
{
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "DELETE FROM Signatures_Sources WHERE Id = @sourceId;";
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "sourceId", sourceId }
|
||||||
|
};
|
||||||
|
db.ExecuteCMD(sql, dbDict);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -15,7 +15,7 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/v{version:apiVersion}/[controller]")]
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
[ApiVersion("1.0")]
|
[ApiVersion("1.0", Deprecated = true)]
|
||||||
[ApiVersion("1.1")]
|
[ApiVersion("1.1")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class AccountController : Controller
|
public class AccountController : Controller
|
||||||
|
@@ -10,7 +10,7 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/v{version:apiVersion}/[controller]")]
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
[ApiVersion("1.0")]
|
[ApiVersion("1.0", Deprecated = true)]
|
||||||
[ApiVersion("1.1")]
|
[ApiVersion("1.1")]
|
||||||
[Authorize(Roles = "Admin,Gamer,Player")]
|
[Authorize(Roles = "Admin,Gamer,Player")]
|
||||||
public class BackgroundTasksController : Controller
|
public class BackgroundTasksController : Controller
|
||||||
|
@@ -12,7 +12,7 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/v{version:apiVersion}/[controller]")]
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
[ApiVersion("1.0")]
|
[ApiVersion("1.0", Deprecated = true)]
|
||||||
[ApiVersion("1.1")]
|
[ApiVersion("1.1")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class BiosController : Controller
|
public class BiosController : Controller
|
||||||
|
@@ -14,7 +14,7 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/v{version:apiVersion}/[controller]")]
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
[ApiVersion("1.0")]
|
[ApiVersion("1.0", Deprecated = true)]
|
||||||
[ApiVersion("1.1")]
|
[ApiVersion("1.1")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class CollectionsController : Controller
|
public class CollectionsController : Controller
|
||||||
@@ -29,7 +29,7 @@ namespace gaseous_server.Controllers
|
|||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_signInManager = signInManager;
|
_signInManager = signInManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all ROM collections
|
/// Gets all ROM collections
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -145,7 +145,7 @@ namespace gaseous_server.Controllers
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return NotFound(ex);
|
return NotFound(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -212,7 +212,7 @@ namespace gaseous_server.Controllers
|
|||||||
public async Task<ActionResult> NewCollectionAsync(Classes.Collections.CollectionItem Item)
|
public async Task<ActionResult> NewCollectionAsync(Classes.Collections.CollectionItem Item)
|
||||||
{
|
{
|
||||||
var user = await _userManager.GetUserAsync(User);
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -246,7 +246,7 @@ namespace gaseous_server.Controllers
|
|||||||
public async Task<ActionResult> EditCollection(long CollectionId, Classes.Collections.CollectionItem Item)
|
public async Task<ActionResult> EditCollection(long CollectionId, Classes.Collections.CollectionItem Item)
|
||||||
{
|
{
|
||||||
var user = await _userManager.GetUserAsync(User);
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -277,10 +277,10 @@ namespace gaseous_server.Controllers
|
|||||||
[Route("{CollectionId}/AlwaysInclude")]
|
[Route("{CollectionId}/AlwaysInclude")]
|
||||||
[ProducesResponseType(typeof(Classes.Collections.CollectionItem), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Classes.Collections.CollectionItem), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public async Task<ActionResult> EditCollectionAlwaysInclude(long CollectionId, [FromQuery]bool Rebuild, [FromBody]Collections.CollectionItem.AlwaysIncludeItem Inclusion)
|
public async Task<ActionResult> EditCollectionAlwaysInclude(long CollectionId, [FromQuery] bool Rebuild, [FromBody] Collections.CollectionItem.AlwaysIncludeItem Inclusion)
|
||||||
{
|
{
|
||||||
var user = await _userManager.GetUserAsync(User);
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -326,7 +326,7 @@ namespace gaseous_server.Controllers
|
|||||||
public async Task<ActionResult> DeleteCollection(long CollectionId)
|
public async Task<ActionResult> DeleteCollection(long CollectionId)
|
||||||
{
|
{
|
||||||
var user = await _userManager.GetUserAsync(User);
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@@ -15,7 +15,7 @@ using Asp.Versioning;
|
|||||||
namespace gaseous_server.Controllers
|
namespace gaseous_server.Controllers
|
||||||
{
|
{
|
||||||
[Route("api/v{version:apiVersion}/[controller]")]
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
[ApiVersion("1.0")]
|
[ApiVersion("1.0", Deprecated = true)]
|
||||||
[ApiVersion("1.1")]
|
[ApiVersion("1.1")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
@@ -23,7 +23,7 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||||
|
|
||||||
public FilterController(
|
public FilterController(
|
||||||
UserManager<ApplicationUser> userManager,
|
UserManager<ApplicationUser> userManager,
|
||||||
SignInManager<ApplicationUser> signInManager)
|
SignInManager<ApplicationUser> signInManager)
|
||||||
@@ -40,7 +40,7 @@ namespace gaseous_server.Controllers
|
|||||||
public async Task<IActionResult> FilterAsync()
|
public async Task<IActionResult> FilterAsync()
|
||||||
{
|
{
|
||||||
var user = await _userManager.GetUserAsync(User);
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
|
||||||
return Ok(Filters.Filter(user.SecurityProfile.AgeRestrictionPolicy.MaximumAgeRestriction, user.SecurityProfile.AgeRestrictionPolicy.IncludeUnrated));
|
return Ok(Filters.Filter(user.SecurityProfile.AgeRestrictionPolicy.MaximumAgeRestriction, user.SecurityProfile.AgeRestrictionPolicy.IncludeUnrated));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,7 @@ using Asp.Versioning;
|
|||||||
namespace gaseous_server.Controllers
|
namespace gaseous_server.Controllers
|
||||||
{
|
{
|
||||||
[Route("api/v{version:apiVersion}/[controller]")]
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
[ApiVersion("1.0")]
|
[ApiVersion("1.0", Deprecated = true)]
|
||||||
[ApiVersion("1.1")]
|
[ApiVersion("1.1")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
@@ -30,7 +30,7 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||||
|
|
||||||
public GamesController(
|
public GamesController(
|
||||||
UserManager<ApplicationUser> userManager,
|
UserManager<ApplicationUser> userManager,
|
||||||
SignInManager<ApplicationUser> signInManager
|
SignInManager<ApplicationUser> signInManager
|
||||||
@@ -43,7 +43,7 @@ namespace gaseous_server.Controllers
|
|||||||
[MapToApiVersion("1.0")]
|
[MapToApiVersion("1.0")]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[ProducesResponseType(typeof(List<Game>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<Game>), StatusCodes.Status200OK)]
|
||||||
public ActionResult Game(
|
public async Task<ActionResult> Game(
|
||||||
string name = "",
|
string name = "",
|
||||||
string platform = "",
|
string platform = "",
|
||||||
string genre = "",
|
string genre = "",
|
||||||
@@ -53,7 +53,7 @@ namespace gaseous_server.Controllers
|
|||||||
int minrating = -1,
|
int minrating = -1,
|
||||||
int maxrating = -1,
|
int maxrating = -1,
|
||||||
bool sortdescending = false)
|
bool sortdescending = false)
|
||||||
{
|
{
|
||||||
|
|
||||||
return Ok(GetGames(name, platform, genre, gamemode, playerperspective, theme, minrating, maxrating, "Adult", true, true, sortdescending));
|
return Ok(GetGames(name, platform, genre, gamemode, playerperspective, theme, minrating, maxrating, "Adult", true, true, sortdescending));
|
||||||
}
|
}
|
||||||
@@ -303,7 +303,7 @@ namespace gaseous_server.Controllers
|
|||||||
[ProducesResponseType(typeof(Game), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Game), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "5Minute")]
|
[ResponseCache(CacheProfileName = "5Minute")]
|
||||||
public ActionResult Game(long GameId)
|
public async Task<ActionResult> Game(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -331,7 +331,7 @@ namespace gaseous_server.Controllers
|
|||||||
[ProducesResponseType(typeof(List<AlternativeName>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<AlternativeName>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameAlternativeNames(long GameId)
|
public async Task<ActionResult> GameAlternativeNames(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -364,7 +364,7 @@ namespace gaseous_server.Controllers
|
|||||||
[ProducesResponseType(typeof(List<AgeRatings.GameAgeRating>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<AgeRatings.GameAgeRating>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameAgeClassification(long GameId)
|
public async Task<ActionResult> GameAgeClassification(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -397,7 +397,7 @@ namespace gaseous_server.Controllers
|
|||||||
[ProducesResponseType(typeof(List<Artwork>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<Artwork>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameArtwork(long GameId)
|
public async Task<ActionResult> GameArtwork(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -428,7 +428,7 @@ namespace gaseous_server.Controllers
|
|||||||
[ProducesResponseType(typeof(Artwork), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Artwork), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameArtwork(long GameId, long ArtworkId)
|
public async Task<ActionResult> GameArtwork(long GameId, long ArtworkId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -464,7 +464,7 @@ namespace gaseous_server.Controllers
|
|||||||
[Route("{GameId}/artwork/{ArtworkId}/image/{size}/{ImageName}")]
|
[Route("{GameId}/artwork/{ArtworkId}/image/{size}/{ImageName}")]
|
||||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameCoverImage(long GameId, long ArtworkId, Communications.IGDBAPI_ImageSize size, string ImageName)
|
public async Task<ActionResult> GameCoverImage(long GameId, long ArtworkId, Communications.IGDBAPI_ImageSize size, string ImageName)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -473,14 +473,15 @@ namespace gaseous_server.Controllers
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
IGDB.Models.Artwork artworkObject = Artworks.GetArtwork(ArtworkId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), true);
|
IGDB.Models.Artwork artworkObject = Artworks.GetArtwork(ArtworkId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), true);
|
||||||
|
|
||||||
if (artworkObject != null) {
|
if (artworkObject != null)
|
||||||
|
{
|
||||||
//string coverFilePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), "Artwork", size.ToString(), artworkObject.ImageId + ".jpg");
|
//string coverFilePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), "Artwork", size.ToString(), artworkObject.ImageId + ".jpg");
|
||||||
|
|
||||||
string basePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), "Artwork");
|
string basePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), "Artwork");
|
||||||
|
|
||||||
Communications comms = new Communications();
|
Communications comms = new Communications();
|
||||||
Task<string> ImgFetch = comms.GetSpecificImageFromServer(basePath, artworkObject.ImageId, size, new List<Communications.IGDBAPI_ImageSize>{ Communications.IGDBAPI_ImageSize.original });
|
Task<string> ImgFetch = comms.GetSpecificImageFromServer(basePath, artworkObject.ImageId, size, new List<Communications.IGDBAPI_ImageSize> { Communications.IGDBAPI_ImageSize.original });
|
||||||
|
|
||||||
string coverFilePath = ImgFetch.Result;
|
string coverFilePath = ImgFetch.Result;
|
||||||
|
|
||||||
@@ -531,7 +532,7 @@ namespace gaseous_server.Controllers
|
|||||||
[ProducesResponseType(typeof(Cover), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Cover), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameCover(long GameId)
|
public async Task<ActionResult> GameCover(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -566,7 +567,7 @@ namespace gaseous_server.Controllers
|
|||||||
[Route("{GameId}/cover/image/{size}/{imagename}")]
|
[Route("{GameId}/cover/image/{size}/{imagename}")]
|
||||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameCoverImage(long GameId, Communications.IGDBAPI_ImageSize size, string imagename = "")
|
public async Task<ActionResult> GameCoverImage(long GameId, Communications.IGDBAPI_ImageSize size, string imagename = "")
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -578,13 +579,14 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
IGDB.Models.Cover cover = Classes.Metadata.Covers.GetCover(gameObject.Cover.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), false);
|
IGDB.Models.Cover cover = Classes.Metadata.Covers.GetCover(gameObject.Cover.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), false);
|
||||||
string basePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), "Covers");
|
string basePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), "Covers");
|
||||||
|
|
||||||
Communications comms = new Communications();
|
Communications comms = new Communications();
|
||||||
Task<string> ImgFetch = comms.GetSpecificImageFromServer(basePath, cover.ImageId, size, new List<Communications.IGDBAPI_ImageSize>{ Communications.IGDBAPI_ImageSize.cover_big, Communications.IGDBAPI_ImageSize.original });
|
Task<string> ImgFetch = comms.GetSpecificImageFromServer(basePath, cover.ImageId, size, new List<Communications.IGDBAPI_ImageSize> { Communications.IGDBAPI_ImageSize.cover_big, Communications.IGDBAPI_ImageSize.original });
|
||||||
|
|
||||||
string coverFilePath = ImgFetch.Result;
|
string coverFilePath = ImgFetch.Result;
|
||||||
|
|
||||||
if (System.IO.File.Exists(coverFilePath)) {
|
if (System.IO.File.Exists(coverFilePath))
|
||||||
|
{
|
||||||
string filename = cover.ImageId + ".jpg";
|
string filename = cover.ImageId + ".jpg";
|
||||||
string filepath = coverFilePath;
|
string filepath = coverFilePath;
|
||||||
byte[] filedata = System.IO.File.ReadAllBytes(filepath);
|
byte[] filedata = System.IO.File.ReadAllBytes(filepath);
|
||||||
@@ -627,7 +629,7 @@ namespace gaseous_server.Controllers
|
|||||||
if (gameObject != null)
|
if (gameObject != null)
|
||||||
{
|
{
|
||||||
var user = await _userManager.GetUserAsync(User);
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
Favourites favourites = new Favourites();
|
Favourites favourites = new Favourites();
|
||||||
@@ -664,7 +666,7 @@ namespace gaseous_server.Controllers
|
|||||||
if (gameObject != null)
|
if (gameObject != null)
|
||||||
{
|
{
|
||||||
var user = await _userManager.GetUserAsync(User);
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
Favourites favourites = new Favourites();
|
Favourites favourites = new Favourites();
|
||||||
@@ -693,7 +695,7 @@ namespace gaseous_server.Controllers
|
|||||||
[ProducesResponseType(typeof(List<Genre>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<Genre>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameGenre(long GameId)
|
public async Task<ActionResult> GameGenre(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -731,7 +733,7 @@ namespace gaseous_server.Controllers
|
|||||||
[ProducesResponseType(typeof(List<Dictionary<string, object>>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<Dictionary<string, object>>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameInvolvedCompanies(long GameId)
|
public async Task<ActionResult> GameInvolvedCompanies(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -776,7 +778,7 @@ namespace gaseous_server.Controllers
|
|||||||
[ProducesResponseType(typeof(Dictionary<string, object>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Dictionary<string, object>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameInvolvedCompanies(long GameId, long CompanyId)
|
public async Task<ActionResult> GameInvolvedCompanies(long GameId, long CompanyId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -796,7 +798,8 @@ namespace gaseous_server.Controllers
|
|||||||
companyData.Add("company", company);
|
companyData.Add("company", company);
|
||||||
|
|
||||||
return Ok(companyData);
|
return Ok(companyData);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
@@ -818,7 +821,7 @@ namespace gaseous_server.Controllers
|
|||||||
[Route("{GameId}/companies/{CompanyId}/image")]
|
[Route("{GameId}/companies/{CompanyId}/image")]
|
||||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameCompanyImage(long GameId, long CompanyId)
|
public async Task<ActionResult> GameCompanyImage(long GameId, long CompanyId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -863,7 +866,7 @@ namespace gaseous_server.Controllers
|
|||||||
[Route("{GameId}/platforms")]
|
[Route("{GameId}/platforms")]
|
||||||
[ProducesResponseType(typeof(List<KeyValuePair<long, string>>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<KeyValuePair<long, string>>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GamePlatforms(long GameId)
|
public async Task<ActionResult> GamePlatforms(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -882,7 +885,7 @@ namespace gaseous_server.Controllers
|
|||||||
[ProducesResponseType(typeof(List<ReleaseDate>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<ReleaseDate>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameReleaseDates(long GameId)
|
public async Task<ActionResult> GameReleaseDates(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -895,7 +898,7 @@ namespace gaseous_server.Controllers
|
|||||||
foreach (long icId in gameObject.ReleaseDates.Ids)
|
foreach (long icId in gameObject.ReleaseDates.Ids)
|
||||||
{
|
{
|
||||||
ReleaseDate releaseDate = Classes.Metadata.ReleaseDates.GetReleaseDates(icId);
|
ReleaseDate releaseDate = Classes.Metadata.ReleaseDates.GetReleaseDates(icId);
|
||||||
|
|
||||||
rdObjects.Add(releaseDate);
|
rdObjects.Add(releaseDate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -923,7 +926,7 @@ namespace gaseous_server.Controllers
|
|||||||
public async Task<ActionResult> GameRomAsync(long GameId, int pageNumber = 0, int pageSize = 0, long PlatformId = -1, string NameSearch = "")
|
public async Task<ActionResult> GameRomAsync(long GameId, int pageNumber = 0, int pageSize = 0, long PlatformId = -1, string NameSearch = "")
|
||||||
{
|
{
|
||||||
var user = await _userManager.GetUserAsync(User);
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||||
@@ -943,7 +946,7 @@ namespace gaseous_server.Controllers
|
|||||||
[ProducesResponseType(typeof(Classes.Roms.GameRomItem), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Classes.Roms.GameRomItem), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
//[ResponseCache(CacheProfileName = "5Minute")]
|
//[ResponseCache(CacheProfileName = "5Minute")]
|
||||||
public ActionResult GameRom(long GameId, long RomId)
|
public async Task<ActionResult> GameRom(long GameId, long RomId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -972,7 +975,7 @@ namespace gaseous_server.Controllers
|
|||||||
[Route("{GameId}/roms/{RomId}")]
|
[Route("{GameId}/roms/{RomId}")]
|
||||||
[ProducesResponseType(typeof(Classes.Roms.GameRomItem), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Classes.Roms.GameRomItem), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameRomRename(long GameId, long RomId, long NewPlatformId, long NewGameId)
|
public async Task<ActionResult> GameRomRename(long GameId, long RomId, long NewPlatformId, long NewGameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1002,7 +1005,7 @@ namespace gaseous_server.Controllers
|
|||||||
[Route("{GameId}/roms/{RomId}")]
|
[Route("{GameId}/roms/{RomId}")]
|
||||||
[ProducesResponseType(typeof(Classes.Roms.GameRomItem), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Classes.Roms.GameRomItem), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameRomDelete(long GameId, long RomId)
|
public async Task<ActionResult> GameRomDelete(long GameId, long RomId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1034,7 +1037,7 @@ namespace gaseous_server.Controllers
|
|||||||
[Route("{GameId}/roms/{RomId}/file")]
|
[Route("{GameId}/roms/{RomId}/file")]
|
||||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameRomFile(long GameId, long RomId)
|
public async Task<ActionResult> GameRomFile(long GameId, long RomId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1073,7 +1076,7 @@ namespace gaseous_server.Controllers
|
|||||||
[Route("{GameId}/roms/{RomId}/{FileName}")]
|
[Route("{GameId}/roms/{RomId}/{FileName}")]
|
||||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameRomFile(long GameId, long RomId, string FileName)
|
public async Task<ActionResult> GameRomFile(long GameId, long RomId, string FileName)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1113,7 +1116,7 @@ namespace gaseous_server.Controllers
|
|||||||
public async Task<ActionResult> GameRomGroupAsync(long GameId, long RomGroupId)
|
public async Task<ActionResult> GameRomGroupAsync(long GameId, long RomGroupId)
|
||||||
{
|
{
|
||||||
var user = await _userManager.GetUserAsync(User);
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||||
@@ -1144,7 +1147,7 @@ namespace gaseous_server.Controllers
|
|||||||
public async Task<ActionResult> GetGameRomGroupAsync(long GameId)
|
public async Task<ActionResult> GetGameRomGroupAsync(long GameId)
|
||||||
{
|
{
|
||||||
var user = await _userManager.GetUserAsync(User);
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||||
@@ -1172,7 +1175,7 @@ namespace gaseous_server.Controllers
|
|||||||
[Route("{GameId}/romgroup")]
|
[Route("{GameId}/romgroup")]
|
||||||
[ProducesResponseType(typeof(Classes.RomMediaGroup.GameRomMediaGroupItem), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Classes.RomMediaGroup.GameRomMediaGroupItem), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult NewGameRomGroup(long GameId, long PlatformId, [FromBody] List<long> RomIds)
|
public async Task<ActionResult> NewGameRomGroup(long GameId, long PlatformId, [FromBody] List<long> RomIds)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1204,7 +1207,7 @@ namespace gaseous_server.Controllers
|
|||||||
public async Task<ActionResult> GameRomGroupMembersAsync(long GameId, long RomGroupId, [FromBody] List<long> RomIds)
|
public async Task<ActionResult> GameRomGroupMembersAsync(long GameId, long RomGroupId, [FromBody] List<long> RomIds)
|
||||||
{
|
{
|
||||||
var user = await _userManager.GetUserAsync(User);
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||||
@@ -1233,7 +1236,7 @@ namespace gaseous_server.Controllers
|
|||||||
[Route("{GameId}/romgroup/{RomGroupId}")]
|
[Route("{GameId}/romgroup/{RomGroupId}")]
|
||||||
[ProducesResponseType(typeof(Classes.RomMediaGroup.GameRomMediaGroupItem), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Classes.RomMediaGroup.GameRomMediaGroupItem), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameRomGroupDelete(long GameId, long RomGroupId)
|
public async Task<ActionResult> GameRomGroupDelete(long GameId, long RomGroupId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1266,7 +1269,7 @@ namespace gaseous_server.Controllers
|
|||||||
[Route("{GameId}/romgroup/{RomGroupId}/{filename}")]
|
[Route("{GameId}/romgroup/{RomGroupId}/{filename}")]
|
||||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameRomGroupFile(long GameId, long RomGroupId, string filename = "")
|
public async Task<ActionResult> GameRomGroupFile(long GameId, long RomGroupId, string filename = "")
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1311,7 +1314,7 @@ namespace gaseous_server.Controllers
|
|||||||
[Route("search")]
|
[Route("search")]
|
||||||
[ProducesResponseType(typeof(List<Game>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<Game>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameSearch(long RomId = 0, string SearchString = "")
|
public async Task<ActionResult> GameSearch(long RomId = 0, string SearchString = "")
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1352,7 +1355,7 @@ namespace gaseous_server.Controllers
|
|||||||
[ProducesResponseType(typeof(List<Screenshot>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<Screenshot>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameScreenshot(long GameId)
|
public async Task<ActionResult> GameScreenshot(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1383,12 +1386,13 @@ namespace gaseous_server.Controllers
|
|||||||
[ProducesResponseType(typeof(Screenshot), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(Screenshot), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameScreenshot(long GameId, long ScreenshotId)
|
public async Task<ActionResult> GameScreenshot(long GameId, long ScreenshotId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IGDB.Models.Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
IGDB.Models.Game gameObject = Classes.Metadata.Games.GetGame(GameId, false, false, false);
|
||||||
if (gameObject != null) {
|
if (gameObject != null)
|
||||||
|
{
|
||||||
IGDB.Models.Screenshot screenshotObject = Screenshots.GetScreenshot(ScreenshotId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), false);
|
IGDB.Models.Screenshot screenshotObject = Screenshots.GetScreenshot(ScreenshotId, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), false);
|
||||||
if (screenshotObject != null)
|
if (screenshotObject != null)
|
||||||
{
|
{
|
||||||
@@ -1417,7 +1421,7 @@ namespace gaseous_server.Controllers
|
|||||||
[Route("{GameId}/screenshots/{ScreenshotId}/image/{size}/{ImageName}")]
|
[Route("{GameId}/screenshots/{ScreenshotId}/image/{size}/{ImageName}")]
|
||||||
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public ActionResult GameScreenshotImage(long GameId, long ScreenshotId, Communications.IGDBAPI_ImageSize Size, string ImageName)
|
public async Task<ActionResult> GameScreenshotImage(long GameId, long ScreenshotId, Communications.IGDBAPI_ImageSize Size, string ImageName)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1428,7 +1432,7 @@ namespace gaseous_server.Controllers
|
|||||||
string basePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), "Screenshots");
|
string basePath = Path.Combine(Config.LibraryConfiguration.LibraryMetadataDirectory_Game(gameObject), "Screenshots");
|
||||||
|
|
||||||
Communications comms = new Communications();
|
Communications comms = new Communications();
|
||||||
Task<string> ImgFetch = comms.GetSpecificImageFromServer(basePath, screenshotObject.ImageId, Size, new List<Communications.IGDBAPI_ImageSize>{ Communications.IGDBAPI_ImageSize.original });
|
Task<string> ImgFetch = comms.GetSpecificImageFromServer(basePath, screenshotObject.ImageId, Size, new List<Communications.IGDBAPI_ImageSize> { Communications.IGDBAPI_ImageSize.original });
|
||||||
|
|
||||||
string coverFilePath = ImgFetch.Result;
|
string coverFilePath = ImgFetch.Result;
|
||||||
|
|
||||||
@@ -1468,7 +1472,7 @@ namespace gaseous_server.Controllers
|
|||||||
[ProducesResponseType(typeof(List<GameVideo>), StatusCodes.Status200OK)]
|
[ProducesResponseType(typeof(List<GameVideo>), StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ResponseCache(CacheProfileName = "7Days")]
|
[ResponseCache(CacheProfileName = "7Days")]
|
||||||
public ActionResult GameVideo(long GameId)
|
public async Task<ActionResult> GameVideo(long GameId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@@ -11,7 +11,7 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/v{version:apiVersion}/[controller]")]
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
[ApiVersion("1.0")]
|
[ApiVersion("1.0", Deprecated = true)]
|
||||||
[ApiVersion("1.1")]
|
[ApiVersion("1.1")]
|
||||||
[Authorize(Roles = "Admin")]
|
[Authorize(Roles = "Admin")]
|
||||||
public class LibraryController : Controller
|
public class LibraryController : Controller
|
||||||
|
@@ -11,7 +11,7 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/v{version:apiVersion}/[controller]")]
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
[ApiVersion("1.0")]
|
[ApiVersion("1.0", Deprecated = true)]
|
||||||
[ApiVersion("1.1")]
|
[ApiVersion("1.1")]
|
||||||
[Authorize(Roles = "Admin")]
|
[Authorize(Roles = "Admin")]
|
||||||
public class LogsController : Controller
|
public class LogsController : Controller
|
||||||
|
@@ -19,7 +19,7 @@ using Asp.Versioning;
|
|||||||
namespace gaseous_server.Controllers
|
namespace gaseous_server.Controllers
|
||||||
{
|
{
|
||||||
[Route("api/v{version:apiVersion}/[controller]")]
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
[ApiVersion("1.0")]
|
[ApiVersion("1.0", Deprecated = true)]
|
||||||
[ApiVersion("1.1")]
|
[ApiVersion("1.1")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
|
@@ -18,7 +18,7 @@ using Asp.Versioning;
|
|||||||
namespace gaseous_server.Controllers
|
namespace gaseous_server.Controllers
|
||||||
{
|
{
|
||||||
[Route("api/v{version:apiVersion}/[controller]")]
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
[ApiVersion("1.0")]
|
[ApiVersion("1.0", Deprecated = true)]
|
||||||
[ApiVersion("1.1")]
|
[ApiVersion("1.1")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
|
@@ -19,7 +19,7 @@ using Asp.Versioning;
|
|||||||
namespace gaseous_server.Controllers
|
namespace gaseous_server.Controllers
|
||||||
{
|
{
|
||||||
[Route("api/v{version:apiVersion}/[controller]")]
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
[ApiVersion("1.0")]
|
[ApiVersion("1.0", Deprecated = true)]
|
||||||
[ApiVersion("1.1")]
|
[ApiVersion("1.1")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
|
@@ -18,7 +18,7 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/v{version:apiVersion}/[controller]")]
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
[ApiVersion("1.0")]
|
[ApiVersion("1.0", Deprecated = true)]
|
||||||
[ApiVersion("1.1")]
|
[ApiVersion("1.1")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class SearchController : Controller
|
public class SearchController : Controller
|
||||||
@@ -73,9 +73,11 @@ namespace gaseous_server.Controllers
|
|||||||
private static async Task<List<GaseousGame>> _SearchForGame(long PlatformId, string SearchString)
|
private static async Task<List<GaseousGame>> _SearchForGame(long PlatformId, string SearchString)
|
||||||
{
|
{
|
||||||
string searchBody = "";
|
string searchBody = "";
|
||||||
string searchFields = "fields cover,first_release_date,name,platforms,slug; ";
|
// string searchFields = "fields cover,first_release_date,name,platforms,slug; ";
|
||||||
|
string searchFields = "fields *; ";
|
||||||
searchBody += "search \"" + SearchString + "\";";
|
searchBody += "search \"" + SearchString + "\";";
|
||||||
searchBody += "where platforms = (" + PlatformId + ");";
|
searchBody += "where platforms = (" + PlatformId + ");";
|
||||||
|
searchBody += "limit 100;";
|
||||||
|
|
||||||
List<GaseousGame>? searchCache = Communications.GetSearchCache<List<GaseousGame>>(searchFields, searchBody);
|
List<GaseousGame>? searchCache = Communications.GetSearchCache<List<GaseousGame>>(searchFields, searchBody);
|
||||||
|
|
||||||
@@ -85,12 +87,12 @@ namespace gaseous_server.Controllers
|
|||||||
// get Game metadata from data source
|
// get Game metadata from data source
|
||||||
Communications comms = new Communications();
|
Communications comms = new Communications();
|
||||||
var results = await comms.APIComm<Game>(IGDBClient.Endpoints.Games, searchFields, searchBody);
|
var results = await comms.APIComm<Game>(IGDBClient.Endpoints.Games, searchFields, searchBody);
|
||||||
|
|
||||||
List<GaseousGame> games = new List<GaseousGame>();
|
List<GaseousGame> games = new List<GaseousGame>();
|
||||||
foreach (Game game in results.ToList())
|
foreach (Game game in results.ToList())
|
||||||
{
|
{
|
||||||
Storage.CacheStatus cacheStatus = Storage.GetCacheStatus("Game", (long)game.Id);
|
Storage.CacheStatus cacheStatus = Storage.GetCacheStatus("Game", (long)game.Id);
|
||||||
switch(cacheStatus)
|
switch (cacheStatus)
|
||||||
{
|
{
|
||||||
case Storage.CacheStatus.NotPresent:
|
case Storage.CacheStatus.NotPresent:
|
||||||
Storage.NewCacheValue(game, false);
|
Storage.NewCacheValue(game, false);
|
||||||
|
@@ -9,6 +9,7 @@ using gaseous_signature_parser.models.RomSignatureObject;
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Asp.Versioning;
|
using Asp.Versioning;
|
||||||
|
using gaseous_server.Models;
|
||||||
|
|
||||||
// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
|
// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
|
||||||
|
|
||||||
@@ -16,7 +17,7 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/v{version:apiVersion}/[controller]/[action]")]
|
[Route("api/v{version:apiVersion}/[controller]/[action]")]
|
||||||
[ApiVersion("1.0")]
|
[ApiVersion("1.0", Deprecated = true)]
|
||||||
[ApiVersion("1.1")]
|
[ApiVersion("1.1")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class SignaturesController : Controller
|
public class SignaturesController : Controller
|
||||||
@@ -54,11 +55,34 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
SignatureManagement signatureManagement = new SignatureManagement();
|
SignatureManagement signatureManagement = new SignatureManagement();
|
||||||
return signatureManagement.GetByTosecName(TosecName);
|
return signatureManagement.GetByTosecName(TosecName);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MapToApiVersion("1.0")]
|
||||||
|
[MapToApiVersion("1.1")]
|
||||||
|
[HttpGet]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
public List<Signatures_Sources> GetSignatureSources()
|
||||||
|
{
|
||||||
|
SignatureManagement signatureManagement = new SignatureManagement();
|
||||||
|
return signatureManagement.GetSources();
|
||||||
|
}
|
||||||
|
|
||||||
|
[MapToApiVersion("1.0")]
|
||||||
|
[MapToApiVersion("1.1")]
|
||||||
|
[HttpDelete]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
public IActionResult DeleteSignatureSource(int Id)
|
||||||
|
{
|
||||||
|
SignatureManagement signatureManagement = new SignatureManagement();
|
||||||
|
signatureManagement.DeleteSource(Id);
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/v{version:apiVersion}/[controller]")]
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
[ApiVersion("1.0")]
|
[ApiVersion("1.0", Deprecated = true)]
|
||||||
[ApiVersion("1.1")]
|
[ApiVersion("1.1")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class SystemController : Controller
|
public class SystemController : Controller
|
||||||
@@ -70,7 +70,8 @@ namespace gaseous_server.Controllers
|
|||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("Version")]
|
[Route("Version")]
|
||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
public Version GetSystemVersion() {
|
public Version GetSystemVersion()
|
||||||
|
{
|
||||||
return Assembly.GetExecutingAssembly().GetName().Version;
|
return Assembly.GetExecutingAssembly().GetName().Version;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,32 +81,36 @@ namespace gaseous_server.Controllers
|
|||||||
[Route("VersionFile")]
|
[Route("VersionFile")]
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
public FileContentResult GetSystemVersionAsFile() {
|
public FileContentResult GetSystemVersionAsFile()
|
||||||
|
{
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
|
||||||
// get age ratings dictionary
|
// get age ratings dictionary
|
||||||
Dictionary<int, string> ClassificationBoardsStrings = new Dictionary<int, string>();
|
Dictionary<int, string> ClassificationBoardsStrings = new Dictionary<int, string>();
|
||||||
foreach(IGDB.Models.AgeRatingCategory ageRatingCategory in Enum.GetValues(typeof(IGDB.Models.AgeRatingCategory)) )
|
foreach (IGDB.Models.AgeRatingCategory ageRatingCategory in Enum.GetValues(typeof(IGDB.Models.AgeRatingCategory)))
|
||||||
{
|
{
|
||||||
ClassificationBoardsStrings.Add((int)ageRatingCategory, ageRatingCategory.ToString());
|
ClassificationBoardsStrings.Add((int)ageRatingCategory, ageRatingCategory.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary<int, string> AgeRatingsStrings = new Dictionary<int, string>();
|
Dictionary<int, string> AgeRatingsStrings = new Dictionary<int, string>();
|
||||||
foreach(IGDB.Models.AgeRatingTitle ageRatingTitle in Enum.GetValues(typeof(IGDB.Models.AgeRatingTitle)) )
|
foreach (IGDB.Models.AgeRatingTitle ageRatingTitle in Enum.GetValues(typeof(IGDB.Models.AgeRatingTitle)))
|
||||||
{
|
{
|
||||||
AgeRatingsStrings.Add((int)ageRatingTitle, ageRatingTitle.ToString());
|
AgeRatingsStrings.Add((int)ageRatingTitle, ageRatingTitle.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
string ver = "var AppVersion = \"" + Assembly.GetExecutingAssembly().GetName().Version.ToString() + "\";" + Environment.NewLine +
|
string ver = "var AppVersion = \"" + Assembly.GetExecutingAssembly().GetName().Version.ToString() + "\";" + Environment.NewLine +
|
||||||
"var DBSchemaVersion = \"" + db.GetDatabaseSchemaVersion() + "\";" + Environment.NewLine +
|
"var DBSchemaVersion = \"" + db.GetDatabaseSchemaVersion() + "\";" + Environment.NewLine +
|
||||||
"var FirstRunStatus = " + Config.ReadSetting<string>("FirstRunStatus", "0") + ";" + Environment.NewLine +
|
"var FirstRunStatus = \"" + Config.ReadSetting<string>("FirstRunStatus", "0") + "\";" + Environment.NewLine +
|
||||||
"var AgeRatingBoardsStrings = " + JsonSerializer.Serialize(ClassificationBoardsStrings, new JsonSerializerOptions{
|
"var AgeRatingBoardsStrings = " + JsonSerializer.Serialize(ClassificationBoardsStrings, new JsonSerializerOptions
|
||||||
|
{
|
||||||
WriteIndented = true
|
WriteIndented = true
|
||||||
}) + ";" + Environment.NewLine +
|
}) + ";" + Environment.NewLine +
|
||||||
"var AgeRatingStrings = " + JsonSerializer.Serialize(AgeRatingsStrings, new JsonSerializerOptions{
|
"var AgeRatingStrings = " + JsonSerializer.Serialize(AgeRatingsStrings, new JsonSerializerOptions
|
||||||
|
{
|
||||||
WriteIndented = true
|
WriteIndented = true
|
||||||
}) + ";" + Environment.NewLine +
|
}) + ";" + Environment.NewLine +
|
||||||
"var AgeRatingGroups = " + JsonSerializer.Serialize(AgeGroups.AgeGroupingsFlat, new JsonSerializerOptions{
|
"var AgeRatingGroups = " + JsonSerializer.Serialize(AgeGroups.AgeGroupingsFlat, new JsonSerializerOptions
|
||||||
|
{
|
||||||
WriteIndented = true
|
WriteIndented = true
|
||||||
}) + ";" + Environment.NewLine +
|
}) + ";" + Environment.NewLine +
|
||||||
"var emulatorDebugMode = " + Config.ReadSetting<string>("emulatorDebugMode", false.ToString()).ToLower() + ";";
|
"var emulatorDebugMode = " + Config.ReadSetting<string>("emulatorDebugMode", false.ToString()).ToLower() + ";";
|
||||||
@@ -159,7 +164,7 @@ namespace gaseous_server.Controllers
|
|||||||
{
|
{
|
||||||
// update task enabled
|
// update task enabled
|
||||||
Logging.Log(Logging.LogType.Information, "Update Background Task", "Updating task " + TaskConfiguration.Task + " with enabled value " + TaskConfiguration.Enabled.ToString());
|
Logging.Log(Logging.LogType.Information, "Update Background Task", "Updating task " + TaskConfiguration.Task + " with enabled value " + TaskConfiguration.Enabled.ToString());
|
||||||
|
|
||||||
Config.SetSetting<string>("Enabled_" + TaskConfiguration.Task, TaskConfiguration.Enabled.ToString());
|
Config.SetSetting<string>("Enabled_" + TaskConfiguration.Task, TaskConfiguration.Enabled.ToString());
|
||||||
|
|
||||||
// update existing process
|
// update existing process
|
||||||
@@ -170,12 +175,12 @@ namespace gaseous_server.Controllers
|
|||||||
item.Enabled(Boolean.Parse(TaskConfiguration.Enabled.ToString()));
|
item.Enabled(Boolean.Parse(TaskConfiguration.Enabled.ToString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update task interval
|
// update task interval
|
||||||
if (TaskConfiguration.Interval >= taskItem.MinimumAllowedInterval)
|
if (TaskConfiguration.Interval >= taskItem.MinimumAllowedInterval)
|
||||||
{
|
{
|
||||||
Logging.Log(Logging.LogType.Information, "Update Background Task", "Updating task " + TaskConfiguration.Task + " with new interval " + TaskConfiguration.Interval);
|
Logging.Log(Logging.LogType.Information, "Update Background Task", "Updating task " + TaskConfiguration.Task + " with new interval " + TaskConfiguration.Interval);
|
||||||
|
|
||||||
Config.SetSetting<string>("Interval_" + TaskConfiguration.Task, TaskConfiguration.Interval.ToString());
|
Config.SetSetting<string>("Interval_" + TaskConfiguration.Task, TaskConfiguration.Interval.ToString());
|
||||||
|
|
||||||
// update existing process
|
// update existing process
|
||||||
@@ -194,7 +199,7 @@ namespace gaseous_server.Controllers
|
|||||||
|
|
||||||
// update task weekdays
|
// update task weekdays
|
||||||
Logging.Log(Logging.LogType.Information, "Update Background Task", "Updating task " + TaskConfiguration.Task + " with new weekdays " + String.Join(", ", TaskConfiguration.AllowedDays));
|
Logging.Log(Logging.LogType.Information, "Update Background Task", "Updating task " + TaskConfiguration.Task + " with new weekdays " + String.Join(", ", TaskConfiguration.AllowedDays));
|
||||||
|
|
||||||
Config.SetSetting<string>("AllowedDays_" + TaskConfiguration.Task, Newtonsoft.Json.JsonConvert.SerializeObject(TaskConfiguration.AllowedDays));
|
Config.SetSetting<string>("AllowedDays_" + TaskConfiguration.Task, Newtonsoft.Json.JsonConvert.SerializeObject(TaskConfiguration.AllowedDays));
|
||||||
|
|
||||||
// update existing process
|
// update existing process
|
||||||
@@ -208,7 +213,7 @@ namespace gaseous_server.Controllers
|
|||||||
|
|
||||||
// update task hours
|
// update task hours
|
||||||
Logging.Log(Logging.LogType.Information, "Update Background Task", "Updating task " + TaskConfiguration.Task + " with new hours " + TaskConfiguration.AllowedStartHours + ":" + TaskConfiguration.AllowedStartMinutes.ToString("00") + " to " + TaskConfiguration.AllowedEndHours + ":" + TaskConfiguration.AllowedEndMinutes.ToString("00"));
|
Logging.Log(Logging.LogType.Information, "Update Background Task", "Updating task " + TaskConfiguration.Task + " with new hours " + TaskConfiguration.AllowedStartHours + ":" + TaskConfiguration.AllowedStartMinutes.ToString("00") + " to " + TaskConfiguration.AllowedEndHours + ":" + TaskConfiguration.AllowedEndMinutes.ToString("00"));
|
||||||
|
|
||||||
Config.SetSetting<string>("AllowedStartHours_" + TaskConfiguration.Task, TaskConfiguration.AllowedStartHours.ToString());
|
Config.SetSetting<string>("AllowedStartHours_" + TaskConfiguration.Task, TaskConfiguration.AllowedStartHours.ToString());
|
||||||
Config.SetSetting<string>("AllowedStartMinutes_" + TaskConfiguration.Task, TaskConfiguration.AllowedStartMinutes.ToString());
|
Config.SetSetting<string>("AllowedStartMinutes_" + TaskConfiguration.Task, TaskConfiguration.AllowedStartMinutes.ToString());
|
||||||
Config.SetSetting<string>("AllowedEndHours_" + TaskConfiguration.Task, TaskConfiguration.AllowedEndHours.ToString());
|
Config.SetSetting<string>("AllowedEndHours_" + TaskConfiguration.Task, TaskConfiguration.AllowedEndHours.ToString());
|
||||||
@@ -225,7 +230,7 @@ namespace gaseous_server.Controllers
|
|||||||
item.AllowedEndMinutes = TaskConfiguration.AllowedEndMinutes;
|
item.AllowedEndMinutes = TaskConfiguration.AllowedEndMinutes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -251,10 +256,17 @@ namespace gaseous_server.Controllers
|
|||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
public ActionResult GetSystemSettings()
|
public ActionResult GetSystemSettings()
|
||||||
{
|
{
|
||||||
SystemSettingsModel systemSettingsModel = new SystemSettingsModel{
|
SystemSettingsModel systemSettingsModel = new SystemSettingsModel
|
||||||
|
{
|
||||||
AlwaysLogToDisk = Config.LoggingConfiguration.AlwaysLogToDisk,
|
AlwaysLogToDisk = Config.LoggingConfiguration.AlwaysLogToDisk,
|
||||||
MinimumLogRetentionPeriod = Config.LoggingConfiguration.LogRetention,
|
MinimumLogRetentionPeriod = Config.LoggingConfiguration.LogRetention,
|
||||||
EmulatorDebugMode = Boolean.Parse(Config.ReadSetting<string>("emulatorDebugMode", false.ToString()))
|
EmulatorDebugMode = Boolean.Parse(Config.ReadSetting<string>("emulatorDebugMode", false.ToString())),
|
||||||
|
SearchTypes = Config.ReadSetting<List<Classes.Metadata.Games.SearchType>>("DefaultSearchMethods", new List<gaseous_server.Classes.Metadata.Games.SearchType>() {
|
||||||
|
Games.SearchType.where,
|
||||||
|
Games.SearchType.wherefuzzy,
|
||||||
|
Games.SearchType.search,
|
||||||
|
Games.SearchType.searchNoPlatform
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok(systemSettingsModel);
|
return Ok(systemSettingsModel);
|
||||||
@@ -273,6 +285,7 @@ namespace gaseous_server.Controllers
|
|||||||
Config.LoggingConfiguration.AlwaysLogToDisk = model.AlwaysLogToDisk;
|
Config.LoggingConfiguration.AlwaysLogToDisk = model.AlwaysLogToDisk;
|
||||||
Config.LoggingConfiguration.LogRetention = model.MinimumLogRetentionPeriod;
|
Config.LoggingConfiguration.LogRetention = model.MinimumLogRetentionPeriod;
|
||||||
Config.SetSetting<string>("emulatorDebugMode", model.EmulatorDebugMode.ToString());
|
Config.SetSetting<string>("emulatorDebugMode", model.EmulatorDebugMode.ToString());
|
||||||
|
Config.SetSetting<List<Classes.Metadata.Games.SearchType>>("DefaultSearchMethods", model.SearchTypes);
|
||||||
Config.UpdateConfig();
|
Config.UpdateConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,7 +294,8 @@ namespace gaseous_server.Controllers
|
|||||||
|
|
||||||
private SystemInfo.PathItem GetDisk(string Path)
|
private SystemInfo.PathItem GetDisk(string Path)
|
||||||
{
|
{
|
||||||
SystemInfo.PathItem pathItem = new SystemInfo.PathItem {
|
SystemInfo.PathItem pathItem = new SystemInfo.PathItem
|
||||||
|
{
|
||||||
LibraryPath = Path,
|
LibraryPath = Path,
|
||||||
SpaceUsed = Common.DirSize(new DirectoryInfo(Path)),
|
SpaceUsed = Common.DirSize(new DirectoryInfo(Path)),
|
||||||
SpaceAvailable = new DriveInfo(Path).AvailableFreeSpace,
|
SpaceAvailable = new DriveInfo(Path).AvailableFreeSpace,
|
||||||
@@ -293,11 +307,12 @@ namespace gaseous_server.Controllers
|
|||||||
|
|
||||||
public class SystemInfo
|
public class SystemInfo
|
||||||
{
|
{
|
||||||
public Version ApplicationVersion {
|
public Version ApplicationVersion
|
||||||
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return Assembly.GetExecutingAssembly().GetName().Version;
|
return Assembly.GetExecutingAssembly().GetName().Version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public List<PathItem>? Paths { get; set; }
|
public List<PathItem>? Paths { get; set; }
|
||||||
public long DatabaseSize { get; set; }
|
public long DatabaseSize { get; set; }
|
||||||
@@ -352,7 +367,7 @@ namespace gaseous_server.Controllers
|
|||||||
this.DefaultAllowedEndHours = 23;
|
this.DefaultAllowedEndHours = 23;
|
||||||
this.DefaultAllowedEndMinutes = 59;
|
this.DefaultAllowedEndMinutes = 59;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ProcessQueue.QueueItemType.TitleIngestor:
|
case ProcessQueue.QueueItemType.TitleIngestor:
|
||||||
this._UserManageable = true;
|
this._UserManageable = true;
|
||||||
this.DefaultInterval = 1;
|
this.DefaultInterval = 1;
|
||||||
@@ -589,7 +604,8 @@ namespace gaseous_server.Controllers
|
|||||||
}
|
}
|
||||||
private bool _UserManageable;
|
private bool _UserManageable;
|
||||||
public bool UserManageable => _UserManageable;
|
public bool UserManageable => _UserManageable;
|
||||||
public int Interval {
|
public int Interval
|
||||||
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return int.Parse(Config.ReadSetting<string>("Interval_" + Task, DefaultInterval.ToString()));
|
return int.Parse(Config.ReadSetting<string>("Interval_" + Task, DefaultInterval.ToString()));
|
||||||
@@ -642,7 +658,7 @@ namespace gaseous_server.Controllers
|
|||||||
public List<ProcessQueue.QueueItemType> Blocks
|
public List<ProcessQueue.QueueItemType> Blocks
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_Blocks.Contains(ProcessQueue.QueueItemType.All))
|
if (_Blocks.Contains(ProcessQueue.QueueItemType.All))
|
||||||
{
|
{
|
||||||
List<ProcessQueue.QueueItemType> blockList = new List<ProcessQueue.QueueItemType>();
|
List<ProcessQueue.QueueItemType> blockList = new List<ProcessQueue.QueueItemType>();
|
||||||
@@ -710,5 +726,6 @@ namespace gaseous_server.Controllers
|
|||||||
public bool AlwaysLogToDisk { get; set; }
|
public bool AlwaysLogToDisk { get; set; }
|
||||||
public int MinimumLogRetentionPeriod { get; set; }
|
public int MinimumLogRetentionPeriod { get; set; }
|
||||||
public bool EmulatorDebugMode { get; set; }
|
public bool EmulatorDebugMode { get; set; }
|
||||||
|
public List<Classes.Metadata.Games.SearchType> SearchTypes { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -479,6 +479,7 @@ namespace gaseous_server.Controllers.v1_1
|
|||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
|
||||||
string sql = @"
|
string sql = @"
|
||||||
|
SET SESSION sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
|
||||||
SELECT DISTINCT
|
SELECT DISTINCT
|
||||||
Game.Id,
|
Game.Id,
|
||||||
Game.`Name`,
|
Game.`Name`,
|
||||||
@@ -569,6 +570,7 @@ FROM
|
|||||||
|
|
||||||
Game retGame = Storage.BuildCacheObject<Game>(new Game() , dbResponse.Rows[i]);
|
Game retGame = Storage.BuildCacheObject<Game>(new Game() , dbResponse.Rows[i]);
|
||||||
Games.MinimalGameItem retMinGame = new Games.MinimalGameItem(retGame);
|
Games.MinimalGameItem retMinGame = new Games.MinimalGameItem(retGame);
|
||||||
|
retMinGame.Index = i;
|
||||||
if (dbResponse.Rows[i]["RomSaveCount"] != DBNull.Value || dbResponse.Rows[i]["MediaGroupSaveCount"] != DBNull.Value)
|
if (dbResponse.Rows[i]["RomSaveCount"] != DBNull.Value || dbResponse.Rows[i]["MediaGroupSaveCount"] != DBNull.Value)
|
||||||
{
|
{
|
||||||
retMinGame.HasSavedGame = true;
|
retMinGame.HasSavedGame = true;
|
||||||
@@ -591,23 +593,29 @@ FROM
|
|||||||
|
|
||||||
// build alpha list
|
// build alpha list
|
||||||
Dictionary<string, int> AlphaList = new Dictionary<string, int>();
|
Dictionary<string, int> AlphaList = new Dictionary<string, int>();
|
||||||
int CurrentPage = 0;
|
int CurrentPage = 1;
|
||||||
int NextPageIndex = 0;
|
int NextPageIndex = pageSize;
|
||||||
for (int i = 0; i < dbResponse.Rows.Count; i++)
|
for (int i = 0; i < dbResponse.Rows.Count; i++)
|
||||||
{
|
{
|
||||||
string firstChar = dbResponse.Rows[i]["NameThe"].ToString().Substring(0, 1).ToUpperInvariant();
|
string firstChar = dbResponse.Rows[i]["NameThe"].ToString().Substring(0, 1).ToUpperInvariant();
|
||||||
if (!"ABCDEFGHIJKLMNOPQRSTUVWXYZ".Contains(firstChar))
|
if (!"ABCDEFGHIJKLMNOPQRSTUVWXYZ".Contains(firstChar))
|
||||||
{
|
{
|
||||||
firstChar = "#";
|
if (!AlphaList.ContainsKey("#"))
|
||||||
|
{
|
||||||
|
AlphaList.Add("#", 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!AlphaList.ContainsKey(firstChar))
|
else
|
||||||
{
|
{
|
||||||
AlphaList.Add(firstChar, CurrentPage);
|
if (!AlphaList.ContainsKey(firstChar))
|
||||||
}
|
{
|
||||||
if (NextPageIndex == i)
|
AlphaList.Add(firstChar, CurrentPage);
|
||||||
{
|
}
|
||||||
NextPageIndex += pageSize;
|
if (NextPageIndex == i + 1)
|
||||||
CurrentPage += 1;
|
{
|
||||||
|
NextPageIndex += pageSize;
|
||||||
|
CurrentPage += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
gaseous-server/Controllers/V1.1/HealthCheckController.cs
Normal file
19
gaseous-server/Controllers/V1.1/HealthCheckController.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Asp.Versioning;
|
||||||
|
|
||||||
|
namespace gaseous_server.Controllers.v1_1
|
||||||
|
{
|
||||||
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
|
[ApiVersion("1.1")]
|
||||||
|
[ApiController]
|
||||||
|
public class HealthCheckController : ControllerBase
|
||||||
|
{
|
||||||
|
[MapToApiVersion("1.1")]
|
||||||
|
[HttpGet]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
public ActionResult Healthcheck()
|
||||||
|
{
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -6,14 +6,15 @@ using Authentication;
|
|||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using Asp.Versioning;
|
using Asp.Versioning;
|
||||||
|
using System.IO.Compression;
|
||||||
|
|
||||||
namespace gaseous_server.Controllers.v1_1
|
namespace gaseous_server.Controllers.v1_1
|
||||||
{
|
{
|
||||||
[Route("api/v{version:apiVersion}/[controller]")]
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
[ApiVersion("1.0")]
|
[ApiVersion("1.0", Deprecated = true)]
|
||||||
[ApiVersion("1.1")]
|
[ApiVersion("1.1")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
public class StateManagerController: ControllerBase
|
public class StateManagerController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||||
@@ -39,7 +40,7 @@ namespace gaseous_server.Controllers.v1_1
|
|||||||
var user = await _userManager.GetUserAsync(User);
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
|
||||||
byte[] CompressedState = Common.Compress(uploadState.StateByteArray);
|
byte[] CompressedState = Common.Compress(uploadState.StateByteArray);
|
||||||
|
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
string sql = "INSERT INTO GameState (UserId, RomId, IsMediaGroup, StateDateTime, Name, Screenshot, State, Zipped) VALUES (@userid, @romid, @ismediagroup, @statedatetime, @name, @screenshot, @state, @zipped); SELECT LAST_INSERT_ID();";
|
string sql = "INSERT INTO GameState (UserId, RomId, IsMediaGroup, StateDateTime, Name, Screenshot, State, Zipped) VALUES (@userid, @romid, @ismediagroup, @statedatetime, @name, @screenshot, @state, @zipped); SELECT LAST_INSERT_ID();";
|
||||||
Dictionary<string, object> dbDict = new Dictionary<string, object>
|
Dictionary<string, object> dbDict = new Dictionary<string, object>
|
||||||
@@ -86,7 +87,7 @@ namespace gaseous_server.Controllers.v1_1
|
|||||||
{ "ismediagroup", IsMediaGroup }
|
{ "ismediagroup", IsMediaGroup }
|
||||||
};
|
};
|
||||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
List<Models.GameStateItem> gameStates = new List<GameStateItem>();
|
List<Models.GameStateItem> gameStates = new List<GameStateItem>();
|
||||||
foreach (DataRow row in data.Rows)
|
foreach (DataRow row in data.Rows)
|
||||||
{
|
{
|
||||||
@@ -116,7 +117,7 @@ namespace gaseous_server.Controllers.v1_1
|
|||||||
{ "ismediagroup", IsMediaGroup }
|
{ "ismediagroup", IsMediaGroup }
|
||||||
};
|
};
|
||||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
if (data.Rows.Count == 0)
|
if (data.Rows.Count == 0)
|
||||||
{
|
{
|
||||||
// invalid match - return not found
|
// invalid match - return not found
|
||||||
@@ -150,7 +151,7 @@ namespace gaseous_server.Controllers.v1_1
|
|||||||
{ "ismediagroup", IsMediaGroup }
|
{ "ismediagroup", IsMediaGroup }
|
||||||
};
|
};
|
||||||
db.ExecuteNonQuery(sql, dbDict);
|
db.ExecuteNonQuery(sql, dbDict);
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +176,7 @@ namespace gaseous_server.Controllers.v1_1
|
|||||||
{ "name", model.Name }
|
{ "name", model.Name }
|
||||||
};
|
};
|
||||||
db.ExecuteNonQuery(sql, dbDict);
|
db.ExecuteNonQuery(sql, dbDict);
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,7 +201,7 @@ namespace gaseous_server.Controllers.v1_1
|
|||||||
{ "ismediagroup", IsMediaGroup }
|
{ "ismediagroup", IsMediaGroup }
|
||||||
};
|
};
|
||||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
if (data.Rows.Count == 0)
|
if (data.Rows.Count == 0)
|
||||||
{
|
{
|
||||||
// invalid match - return not found
|
// invalid match - return not found
|
||||||
@@ -233,11 +234,11 @@ namespace gaseous_server.Controllers.v1_1
|
|||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[Route("{RomId}/{StateId}/State/")]
|
[Route("{RomId}/{StateId}/State/")]
|
||||||
[Route("{RomId}/{StateId}/State/savestate.state")]
|
[Route("{RomId}/{StateId}/State/savestate.state")]
|
||||||
public async Task<ActionResult> GetStateDataAsync(long RomId, long StateId, bool IsMediaGroup = false)
|
public async Task<ActionResult> GetStateDataAsync(long RomId, long StateId, bool IsMediaGroup = false, bool StateOnly = false)
|
||||||
{
|
{
|
||||||
var user = await _userManager.GetUserAsync(User);
|
var user = await _userManager.GetUserAsync(User);
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
string sql = "SELECT Zipped, State FROM GameState WHERE Id = @id AND RomId = @romid AND IsMediaGroup = @ismediagroup AND UserId = @userid;";
|
string sql = "SELECT * FROM GameState WHERE Id = @id AND RomId = @romid AND IsMediaGroup = @ismediagroup AND UserId = @userid;";
|
||||||
Dictionary<string, object> dbDict = new Dictionary<string, object>
|
Dictionary<string, object> dbDict = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "id", StateId },
|
{ "id", StateId },
|
||||||
@@ -246,7 +247,7 @@ namespace gaseous_server.Controllers.v1_1
|
|||||||
{ "ismediagroup", IsMediaGroup }
|
{ "ismediagroup", IsMediaGroup }
|
||||||
};
|
};
|
||||||
DataTable data = db.ExecuteCMD(sql, dbDict);
|
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
if (data.Rows.Count == 0)
|
if (data.Rows.Count == 0)
|
||||||
{
|
{
|
||||||
// invalid match - return not found
|
// invalid match - return not found
|
||||||
@@ -254,7 +255,9 @@ namespace gaseous_server.Controllers.v1_1
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string filename = "savestate.state";
|
// get rom data
|
||||||
|
Roms.GameRomItem romItem = Roms.GetRom(RomId);
|
||||||
|
|
||||||
byte[] bytes;
|
byte[] bytes;
|
||||||
if ((bool)data.Rows[0]["Zipped"] == false)
|
if ((bool)data.Rows[0]["Zipped"] == false)
|
||||||
{
|
{
|
||||||
@@ -264,7 +267,86 @@ namespace gaseous_server.Controllers.v1_1
|
|||||||
{
|
{
|
||||||
bytes = Common.Decompress((byte[])data.Rows[0]["State"]);
|
bytes = Common.Decompress((byte[])data.Rows[0]["State"]);
|
||||||
}
|
}
|
||||||
string contentType = "application/octet-stream";
|
|
||||||
|
string contentType = "";
|
||||||
|
string filename = ((DateTime)data.Rows[0]["StateDateTime"]).ToString("yyyy-MM-ddTHH-mm-ss") + "-" + Path.GetFileNameWithoutExtension(romItem.Name);
|
||||||
|
|
||||||
|
|
||||||
|
if (StateOnly == true)
|
||||||
|
{
|
||||||
|
contentType = "application/octet-stream";
|
||||||
|
filename = filename + ".state";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
contentType = "application/zip";
|
||||||
|
filename = filename + ".zip";
|
||||||
|
|
||||||
|
Dictionary<string, object> RomInfo = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "Name", romItem.Name },
|
||||||
|
{ "StateDateTime", data.Rows[0]["StateDateTime"] },
|
||||||
|
{ "StateName", data.Rows[0]["Name"] }
|
||||||
|
};
|
||||||
|
if ((int)data.Rows[0]["IsMediaGroup"] == 0)
|
||||||
|
{
|
||||||
|
RomInfo.Add("MD5", romItem.Md5);
|
||||||
|
RomInfo.Add("SHA1", romItem.Sha1);
|
||||||
|
RomInfo.Add("Type", "ROM");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RomInfo.Add("Type", "Media Group");
|
||||||
|
RomInfo.Add("MediaGroupId", (long)data.Rows[0]["RomId"]);
|
||||||
|
}
|
||||||
|
string RomInfoString = Newtonsoft.Json.JsonConvert.SerializeObject(RomInfo, Newtonsoft.Json.Formatting.Indented, new Newtonsoft.Json.JsonSerializerSettings { NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore });
|
||||||
|
|
||||||
|
// compile zip file
|
||||||
|
using (var compressedFileStream = new MemoryStream())
|
||||||
|
{
|
||||||
|
List<Dictionary<string, object>> Attachments = new List<Dictionary<string, object>>();
|
||||||
|
Attachments.Add(new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "Name", "savestate.state" },
|
||||||
|
{ "Body", bytes }
|
||||||
|
});
|
||||||
|
// check if value is dbnull
|
||||||
|
if (data.Rows[0]["Screenshot"] != DBNull.Value)
|
||||||
|
{
|
||||||
|
Attachments.Add(new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "Name", "screenshot.jpg" },
|
||||||
|
{ "Body", (byte[])data.Rows[0]["Screenshot"] }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Attachments.Add(new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "Name", "rominfo.json" },
|
||||||
|
{ "Body", System.Text.Encoding.UTF8.GetBytes(RomInfoString) }
|
||||||
|
});
|
||||||
|
|
||||||
|
//Create an archive and store the stream in memory.
|
||||||
|
using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Create, false))
|
||||||
|
{
|
||||||
|
foreach (var Attachment in Attachments)
|
||||||
|
{
|
||||||
|
//Create a zip entry for each attachment
|
||||||
|
var zipEntry = zipArchive.CreateEntry(Attachment["Name"].ToString());
|
||||||
|
|
||||||
|
//Get the stream of the attachment
|
||||||
|
using (var originalFileStream = new MemoryStream((byte[])Attachment["Body"]))
|
||||||
|
using (var zipEntryStream = zipEntry.Open())
|
||||||
|
{
|
||||||
|
//Copy the attachment stream to the zip entry stream
|
||||||
|
originalFileStream.CopyTo(zipEntryStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//return new FileContentResult(compressedFileStream.ToArray(), "application/zip") { FileDownloadName = filename };
|
||||||
|
bytes = compressedFileStream.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var cd = new System.Net.Mime.ContentDisposition
|
var cd = new System.Net.Mime.ContentDisposition
|
||||||
{
|
{
|
||||||
@@ -279,6 +361,156 @@ namespace gaseous_server.Controllers.v1_1
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MapToApiVersion("1.0")]
|
||||||
|
[MapToApiVersion("1.1")]
|
||||||
|
[HttpPost]
|
||||||
|
[Authorize]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
[RequestSizeLimit(long.MaxValue)]
|
||||||
|
[Consumes("multipart/form-data")]
|
||||||
|
[DisableRequestSizeLimit, RequestFormLimits(MultipartBodyLengthLimit = long.MaxValue, ValueLengthLimit = int.MaxValue)]
|
||||||
|
[Route("Upload")]
|
||||||
|
public async Task<ActionResult> UploadStateDataAsync(IFormFile file, long RomId = 0, bool IsMediaGroup = false)
|
||||||
|
{
|
||||||
|
// get user
|
||||||
|
var user = await _userManager.GetUserAsync(User);
|
||||||
|
|
||||||
|
if (file.Length > 0)
|
||||||
|
{
|
||||||
|
MemoryStream fileContent = new MemoryStream();
|
||||||
|
file.CopyTo(fileContent);
|
||||||
|
|
||||||
|
// test if file is a zip file
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var zipArchive = new ZipArchive(fileContent, ZipArchiveMode.Read, false))
|
||||||
|
{
|
||||||
|
foreach (var entry in zipArchive.Entries)
|
||||||
|
{
|
||||||
|
if (entry.FullName == "rominfo.json")
|
||||||
|
{
|
||||||
|
using (var stream = entry.Open())
|
||||||
|
using (var reader = new StreamReader(stream))
|
||||||
|
{
|
||||||
|
string RomInfoString = reader.ReadToEnd();
|
||||||
|
Dictionary<string, object> RomInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(RomInfoString);
|
||||||
|
|
||||||
|
// get rom data
|
||||||
|
Roms.GameRomItem romItem;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
romItem = Roms.GetRom((string)RomInfo["MD5"]);
|
||||||
|
}
|
||||||
|
catch (Roms.InvalidRomHash)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
// get state data
|
||||||
|
byte[] StateData = null;
|
||||||
|
byte[] ScreenshotData = null;
|
||||||
|
string StateName = RomInfo["StateName"].ToString();
|
||||||
|
DateTime StateDateTime = DateTime.Parse(RomInfo["StateDateTime"].ToString());
|
||||||
|
IsMediaGroup = RomInfo["Type"].ToString() == "Media Group" ? true : false;
|
||||||
|
|
||||||
|
if (zipArchive.GetEntry("savestate.state") != null)
|
||||||
|
{
|
||||||
|
using (var stateStream = zipArchive.GetEntry("savestate.state").Open())
|
||||||
|
using (var stateReader = new MemoryStream())
|
||||||
|
{
|
||||||
|
stateStream.CopyTo(stateReader);
|
||||||
|
StateData = stateReader.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (zipArchive.GetEntry("screenshot.jpg") != null)
|
||||||
|
{
|
||||||
|
using (var screenshotStream = zipArchive.GetEntry("screenshot.jpg").Open())
|
||||||
|
using (var screenshotReader = new MemoryStream())
|
||||||
|
{
|
||||||
|
screenshotStream.CopyTo(screenshotReader);
|
||||||
|
ScreenshotData = screenshotReader.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// save state
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "INSERT INTO GameState (UserId, RomId, IsMediaGroup, StateDateTime, Name, Screenshot, State, Zipped) VALUES (@userid, @romid, @ismediagroup, @statedatetime, @name, @screenshot, @state, @zipped); SELECT LAST_INSERT_ID();";
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "userid", user.Id },
|
||||||
|
{ "romid", romItem.Id },
|
||||||
|
{ "ismediagroup", IsMediaGroup },
|
||||||
|
{ "statedatetime", StateDateTime },
|
||||||
|
{ "name", StateName },
|
||||||
|
{ "screenshot", ScreenshotData },
|
||||||
|
{ "state", Common.Compress(StateData) },
|
||||||
|
{ "zipped", true }
|
||||||
|
};
|
||||||
|
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
|
RomInfo.Add("RomId", romItem.Id);
|
||||||
|
RomInfo.Add("Management", "Managed");
|
||||||
|
return Ok(RomInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BadRequest("File is not a valid Gaseous state file.");
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// not a zip file
|
||||||
|
if (RomId != 0)
|
||||||
|
{
|
||||||
|
// get rom data
|
||||||
|
Roms.GameRomItem romItem;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
romItem = Roms.GetRom(RomId);
|
||||||
|
}
|
||||||
|
catch (Roms.InvalidRomHash)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
// save state
|
||||||
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
|
string sql = "INSERT INTO GameState (UserId, RomId, IsMediaGroup, StateDateTime, Name, Screenshot, State, Zipped) VALUES (@userid, @romid, @ismediagroup, @statedatetime, @name, @screenshot, @state, @zipped); SELECT LAST_INSERT_ID();";
|
||||||
|
Dictionary<string, object> dbDict = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "userid", user.Id },
|
||||||
|
{ "romid", RomId },
|
||||||
|
{ "ismediagroup", IsMediaGroup },
|
||||||
|
{ "statedatetime", DateTime.UtcNow },
|
||||||
|
{ "name", "" },
|
||||||
|
{ "screenshot", null },
|
||||||
|
{ "state", Common.Compress(fileContent.ToArray()) },
|
||||||
|
{ "zipped", true }
|
||||||
|
};
|
||||||
|
DataTable data = db.ExecuteCMD(sql, dbDict);
|
||||||
|
|
||||||
|
return Ok(new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "RomId", RomId },
|
||||||
|
{ "Management", "Unmanaged" }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return BadRequest("No rom id provided.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return BadRequest("File is empty.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Models.GameStateItem BuildGameStateItem(DataRow dr)
|
private Models.GameStateItem BuildGameStateItem(DataRow dr)
|
||||||
{
|
{
|
||||||
bool HasScreenshot = true;
|
bool HasScreenshot = true;
|
||||||
|
@@ -9,10 +9,10 @@ using Asp.Versioning;
|
|||||||
namespace gaseous_server.Controllers.v1_1
|
namespace gaseous_server.Controllers.v1_1
|
||||||
{
|
{
|
||||||
[Route("api/v{version:apiVersion}/[controller]")]
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
[ApiVersion("1.0")]
|
[ApiVersion("1.0", Deprecated = true)]
|
||||||
[ApiVersion("1.1")]
|
[ApiVersion("1.1")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
public class StatisticsController: ControllerBase
|
public class StatisticsController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||||
|
@@ -16,7 +16,7 @@ namespace gaseous_server.Models
|
|||||||
{
|
{
|
||||||
var targetType = this.GetType();
|
var targetType = this.GetType();
|
||||||
var sourceType = game.GetType();
|
var sourceType = game.GetType();
|
||||||
foreach(var prop in targetType.GetProperties(BindingFlags.Instance | BindingFlags.Public| BindingFlags.SetProperty))
|
foreach (var prop in targetType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty))
|
||||||
{
|
{
|
||||||
// check whether source object has the the property
|
// check whether source object has the the property
|
||||||
var sp = sourceType.GetProperty(prop.Name);
|
var sp = sourceType.GetProperty(prop.Name);
|
||||||
@@ -39,7 +39,11 @@ namespace gaseous_server.Models
|
|||||||
{
|
{
|
||||||
if (this.Cover.Id != null)
|
if (this.Cover.Id != null)
|
||||||
{
|
{
|
||||||
IGDB.Models.Cover cover = Covers.GetCover(Cover.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(this), false);
|
// IGDB.Models.Cover cover = Covers.GetCover(Cover.Id, Config.LibraryConfiguration.LibraryMetadataDirectory_Game(this), false);
|
||||||
|
IGDB.Models.Cover cover = new IGDB.Models.Cover()
|
||||||
|
{
|
||||||
|
Id = this.Cover.Id
|
||||||
|
};
|
||||||
|
|
||||||
return cover;
|
return cover;
|
||||||
}
|
}
|
||||||
|
@@ -13,8 +13,8 @@ using Newtonsoft.Json;
|
|||||||
|
|
||||||
namespace gaseous_server.Models
|
namespace gaseous_server.Models
|
||||||
{
|
{
|
||||||
public class PlatformMapping
|
public class PlatformMapping
|
||||||
{
|
{
|
||||||
private static Dictionary<string, PlatformMapItem> PlatformMapCache = new Dictionary<string, PlatformMapItem>();
|
private static Dictionary<string, PlatformMapItem> PlatformMapCache = new Dictionary<string, PlatformMapItem>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -27,7 +27,8 @@ namespace gaseous_server.Models
|
|||||||
{
|
{
|
||||||
string rawJson = reader.ReadToEnd();
|
string rawJson = reader.ReadToEnd();
|
||||||
List<PlatformMapItem> platforms = new List<PlatformMapItem>();
|
List<PlatformMapItem> platforms = new List<PlatformMapItem>();
|
||||||
Newtonsoft.Json.JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings{
|
Newtonsoft.Json.JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings
|
||||||
|
{
|
||||||
MaxDepth = 64
|
MaxDepth = 64
|
||||||
};
|
};
|
||||||
platforms = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PlatformMapItem>>(rawJson, jsonSerializerSettings);
|
platforms = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PlatformMapItem>>(rawJson, jsonSerializerSettings);
|
||||||
@@ -74,7 +75,7 @@ namespace gaseous_server.Models
|
|||||||
foreach (PlatformMapItem mapItem in platforms)
|
foreach (PlatformMapItem mapItem in platforms)
|
||||||
{
|
{
|
||||||
// get the IGDB platform data
|
// get the IGDB platform data
|
||||||
Platform platform = Platforms.GetPlatform(mapItem.IGDBId);
|
Platform platform = Platforms.GetPlatform(mapItem.IGDBId, false);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -92,7 +93,7 @@ namespace gaseous_server.Models
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<PlatformMapItem> PlatformMap
|
public static List<PlatformMapItem> PlatformMap
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -254,7 +255,7 @@ namespace gaseous_server.Models
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void WriteAvailableEmulators (PlatformMapItem item)
|
public static void WriteAvailableEmulators(PlatformMapItem item)
|
||||||
{
|
{
|
||||||
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
|
||||||
string sql = "";
|
string sql = "";
|
||||||
@@ -286,7 +287,7 @@ namespace gaseous_server.Models
|
|||||||
string sql = "";
|
string sql = "";
|
||||||
|
|
||||||
// get platform data
|
// get platform data
|
||||||
IGDB.Models.Platform? platform = Platforms.GetPlatform(IGDBId);
|
IGDB.Models.Platform? platform = Platforms.GetPlatform(IGDBId, false);
|
||||||
|
|
||||||
if (platform != null)
|
if (platform != null)
|
||||||
{
|
{
|
||||||
@@ -369,18 +370,20 @@ namespace gaseous_server.Models
|
|||||||
mapItem.IGDBName = platform.Name;
|
mapItem.IGDBName = platform.Name;
|
||||||
mapItem.IGDBSlug = platform.Slug;
|
mapItem.IGDBSlug = platform.Slug;
|
||||||
mapItem.AlternateNames = alternateNames;
|
mapItem.AlternateNames = alternateNames;
|
||||||
mapItem.Extensions = new PlatformMapItem.FileExtensions{
|
mapItem.Extensions = new PlatformMapItem.FileExtensions
|
||||||
|
{
|
||||||
SupportedFileExtensions = knownExtensions,
|
SupportedFileExtensions = knownExtensions,
|
||||||
UniqueFileExtensions = uniqueExtensions
|
UniqueFileExtensions = uniqueExtensions
|
||||||
};
|
};
|
||||||
mapItem.RetroPieDirectoryName = (string)Common.ReturnValueIfNull(row["RetroPieDirectoryName"], "");
|
mapItem.RetroPieDirectoryName = (string)Common.ReturnValueIfNull(row["RetroPieDirectoryName"], "");
|
||||||
mapItem.WebEmulator = new PlatformMapItem.WebEmulatorItem{
|
mapItem.WebEmulator = new PlatformMapItem.WebEmulatorItem
|
||||||
|
{
|
||||||
Type = (string)Common.ReturnValueIfNull(row["WebEmulator_Type"], ""),
|
Type = (string)Common.ReturnValueIfNull(row["WebEmulator_Type"], ""),
|
||||||
Core = (string)Common.ReturnValueIfNull(row["WebEmulator_Core"], ""),
|
Core = (string)Common.ReturnValueIfNull(row["WebEmulator_Core"], ""),
|
||||||
AvailableWebEmulators = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PlatformMapItem.WebEmulatorItem.AvailableWebEmulatorItem>>((string)Common.ReturnValueIfNull(row["AvailableWebEmulators"], "[]"))
|
AvailableWebEmulators = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PlatformMapItem.WebEmulatorItem.AvailableWebEmulatorItem>>((string)Common.ReturnValueIfNull(row["AvailableWebEmulators"], "[]"))
|
||||||
};
|
};
|
||||||
mapItem.Bios = bioss;
|
mapItem.Bios = bioss;
|
||||||
|
|
||||||
if (PlatformMapCache.ContainsKey(IGDBId.ToString()))
|
if (PlatformMapCache.ContainsKey(IGDBId.ToString()))
|
||||||
{
|
{
|
||||||
PlatformMapCache[IGDBId.ToString()] = mapItem;
|
PlatformMapCache[IGDBId.ToString()] = mapItem;
|
||||||
@@ -461,7 +464,7 @@ namespace gaseous_server.Models
|
|||||||
public string IGDBName { get; set; }
|
public string IGDBName { get; set; }
|
||||||
public string IGDBSlug { get; set; }
|
public string IGDBSlug { get; set; }
|
||||||
public List<string> AlternateNames { get; set; } = new List<string>();
|
public List<string> AlternateNames { get; set; } = new List<string>();
|
||||||
|
|
||||||
public FileExtensions Extensions { get; set; }
|
public FileExtensions Extensions { get; set; }
|
||||||
public class FileExtensions
|
public class FileExtensions
|
||||||
{
|
{
|
||||||
@@ -503,6 +506,6 @@ namespace gaseous_server.Models
|
|||||||
public string filename { get; set; }
|
public string filename { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,11 +4,11 @@ using gaseous_signature_parser.models.RomSignatureObject;
|
|||||||
|
|
||||||
namespace gaseous_server.Models
|
namespace gaseous_server.Models
|
||||||
{
|
{
|
||||||
public class Signatures_Games : HasheousClient.Models.LookupResponseModel
|
public class Signatures_Games : HasheousClient.Models.LookupResponseModel
|
||||||
{
|
{
|
||||||
public Signatures_Games()
|
public Signatures_Games()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public SignatureFlags Flags = new SignatureFlags();
|
public SignatureFlags Flags = new SignatureFlags();
|
||||||
|
|
||||||
@@ -20,4 +20,3 @@ namespace gaseous_server.Models
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
gaseous-server/Models/Signatures_Sources.cs
Normal file
20
gaseous-server/Models/Signatures_Sources.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using NuGet.Protocol.Core.Types;
|
||||||
|
|
||||||
|
namespace gaseous_server.Models
|
||||||
|
{
|
||||||
|
public class Signatures_Sources
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public string URL { get; set; }
|
||||||
|
public string Category { get; set; }
|
||||||
|
public string Version { get; set; }
|
||||||
|
public string Author { get; set; }
|
||||||
|
public string Email { get; set; }
|
||||||
|
public string Homepage { get; set; }
|
||||||
|
public gaseous_signature_parser.parser.SignatureParser SourceType { get; set; }
|
||||||
|
public string MD5 { get; set; }
|
||||||
|
public string SHA1 { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@@ -9,8 +9,8 @@ using NuGet.Packaging;
|
|||||||
|
|
||||||
namespace gaseous_server
|
namespace gaseous_server
|
||||||
{
|
{
|
||||||
public static class ProcessQueue
|
public static class ProcessQueue
|
||||||
{
|
{
|
||||||
public static List<QueueItem> QueueItems = new List<QueueItem>();
|
public static List<QueueItem> QueueItems = new List<QueueItem>();
|
||||||
|
|
||||||
public class QueueItem
|
public class QueueItem
|
||||||
@@ -115,8 +115,8 @@ namespace gaseous_server
|
|||||||
};
|
};
|
||||||
private List<QueueItemType> _Blocks = new List<QueueItemType>();
|
private List<QueueItemType> _Blocks = new List<QueueItemType>();
|
||||||
|
|
||||||
public List<DayOfWeek> AllowedDays
|
public List<DayOfWeek> AllowedDays
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _AllowedDays;
|
return _AllowedDays;
|
||||||
@@ -124,7 +124,7 @@ namespace gaseous_server
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
_AllowedDays = value;
|
_AllowedDays = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public int AllowedStartHours { get; set; } = 0;
|
public int AllowedStartHours { get; set; } = 0;
|
||||||
public int AllowedStartMinutes { get; set; } = 0;
|
public int AllowedStartMinutes { get; set; } = 0;
|
||||||
@@ -135,7 +135,7 @@ namespace gaseous_server
|
|||||||
public DateTime LastRunTime => _LastRunTime;
|
public DateTime LastRunTime => _LastRunTime;
|
||||||
public DateTime LastFinishTime => _LastFinishTime;
|
public DateTime LastFinishTime => _LastFinishTime;
|
||||||
public double LastRunDuration => _LastRunDuration;
|
public double LastRunDuration => _LastRunDuration;
|
||||||
public DateTime NextRunTime
|
public DateTime NextRunTime
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
@@ -245,15 +245,33 @@ namespace gaseous_server
|
|||||||
CallingQueueItem = this
|
CallingQueueItem = this
|
||||||
};
|
};
|
||||||
|
|
||||||
Logging.Log(Logging.LogType.Debug, "Signature Import", "Processing TOSEC files");
|
foreach (int i in Enum.GetValues(typeof(gaseous_signature_parser.parser.SignatureParser)))
|
||||||
tIngest.Import(Path.Combine(Config.LibraryConfiguration.LibrarySignatureImportDirectory, "TOSEC"), gaseous_signature_parser.parser.SignatureParser.TOSEC);
|
{
|
||||||
|
gaseous_signature_parser.parser.SignatureParser parserType = (gaseous_signature_parser.parser.SignatureParser)i;
|
||||||
Logging.Log(Logging.LogType.Debug, "Signature Import", "Processing MAME Arcade files");
|
if (
|
||||||
tIngest.Import(Path.Combine(Config.LibraryConfiguration.LibrarySignatureImportDirectory, "MAME Arcade"), gaseous_signature_parser.parser.SignatureParser.MAMEArcade);
|
parserType != gaseous_signature_parser.parser.SignatureParser.Auto &&
|
||||||
|
parserType != gaseous_signature_parser.parser.SignatureParser.Unknown
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Logging.Log(Logging.LogType.Debug, "Signature Import", "Processing " + parserType + " files");
|
||||||
|
|
||||||
|
string SignaturePath = Path.Combine(Config.LibraryConfiguration.LibrarySignatureImportDirectory, parserType.ToString());
|
||||||
|
string SignatureProcessedPath = Path.Combine(Config.LibraryConfiguration.LibrarySignatureImportDirectory, parserType.ToString());
|
||||||
|
|
||||||
|
if (!Directory.Exists(SignaturePath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(SignaturePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Directory.Exists(SignatureProcessedPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(SignatureProcessedPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
tIngest.Import(SignaturePath, SignatureProcessedPath, parserType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Logging.Log(Logging.LogType.Debug, "Signature Import", "Processing MAME MESS files");
|
|
||||||
tIngest.Import(Path.Combine(Config.LibraryConfiguration.LibrarySignatureImportDirectory, "MAME MESS"), gaseous_signature_parser.parser.SignatureParser.MAMEMess);
|
|
||||||
|
|
||||||
_SaveLastRunTime = true;
|
_SaveLastRunTime = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -350,7 +368,8 @@ namespace gaseous_server
|
|||||||
|
|
||||||
case QueueItemType.DailyMaintainer:
|
case QueueItemType.DailyMaintainer:
|
||||||
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Daily Maintenance");
|
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Daily Maintenance");
|
||||||
Classes.Maintenance maintenance = new Maintenance{
|
Classes.Maintenance maintenance = new Maintenance
|
||||||
|
{
|
||||||
CallingQueueItem = this
|
CallingQueueItem = this
|
||||||
};
|
};
|
||||||
maintenance.RunDailyMaintenance();
|
maintenance.RunDailyMaintenance();
|
||||||
@@ -361,7 +380,8 @@ namespace gaseous_server
|
|||||||
|
|
||||||
case QueueItemType.WeeklyMaintainer:
|
case QueueItemType.WeeklyMaintainer:
|
||||||
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Weekly Maintenance");
|
Logging.Log(Logging.LogType.Debug, "Timered Event", "Starting Weekly Maintenance");
|
||||||
Classes.Maintenance weeklyMaintenance = new Maintenance{
|
Classes.Maintenance weeklyMaintenance = new Maintenance
|
||||||
|
{
|
||||||
CallingQueueItem = this
|
CallingQueueItem = this
|
||||||
};
|
};
|
||||||
weeklyMaintenance.RunWeeklyMaintenance();
|
weeklyMaintenance.RunWeeklyMaintenance();
|
||||||
|
@@ -36,12 +36,27 @@ db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.Conn
|
|||||||
|
|
||||||
// set up db
|
// set up db
|
||||||
db.InitDB();
|
db.InitDB();
|
||||||
|
// create relation tables if they don't exist
|
||||||
|
Storage.CreateRelationsTables<IGDB.Models.Game>();
|
||||||
|
Storage.CreateRelationsTables<IGDB.Models.Platform>();
|
||||||
|
|
||||||
// populate db with static data for lookups
|
// populate db with static data for lookups
|
||||||
AgeRatings.PopulateAgeMap();
|
AgeRatings.PopulateAgeMap();
|
||||||
|
|
||||||
// load app settings
|
// load app settings
|
||||||
Config.InitSettings();
|
Config.InitSettings();
|
||||||
|
|
||||||
|
// set default search settings
|
||||||
|
Config.SetSetting<List<gaseous_server.Classes.Metadata.Games.SearchType>>("DefaultSearchMethods", new List<gaseous_server.Classes.Metadata.Games.SearchType>() {
|
||||||
|
Games.SearchType.where,
|
||||||
|
Games.SearchType.wherefuzzy,
|
||||||
|
Games.SearchType.search,
|
||||||
|
Games.SearchType.searchNoPlatform
|
||||||
|
});
|
||||||
|
|
||||||
|
// disable hasheous
|
||||||
|
Config.MetadataConfiguration.SignatureSource = HasheousClient.Models.MetadataModel.SignatureSources.LocalOnly;
|
||||||
|
|
||||||
// write updated settings back to the config file
|
// write updated settings back to the config file
|
||||||
Config.UpdateConfig();
|
Config.UpdateConfig();
|
||||||
|
|
||||||
@@ -121,7 +136,7 @@ builder.Services.AddControllers(options =>
|
|||||||
});
|
});
|
||||||
builder.Services.AddApiVersioning(config =>
|
builder.Services.AddApiVersioning(config =>
|
||||||
{
|
{
|
||||||
config.DefaultApiVersion = new ApiVersion(1, 0);
|
config.DefaultApiVersion = new ApiVersion(1, 1);
|
||||||
config.AssumeDefaultVersionWhenUnspecified = true;
|
config.AssumeDefaultVersionWhenUnspecified = true;
|
||||||
config.ReportApiVersions = true;
|
config.ReportApiVersions = true;
|
||||||
config.ApiVersionReader = ApiVersionReader.Combine(new UrlSegmentApiVersionReader(),
|
config.ApiVersionReader = ApiVersionReader.Combine(new UrlSegmentApiVersionReader(),
|
||||||
@@ -192,6 +207,9 @@ builder.Services.AddSwaggerGen(options =>
|
|||||||
// using System.Reflection;
|
// using System.Reflection;
|
||||||
var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
|
var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
|
||||||
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
|
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
|
||||||
|
|
||||||
|
// sort the endpoints
|
||||||
|
options.OrderActionsBy((apiDesc) => $"{apiDesc.RelativePath}_{apiDesc.HttpMethod}");
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
builder.Services.AddHostedService<TimedHostedService>();
|
builder.Services.AddHostedService<TimedHostedService>();
|
||||||
@@ -256,9 +274,12 @@ app.UseSwaggerUI(options =>
|
|||||||
var descriptions = app.DescribeApiVersions();
|
var descriptions = app.DescribeApiVersions();
|
||||||
foreach (var description in descriptions)
|
foreach (var description in descriptions)
|
||||||
{
|
{
|
||||||
var url = $"/swagger/{description.GroupName}/swagger.json";
|
if (description.IsDeprecated == false)
|
||||||
var name = description.GroupName.ToUpperInvariant();
|
{
|
||||||
options.SwaggerEndpoint(url, name);
|
var url = $"/swagger/{description.GroupName}/swagger.json";
|
||||||
|
var name = description.GroupName.ToUpperInvariant();
|
||||||
|
options.SwaggerEndpoint(url, name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -273,7 +294,7 @@ using (var scope = app.Services.CreateScope())
|
|||||||
{
|
{
|
||||||
var roleManager = scope.ServiceProvider.GetRequiredService<RoleStore>();
|
var roleManager = scope.ServiceProvider.GetRequiredService<RoleStore>();
|
||||||
var roles = new[] { "Admin", "Gamer", "Player" };
|
var roles = new[] { "Admin", "Gamer", "Player" };
|
||||||
|
|
||||||
foreach (var role in roles)
|
foreach (var role in roles)
|
||||||
{
|
{
|
||||||
if (await roleManager.FindByNameAsync(role, CancellationToken.None) == null)
|
if (await roleManager.FindByNameAsync(role, CancellationToken.None) == null)
|
||||||
@@ -303,11 +324,11 @@ app.Use(async (context, next) =>
|
|||||||
string correlationId = Guid.NewGuid().ToString();
|
string correlationId = Guid.NewGuid().ToString();
|
||||||
CallContext.SetData("CorrelationId", correlationId);
|
CallContext.SetData("CorrelationId", correlationId);
|
||||||
CallContext.SetData("CallingProcess", context.Request.Method + ": " + context.Request.Path);
|
CallContext.SetData("CallingProcess", context.Request.Method + ": " + context.Request.Path);
|
||||||
|
|
||||||
string userIdentity;
|
string userIdentity;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
userIdentity = context.User.Claims.Where(x=>x.Type==System.Security.Claims.ClaimTypes.NameIdentifier).FirstOrDefault().Value;
|
userIdentity = context.User.Claims.Where(x => x.Type == System.Security.Claims.ClaimTypes.NameIdentifier).FirstOrDefault().Value;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -329,7 +350,7 @@ app.Use(async (context, next) =>
|
|||||||
// - the server will not start while the RecoverAccount.txt file exists
|
// - the server will not start while the RecoverAccount.txt file exists
|
||||||
string PasswordRecoveryFile = Path.Combine(Config.LibraryConfiguration.LibraryRootDirectory, "RecoverAccount.txt");
|
string PasswordRecoveryFile = Path.Combine(Config.LibraryConfiguration.LibraryRootDirectory, "RecoverAccount.txt");
|
||||||
if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("recoveraccount")))
|
if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("recoveraccount")))
|
||||||
{
|
{
|
||||||
if (File.Exists(PasswordRecoveryFile))
|
if (File.Exists(PasswordRecoveryFile))
|
||||||
{
|
{
|
||||||
// password has already been set - do nothing and just exit
|
// password has already been set - do nothing and just exit
|
||||||
@@ -345,7 +366,7 @@ if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("recoveraccount")))
|
|||||||
string password = new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray());
|
string password = new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray());
|
||||||
|
|
||||||
File.WriteAllText(PasswordRecoveryFile, password);
|
File.WriteAllText(PasswordRecoveryFile, password);
|
||||||
|
|
||||||
// reset the password
|
// reset the password
|
||||||
using (var scope = app.Services.CreateScope())
|
using (var scope = app.Services.CreateScope())
|
||||||
{
|
{
|
||||||
|
73
gaseous-server/Support/Country.txt
Normal file
73
gaseous-server/Support/Country.txt
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
AE|United Arab Emirates
|
||||||
|
AL|Albania
|
||||||
|
AS|Asia
|
||||||
|
AT|Austria
|
||||||
|
AU|Australia
|
||||||
|
BA|Bosnia and Herzegovina
|
||||||
|
BE|Belgium
|
||||||
|
BG|Bulgaria
|
||||||
|
BR|Brazil
|
||||||
|
CA|Canada
|
||||||
|
CH|Switzerland
|
||||||
|
CL|Chile
|
||||||
|
CN|China
|
||||||
|
CS|Serbia and Montenegro
|
||||||
|
CY|Cyprus
|
||||||
|
CZ|Czech Republic
|
||||||
|
DE|Germany
|
||||||
|
DK|Denmark
|
||||||
|
EE|Estonia
|
||||||
|
EG|Egypt
|
||||||
|
ES|Spain
|
||||||
|
EU|Europe
|
||||||
|
FI|Finland
|
||||||
|
FR|France
|
||||||
|
GB|United Kingdom
|
||||||
|
GR|Greece
|
||||||
|
HK|Hong Kong
|
||||||
|
HR|Croatia
|
||||||
|
HU|Hungary
|
||||||
|
ID|Indonesia
|
||||||
|
IE|Ireland
|
||||||
|
IL|Israel
|
||||||
|
IN|India
|
||||||
|
IR|Iran
|
||||||
|
IS|Iceland
|
||||||
|
IT|Italy
|
||||||
|
JO|Jordan
|
||||||
|
JP|Japan
|
||||||
|
KR|Korea
|
||||||
|
KR|South Korea
|
||||||
|
LT|Lithuania
|
||||||
|
LU|Luxembourg
|
||||||
|
LV|Latvia
|
||||||
|
MN|Mongolia
|
||||||
|
MX|Mexico
|
||||||
|
MY|Malaysia
|
||||||
|
NL|Netherlands
|
||||||
|
NO|Norway
|
||||||
|
NP|Nepal
|
||||||
|
NZ|New Zealand
|
||||||
|
OM|Oman
|
||||||
|
PE|Peru
|
||||||
|
PH|Philippines
|
||||||
|
PL|Poland
|
||||||
|
PT|Portugal
|
||||||
|
QA|Qatar
|
||||||
|
RO|Romania
|
||||||
|
RU|Russia
|
||||||
|
SE|Sweden
|
||||||
|
SG|Singapore
|
||||||
|
SI|Slovenia
|
||||||
|
SK|Slovakia
|
||||||
|
TH|Thailand
|
||||||
|
TR|Turkey
|
||||||
|
TW|Taiwan
|
||||||
|
US|United States
|
||||||
|
USA|United States
|
||||||
|
VN|Vietnam
|
||||||
|
YU|Yugoslavia
|
||||||
|
ZA|South Africa
|
||||||
|
World|World
|
||||||
|
Europe|Europe
|
||||||
|
Asia|Asia
|
1
gaseous-server/Support/Database/MySQL/gaseous-1022.sql
Normal file
1
gaseous-server/Support/Database/MySQL/gaseous-1022.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE `Platform` CHANGE `Name` `Name` varchar(255);
|
37
gaseous-server/Support/Database/MySQL/gaseous-1023.sql
Normal file
37
gaseous-server/Support/Database/MySQL/gaseous-1023.sql
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
CREATE TABLE `Country` (
|
||||||
|
`Id` INT NOT NULL AUTO_INCREMENT,
|
||||||
|
`Code` VARCHAR(20) NULL,
|
||||||
|
`Value` VARCHAR(255) NULL,
|
||||||
|
PRIMARY KEY (`Id`),
|
||||||
|
INDEX `id_Code` (`Code` ASC) VISIBLE,
|
||||||
|
INDEX `id_Value` (`Value` ASC) VISIBLE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `Language` (
|
||||||
|
`Id` INT NOT NULL AUTO_INCREMENT,
|
||||||
|
`Code` VARCHAR(20) NULL,
|
||||||
|
`Value` VARCHAR(255) NULL,
|
||||||
|
PRIMARY KEY (`Id`),
|
||||||
|
INDEX `id_Code` (`Code` ASC) VISIBLE,
|
||||||
|
INDEX `id_Value` (`Value` ASC) VISIBLE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `Signatures_RomToSource` (
|
||||||
|
`SourceId` int NOT NULL,
|
||||||
|
`RomId` int NOT NULL,
|
||||||
|
PRIMARY KEY (`SourceId`, `RomId`)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `Signatures_Games_Countries` (
|
||||||
|
`GameId` INT NOT NULL,
|
||||||
|
`CountryId` INT NOT NULL,
|
||||||
|
PRIMARY KEY (`GameId`, `CountryId`),
|
||||||
|
CONSTRAINT `GameCountry` FOREIGN KEY (`GameId`) REFERENCES `Signatures_Games` (`Id`) ON DELETE CASCADE ON UPDATE NO ACTION
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `Signatures_Games_Languages` (
|
||||||
|
`GameId` INT NOT NULL,
|
||||||
|
`LanguageId` INT NOT NULL,
|
||||||
|
PRIMARY KEY (`GameId`, `LanguageId`),
|
||||||
|
CONSTRAINT `GameLanguage` FOREIGN KEY (`GameId`) REFERENCES `Signatures_Games` (`Id`) ON DELETE CASCADE ON UPDATE NO ACTION
|
||||||
|
);
|
47
gaseous-server/Support/Language.txt
Normal file
47
gaseous-server/Support/Language.txt
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
ar|Arabic
|
||||||
|
bg|Bulgarian
|
||||||
|
bs|Bosnian
|
||||||
|
cs|Czech
|
||||||
|
cy|Welsh
|
||||||
|
da|Danish
|
||||||
|
de|German
|
||||||
|
el|Greek
|
||||||
|
en|English
|
||||||
|
eo|Esperanto
|
||||||
|
es|Spanish
|
||||||
|
et|Estonian
|
||||||
|
fa|Persian
|
||||||
|
fi|Finnish
|
||||||
|
fr|French
|
||||||
|
fr-ca|French Canadian
|
||||||
|
ga|Irish
|
||||||
|
gd|Gaelic
|
||||||
|
gu|Gujarati
|
||||||
|
he|Hebrew
|
||||||
|
hi|Hindi
|
||||||
|
hr|Croatian
|
||||||
|
hu|Hungarian
|
||||||
|
is|Icelandic
|
||||||
|
it|Italian
|
||||||
|
ja|Japanese
|
||||||
|
ko|Korean
|
||||||
|
lt|Lithuanian
|
||||||
|
lv|Latvian
|
||||||
|
ms|Malay
|
||||||
|
nl|Dutch
|
||||||
|
no|Norwegian
|
||||||
|
pl|Polish
|
||||||
|
pt|Portuguese
|
||||||
|
ro|Romanian
|
||||||
|
ru|Russian
|
||||||
|
sk|Slovakian
|
||||||
|
sl|Slovenian
|
||||||
|
sq|Albanian
|
||||||
|
sr|Serbian
|
||||||
|
sv|Swedish
|
||||||
|
th|Thai
|
||||||
|
tr|Turkish
|
||||||
|
ur|Urdu
|
||||||
|
vi|Vietnamese
|
||||||
|
yi|Yiddish
|
||||||
|
zh|Chinese
|
File diff suppressed because it is too large
Load Diff
@@ -16,20 +16,20 @@
|
|||||||
<DocumentationFile>bin\Release\net8.0\gaseous-server.xml</DocumentationFile>
|
<DocumentationFile>bin\Release\net8.0\gaseous-server.xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Asp.Versioning.Mvc" Version="8.0.0" />
|
<PackageReference Include="Asp.Versioning.Mvc" Version="8.1.0" />
|
||||||
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.0.0" />
|
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
|
||||||
<PackageReference Include="gaseous-signature-parser" Version="2.1.0" />
|
<PackageReference Include="gaseous-signature-parser" Version="2.3.0" />
|
||||||
<PackageReference Include="gaseous.IGDB" Version="1.0.2" />
|
<PackageReference Include="gaseous.IGDB" Version="1.0.2" />
|
||||||
<PackageReference Include="hasheous-client" Version="0.2.0" />
|
<PackageReference Include="hasheous-client" Version="0.1.0" />
|
||||||
<PackageReference Include="Magick.NET-Q8-AnyCPU" Version="13.5.0" />
|
<PackageReference Include="Magick.NET-Q8-AnyCPU" Version="13.5.0" />
|
||||||
<PackageReference Include="sharpcompress" Version="0.36.0" />
|
<PackageReference Include="sharpcompress" Version="0.38.0" />
|
||||||
<PackageReference Include="Squid-Box.SevenZipSharp" Version="1.6.1.23" />
|
<PackageReference Include="Squid-Box.SevenZipSharp" Version="1.6.2.24" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.9.0" />
|
||||||
<PackageReference Include="MySqlConnector" Version="2.3.5" />
|
<PackageReference Include="MySqlConnector" Version="2.3.7" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="8.0.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="8.0.10" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.1" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.10" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="8.0.0" />
|
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="8.0.6" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -64,6 +64,8 @@
|
|||||||
<None Remove="Support\Database\MySQL\gaseous-1019.sql" />
|
<None Remove="Support\Database\MySQL\gaseous-1019.sql" />
|
||||||
<None Remove="Support\Database\MySQL\gaseous-1020.sql" />
|
<None Remove="Support\Database\MySQL\gaseous-1020.sql" />
|
||||||
<None Remove="Support\Database\MySQL\gaseous-1021.sql" />
|
<None Remove="Support\Database\MySQL\gaseous-1021.sql" />
|
||||||
|
<None Remove="Support\Database\MySQL\gaseous-1022.sql" />
|
||||||
|
<None Remove="Support\Database\MySQL\gaseous-1023.sql" />
|
||||||
<None Remove="Classes\Metadata\" />
|
<None Remove="Classes\Metadata\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -85,6 +87,8 @@
|
|||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Support\Country.txt" />
|
||||||
|
<EmbeddedResource Include="Support\Language.txt" />
|
||||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1000.sql" />
|
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1000.sql" />
|
||||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1001.sql" />
|
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1001.sql" />
|
||||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1002.sql" />
|
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1002.sql" />
|
||||||
@@ -108,5 +112,7 @@
|
|||||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1019.sql" />
|
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1019.sql" />
|
||||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1020.sql" />
|
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1020.sql" />
|
||||||
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1021.sql" />
|
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1021.sql" />
|
||||||
|
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1022.sql" />
|
||||||
|
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1023.sql" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@@ -40,7 +40,11 @@
|
|||||||
|
|
||||||
EJS_threads = false;
|
EJS_threads = false;
|
||||||
|
|
||||||
EJS_onSaveState = function(e) {
|
EJS_Buttons = {
|
||||||
|
exitEmulation: false
|
||||||
|
}
|
||||||
|
|
||||||
|
EJS_onSaveState = function (e) {
|
||||||
var returnValue = {
|
var returnValue = {
|
||||||
"ScreenshotByteArrayBase64": btoa(Uint8ToString(e.screenshot)),
|
"ScreenshotByteArrayBase64": btoa(Uint8ToString(e.screenshot)),
|
||||||
"StateByteArrayBase64": btoa(Uint8ToString(e.state))
|
"StateByteArrayBase64": btoa(Uint8ToString(e.state))
|
||||||
@@ -67,7 +71,7 @@
|
|||||||
returnValue = undefined;
|
returnValue = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
EJS_onLoadState = function(e) {
|
EJS_onLoadState = function (e) {
|
||||||
showDialog('emulatorloadstate', { "romId": romId, "IsMediaGroup": IsMediaGroup });
|
showDialog('emulatorloadstate', { "romId": romId, "IsMediaGroup": IsMediaGroup });
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
8
gaseous-server/wwwroot/images/NoIntro-logo.svg
Normal file
8
gaseous-server/wwwroot/images/NoIntro-logo.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 480 KiB |
BIN
gaseous-server/wwwroot/images/redump.png
Normal file
BIN
gaseous-server/wwwroot/images/redump.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 92 KiB |
@@ -1,5 +1,6 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<script src="/api/v1.1/System/VersionFile"></script>
|
<script src="/api/v1.1/System/VersionFile"></script>
|
||||||
@@ -44,48 +45,56 @@
|
|||||||
var userProfile;
|
var userProfile;
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<!-- Notifications -->
|
<!-- Notifications -->
|
||||||
<div id="notifications_target"></div>
|
<div id="notifications_target"></div>
|
||||||
|
|
||||||
<div id="banner_icon" onclick="window.location.href = '/index.html';">
|
<div id="banner_icon" onclick="window.location.href = '/index.html';">
|
||||||
<img src="/images/logo.png" alt="Gaseous" id="banner_icon_image" />
|
<img src="/images/logo.png" alt="Gaseous" id="banner_icon_image" />
|
||||||
</div>
|
</div>
|
||||||
<div id="banner_header">
|
<div id="banner_header">
|
||||||
<div id="bannerButtons">
|
<div id="bannerButtons">
|
||||||
<div id="banner_user" onclick="showMenu();" class="banner_button dropdown dropbtn">
|
<div id="banner_user" onclick="showMenu();" class="banner_button dropdown dropbtn">
|
||||||
<img src="/images/user.svg" alt="Account" title="Account" id="banner_user_image" class="banner_button_image" style="position: relative; top: 10px; right: 0px; pointer-events: none;" onclick="showMenu();" />
|
<img src="/images/user.svg" alt="Account" title="Account" id="banner_user_image"
|
||||||
|
class="banner_button_image" style="position: relative; top: 10px; right: 0px; pointer-events: none;"
|
||||||
|
onclick="showMenu();" />
|
||||||
<div id="myDropdown" class="dropdown-content">
|
<div id="myDropdown" class="dropdown-content">
|
||||||
<div id="banner_user_roles"></div>
|
<div id="banner_user_roles"></div>
|
||||||
<a href="#" onclick="showDialog('userprofile');">Profile</a>
|
<a href="#" onclick="showDialog('userprofile');">Profile</a>
|
||||||
<a href="#" onclick="userLogoff();">Sign Out</a>
|
<a href="#" onclick="userLogoff();">Sign Out</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="banner_cog" onclick="window.location.href = '/index.html?page=settings';" class="banner_button">
|
<div id="banner_cog" onclick="window.location.href = '/index.html?page=settings';" class="banner_button">
|
||||||
<img src="/images/settings.svg" alt="Settings" title="Settings" id="banner_system_image" class="banner_button_image" />
|
<img src="/images/settings.svg" alt="Settings" title="Settings" id="banner_system_image"
|
||||||
|
class="banner_button_image" />
|
||||||
<span id="banner_system_label">Settings</span>
|
<span id="banner_system_label">Settings</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="banner_upload" onclick="showDialog('upload');" class="banner_button">
|
<div id="banner_upload" onclick="showDialog('upload');" class="banner_button">
|
||||||
<img src="/images/upload.svg" alt="Upload" title="Upload" id="banner_upload_image" class="banner_button_image" />
|
<img src="/images/upload.svg" alt="Upload" title="Upload" id="banner_upload_image"
|
||||||
|
class="banner_button_image" />
|
||||||
<span id="banner_upload_label">Upload</span>
|
<span id="banner_upload_label">Upload</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="banner_collections" onclick="window.location.href = '/index.html?page=collections';" class="banner_button">
|
<div id="banner_collections" onclick="window.location.href = '/index.html?page=collections';"
|
||||||
<img src="/images/collections.svg" alt="Collections" title="Collections" id="banner_collections_image" class="banner_button_image" />
|
class="banner_button">
|
||||||
|
<img src="/images/collections.svg" alt="Collections" title="Collections" id="banner_collections_image"
|
||||||
|
class="banner_button_image" />
|
||||||
<span id="banner_collections_label">Collections</span>
|
<span id="banner_collections_label">Collections</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="banner_library" onclick="window.location.href = '/index.html';" class="banner_button">
|
<div id="banner_library" onclick="window.location.href = '/index.html';" class="banner_button">
|
||||||
<img src="/images/library.svg" alt="Library" title="Library" id="banner_library_image" class="banner_button_image" />
|
<img src="/images/library.svg" alt="Library" title="Library" id="banner_library_image"
|
||||||
|
class="banner_button_image" />
|
||||||
<span id="banner_library_label">Library</span>
|
<span id="banner_library_label">Library</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="banner_header_label" onclick="window.location.href = '/index.html';">Gaseous Games</div>
|
<div id="banner_header_label" onclick="window.location.href = '/index.html';">Gaseous Games</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div id="content">
|
<div id="content">
|
||||||
|
|
||||||
@@ -97,7 +106,9 @@
|
|||||||
<!-- Modal content -->
|
<!-- Modal content -->
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<span class="close">×</span>
|
<span class="close">×</span>
|
||||||
<div><h1 id="modal-heading">Modal heading</h1></div>
|
<div>
|
||||||
|
<h1 id="modal-heading">Modal heading</h1>
|
||||||
|
</div>
|
||||||
<div id="modal-content">Some text in the Modal..</div>
|
<div id="modal-content">Some text in the Modal..</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -118,7 +129,7 @@
|
|||||||
var modalVariables = null;
|
var modalVariables = null;
|
||||||
|
|
||||||
// redirect if first run status = 0
|
// redirect if first run status = 0
|
||||||
if (FirstRunStatus == 0) {
|
if (FirstRunStatus == 0 || FirstRunStatus == "0") {
|
||||||
window.location.replace("/pages/first.html");
|
window.location.replace("/pages/first.html");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +137,7 @@
|
|||||||
ajaxCall(
|
ajaxCall(
|
||||||
'/api/v1.1/Account/Profile/Basic',
|
'/api/v1.1/Account/Profile/Basic',
|
||||||
'GET',
|
'GET',
|
||||||
function(result) {
|
function (result) {
|
||||||
console.log("User is logged in");
|
console.log("User is logged in");
|
||||||
userProfile = result;
|
userProfile = result;
|
||||||
|
|
||||||
@@ -137,7 +148,7 @@
|
|||||||
if (!userProfile.roles.includes("Admin") && !userProfile.roles.includes("Gamer")) {
|
if (!userProfile.roles.includes("Admin") && !userProfile.roles.includes("Gamer")) {
|
||||||
uploadButton.style.display = 'none';
|
uploadButton.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
// populate page
|
// populate page
|
||||||
var myParam = getQueryString('page', 'string');
|
var myParam = getQueryString('page', 'string');
|
||||||
|
|
||||||
@@ -147,7 +158,7 @@
|
|||||||
|
|
||||||
$('#content').load('/pages/' + myParam + '.html?v=' + AppVersion);
|
$('#content').load('/pages/' + myParam + '.html?v=' + AppVersion);
|
||||||
},
|
},
|
||||||
function(error) {
|
function (error) {
|
||||||
window.location.replace("/pages/login.html");
|
window.location.replace("/pages/login.html");
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -159,15 +170,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Close the dropdown menu if the user clicks outside of it
|
// Close the dropdown menu if the user clicks outside of it
|
||||||
window.onclick = function(event) {
|
window.onclick = function (event) {
|
||||||
if (!event.target.matches('.dropbtn')) {
|
if (!event.target.matches('.dropbtn')) {
|
||||||
var dropdowns = document.getElementsByClassName("dropdown-content");
|
var dropdowns = document.getElementsByClassName("dropdown-content");
|
||||||
var i;
|
var i;
|
||||||
for (i = 0; i < dropdowns.length; i++) {
|
for (i = 0; i < dropdowns.length; i++) {
|
||||||
var openDropdown = dropdowns[i];
|
var openDropdown = dropdowns[i];
|
||||||
if (openDropdown.classList.contains('show')) {
|
if (openDropdown.classList.contains('show')) {
|
||||||
openDropdown.classList.remove('show');
|
openDropdown.classList.remove('show');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,4 +197,5 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
|
||||||
|
</html>
|
@@ -1,6 +1,9 @@
|
|||||||
<div id="saved_states">
|
<div id="saved_states">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>Upload state file: </span><input type="file" id="stateFile" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<script text="text/javascript">
|
<script text="text/javascript">
|
||||||
document.getElementById('modal-heading').innerHTML = "Load saved state";
|
document.getElementById('modal-heading').innerHTML = "Load saved state";
|
||||||
@@ -13,9 +16,10 @@
|
|||||||
ajaxCall(
|
ajaxCall(
|
||||||
statesUrl,
|
statesUrl,
|
||||||
'GET',
|
'GET',
|
||||||
function(result) {
|
function (result) {
|
||||||
var statesBox = document.getElementById('saved_states');
|
var statesBox = document.getElementById('saved_states');
|
||||||
statesBox.innerHTML = '';
|
statesBox.innerHTML = '';
|
||||||
|
document.getElementById('stateFile').value = '';
|
||||||
|
|
||||||
for (var i = 0; i < result.length; i++) {
|
for (var i = 0; i < result.length; i++) {
|
||||||
var stateBox = document.createElement('div');
|
var stateBox = document.createElement('div');
|
||||||
@@ -62,7 +66,7 @@
|
|||||||
stateControls.id = 'stateControls_' + result[i].id;
|
stateControls.id = 'stateControls_' + result[i].id;
|
||||||
stateControls.className = 'saved_state_controls';
|
stateControls.className = 'saved_state_controls';
|
||||||
|
|
||||||
var stateControlsLaunch= document.createElement('span');
|
var stateControlsLaunch = document.createElement('span');
|
||||||
stateControlsLaunch.id = 'stateControlsLaunch_' + result[i].id;
|
stateControlsLaunch.id = 'stateControlsLaunch_' + result[i].id;
|
||||||
stateControlsLaunch.className = 'romstart';
|
stateControlsLaunch.className = 'romstart';
|
||||||
var emulatorTarget = '/index.html?page=emulator&engine=@engine&core=@core&platformid=@platformid&gameid=@gameid&romid=@romid&mediagroup=@mediagroup&rompath=@rompath&stateid=' + result[i].id;
|
var emulatorTarget = '/index.html?page=emulator&engine=@engine&core=@core&platformid=@platformid&gameid=@gameid&romid=@romid&mediagroup=@mediagroup&rompath=@rompath&stateid=' + result[i].id;
|
||||||
@@ -128,7 +132,7 @@
|
|||||||
ajaxCall(
|
ajaxCall(
|
||||||
'/api/v1.1/StateManager/' + modalVariables.romId + '/' + StateId + '?IsMediaGroup=' + IsMediaGroup,
|
'/api/v1.1/StateManager/' + modalVariables.romId + '/' + StateId + '?IsMediaGroup=' + IsMediaGroup,
|
||||||
'DELETE',
|
'DELETE',
|
||||||
function(success) {
|
function (success) {
|
||||||
LoadStates();
|
LoadStates();
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
@@ -147,7 +151,7 @@
|
|||||||
ajaxCall(
|
ajaxCall(
|
||||||
'/api/v1.1/StateManager/' + modalVariables.romId + '/' + StateId + '?IsMediaGroup=' + IsMediaGroup,
|
'/api/v1.1/StateManager/' + modalVariables.romId + '/' + StateId + '?IsMediaGroup=' + IsMediaGroup,
|
||||||
'PUT',
|
'PUT',
|
||||||
function(success) {
|
function (success) {
|
||||||
LoadStates();
|
LoadStates();
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
@@ -156,4 +160,36 @@
|
|||||||
JSON.stringify(model)
|
JSON.stringify(model)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.getElementById('stateFile').addEventListener('change', function () {
|
||||||
|
let file = document.getElementById('stateFile').files[0];
|
||||||
|
let formData = new FormData();
|
||||||
|
formData.append('file', file);
|
||||||
|
|
||||||
|
console.log("Uploading state file");
|
||||||
|
|
||||||
|
fetch('/api/v1.1/StateManager/Upload?RomId=' + modalVariables.romId + '&IsMediaGroup=' + modalVariables.IsMediaGroup, {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
console.log('Success:', data);
|
||||||
|
UploadAlert(data);
|
||||||
|
LoadStates();
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error("Error:", error);
|
||||||
|
UploadAlert(error);
|
||||||
|
LoadStates();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function UploadAlert(data) {
|
||||||
|
if (data.Management == "Managed") {
|
||||||
|
alert("State uploaded successfully.");
|
||||||
|
} else {
|
||||||
|
alert("State uploaded successfully, but it might not function correctly for this platform and ROM.");
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
@@ -1,34 +1,30 @@
|
|||||||
<div style="padding-top: 5px;">
|
<table style="width: 98%; margin-top: 15px; margin-bottom: 15px;">
|
||||||
<strong>New Library</strong>
|
<tr>
|
||||||
</div>
|
<th style="width: 20%;">Name</th>
|
||||||
|
<td style="width: 80%;"><input type="text" id="newlibrary_name" style="width: 98%;" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Default Platform</th>
|
||||||
|
<td><select id="newlibrary_defaultplatform" style="width: 100%;"></select></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Path</th>
|
||||||
|
<td><input type="text" id="newlibrary_path" style="width: 98%;" /></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
<div style="width: 300px;">
|
<div style="width: 100%; text-align: right; margin-top: 160px;">
|
||||||
<table style="width: 98%; margin-top: 15px; margin-bottom: 15px;">
|
<div style="display: inline-block; margin-right: 20px;">
|
||||||
<tr>
|
<button value="OK" onclick="newLibrary();">OK</button>
|
||||||
<th>Name</th>
|
</div>
|
||||||
<td><input type="text" id="newlibrary_name" style="width: 95%;" /></td>
|
<div style="display: inline-block;">
|
||||||
</tr>
|
<button value="Cancel" onclick="closeDialog();">Cancel</button>
|
||||||
<tr>
|
|
||||||
<th>Default Platform</th>
|
|
||||||
<td><select id="newlibrary_defaultplatform" style="width: 100%;"></select></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Path</th>
|
|
||||||
<td><input type="text" id="newlibrary_path" style="width: 95%;" /></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<div style="width: 100%; text-align: right;">
|
|
||||||
<div style="display: inline-block; margin-right: 20px;">
|
|
||||||
<button value="OK" onclick="newLibrary();">OK</button>
|
|
||||||
</div>
|
|
||||||
<div style="display: inline-block;">
|
|
||||||
<button value="Cancel" onclick="closeSubDialog();">Cancel</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
document.getElementById('modal-heading').innerHTML = "New Library";
|
||||||
|
|
||||||
$('#newlibrary_defaultplatform').select2({
|
$('#newlibrary_defaultplatform').select2({
|
||||||
minimumInputLength: 3,
|
minimumInputLength: 3,
|
||||||
ajax: {
|
ajax: {
|
||||||
|
@@ -78,7 +78,7 @@
|
|||||||
<td style="width: 75%;"><select id="properties_fixgame" style="width: 100%;"></select></td>
|
<td style="width: 75%;"><select id="properties_fixgame" style="width: 100%;"></select></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2" style="text-align: right;"><button id="properties_fixsave" value="Save Match" onclick="SaveFixedGame();">Save Match</button></td>
|
<td colspan="2" style="text-align: right;"><button id="properties_fixclear" value="Clear Match" onclick="ClearFixedGame();">Clear Match</button><button id="properties_fixsave" value="Save Match" onclick="SaveFixedGame();">Save Match</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
@@ -252,6 +252,7 @@
|
|||||||
var fixplatform = $('#properties_fixplatform').select2('data');
|
var fixplatform = $('#properties_fixplatform').select2('data');
|
||||||
var fixgame = $('#properties_fixgame').select2('data');
|
var fixgame = $('#properties_fixgame').select2('data');
|
||||||
|
|
||||||
|
document.getElementById('properties_fixclear').setAttribute("disabled", "disabled");
|
||||||
document.getElementById('properties_fixsave').setAttribute("disabled", "disabled");
|
document.getElementById('properties_fixsave').setAttribute("disabled", "disabled");
|
||||||
|
|
||||||
ajaxCall('/api/v1.1/Games/' + gameId + '/roms/' + modalVariables + '?NewPlatformId=' + fixplatform[0].id + '&NewGameId=' + fixgame[0].id, 'PATCH', function (result) {
|
ajaxCall('/api/v1.1/Games/' + gameId + '/roms/' + modalVariables + '?NewPlatformId=' + fixplatform[0].id + '&NewGameId=' + fixgame[0].id, 'PATCH', function (result) {
|
||||||
@@ -259,6 +260,18 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ClearFixedGame() {
|
||||||
|
var fixplatform = 0;
|
||||||
|
var fixgame = 0;
|
||||||
|
|
||||||
|
document.getElementById('properties_fixclear').setAttribute("disabled", "disabled");
|
||||||
|
document.getElementById('properties_fixsave').setAttribute("disabled", "disabled");
|
||||||
|
|
||||||
|
ajaxCall('/api/v1.1/Games/' + gameId + '/roms/' + modalVariables + '?NewPlatformId=' + fixplatform + '&NewGameId=' + fixgame, 'PATCH', function (result) {
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function BuildAttributesTable(attributes, sourceName) {
|
function BuildAttributesTable(attributes, sourceName) {
|
||||||
var aTable = document.createElement('table');
|
var aTable = document.createElement('table');
|
||||||
aTable.style.width = '100%';
|
aTable.style.width = '100%';
|
||||||
|
@@ -72,6 +72,11 @@
|
|||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>Note</strong>: The page will need to be reloaded for changes to take effect.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: right;">
|
<td style="text-align: right;">
|
||||||
<button id="profile_pref_ok" value="OK" onclick="SavePrefs();">OK</button>
|
<button id="profile_pref_ok" value="OK" onclick="SavePrefs();">OK</button>
|
||||||
@@ -220,7 +225,8 @@
|
|||||||
SetPreference_Batch(model);
|
SetPreference_Batch(model);
|
||||||
|
|
||||||
if (getQueryString('page', 'string') == 'home' || getQueryString('page', 'string') == undefined) {
|
if (getQueryString('page', 'string') == 'home' || getQueryString('page', 'string') == undefined) {
|
||||||
executeFilter1_1(1);
|
setCookie('games_library_last_page', 1);
|
||||||
|
//location.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
closeDialog();
|
closeDialog();
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
if (IsMediaGroupInt == 1) { IsMediaGroup = true; }
|
if (IsMediaGroupInt == 1) { IsMediaGroup = true; }
|
||||||
var StateUrl = undefined;
|
var StateUrl = undefined;
|
||||||
if (getQueryString('stateid', 'int')) {
|
if (getQueryString('stateid', 'int')) {
|
||||||
StateUrl = '/api/v1.1/StateManager/' + romId + '/' + getQueryString('stateid', 'int') + '/State/savestate.state?IsMediaGroup=' + IsMediaGroup;
|
StateUrl = '/api/v1.1/StateManager/' + romId + '/' + getQueryString('stateid', 'int') + '/State/savestate.state?StateOnly=true&IsMediaGroup=' + IsMediaGroup;
|
||||||
}
|
}
|
||||||
var gameData;
|
var gameData;
|
||||||
var artworks = null;
|
var artworks = null;
|
||||||
@@ -23,6 +23,8 @@
|
|||||||
var emuBios = '';
|
var emuBios = '';
|
||||||
var emuBackground = '';
|
var emuBackground = '';
|
||||||
|
|
||||||
|
console.log("Loading rom url: " + decodeURIComponent(getQueryString('rompath', 'string')));
|
||||||
|
|
||||||
ajaxCall('/api/v1.1/Games/' + gameId, 'GET', function (result) {
|
ajaxCall('/api/v1.1/Games/' + gameId, 'GET', function (result) {
|
||||||
gameData = result;
|
gameData = result;
|
||||||
|
|
||||||
@@ -51,10 +53,14 @@
|
|||||||
emuBios = '';
|
emuBios = '';
|
||||||
} else {
|
} else {
|
||||||
emuBios = '/api/v1.1/Bios/zip/' + platformId;
|
emuBios = '/api/v1.1/Bios/zip/' + platformId;
|
||||||
|
console.log("Using BIOS link: " + emuBios);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (getQueryString('engine', 'string')) {
|
switch (getQueryString('engine', 'string')) {
|
||||||
case 'EmulatorJS':
|
case 'EmulatorJS':
|
||||||
|
console.log("Emulator: " + getQueryString('engine', 'string'));
|
||||||
|
console.log("Core: " + getQueryString('core', 'string'));
|
||||||
|
|
||||||
$('#emulator').load('/emulators/EmulatorJS.html?v=' + AppVersion);
|
$('#emulator').load('/emulators/EmulatorJS.html?v=' + AppVersion);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -89,11 +95,11 @@
|
|||||||
'/api/v1.1/Statistics/Games/' + gameId + '/' + SessionId,
|
'/api/v1.1/Statistics/Games/' + gameId + '/' + SessionId,
|
||||||
'PUT',
|
'PUT',
|
||||||
function (success) {
|
function (success) {
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(SaveStatistics, 60000);
|
setInterval(SaveStatistics, 60000);
|
||||||
</script>
|
</script>
|
@@ -1,5 +1,6 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<script src="/api/v1.1/System/VersionFile"></script>
|
<script src="/api/v1.1/System/VersionFile"></script>
|
||||||
@@ -40,8 +41,10 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="bgImage" style="background-image: url('/images/LoginWallpaper.jpg'); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);">
|
<div id="bgImage"
|
||||||
|
style="background-image: url('/images/LoginWallpaper.jpg'); background-position: center; background-repeat: no-repeat; background-size: cover; filter: blur(10px); -webkit-filter: blur(10px);">
|
||||||
<div id="bgImage_Opacity"></div>
|
<div id="bgImage_Opacity"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -52,7 +55,9 @@
|
|||||||
|
|
||||||
<div id="loginwindow_header_label" style="display: block; text-align: center;">Gaseous Games</div>
|
<div id="loginwindow_header_label" style="display: block; text-align: center;">Gaseous Games</div>
|
||||||
|
|
||||||
<button type="button" value="Get Started" onclick="document.getElementById('first_welcome').style.display = 'none'; document.getElementById('first_newadmin').style.display = '';" class="bigbutton">Get Started</button>
|
<button type="button" value="Get Started"
|
||||||
|
onclick="document.getElementById('first_welcome').style.display = 'none'; document.getElementById('first_newadmin').style.display = '';"
|
||||||
|
class="bigbutton">Get Started</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="loginwindow" id="first_newadmin" style="display: none;">
|
<div class="loginwindow" id="first_newadmin" style="display: none;">
|
||||||
@@ -67,15 +72,18 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Email</th>
|
<th>Email</th>
|
||||||
<td><input type="email" id="login_email" style="width: 95%;" onkeyup="checkPasswordsMatch();" /></td>
|
<td><input type="email" id="login_email" style="width: 95%;" onkeyup="checkPasswordsMatch();" />
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>New Password</th>
|
<th>New Password</th>
|
||||||
<td><input type="password" id="login_password" style="width: 95%;" onkeyup="checkPasswordsMatch();" /></td>
|
<td><input type="password" id="login_password" style="width: 95%;"
|
||||||
|
onkeyup="checkPasswordsMatch();" /></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Confirm Password</th>
|
<th>Confirm Password</th>
|
||||||
<td><input type="password" id="login_confirmpassword" style="width: 95%;" onkeyup="checkPasswordsMatch();" /></td>
|
<td><input type="password" id="login_confirmpassword" style="width: 95%;"
|
||||||
|
onkeyup="checkPasswordsMatch();" /></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2" id="login_passwordnotice"> </td>
|
<td colspan="2" id="login_passwordnotice"> </td>
|
||||||
@@ -85,7 +93,9 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2" style="padding-top: 20px;">
|
<td colspan="2" style="padding-top: 20px;">
|
||||||
<button id="login_createaccount" type="button" value="Create Account" onclick="registerAccount();" disabled="disabled" class="bigbutton">Create Account</button>
|
<button id="login_createaccount" type="button" value="Create Account"
|
||||||
|
onclick="registerAccount();" disabled="disabled" class="bigbutton">Create
|
||||||
|
Account</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@@ -94,12 +104,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="settings_photocredit">
|
<div id="settings_photocredit">
|
||||||
Wallpaper by <a href="https://unsplash.com/@spideyjoey" class="romlink">Joey Kwok</a> / <a href="https://unsplash.com/photos/a-room-filled-with-arcade-machines-and-neon-lights-jbIsTd7rdd8" class="romlink">Unsplash</a>
|
Wallpaper by <a href="https://unsplash.com/@spideyjoey" class="romlink">Joey Kwok</a> / <a
|
||||||
|
href="https://unsplash.com/photos/a-room-filled-with-arcade-machines-and-neon-lights-jbIsTd7rdd8"
|
||||||
|
class="romlink">Unsplash</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
// redirect if first run status != 0 as 0 indicates that first run needs to be run
|
// redirect if first run status != 0 as 0 indicates that first run needs to be run
|
||||||
if (FirstRunStatus != 0) {
|
if (FirstRunStatus != 0 && FirstRunStatus != "0") {
|
||||||
window.location.replace("/");
|
window.location.replace("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,10 +158,10 @@
|
|||||||
ajaxCall(
|
ajaxCall(
|
||||||
'/api/v1.1/FirstSetup/0',
|
'/api/v1.1/FirstSetup/0',
|
||||||
'POST',
|
'POST',
|
||||||
function(result){
|
function (result) {
|
||||||
loginCallback(result);
|
loginCallback(result);
|
||||||
},
|
},
|
||||||
function(error){
|
function (error) {
|
||||||
loginCallback(error);
|
loginCallback(error);
|
||||||
},
|
},
|
||||||
JSON.stringify(model)
|
JSON.stringify(model)
|
||||||
|
@@ -545,7 +545,7 @@
|
|||||||
var saveStatesButton = '';
|
var saveStatesButton = '';
|
||||||
if (mediaGroup.emulator) {
|
if (mediaGroup.emulator) {
|
||||||
if (mediaGroup.emulator.type.length > 0) {
|
if (mediaGroup.emulator.type.length > 0) {
|
||||||
var romPath = encodeURIComponent('/api/v1.1/Games/' + gameId + '/romgroup/' + mediaGroup.id + '/' + gameData.name + '(' + mediaGroup.id + ')' + '.zip');
|
var romPath = encodeURIComponent('/api/v1.1/Games/' + gameId + '/romgroup/' + mediaGroup.id + '/' + gameData.name + '.zip');
|
||||||
|
|
||||||
if (mediaGroup.hasSaveStates == true) {
|
if (mediaGroup.hasSaveStates == true) {
|
||||||
var modalVariables = {
|
var modalVariables = {
|
||||||
|
@@ -5,15 +5,17 @@
|
|||||||
<table style="width: 100%;">
|
<table style="width: 100%;">
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width: 20%;">Home Page</th>
|
<th style="width: 20%;">Home Page</th>
|
||||||
<td><a href="https://github.com/gaseous-project/gaseous-server" class="romlink">https://github.com/gaseous-project/gaseous-server</a></td>
|
<td><a href="https://github.com/gaseous-project/gaseous-server"
|
||||||
|
class="romlink">https://github.com/gaseous-project/gaseous-server</a></td>
|
||||||
<td rowspan="5" style="text-align: center; width: 128px;">
|
<td rowspan="5" style="text-align: center; width: 128px;">
|
||||||
<img src="/images/logo.png" style="display: block; margin: 20px auto; width: 100px;" />
|
<img src="/images/logo.png" style="display: block; margin: 20px auto; width: 100px;" />
|
||||||
<span style="display: block;">The Gaseous logo was designed by Tom2.0</span>
|
<span style="display: block;">The Gaseous logo was designed by Tom1243</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Bugs and Feature Requests</th>
|
<th>Bugs and Feature Requests</th>
|
||||||
<td><a href="https://github.com/gaseous-project/gaseous-server/issues" class="romlink">https://github.com/gaseous-project/gaseous-server/issues</a></td>
|
<td><a href="https://github.com/gaseous-project/gaseous-server/issues"
|
||||||
|
class="romlink">https://github.com/gaseous-project/gaseous-server/issues</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Join our Discord</th>
|
<th>Join our Discord</th>
|
||||||
@@ -33,21 +35,24 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: center;"><a href="https://github.com/EmulatorJS/EmulatorJS" target="_blank"><img src="/images/EmulatorJS.png" style="height: 36px;" /></a></td>
|
<td style="text-align: center;"><a href="https://github.com/EmulatorJS/EmulatorJS" target="_blank"><img
|
||||||
|
src="/images/EmulatorJS.png" style="height: 36px;" /></a></td>
|
||||||
<td colspan="3">
|
<td colspan="3">
|
||||||
The EmulatorJS Project<br />
|
The EmulatorJS Project<br />
|
||||||
<a href="https://github.com/EmulatorJS/EmulatorJS" target="_blank" class="romlink">https://github.com/EmulatorJS/EmulatorJS</a>
|
<a href="https://github.com/EmulatorJS/EmulatorJS" target="_blank"
|
||||||
|
class="romlink">https://github.com/EmulatorJS/EmulatorJS</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3">
|
<td colspan="3">
|
||||||
<h3>Data Sources</h2>
|
<h3>Data Sources</h2>
|
||||||
<h4>Game data</h4>
|
<h4>Game data</h4>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: center;">
|
<td style="text-align: center;">
|
||||||
<a href="https://www.igdb.com/" target="_blank"><img src="/images/IGDB_logo.svg" style="filter: invert(100%); height: 36px;" /></a>
|
<a href="https://www.igdb.com/" target="_blank"><img src="/images/IGDB_logo.svg"
|
||||||
|
style="filter: invert(100%); height: 36px;" /></a>
|
||||||
</td>
|
</td>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
The Internet Game Database<br />
|
The Internet Game Database<br />
|
||||||
@@ -61,7 +66,8 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: center;">
|
<td style="text-align: center;">
|
||||||
<a href="https://www.tosecdev.org/" target="_blank"><img src="/images/TOSEC_logo.gif" style="height: 36px;" /></a>
|
<a href="https://www.tosecdev.org/" target="_blank"><img src="/images/TOSEC_logo.gif"
|
||||||
|
style="height: 36px;" /></a>
|
||||||
</td>
|
</td>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
The Old School Emulation Center<br />
|
The Old School Emulation Center<br />
|
||||||
@@ -70,11 +76,34 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: center;">
|
<td style="text-align: center;">
|
||||||
<a href="https://www.progettosnaps.net/index.php" target="_blank"><img src="/images/ProgettoSnaps.gif" style="height: 36px;" /></a>
|
<a href="https://www.progettosnaps.net/index.php" target="_blank"><img src="/images/ProgettoSnaps.gif"
|
||||||
|
style="height: 36px;" /></a>
|
||||||
</td>
|
</td>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
Progetto-Snaps<br />
|
Progetto-Snaps<br />
|
||||||
<a href="https://www.progettosnaps.net/index.php" target="_blank" class="romlink">https://www.progettosnaps.net/index.php</a>
|
<a href="https://www.progettosnaps.net/index.php" target="_blank"
|
||||||
|
class="romlink">https://www.progettosnaps.net/index.php</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;">
|
||||||
|
<a href="https://no-intro.org" target="_blank" rel="noopener noreferrer"><img src="/images/NoIntro-logo.svg"
|
||||||
|
style="height: 36px;"></a>
|
||||||
|
</td>
|
||||||
|
<td colspan="2">
|
||||||
|
No-Intro<br>
|
||||||
|
<a href="https://no-intro.org" target="_blank" rel="noopener noreferrer"
|
||||||
|
class="romlink">https://no-intro.org</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;">
|
||||||
|
<a href="http://redump.org" target="_blank" rel="noopener noreferrer"><img src="/images/redump.png"
|
||||||
|
style="height: 36px;"></a>
|
||||||
|
</td>
|
||||||
|
<td colspan="2">
|
||||||
|
Redump<br>
|
||||||
|
<a href="http://redump.org" target="_blank" rel="noopener noreferrer" class="romlink">http://redump.org</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
@@ -6,15 +6,17 @@
|
|||||||
<table id="settings_libraries" class="romtable" style="width: 100%;" cellspacing="0">
|
<table id="settings_libraries" class="romtable" style="width: 100%;" cellspacing="0">
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
<div style="text-align: right;"><button id="settings_newlibrary" onclick="showSubDialog('librarynew');">New Library</button></div>
|
<div style="text-align: right;"><button id="settings_newlibrary" onclick="showDialog('librarynew');">New
|
||||||
|
Library</button></div>
|
||||||
|
|
||||||
<h2>Advanced Settings</h2>
|
<h2>Advanced Settings</h2>
|
||||||
<p><strong>Warning</strong> Do not modify the below settings unless you know what you're doing.</p>
|
<p><strong>Warning</strong> Do not modify the below settings unless you know what you're doing.</p>
|
||||||
<h3>Background Task Timers</h3>
|
<h3>Background Task Timers</h3>
|
||||||
<table id="settings_tasktimers" class="romtable" style="width: 100%;" cellspacing="0">
|
<table id="settings_tasktimers" class="romtable" style="width: 100%;" cellspacing="0">
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
<div style="text-align: right;"><button id="settings_tasktimers_default" onclick="defaultTaskTimers();">Reset to Default</button><button id="settings_tasktimers_new" onclick="saveTaskTimers();">Save</button></div>
|
<div style="text-align: right;"><button id="settings_tasktimers_default" onclick="defaultTaskTimers();">Reset to
|
||||||
|
Default</button><button id="settings_tasktimers_new" onclick="saveTaskTimers();">Save</button></div>
|
||||||
|
|
||||||
<h3>System Settings</h3>
|
<h3>System Settings</h3>
|
||||||
<table cellspacing="0" style="width: 100%;">
|
<table cellspacing="0" style="width: 100%;">
|
||||||
@@ -26,13 +28,15 @@
|
|||||||
Write logs
|
Write logs
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<input type="radio" name="settings_logs_write" id="settings_logs_write_db" value="false" checked="checked"><label for="settings_logs_write_db"> To database only (default)</label>
|
<input type="radio" name="settings_logs_write" id="settings_logs_write_db" value="false"
|
||||||
|
checked="checked"><label for="settings_logs_write_db"> To database only (default)</label>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td>
|
<td>
|
||||||
<input type="radio" name="settings_logs_write" id="settings_logs_write_fs" value="true"><label for="settings_logs_write_fs"> To database and disk</label>
|
<input type="radio" name="settings_logs_write" id="settings_logs_write_fs" value="true"><label
|
||||||
|
for="settings_logs_write_fs"> To database and disk</label>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -46,6 +50,58 @@
|
|||||||
<input type="number" min="1" id="settings_logs_retention" />
|
<input type="number" min="1" id="settings_logs_retention" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
Allowed metadata search modes:
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" name="settings_metadata_search" id="settings_metadata_search_where" /><label
|
||||||
|
for="settings_metadata_search_where">
|
||||||
|
Exact:
|
||||||
|
<i>
|
||||||
|
Searches for exact matches only. Example search: name = "Super Mario Bros."
|
||||||
|
</i>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" name="settings_metadata_search" id="settings_metadata_search_wherefuzzy" /><label
|
||||||
|
for="settings_metadata_search_wherefuzzy">
|
||||||
|
Partial:
|
||||||
|
<i>
|
||||||
|
Searches for partial matches. Example search: name = "Mario"
|
||||||
|
</i>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" name="settings_metadata_search" id="settings_metadata_search_search" /><label
|
||||||
|
for="settings_metadata_search_search">
|
||||||
|
Search:
|
||||||
|
<i>
|
||||||
|
Searches for partial matches using full text search. Example search: name = "Mario"
|
||||||
|
</i>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" name="settings_metadata_search"
|
||||||
|
id="settings_metadata_search_searchNoPlatform" /><label for="settings_metadata_search_searchNoPlatform">
|
||||||
|
Search (no platform
|
||||||
|
contraint):
|
||||||
|
<i>
|
||||||
|
Searches for partial matches using full text search, but without a platform constraint. Example
|
||||||
|
search: name = "Mario"
|
||||||
|
</i>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="2">Emulator</th>
|
<th colspan="2">Emulator</th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -95,9 +151,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
newTable.appendChild(createTableRow(
|
newTable.appendChild(createTableRow(
|
||||||
false,
|
false,
|
||||||
[
|
[
|
||||||
result[i].name,
|
result[i].name,
|
||||||
result[i].path,
|
result[i].path,
|
||||||
platformName,
|
platformName,
|
||||||
defaultLibrary,
|
defaultLibrary,
|
||||||
@@ -115,14 +171,14 @@
|
|||||||
ajaxCall(
|
ajaxCall(
|
||||||
'/api/v1/System/Settings/BackgroundTasks/Configuration',
|
'/api/v1/System/Settings/BackgroundTasks/Configuration',
|
||||||
'GET',
|
'GET',
|
||||||
function(result) {
|
function (result) {
|
||||||
var targetTable = document.getElementById('settings_tasktimers');
|
var targetTable = document.getElementById('settings_tasktimers');
|
||||||
targetTable.innerHTML = '';
|
targetTable.innerHTML = '';
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(result)) {
|
for (const [key, value] of Object.entries(result)) {
|
||||||
var newTableRowBody = document.createElement('tbody');
|
var newTableRowBody = document.createElement('tbody');
|
||||||
newTableRowBody.className = 'romrow';
|
newTableRowBody.className = 'romrow';
|
||||||
|
|
||||||
var enabledString = "";
|
var enabledString = "";
|
||||||
if (value.enabled == true) {
|
if (value.enabled == true) {
|
||||||
enabledString = 'checked="checked"';
|
enabledString = 'checked="checked"';
|
||||||
@@ -171,7 +227,7 @@
|
|||||||
daySelector.multiple = 'multiple';
|
daySelector.multiple = 'multiple';
|
||||||
daySelector.setAttribute('data-default', value.defaultAllowedDays.join(","));
|
daySelector.setAttribute('data-default', value.defaultAllowedDays.join(","));
|
||||||
daySelector.style.width = '95%';
|
daySelector.style.width = '95%';
|
||||||
var days = [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ];
|
var days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
|
||||||
for (var d = 0; d < days.length; d++) {
|
for (var d = 0; d < days.length; d++) {
|
||||||
var dayOpt = document.createElement('option');
|
var dayOpt = document.createElement('option');
|
||||||
dayOpt.value = days[d];
|
dayOpt.value = days[d];
|
||||||
@@ -312,7 +368,7 @@
|
|||||||
var taskName = timerValues[i].getAttribute('data-name');
|
var taskName = timerValues[i].getAttribute('data-name');
|
||||||
var taskEnabled = document.getElementById('settings_enabled_' + taskName).checked;
|
var taskEnabled = document.getElementById('settings_enabled_' + taskName).checked;
|
||||||
var taskIntervalObj = document.getElementById('settings_tasktimers_' + taskName);
|
var taskIntervalObj = document.getElementById('settings_tasktimers_' + taskName);
|
||||||
var taskInterval = function() { if (taskIntervalObj.value) { return taskIntervalObj.value; } else { return taskIntervalObj.getAttribute('placeholder'); } };
|
var taskInterval = function () { if (taskIntervalObj.value) { return taskIntervalObj.value; } else { return taskIntervalObj.getAttribute('placeholder'); } };
|
||||||
var taskDaysRaw = $('#settings_alloweddays_' + taskName).select2('data');
|
var taskDaysRaw = $('#settings_alloweddays_' + taskName).select2('data');
|
||||||
var taskDays = [];
|
var taskDays = [];
|
||||||
if (taskDaysRaw.length > 0) {
|
if (taskDaysRaw.length > 0) {
|
||||||
@@ -327,10 +383,10 @@
|
|||||||
var taskEndHourObj = document.getElementById('settings_tasktimers_' + taskName + '_End_Hour');
|
var taskEndHourObj = document.getElementById('settings_tasktimers_' + taskName + '_End_Hour');
|
||||||
var taskEndMinuteObj = document.getElementById('settings_tasktimers_' + taskName + '_End_Minute');
|
var taskEndMinuteObj = document.getElementById('settings_tasktimers_' + taskName + '_End_Minute');
|
||||||
|
|
||||||
var taskStartHour = function() { if (taskStartHourObj.value) { return taskStartHourObj.value; } else { return taskStartHourObj.getAttribute('placeholder'); } };
|
var taskStartHour = function () { if (taskStartHourObj.value) { return taskStartHourObj.value; } else { return taskStartHourObj.getAttribute('placeholder'); } };
|
||||||
var taskStartMinute = function() { if (taskStartMinuteObj.value) { return taskStartMinuteObj.value; } else { return taskStartMinuteObj.getAttribute('placeholder'); } };
|
var taskStartMinute = function () { if (taskStartMinuteObj.value) { return taskStartMinuteObj.value; } else { return taskStartMinuteObj.getAttribute('placeholder'); } };
|
||||||
var taskEndHour = function() { if (taskEndHourObj.value) { return taskEndHourObj.value; } else { return taskEndHourObj.getAttribute('placeholder'); } };
|
var taskEndHour = function () { if (taskEndHourObj.value) { return taskEndHourObj.value; } else { return taskEndHourObj.getAttribute('placeholder'); } };
|
||||||
var taskEndMinute = function() { if (taskEndMinuteObj.value) { return taskEndMinuteObj.value; } else { return taskEndMinuteObj.getAttribute('placeholder'); } };
|
var taskEndMinute = function () { if (taskEndMinuteObj.value) { return taskEndMinuteObj.value; } else { return taskEndMinuteObj.getAttribute('placeholder'); } };
|
||||||
|
|
||||||
model.push(
|
model.push(
|
||||||
{
|
{
|
||||||
@@ -349,10 +405,10 @@
|
|||||||
ajaxCall(
|
ajaxCall(
|
||||||
'/api/v1/System/Settings/BackgroundTasks/Configuration',
|
'/api/v1/System/Settings/BackgroundTasks/Configuration',
|
||||||
'POST',
|
'POST',
|
||||||
function(result) {
|
function (result) {
|
||||||
getBackgroundTaskTimers();
|
getBackgroundTaskTimers();
|
||||||
},
|
},
|
||||||
function(error) {
|
function (error) {
|
||||||
getBackgroundTaskTimers();
|
getBackgroundTaskTimers();
|
||||||
},
|
},
|
||||||
JSON.stringify(model)
|
JSON.stringify(model)
|
||||||
@@ -393,7 +449,7 @@
|
|||||||
ajaxCall(
|
ajaxCall(
|
||||||
'/api/v1/System/Settings/System',
|
'/api/v1/System/Settings/System',
|
||||||
'GET',
|
'GET',
|
||||||
function(result) {
|
function (result) {
|
||||||
var optionToSelect = 'settings_logs_write_db';
|
var optionToSelect = 'settings_logs_write_db';
|
||||||
if (result.alwaysLogToDisk == true) {
|
if (result.alwaysLogToDisk == true) {
|
||||||
optionToSelect = 'settings_logs_write_fs';
|
optionToSelect = 'settings_logs_write_fs';
|
||||||
@@ -403,6 +459,11 @@
|
|||||||
document.getElementById('settings_logs_retention').value = result.minimumLogRetentionPeriod;
|
document.getElementById('settings_logs_retention').value = result.minimumLogRetentionPeriod;
|
||||||
|
|
||||||
document.getElementById('settings_emulator_debug').checked = result.emulatorDebugMode;
|
document.getElementById('settings_emulator_debug').checked = result.emulatorDebugMode;
|
||||||
|
|
||||||
|
for (let i = 0; i < result.searchTypes.length; i++) {
|
||||||
|
const element = result.searchTypes[i];
|
||||||
|
document.getElementById('settings_metadata_search_' + element).checked = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -421,19 +482,29 @@
|
|||||||
retentionValue = 7;
|
retentionValue = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let searchTypes = [];
|
||||||
|
let searchTypeElements = document.getElementsByName('settings_metadata_search');
|
||||||
|
for (let i = 0; i < searchTypeElements.length; i++) {
|
||||||
|
const element = searchTypeElements[i];
|
||||||
|
if (element.checked) {
|
||||||
|
searchTypes.push(element.id.replace('settings_metadata_search_', ''));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var model = {
|
var model = {
|
||||||
"alwaysLogToDisk": alwaysLogToDisk,
|
"alwaysLogToDisk": alwaysLogToDisk,
|
||||||
"minimumLogRetentionPeriod": retentionValue,
|
"minimumLogRetentionPeriod": retentionValue,
|
||||||
"emulatorDebugMode": document.getElementById('settings_emulator_debug').checked
|
"emulatorDebugMode": document.getElementById('settings_emulator_debug').checked,
|
||||||
|
"searchTypes": searchTypes
|
||||||
};
|
};
|
||||||
|
|
||||||
ajaxCall(
|
ajaxCall(
|
||||||
'/api/v1/System/Settings/System',
|
'/api/v1/System/Settings/System',
|
||||||
'POST',
|
'POST',
|
||||||
function(result) {
|
function (result) {
|
||||||
getSystemSettings();
|
getSystemSettings();
|
||||||
},
|
},
|
||||||
function(error) {
|
function (error) {
|
||||||
getSystemSettings();
|
getSystemSettings();
|
||||||
},
|
},
|
||||||
JSON.stringify(model)
|
JSON.stringify(model)
|
||||||
|
@@ -27,7 +27,7 @@ function formatFilterPanel(containerElement, result) {
|
|||||||
// Cancel the default action, if needed
|
// Cancel the default action, if needed
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
// Trigger the button element with a click
|
// Trigger the button element with a click
|
||||||
executeFilter1_1();
|
applyFilters();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
containerPanelSearch.appendChild(containerPanelSearchField);
|
containerPanelSearch.appendChild(containerPanelSearchField);
|
||||||
@@ -99,7 +99,7 @@ function formatFilterPanel(containerElement, result) {
|
|||||||
// add filter button
|
// add filter button
|
||||||
var searchButton = document.createElement('div');
|
var searchButton = document.createElement('div');
|
||||||
searchButton.id = 'games_library_searchbutton';
|
searchButton.id = 'games_library_searchbutton';
|
||||||
searchButton.setAttribute('onclick', 'executeFilter1_1();');
|
searchButton.setAttribute('onclick', 'applyFilters();');
|
||||||
searchButton.innerHTML = 'Apply';
|
searchButton.innerHTML = 'Apply';
|
||||||
|
|
||||||
buttonsDiv.appendChild(searchButton);
|
buttonsDiv.appendChild(searchButton);
|
||||||
@@ -365,6 +365,12 @@ function filter_panel_range_value(name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applyFilters() {
|
||||||
|
document.getElementById('games_library').innerHTML = '';
|
||||||
|
|
||||||
|
executeFilter1_1();
|
||||||
|
}
|
||||||
|
|
||||||
function resetFilters() {
|
function resetFilters() {
|
||||||
// clear name
|
// clear name
|
||||||
document.getElementById('filter_panel_search').value = '';
|
document.getElementById('filter_panel_search').value = '';
|
||||||
@@ -381,6 +387,7 @@ function resetFilters() {
|
|||||||
filter_panel_range_enabled_check(rangeCheckboxes[i].getAttribute('data-name'));
|
filter_panel_range_enabled_check(rangeCheckboxes[i].getAttribute('data-name'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.getElementById('games_library').innerHTML = '';
|
||||||
executeFilter1_1();
|
executeFilter1_1();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,8 +400,18 @@ function executeFilter1_1(pageNumber, pageSize) {
|
|||||||
existingSearchModel = undefined;
|
existingSearchModel = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let pageMode = GetPreference('LibraryPagination', 'paged');
|
||||||
|
|
||||||
if (!pageSize) {
|
if (!pageSize) {
|
||||||
pageSize = 30;
|
switch (pageMode) {
|
||||||
|
case "infinite":
|
||||||
|
pageSize = 30;
|
||||||
|
break;
|
||||||
|
case "paged":
|
||||||
|
default:
|
||||||
|
pageSize = 30;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var model;
|
var model;
|
||||||
|
@@ -56,192 +56,251 @@ var ClassificationRatings = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var pageReloadInterval;
|
var pageReloadInterval;
|
||||||
|
var firstLoad = true;
|
||||||
|
|
||||||
function formatGamesPanel(targetElement, result, pageNumber, pageSize, forceScrollTop) {
|
function formatGamesPanel(targetElement, result, pageNumber, pageSize, forceScrollTop) {
|
||||||
console.log("Displaying page: " + pageNumber);
|
|
||||||
console.log("Page size: " + pageSize);
|
|
||||||
|
|
||||||
var pageMode = GetPreference('LibraryPagination', 'paged');
|
var pageMode = GetPreference('LibraryPagination', 'paged');
|
||||||
|
|
||||||
if (pageNumber == 1 || pageMode == 'paged') {
|
if (pageNumber == 1) {
|
||||||
targetElement.innerHTML = '';
|
localStorage.setItem("gaseous-library-scrollpos", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pageMode == 'paged') {
|
if (pageMode == 'paged') {
|
||||||
if (forceScrollTop == true) {
|
targetElement.innerHTML = '';
|
||||||
window.scrollTo(0, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var pagerCheck = document.getElementById('games_library_pagerstore');
|
switch (pageMode) {
|
||||||
if (pageNumber == 1) {
|
case 'paged':
|
||||||
pagerCheck.innerHTML = "0";
|
if (forceScrollTop == true) {
|
||||||
}
|
window.scrollTo(0, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'infinite':
|
||||||
|
var gamePlaceholders = document.getElementsByName('GamePlaceholder');
|
||||||
|
|
||||||
if (pageNumber > Number(pagerCheck.innerHTML) || pageMode == 'paged') {
|
let currentPage = 1;
|
||||||
pagerCheck.innerHTML = pageNumber;
|
let totalPages = Math.ceil(result.count / pageSize);
|
||||||
|
let startIndex = 0;
|
||||||
|
let endIndex = pageSize;
|
||||||
|
for (let p = currentPage; p < totalPages + 1; p++) {
|
||||||
|
//console.log("Page: " + p + " - StartIndex: " + startIndex + " - EndIndex: " + endIndex);
|
||||||
|
|
||||||
document.getElementById('games_library_recordcount').innerHTML = result.count + ' games';
|
let newPageAnchor = document.getElementById('pageAnchor' + p);
|
||||||
|
if (!newPageAnchor) {
|
||||||
var existingLoadPageButton = document.getElementById('games_library_loadmore');
|
newPageAnchor = document.createElement('span');
|
||||||
if (existingLoadPageButton) {
|
newPageAnchor.id = 'pageAnchor' + p;
|
||||||
existingLoadPageButton.parentNode.removeChild(existingLoadPageButton);
|
newPageAnchor.setAttribute('name', 'pageAnchor' + p);
|
||||||
}
|
newPageAnchor.className = 'pageAnchor';
|
||||||
|
newPageAnchor.setAttribute('data-page', p);
|
||||||
// setup preferences
|
newPageAnchor.setAttribute('data-loaded', "0");
|
||||||
var showTitle = GetPreference("LibraryShowGameTitle", true);
|
targetElement.appendChild(newPageAnchor);
|
||||||
var showRatings = GetPreference("LibraryShowGameRating", true);
|
|
||||||
var showClassification = GetPreference("LibraryShowGameClassification", true);
|
|
||||||
var classificationDisplayOrderString = GetPreference("LibraryGameClassificationDisplayOrder", JSON.stringify([ "ESRB" ]));
|
|
||||||
var classificationDisplayOrder = JSON.parse(classificationDisplayOrderString);
|
|
||||||
if (showTitle == "true") { showTitle = true; } else { showTitle = false; }
|
|
||||||
if (showRatings == "true") { showRatings = true; } else { showRatings = false; }
|
|
||||||
if (showClassification == "true") { showClassification = true; } else { showClassification = false; }
|
|
||||||
|
|
||||||
for (var i = 0; i < result.games.length; i++) {
|
|
||||||
var game = renderGameIcon(result.games[i], showTitle, showRatings, showClassification, classificationDisplayOrder, false);
|
|
||||||
targetElement.appendChild(game);
|
|
||||||
}
|
|
||||||
|
|
||||||
$('.lazy').Lazy({
|
|
||||||
scrollDirection: 'vertical',
|
|
||||||
effect: 'fadeIn',
|
|
||||||
visibleOnly: true
|
|
||||||
});
|
|
||||||
|
|
||||||
var pager = document.getElementById('games_pager');
|
|
||||||
pager.style.display = 'none';
|
|
||||||
|
|
||||||
var alphaPager = document.getElementById('games_library_alpha_pager');
|
|
||||||
alphaPager.innerHTML = '';
|
|
||||||
|
|
||||||
switch(pageMode) {
|
|
||||||
case 'infinite':
|
|
||||||
if (result.games.length == pageSize) {
|
|
||||||
var loadPageButton = document.createElement("div");
|
|
||||||
loadPageButton.id = 'games_library_loadmore';
|
|
||||||
loadPageButton.innerHTML = 'Load More';
|
|
||||||
loadPageButton.setAttribute('onclick', 'executeFilter1_1(' + (pageNumber + 1) + ', ' + pageSize + ');');
|
|
||||||
loadPageButton.setAttribute('data-pagenumber', Number(pageNumber + 1));
|
|
||||||
loadPageButton.setAttribute('data-pagesize', pageSize);
|
|
||||||
targetElement.appendChild(loadPageButton);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'paged':
|
|
||||||
for (const [key, value] of Object.entries(result.alphaList)) {
|
|
||||||
var letterPager = document.createElement('span');
|
|
||||||
letterPager.className = 'games_library_alpha_pager_letter';
|
|
||||||
letterPager.setAttribute('onclick', 'executeFilter1_1(' + value + ');');
|
|
||||||
letterPager.innerHTML = key;
|
|
||||||
alphaPager.appendChild(letterPager);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.count > pageSize) {
|
if (endIndex > result.count) {
|
||||||
// add some padding to the bottom of the games list
|
endIndex = result.count;
|
||||||
var loadPageButton = document.createElement("div");
|
}
|
||||||
loadPageButton.id = 'games_library_padding';
|
|
||||||
targetElement.appendChild(loadPageButton);
|
|
||||||
|
|
||||||
var pageCount = Math.ceil(result.count / pageSize);
|
for (let i = startIndex; i < endIndex; i++) {
|
||||||
|
var placeHolderpresent = false;
|
||||||
// add first page button
|
for (var x = 0; x < gamePlaceholders.length; x++) {
|
||||||
var firstPage = document.createElement('span');
|
if (gamePlaceholders[x].getAttribute('data-index') == i) {
|
||||||
firstPage.innerHTML = '|<';
|
placeHolderpresent = true;
|
||||||
if (pageNumber == 1) {
|
|
||||||
firstPage.className = 'games_pager_number_disabled';
|
|
||||||
} else {
|
|
||||||
firstPage.className = 'games_pager_number';
|
|
||||||
firstPage.setAttribute('onclick', 'executeFilter1_1(1);');
|
|
||||||
}
|
|
||||||
|
|
||||||
// add previous page button
|
|
||||||
var prevPage = document.createElement('span');
|
|
||||||
prevPage.innerHTML = '<';
|
|
||||||
if (pageNumber == 1) {
|
|
||||||
prevPage.className = 'games_pager_number_disabled';
|
|
||||||
} else {
|
|
||||||
prevPage.className = 'games_pager_number';
|
|
||||||
prevPage.setAttribute('onclick', 'executeFilter1_1(' + (pageNumber - 1) + ');');
|
|
||||||
}
|
|
||||||
|
|
||||||
// add page numbers
|
|
||||||
var pageEitherSide = 4;
|
|
||||||
var currentPage = Number(pagerCheck.innerHTML);
|
|
||||||
var pageNumbers = document.createElement('span');
|
|
||||||
for (var i = 1; i <= pageCount; i++) {
|
|
||||||
if (
|
|
||||||
(
|
|
||||||
(i >= currentPage - pageEitherSide) &&
|
|
||||||
(i <= currentPage + pageEitherSide)
|
|
||||||
) ||
|
|
||||||
(
|
|
||||||
(
|
|
||||||
i <= (pageEitherSide * 2 + 1) &&
|
|
||||||
currentPage <= (pageEitherSide)
|
|
||||||
) ||
|
|
||||||
(
|
|
||||||
i >= (pageCount - (pageEitherSide * 2)) &&
|
|
||||||
currentPage >= (pageCount - (pageEitherSide))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
var pageNum = document.createElement('span');
|
|
||||||
if (Number(pagerCheck.innerHTML) == i) {
|
|
||||||
pageNum.className = 'games_pager_number_disabled';
|
|
||||||
} else {
|
|
||||||
pageNum.className = 'games_pager_number';
|
|
||||||
pageNum.setAttribute('onclick', 'executeFilter1_1(' + i + ');');
|
|
||||||
}
|
|
||||||
pageNum.innerHTML = i;
|
|
||||||
pageNumbers.appendChild(pageNum);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (placeHolderpresent == false) {
|
||||||
// add next page button
|
var gamePlaceholder = document.createElement('div');
|
||||||
var nextPage = document.createElement('span');
|
gamePlaceholder.setAttribute('name', 'GamePlaceholder');
|
||||||
nextPage.innerHTML = '>';
|
gamePlaceholder.id = 'GamePlaceholder' + i;
|
||||||
if (pageNumber == pageCount) {
|
gamePlaceholder.setAttribute('data-index', i);
|
||||||
nextPage.className = 'games_pager_number_disabled';
|
gamePlaceholder.className = 'game_tile';
|
||||||
} else {
|
newPageAnchor.appendChild(gamePlaceholder);
|
||||||
nextPage.className = 'games_pager_number';
|
|
||||||
nextPage.setAttribute('onclick', 'executeFilter1_1(' + (pageNumber + 1) + ');');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add last page button
|
|
||||||
var lastPage = document.createElement('span');
|
|
||||||
lastPage.innerHTML = '>|';
|
|
||||||
if (pageNumber == pageCount) {
|
|
||||||
lastPage.className = 'games_pager_number_disabled';
|
|
||||||
} else {
|
|
||||||
lastPage.className = 'games_pager_number';
|
|
||||||
lastPage.setAttribute('onclick', 'executeFilter1_1(' + pageCount + ');');
|
|
||||||
}
|
|
||||||
|
|
||||||
pager.innerHTML = '';
|
|
||||||
pager.appendChild(firstPage);
|
|
||||||
pager.appendChild(prevPage);
|
|
||||||
pager.appendChild(pageNumbers);
|
|
||||||
pager.appendChild(nextPage);
|
|
||||||
pager.appendChild(lastPage);
|
|
||||||
|
|
||||||
pager.style.display = '';
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
startIndex = endIndex;
|
||||||
|
endIndex = startIndex + pageSize;
|
||||||
|
|
||||||
|
if (startIndex > result.count) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// var pageReloadFunction = function() {
|
document.getElementById('games_library_recordcount').innerHTML = result.count + ' games';
|
||||||
// formatGamesPanel(targetElement, result, pageNumber, pageSize, false);
|
|
||||||
|
|
||||||
// ajaxCall('/api/v1.1/Filter', 'GET', function (result) {
|
var existingLoadPageButton = document.getElementById('games_library_loadmore');
|
||||||
// var scrollerElement = document.getElementById('games_filter_scroller');
|
if (existingLoadPageButton) {
|
||||||
// formatFilterPanel(scrollerElement, result);
|
existingLoadPageButton.parentNode.removeChild(existingLoadPageButton);
|
||||||
// })
|
}
|
||||||
// };
|
|
||||||
|
|
||||||
// window.clearTimeout(pageReloadInterval);
|
// setup preferences
|
||||||
// pageReloadInterval = setTimeout(pageReloadFunction, 10000);
|
var showTitle = GetPreference("LibraryShowGameTitle", true);
|
||||||
|
var showRatings = GetPreference("LibraryShowGameRating", true);
|
||||||
|
var showClassification = GetPreference("LibraryShowGameClassification", true);
|
||||||
|
var classificationDisplayOrderString = GetPreference("LibraryGameClassificationDisplayOrder", JSON.stringify([ "ESRB" ]));
|
||||||
|
var classificationDisplayOrder = JSON.parse(classificationDisplayOrderString);
|
||||||
|
if (showTitle == "true") { showTitle = true; } else { showTitle = false; }
|
||||||
|
if (showRatings == "true") { showRatings = true; } else { showRatings = false; }
|
||||||
|
if (showClassification == "true") { showClassification = true; } else { showClassification = false; }
|
||||||
|
|
||||||
|
for (var i = 0; i < result.games.length; i++) {
|
||||||
|
var game = renderGameIcon(result.games[i], showTitle, showRatings, showClassification, classificationDisplayOrder, false);
|
||||||
|
switch (pageMode) {
|
||||||
|
case "paged":
|
||||||
|
targetElement.appendChild(game);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "infinite":
|
||||||
|
var placeholderElement = document.getElementById('GamePlaceholder' + result.games[i].index);
|
||||||
|
if (placeholderElement.className != 'game_tile_wrapper') {
|
||||||
|
placeholderElement.className = 'game_tile_wrapper';
|
||||||
|
placeholderElement.innerHTML = '';
|
||||||
|
placeholderElement.appendChild(game);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$(game).fadeIn(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
var pager = document.getElementById('games_pager');
|
||||||
|
pager.style.display = 'none';
|
||||||
|
|
||||||
|
var alphaPager = document.getElementById('games_library_alpha_pager');
|
||||||
|
alphaPager.innerHTML = '';
|
||||||
|
|
||||||
|
switch(pageMode) {
|
||||||
|
case 'infinite':
|
||||||
|
for (const [key, value] of Object.entries(result.alphaList)) {
|
||||||
|
var letterPager = document.createElement('span');
|
||||||
|
letterPager.className = 'games_library_alpha_pager_letter';
|
||||||
|
letterPager.setAttribute('onclick', 'document.location.hash = "#pageAnchor' + (value) + '"; executeFilter1_1(' + (value) + ');');
|
||||||
|
letterPager.innerHTML = key;
|
||||||
|
alphaPager.appendChild(letterPager);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstLoad == true) {
|
||||||
|
if (localStorage.getItem("gaseous-library-scrollpos") != null) {
|
||||||
|
$(window).scrollTop(localStorage.getItem("gaseous-library-scrollpos"));
|
||||||
|
}
|
||||||
|
firstLoad = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IsInView();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'paged':
|
||||||
|
for (const [key, value] of Object.entries(result.alphaList)) {
|
||||||
|
var letterPager = document.createElement('span');
|
||||||
|
letterPager.className = 'games_library_alpha_pager_letter';
|
||||||
|
letterPager.setAttribute('onclick', 'executeFilter1_1(' + value + ');');
|
||||||
|
letterPager.innerHTML = key;
|
||||||
|
alphaPager.appendChild(letterPager);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.count > pageSize) {
|
||||||
|
var pageCount = Math.ceil(result.count / pageSize);
|
||||||
|
|
||||||
|
// add first page button
|
||||||
|
var firstPage = document.createElement('span');
|
||||||
|
firstPage.innerHTML = '|<';
|
||||||
|
if (pageNumber == 1) {
|
||||||
|
firstPage.className = 'games_pager_number_disabled';
|
||||||
|
} else {
|
||||||
|
firstPage.className = 'games_pager_number';
|
||||||
|
firstPage.setAttribute('onclick', 'executeFilter1_1(1);');
|
||||||
|
}
|
||||||
|
|
||||||
|
// add previous page button
|
||||||
|
var prevPage = document.createElement('span');
|
||||||
|
prevPage.innerHTML = '<';
|
||||||
|
if (pageNumber == 1) {
|
||||||
|
prevPage.className = 'games_pager_number_disabled';
|
||||||
|
} else {
|
||||||
|
prevPage.className = 'games_pager_number';
|
||||||
|
prevPage.setAttribute('onclick', 'executeFilter1_1(' + (pageNumber - 1) + ');');
|
||||||
|
}
|
||||||
|
|
||||||
|
// add page numbers
|
||||||
|
var pageEitherSide = 4;
|
||||||
|
// var currentPage = Number(pagerCheck.innerHTML);
|
||||||
|
var currentPage = pageNumber;
|
||||||
|
var pageNumbers = document.createElement('span');
|
||||||
|
for (var i = 1; i <= pageCount; i++) {
|
||||||
|
if (
|
||||||
|
(
|
||||||
|
(i >= currentPage - pageEitherSide) &&
|
||||||
|
(i <= currentPage + pageEitherSide)
|
||||||
|
) ||
|
||||||
|
(
|
||||||
|
(
|
||||||
|
i <= (pageEitherSide * 2 + 1) &&
|
||||||
|
currentPage <= (pageEitherSide)
|
||||||
|
) ||
|
||||||
|
(
|
||||||
|
i >= (pageCount - (pageEitherSide * 2)) &&
|
||||||
|
currentPage >= (pageCount - (pageEitherSide))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
var pageNum = document.createElement('span');
|
||||||
|
if (pageNumber == i) {
|
||||||
|
pageNum.className = 'games_pager_number_disabled';
|
||||||
|
} else {
|
||||||
|
pageNum.className = 'games_pager_number';
|
||||||
|
pageNum.setAttribute('onclick', 'executeFilter1_1(' + i + ');');
|
||||||
|
}
|
||||||
|
pageNum.innerHTML = i;
|
||||||
|
pageNumbers.appendChild(pageNum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add next page button
|
||||||
|
var nextPage = document.createElement('span');
|
||||||
|
nextPage.innerHTML = '>';
|
||||||
|
if (pageNumber == pageCount) {
|
||||||
|
nextPage.className = 'games_pager_number_disabled';
|
||||||
|
} else {
|
||||||
|
nextPage.className = 'games_pager_number';
|
||||||
|
nextPage.setAttribute('onclick', 'executeFilter1_1(' + (pageNumber + 1) + ');');
|
||||||
|
}
|
||||||
|
|
||||||
|
// add last page button
|
||||||
|
var lastPage = document.createElement('span');
|
||||||
|
lastPage.innerHTML = '>|';
|
||||||
|
if (pageNumber == pageCount) {
|
||||||
|
lastPage.className = 'games_pager_number_disabled';
|
||||||
|
} else {
|
||||||
|
lastPage.className = 'games_pager_number';
|
||||||
|
lastPage.setAttribute('onclick', 'executeFilter1_1(' + pageCount + ');');
|
||||||
|
}
|
||||||
|
|
||||||
|
pager.innerHTML = '';
|
||||||
|
pager.appendChild(firstPage);
|
||||||
|
pager.appendChild(prevPage);
|
||||||
|
pager.appendChild(pageNumbers);
|
||||||
|
pager.appendChild(nextPage);
|
||||||
|
pager.appendChild(lastPage);
|
||||||
|
|
||||||
|
pager.style.display = '';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.lazy').Lazy({
|
||||||
|
effect: 'show',
|
||||||
|
effectTime: 500,
|
||||||
|
visibleOnly: true,
|
||||||
|
defaultImage: '/images/unknowngame.png',
|
||||||
|
delay: 250,
|
||||||
|
afterLoad: function(element) {
|
||||||
|
//console.log(element[0].getAttribute('data-id'));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function isScrolledIntoView(elem) {
|
function isScrolledIntoView(elem) {
|
||||||
@@ -256,14 +315,48 @@ function isScrolledIntoView(elem) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
|
||||||
|
const { top, left, bottom, right } = el.getBoundingClientRect();
|
||||||
|
const { innerHeight, innerWidth } = window;
|
||||||
|
return partiallyVisible
|
||||||
|
? ((top > 0 && top < innerHeight) ||
|
||||||
|
(bottom > 0 && bottom < innerHeight)) &&
|
||||||
|
((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
|
||||||
|
: top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
|
||||||
|
};
|
||||||
|
|
||||||
function IsInView() {
|
function IsInView() {
|
||||||
var loadElement = document.getElementById('games_library_loadmore');
|
var pageMode = GetPreference('LibraryPagination', 'paged');
|
||||||
if (loadElement) {
|
switch (pageMode) {
|
||||||
if (isScrolledIntoView(loadElement)) {
|
case "paged":
|
||||||
var pageNumber = Number(document.getElementById('games_library_loadmore').getAttribute('data-pagenumber'));
|
var loadElement = document.getElementById('games_library_loadmore');
|
||||||
var pageSize = document.getElementById('games_library_loadmore').getAttribute('data-pagesize');
|
if (loadElement) {
|
||||||
executeFilter1_1(pageNumber, pageSize);
|
//if (isScrolledIntoView(loadElement)) {
|
||||||
}
|
if (elementIsVisibleInViewport(loadElement, true)) {
|
||||||
|
var pageNumber = Number(document.getElementById('games_library_loadmore').getAttribute('data-pagenumber'));
|
||||||
|
var pageSize = document.getElementById('games_library_loadmore').getAttribute('data-pagesize');
|
||||||
|
executeFilter1_1(pageNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "infinite":
|
||||||
|
// store scroll location
|
||||||
|
localStorage.setItem("gaseous-library-scrollpos", $(window).scrollTop());
|
||||||
|
|
||||||
|
// load page
|
||||||
|
let anchors = document.getElementsByClassName('pageAnchor');
|
||||||
|
for (let i = 0; i < anchors.length; i++) {
|
||||||
|
//if (isScrolledIntoView(anchors[i])) {
|
||||||
|
if (elementIsVisibleInViewport(anchors[i], true)) {
|
||||||
|
if (anchors[i].getAttribute('data-loaded') == "0") {
|
||||||
|
console.log("Loading page: " + anchors[i].getAttribute('data-page'));
|
||||||
|
document.getElementById(anchors[i].id).setAttribute('data-loaded', "1");
|
||||||
|
executeFilter1_1(Number(anchors[i].getAttribute('data-page')));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,26 +372,30 @@ function renderGameIcon(gameObject, showTitle, showRatings, showClassification,
|
|||||||
var gameBox = document.createElement('div');
|
var gameBox = document.createElement('div');
|
||||||
gameBox.id = "game_tile_" + gameObject.id;
|
gameBox.id = "game_tile_" + gameObject.id;
|
||||||
if (useSmallCover == true) {
|
if (useSmallCover == true) {
|
||||||
gameBox.className = classes['game_tile game_tile_small'];
|
gameBox.classList.add(...classes['game_tile game_tile_small']);
|
||||||
} else {
|
} else {
|
||||||
gameBox.className = classes['game_tile'];
|
gameBox.classList.add(...classes['game_tile']);
|
||||||
}
|
}
|
||||||
gameBox.setAttribute('onclick', 'window.location.href = "/index.html?page=game&id=' + gameObject.id + '";');
|
gameBox.setAttribute('onclick', 'window.location.href = "/index.html?page=game&id=' + gameObject.id + '";');
|
||||||
|
gameBox.style.display = 'none';
|
||||||
|
|
||||||
var gameImageBox = document.createElement('div');
|
var gameImageBox = document.createElement('div');
|
||||||
gameImageBox.className = classes['game_tile_box'];
|
gameImageBox.classList.add(...classes['game_tile_box']);
|
||||||
|
|
||||||
var gameImage = document.createElement('img');
|
var gameImage = document.createElement('img');
|
||||||
|
gameImage.id = 'game_tile_cover_' + gameObject.id;
|
||||||
|
gameImage.setAttribute('data-id', gameObject.id);
|
||||||
if (useSmallCover == true) {
|
if (useSmallCover == true) {
|
||||||
gameImage.className = classes['game_tile_image game_tile_image_small lazy'];
|
gameImage.classList.add(...classes['game_tile_image game_tile_image_small lazy']);
|
||||||
} else {
|
} else {
|
||||||
gameImage.className = classes['game_tile_image lazy'];
|
gameImage.classList.add(...classes['game_tile_image lazy']);
|
||||||
}
|
}
|
||||||
gameImage.src = '/images/unknowngame.png';
|
// gameImage.src = '/images/unknowngame.png';
|
||||||
if (gameObject.cover) {
|
if (gameObject.cover) {
|
||||||
gameImage.setAttribute('data-src', '/api/v1.1/Games/' + gameObject.id + '/cover/image/cover_big/' + gameObject.cover.imageId + '.jpg');
|
gameImage.setAttribute('data-src', '/api/v1.1/Games/' + gameObject.id + '/cover/image/cover_big/' + gameObject.cover.imageId + '.jpg');
|
||||||
} else {
|
} else {
|
||||||
gameImage.className = classes['game_tile_image unknown'];
|
gameImage.classList.add(...classes['game_tile_image unknown']);
|
||||||
|
gameImage.setAttribute('data-src', '/images/unknowngame.png');
|
||||||
}
|
}
|
||||||
gameImageBox.appendChild(gameImage);
|
gameImageBox.appendChild(gameImage);
|
||||||
|
|
||||||
@@ -312,7 +409,6 @@ function renderGameIcon(gameObject, showTitle, showRatings, showClassification,
|
|||||||
if (gameObject.ageRatings[c].category == classificationDisplayOrder[b]) {
|
if (gameObject.ageRatings[c].category == classificationDisplayOrder[b]) {
|
||||||
shownClassificationBoard = classificationDisplayOrder[b];
|
shownClassificationBoard = classificationDisplayOrder[b];
|
||||||
displayClassification = true;
|
displayClassification = true;
|
||||||
//classificationPath = '/api/v1.1/Ratings/Images/' + classificationDisplayOrder[b] + '/' + getKeyByValue(AgeRatingStrings, gameObject.ageRatings[c].rating) + '/image.svg';
|
|
||||||
classificationPath = '/images/Ratings/' + classificationDisplayOrder[b] + '/' + gameObject.ageRatings[c].rating + '.svg';
|
classificationPath = '/images/Ratings/' + classificationDisplayOrder[b] + '/' + gameObject.ageRatings[c].rating + '.svg';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -326,7 +422,7 @@ function renderGameIcon(gameObject, showTitle, showRatings, showClassification,
|
|||||||
if (gameObject.hasSavedGame == true) {
|
if (gameObject.hasSavedGame == true) {
|
||||||
var gameSaveIcon = document.createElement('img');
|
var gameSaveIcon = document.createElement('img');
|
||||||
gameSaveIcon.src = '/images/SaveStates.png';
|
gameSaveIcon.src = '/images/SaveStates.png';
|
||||||
gameSaveIcon.className = classes['game_tile_box_savedgame savedstateicon'];
|
gameSaveIcon.classList.add(...classes['game_tile_box_savedgame savedstateicon']);
|
||||||
gameImageBox.appendChild(gameSaveIcon);
|
gameImageBox.appendChild(gameSaveIcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,13 +430,13 @@ function renderGameIcon(gameObject, showTitle, showRatings, showClassification,
|
|||||||
if (gameObject.isFavourite == true) {
|
if (gameObject.isFavourite == true) {
|
||||||
var gameFavIcon = document.createElement('img');
|
var gameFavIcon = document.createElement('img');
|
||||||
gameFavIcon.src = '/images/favourite-filled.svg';
|
gameFavIcon.src = '/images/favourite-filled.svg';
|
||||||
gameFavIcon.className = classes['game_tile_box_favouritegame favouriteicon'];
|
gameFavIcon.classList.add(...classes['game_tile_box_favouritegame favouriteicon']);
|
||||||
gameImageBox.appendChild(gameFavIcon);
|
gameImageBox.appendChild(gameFavIcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameObject.totalRating || displayClassification == true) {
|
if (gameObject.totalRating || displayClassification == true) {
|
||||||
var gameImageRatingBanner = document.createElement('div');
|
var gameImageRatingBanner = document.createElement('div');
|
||||||
gameImageRatingBanner.className = classes['game_tile_box_ratingbanner'];
|
gameImageRatingBanner.classList.add(...classes['game_tile_box_ratingbanner']);
|
||||||
|
|
||||||
if (showRatings == true || displayClassification == true) {
|
if (showRatings == true || displayClassification == true) {
|
||||||
if (showRatings == true) {
|
if (showRatings == true) {
|
||||||
@@ -361,7 +457,7 @@ function renderGameIcon(gameObject, showTitle, showRatings, showClassification,
|
|||||||
if (displayClassification == true) {
|
if (displayClassification == true) {
|
||||||
var gameImageClassificationLogo = document.createElement('img');
|
var gameImageClassificationLogo = document.createElement('img');
|
||||||
gameImageClassificationLogo.src = classificationPath;
|
gameImageClassificationLogo.src = classificationPath;
|
||||||
gameImageClassificationLogo.className = classes['rating_image_overlay'];
|
gameImageClassificationLogo.classList.add(...classes['rating_image_overlay']);
|
||||||
gameImageBox.appendChild(gameImageClassificationLogo);
|
gameImageBox.appendChild(gameImageClassificationLogo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -370,7 +466,7 @@ function renderGameIcon(gameObject, showTitle, showRatings, showClassification,
|
|||||||
|
|
||||||
if (showTitle == true) {
|
if (showTitle == true) {
|
||||||
var gameBoxTitle = document.createElement('div');
|
var gameBoxTitle = document.createElement('div');
|
||||||
gameBoxTitle.className = classes['game_tile_label'];
|
gameBoxTitle.classList.add(...classes['game_tile_label']);
|
||||||
gameBoxTitle.innerHTML = gameObject.name;
|
gameBoxTitle.innerHTML = gameObject.name;
|
||||||
gameBox.appendChild(gameBoxTitle);
|
gameBox.appendChild(gameBoxTitle);
|
||||||
}
|
}
|
||||||
@@ -381,31 +477,31 @@ function renderGameIcon(gameObject, showTitle, showRatings, showClassification,
|
|||||||
function getViewModeClasses(listView) {
|
function getViewModeClasses(listView) {
|
||||||
if (listView == false) {
|
if (listView == false) {
|
||||||
return {
|
return {
|
||||||
"game_tile game_tile_small": "game_tile game_tile_small",
|
"game_tile game_tile_small": [ "game_tile", "game_tile_small" ],
|
||||||
"game_tile": "game_tile",
|
"game_tile": [ "game_tile" ],
|
||||||
"game_tile_box": "game_tile_box",
|
"game_tile_box": [ "game_tile_box" ],
|
||||||
"game_tile_image game_tile_image_small lazy": "game_tile_image game_tile_image_small lazy",
|
"game_tile_image game_tile_image_small lazy": [ "game_tile_image", "game_tile_image_small", "lazy" ],
|
||||||
"game_tile_image lazy": "game_tile_image lazy",
|
"game_tile_image lazy": [ "game_tile_image", "lazy" ],
|
||||||
"game_tile_image unknown": "game_tile_image unknown",
|
"game_tile_image unknown": [ "game_tile_image", "unknown" ],
|
||||||
"game_tile_box_savedgame savedstateicon": "game_tile_box_savedgame savedstateicon",
|
"game_tile_box_savedgame savedstateicon": [ "game_tile_box_savedgame", "savedstateicon" ],
|
||||||
"game_tile_box_favouritegame favouriteicon": "game_tile_box_favouritegame favouriteicon",
|
"game_tile_box_favouritegame favouriteicon": [ "game_tile_box_favouritegame", "favouriteicon" ],
|
||||||
"game_tile_box_ratingbanner": "game_tile_box_ratingbanner",
|
"game_tile_box_ratingbanner": [ "game_tile_box_ratingbanner" ],
|
||||||
"rating_image_overlay": "rating_image_overlay",
|
"rating_image_overlay": [ "rating_image_overlay" ],
|
||||||
"game_tile_label": "game_tile_label"
|
"game_tile_label": [ "game_tile_label" ]
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
"game_tile game_tile_small": "game_tile_row game_tile_small",
|
"game_tile game_tile_small": [ "game_tile_row", "game_tile_small" ],
|
||||||
"game_tile": "game_tile_row",
|
"game_tile": [ "game_tile_row" ],
|
||||||
"game_tile_box": "game_tile_box_row",
|
"game_tile_box": [ "game_tile_box_row" ],
|
||||||
"game_tile_image game_tile_image_small lazy": "game_tile_image_row game_tile_image_small lazy",
|
"game_tile_image game_tile_image_small lazy": [ "game_tile_image_row", "game_tile_image_small", "lazy" ],
|
||||||
"game_tile_image lazy": "game_tile_image_row lazy",
|
"game_tile_image lazy": [ "game_tile_image_row", "lazy" ],
|
||||||
"game_tile_image unknown": "game_tile_image_row unknown",
|
"game_tile_image unknown": [ "game_tile_image_row", "unknown" ],
|
||||||
"game_tile_box_savedgame savedstateicon": "game_tile_box_savedgame_row savedstateicon",
|
"game_tile_box_savedgame savedstateicon": [ "game_tile_box_savedgame_row", "savedstateicon" ],
|
||||||
"game_tile_box_favouritegame favouriteicon": "game_tile_box_favouritegame_row favouriteicon",
|
"game_tile_box_favouritegame favouriteicon": [ "game_tile_box_favouritegame_row", "favouriteicon" ],
|
||||||
"game_tile_box_ratingbanner": "game_tile_box_ratingbanner_row",
|
"game_tile_box_ratingbanner": [ "game_tile_box_ratingbanner_row" ],
|
||||||
"rating_image_overlay": "rating_image_overlay_row",
|
"rating_image_overlay": [ "rating_image_overlay_row" ],
|
||||||
"game_tile_label": "game_tile_label_row"
|
"game_tile_label": [ "game_tile_label_row" ]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -39,7 +39,7 @@ function ajaxCall(endpoint, method, successFunction, errorFunction, body) {
|
|||||||
|
|
||||||
function getQueryString(stringName, type) {
|
function getQueryString(stringName, type) {
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
var myParam = urlParams.get(stringName);
|
var myParam = urlParams.get(stringName);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "int":
|
case "int":
|
||||||
@@ -63,9 +63,9 @@ function getQueryString(stringName, type) {
|
|||||||
|
|
||||||
function setCookie(cname, cvalue, exdays) {
|
function setCookie(cname, cvalue, exdays) {
|
||||||
const d = new Date();
|
const d = new Date();
|
||||||
d.setTime(d.getTime() + (exdays*24*60*60*1000));
|
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
|
||||||
if (exdays) {
|
if (exdays) {
|
||||||
let expires = "expires="+ d.toUTCString();
|
let expires = "expires=" + d.toUTCString();
|
||||||
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
|
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
|
||||||
} else {
|
} else {
|
||||||
document.cookie = cname + "=" + cvalue + ";path=/";
|
document.cookie = cname + "=" + cvalue + ";path=/";
|
||||||
@@ -76,14 +76,14 @@ function getCookie(cname) {
|
|||||||
let name = cname + "=";
|
let name = cname + "=";
|
||||||
let decodedCookie = decodeURIComponent(document.cookie);
|
let decodedCookie = decodeURIComponent(document.cookie);
|
||||||
let ca = decodedCookie.split(';');
|
let ca = decodedCookie.split(';');
|
||||||
for(let i = 0; i <ca.length; i++) {
|
for (let i = 0; i < ca.length; i++) {
|
||||||
let c = ca[i];
|
let c = ca[i];
|
||||||
while (c.charAt(0) == ' ') {
|
while (c.charAt(0) == ' ') {
|
||||||
c = c.substring(1);
|
c = c.substring(1);
|
||||||
}
|
}
|
||||||
if (c.indexOf(name) == 0) {
|
if (c.indexOf(name) == 0) {
|
||||||
return c.substring(name.length, c.length);
|
return c.substring(name.length, c.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -207,7 +207,7 @@ function createTableRow(isHeader, row, rowClass, cellClass) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var newCell = document.createElement(cellType);
|
var newCell = document.createElement(cellType);
|
||||||
if (typeof(row[i]) != "object") {
|
if (typeof (row[i]) != "object") {
|
||||||
newCell.innerHTML = row[i];
|
newCell.innerHTML = row[i];
|
||||||
newCell.className = cellClass;
|
newCell.className = cellClass;
|
||||||
} else {
|
} else {
|
||||||
@@ -258,7 +258,7 @@ function DropDownRenderGameOption(state) {
|
|||||||
|
|
||||||
if (state.cover) {
|
if (state.cover) {
|
||||||
response = $(
|
response = $(
|
||||||
'<table class="dropdown-div"><tr><td class="dropdown-cover"><img src="/api/v1.1/Games/' + state.id + '/cover/image/cover_small/' + state.cover.imageId + '.jpg" /></td><td class="dropdown-label"><span class="dropdown-title">' + state.text + '</span><span class="dropdown-releasedate">' + releaseDate + '</span></td></tr></table>'
|
'<table class="dropdown-div"><tr><td class="dropdown-cover"><img src="/api/v1.1/Games/' + state.id + '/cover/image/cover_small/' + state.id + '.jpg" class="game_tile_small_search" /></td><td class="dropdown-label"><span class="dropdown-title">' + state.text + '</span><span class="dropdown-releasedate">' + releaseDate + '</span></td></tr></table>'
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
response = $(
|
response = $(
|
||||||
@@ -317,8 +317,8 @@ function CreateEditableTable(TableName, Headers) {
|
|||||||
var addButton = document.createElement('button');
|
var addButton = document.createElement('button');
|
||||||
addButton.value = 'Add Row';
|
addButton.value = 'Add Row';
|
||||||
addButton.innerHTML = 'Add Row';
|
addButton.innerHTML = 'Add Row';
|
||||||
|
|
||||||
$(addButton).click(function() {
|
$(addButton).click(function () {
|
||||||
eTable.appendChild(AddEditableTableRow(Headers));
|
eTable.appendChild(AddEditableTableRow(Headers));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -463,10 +463,10 @@ function SetPreference(Setting, Value) {
|
|||||||
ajaxCall(
|
ajaxCall(
|
||||||
'/api/v1.1/Account/Preferences',
|
'/api/v1.1/Account/Preferences',
|
||||||
'POST',
|
'POST',
|
||||||
function(result) {
|
function (result) {
|
||||||
SetPreference_Local(Setting, Value);
|
SetPreference_Local(Setting, Value);
|
||||||
},
|
},
|
||||||
function(error) {
|
function (error) {
|
||||||
SetPreference_Local(Setting, Value);
|
SetPreference_Local(Setting, Value);
|
||||||
},
|
},
|
||||||
JSON.stringify(model)
|
JSON.stringify(model)
|
||||||
@@ -478,12 +478,12 @@ function SetPreference_Batch(model) {
|
|||||||
ajaxCall(
|
ajaxCall(
|
||||||
'/api/v1.1/Account/Preferences',
|
'/api/v1.1/Account/Preferences',
|
||||||
'POST',
|
'POST',
|
||||||
function(result) {
|
function (result) {
|
||||||
for (var i = 0; i < model.length; i++) {
|
for (var i = 0; i < model.length; i++) {
|
||||||
SetPreference_Local(model[i].setting, model[i].value.toString());
|
SetPreference_Local(model[i].setting, model[i].value.toString());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
function(error) {
|
function (error) {
|
||||||
for (var i = 0; i < model.length; i++) {
|
for (var i = 0; i < model.length; i++) {
|
||||||
SetPreference_Local(model[i].setting, model[i].value.toString());
|
SetPreference_Local(model[i].setting, model[i].value.toString());
|
||||||
}
|
}
|
||||||
@@ -509,11 +509,11 @@ function SetPreference_Local(Setting, Value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Uint8ToString(u8a){
|
function Uint8ToString(u8a) {
|
||||||
var CHUNK_SZ = 0x8000;
|
var CHUNK_SZ = 0x8000;
|
||||||
var c = [];
|
var c = [];
|
||||||
for (var i=0; i < u8a.length; i+=CHUNK_SZ) {
|
for (var i = 0; i < u8a.length; i += CHUNK_SZ) {
|
||||||
c.push(String.fromCharCode.apply(null, u8a.subarray(i, i+CHUNK_SZ)));
|
c.push(String.fromCharCode.apply(null, u8a.subarray(i, i + CHUNK_SZ)));
|
||||||
}
|
}
|
||||||
return c.join("");
|
return c.join("");
|
||||||
}
|
}
|
||||||
|
@@ -23,21 +23,29 @@ h3 {
|
|||||||
border-bottom-width: 1px;
|
border-bottom-width: 1px;
|
||||||
/*border-image: linear-gradient(to right, blue 25%, yellow 25%, yellow 50%,red 50%, red 75%, teal 75%) 5;*/
|
/*border-image: linear-gradient(to right, blue 25%, yellow 25%, yellow 50%,red 50%, red 75%, teal 75%) 5;*/
|
||||||
|
|
||||||
border-image: linear-gradient(to right, rgba(255,0,0,1) 0%, rgba(251,255,0,1) 16%, rgba(0,255,250,1) 30%, rgba(0,16,255,1) 46%, rgba(250,0,255,1) 62%, rgba(255,0,0,1) 78%, rgba(255,237,0,1) 90%, rgba(20,255,0,1) 100%) 5;
|
border-image: linear-gradient(to right, rgba(255, 0, 0, 1) 0%, rgba(251, 255, 0, 1) 16%, rgba(0, 255, 250, 1) 30%, rgba(0, 16, 255, 1) 46%, rgba(250, 0, 255, 1) 62%, rgba(255, 0, 0, 1) 78%, rgba(255, 237, 0, 1) 90%, rgba(20, 255, 0, 1) 100%) 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The Modal (background) */
|
/* The Modal (background) */
|
||||||
.modal {
|
.modal {
|
||||||
display: none; /* Hidden by default */
|
display: none;
|
||||||
position: fixed; /* Stay in place */
|
/* Hidden by default */
|
||||||
z-index: 100; /* Sit on top */
|
position: fixed;
|
||||||
|
/* Stay in place */
|
||||||
|
z-index: 100;
|
||||||
|
/* Sit on top */
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 100%; /* Full width */
|
width: 100%;
|
||||||
height: 100%; /* Full height */
|
/* Full width */
|
||||||
overflow: none; /* Enable scroll if needed */
|
height: 100%;
|
||||||
background-color: rgb(0,0,0); /* Fallback color */
|
/* Full height */
|
||||||
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
|
overflow: none;
|
||||||
|
/* Enable scroll if needed */
|
||||||
|
background-color: rgb(0, 0, 0);
|
||||||
|
/* Fallback color */
|
||||||
|
background-color: rgba(0, 0, 0, 0.4);
|
||||||
|
/* Black w/ opacity */
|
||||||
backdrop-filter: blur(8px);
|
backdrop-filter: blur(8px);
|
||||||
-webkit-backdrop-filter: blur(8px);
|
-webkit-backdrop-filter: blur(8px);
|
||||||
filter: drop-shadow(5px 5px 10px #000);
|
filter: drop-shadow(5px 5px 10px #000);
|
||||||
@@ -47,22 +55,28 @@ h3 {
|
|||||||
/* Modal Content/Box */
|
/* Modal Content/Box */
|
||||||
.modal-content {
|
.modal-content {
|
||||||
background-color: #383838;
|
background-color: #383838;
|
||||||
margin: 10% auto; /* 15% from the top and centered */
|
margin: 10% auto;
|
||||||
|
/* 15% from the top and centered */
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border: 1px solid #888;
|
border: 1px solid #888;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
width: 700px; /* Could be more or less, depending on screen size */
|
width: 700px;
|
||||||
|
/* Could be more or less, depending on screen size */
|
||||||
min-height: 358px;
|
min-height: 358px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-content-sub {
|
.modal-content-sub {
|
||||||
background-color: #383838;
|
background-color: #383838;
|
||||||
margin: 20% auto; /* 20% from the top and centered */
|
margin: 20% auto;
|
||||||
|
/* 20% from the top and centered */
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border: 1px solid #888;
|
border: 1px solid #888;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
width: 300px; /* Could be more or less, depending on screen size */
|
width: 300px;
|
||||||
|
/* Could be more or less, depending on screen size */
|
||||||
min-height: 110px;
|
min-height: 110px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#modal-heading {
|
#modal-heading {
|
||||||
margin-block: 5px;
|
margin-block: 5px;
|
||||||
border-bottom-style: solid;
|
border-bottom-style: solid;
|
||||||
@@ -70,8 +84,9 @@ h3 {
|
|||||||
border-bottom-width: 3px;
|
border-bottom-width: 3px;
|
||||||
/*border-image: linear-gradient(to right, blue 25%, yellow 25%, yellow 50%,red 50%, red 75%, teal 75%) 5;*/
|
/*border-image: linear-gradient(to right, blue 25%, yellow 25%, yellow 50%,red 50%, red 75%, teal 75%) 5;*/
|
||||||
|
|
||||||
border-image: linear-gradient(to right, rgba(255,0,0,1) 0%, rgba(251,255,0,1) 16%, rgba(0,255,250,1) 30%, rgba(0,16,255,1) 46%, rgba(250,0,255,1) 62%, rgba(255,0,0,1) 78%, rgba(255,237,0,1) 90%, rgba(20,255,0,1) 100%) 5;
|
border-image: linear-gradient(to right, rgba(255, 0, 0, 1) 0%, rgba(251, 255, 0, 1) 16%, rgba(0, 255, 250, 1) 30%, rgba(0, 16, 255, 1) 46%, rgba(250, 0, 255, 1) 62%, rgba(255, 0, 0, 1) 78%, rgba(255, 237, 0, 1) 90%, rgba(20, 255, 0, 1) 100%) 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
#modal-content {
|
#modal-content {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
@@ -268,7 +283,7 @@ h3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#games_filter {
|
#games_filter {
|
||||||
|
|
||||||
width: 200px;
|
width: 200px;
|
||||||
/* border-style: solid;
|
/* border-style: solid;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
@@ -296,7 +311,11 @@ h3 {
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type='text'], input[type='number'], input[type="email"], input[type="password"], input[type="datetime-local"] {
|
input[type='text'],
|
||||||
|
input[type='number'],
|
||||||
|
input[type="email"],
|
||||||
|
input[type="password"],
|
||||||
|
input[type="datetime-local"] {
|
||||||
background-color: #2b2b2b;
|
background-color: #2b2b2b;
|
||||||
color: white;
|
color: white;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
@@ -313,7 +332,11 @@ input[type='text'], input[type='number'], input[type="email"], input[type="passw
|
|||||||
height: 21px;
|
height: 21px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type='text']:hover, input[type='number']:hover, input[type="email"]:hover, input[type="password"]:hover, input[type="datetime-local"]:hover {
|
input[type='text']:hover,
|
||||||
|
input[type='number']:hover,
|
||||||
|
input[type="email"]:hover,
|
||||||
|
input[type="password"]:hover,
|
||||||
|
input[type="datetime-local"]:hover {
|
||||||
border-color: #939393;
|
border-color: #939393;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,9 +374,7 @@ input[name='filter_panel_range_max'] {
|
|||||||
background: #555;
|
background: #555;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text_link {
|
.text_link {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.text_link:hover {
|
.text_link:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -390,9 +411,9 @@ input[name='filter_panel_range_max'] {
|
|||||||
background-color: rgba(0, 22, 56, 0.8);
|
background-color: rgba(0, 22, 56, 0.8);
|
||||||
backdrop-filter: blur(8px);
|
backdrop-filter: blur(8px);
|
||||||
-webkit-backdrop-filter: blur(8px);
|
-webkit-backdrop-filter: blur(8px);
|
||||||
box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
-webkit-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
-moz-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
}
|
}
|
||||||
|
|
||||||
.games_pager_number {
|
.games_pager_number {
|
||||||
@@ -525,13 +546,13 @@ input[name='filter_panel_range_max'] {
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
/* display: flex; */
|
/* display: flex; */
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
#games_library_alpha_pager {
|
#games_library_alpha_pager {
|
||||||
width: 50px;
|
width: 50px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.games_library_alpha_pager_letter {
|
.games_library_alpha_pager_letter {
|
||||||
@@ -548,11 +569,25 @@ input[name='filter_panel_range_max'] {
|
|||||||
background-color: blue;
|
background-color: blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.game_tile_wrapper {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game_tile_placeholder {
|
||||||
|
display: inline-block;
|
||||||
|
min-height: 243px;
|
||||||
|
width: 232px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.game_tile {
|
.game_tile {
|
||||||
padding: 5px;
|
padding-top: 10px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
padding-left: 5px;
|
||||||
|
padding-right: 5px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 220px;
|
width: 220px;
|
||||||
min-height: 200px;
|
min-height: 243px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -590,6 +625,12 @@ input[name='filter_panel_range_max'] {
|
|||||||
border: 1px solid #2b2b2b;
|
border: 1px solid #2b2b2b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.game_tile_small_search {
|
||||||
|
min-height: 50px;
|
||||||
|
min-width: 50px;
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
.game_tile_row {
|
.game_tile_row {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
display: block;
|
display: block;
|
||||||
@@ -689,9 +730,12 @@ input[name='filter_panel_range_max'] {
|
|||||||
max-height: 200px;
|
max-height: 200px;
|
||||||
min-height: 200px;
|
min-height: 200px;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
}
|
||||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
|
||||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
.game_tile_image_shadow {
|
||||||
|
box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
|
-webkit-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
|
-moz-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
}
|
}
|
||||||
|
|
||||||
.game_tile_image_row {
|
.game_tile_image_row {
|
||||||
@@ -701,16 +745,15 @@ input[name='filter_panel_range_max'] {
|
|||||||
min-height: 75px;
|
min-height: 75px;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
|
||||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
|
||||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.game_tile_image, .unknown {
|
.game_tile_image,
|
||||||
|
.unknown {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.game_tile_image_row, .unknown {
|
.game_tile_image_row,
|
||||||
|
.unknown {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -776,9 +819,9 @@ input[name='filter_panel_range_max'] {
|
|||||||
max-width: 250px;
|
max-width: 250px;
|
||||||
max-height: 350px;
|
max-height: 350px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
-webkit-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
-moz-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
}
|
}
|
||||||
|
|
||||||
.gamegenrelabel {
|
.gamegenrelabel {
|
||||||
@@ -828,9 +871,9 @@ input[name='filter_panel_range_max'] {
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
/*height: 350px;*/
|
/*height: 350px;*/
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
-webkit-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
-moz-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
}
|
}
|
||||||
|
|
||||||
#gamescreenshots_main {
|
#gamescreenshots_main {
|
||||||
@@ -889,11 +932,16 @@ iframe {
|
|||||||
background-color: #383838;
|
background-color: #383838;
|
||||||
color: black;
|
color: black;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
user-select: none; /* standard syntax */
|
user-select: none;
|
||||||
-webkit-user-select: none; /* webkit (safari, chrome) browsers */
|
/* standard syntax */
|
||||||
-moz-user-select: none; /* mozilla browsers */
|
-webkit-user-select: none;
|
||||||
-khtml-user-select: none; /* webkit (konqueror) browsers */
|
/* webkit (safari, chrome) browsers */
|
||||||
-ms-user-select: none; /* IE10+ */
|
-moz-user-select: none;
|
||||||
|
/* mozilla browsers */
|
||||||
|
-khtml-user-select: none;
|
||||||
|
/* webkit (konqueror) browsers */
|
||||||
|
-ms-user-select: none;
|
||||||
|
/* IE10+ */
|
||||||
}
|
}
|
||||||
|
|
||||||
.gamescreenshots_arrows:hover {
|
.gamescreenshots_arrows:hover {
|
||||||
@@ -967,9 +1015,7 @@ iframe {
|
|||||||
background-color: rgba(56, 56, 56, 0.9);
|
background-color: rgba(56, 56, 56, 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
#gamesummarytext_label {
|
#gamesummarytext_label {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.line-clamp-4 {
|
.line-clamp-4 {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -1043,9 +1089,9 @@ th {
|
|||||||
-webkit-border-radius: 5px 5px 5px 5px;
|
-webkit-border-radius: 5px 5px 5px 5px;
|
||||||
-moz-border-radius: 5px 5px 5px 5px;
|
-moz-border-radius: 5px 5px 5px 5px;
|
||||||
border: 1px solid #19d348;
|
border: 1px solid #19d348;
|
||||||
box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
-webkit-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
-moz-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
}
|
}
|
||||||
|
|
||||||
.romstart:hover {
|
.romstart:hover {
|
||||||
@@ -1070,9 +1116,9 @@ th {
|
|||||||
border-color: white;
|
border-color: white;
|
||||||
background-color: blue;
|
background-color: blue;
|
||||||
outline-color: blue;
|
outline-color: blue;
|
||||||
box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
-webkit-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
-moz-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
}
|
}
|
||||||
|
|
||||||
.properties_button:hover {
|
.properties_button:hover {
|
||||||
@@ -1101,14 +1147,18 @@ th {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
div[name="properties_toc_item"],div[name="properties_user_toc_item"],div[name="properties_profile_toc_item"] {
|
div[name="properties_toc_item"],
|
||||||
|
div[name="properties_user_toc_item"],
|
||||||
|
div[name="properties_profile_toc_item"] {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-bottom-width: 1px;
|
border-bottom-width: 1px;
|
||||||
border-bottom-style: solid;
|
border-bottom-style: solid;
|
||||||
border-bottom-color: #2b2b2b;
|
border-bottom-color: #2b2b2b;
|
||||||
}
|
}
|
||||||
|
|
||||||
div[name="properties_toc_item"]:hover,div[name="properties_user_toc_item"]:hover,div[name="properties_profile_toc_item"]:hover {
|
div[name="properties_toc_item"]:hover,
|
||||||
|
div[name="properties_user_toc_item"]:hover,
|
||||||
|
div[name="properties_profile_toc_item"]:hover {
|
||||||
background-color: #2b2b2b;
|
background-color: #2b2b2b;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
@@ -1136,7 +1186,8 @@ div[name="properties_toc_item"]:hover,div[name="properties_user_toc_item"]:hover
|
|||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.select2-container--default:hover, .select2-selection--multiple:hover {
|
.select2-container--default:hover,
|
||||||
|
.select2-selection--multiple:hover {
|
||||||
border-color: #939393;
|
border-color: #939393;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1183,7 +1234,8 @@ div[name="properties_toc_item"]:hover,div[name="properties_user_toc_item"]:hover
|
|||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.select2-selection--single:hover, .select2-selection__rendered:hover {
|
.select2-selection--single:hover,
|
||||||
|
.select2-selection__rendered:hover {
|
||||||
border-color: #939393;
|
border-color: #939393;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1288,9 +1340,7 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
|||||||
background-color: #555;
|
background-color: #555;
|
||||||
}
|
}
|
||||||
|
|
||||||
#emulator {
|
#emulator {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.emulator_partscreen {
|
.emulator_partscreen {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
@@ -1363,15 +1413,14 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
|||||||
margin-left: 15px;
|
margin-left: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rom_checkbox_box {
|
.rom_checkbox_box {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.rom_checkbox_box_hidden {
|
.rom_checkbox_box_hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#rom_edit, #rom_edit_delete {
|
#rom_edit,
|
||||||
|
#rom_edit_delete {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1384,9 +1433,9 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#game {
|
#game {
|
||||||
box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
-webkit-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
-moz-box-shadow: 5px 5px 19px 0px rgba(0, 0, 0, 0.44);
|
||||||
}
|
}
|
||||||
|
|
||||||
#gametitle_criticrating {
|
#gametitle_criticrating {
|
||||||
@@ -1426,7 +1475,7 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
|||||||
width: 1000px;
|
width: 1000px;
|
||||||
height: 90%;
|
height: 90%;
|
||||||
margin: 25px auto;
|
margin: 25px auto;
|
||||||
/* overflow-x: scroll;*/
|
/* overflow-x: scroll;*/
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1454,7 +1503,8 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.bgalt1 {
|
.bgalt1 {
|
||||||
background-color: transparent;;
|
background-color: transparent;
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logs_table_cell_150px {
|
.logs_table_cell_150px {
|
||||||
@@ -1506,13 +1556,33 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
|||||||
background-color: #383838;
|
background-color: #383838;
|
||||||
}
|
}
|
||||||
|
|
||||||
.string { color: lightblue; }
|
.string {
|
||||||
.number { color: lightblue; }
|
color: lightblue;
|
||||||
.boolean { color: lightblue; }
|
}
|
||||||
.null { color: magenta; }
|
|
||||||
.key { color: greenyellow; }
|
.number {
|
||||||
.brace { color: #888; }
|
color: lightblue;
|
||||||
.square { color: #fff000; }
|
}
|
||||||
|
|
||||||
|
.boolean {
|
||||||
|
color: lightblue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.null {
|
||||||
|
color: magenta;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key {
|
||||||
|
color: greenyellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brace {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.square {
|
||||||
|
color: #fff000;
|
||||||
|
}
|
||||||
|
|
||||||
.tagBox {
|
.tagBox {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -1543,12 +1613,16 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.loginwindow {
|
.loginwindow {
|
||||||
position: fixed; /* Stay in place */
|
position: fixed;
|
||||||
|
/* Stay in place */
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 100%; /* Full width */
|
width: 100%;
|
||||||
height: 100%; /* Full height */
|
/* Full width */
|
||||||
overflow: auto; /* Enable scroll if needed */
|
height: 100%;
|
||||||
|
/* Full height */
|
||||||
|
overflow: auto;
|
||||||
|
/* Enable scroll if needed */
|
||||||
/*background-color: rgb(0,0,0); /* Fallback color */
|
/*background-color: rgb(0,0,0); /* Fallback color */
|
||||||
/*background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
|
/*background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
|
||||||
/*backdrop-filter: blur(8px);
|
/*backdrop-filter: blur(8px);
|
||||||
@@ -1561,11 +1635,13 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
|||||||
.loginwindow-content {
|
.loginwindow-content {
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: #383838;
|
background-color: #383838;
|
||||||
margin: 15% auto; /* 15% from the top and centered */
|
margin: 15% auto;
|
||||||
|
/* 15% from the top and centered */
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border: 1px solid #888;
|
border: 1px solid #888;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
width: 350px; /* Could be more or less, depending on screen size */
|
width: 350px;
|
||||||
|
/* Could be more or less, depending on screen size */
|
||||||
min-height: 250px;
|
min-height: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1601,7 +1677,8 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Links inside the dropdown */
|
/* Links inside the dropdown */
|
||||||
.dropdown-content a, .dropdown-content span {
|
.dropdown-content a,
|
||||||
|
.dropdown-content span {
|
||||||
color: black;
|
color: black;
|
||||||
padding: 12px 16px;
|
padding: 12px 16px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
@@ -1611,12 +1688,16 @@ button:not(.select2-selection__choice__remove):not(.ejs_menu_button):disabled {
|
|||||||
.dropdown-content span {
|
.dropdown-content span {
|
||||||
cursor: auto;
|
cursor: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Change color of dropdown links on hover */
|
/* Change color of dropdown links on hover */
|
||||||
.dropdown-content a:hover {background-color: #ddd;}
|
.dropdown-content a:hover {
|
||||||
|
background-color: #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */
|
/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */
|
||||||
.show {display:block;}
|
.show {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
.dropdownroleitem {
|
.dropdownroleitem {
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
|
Reference in New Issue
Block a user