Skip to content

Commit 8caa3f0

Browse files
committed
Merge branch 'master' into upd_banner_fmt
2 parents 45a434b + 063b673 commit 8caa3f0

11 files changed

Lines changed: 107 additions & 46 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,6 @@ platforms_idmap_local.csv
7373
# VS Code
7474
*.code-workspace
7575
.vscode
76+
77+
# docker config
78+
docker/config.ini

VERSION.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
VERSION="3.18.4"
1+
VERSION="3.18.5"

docker/Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ RUN rm -rf /var/lib/apt/lists/*
2323
RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo
2424

2525
# Building skyscraper
26-
COPY ./* ./
26+
RUN mkdir -p /opt/skyscraper
27+
WORKDIR /opt/skyscraper
28+
COPY . .
2729
RUN rm -f ./VERSION.ini
2830
RUN chmod +x update_skyscraper.sh && ./update_skyscraper.sh
2931

docker/process_dir.sh

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
#!/bin/bash
22

33
# Usage:
4-
# ./process_dir.sh [ROMS_DIR]
4+
# ./process_dir.sh [ROMS_DIR] {source1} {source2} ...
55
# Example
66
# ./process_dir.sh ~/roms
7-
# ./process_dir.sh ~/roms > output.txt
7+
# ./process_dir.sh ~/roms screenscraper > output.txt
88
#
9-
# Note: can be use for Emulation Station roms folder, but platform name can be different. ES's genesis is megadrive for skyscraper,
9+
# Note: can be use for Emulation Station roms folder, but platform name can be different. ES's genesis is megadrive for skyscraper.
10+
# Defaults to screenscraper and thegamesdb sources if none are specified.
1011

1112
TAG=skyscraper
1213

1314
PLATFORMS=$1/*
15+
shift
16+
17+
SOURCES=("$@")
18+
if [ ${#SOURCES[@]} -eq 0 ]; then
19+
SOURCES=(screenscraper thegamesdb)
20+
fi
1421

1522
mkdir cache
1623

@@ -23,7 +30,7 @@ for file_name in $PLATFORMS; do
2330
echo "Processing ${PLATFORM}..."
2431
echo "Mounting $file_name:./roms/$PLATFORM..."
2532

26-
for source in "screenscraper" "thegamesdb"; do
33+
for source in "${SOURCES[@]}"; do
2734
echo "Processing $PLATFORM on $source..."
2835

2936
./scrape.sh $file_name $PLATFORM $source

docker/save.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#!/bin/bash
22

33
# Usage:
4-
# ./scrape.sh [ROMS_DIR] [PLATFORM]
4+
# ./save.sh [ROMS_DIR] [PLATFORM]
55
# Example
6-
# ./scrape.sh ./roms/snes snes
6+
# ./save.sh ./roms/snes snes
77

88
TAG=skyscraper
99

@@ -14,4 +14,4 @@ docker run \
1414
-v "$ROMS_DIR:/tmp/roms/$PLATFORM" \
1515
-v "$(pwd)/cache:/tmp/skyscraper_cache" \
1616
$TAG \
17-
-p $PLATFORM -i /tmp/roms/$PLATFORM -d /tmp/skyscraper_cache --flags relative,unattendskip
17+
-p $PLATFORM -i /tmp/roms/$PLATFORM -g /tmp/roms/$PLATFORM -o /tmp/roms/$PLATFORM/media -d /tmp/skyscraper_cache --flags relative,unattend

docker/scrape.sh

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,17 @@ ROMS_DIR=$1
1111
PLATFORM=$2
1212
SOURCE=$3
1313

14-
docker run \
15-
-v "$ROMS_DIR:/tmp/roms/$PLATFORM" \
16-
-v "$(pwd)/cache:/tmp/skyscraper_cache" \
17-
$TAG \
18-
-p $PLATFORM -s $SOURCE -i /tmp/roms/$PLATFORM -d /tmp/skyscraper_cache
14+
if [ -f ./config.ini ]; then
15+
docker run \
16+
-v "$ROMS_DIR:/tmp/roms/$PLATFORM" \
17+
-v "$(pwd)/cache:/tmp/skyscraper_cache" \
18+
-v "$(pwd)/config.ini:/root/.skyscraper/config.ini" \
19+
$TAG \
20+
-p $PLATFORM -s $SOURCE -i /tmp/roms/$PLATFORM -d /tmp/skyscraper_cache
21+
else
22+
docker run \
23+
-v "$ROMS_DIR:/tmp/roms/$PLATFORM" \
24+
-v "$(pwd)/cache:/tmp/skyscraper_cache" \
25+
$TAG \
26+
-p $PLATFORM -s $SOURCE -i /tmp/roms/$PLATFORM -d /tmp/skyscraper_cache
27+
fi

docs/CONFIGINI.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,13 @@ or
10561056
userCreds="<Client-ID>:<Client-Secret>"
10571057
```
10581058

1059+
or
1060+
1061+
```ini
1062+
[thegamesdb]
1063+
userCreds="<your-private-api-key-of-64chars>"
1064+
```
1065+
10591066
Default value: unset
10601067
Allowed in sections: `[<SCRAPER>]`
10611068

docs/SCRAPINGMODULES.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ I strongly recommend supporting them by contributing data to the database, or by
9696
- Website: _[www.thegamesdb.net](http://www.thegamesdb.net)_
9797
- Type: _File name search based_
9898
- User credential support: _Not required_
99-
- API request limit: _Limited to 3000 requests per IP per month_
99+
- API request limit: _Limited to 1000 requests per IP per month_
100100
- Thread limit: _None_
101101
- Platform support: _[Link to list](https://thegamesdb.net/list_platforms.php) or see `tgdb_platforms.json` sibling to your `config.ini`_
102102
- Media support: `backcover`, `cover`, `fanart`, `marquee`, `screenshot`, `wheel`
@@ -107,7 +107,7 @@ I strongly recommend supporting them by contributing data to the database, or by
107107

108108
For newer games there's no way around TheGames DB. It recently had a huge redesign and their database remains one of the best out there. I would recommend scraping your roms with `screenscraper` first, and then use `thegamesdb` to fill out the gaps in your cache.
109109

110-
There's a small caveat to this module, as it has a monthly request limit (see above) per IP per month. But this should be plenty for most people.
110+
There's a small caveat to this module, as it has a monthly request limit (see above) per IP per month. As per Feb 17th of 2026 TGDB have changed they API usage policy: You may have to register for your private API key to increase the above limits. Put your private API key then in the [`userCreds=`](CONFIGINI.md#usercreds) section of `[thegamesdb]`, or use the `-u` option when scraping with this module.
111111

112112
Their API is based on a file name search. This means that the returned results do have a chance of being faulty. Skyscraper does a lot internally to make sure accepted data is for the correct game. But it is impossible to ensure 100% correct results, so do keep that in mind when using it. Consider using the `--flags interactive` command line flag if you want complete control of the accepted entries.
113113

src/settings.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,13 @@ void RuntimeCfg::applyCli(bool &inputFolderSet, bool &gameListFolderSet,
699699
if (parser->isSet("cache")) {
700700
config->cacheOptions =
701701
parser->value("cache").simplified().replace(" ", "");
702-
if (config->cacheOptions == "refresh") {
702+
bool valid = validateCacheSubCommand(config->cacheOptions);
703+
if (!valid) {
704+
printf("\033[1;31mInvalid parameter '--cache %s'\033[0m, "
705+
"please check '--cache help' for more info.\n",
706+
config->cacheOptions.toStdString().c_str());
707+
exit(2);
708+
} else if (config->cacheOptions == "refresh") {
703709
config->refresh = true;
704710
config->cacheOptions = "";
705711
} else if (config->cacheOptions == "help") {
@@ -709,8 +715,7 @@ void RuntimeCfg::applyCli(bool &inputFolderSet, bool &gameListFolderSet,
709715
Cli::cacheReportMissingUsage();
710716
exit(0);
711717
} else if (config->cacheOptions.startsWith("purge:")) {
712-
bool valid = validatePurgeParameters(config->cacheOptions);
713-
if (!valid) {
718+
if (!validatePurgeParameters(config->cacheOptions)) {
714719
printf(
715720
"\033[1;31mInvalid purge: parameter '--cache %s'\033[0m, "
716721
"please check '--cache help' for more info.\n",

src/thegamesdb.cpp

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -65,33 +65,54 @@ void TheGamesDb::getSearchResults(QList<GameEntry> &gameEntries,
6565
pIds.append(QString::number(p));
6666
}
6767
}
68-
69-
QString req =
70-
searchUrlPre +
71-
StrTools::unMagic(
72-
"187;161;217;126;172;149;202;122;163;197;163;219;162;171;203;197;"
73-
"139;151;215;173;122;206;161;162;200;216;217;123;124;215;200;170;"
74-
"171;132;158;155;215;120;149;169;140;164;122;154;178;174;160;172;"
75-
"157;131;210;161;203;137;159;117;205;166;162;139;171;169;210;163") +
76-
"&name=" + searchName + "&filter[platform]=" + pIds.join(",");
68+
QString k = getKey();
69+
QString req = searchUrlPre % k % "&name=" % searchName %
70+
"&filter[platform]=" % pIds.join(",");
7771
netComm->request(req);
72+
qDebug() << req;
7873
q.exec();
74+
int httpStatus = netComm->getHttpStatus();
75+
qDebug() << "HTTP status" << httpStatus;
7976
data = netComm->getData();
80-
qDebug() << req;
81-
8277
jsonDoc = QJsonDocument::fromJson(data);
78+
QString apiStatus = jsonDoc.object()["status"].toString();
79+
80+
if (httpStatus >= 400) {
81+
printf(
82+
"\033[1;31mServer response status %d\033[0m: Cannot continue! See "
83+
"https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/"
84+
"Status/%d\n",
85+
httpStatus, httpStatus);
86+
reqRemaining = 0;
87+
if (!apiStatus.isEmpty()) {
88+
printf("\033[1;31mAPI status message\033[0m: %s\n",
89+
apiStatus.toStdString().c_str());
90+
}
91+
return;
92+
}
93+
8394
if (jsonDoc.isEmpty()) {
8495
return;
8596
}
8697

87-
reqRemaining = jsonDoc.object()["remaining_monthly_allowance"].toInt();
98+
if (!apiStatus.isEmpty() && apiStatus != "Success") {
99+
printf("\033[1;31mAPI status message\033[0m: %s. Cannot continue...\n",
100+
apiStatus.toStdString().c_str());
101+
reqRemaining = 0;
102+
return;
103+
}
104+
105+
QJsonObject obj = jsonDoc.object();
106+
reqRemaining = obj["extra_allowance"].toInt();
107+
if (reqRemaining <= 0) {
108+
reqRemaining = obj["remaining_monthly_allowance"].toInt();
109+
}
110+
88111
if (reqRemaining <= 0)
89112
printf("\033[1;31mYou've reached TheGamesdDb's request limit for this "
90-
"month.\033[0m\n");
113+
"month with %s API key.\033[0m\n",
114+
config->userCreds.isEmpty() ? "the public" : "your private");
91115

92-
if (jsonDoc.object()["status"].toString() != "Success") {
93-
return;
94-
}
95116
if (jsonDoc.object()["data"].toObject()["count"].toInt() < 1) {
96117
return;
97118
}
@@ -109,17 +130,11 @@ void TheGamesDb::getSearchResults(QList<GameEntry> &gameEntries,
109130
GameEntry game;
110131

111132
game.id = QString::number(jsonGame["id"].toInt());
112-
game.url =
113-
QString("%1/Games/ByGameID?id=%2&apikey=%3&fields=%4")
114-
.arg(baseUrl)
115-
.arg(game.id)
116-
.arg(QString(StrTools::unMagic(
117-
"187;161;217;126;172;149;202;122;163;197;163;219;162;"
118-
"171;203;197;139;151;215;173;122;206;161;162;200;216;"
119-
"217;123;124;215;200;170;171;132;158;155;215;120;149;"
120-
"169;140;164;122;154;178;174;160;172;157;131;210;161;"
121-
"203;137;159;117;205;166;162;139;171;169;210;163")))
122-
.arg(fields.join(","));
133+
game.url = QString("%1/Games/ByGameID?id=%2&apikey=%3&fields=%4")
134+
.arg(baseUrl)
135+
.arg(game.id)
136+
.arg(k)
137+
.arg(fields.join(","));
123138

124139
game.title = jsonGame["game_title"].toString();
125140
// Remove anything at the end with a parentheses. 'thegamesdb' has a
@@ -301,4 +316,16 @@ void TheGamesDb::loadMaps() {
301316

302317
QVector<int> TheGamesDb::getPlatformId(const QString platform) {
303318
return Platform::get().getPlatformIdOnScraper(platform, config->scraper);
319+
}
320+
321+
QString TheGamesDb::getKey() {
322+
QString k = config->userCreds;
323+
if (k.isEmpty()) {
324+
k = StrTools::unMagic(
325+
"189;159;218;132;218;153;203;170;166;155;168;177;211;217;203;153;"
326+
"137;152;167;175;126;161;209;162;150;165;216;128;173;168;149;169;"
327+
"213;137;203;161;163;170;196;215;182;168;118;156;132;171;202;165;"
328+
"153;177;168;208;155;134;212;166;164;163;161;184;168;163;160;211");
329+
}
330+
return k;
304331
}

0 commit comments

Comments
 (0)