Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.6 #99

Merged
merged 8 commits into from
Mar 31, 2023
Merged

v1.6 #99

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion backend/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ fastapi==0.92.0
uvicorn==0.20.0
mariadb==1.1.6
SQLAlchemy==2.0.7
PyYAML==6.0
PyYAML==6.0
Unidecode==1.3.6
1 change: 1 addition & 0 deletions backend/src/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

# PATHS
LIBRARY_BASE_PATH: str = f"{pathlib.Path(__file__).parent.parent.parent.parent.resolve()}/library"
HIGH_PRIO_STRUCTURE_PATH: str = f"{LIBRARY_BASE_PATH}/roms"
ROMM_USER_CONFIG_PATH: str = f"{pathlib.Path(__file__).parent.parent.parent.parent.resolve()}/romm/config.yml"

# ROMM RESERVED FOLDERS
Expand Down
12 changes: 7 additions & 5 deletions backend/src/handler/igdb_handler.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import sys
import functools
import re
import unidecode
from time import time

import requests
Expand Down Expand Up @@ -63,12 +64,13 @@ def get_rom_details(self, file_name: str, p_igdb_id: int, r_igdb_id_search: str)
except KeyError:
pass

else:
else: #TODO: improve API calls to make only one
search_term: str = unidecode.unidecode(file_name_no_tags)
if p_igdb_id:
try:

res_details: dict = requests.post("https://api.igdb.com/v4/games/", headers=self.headers,
data=f"search \"{file_name_no_tags}\";fields id, slug, name, summary; where platforms=[{p_igdb_id}] & category=0;").json()[0]
data=f"search \"{search_term}\";fields id, slug, name, summary; where platforms=[{p_igdb_id}] & category=0;").json()[0]
r_igdb_id = res_details['id']
slug = res_details['slug']
name = res_details['name']
Expand All @@ -79,7 +81,7 @@ def get_rom_details(self, file_name: str, p_igdb_id: int, r_igdb_id_search: str)
except IndexError:
try:
res_details: dict = requests.post("https://api.igdb.com/v4/games/", headers=self.headers,
data=f"search \"{file_name_no_tags}\";fields name, id, slug, summary; where platforms=[{p_igdb_id}] & category=10;").json()[0]
data=f"search \"{search_term}\";fields name, id, slug, summary; where platforms=[{p_igdb_id}] & category=10;").json()[0]
r_igdb_id = res_details['id']
slug = res_details['slug']
name = res_details['name']
Expand All @@ -90,7 +92,7 @@ def get_rom_details(self, file_name: str, p_igdb_id: int, r_igdb_id_search: str)
except IndexError:
try:
res_details: dict = requests.post("https://api.igdb.com/v4/games/", headers=self.headers,
data=f"search \"{file_name_no_tags}\";fields name, id, slug, summary; where platforms=[{p_igdb_id}];").json()[0]
data=f"search \"{search_term}\";fields name, id, slug, summary; where platforms=[{p_igdb_id}];").json()[0]
r_igdb_id = res_details['id']
slug = res_details['slug']
name = res_details['name']
Expand All @@ -113,7 +115,7 @@ def get_rom_details(self, file_name: str, p_igdb_id: int, r_igdb_id_search: str)

@check_twitch_token
def get_matched_roms(self, file_name: str, p_igdb_id: int) -> list:
search_term: str = re.sub('[\(\[].*?[\)\]]', '', file_name.split('.')[0])
search_term: str = unidecode.unidecode(re.sub('[\(\[].*?[\)\]]', '', file_name.split('.')[0]))
matched_roms: list = requests.post("https://api.igdb.com/v4/games/", headers=self.headers,
data=f"search \"{search_term}\";fields name, id, slug, summary; where platforms=[{p_igdb_id}];").json()
log.info(f"Matched roms for {file_name}: {matched_roms}")
Expand Down
6 changes: 3 additions & 3 deletions backend/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ async def platforms() -> dict:


@app.put("/scan")
async def scan(req: Request, overwrite: bool=False) -> dict:
async def scan(req: Request, full_scan: bool=False, overwrite: bool=False) -> dict:
"""Scan platforms and roms and write them in database."""

log.info("complete scaning...")
Expand All @@ -84,10 +84,10 @@ async def scan(req: Request, overwrite: bool=False) -> dict:
platforms: list[str] = data['platforms'] if data['platforms'] else fs.get_platforms()
for p_slug in platforms:
platform: Platform = fastapi.scan_platform(p_slug)
roms: list[dict] = fs.get_roms(p_slug)
roms: list[dict] = fs.get_roms(p_slug, full_scan)
for rom in roms:
fastapi.scan_rom(platform, rom)
dbh.purge_roms(p_slug, roms)
dbh.purge_roms(p_slug, fs.get_roms(p_slug, True))
dbh.purge_platforms(fs.get_platforms())
return {'msg': 'success'}

