rommapp / romm Goto Github PK
View Code? Open in Web Editor NEWA beautiful, powerful, self-hosted rom manager
Home Page: https://romm.app
License: GNU Affero General Public License v3.0
A beautiful, powerful, self-hosted rom manager
Home Page: https://romm.app
License: GNU Affero General Public License v3.0
Some Games do not get recognized even when they have an entry in the IGDB Database.
The 'Search IGDB' button returns no results and therefore i can not link an IGDB entry to my game.
It would be nice if you could manually pick the IGDB entry.
There could be an additional field in the 'Edit' Section of a game.
(See mock image)
This field would contain just the IGDB ID.
After editing the IGDB ID and applying the new data/cover should be fetched and saved.
Alternatively the 'Search IGDB' button could be improved to allow more filters then just the file name.
Add any other context or screenshots about the feature request here.
I made a quick Mock of how the menu could look like:
Loving the project so far. Thanks for the hard work.
If you are add more sources for game metadata:
Hi,
I looked a round in the issues but couldn't find anything related to my problem.
I played around with romm the last couple of days but I couldn't get the IGDB scraper to work. For every title I search get no results and the logs show this error:
INFO: [ROMM] getting Arkanoid.d64 roms from igdb ... 2023-04-01 13:38:03
INFO: [ROMM] Matched roms for Arkanoid.d64: [{'title': 'Syntax Error', 'status': 400, 'cause': "Expecting a STRING as input, surround your input with quotes starting at ']' expecting {'{', 'f', '(', '[', 'true', 't', 'false', 'null', 'n'"}] 2023-04-01 13:38:03
INFO: 192.168.0.6:0 - "PUT /search/roms/igdb HTTP/1.0" 500 Internal Server Error
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "/usr/local/lib/python3.10/dist-packages/uvicorn/protocols/http/h11_impl.py", line 407, in run_asgi
result = await app( # type: ignore[func-returns-value]
File "/usr/local/lib/python3.10/dist-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
return await self.app(scope, receive, send)
File "/usr/local/lib/python3.10/dist-packages/fastapi/applications.py", line 271, in __call__
await super().__call__(scope, receive, send)
File "/usr/local/lib/python3.10/dist-packages/starlette/applications.py", line 118, in __call__
await self.middleware_stack(scope, receive, send)
File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/errors.py", line 184, in __call__
raise exc
File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/errors.py", line 162, in __call__
await self.app(scope, receive, _send)
File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/cors.py", line 92, in __call__
await self.simple_response(scope, receive, send, request_headers=headers)
File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/cors.py", line 147, in simple_response
await self.app(scope, receive, send)
File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/exceptions.py", line 79, in __call__
raise exc
File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/exceptions.py", line 68, in __call__
await self.app(scope, receive, sender)
File "/usr/local/lib/python3.10/dist-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
raise e
File "/usr/local/lib/python3.10/dist-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
await self.app(scope, receive, send)
File "/usr/local/lib/python3.10/dist-packages/starlette/routing.py", line 706, in __call__
await route.handle(scope, receive, send)
File "/usr/local/lib/python3.10/dist-packages/starlette/routing.py", line 276, in handle
await self.app(scope, receive, send)
File "/usr/local/lib/python3.10/dist-packages/starlette/routing.py", line 66, in app
response = await func(request)
File "/usr/local/lib/python3.10/dist-packages/fastapi/routing.py", line 237, in app
raw_response = await run_endpoint_function(
File "/usr/local/lib/python3.10/dist-packages/fastapi/routing.py", line 163, in run_endpoint_function
return await dependant.call(**values)
File "/back/./main.py", line 101, in search_rom_igdb
return {'data': igdbh.get_matched_roms(data['file_name'], data['p_igdb_id'])}
File "/back/./handler/igdb_handler.py", line 28, in wrapper
return func(*args)
File "/back/./handler/igdb_handler.py", line 125, in get_matched_roms
data=f"fields url; where game={rom['id']};").json()[0]
KeyError: 'id'
The IGDB client_id and secret are working when call in the API with powershell. I'm running version 1.6 in Docker.
Thanks
Faba
I tried running the example compose file and keep getting an error related to a missing bind mount.
failed to deploy a stack: time="2023-03-28T13:30:15Z" level=warning msg="The "Vi" variable is not set. Defaulting to a blank string." Network romm_default Creating Network romm_default Created Container romm_db Creating Container romm_db Created Container romm Creating Container romm Created Container romm_db Starting Error response from daemon: Bind mount failed: '/data/compose/56/config' does not exists
I am guessing this is related to the following:
Also not sure what the undefined Vi variable is
volumes:
- ./config:/config
I tried changing this to
volumes:
- ./volume1/docker/romm:/config
failed to deploy a stack: time="2023-03-28T13:34:24Z" level=warning msg="The "Vi" variable is not set. Defaulting to a blank string." Network romm_default Creating Network romm_default Created Container romm_db Creating Container romm_db Created Container romm Creating Container romm Created Container romm_db Starting Error response from daemon: Bind mount failed: '/data/compose/58/volume1/docker/romm' does not exists
Should I create a config folder inside the data folder? I'd rather have config files in volume1/docker/romm and roms in volume1/data/media/roms
I can see it did actually try to create the database
currently compose file without the sensitive info
`version: '3'
services:
romm:
image: 'zurdi15/romm:latest'
container_name: romm
network_mode: bridge0
environment:
- ROMM_DB_DRIVER="mariadb" # This variable can be set as: mariadb | sqlite. If it is not defined, sqlite will be the database by default
- DB_HOST=romm_db # Only if ROMM_DB_DRIVER='mariadb'
- DB_PORT=3306 # Only if ROMM_DB_DRIVER='mariadb'
- DB_USER=romm-user # Only if ROMM_DB_DRIVER='mariadb'
- DB_PASSWD=alreadychangedthis # Only if ROMM_DB_DRIVER='mariadb'
- CLIENT_ID=gottheclientid
- CLIENT_SECRET=gotthesecretaswell
- STEAMGRIDDB_API_KEY=WIP
volumes:
- ./volume1/data/media/roms:/library
ports:
- '82:80' #80 was in use by pihole. Changed this to 82 on host
depends_on:
- romm_db
restart: "unless-stopped"
romm_db:
image: lscr.io/linuxserver/mariadb:latest
container_name: romm_db
environment:
- MYSQL_ROOT_PASSWORD=changedthisone
- MYSQL_DATABASE=romm
- MYSQL_USER=romm-user
- MYSQL_PASSWORD=alsochangedthisone
volumes:
- ./config:/config #did not change this bind
ports:
- 3306:3306
restart: "unless-stopped"
`
Describe the solution you'd like
Add more useful metadata, like publisher, release date, etc to the game details page
Is your feature request related to a problem? Please describe.
I keep my library read-only, mainly so apps such as this cannot accidentally delete files (either because of an app bug, or my own user error). Currently the docker mounts /library
for games and /library/resources
for image resources related to each game. When mounting the former as RO and the latter as RW, docker will throw an error similar to error mounting to rootfs at read-only file system: unknown
. This is due to adding the RW folder as a subfolder of a RO mount. This can be overcome by adding a folder called "resources" within my game library (but I'd rather not have this empty folder in my host's library mount folder).
Describe the solution you'd like
It would be useful to separate the location of the game library and the downloaded resources. Entirely separate directories would be ideal. Or maybe some setting/config to set the location?
Describe alternatives you've considered
The image assets could also be stored in the DB. Though it could result in DB bloat, and may require some implementation of sqlite VACUUM for deleted/removed games.
Additional context
Great app! Very glad you've shared this with all of us~!
RomM version
v1.5
Describe the bug
Unable to delete rom when using structure folder 1. RomM doesn't find the file
To Reproduce
Expected behavior
RomM should be able to delete the file from the system
please may we have dreamcast in the supported systems so we get a pretty icon in the system list?
Is your feature request related to a problem? Please describe.
Posibility to use a custom cover for each game
It would be cool if the program was able to put different regions and revisions under one game entry. Currently games with multiple regions and revisions have multiple game entries. Some examples of different regions and revisions could be:
-Zelda no Densetsu - Yume o Miru Shima (Japan) (Rev 1).gb
-Zelda no Densetsu - Yume o Miru Shima (Japan).gb
-The Legend of Zelda: Link's Awakening (Europe).gb
I think these should be under the same game entry and then when you click on the game you should be able to choose which revision and region you would like to download. Maybe there should also be a "default" download button, where it chooses a prechosen region (that you can set in the settings) and the latest revision.
Is your feature request related to a problem? Please describe.
When adding a new platform there is no option to just scan the new one.
Can you please insert the version number somewhere?
Maybe nearby the dark/light theme toggle?
So I've followed the example docker compose and deployed it with my Client ID/Secret but for some reason when I try to pull the artwork for a game, it says no results found. Here are my logs from startup to when I get that error:
I'm running the docker container on a server running OMV, and deployed the compose through Portainer if that helps.
When scanning /library/gb/roms/ I encountered the below error and it halted any further scanning:
2023-03-28T15:07:22.973406594Z sqlalchemy.exc.DataError: (mariadb.DataError) Data too long for column 'name' at row 1
2023-03-28T15:07:22.973412167Z [SQL: INSERT INTO roms (filename, filename_no_ext, r_igdb_id, p_igdb_id, r_sgdb_id, p_sgdb_id, name, r_slug, p_slug, summary, path_cover_s, path_cover_l, has_cover, size) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]
2023-03-28T15:07:22.973418529Z [parameters: ('Mani 4 in 1 - R-Type II + Saigo no Nindou + Ganso!! Yancha Maru + Shisenshou - Match-Mania (China) (Ja).zip', 'Mani 4 in 1 - R-Type II + Saigo no Nindou + Ganso!! Yancha Maru + Shisenshou - Match-Mania (China) (Ja)', '', 33, '', '', 'Mani 4 in 1 - R-Type II + Saigo no Nindou + Ganso!! Yancha Maru + Shisenshou - Match-Mania (China) (Ja)', '', 'gb', '', '/assets/library/resources/default/cover_s.png', '/assets/library/resources/default/cover_l.png', 0, '0.21')]
Running via docker with mariadb as defined from the docker-compose in the repo.
I see you have no LICENSE file for this project. The default is copyright.
I would suggest releasing the code under the GPL-3.0-or-later or AGPL-3.0-or-later license so that others are encouraged to contribute changes back to your project.
Describe the solution you'd like
As EmuDeck creates a very specific folders structure, would be nice to be able to scan it with RomM
RomM version
1.6
Describe the bug
RomM doesn't automatically prune headings / directories which are empty. Instead, it leaves it intact with a "0" next to it. Clicking on the empty heading loads a page that says "Feels cold here :( ". I encountered this because initially I created a directory for PlayStation called "ps1" instead of "ps". When I renamed the directory from "ps1" to "ps" then scanned in RomM, it correctly created the PlayStation heading but also left the "ps1" heading as empty.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
If RomM encounters a directory or heading with no roms in it, or cannot find a directory it previously scanned, delete that heading in the application. RomM already deletes the individual rom entries when they're deleted, so this should be extended to headings as well. Currently, there is no way in the UI to remove these empty headings.
Greetings,
I'm Xargon, the founder of RetroDECK and before of that developer on 351ELEC/AmberELEC.
With another developer I recently started a project named RetroMan (https://github.com/RetroMan-project).
Our project just started and we noticed your RomM project and we are interested in it as I found it somehow similar to ours.
RetroMan stands for "Retro Manager", it amis to be a fully pluginable core for managing user's rom libraries.
RetroMan, is focusing on recognizing and syncing the roms on different devices, let's say that you have a miyoo mini and a game boy flahs cart, you can decide which roms (and saves/states) to keep synced in the various devices by having one (or more) main library.
So there will be a "server mode" and a "client" mode to allow the user to use it to catalogue their roms and to manage their physical devices.
Basically every device got two templates: the device template and the physical device file that they are linked together to instruct RetroMan about the device's features, supported systems, folder locations, etc.
These files are yaml that they can always be updated.
Then it can generate gameslists.xml that suits the devices frontend, such as EmulationStation or Onion for example.
It seems like we have similar goals, at least for the server side, so I would like to discuss the evenutality to unify the projects and join our forces to do a single better software and avoid fragmentation.
Feel free to check our page and ask any questions :)
Kindly,
Xargon
i open up some of my services (like overseer / audiobookshelf / calibre-web / komga etc) via cloudflare tunnels, but all these have username / password and user management or some other authentication to help prevent bad actors.
Any plans for something similar here so we can open up to the internet relatively safely?
Was attempting to scan my EmulatorJS library, and after Sega 32X got this error:
romm | WARNING: [ROMM] platform not found in igdb 2023-03-27 20:07:30
romm | INFO: [ROMM] filesystem roms found for sega32x: [] 2023-03-27 20:07:30
romm | INFO: [ROMM] filesystem roms found for sega32x: [] 2023-03-27 20:07:30
romm | INFO: [ROMM] Purge sega32x 2023-03-27 20:07:30
romm | INFO: [ROMM] filesystem roms found for sega32x: [] 2023-03-27 20:07:30
romm | INFO: [ROMM] Getting arcade details 2023-03-27 20:07:30
romm | INFO: 10.0.2.4:0 - "PUT /scan?overwrite=false HTTP/1.0" 500 Internal Server Error
romm | ERROR: Exception in ASGI application
romm | Traceback (most recent call last):
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/protocols/http/h11_impl.py", line 407, in run_asgi
romm | result = await app( # type: ignore[func-returns-value]
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
romm | return await self.app(scope, receive, send)
romm | File "/usr/local/lib/python3.10/dist-packages/fastapi/applications.py", line 271, in __call__
romm | await super().__call__(scope, receive, send)
romm | File "/usr/local/lib/python3.10/dist-packages/starlette/applications.py", line 118, in __call__
romm | await self.middleware_stack(scope, receive, send)
romm | File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/errors.py", line 184, in __call__
romm | raise exc
romm | File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/errors.py", line 162, in __call__
romm | await self.app(scope, receive, _send)
romm | File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/cors.py", line 92, in __call__
romm | await self.simple_response(scope, receive, send, request_headers=headers)
romm | File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/cors.py", line 147, in simple_response
romm | await self.app(scope, receive, send)
romm | File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/exceptions.py", line 79, in __call__
romm | raise exc
romm | File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/exceptions.py", line 68, in __call__
romm | await self.app(scope, receive, sender)
romm | File "/usr/local/lib/python3.10/dist-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
romm | raise e
romm | File "/usr/local/lib/python3.10/dist-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
romm | await self.app(scope, receive, send)
romm | File "/usr/local/lib/python3.10/dist-packages/starlette/routing.py", line 706, in __call__
romm | await route.handle(scope, receive, send)
romm | File "/usr/local/lib/python3.10/dist-packages/starlette/routing.py", line 276, in handle
romm | await self.app(scope, receive, send)
romm | File "/usr/local/lib/python3.10/dist-packages/starlette/routing.py", line 66, in app
romm | response = await func(request)
romm | File "/usr/local/lib/python3.10/dist-packages/fastapi/routing.py", line 237, in app
romm | raw_response = await run_endpoint_function(
romm | File "/usr/local/lib/python3.10/dist-packages/fastapi/routing.py", line 163, in run_endpoint_function
romm | return await dependant.call(**values)
romm | File "/back/./main.py", line 84, in scan
romm | p_igdb_id: str = fastapi.scan_platform(overwrite, p_slug, igdbh, dbh)
romm | File "/back/./utils/fastapi.py", line 24, in scan_platform
romm | p_igdb_id, p_name, url_logo = igdbh.get_platform_details(p_slug)
romm | File "/back/./handler/igdb_handler.py", line 26, in wrapper
romm | return func(*args)
romm | File "/back/./handler/igdb_handler.py", line 40, in get_platform_details
romm | id_logo = res_details['platform_logo']
romm | KeyError: 'platform_logo'
Weird thing is, there are no arcade roms in the arcade/roms dir.
(Edited, i thought sega32x was causing the error, but it's what comes AFTEE sega32x)
Wow for only three weeks since first commit the progress here is nothing short of impressive, well done!
I hate to be the one to add yet another feature request, but this is more of a requirement. You need to be informed about this (if you don't already know), sooner rather than later.
The ROM Management Datafile, is a fairly basic specification, which provides you with everything you need to identify a ROM, like file names, sizes and hashes. The definition also include a name, description and usually also language, region, etc. all the information you need which is difficult or impossible to find from the file name alone. It is also what is traditionally expected from a ROM Manager, by your target audience and competition.
The tool you use to organize your ROMs, the ROM Manager. To rebuild a working ROM set from other collections or unknown files, while ensuring completeness, no corruption, modification, or manipulation. Which is also why it is championed by the preservation community, wanting to ensure every bit and original byte is accounted for. But it also enables you to compile a collection of known working ROMs, in the structure and layout as expected by different emulators.
MAME is particularly tricky, and as time progress more and more systems and their ROMs are being encapsulated by the project. It has already become the de-facto set for PSX ROMs only in a matter months. The problem is not only that their naming convention is obscure, using only a few lower case characters and numbers as file names, with no spaces, but they have three different types of ROMs for the same game(s). The ROMs can be zipped as split, full merged, or non-merged files, which may include one game, or multiple games of separate releases of the same game, or different games of the same type (hardware speaking). They also may or may not include the required BIOS dumps necessary to play the game which means these also need to be managed.
Not only are the dat files necessary to identify the actual game, but it is also required from a ROM Manager to be able to unzip and compile one type from another, as may be needed, to mitigate having to keep duplicates. I have been praying for a web manager, all the others are desktop clients which makes it difficult to combine into any sensible workflow automation, and they are singular in purpose. There is a disconnect between organizing files, and the identifying data contained therein, which is required to source the additional meta data needed to actually manage a library of media content.
These two worlds of organization vs manageability has remained in disconnect, which impairs the archivability of retro games into a singular source library by any definition. Hopefully RomM is here to finally make sense of all the chaos.
Logiqx actually came up with the dat file specification which most projects are using, there is of course always that one, no-intro has a slightly different schema but the content is similar and also well documented. Since it's all XML the data is self explaining anyway. This is not an exhaustive list...
http://www.logiqx.com/Dats/ - legacy sets
https://pleasuredome.github.io/pleasuredome/ - mame sets and others
https://github.com/danmons/datfiles - Mister set
The preservationists each with their own focus and peculiarities but each in their own right indispensable for their work cataloging our history.
http://redump.org - optical discs
https://no-intro.org - cartridges
https://www.tosecdev.org/downloads/category/22-datfiles
There is another one, trurip being rebranded as emuarc, but I am still unable to find their actual dat files, moving on...
Should probably be considered out of scope, more applicable to a lister project for sourcing roms, but for interest sake. The first, catalogs the scene releases of split archive files, the other has defined a specification called srr which catalogs the metadata required to "rescene" the extracted content back to identical split archives again.
https://dats.site
https://www.srrdb.com/
...and other useful technical information to assist with the implementation of dat files.
https://pleasuredome.miraheze.org/wiki/DAT_File
http://www.logiqx.com/DatFAQs/DatCreation.php
https://wiki.no-intro.org/index.php?title=DAT-o-MATIC_Guide
https://www.oreilly.com/library/view/gaming-hacks/0596007140/ch01s13.html
The missing link which ties ROM files to their meta data, countless hours by a vast community capturing and cataloging this information, a saving grace unavailable to any other type of media.
It would be nice to have an 'all games' option at the top of the system list, so you can see everything in your library at once
Is your feature request related to a problem? Please describe.
Posibility to add games directly from RomM interface
Sorry, it's me again :)
RomM version
docker:1.5
Describe the bug
Download of a roms always stops at 411kb
To Reproduce
Steps to reproduce the behavior:
Expected behavior
The file is downloaded in its full size.
Desktop (please complete the following information):
RomM version
V1.5
Describe the bug
When attempting to load a platform with a large number of entries, there is a huge lag.
700 entries: takes 1-5 seconds, loads smoothly
8500 entires: takes 60+ seconds, sometimes Chrome will prompt to terminate the tab. Scrolling down quickly seems to lazy load the image for each game (in this case, 'cover missing' for most of them).
To Reproduce
Expected behavior
It would be nice if large collections could be loaded lazily, instead of the page trying to fetch every game at once. Actually, the implementation doesn't really matter - I'd just like the page to load faster, even if the cover images load in later.
Desktop (please complete the following information):
Windows 10, Chrome v109.0.5414.75
I wonder if it would be possible to play games directly in the browser. Could be coupled with EmulatorJS.
This would make it awesome for parents with their kids, where they can just add a shortcut to RomM somehwere on their systems and they can just open it, pick a game an play.
Describe the bug
On a fresh container stood up using a lightly modified version of the provided docker-compose.yml (see below for the docker compose I'm using), I'm seeing an error and RomM isn't able to find the roms I've put in the library directory.
Error from the container logs:
To Reproduce
The error in the container logs seems to only show up on boot/reboot of the RomM container, while the error in the RomM webpage shows up anytime I click the "Scan" button.
Expected behavior
The roms that I've placed in the library directory should be showing up in the RomM web console (web page?).
Additional context
The library directory structure is following the exact requirements shown in the instructions. For example, I have one rom loaded as this: /library/gbc/roms/Pokemon_YellowVersion.gbc
The docker-compose.yml (only passwords and api keys omitted)
version: '3'
services:
romm:
image: 'zurdi15/romm:latest'
container_name: romm
environment:
- ROMM_DB_DRIVER="mariadb"
- DB_HOST=romm_db
- DB_PORT=3306
- DB_USER=romm-user
- DB_NAME=romm
- DB_PASSWD=
- CLIENT_ID=
- CLIENT_SECRET=
volumes:
- '/host/path/to/romm:/library'
ports:
- 8080:80
depends_on:
- romm_db
restart: 'unless-stopped'
romm_db:
image: lscr.io/linuxserver/mariadb:latest
container_name: romm_db
environment:
- MYSQL_ROOT_PASSWORD=
- MYSQL_DATABASE=romm
- MYSQL_USER=romm-user
- MYSQL_PASSWORD=
volumes:
- ./config:/config
ports:
- 3306:3306
restart: 'unless-stopped'
Describe the bug
When I start romm via docker compose in sqlite mode I get this errors:
[+] Running 1/1
⠿ Container romm Recreated 0.5s
Attaching to romm
romm | INFO: Uvicorn running on http://0.0.0.0:5000 (Press CTRL+C to quit)
romm | INFO: Started parent process [10]
romm | Process SpawnProcess-3:
romm | Traceback (most recent call last):
romm | File "/usr/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap
romm | self.run()
romm | File "/usr/lib/python3.10/multiprocessing/process.py", line 108, in run
romm | self._target(*self._args, **self._kwargs)
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/_subprocess.py", line 76, in subprocess_started
romm | target(sockets=sockets)
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/server.py", line 60, in run
romm | return asyncio.run(self.serve(sockets=sockets))
romm | File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run
romm | return loop.run_until_complete(main)
romm | File "/usr/lib/python3.10/asyncio/base_events.py", line 646, in run_until_complete
romm | return future.result()
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/server.py", line 67, in serve
romm | config.load()
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/config.py", line 477, in load
romm | self.loaded_app = import_from_string(self.app)
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/importer.py", line 21, in import_from_string
romm | module = importlib.import_module(module_str)
romm | File "/usr/lib/python3.10/importlib/__init__.py", line 126, in import_module
romm | return _bootstrap._gcd_import(name[level:], package, level)
romm | File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
romm | File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
romm | File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
romm | File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
romm | File "<frozen importlib._bootstrap_external>", line 883, in exec_module
romm | File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
romm | File "/back/./main.py", line 5, in <module>
romm | from handler.igdb_handler import IGDBHandler
romm | File "/back/./handler/igdb_handler.py", line 8, in <module>
romm | from config.config import CLIENT_ID, CLIENT_SECRET
romm | File "/back/./config/config.py", line 28, in <module>
romm | DB_PORT: int = int(os.getenv('DB_PORT'))
romm | TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'
romm | Process SpawnProcess-1:
romm | Traceback (most recent call last):
romm | File "/usr/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap
romm | self.run()
romm | File "/usr/lib/python3.10/multiprocessing/process.py", line 108, in run
romm | self._target(*self._args, **self._kwargs)
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/_subprocess.py", line 76, in subprocess_started
romm | target(sockets=sockets)
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/server.py", line 60, in run
romm | return asyncio.run(self.serve(sockets=sockets))
romm | File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run
romm | return loop.run_until_complete(main)
romm | File "/usr/lib/python3.10/asyncio/base_events.py", line 646, in run_until_complete
romm | return future.result()
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/server.py", line 67, in serve
romm | config.load()
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/config.py", line 477, in load
romm | self.loaded_app = import_from_string(self.app)
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/importer.py", line 21, in import_from_string
romm | module = importlib.import_module(module_str)
romm | File "/usr/lib/python3.10/importlib/__init__.py", line 126, in import_module
romm | return _bootstrap._gcd_import(name[level:], package, level)
romm | File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
romm | File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
romm | File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
romm | File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
romm | File "<frozen importlib._bootstrap_external>", line 883, in exec_module
romm | File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
romm | File "/back/./main.py", line 5, in <module>
romm | from handler.igdb_handler import IGDBHandler
romm | File "/back/./handler/igdb_handler.py", line 8, in <module>
romm | from config.config import CLIENT_ID, CLIENT_SECRET
romm | File "/back/./config/config.py", line 28, in <module>
romm | DB_PORT: int = int(os.getenv('DB_PORT'))
romm | TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'
romm | Process SpawnProcess-4:
romm | Traceback (most recent call last):
romm | File "/usr/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap
romm | self.run()
romm | File "/usr/lib/python3.10/multiprocessing/process.py", line 108, in run
romm | self._target(*self._args, **self._kwargs)
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/_subprocess.py", line 76, in subprocess_started
romm | target(sockets=sockets)
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/server.py", line 60, in run
romm | return asyncio.run(self.serve(sockets=sockets))
romm | File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run
romm | return loop.run_until_complete(main)
romm | File "/usr/lib/python3.10/asyncio/base_events.py", line 646, in run_until_complete
romm | return future.result()
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/server.py", line 67, in serve
romm | config.load()
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/config.py", line 477, in load
romm | self.loaded_app = import_from_string(self.app)
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/importer.py", line 21, in import_from_string
romm | module = importlib.import_module(module_str)
romm | File "/usr/lib/python3.10/importlib/__init__.py", line 126, in import_module
romm | return _bootstrap._gcd_import(name[level:], package, level)
romm | File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
romm | File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
romm | File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
romm | File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
romm | File "<frozen importlib._bootstrap_external>", line 883, in exec_module
romm | File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
romm | File "/back/./main.py", line 5, in <module>
romm | from handler.igdb_handler import IGDBHandler
romm | File "/back/./handler/igdb_handler.py", line 8, in <module>
romm | from config.config import CLIENT_ID, CLIENT_SECRET
romm | File "/back/./config/config.py", line 28, in <module>
romm | DB_PORT: int = int(os.getenv('DB_PORT'))
romm | TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'
romm | Process SpawnProcess-2:
romm | Traceback (most recent call last):
romm | File "/usr/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap
romm | self.run()
romm | File "/usr/lib/python3.10/multiprocessing/process.py", line 108, in run
romm | self._target(*self._args, **self._kwargs)
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/_subprocess.py", line 76, in subprocess_started
romm | target(sockets=sockets)
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/server.py", line 60, in run
romm | return asyncio.run(self.serve(sockets=sockets))
romm | File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run
romm | return loop.run_until_complete(main)
romm | File "/usr/lib/python3.10/asyncio/base_events.py", line 646, in run_until_complete
romm | return future.result()
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/server.py", line 67, in serve
romm | config.load()
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/config.py", line 477, in load
romm | self.loaded_app = import_from_string(self.app)
romm | File "/usr/local/lib/python3.10/dist-packages/uvicorn/importer.py", line 21, in import_from_string
romm | module = importlib.import_module(module_str)
romm | File "/usr/lib/python3.10/importlib/__init__.py", line 126, in import_module
romm | return _bootstrap._gcd_import(name[level:], package, level)
romm | File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
romm | File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
romm | File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
romm | File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
romm | File "<frozen importlib._bootstrap_external>", line 883, in exec_module
romm | File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
romm | File "/back/./main.py", line 5, in <module>
romm | from handler.igdb_handler import IGDBHandler
romm | File "/back/./handler/igdb_handler.py", line 8, in <module>
romm | from config.config import CLIENT_ID, CLIENT_SECRET
romm | File "/back/./config/config.py", line 28, in <module>
romm | DB_PORT: int = int(os.getenv('DB_PORT'))
romm | TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'
If I try to scan me roms folder I get " Couldn't complete scan. Something went wrong...".
To Reproduce
Steps to reproduce the behavior:
Desktop (please complete the following information):
Would love to run this without having to deploy a full mariadb container to run it.
Wanted to just put in a quick request for SQLite support, will also look into the code and see if I can just PR it.
Thanks!
Hi Zurdi,
You asked me to open an issue on unzipping files. I think this can both be done on the server side or in the browser. I think it is worth noting that this will cause a delay in the download process (especially for large files).
Is your feature request related to a problem? Please describe.
Some games have different localized names so it would be nice to search for all of them when scanning the library
how should we handle games with more than one disk?
e.g,. Alone in the Dark has two disks
i tried
> games
>> dc
>>> roms
>>>> Alone in the Dark
>>>>> Alone in the Dark - The New Nightmare (USA) (Disc 1).chd
>>>>> Alone in the Dark - The New Nightmare (USA) (Disc 2).chd
but nothing showed up after scanning the folder from the front end. So i tried taking them out of the subfolder and put both disks in the roms folder, thus...
> games
>> dc
>>> roms
>>>>> Alone in the Dark - The New Nightmare (USA) (Disc 1).chd
>>>>> Alone in the Dark - The New Nightmare (USA) (Disc 2).chd
...but now I have two entries for one game in the front end.
What's the correct way to handle these?
RomM version
docker:latest
Describe the bug
Scan is broken after the systems update
To Reproduce
Steps to reproduce the behavior:
Expected behavior
Roms are scanned
Desktop (please complete the following information):
in case there are any other apple users out out there, i just worked out to make RomM act like an app.
Originally, I just added a safari link to 192.168.1.XXX:4044 but the icon it created from the site was a bit ugly and incoherent.
But if you
now you have a nice app-looking link to your game library
It would be great to have a single button or automated way to rename a rom or roms based on the matching IGDB results.
I know you can come up with a better name for this than 'ROM Manager'. C'mon man, this is a really great app and you need a better name to go with it :)
Maybe we can brainstorm it in this thread.
Is your feature request related to a problem? Please describe.
It would be nice if we could set our own folder structure. Allowing some sort of mapping schema would allow for more people to easily use this project without having to modify their existing folder structure. For example, I personally don't use a 'rom' folder like you do. I think someone mentioned something similar on the reddit thread, but I didn't see a github issue.
Personally I use the following structure:
library/
├─ gbc/
│ ├─ rom_1.gbc
│ ├─ rom_1.sav
│ ├─ rom_1.sav1
│ ├─ rom_2.gbc
|
├─ switch/
│ ├─ rom_1
│ ├─ rom_1.xci
│ ├─ rom_1.nsp
│ ├─ rom_2.xci
|
├─ pc/
│ ├─ game_1/
│ ├─ game_1.iso
│ ├─ game_1_patch.exe
│ ├─ game_2/
│ ├─ soundtrack/
│ ├─ song_1.mp3
│ ├─ song_2.mp3
│ ├─ game_2.iso
│ ├─ game_2_patch.exe
│ ├─ random1_game.iso
│ ├─ random2_game.7z
│ ├─ random3_game.rar
Describe the solution you'd like
I'd like to have a more dynamic method of linking folders/files to game entries. Additionally it could be useful to exclude certain files/folders (eg: the 'soundtrack' folder in my example above)
Appreciate you making this app and sharing it with us!
Plex has the useful ability to fix occasions when a movie will stubbornly refused to find its match on IMDB by letting you search by the IMDB id instead of the movie name, like so:
I have several roms which, for reasons I can't work out, refuse to be matched on IGDB so it would be useful to be able to do the same here. I see the search already drags in the IGDB id when matching.
Pretty simple issue. Seems like .iso files are not recognized as gamecube roms. Either that or wrong folder name? Its supposed to be ngc right?
Is your feature request related to a problem? Please describe.
Posibility to manage (download and upload) different savefiles/states for each game
Is your feature request related to a problem? Please describe.
Unfortunately it doesn't appear gamecube roms are compatible with romM. At least as far as grabbing metadata from IGDB goes.
Describe the solution you'd like
Support for GC roms. It should be possible since the platform is on IGDB.
Describe alternatives you've considered
N/A
Thanks!
After encountering the issue from #41, I removed the long titled file from the folder and now the application cannot complete any scans.
Running via Docker with MariaDB using the repo docker-compose.
2023-03-28T15:11:06.144462222Z INFO: [ROMM] complete scaning... 2023-03-28 15:11:06
2023-03-28T15:11:09.402536345Z INFO: 192.168.3.20:0 - "PUT /scan?overwrite=false HTTP/1.0" 500 Internal Server Error
2023-03-28T15:11:09.403992018Z ERROR: Exception in ASGI application
2023-03-28T15:11:09.404010984Z Traceback (most recent call last):
2023-03-28T15:11:09.404017252Z File "/usr/local/lib/python3.10/dist-packages/uvicorn/protocols/http/h11_impl.py", line 407, in run_asgi
2023-03-28T15:11:09.404024262Z result = await app( # type: ignore[func-returns-value]
2023-03-28T15:11:09.404029798Z File "/usr/local/lib/python3.10/dist-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
2023-03-28T15:11:09.404035526Z return await self.app(scope, receive, send)
2023-03-28T15:11:09.404041126Z File "/usr/local/lib/python3.10/dist-packages/fastapi/applications.py", line 271, in __call__
2023-03-28T15:11:09.404046971Z await super().__call__(scope, receive, send)
2023-03-28T15:11:09.404052379Z File "/usr/local/lib/python3.10/dist-packages/starlette/applications.py", line 118, in __call__
2023-03-28T15:11:09.404058346Z await self.middleware_stack(scope, receive, send)
2023-03-28T15:11:09.404063790Z File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/errors.py", line 184, in __call__
2023-03-28T15:11:09.404070074Z raise exc
2023-03-28T15:11:09.404075548Z File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/errors.py", line 162, in __call__
2023-03-28T15:11:09.404081245Z await self.app(scope, receive, _send)
2023-03-28T15:11:09.404086719Z File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/cors.py", line 92, in __call__
2023-03-28T15:11:09.404092452Z await self.simple_response(scope, receive, send, request_headers=headers)
2023-03-28T15:11:09.404097926Z File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/cors.py", line 147, in simple_response
2023-03-28T15:11:09.404103644Z await self.app(scope, receive, send)
2023-03-28T15:11:09.404109017Z File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/exceptions.py", line 79, in __call__
2023-03-28T15:11:09.404114703Z raise exc
2023-03-28T15:11:09.404139975Z File "/usr/local/lib/python3.10/dist-packages/starlette/middleware/exceptions.py", line 68, in __call__
2023-03-28T15:11:09.404146086Z await self.app(scope, receive, sender)
2023-03-28T15:11:09.404151377Z File "/usr/local/lib/python3.10/dist-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
2023-03-28T15:11:09.404156983Z raise e
2023-03-28T15:11:09.404162013Z File "/usr/local/lib/python3.10/dist-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
2023-03-28T15:11:09.404167773Z await self.app(scope, receive, send)
2023-03-28T15:11:09.404173233Z File "/usr/local/lib/python3.10/dist-packages/starlette/routing.py", line 706, in __call__
2023-03-28T15:11:09.404178907Z await route.handle(scope, receive, send)
2023-03-28T15:11:09.404185167Z File "/usr/local/lib/python3.10/dist-packages/starlette/routing.py", line 276, in handle
2023-03-28T15:11:09.404190749Z await self.app(scope, receive, send)
2023-03-28T15:11:09.404196111Z File "/usr/local/lib/python3.10/dist-packages/starlette/routing.py", line 66, in app
2023-03-28T15:11:09.404201606Z response = await func(request)
2023-03-28T15:11:09.404206835Z File "/usr/local/lib/python3.10/dist-packages/fastapi/routing.py", line 237, in app
2023-03-28T15:11:09.404212453Z raw_response = await run_endpoint_function(
2023-03-28T15:11:09.404217743Z File "/usr/local/lib/python3.10/dist-packages/fastapi/routing.py", line 163, in run_endpoint_function
2023-03-28T15:11:09.404223411Z return await dependant.call(**values)
2023-03-28T15:11:09.404228612Z File "/back/./main.py", line 82, in scan
2023-03-28T15:11:09.404233924Z platforms = data['platforms'] if data['platforms'] else fs.get_platforms()
2023-03-28T15:11:09.404239531Z File "/back/./utils/fs.py", line 76, in get_platforms
2023-03-28T15:11:09.404245018Z [platforms.remove(reserved) for reserved in RESERVED_FOLDERS]
2023-03-28T15:11:09.404250402Z File "/back/./utils/fs.py", line 76, in <listcomp>
2023-03-28T15:11:09.404257271Z [platforms.remove(reserved) for reserved in RESERVED_FOLDERS]
2023-03-28T15:11:09.404262638Z ValueError: list.remove(x): x not in list
At the moment, it is only possible to see if a download has started via the dev-tools of the browser.
This isn't a problem with small files like GBA games or similar ones where it pops up relatively fast in the browser downloads, but when it goes to PS2 or Switch Games for instance, it would be nice to see a notification that the Download started.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.