Skip to content

Commit

Permalink
Merge branch 'master' into typescript-frontend
Browse files Browse the repository at this point in the history
  • Loading branch information
zurdi15 authored Jan 3, 2024
2 parents 0772882 + c027d7a commit b6da52b
Show file tree
Hide file tree
Showing 57 changed files with 109 additions and 48 deletions.
122 changes: 80 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,26 @@
<div align="center">
<h1><img src="https://github.com/raw/zurdi15/romm/release/.github/resources/romm.svg" height="220px" width="auto" alt="RomM Logo"></h1>
<img alt="GitHub" src="https://img.shields.io/github/license/zurdi15/romm?style=flat-square">
<img alt="GitHub release (latest SemVer)" src="https://img.shields.io/github/v/release/zurdi15/romm?style=flat-square">
<img alt="GitHub Workflow Status (with branch)" src="https://img.shields.io/github/actions/workflow/status/zurdi15/romm/build.yml?style=flat-square&branch=master">
</div>
<div align="center">
<a href="https://hub.docker.com/r/zurdi15/romm">
<img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/zurdi15/romm?style=flat-square">
</a>
<a href="https://hub.docker.com/r/zurdi15/romm">
<img alt="Docker Image Size (latest by date)" src="https://img.shields.io/docker/image-size/zurdi15/romm?style=flat-square">
</a>
<a href="https://discord.gg/P5HtHnhUDH">
<img alt="Discord" src="https://img.shields.io/discord/1138838206532554853?logo=discord&style=flat-square&label=Discord">
</a>
</div>
<h1><img src=".github/resources/romm.svg" height="220px" width="auto" alt="RomM Logo"></h1>

<br>
[![license-badge]][license-url]
[![build-badge]][build-url]
[![release-badge]][release-url]<br>
[![docker-pulls-badge]][docker-pulls-url]
[![docker-image-size-badge]][docker-image-size-url]

[![unraid-badge]][unraid-url]
[![wiki-badge]][wiki-url]

[![discord-badge]][discord-url]

[![coffee-badge]][coffee-url]

<div align="center">
<a href="https://www.buymeacoff.ee/zurdi15" target="_blank">
<img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" target="_blank">
</a>
</div>

# Overview

RomM (**ROM M**anager) is a game library manager focused on retro gaming. It enables you to efficiently manage and organize all your games from a web browser.