Expand Down
2 changes: 1 addition & 1 deletion backend/src/utils/fastapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def scan_platform(p_slug: str) -> Platform:
platform_attrs: dict = igdbh.get_platform_details(p_slug)
platform_attrs['slug'] = p_slug
platform_attrs['logo_path'] = ''
platform_attrs['n_roms'] = fs.get_roms(p_slug, only_amount=True)
platform_attrs['n_roms'] = fs.get_roms(p_slug, True, only_amount=True)
log.info(f"Platform n_roms: {platform_attrs['n_roms']}")
platform = Platform(**platform_attrs)
dbh.add_platform(platform)
Expand Down
49 changes: 25 additions & 24 deletions backend/src/utils/fs.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
import requests
from fastapi import HTTPException

from config import user_config, LIBRARY_BASE_PATH, RESERVED_FOLDERS, DEFAULT_URL_COVER_L, DEFAULT_PATH_COVER_L, DEFAULT_URL_COVER_S, DEFAULT_PATH_COVER_S
from config import user_config, LIBRARY_BASE_PATH, HIGH_PRIO_STRUCTURE_PATH, RESERVED_FOLDERS, DEFAULT_URL_COVER_L, DEFAULT_PATH_COVER_L, DEFAULT_URL_COVER_S, DEFAULT_PATH_COVER_S
from models.platform import Platform
from models.rom import Rom
from handler import dbh
from logger.logger import log


Expand Down Expand Up @@ -52,12 +55,11 @@ def get_platforms() -> list[str]:

# ========= Roms utils =========
def _check_folder_structure(p_slug) -> tuple:
if os.path.exists(f"{LIBRARY_BASE_PATH}/roms"):
roms_path: str = f"{LIBRARY_BASE_PATH}/roms/{p_slug}"
roms_files = list(os.walk(f"{LIBRARY_BASE_PATH}/roms/{p_slug}"))[0][2]
else:
roms_path: str = f"{LIBRARY_BASE_PATH}/{p_slug}/roms"
roms_files = list(os.walk(f"{LIBRARY_BASE_PATH}/{p_slug}/roms"))[0][2]
roms_path: str = f"{HIGH_PRIO_STRUCTURE_PATH}/{p_slug}" if os.path.exists(HIGH_PRIO_STRUCTURE_PATH) else f"{LIBRARY_BASE_PATH}/{p_slug}/roms"
try:
roms_files = list(os.walk(roms_path))[0][2]
except IndexError:
roms_files = []
return roms_path, roms_files


Expand Down Expand Up @@ -91,30 +93,29 @@ def parse_tags(file_name: str) -> tuple:
return reg, rev, other_tags


def get_roms(p_slug: str, only_amount: bool = False) -> list[dict]:
def get_roms(p_slug: str, full_scan: bool, only_amount: bool = False) -> list[dict]:
"""Gets all filesystem roms for a platform

Args:
p_slug: short name of the platform
only_amount: flag to return only amount of roms instead of all info
Returns: list with all the filesystem roms for a platform found in the LIBRARY_BASE_PATH. Just the amount of them if only_amount=True
"""
try:
roms: list[dict] = []
roms_path, roms_files = _check_folder_structure(p_slug)
roms_files = _exclude_files(roms_files)

if only_amount: return len(roms_files)

for rom in roms_files:
file_size: str = str(round(os.stat(f"{roms_path}/{rom}").st_size / (1024 * 1024), 2))
file_extension: str = rom.split('.')[-1] if '.' in rom else ""
reg, rev, other_tags = parse_tags(rom)
roms.append({'file_name': rom, 'file_path': roms_path, 'file_size': file_size, 'file_extension': file_extension,
'region': reg, 'revision': rev, 'tags': other_tags})
log.info(f"Roms found for {p_slug}: {roms}")
except IndexError:
log.warning(f"Roms not found for {p_slug}")
roms: list[dict] = []
roms_path, roms_files = _check_folder_structure(p_slug)
roms_files = _exclude_files(roms_files)

if only_amount: return len(roms_files)

excluded_roms: list[str] = [rom.file_name for rom in dbh.get_roms(p_slug)]
for rom in roms_files:
if rom in excluded_roms and not full_scan: continue
file_size: str = str(round(os.stat(f"{roms_path}/{rom}").st_size / (1024 * 1024), 2))
file_extension: str = rom.split('.')[-1] if '.' in rom else ""
reg, rev, other_tags = parse_tags(rom)
roms.append({'file_name': rom, 'file_path': roms_path, 'file_size': file_size, 'file_extension': file_extension,
'region': reg, 'revision': rev, 'tags': other_tags})
log.info(f"Roms found for {p_slug}: {roms}")
if only_amount: return 0
return roms

Expand Down
6 changes: 6 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# v1.6 (_10-04-2023_)

## Added
- Smart scan: now RomM will only scan the changes in the filesystem, making the scan process too much faster. Added an option to force a full scan.
- Now game files can be renamed after the name matched in IGDB, keeping the tags.

