mirror of
https://github.com/rommapp/romm.git
synced 2026-02-19 07:50:57 +01:00
Merge branch 'master' into scheduled-tasks
This commit is contained in:
@@ -75,16 +75,14 @@ Inspired by [Jellyfin](https://jellyfin.org/), allows you to manage all your gam
|
||||
|
||||
Docker should be installed and set up before running the [image](https://hub.docker.com/r/zurdi15/romm/tags).
|
||||
|
||||
1. Generate an API key for [IGDB](https://www.igdb.com/), and set the `IGDB_CLIENT_ID` and `IGDB_CLIENT_SECRET` variables. _This is required to run a library scan._ Instructions on generating the ID and Secret are [here](https://api-docs.igdb.com/#about). Note that IDGB requires a Twitch account with 2FA enabled to generate the ID and Secret.
|
||||
1. Generate an API key for [IGDB](https://www.igdb.com/), and set the `IGDB_CLIENT_ID` and `IGDB_CLIENT_SECRET` variables. _This is required to run a library scan._ Instructions on generating the ID and Secret are [here](https://api-docs.igdb.com/#about). Note that IGDB requires a Twitch account with 2FA enabled to generate the ID and Secret.
|
||||
2. Verify that your library folder structure matches one of the options listed in the [following section](#folder-structure).
|
||||
3. Create a docker-compose file. See the following example [docker-compose.yml](https://github.com/zurdi15/romm/blob/master/examples/docker-compose.example.yml) file for reference. Customize for your setup and include the `IGDB_CLIENT_ID` and `IGDB_CLIENT_SECRET` vareiables where indicated in the environment section of the file.
|
||||
3. Create a docker-compose file. See the following example [docker-compose.yml](https://github.com/zurdi15/romm/blob/master/examples/docker-compose.example.yml) file for reference. Customize for your setup and include the `IGDB_CLIENT_ID` and `IGDB_CLIENT_SECRET` variables where indicated in the environment section of the file.
|
||||
4. Launch the container:
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
If configured correctly, Romm will automatically run an initial scan on your library.
|
||||
|
||||
|
||||
# Configuration
|
||||
@@ -143,7 +141,7 @@ If you want to enable the user management system, a redis container and some env
|
||||
- `ROMM_AUTH_ENABLED` and `ENABLE_EXPERIMENTAL_REDIS` must be set as `true`
|
||||
- `ROMM_AUTH_SECRET_KEY` must be generated with `openssl rand -hex 32`
|
||||
- `ROMM_AUTH_USERNAME` and `ROMM_AUTH_PASSWORD` can be set as wanted, being both `admin` by default.
|
||||
- `REDIS_HOST` and `REDIS_PORT` must point to your redis instance
|
||||
- `REDIS_HOST` and `REDIS_PORT` must point to your redis instance. Aditionally, if your redis is secured you can set `REDIS_PASSWORD`
|
||||
|
||||
<h2 id="configuration-file">⚙️ Configuration file</h2>
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ ENABLE_EXPERIMENTAL_REDIS: Final = (
|
||||
)
|
||||
REDIS_HOST: Final = os.environ.get("REDIS_HOST", "localhost")
|
||||
REDIS_PORT: Final = os.environ.get("REDIS_PORT", "6379")
|
||||
REDIS_PASSWORD: Final = os.environ.get("REDIS_PASSWORD")
|
||||
|
||||
# IGDB
|
||||
IGDB_CLIENT_ID: Final = os.environ.get(
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
from redis import Redis
|
||||
|
||||
from config import REDIS_HOST, REDIS_PORT, ENABLE_EXPERIMENTAL_REDIS
|
||||
from config import REDIS_HOST, REDIS_PORT, REDIS_PASSWORD, ENABLE_EXPERIMENTAL_REDIS
|
||||
|
||||
redis_client = Redis(
|
||||
host=REDIS_HOST, port=int(REDIS_PORT), password=REDIS_PASSWORD, db=0
|
||||
)
|
||||
redis_url = (
|
||||
f"redis://:{REDIS_PASSWORD}@{REDIS_HOST}:{REDIS_PORT}"
|
||||
if REDIS_PASSWORD
|
||||
else f"redis://{REDIS_HOST}:{REDIS_PORT}"
|
||||
)
|
||||
|
||||
|
||||
class FallbackCache:
|
||||
def __init__(self) -> None:
|
||||
@@ -30,7 +40,11 @@ class FallbackCache:
|
||||
|
||||
# A seperate client that auto-decodes responses is needed
|
||||
_cache_client = Redis(
|
||||
host=REDIS_HOST, port=int(REDIS_PORT), db=0, decode_responses=True
|
||||
host=REDIS_HOST,
|
||||
port=int(REDIS_PORT),
|
||||
password=REDIS_PASSWORD,
|
||||
db=0,
|
||||
decode_responses=True,
|
||||
)
|
||||
_fallback_cache = FallbackCache()
|
||||
cache = _cache_client if ENABLE_EXPERIMENTAL_REDIS else _fallback_cache
|
||||
|
||||
@@ -15,6 +15,16 @@ services:
|
||||
redis:
|
||||
image: redis:alpine
|
||||
container_name: redis
|
||||
command:
|
||||
# - /bin/sh
|
||||
# - -c
|
||||
# # - Double dollars, so that the variable is not expanded by Docker Compose
|
||||
# # - Surround by quotes, so that the shell does not split the password
|
||||
# # - The ${variable:?message} syntax causes shell to exit with a non-zero
|
||||
# # code and print a message, when the variable is not set or empty
|
||||
# - redis-server --requirepass "$${REDIS_PASSWORD:?REDIS_PASSWORD variable is not set}"
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- ${REDIS_PORT}:6379
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
@@ -24,6 +24,7 @@ ENABLE_EXPERIMENTAL_REDIS=true
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PORT=6379
|
||||
ENABLE_EXPERIMENTAL_REDIS=true
|
||||
#REDIS_PASSWORD=admin_redis
|
||||
|
||||
# Authentication (optional)
|
||||
ROMM_AUTH_ENABLED=true
|
||||
|
||||
@@ -27,6 +27,7 @@ services:
|
||||
- ENABLE_EXPERIMENTAL_REDIS=true # default: false
|
||||
- REDIS_HOST=redis # default: localhost
|
||||
- REDIS_PORT=6379 # default: 6379
|
||||
- REDIS_PASSWORD=<redis password> # [Optional] Support for secured redis
|
||||
volumes:
|
||||
- "/path/to/library:/romm/library"
|
||||
- "/path/to/resources:/romm/resources" # [Optional] Path where roms metadata (covers) are stored
|
||||
@@ -40,9 +41,9 @@ services:
|
||||
restart: "unless-stopped"
|
||||
|
||||
# [Optional] Only required if using MariaDB as the database
|
||||
mariadb:
|
||||
romm_db:
|
||||
image: mariadb:latest
|
||||
container_name: mariadb
|
||||
container_name: romm_db
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=<root password>
|
||||
- MYSQL_DATABASE=romm
|
||||
|
||||
2
frontend/package-lock.json
generated
2
frontend/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "romm",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "romm",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite --host",
|
||||
|
||||
@@ -50,7 +50,7 @@ emitter.on("toggleDrawerRail", () => {
|
||||
</v-list-item>
|
||||
</template>
|
||||
<platform-list-item
|
||||
v-for="platform in platforms.value"
|
||||
v-for="platform in platforms.filledPlatforms"
|
||||
:platform="platform"
|
||||
:rail="rail"
|
||||
:key="platform.slug"
|
||||
|
||||
@@ -8,6 +8,7 @@ export default defineStore("platforms", {
|
||||
},
|
||||
getters: {
|
||||
totalGames: ({ value }) => value.reduce((count, p) => count + p.n_roms, 0),
|
||||
filledPlatforms: ({ value }) => value.filter((p) => p.n_roms > 0),
|
||||
},
|
||||
actions: {
|
||||
set(platforms) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { defineStore } from "pinia";
|
||||
|
||||
export default defineStore("roms", {
|
||||
state: () => ({
|
||||
_platform: "",
|
||||
_all: [],
|
||||
_filteredIDs: [],
|
||||
_searchIDs: [],
|
||||
@@ -14,6 +15,7 @@ export default defineStore("roms", {
|
||||
}),
|
||||
|
||||
getters: {
|
||||
platform: (state) => state._platform,
|
||||
allRoms: (state) => state._all,
|
||||
filteredRoms: (state) =>
|
||||
state._all.filter((rom) => state._filteredIDs.includes(rom.id)),
|
||||
@@ -33,6 +35,9 @@ export default defineStore("roms", {
|
||||
"id"
|
||||
);
|
||||
},
|
||||
setPlatform(platform) {
|
||||
this._platform = platform;
|
||||
},
|
||||
// All roms
|
||||
set(roms) {
|
||||
this._all = roms;
|
||||
|
||||
@@ -17,7 +17,7 @@ const platforms = storePlatforms();
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col
|
||||
v-for="platform in platforms.value"
|
||||
v-for="platform in platforms.filledPlatforms"
|
||||
class="pa-1"
|
||||
:key="platform.slug"
|
||||
:cols="views[0]['size-cols']"
|
||||
|
||||
@@ -10,7 +10,7 @@ const platforms = storePlatforms();
|
||||
<v-chip-group>
|
||||
<v-chip class="text-overline" variant="text" label>
|
||||
<v-icon class="mr-2">mdi-controller</v-icon
|
||||
>{{ platforms.value.length }} Platforms
|
||||
>{{ platforms.filledPlatforms.length }} Platforms
|
||||
</v-chip>
|
||||
<v-chip class="text-overline" variant="text" label>
|
||||
<v-icon class="mr-2">mdi-disc</v-icon>{{ platforms.totalGames }} Games
|
||||
|
||||
@@ -68,10 +68,11 @@ async function fetchRoms(platform) {
|
||||
const allRomsSet = [...allRoms.value, ...response.data.items];
|
||||
romsStore.set(allRomsSet);
|
||||
romsStore.setFiltered(allRomsSet);
|
||||
romsStore.setPlatform(platform);
|
||||
|
||||
if (isFiltered) {
|
||||
searchCursor.value = response.data.next_page;
|
||||
|
||||
|
||||
const serchedRomsSet = [...searchRoms.value, ...response.data.items];
|
||||
romsStore.setSearch(serchedRomsSet);
|
||||
romsStore.setFiltered(serchedRomsSet);
|
||||
@@ -143,7 +144,23 @@ function selectRom({ event, index, selected }) {
|
||||
}
|
||||
}
|
||||
|
||||
function resetGallery() {
|
||||
cursor.value = "";
|
||||
searchCursor.value = "";
|
||||
romsStore.reset();
|
||||
scrolledToTop.value = true;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const platform = route.params.platform;
|
||||
|
||||
// If platform is different, reset store and fetch roms
|
||||
if (platform != romsStore.platform) {
|
||||
resetGallery();
|
||||
fetchRoms(route.params.platform);
|
||||
}
|
||||
|
||||
// If platform is the same but there are no roms, fetch them
|
||||
if (filteredRoms.value.length == 0) {
|
||||
fetchRoms(route.params.platform);
|
||||
}
|
||||
@@ -154,14 +171,12 @@ onBeforeUnmount(() => {
|
||||
});
|
||||
|
||||
onBeforeRouteLeave((to, from, next) => {
|
||||
// Only reset selection if platform is the same
|
||||
// Reset only the selection if platform is the same
|
||||
if (to.fullPath.includes(from.path)) {
|
||||
romsStore.resetSelection();
|
||||
// Otherwise reset store
|
||||
// Otherwise reset the entire store
|
||||
} else {
|
||||
cursor.value = "";
|
||||
searchCursor.value = "";
|
||||
romsStore.reset();
|
||||
resetGallery();
|
||||
}
|
||||
|
||||
next();
|
||||
@@ -169,11 +184,8 @@ onBeforeRouteLeave((to, from, next) => {
|
||||
|
||||
onBeforeRouteUpdate((to, _) => {
|
||||
// Reset store if switching to another platform
|
||||
cursor.value = "";
|
||||
searchCursor.value = "";
|
||||
romsStore.reset();
|
||||
resetGallery();
|
||||
fetchRoms(to.params.platform);
|
||||
scrolledToTop.value = true;
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -11,8 +11,10 @@ const router = useRouter();
|
||||
const username = ref();
|
||||
const password = ref();
|
||||
const visiblePassword = ref(false);
|
||||
const logging = ref(false);
|
||||
|
||||
function login() {
|
||||
logging.value = true;
|
||||
api
|
||||
.post(
|
||||
"/login",
|
||||
@@ -36,6 +38,9 @@ function login() {
|
||||
icon: "mdi-close-circle",
|
||||
color: "red",
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
logging.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -88,10 +93,20 @@ onBeforeMount(async () => {
|
||||
<v-col cols="10" md="8">
|
||||
<v-btn
|
||||
@click="login()"
|
||||
:disabled="logging"
|
||||
append-icon="mdi-chevron-right-circle-outline"
|
||||
block
|
||||
>Login</v-btn
|
||||
>
|
||||
:loading="logging"
|
||||
>Login
|
||||
<template v-slot:loader>
|
||||
<v-progress-circular
|
||||
color="romm-accent-1"
|
||||
:width="2"
|
||||
:size="20"
|
||||
indeterminate
|
||||
/>
|
||||
</template>
|
||||
</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-col>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "RomM"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
description = "RomM (Rom Manager) is a web based retro roms manager integrated with IGDB."
|
||||
authors = ["zurdi <zurdizurdo25@gmail.com>"]
|
||||
readme = "README.md"
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
<Config Name="ENABLE_EXPERIMENTAL_REDIS" Target="ENABLE_EXPERIMENTAL_REDIS" Default="false" Mode="" Description="Enable Redis (experimental)" Type="Variable" Display="advanced" Required="false" Mask="false"/>
|
||||
<Config Name="REDIS_HOST" Target="REDIS_HOST" Default="127.0.0.1" Mode="" Description="Redis host" Type="Variable" Display="advanced" Required="false" Mask="false"/>
|
||||
<Config Name="REDIS_PORT" Target="REDIS_PORT" Default="6379" Mode="" Description="Redis port" Type="Variable" Display="advanced" Required="false" Mask="false"/>
|
||||
<Config Name="REDIS_PASSWORD" Target="REDIS_PASSWORD" Default="" Mode="" Description="Redis password" Type="Variable" Display="advanced" Required="false" Mask="false"/>
|
||||
<Config Name="ROMM_AUTH_ENABLED" Target="ROMM_AUTH_ENABLED" Default="false" Mode="" Description="Enable authentication" Type="Variable" Display="advanced" Required="false" Mask="false"/>
|
||||
<Config Name="ROMM_AUTH_USERNAME" Target="ROMM_AUTH_USERNAME" Default="admin" Mode="" Description="Default admin username" Type="Variable" Display="advanced" Required="false" Mask="false"/>
|
||||
<Config Name="ROMM_AUTH_PASSWORD" Target="ROMM_AUTH_PASSWORD" Default="" Mode="" Description="Default admin password" Type="Variable" Display="advanced" Required="false" Mask="true"/>
|
||||
|
||||
Reference in New Issue
Block a user