Migrate Free Games Claimer to remaster upstream
This commit is contained in:
Alexandre
2026-07-17 09:27:19 +02:00
committed by GitHub
9 changed files with 719 additions and 254 deletions

View File

@@ -1,20 +1,53 @@
- Added support for configuring extra environment variables via the `env_vars` add-on option alongside config.yaml. See https://github.com/alexbelgium/hassio-addons/wiki/Add-Environment-variables-to-your-Addon-2 for details. ## 2.0.0 (2026-07-17)
- Replaced the abandoned `vogler/free-games-claimer` upstream with
`P-Adamiec/Free-Games-Claimer-Remaster`.
- Reworked the image build for the remaster's Python, Chromium, TurboVNC, and
noVNC runtime on both amd64 and aarch64.
- Preserved the previous default one-shot behavior and Epic, Prime Gaming, and
GOG store selection.
- Kept noVNC on port 6080 for upgrade compatibility.
- Added `RUN_ONCE` and `STORES` options while retaining `CMD_ARGUMENTS` as a
deprecated compatibility input.
- Added an automatic, idempotent migration of legacy Epic, Prime Gaming, and
GOG JSON claim history into the remaster SQLite database.
- Preserved legacy files for rollback and documented the required one-time
Chromium login when a Firefox session cannot be migrated.
- Pinned the reviewed upstream source commit and paused generic automatic
updates so the add-on's independent `2.x` version cannot regress to `1.x`.
- Updated the configuration template, upstream metadata, and documentation.
- Added support for configuring extra environment variables via the `env_vars`
add-on option.
## 1.8 (2025-05-17) ## 1.8 (2025-05-17)
- Update to latest version from vogler/free-games-claimer (changelog : https://github.com/vogler/free-games-claimer/releases)
- Update to latest version from vogler/free-games-claimer (changelog: https://github.com/vogler/free-games-claimer/releases)
## 1.7 (2025-03-08) ## 1.7 (2025-03-08)
- Update to latest version from vogler/free-games-claimer (changelog : https://github.com/vogler/free-games-claimer/releases)
- Update to latest version from vogler/free-games-claimer (changelog: https://github.com/vogler/free-games-claimer/releases)
## 1.6-6 (2024-12-29) ## 1.6-6 (2024-12-29)
- Minor bugs fixed - Minor bugs fixed
## 1.6-5 (2024-12-13) ## 1.6-5 (2024-12-13)
- Minor bugs fixed - Minor bugs fixed
## 1.6-4 (2024-12-07) ## 1.6-4 (2024-12-07)
- ⚠ MAJOR CHANGE : switch to the new config logic from homeassistant. Your configuration files will have migrated from /config/hassio_addons/free_games_claimer in a folder only accessible from my Filebrowser addon called /addon_configs/db21ed7f_free_games_claimer. This avoids the addon to mess with your homeassistant configuration folder, and allows to backup the options. For more information, see here : https://developers.home-assistant.io/blog/2023/11/06/public-addon-config/
- Major change: switch to the new Home Assistant add-on configuration logic.
Configuration files were migrated from
`/config/hassio_addons/free_games_claimer` to the private add-on configuration
directory available through compatible file browser add-ons.
## 1.6-3 (2024-12-05) ## 1.6-3 (2024-12-05)
- Minor bugs fixed - Minor bugs fixed
## 1.6-2 (2024-12-05) ## 1.6-2 (2024-12-05)
- Minor bugs fixed - Minor bugs fixed
## 1.6 (2023-12-30) ## 1.6 (2023-12-30)
@@ -28,18 +61,23 @@
## 1.4 (2023-05-27) ## 1.4 (2023-05-27)
- Update to latest version from vogler/free-games-claimer - Update to latest version from vogler/free-games-claimer
## 1.4-5 (2023-05-26) ## 1.4-5 (2023-05-26)
- Minor bugs fixed - Minor bugs fixed
## 1.4-4 (2023-05-26) ## 1.4-4 (2023-05-26)
- Minor bugs fixed - Minor bugs fixed
## 1.4-3 (2023-05-26) ## 1.4-3 (2023-05-26)
- Minor bugs fixed - Minor bugs fixed
## 1.4-2 (2023-05-25) ## 1.4-2 (2023-05-25)
- Minor bugs fixed - Minor bugs fixed
## NOT_WORKING (2023-05-22) ## NOT_WORKING (2023-05-22)
- Minor bugs fixed - Minor bugs fixed

View File

@@ -1,91 +1,14 @@
#============================# #============================#
# ALEXBELGIUM'S DOCKERFILE # # ALEXBELGIUM'S DOCKERFILE #
#============================# #============================#
# _.------. #=== Home Assistant Add-on ===#
# _.-` ('>.-`"""-.
# '.--'` _'` _ .--.)
# -' '-.-';` `
# ' - _.' ``'--.
# '---` .-'""`
# /`
#=== Home Assistant Addon ===#
################# ARG BUILD_FROM="debian:bookworm-slim"
# 1 Build Image #
#################
ARG BUILD_FROM
ARG BUILD_VERSION
FROM ${BUILD_FROM} FROM ${BUILD_FROM}
##################
# 2 Modify Image #
##################
# Set S6 wait time
ENV S6_CMD_WAIT_FOR_SERVICES=1 \
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
S6_SERVICES_GRACETIME=0
##################
# 3 Install apps #
##################
# Add rootfs
COPY rootfs/ /
RUN find . -type f \( -name "*.sh" -o -name "run" -o -name "finish" \) -print -exec chmod +x {} \;
# Uses /bin for compatibility purposes
# hadolint ignore=DL4005
RUN if [ ! -f /bin/sh ] && [ -f /usr/bin/sh ]; then ln -s /usr/bin/sh /bin/sh; fi && \
if [ ! -f /bin/bash ] && [ -f /usr/bin/bash ]; then ln -s /usr/bin/bash /bin/bash; fi
# Modules
ARG MODULES="00-banner.sh 01-custom_script.sh"
# Automatic modules download
COPY ha_automodules.sh /ha_automodules.sh
RUN chmod 744 /ha_automodules.sh && /ha_automodules.sh "$MODULES" && rm /ha_automodules.sh
# Manual apps
ENV PACKAGES=""
# Automatic apps & bashio
COPY ha_autoapps.sh /ha_autoapps.sh
RUN chmod 744 /ha_autoapps.sh && /ha_autoapps.sh "$PACKAGES" && rm /ha_autoapps.sh
################
# 4 Entrypoint #
################
# Add entrypoint
ENV S6_STAGE2_HOOK=/ha_entrypoint.sh
COPY ha_entrypoint.sh /ha_entrypoint.sh
RUN chmod 777 /ha_entrypoint.sh
# Install bashio
COPY bashio-standalone.sh /usr/local/lib/bashio-standalone.sh
RUN chmod 0755 /usr/local/lib/bashio-standalone.sh
RUN \
# Change data folder
sed -i "s|/fgc|/data|g" /usr/local/bin/docker-entrypoint.sh && \
# Run scripts only once
sed -i "1a if [ -f /done ]; then exit 0; fi && touch /done" /ha_entrypoint.sh && \
sed -i "s=x11vnc=[[ \"\$(ps aux | grep \"x11vnc\" | grep -v grep)\" ]] || x11vnc=g" /usr/local/bin/docker-entrypoint.sh && \
# Update playwright
npx playwright install-deps && \
npx playwright install
WORKDIR /data
ENTRYPOINT [ "/usr/bin/env" ]
CMD [ "/ha_entrypoint.sh" ]
SHELL ["/bin/bash", "-o", "pipefail", "-c"] SHELL ["/bin/bash", "-o", "pipefail", "-c"]
############ ARG DEBIAN_FRONTEND="noninteractive"
# 5 Labels #
############
ARG BUILD_ARCH ARG BUILD_ARCH
ARG BUILD_DATE ARG BUILD_DATE
ARG BUILD_DESCRIPTION ARG BUILD_DESCRIPTION
@@ -93,28 +16,143 @@ ARG BUILD_NAME
ARG BUILD_REF ARG BUILD_REF
ARG BUILD_REPOSITORY ARG BUILD_REPOSITORY
ARG BUILD_VERSION ARG BUILD_VERSION
ENV BUILD_VERSION="${BUILD_VERSION}" ARG UPSTREAM_REPOSITORY="P-Adamiec/Free-Games-Claimer-Remaster"
ARG UPSTREAM_REF="cca4992354215cef8807b748575af797606627f4"
ENV S6_CMD_WAIT_FOR_SERVICES="1" \
S6_CMD_WAIT_FOR_SERVICES_MAXTIME="0" \
S6_SERVICES_GRACETIME="0" \
VNC_PORT="5900" \
NOVNC_PORT="6080" \
WIDTH="1280" \
HEIGHT="720" \
DEPTH="24" \
SHOW="1" \
COMMIT="${UPSTREAM_REF}" \
BRANCH="main" \
NOW="${BUILD_DATE}"
# Install the dependencies used by Free Games Claimer Remaster. The upstream
# Dockerfile supports both amd64 (Google Chrome) and arm64 (Chromium), so the
# add-on keeps its existing multi-architecture support.
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
curl \
dos2unix \
gnupg \
gzip \
jq \
python3 \
python3-pip \
tar \
tini \
&& mkdir -p /etc/apt/keyrings \
&& curl --proto "=https" --tlsv1.2 -fsSL https://packagecloud.io/dcommander/virtualgl/gpgkey \
| gpg --dearmor -o /etc/apt/trusted.gpg.d/VirtualGL.gpg \
&& curl --proto "=https" --tlsv1.2 -fsSL https://packagecloud.io/dcommander/turbovnc/gpgkey \
| gpg --dearmor -o /etc/apt/trusted.gpg.d/TurboVNC.gpg \
&& curl --proto "=https" --tlsv1.2 -fsSL https://raw.githubusercontent.com/VirtualGL/repo/main/VirtualGL.list \
> /etc/apt/sources.list.d/VirtualGL.list \
&& curl --proto "=https" --tlsv1.2 -fsSL https://raw.githubusercontent.com/TurboVNC/repo/main/TurboVNC.list \
> /etc/apt/sources.list.d/TurboVNC.list \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
novnc \
ratpoison \
turbovnc \
virtualgl \
websockify \
libasound2 \
libatk-bridge2.0-0 \
libatk1.0-0 \
libatspi2.0-0 \
libcairo2 \
libcups2 \
libgbm1 \
libnspr4 \
libnss3 \
libpango-1.0-0 \
libxcomposite1 \
libxdamage1 \
libxfixes3 \
libxkbcommon0 \
&& if [ "$(dpkg --print-architecture)" = "amd64" ]; then \
curl -fsSL https://dl.google.com/linux/linux_signing_key.pub \
| gpg --dearmor -o /etc/apt/keyrings/google-chrome.gpg; \
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/google-chrome.gpg] https://dl.google.com/linux/chrome/deb/ stable main" \
> /etc/apt/sources.list.d/google-chrome.list; \
apt-get update; \
apt-get install -y --no-install-recommends google-chrome-stable; \
else \
apt-get install -y --no-install-recommends chromium; \
fi \
&& ln -sf /usr/share/novnc/vnc_auto.html /usr/share/novnc/index.html \
&& ln -sf /usr/bin/python3 /usr/bin/python \
&& apt-get purge -y gnupg \
&& apt-get autoremove -y \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /var/cache/* /var/tmp/* /tmp/* /usr/share/doc/*
# Install a deterministic snapshot of the replacement upstream. Updating the
# upstream reference is intentionally explicit so image contents cannot change
# without an add-on version bump.
WORKDIR /fgc
RUN curl --proto "=https" --tlsv1.2 -fsSL \
"https://github.com/${UPSTREAM_REPOSITORY}/archive/${UPSTREAM_REF}.tar.gz" \
-o /tmp/free-games-claimer-remaster.tar.gz \
&& tar -xzf /tmp/free-games-claimer-remaster.tar.gz --strip-components=1 -C /fgc \
&& python3 -m pip install --no-cache-dir --break-system-packages -r requirements.txt \
&& dos2unix ./*.sh \
&& chmod +x ./*.sh \
&& cp docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh \
&& chmod 0755 /usr/local/bin/docker-entrypoint.sh \
&& rm -f /tmp/free-games-claimer-remaster.tar.gz \
&& rm -rf /fgc/data \
&& ln -s /data /fgc/data
# Add Home Assistant integration files and shared helper modules.
COPY rootfs/ /
RUN find /etc/cont-init.d /usr/local/bin -type f -name "*.sh" -exec chmod 0755 {} + \
&& chmod 0755 /usr/local/bin/migrate_vogler_data.py
ARG MODULES="00-banner.sh 01-custom_script.sh"
COPY ha_automodules.sh /ha_automodules.sh
RUN chmod 0755 /ha_automodules.sh \
&& /ha_automodules.sh "${MODULES}" \
&& rm /ha_automodules.sh
ENV PACKAGES=""
COPY ha_autoapps.sh /ha_autoapps.sh
RUN chmod 0755 /ha_autoapps.sh \
&& /ha_autoapps.sh "${PACKAGES}" \
&& rm /ha_autoapps.sh
ENV S6_STAGE2_HOOK="/ha_entrypoint.sh"
COPY ha_entrypoint.sh /ha_entrypoint.sh
COPY bashio-standalone.sh /usr/local/lib/bashio-standalone.sh
RUN chmod 0755 /ha_entrypoint.sh /usr/local/lib/bashio-standalone.sh
EXPOSE 5900 6080
ENTRYPOINT ["/usr/bin/env"]
CMD ["/ha_entrypoint.sh"]
LABEL \ LABEL \
io.hass.name="${BUILD_NAME}" \ io.hass.name="${BUILD_NAME}" \
io.hass.description="${BUILD_DESCRIPTION}" \ io.hass.description="${BUILD_DESCRIPTION}" \
io.hass.arch="${BUILD_ARCH}" \ io.hass.arch="${BUILD_ARCH}" \
io.hass.type="addon" \ io.hass.type="addon" \
io.hass.version=${BUILD_VERSION} \ io.hass.version="${BUILD_VERSION}" \
maintainer="alexbelgium (https://github.com/alexbelgium)" \ maintainer="alexbelgium (https://github.com/alexbelgium)" \
org.opencontainers.image.title="${BUILD_NAME}" \ org.opencontainers.image.title="${BUILD_NAME}" \
org.opencontainers.image.description="${BUILD_DESCRIPTION}" \ org.opencontainers.image.description="${BUILD_DESCRIPTION}" \
org.opencontainers.image.vendor="Home Assistant Add-ons" \ org.opencontainers.image.vendor="Home Assistant Add-ons" \
org.opencontainers.image.authors="alexbelgium (https://github.com/alexbelgium)" \ org.opencontainers.image.authors="alexbelgium (https://github.com/alexbelgium)" \
org.opencontainers.image.licenses="MIT" \ org.opencontainers.image.licenses="AGPL-3.0" \
org.opencontainers.image.url="https://github.com/alexbelgium" \ org.opencontainers.image.url="https://github.com/${BUILD_REPOSITORY}" \
org.opencontainers.image.source="https://github.com/${BUILD_REPOSITORY}" \ org.opencontainers.image.source="https://github.com/${BUILD_REPOSITORY}" \
org.opencontainers.image.documentation="https://github.com/${BUILD_REPOSITORY}/blob/main/README.md" \ org.opencontainers.image.documentation="https://github.com/${BUILD_REPOSITORY}/blob/master/free_games_claimer/README.md" \
org.opencontainers.image.created=${BUILD_DATE} \ org.opencontainers.image.created="${BUILD_DATE}" \
org.opencontainers.image.revision=${BUILD_REF} \ org.opencontainers.image.revision="${BUILD_REF}" \
org.opencontainers.image.version=${BUILD_VERSION} org.opencontainers.image.version="${BUILD_VERSION}" \
io.hass.upstream="https://github.com/${UPSTREAM_REPOSITORY}/tree/${UPSTREAM_REF}"
####################
# 6 HealthcheckNOT #
####################
# Can't be implemented as container is optimized for memory usage, so the webserver and Node are spun down during idle

View File

@@ -1,128 +1,164 @@
## ⚠ VNC not working on several machines. Please use config.env to execute the script # Home Assistant add-on: Free Games Claimer
# Home assistant add-on: Free Games Claimer I maintain this and other Home Assistant add-ons in my free time. Keeping up
with upstream changes, Home Assistant changes, and testing on real hardware
takes a significant amount of time.
I maintain this and other Home Assistant add-ons in my free time: keeping up with upstream changes, HA changes, and testing on real hardware takes a lot of time (and some money). I use around 5-10 of my >110 addons so regularly I install test machines (and purchase some test services such as vpn) that I don't use myself to troubleshoot and improve the addons
If this add-on saves you time or makes your setup easier, I would be very grateful for your support!
[![Buy me a coffee][donation-badge]](https://www.buymeacoffee.com/alexbelgium) [![Buy me a coffee][donation-badge]](https://www.buymeacoffee.com/alexbelgium)
[![Donate via PayPal][paypal-badge]](https://www.paypal.com/donate/?hosted_button_id=DZFULJZTP3UQA) [![Donate via PayPal][paypal-badge]](https://www.paypal.com/donate/?hosted_button_id=DZFULJZTP3UQA)
## Addon informations ## Add-on information
![Version](https://img.shields.io/badge/dynamic/yaml?label=Version&query=%24.version&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Ffree_games_claimer%2Fconfig.yaml) ![Version](https://img.shields.io/badge/dynamic/yaml?label=Version&query=%24.version&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Ffree_games_claimer%2Fconfig.yaml)
![Ingress](https://img.shields.io/badge/dynamic/yaml?label=Ingress&query=%24.ingress&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Ffree_games_claimer%2Fconfig.yaml)
![Arch](https://img.shields.io/badge/dynamic/yaml?color=success&label=Arch&query=%24.arch&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Ffree_games_claimer%2Fconfig.yaml) ![Arch](https://img.shields.io/badge/dynamic/yaml?color=success&label=Arch&query=%24.arch&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Ffree_games_claimer%2Fconfig.yaml)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/9c6cf10bdbba45ecb202d7f579b5be0e)](https://www.codacy.com/gh/alexbelgium/hassio-addons/dashboard?utm_source=github.com&utm_medium=referral&utm_content=alexbelgium/hassio-addons&utm_campaign=Badge_Grade)
[![GitHub Super-Linter](https://img.shields.io/github/actions/workflow/status/alexbelgium/hassio-addons/weekly-supelinter.yaml?label=Lint%20code%20base)](https://github.com/alexbelgium/hassio-addons/actions/workflows/weekly-supelinter.yaml) [![GitHub Super-Linter](https://img.shields.io/github/actions/workflow/status/alexbelgium/hassio-addons/weekly-supelinter.yaml?label=Lint%20code%20base)](https://github.com/alexbelgium/hassio-addons/actions/workflows/weekly-supelinter.yaml)
[![Builder](https://img.shields.io/github/actions/workflow/status/alexbelgium/hassio-addons/onpush_builder.yaml?label=Builder)](https://github.com/alexbelgium/hassio-addons/actions/workflows/onpush_builder.yaml) [![Builder](https://img.shields.io/github/actions/workflow/status/alexbelgium/hassio-addons/onpush_builder.yaml?label=Builder)](https://github.com/alexbelgium/hassio-addons/actions/workflows/onpush_builder.yaml)
[donation-badge]: https://img.shields.io/badge/Buy%20me%20a%20coffee-%23d32f2f?logo=buy-me-a-coffee&style=flat&logoColor=white [donation-badge]: https://img.shields.io/badge/Buy%20me%20a%20coffee-%23d32f2f?logo=buy-me-a-coffee&style=flat&logoColor=white
[paypal-badge]: https://img.shields.io/badge/Donate%20via%20PayPal-0070BA?logo=paypal&style=flat&logoColor=white [paypal-badge]: https://img.shields.io/badge/Donate%20via%20PayPal-0070BA?logo=paypal&style=flat&logoColor=white
_Thanks to everyone having starred my repo! To star it click on the image below, then it will be on top right. Thanks!_
[![Stargazers repo roster for @alexbelgium/hassio-addons](https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.github/stars2.svg)](https://github.com/alexbelgium/hassio-addons/stargazers)
![downloads evolution](https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/free_games_claimer/stats.png)
## About ## About
[Free Games Claimer](https://github.com/vogler/free-games-claimer) : Claims free games periodically on This add-on is based on
[Free Games Claimer Remaster](https://github.com/P-Adamiec/Free-Games-Claimer-Remaster).
It can claim free games from:
- Epic Games Store - Epic Games Store
- Amazon Prime Gaming - Amazon Prime Gaming
- GOG - GOG
- Live Games with Gold - planned - Steam
- GamerPower-supported stores, when explicitly enabled
This addon is based on the docker image https://github.com/vogler/free-games-claimer For compatibility with previous add-on releases, the default store selection
remains Epic Games, Prime Gaming, and GOG.
## Configuration ## Web interface
Webui can be found at <http://homeassistant:6080> (NoVNC interface - currently has issues on some machines). The noVNC interface remains available on port `6080`:
### Options ```text
http://homeassistant:6080
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `CMD_ARGUMENTS` | str | `node epic-games ; node prime-gaming ; node gog` | Commands to run for claiming games |
| `CONFIG_LOCATION` | str | `/config/config.env` | Location of the configuration file |
### Example Configuration
```yaml
CMD_ARGUMENTS: "node epic-games ; node prime-gaming ; node gog"
CONFIG_LOCATION: "/config/config.env"
``` ```
### Environment Configuration It can be used for initial sign-in, CAPTCHA handling, or other manual browser
interaction. Set `VNC_PASSWORD` in `config.env` to protect the VNC session.
All main configuration is done via the `config.env` file located at `/config/addons_config/free_games_claimer/config.env`. ## Add-on options
If this file doesn't exist, it will be created at first boot with default settings. | Option | Default | Description |
|--------|---------|-------------|
| `CONFIG_LOCATION` | `/config/config.env` | Persistent environment configuration file |
| `RUN_ONCE` | `true` | Run all selected claimers once, then stop the add-on as previous releases did |
| `STORES` | empty | Optional comma-separated override, such as `epic,prime,gog,steam` |
| `CMD_ARGUMENTS` | `node epic-games ; node prime-gaming ; node gog` | Deprecated compatibility option; recognized legacy command names are converted to `STORES` |
| `env_vars` | `[]` | Additional environment variables passed to the add-on |
### Required Environment Variables ### Run modes
Add these to your `config.env` file: With `RUN_ONCE: true`, the add-on performs one claiming pass and stops. This is
the default and preserves the behavior of the former vogler-based add-on.
With `RUN_ONCE: false`, the remaster remains running and uses its internal
scheduler. Set `SCHEDULER_HOURS` in `config.env` to control the interval.
## Environment configuration
The add-on keeps its configuration in `CONFIG_LOCATION`, which defaults to
`/config/config.env`. From Home Assistant this is stored in the add-on's
private `addon_configs` directory and can be edited with a compatible file
browser add-on.
A template is created on first start. Common examples are:
```env ```env
# Epic Games Store # Preserve the former default selection
STORES=epic,prime,gog
# Epic Games
EG_EMAIL=your-email@example.com EG_EMAIL=your-email@example.com
EG_PASSWORD=your-password EG_PASSWORD=your-password
EG_OTPKEY=
# Amazon Prime Gaming # Amazon Prime Gaming
PG_EMAIL=your-amazon-email@example.com PG_EMAIL=your-amazon-email@example.com
PG_PASSWORD=your-amazon-password PG_PASSWORD=your-password
PG_OTPKEY=
# GOG (optional) # GOG
GOG_EMAIL=your-gog-email@example.com GOG_EMAIL=your-gog-email@example.com
GOG_PASSWORD=your-gog-password GOG_PASSWORD=your-password
# Notifications (optional) # Optional Steam support
EMAIL_SMTP_HOST=smtp.gmail.com STEAM_USERNAME=your-steam-username
EMAIL_SMTP_PORT=587 STEAM_PASSWORD=your-password
EMAIL_USER=notifications@example.com
EMAIL_PASS=your-app-password # Optional notifications
EMAIL_TO=recipient@example.com NOTIFY=tgram://bot-token/chat-id
# DISCORD_WEBHOOK=https://discord.com/api/webhooks/...
``` ```
### Additional Options Existing variables such as `EG_EMAIL`, `EG_PASSWORD`, `PG_EMAIL`,
`PG_PASSWORD`, `PG_OTPKEY`, `GOG_EMAIL`, `GOG_PASSWORD`, `SHOW`, `WIDTH`,
`HEIGHT`, `TIMEOUT`, `LOGIN_TIMEOUT`, `DRYRUN`, and `NOTIFY` remain compatible.
See the
[upstream configuration reference](https://github.com/P-Adamiec/Free-Games-Claimer-Remaster#configuration)
for all available settings.
For complete configuration options and advanced settings, see: https://github.com/vogler/free-games-claimer#configuration--options ## Upgrade from version 1.8
### Important Notes Version 2.0 changes the application engine from
`vogler/free-games-claimer` (Node.js, Playwright, and Firefox) to
`P-Adamiec/Free-Games-Claimer-Remaster` (Python, nodriver, and Chromium).
The add-on performs the following migration automatically on first start:
- **VNC Issues**: The NoVNC web interface is currently not working reliably on several machines 1. The existing `config.env` remains at the same configured location.
- **Recommended**: Use the `config.env` file for configuration instead of the web interface 2. Legacy `epic-games.json`, `prime-gaming.json`, and `gog.json` claim history
- **Security**: Store credentials securely and consider using app-specific passwords where available is imported into the remaster SQLite database at `/data/fgc.db`.
3. Existing database rows are detected and are not duplicated if migration is
retried.
4. A pre-migration database backup is created when an existing `fgc.db` is
present.
5. All old files remain under `/data/data` for rollback or manual recovery.
### Custom Scripts and Environment Variables Browser sessions cannot be converted because the old add-on used a shared
Firefox profile while the remaster uses separate Chromium profiles per store.
Credentials remain available through `config.env`, but accounts that require
interactive authentication may need a one-time login through noVNC after the
upgrade. The old Firefox profile is retained and is never deleted.
This addon supports custom scripts and environment variables through the `addon_config` mapping: The external noVNC port remains `6080`, although the standalone remaster image
normally uses port `7080`.
- **Custom scripts**: See [Running Custom Scripts in Addons](https://github.com/alexbelgium/hassio-addons/wiki/Running-custom-scripts-in-Addons) ## Upstream update policy
- **env_vars option**: Use the add-on `env_vars` option to pass extra environment variables (uppercase or lowercase names). See https://github.com/alexbelgium/hassio-addons/wiki/Add-Environment-variables-to-your-Addon-2 for details.
The image is built from an explicit upstream commit in the Dockerfile. This
keeps amd64 and aarch64 images reproducible and prevents an upstream branch or
container tag from changing without an add-on review and version bump.
The repository updater is intentionally paused for this add-on because the
add-on uses its own `2.x` version series while the replacement upstream uses a
`1.x` version series. An automatic replacement would risk a Home Assistant
version regression and would not safely update the pinned commit. A maintainer
upstream update must therefore update `UPSTREAM_REF`, `upstream_version`, the
add-on version, and `CHANGELOG.md` together.
## Installation ## Installation
The installation of this add-on is pretty straightforward and not different in comparison to installing any other add-on. 1. Add this add-on repository to the Home Assistant add-on store.
2. Install **Free Games Claimer**.
3. Configure the add-on options as needed.
4. Start the add-on and review its log.
5. Open noVNC if an account needs manual authentication.
1. Add my add-ons repository to your home assistant instance (in supervisor addons store at top right, or click button below if you have configured my HA) [![Open your Home Assistant instance and show the add add-on repository dialog with a specific repository URL pre-filled.](https://my.home-assistant.io/badges/supervisor_add_addon_repository.svg)](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Falexbelgium%2Fhassio-addons)
[![Open your Home Assistant instance and show the add add-on repository dialog with a specific repository URL pre-filled.](https://my.home-assistant.io/badges/supervisor_add_addon_repository.svg)](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Falexbelgium%2Fhassio-addons)
1. Install this add-on. ## Custom scripts and environment variables
1. Click the `Save` button to store your configuration.
1. Set the add-on options to your preferences - [Running custom scripts in add-ons](https://github.com/alexbelgium/hassio-addons/wiki/Running-custom-scripts-in-Addons)
1. Start the add-on. - [Passing environment variables to an add-on](https://github.com/alexbelgium/hassio-addons/wiki/Add-Environment-variables-to-your-Addon-2)
1. Check the logs of the add-on to see if everything went well.
1. Open the webUI and adapt the software options
## Support ## Support
Create an issue on github Open an issue in the
[add-on repository](https://github.com/alexbelgium/hassio-addons/issues).
[repository]: https://github.com/alexbelgium/hassio-addons

View File

@@ -1,6 +1,6 @@
{ {
"build_from": { "build_from": {
"aarch64": "ghcr.io/vogler/free-games-claimer:latest", "aarch64": "debian:bookworm-slim",
"amd64": "ghcr.io/vogler/free-games-claimer:latest" "amd64": "debian:bookworm-slim"
} }
} }

View File

@@ -1,9 +1,10 @@
# Free Games Claimer Remaster add-on (pinned source)
arch: arch:
- aarch64 - aarch64
- amd64 - amd64
description: description: >-
automatically claims free games on the Epic Games Store, Amazon Prime Automatically claims free games from Epic Games Store, Amazon Prime Gaming,
Gaming and GOG GOG, Steam, and optional GamerPower-supported stores.
devices: devices:
- /dev/dri - /dev/dri
- /dev/dri/card0 - /dev/dri/card0
@@ -73,25 +74,29 @@ init: false
map: map:
- addon_config:rw - addon_config:rw
- homeassistant_config:rw - homeassistant_config:rw
name: Free Games Claimer (NoVNC not working) name: Free Games Claimer
options: options:
env_vars: [] env_vars: []
CMD_ARGUMENTS: node epic-games ; node prime-gaming ; node gog CMD_ARGUMENTS: node epic-games ; node prime-gaming ; node gog
STORES: ""
RUN_ONCE: true
CONFIG_LOCATION: /config/config.env CONFIG_LOCATION: /config/config.env
ports: ports:
5900/tcp: null 5900/tcp: null
6080/tcp: 6080 6080/tcp: 6080
ports_description: ports_description:
5900/tcp: VNC port 5900/tcp: VNC port
6080/tcp: NOVNC port 6080/tcp: noVNC web interface
schema: schema:
env_vars: env_vars:
- name: match(^[A-Za-z0-9_]+$) - name: match(^[A-Za-z0-9_]+$)
value: str? value: str?
CMD_ARGUMENTS: str CMD_ARGUMENTS: str?
STORES: str?
RUN_ONCE: bool
CONFIG_LOCATION: str CONFIG_LOCATION: str
slug: free_games_claimer slug: free_games_claimer
udev: true udev: true
url: https://github.com/alexbelgium/hassio-addons url: https://github.com/alexbelgium/hassio-addons
version: "1.8" version: "2.0.0"
webui: "[PROTO:ssl]://[HOST]:[PORT:6080]" webui: "[PROTO:ssl]://[HOST]:[PORT:6080]"

View File

@@ -1,85 +1,152 @@
#!/usr/bin/env bashio #!/usr/bin/env bashio
# shellcheck shell=bash # shellcheck shell=bash
set -e set -eo pipefail
############## CONFIG_FILE="/config/config.env"
# Initialize # if bashio::config.has_value 'CONFIG_LOCATION'; then
############## CONFIG_FILE="$(bashio::config 'CONFIG_LOCATION')"
fi
CONFIG_DIR="$(dirname "${CONFIG_FILE}")"
RUNTIME_CONFIG="/data/config.env"
CONFIG_HOME="$(bashio::config "CONFIG_LOCATION")" mkdir -p "${CONFIG_DIR}" /data
CONFIG_HOME="$(dirname "$CONFIG_HOME")"
# Use new config file # Recover from an old add-on bug that could create config.env as a directory.
if [ ! -f "$CONFIG_HOME/config.env" ]; then if [ -d "${CONFIG_FILE}" ]; then
# Copy default config.env bashio::log.warning "Found a directory at ${CONFIG_FILE}; replacing it with a configuration file"
cp /templates/config.env "$CONFIG_HOME/" rm -rf "${CONFIG_FILE}"
chmod 755 "$CONFIG_HOME/config.env" fi
bashio::log.warning "A default config.env file was copied to $CONFIG_HOME. Please customize according to https://github.com/vogler/free-games-claimer/tree/main#configuration--options and restart the add-on"
if [ ! -f "${CONFIG_FILE}" ]; then
install -m 0600 /templates/config.env "${CONFIG_FILE}"
bashio::log.warning \
"Created ${CONFIG_FILE}. Add account credentials there and restart the add-on if automatic login is required."
else else
bashio::log.info "Using existing config.env file in $CONFIG_HOME. Please customize according to https://github.com/vogler/free-games-claimer/tree/main#configuration--options and restart the add-on" bashio::log.info "Using configuration from ${CONFIG_FILE}"
fi fi
# Remove erroneous folder named config.env (bug fix for looping issue) # The remaster reads /fgc/data/config.env. /fgc/data is linked to Home
if [ -d "$CONFIG_HOME/config.env" ]; then # Assistant's persistent /data volume by the Dockerfile.
bashio::log.warning "Found directory named config.env, deleting it..." install -m 0600 "${CONFIG_FILE}" "${RUNTIME_CONFIG}"
rm -rf "$CONFIG_HOME/config.env" # Fix: Ensures directory removal even if it exists sed -i 's/\r$//' "${RUNTIME_CONFIG}"
cp /templates/config.env "$CONFIG_HOME/config.env" # Recreate as a valid file
chmod 755 "$CONFIG_HOME/config.env"
fi
# Copy new file # Export values needed by the VNC entrypoint as well as by the Python app.
mkdir -p /data/data
cp "$CONFIG_HOME/config.env" /data/data/
# Permissions
chmod -R 755 "$CONFIG_HOME"
# Export variables
set -a set -a
echo ""
bashio::log.info "Sourcing variables from $CONFIG_HOME/config.env"
cp "$CONFIG_HOME"/config.env /config.env
# Remove previous instance
sed -i "s|export ||g" /config.env
# Add export for non empty lines
sed -i '/\S/s/^/export /' /config.env
# Delete lines starting with #
sed -i '/export #/d' /config.env
# Get variables
# shellcheck source=/dev/null # shellcheck source=/dev/null
source /config.env source "${RUNTIME_CONFIG}"
rm /config.env
set +a set +a
############## # The Home Assistant port mapping is intentionally kept at 6080 for a seamless
# Launch App # # upgrade from the previous add-on, even though the new upstream defaults to 7080.
############## if [ -n "${NOVNC_PORT:-}" ] && [ "${NOVNC_PORT}" != "6080" ]; then
bashio::log.warning "NOVNC_PORT=${NOVNC_PORT} is not supported by the add-on port mapping; using 6080"
fi
export NOVNC_PORT="6080"
export VNC_PORT="5900"
# Go to folder # Absolute paths from the former image pointed to its Firefox profile. The
cd /data || true # replacement uses Chromium profiles and must start with a separate directory.
if [ "${BROWSER_DIR:-}" = "/data/data/browser" ]; then
bashio::log.warning "Remapping legacy Firefox BROWSER_DIR to the remaster Chromium profile directory"
export BROWSER_DIR="data/browser"
fi
if [ "${SCREENSHOTS_DIR:-}" = "/data/data/screenshots" ]; then
export SCREENSHOTS_DIR="/fgc/data/screenshots"
fi
# Fetch commands append_store() {
CMD_ARGUMENTS="$(bashio::config "CMD_ARGUMENTS")" local store="${1}"
IFS=';' local current="${2}"
read -ar strarr <<< "$CMD_ARGUMENTS"
# Sanitizes commands if [[ ",${current}," == *",${store},"* ]]; then
trim() { printf '%s' "${current}"
local var="$*" elif [ -n "${current}" ]; then
var="${var#"${var%%[![:space:]]*}"}" printf '%s,%s' "${current}" "${store}"
var="${var%"${var##*[![:space:]]}"}" else
printf '%s' "$var" printf '%s' "${store}"
fi
} }
# Add docker-entrypoint command legacy_commands_to_stores() {
for val in "${strarr[@]}"; do local commands="${1}"
val="$(trim "$val")" local selected=""
echo " " local command=""
bashio::log.info "Starting the app with arguments \"$val\"" local normalized=""
echo " " local command_list=()
echo "$val" | xargs docker-entrypoint.sh || true
done
bashio::log.info "All actions concluded. Stopping in 10 seconds." IFS=';' read -ra command_list <<< "${commands}"
sleep 10 for command in "${command_list[@]}"; do
bashio::addon.stop normalized="${command,,}"
case "${normalized}" in
*epic-games*|*epicgames*|*" epic"*|epic*)
selected="$(append_store "epic" "${selected}")"
;;
*prime-gaming*|*primegaming*|*" prime"*|prime*|*" amazon"*|amazon*)
selected="$(append_store "prime" "${selected}")"
;;
*steam-games*|*" steam"*|steam*)
selected="$(append_store "steam" "${selected}")"
;;
*gamerpower*)
selected="$(append_store "gamerpower" "${selected}")"
;;
*" gog"*|gog*)
selected="$(append_store "gog" "${selected}")"
;;
esac
done
printf '%s' "${selected}"
}
# A non-empty STORES add-on option takes priority. Otherwise retain a STORES
# value from config.env, then fall back to translating the legacy commands.
STORES_OPTION=""
if bashio::config.has_value 'STORES'; then
STORES_OPTION="$(bashio::config 'STORES')"
fi
if [ -n "${STORES_OPTION}" ]; then
export STORES="${STORES_OPTION}"
elif [ -z "${STORES:-}" ]; then
CMD_ARGUMENTS=""
if bashio::config.has_value 'CMD_ARGUMENTS'; then
CMD_ARGUMENTS="$(bashio::config 'CMD_ARGUMENTS')"
fi
STORES="$(legacy_commands_to_stores "${CMD_ARGUMENTS}")"
export STORES="${STORES:-epic,prime,gog}"
fi
bashio::log.info "Enabled stores: ${STORES:-epic,prime,gog}"
# Import claim history from vogler/free-games-claimer once. Legacy files and
# browser data are retained under /data/data for rollback and manual recovery.
/usr/local/bin/migrate_vogler_data.py
APP_COMMAND=(python3 /fgc/main.py)
RUN_ONCE="true"
if bashio::config.has_value 'RUN_ONCE' && ! bashio::config.true 'RUN_ONCE'; then
RUN_ONCE="false"
fi
if [ "${RUN_ONCE}" = "true" ]; then
APP_COMMAND+=(--once)
bashio::log.info "Starting a single claiming run (legacy-compatible mode)"
set +e
/usr/local/bin/docker-entrypoint.sh "${APP_COMMAND[@]}"
exit_code=$?
set -e
if [ "${exit_code}" -ne 0 ]; then
bashio::log.error "Free Games Claimer exited with status ${exit_code}"
else
bashio::log.info "Claiming run completed"
fi
bashio::log.info "Stopping the add-on"
sleep 2
bashio::addon.stop
exit "${exit_code}"
fi
bashio::log.info "Starting the built-in scheduler"
exec /usr/local/bin/docker-entrypoint.sh "${APP_COMMAND[@]}"

View File

@@ -1,7 +1,39 @@
HEIGHT=1280 # Free Games Claimer Remaster configuration
LOGIN_TIMEOUT=180 # Complete option reference:
NOTIFY_TITLE='Free Games Claimer' # https://github.com/P-Adamiec/Free-Games-Claimer-Remaster#configuration
# List of environment variables, see : https://github.com/vogler/free-games-claimer#configuration--options
# Browser and noVNC
SHOW=1 SHOW=1
TIMEOUT=60
WIDTH=1280 WIDTH=1280
HEIGHT=720
TIMEOUT=60
LOGIN_TIMEOUT=180
VNC_LOGIN_TIMEOUT=180
NOVNC_PORT=6080
# Keep the previous add-on's default stores. Add steam or gamerpower if wanted.
STORES=epic,prime,gog
# Used only when RUN_ONCE is disabled in the add-on options.
SCHEDULER_HOURS=12
# Common credentials can be used as fallbacks for all stores.
# EMAIL=
# PASSWORD=
# Store-specific credentials take priority over EMAIL/PASSWORD.
# EG_EMAIL=
# EG_PASSWORD=
# EG_OTPKEY=
# EG_PARENTALPIN=
# PG_EMAIL=
# PG_PASSWORD=
# PG_OTPKEY=
# GOG_EMAIL=
# GOG_PASSWORD=
# STEAM_USERNAME=
# STEAM_PASSWORD=
# Notifications (Apprise or Discord)
# NOTIFY=
# DISCORD_WEBHOOK=

View File

@@ -0,0 +1,248 @@
#!/usr/bin/env python3
"""Migrate legacy vogler/free-games-claimer JSON history to the remaster DB."""
from __future__ import annotations
import json
import os
import shutil
import sqlite3
import sys
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Iterator
DATA_DIR = Path(os.environ.get("FGC_DATA_DIR", "/data"))
LEGACY_DIR = DATA_DIR / "data"
DATABASE = DATA_DIR / "fgc.db"
MARKER = DATA_DIR / ".vogler-remaster-migrated-v1.json"
BACKUP = DATA_DIR / "fgc.db.pre-vogler-migration"
SOURCES = {
"epic": "epic-games.json",
"prime": "prime-gaming.json",
"gog": "gog.json",
}
def log(message: str) -> None:
print(f"[legacy migration] {message}", flush=True)
def locate_source(filename: str) -> Path | None:
"""Prefer the old nested data directory, with a root fallback."""
for candidate in (LEGACY_DIR / filename, DATA_DIR / filename):
if candidate.is_file():
return candidate
return None
def normalize_timestamp(value: Any) -> str:
if isinstance(value, str) and value.strip():
raw = value.strip().replace("Z", "+00:00")
try:
parsed = datetime.fromisoformat(raw)
if parsed.tzinfo is not None:
parsed = parsed.astimezone(timezone.utc).replace(tzinfo=None)
return parsed.isoformat(sep=" ", timespec="seconds")
except ValueError:
pass
return datetime.now(timezone.utc).replace(tzinfo=None).isoformat(
sep=" ", timespec="seconds"
)
def clean(value: Any, *, default: str = "", limit: int | None = None) -> str:
result = default if value is None else str(value)
if limit is not None:
result = result[:limit]
return result
def iter_records(store: str, payload: Any, source: Path) -> Iterator[dict[str, Any]]:
if not isinstance(payload, dict):
raise ValueError(f"{source} does not contain a JSON object")
for user, games in payload.items():
if not isinstance(games, dict):
continue
for legacy_id, value in games.items():
record = value if isinstance(value, dict) else {}
title = clean(record.get("title"), default=clean(legacy_id), limit=512)
game_id = clean(legacy_id, default=title, limit=256)
if not game_id:
game_id = title[:256] or "unknown"
legacy_store = record.get("store")
extra = {
"migration_source": str(source),
"legacy_store": legacy_store,
"legacy_time": record.get("time") or record.get("timestamp"),
}
extra = {key: val for key, val in extra.items() if val not in (None, "")}
yield {
"store": store,
"user": clean(user, default="unknown", limit=128) or "unknown",
"game_id": game_id,
"title": title or game_id,
"url": clean(record.get("url"), limit=None) or None,
"status": clean(record.get("status"), default="unknown", limit=64)
or "unknown",
"code": clean(record.get("code"), limit=128) or None,
"extra": json.dumps(extra, ensure_ascii=False) if extra else None,
"created_at": normalize_timestamp(
record.get("time") or record.get("timestamp")
),
}
def ensure_schema(connection: sqlite3.Connection) -> None:
connection.executescript(
"""
CREATE TABLE IF NOT EXISTS claimed_games (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
store VARCHAR(32) NOT NULL,
user VARCHAR(128) NOT NULL,
game_id VARCHAR(256) NOT NULL,
title VARCHAR(512) NOT NULL,
url TEXT,
status VARCHAR(64) NOT NULL DEFAULT 'unknown',
code VARCHAR(128),
extra TEXT,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS ix_claimed_games_store ON claimed_games (store);
CREATE INDEX IF NOT EXISTS ix_claimed_games_user ON claimed_games (user);
CREATE INDEX IF NOT EXISTS ix_claimed_games_game_id ON claimed_games (game_id);
"""
)
def migrate() -> int:
DATA_DIR.mkdir(parents=True, exist_ok=True)
if MARKER.exists():
log("Legacy claim history was already migrated")
return 0
sources = {
store: source
for store, filename in SOURCES.items()
if (source := locate_source(filename)) is not None
}
legacy_browser = LEGACY_DIR / "browser"
if not sources:
if legacy_browser.exists():
log(
"Legacy Firefox browser data was found but cannot be converted to "
"the remaster Chromium profile; a one-time login may be required"
)
MARKER.write_text(
json.dumps(
{
"migrated_at": datetime.now(timezone.utc).isoformat(),
"imported": 0,
"sources": [],
},
indent=2,
),
encoding="utf-8",
)
log("No legacy claim-history files were found")
return 0
if DATABASE.exists() and not BACKUP.exists():
shutil.copy2(DATABASE, BACKUP)
log(f"Backed up the existing database to {BACKUP}")
imported = 0
skipped = 0
errors: list[str] = []
try:
with sqlite3.connect(DATABASE) as connection:
ensure_schema(connection)
for store, source in sources.items():
try:
payload = json.loads(source.read_text(encoding="utf-8"))
source_imported = 0
for record in iter_records(store, payload, source):
exists = connection.execute(
"""
SELECT 1 FROM claimed_games
WHERE store = ? AND user = ? AND game_id = ?
LIMIT 1
""",
(record["store"], record["user"], record["game_id"]),
).fetchone()
if exists:
skipped += 1
continue
connection.execute(
"""
INSERT INTO claimed_games (
store, user, game_id, title, url, status, code,
extra, created_at, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
record["store"],
record["user"],
record["game_id"],
record["title"],
record["url"],
record["status"],
record["code"],
record["extra"],
record["created_at"],
record["created_at"],
),
)
imported += 1
source_imported += 1
connection.commit()
log(f"Imported {source_imported} record(s) from {source}")
except (OSError, ValueError, json.JSONDecodeError, sqlite3.Error) as err:
connection.rollback()
message = f"Failed to import {source}: {err}"
errors.append(message)
log(message)
except sqlite3.Error as err:
log(f"Database migration failed: {err}")
return 1
if legacy_browser.exists():
log(
"Legacy Firefox browser data remains in /data/data/browser. It is "
"not compatible with Chromium, so use noVNC for a one-time login if needed."
)
if errors:
log("Migration was incomplete and will be retried on the next start")
return 0
MARKER.write_text(
json.dumps(
{
"migrated_at": datetime.now(timezone.utc).isoformat(),
"imported": imported,
"skipped_existing": skipped,
"sources": [str(path) for path in sources.values()],
},
indent=2,
),
encoding="utf-8",
)
log(f"Migration complete: {imported} imported, {skipped} already present")
return 0
if __name__ == "__main__":
sys.exit(migrate())

View File

@@ -1,10 +1,11 @@
{ {
"dockerhub_by_date": true, "dockerhub_by_date": false,
"dockerhub_list_size": 2, "dockerhub_list_size": 2,
"last_update": "17-05-2025", "last_update": "17-07-2026",
"paused": true,
"repository": "alexbelgium/hassio-addons", "repository": "alexbelgium/hassio-addons",
"slug": "free_games_claimer", "slug": "free_games_claimer",
"source": "github", "source": "github",
"upstream_repo": "vogler/free-games-claimer", "upstream_repo": "P-Adamiec/Free-Games-Claimer-Remaster",
"upstream_version": "1.8" "upstream_version": "1.1"
} }