# v1.5.1 (_31-03-2023_)

## Fix
Expand Down
21 changes: 14 additions & 7 deletions frontend/src/components/Navigation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const currentPlatform = ref(JSON.parse(localStorage.getItem('currentPlatform'))
const platformsToScan = ref([])
const scanning = ref(false)
const scanOverwrite = ref(false)
const fullScan = ref(false)
const gettingRomsFlag = ref(false)
const filter = ref('')
const drawer = ref(null)
Expand All @@ -33,7 +34,7 @@ async function scan() {
toRaw(platformsToScan)._rawValue.forEach(p => {platforms.push(toRaw(p.slug))})
console.log(platforms)

await axios.put('/api/scan?overwrite='+scanOverwrite.value,{
await axios.put('/api/scan?overwrite='+scanOverwrite.value+'&full_scan='+fullScan.value,{
platforms: platforms
}).then((response) => {
console.log("scan completed")
Expand Down Expand Up @@ -103,12 +104,18 @@ getPlatforms()
<v-list>
<!-- Settings drawer - scan button -->
<v-select label="Platforms" item-title="name" v-model="platformsToScan" :items="platforms" class="pl-5 pr-5 mt-2" density="comfortable" variant="outlined" multiple return-object clearable/>
<v-list-item class="d-flex align-center justify-center mb-2 pt-0">
<v-btn title="scan" @click="scan()" :disabled="scanning" prepend-icon="mdi-magnify-scan" color="secondary" rounded="0" inset>
<p v-if="!scanning">Scan</p>
<p v-if="scanning">Scanning</p>
<v-progress-circular v-show="scanning" class="ml-2" :width="2" :size="20" indeterminate/>
</v-btn>
<v-list-item class="pa-0">
<v-row class="align-center">
<v-col class="d-flex justify-center">
<v-btn title="scan" @click="scan()" :disabled="scanning" prepend-icon="mdi-magnify-scan" class="ml-7" color="secondary" rounded="0" inset>
<p v-if="!scanning">Scan</p>
<v-progress-circular v-show="scanning" class="ml-2" :width="2" :size="20" indeterminate/>
</v-btn>
</v-col>
<v-col class="mr-4">
<v-checkbox v-model="fullScan" label="Full scan" hide-details="true"/>
</v-col>
</v-row>
</v-list-item>
</v-list>
<!-- Settings drawer - theme toggle -->
Expand Down
25 changes: 21 additions & 4 deletions frontend/src/components/RomDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const searching = ref(false)
const matchedRoms = ref([])
const updating = ref(false)
const editedRomName = ref(rom.value.file_name)
const renameAsIGDB = ref(false)
const dialogSearchRom = ref(false)
const dialogEditRom = ref(false)
const dialogDeleteRom = ref(false)
Expand Down Expand Up @@ -49,7 +50,14 @@ async function searchRomIGDB() {
async function updateRom(updatedRom=Object.assign({},rom.value), newName=rom.value.file_name) {
updating.value = true
dialogSearchRom.value = false
updatedRom.file_name = newName
if (renameAsIGDB.value) {
updatedRom.file_name = rom.value.file_name.replace(rom.value.file_name_no_tags.trim(), updatedRom.name)
editedRomName.value = updatedRom.file_name
renameAsIGDB.value = false
}
else{
updatedRom.file_name = newName
}
console.log(rom.value)
await axios.patch('/api/platforms/'+rom.value.p_slug+'/roms', {
rom: rom.value,
Expand Down Expand Up @@ -164,7 +172,7 @@ async function deleteRom() {
<v-toolbar-title>Results found</v-toolbar-title>
<v-btn icon @click="dialogSearchRom=false" class="ml-1" rounded="0"><v-icon>mdi-close</v-icon></v-btn>
</v-toolbar>
<v-card-text rounded="0" class="pa-3">
<v-card-text rounded="0" class="pa-3 scroll">
<div class="d-flex justify-center">
<v-progress-circular v-show="searching" :width="2" :size="40" class="pa-3 ma-3" indeterminate/>
</div>
Expand All @@ -182,6 +190,9 @@ async function deleteRom() {
</v-col>
</v-row>
</v-card-text>
<v-card-actions v-show="!searching">
<v-checkbox v-model="renameAsIGDB" label="Rename file" class="pl-3" hide-details="true"/>
</v-card-actions>
</v-card>
</v-dialog>

Expand Down Expand Up @@ -219,9 +230,15 @@ async function deleteRom() {
<v-btn @click="dialogDeleteRom=false" variant="tonal">Cancel</v-btn>
</v-card-actions>
<div class="pl-8">
<v-checkbox v-model="deleteFromFs" label="Delete from filesystem"></v-checkbox>
<v-checkbox v-model="deleteFromFs" label="Delete from filesystem" hide-details="true"/>
</div>
</v-card>
</v-dialog>

</template>
</template>

<style scoped>
.scroll {
overflow-y: scroll
}
</style>