Inspired by [Jellyfin](https://jellyfin.org/), RomM allows you to handle all your games through a modern interface while enhancing them with IGDB metadata.
Inspired by [Jellyfin][jellyfin-url], RomM allows you to handle all your games through a modern interface while enhancing them with IGDB metadata.

## ⚡ Features

Expand All @@ -49,26 +41,21 @@ Inspired by [Jellyfin](https://jellyfin.org/), RomM allows you to handle all you

## 🖥 Desktop

<img src="https://github.com/raw/zurdi15/romm/release/.github/resources/screenshots/romm-desktop-slider.gif" />
![desktop-preview]

## 📱 Mobile

<img style="height: 600px;" src="https://github.com/raw/zurdi15/romm/release/.github/resources/screenshots/romm-mobile-slider.gif" />

# The RomM Community

<a href="https://discord.gg/P5HtHnhUDH"><img src="https://github.com/raw/zurdi15/romm/release/.github/resources/discord_banner.png" height="100px" width="auto" style="margin-top: 5px;" alt="discord-banner" /></a>
<a href="https://github.com/zurdi15/romm/wiki"><img src="https://github.com/raw/zurdi15/romm/release/.github/resources/wiki_banner.png" height="100px" width="auto" alt="wiki-banner" /></a>
<img style="height: 600px;" src=".github/resources/screenshots/romm-mobile-slider.gif" />

# Installation

## 🐳 Docker

Before running the [image](https://hub.docker.com/r/zurdi15/romm/tags), ensure that Docker is installed and set up.
Before running the [image][docker-tags], ensure that Docker is installed and set up.

1. Generate an API key for [IGDB](https://www.igdb.com/) and set the `IGDB_CLIENT_ID` and `IGDB_CLIENT_SECRET` variables. This step is essential for running a library scan. Instructions for generating the ID and Secret can be found [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 [folder structure](#-folder-structure) section.
3. Create a docker-compose file. Refer to the example [docker-compose.yml](examples/docker-compose.example.yml) file for guidance. Customize it for your setup and include the `IGDB_CLIENT_ID` and `IGDB_CLIENT_SECRET` variables in the environment section of the file.
1. Generate an API key for [IGDB][igdb] and set the `IGDB_CLIENT_ID` and `IGDB_CLIENT_SECRET` variables. This step is essential for running a library scan. Instructions for generating the ID and Secret can be found [here][igdb-api]. 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 [folder structure][folder-structure] section.
3. Create a docker-compose file. Refer to the example [docker-compose.yml][docker-compose-example] file for guidance. Customize it for your setup and include the `IGDB_CLIENT_ID` and `IGDB_CLIENT_SECRET` variables in the environment section of the file.
4. Launch the container:

```bash
Expand All @@ -81,7 +68,7 @@ docker-compose up -d

RomM accepts two different folder structures by priority. RomM will attempt to find structure 1, and if it doesn't exist, it will look for structure 2.

For device naming conventions, review the [Platforms Support](#-platform-support) section. To override default system names in the folder structure (if your directories are named differently), see the [Configuration File](#%EF%B8%8F-configuration-file) section.
For device naming conventions, review the [Platforms Support][platforms-support] section. To override default system names in the folder structure (if your directories are named differently), see the [Configuration File][configuration-file] section.

### Structure A (high-priority)

Expand Down Expand Up @@ -135,11 +122,11 @@ library/

RomM can be configured through a YAML file. To apply configuration changes, you must restart RomM.

Refer to the [config.example.yml](https://github.com/zurdi15/romm/blob/release/examples/config.example.yml) file and the [docker-compose.example.yml](https://github.com/zurdi15/romm/blob/release/examples/docker-compose.example.yml) for guidance on how to configure it.
Refer to the [config.example.yml][configuration-file-example] file and the [docker-compose.example.yml][docker-compose-example] for guidance on how to configure it.

## 🔒 Authentication

If you want to enable the user management system, a redis container and some environment variables needs to be set. Complete instructions are available in the [wiki](https://github.com/zurdi15/romm/wiki/Authentication).
If you want to enable the user management system, a redis container and some environment variables needs to be set. Complete instructions are available in the [wiki][wiki-authentication-url].

## 📅 Scheduler

Expand All @@ -162,7 +149,7 @@ Users can opt to enable scheduled rescans, and set the interval using cron notat

### Switch titleDB update

Support was added for Nintendo Switch ROMs with filenames using the [titleid/programid format](https://switchbrew.org/w/index.php?title=Title_list/Games&mobileaction=toggle_view_desktop) (e.g. 0100000000010000.xci). If a file under the `switch` folder matches the regex, the scanner will use the index to attempt to match it to a game. If a match is found, the IGDB handler will use the matched name as the search term.
Support was added for Nintendo Switch ROMs with filenames using the [titleid/programid format][titleid-program-id-url] (e.g. 0100000000010000.xci). If a file under the `switch` folder matches the regex, the scanner will use the index to attempt to match it to a game. If a match is found, the IGDB handler will use the matched name as the search term.

The associated task updates the `/fixtures/switch_titledb.json` file at a regular interval to support new game releases.

Expand Down Expand Up @@ -191,7 +178,7 @@ When a change is detected, a scan will be scheduled for sometime in the future (

## 🎮 Platform Support

If you adhere to the [RomM folder structure](#-folder-structure), RomM supports any platform listed in the [IGDB platforms list](https://www.igdb.com/platforms). RomM will retrieve game information, metadata, and covers for platforms in that list. Additionally, some of these platforms have custom icons available ([learn more about platform icons in our wiki](https://github.com/zurdi15/romm/wiki/Custom-Platform-Icons)).
If you adhere to the [RomM folder structure][folder-structure], RomM supports any platform listed in the [IGDB platforms list][igdb-platforms-list]. RomM will retrieve game information, metadata, and covers for platforms in that list. Additionally, some of these platforms have custom icons available ([learn more about platform icons in our wiki][wiki-platforms-icons-url]).

## 📑 Tag Support

Expand All @@ -208,10 +195,61 @@ Games can be tagged with region, revision, or other tags by using parentheses in

Here are a few projects maintained by members of our community. As they are not regularly reviewed by the RomM team, **we recommend you closely review them before use**.

* CasaOS app via the [BigBear App Store](https://github.com/bigbeartechworld/big-bear-casaos)
* [Helm Chart to deploy on Kubernetes](https://artifacthub.io/packages/helm/crystalnet/romm) by @psych0d0g
* CasaOS app via the [BigBear App Store][big-bear-casaos]
* [Helm Chart to deploy on Kubernetes][kubernetes-helm-chart] by @psych0d0g

# 🎖 Credits

- Pc and Mac icon support - <a href="https://www.flaticon.com/free-icons/keyboard-and-mouse" title="Keyboard and mouse icons">Keyboard and mouse icons created by Flat Icons - Flaticon</a>
- Default user icon - <a target="_blank" href="https://icons8.com/icon/tZuAOUGm9AuS/user-default">User Default</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a>
- Pc and Mac icons - [Keyboard and mouse][pc-mac-icons] icons by [Flaticon][flaticon]
- Default user icon - [User Default][user-default-icon] icon by [Icons8][icons8]

<!-- Sections -->
[folder-structure]: #-folder-structure
[platforms-support]: #-platform-support
[configuration-file]: #%EF%B8%8F-configuration-file

<!-- Files -->
[docker-compose-example]: examples/docker-compose.example.yml
[configuration-file-example]: examples/config.example.yml

<!-- Wiki links -->
[wiki-url]: https://github.com/zurdi15/romm/wiki
[wiki-authentication-url]: https://github.com/zurdi15/romm/wiki/Authentication
[wiki-platforms-icons-url]: https://github.com/zurdi15/romm/wiki/Custom-Platform-Icons

<!-- Badges -->
[license-badge]: https://img.shields.io/github/license/zurdi15/romm?style=flat-square
[release-badge]: https://img.shields.io/github/v/release/zurdi15/romm?style=flat-square
[build-badge]: https://img.shields.io/github/actions/workflow/status/zurdi15/romm/build.yml?style=flat-square&branch=master
[docker-pulls-badge]: https://img.shields.io/docker/pulls/zurdi15/romm?style=flat-square
[docker-image-size-badge]: https://img.shields.io/docker/image-size/zurdi15/romm?style=flat-square
[unraid-badge]: https://img.shields.io/badge/Unraid-f57842?style=for-the-badge
[wiki-badge]: https://img.shields.io/badge/Wiki-736e9b?style=for-the-badge
[discord-badge]: https://invidget.switchblade.xyz/P5HtHnhUDH
[coffee-badge]: https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png

<!-- Previews -->
[desktop-preview]: .github/resources/screenshots/romm-desktop-slider.gif
[mobile-preview]: .github/resources/screenshots/romm-mobile-slider.gif

<!-- External links -->
[license-url]: LICENSE
[release-url]: https://github.com/zurdi15/romm/releases
[build-url]: https://github.com/zurdi15/romm/actions/workflows/build.yml
[docker-pulls-url]: https://hub.docker.com/r/zurdi15/romm
[docker-image-size-url]: https://hub.docker.com/r/zurdi15/romm
[unraid-url]: https://forums.unraid.net/topic/149738-support-eurotimmy-romm-rom-manager-by-zurdi15/
[discord-url]: https://discord.gg/P5HtHnhUDH
[coffee-url]: https://www.buymeacoff.ee/zurdi15
[jellyfin-url]: https://jellyfin.org/
[docker-tags]: https://hub.docker.com/r/zurdi15/romm/tags
[igdb]: https://www.igdb.com/
[igdb-api]: https://api-docs.igdb.com/#getting-started
[titleid-program-id-url]: https://switchbrew.org/w/index.php?title=Title_list/Games&mobileaction=toggle_view_desktop
[igdb-platforms-list]: https://www.igdb.com/platforms
[big-bear-casaos]: https://github.com/bigbeartechworld/big-bear-casaos
[kubernetes-helm-chart]: https://artifacthub.io/packages/helm/crystalnet/romm
[pc-mac-icons]: https://www.flaticon.com/free-icons/keyboard-and-mouse
[flaticon]: https://www.flaticon.com
[user-default-icon]: https://icons8.com/icon/tZuAOUGm9AuS/user-default
[icons8]: https://icons8.com
18 changes: 15 additions & 3 deletions backend/handler/igdb_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,18 +165,21 @@ def _search_screenshots(self, rom_id: int) -> list:
@staticmethod
async def _ps2_opl_format(match: re.Match[str], search_term: str) -> str:
serial_code = match.group(1)

with open(PS2_OPL_INDEX_FILE, "r") as index_json:
opl_index = json.loads(index_json.read())
index_entry = opl_index.get(serial_code, None)
if index_entry:
search_term = index_entry["Name"] # type: ignore

return search_term


@staticmethod
async def _switch_titledb_format(match: re.Match[str], search_term: str) -> str:
title_id = match.group(1)
titledb_index = {}
title_id = match.group(1)

try:
with open(SWITCH_TITLEDB_INDEX_FILE, "r") as index_json:
titledb_index = json.loads(index_json.read())
Expand All @@ -192,12 +195,19 @@ async def _switch_titledb_format(match: re.Match[str], search_term: str) -> str:
index_entry = titledb_index.get(title_id, None)
if index_entry:
search_term = index_entry["name"] # type: ignore

return search_term

@staticmethod
async def _switch_productid_format(match: re.Match[str], search_term: str) -> str:
product_id = match.group(1)
product_id_index = {}
product_id = match.group(1)

# Game updates have the same product ID as the main application, except with bitmask 0x800 set
product_id = list(product_id)
product_id[-3] = '0'
product_id = ''.join(product_id)

try:
with open(SWITCH_PRODUCT_ID_FILE, "r") as index_json:
product_id_index = json.loads(index_json.read())
Expand All @@ -218,6 +228,7 @@ async def _switch_productid_format(match: re.Match[str], search_term: str) -> st
@staticmethod
async def _mame_format(search_term: str) -> str:
mame_index = {"menu": {"game": []}}

try:
with open(MAME_XML_FILE, "r") as index_xml:
mame_index = xmltodict.parse(index_xml.read())
Expand All @@ -240,6 +251,7 @@ async def _mame_format(search_term: str) -> str:
search_term = get_search_term(
index_entry[0].get("description", search_term)
)

return search_term

@check_twitch_token
Expand Down Expand Up @@ -268,7 +280,7 @@ async def get_rom(self, file_name: str, platform_idgb_id: int) -> IGDBRomType:
search_term = await self._ps2_opl_format(match, search_term)

# Support for switch titleID filename format
match = re.match(SWITCH_TITLEDB_REGEX, file_name)
match = re.search(SWITCH_TITLEDB_REGEX, file_name)
if platform_idgb_id == SWITCH_IGDB_ID and match:
search_term = await self._switch_titledb_format(match, search_term)

Expand Down
15 changes: 13 additions & 2 deletions backend/utils/fs.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,20 @@ def _exclude_files(files, filetype) -> list[str]:
filtered_files: list = []

for file in files:
if file.split(".")[-1] in excluded_extensions or file in excluded_names:
# Exclude files starting with a period.
if file.startswith('.'):
filtered_files.append(file)

else:
# Split the file name to get the extension.
parts = file.split(".")
# Exclude the file if it has no extension or the extension is in the excluded list.
if len(parts) == 1 or parts[-1] in excluded_extensions:
filtered_files.append(file)
# Additionally, check if the entire file name is in the excluded names list.
elif file in excluded_names:
filtered_files.append(file)

# Return files that are not in the filtered list.
return [f for f in files if f not in filtered_files]


Expand Down
Binary file added frontend/assets/webrcade/feed/2600-background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/webrcade/feed/2600-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/webrcade/feed/3do-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/webrcade/feed/5200-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/webrcade/feed/7800-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/webrcade/feed/arcade-thum.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/webrcade/feed/arcade-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/webrcade/feed/atari5200-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/webrcade/feed/coleco-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/webrcade/feed/genesis-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/webrcade/feed/neogeo-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/webrcade/feed/neogeocd-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/webrcade/feed/ngc-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/webrcade/feed/ngp-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/webrcade/feed/pce-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/assets/webrcade/feed/pcecd-thumb.png
Binary file added frontend/assets/webrcade/feed/pcecd.png
Binary file added frontend/assets/webrcade/feed/pcfx-thumb.png
Binary file added frontend/assets/webrcade/feed/ps-thumb.png
Binary file added frontend/assets/webrcade/feed/psx-thumb.png
Binary file added frontend/assets/webrcade/feed/quake-thumb.png
Binary file added frontend/assets/webrcade/feed/scummvm-thumb.png
Binary file added frontend/assets/webrcade/feed/segacd-thumb.png
Binary file added frontend/assets/webrcade/feed/sg1000-thumb.png
Binary file added frontend/assets/webrcade/feed/sgx-thumb.png
Binary file added frontend/assets/webrcade/feed/vb-thumb.png
Binary file added frontend/assets/webrcade/feed/ws-thumb.png
2 changes: 1 addition & 1 deletion frontend/src/components/Details/VersionSwitcher.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function formatItem(rom: RomSchema) {
const langs = rom.languages.map((l) => languageToEmoji(l)).join(" ");
const regions = rom.regions.map((r) => regionToEmoji(r)).join(" ");
const tags = rom.tags.map((t) => `(${t})`).join(" ");
return `${langs} ${regions} ${tags}`;
return `${langs} ${regions} ${tags}` || rom.file_name;
}
function updateVersion() {
Expand Down

0 comments on commit b6da52b

Please sign in to comment.