EggContractor is a self-hosted contract monitoring web app + CLI client for Egg

EggContractor

Build status Docker pulls Gallery

EggContractor is a self-hosted contract monitoring web app + CLI client for Egg, Inc.. It allows you to easily monitor all your contract progress, as well as peeking into prospective coops you may want to join.

Note that reverse engineered API protobufs are independently available at misc/protobuf, so you may also find this repo useful for building your own client. (There is also an initially hand-reversed version actually used by this codebase.) You can also find a best-effort contract database at misc/ContractAggregator.

Demo

Below are some semi-interactive demo pages (pre-rendered, with in-page interactivity, but inter-page interactivity is likely broken). Note that the demo pages were captured from the MVP version of EggContractor, hence somewhat outdated; since then a number of major features have been implemented; for instance, contract progress bars, offline timer for each coop member, and projection of eggs laid based on that.

You can also find screenshots in the gallery.

Comparison to egginc.mioi.io

Advantages:

  • No rate limiting, obviously.

  • All the info about all your active contracts (solos & coops) is right on the home page. Even the coop "peeker" widget is right there. No clicking around.

  • Sort coop members by EB, egg laying rate, etc. Very handy.

  • View a list of coops you recently "peeked". Demo page.

  • Stats are routinely retrieved in the background (frequency easily configurable) and stored in a database. So you can project the actual number of eggs laid by taking into account how long each coop member has been offline (implemented), travel back in time to view your contract statuses in the past (implemented), or plot every player's progress.

  • Send you push notifications (via Pushover) when new contracts come online.

Disadvantages:

  • Frontend fanciness in general. I didn't bother to invest time into the frontend, so no pretty little pictures, no progress bars, and no dark theme (kind of a shame, not hard to add though). Hopefully you can still easily pick out whatever info you need from my UI. EggContractor now has fancy progress bars too!

  • No home farm info. I don't need a separate web app to learn about my home farm, so not much of a disadvantage actually.

  • No "Contract Calculator". I never used that feature so not sure how useful.

Installation & deployment

docker-compose is the recommended method of deployment. Sorry k8s fans.

docker-compose.yml:

version: "3"
services:
  app:
    image: fanaticscripter/eggcontractor:latest
    container_name: EggContractor
    restart: always
    environment:
      # TZ should be set to the local timezone in .env; e.g. TZ=America/New_York
      - TZ=${TZ}
    ports:
      # Use 0.0.0.0 only if you want to access the web app on the local network
      # directly, without a reverse proxy layer. You may change the host port
      # (the first port number) to another value.
      - "0.0.0.0:8080:8080"
    volumes:
      # config.toml should set database.path to /data/data.db
      - ./config.toml:/config.toml
      - ./data:/data
    labels:
      ofelia.enabled: "true"
      # Scheduling refreshes.
      #
      # Schedule syntax is documented at
      # - https://github.com/mcuadros/ofelia
      # - https://pkg.go.dev/github.com/robfig/[email protected]
      # Note that if you use cron syntax, the syntax has been extended to add
      # a second field at the beginning, so every minute would be "0 * * * * *"
      # instead of "* * * * *", and so on.
      ofelia.job-exec.refresh.schedule: "@every 2m"
      ofelia.job-exec.refresh.user: 0
      ofelia.job-exec.refresh.command: "/EggContractor refresh"
      ofelia.job-exec.refresh.save-folder: /logs
      ofelia.job-exec.refresh.save-only-on-error: true
      # Scheduling daily database backups.
      ofelia.job-exec.db-backup.schedule: "0 0 0 * * *"
      ofelia.job-exec.db-backup.user: 0
      ofelia.job-exec.db-backup.command: "/EggContractor backup"
      ofelia.job-exec.db-backup.save-folder: /logs
      ofelia.job-exec.db-backup.save-only-on-error: true

  ofelia:
    image: mcuadros/ofelia:latest
    container_name: EggContractor_sched
    restart: always
    depends_on:
      - app
    command: daemon --docker
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./logs:/logs

config.toml:

[player]
# player.id, required.
#
# Your unique player ID. To view your player ID, go to Main Menu -> Settings ->
# Privacy & Data, and the ID should be in the bottom left corner. On iOS (at
# least when signed in via Game Center) this would be of the format G:1234567890.
# Copy the string verbatim for this field.
id = "G:1234567890"

[database]
path = "/data/data.db"

[notification]
  [notification.pushover]
  # notification.pushover.on, optional.
  #
  # If true, turn on notifications through Pushover; in that case, api_key and
  # user_key below are required.
  #
  # Default is false.
  #on = true

  # See https://pushover.net/api#registration.
  #api_key = "azGDORePK8gMaC0QOYAMyEEuzJnyUi"

  # See https://pushover.net/api#identifiers. A group key, or a comma-delimited
  # list of user keys may be used here instead.
  #user_key = "uQiRzpo4DXghDmr9QzzfQu27cmVRsG"

.env:

# Set your local timezone here.
TZ=America/New_York

With these files in place,

$ docker-compose up

Nginx reverse proxying

In case you need help putting nginx in front for SSL termination and stuff, here's my nginx config:

server {
    server_name egg.my.domain;
    root /var/www/html;

    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    ssl_certificate /etc/letsencrypt/live/my.domain/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/my.domain/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    access_log /var/log/nginx/egg.access.log;
    error_log /var/log/nginx/egg.error.log;

    add_header Strict-Transport-Security "max-age=31536000" always;

    location / {
        proxy_pass         http://127.0.0.1:8080;

        proxy_http_version 1.1;
        proxy_buffering    off;
        proxy_set_header   Host                 $host;
        proxy_set_header   Origin               http://$host;
        proxy_set_header   X-Real-IP            $remote_addr;
        proxy_set_header   X-Forwarded-For      $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto    $scheme;
    }
}

server {
    server_name egg.my.domain;

    listen 80;
    listen [::]:80;

    return 301 https://egg.my.domain$request_uri;
}

CLI

$ ./EggContractor help
Usage:
  EggContractor [command]

Available Commands:
  config          Print current configurations
  config-template Print a config file template
  contracts       Print a list of current and past contracts
  events          Print current and past events
  help            Help about any command
  peek            Peek at a coop
  peeked          Print list of recently peeked coops
  refresh         Refresh game state and print statuses of active solo contracts & coops
  serve           Run web server
  status          Print statuses of active solo contracts & coops from last refresh
  units           Print a table of units (order of magnitudes)

Flags:
      --config string    config file, could also be set through env var EGGCONTRACTOR_CONFIG_FILE (default ~/.config/EggContractor/config.toml)
      --debug            enable debug logging
  -h, --help             help for EggContractor
  -s, --sort criterion   sort coop members by one of the following criteria: 'eggs_laid' (aliases: 'contribution', 'total', 'laid'), 'laying_rate' (alias: 'rate'), or 'earning_bonus' (alias: 'eb') (default eggs_laid)
  -v, --verbose          enable verbose logging

Use "EggContractor [command] --help" for more information about a command.

Use help on individual subcommands to learn more about them.

If you're running the docker-compose setup, you need to use

docker exec EggContractor /EggContractor [command]

or

docker-compose exec app /EggContractor [command]

to use the CLI. You may want to set up a shell alias.

Known issues

  • When running the Docker image via Docker for Mac, with a mounted data directory, everything would seem fine and dandy until one accesses the SQLite database from the host system (e.g. do a SELECT on it), at which point all subsequent attempts to open the database from within the container would fail with "unable to open database file" (the error comes from sqlite itself, so doesn't matter if one uses the sqlite3 CLI or the golang driver; the go-sqlite3 driver does however misleadingly add a file/directory does not exist error message, which is irrelevant since the file can be open(2)'ed alright).

    This might be an issue in SQLite / Docker for Mac filesystem driver interactions. I've yet to isolate it.

    Workaround: run the Docker image on a Linux host. Probably already doing that outside of development anyway.

License

The MIT license.

Owner
Z. Wang
I post half-joking code to this account.
Z. Wang
Comments
  • Failure trying to load account data

    Failure trying to load account data

    Thanks for all the awesome tools, they've really been making the game a lot more fun since I discovered them! But lately I've run into a problem: starting about a day ago, any tools that use my account data (I've tried EggContractor, the rockets tracker, and the past contracts viewer) fail on trying to load. Most of the time, the error is this:

    POST https://wasmegg.zw.workers.dev/?url=http://afx-2-dot-auxbrainhome.appspot.com/ei/first_contact: HTTP 500: "400 entity is too big"
    

    But every once in a while I get this instead:

    POST https://wasmegg.zw.workers.dev/?url=http://afx-2-dot-auxbrainhome.appspot.com/ei/first_contact: Post "https://wasmegg.zw.workers.dev/?url=http://afx-2-dot-auxbrainhome.appspot.com/ei/first_contact": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
    

    It seems to be specific to my account, because account IDs of family members who also play the game work just fine. The last time EggContractor was successfully able to update my account was 03/03 at around 10:10 am.

    Do you have any suggestions on how I might be able to debug this?

  • fusion-tankers thinks it's an elite contract

    fusion-tankers thinks it's an elite contract

    I started fusion-tankers as a Standard contract and became Elite during the course of it. The app currently thinks it is an Elite contract, despite it still being standard.

  • Info about the code: where iss the json data file?

    Info about the code: where iss the json data file?

    Regarding this line

    https://github.com/fanaticscripter/EggContractor/blob/master/port/wasm/artifact-explorer/src/App.vue#L47

    I don't find the json in this repository.

    I'm interested in studying the code

  • Explore durations over 1 day drops the

    Explore durations over 1 day drops the "day" and only shows hours

    image

    If your rocket has more than 24 hours remaining on the exploration, only the hours shows. For example I launched a 2 day explore, and there is 1 day and 20 hours remaining however the site only shows 20 hours remaining, however the graph is correct with how far into the duration it is.

  • Add countdown to enlightenment status page

    Add countdown to enlightenment status page

    I just copied the countdown plugin from the rocket tracker. I can move to a common folder if there is one.

    Found the status page and I like to see a countdown.

  • linux/arm64 Docker image contains the x86_64 EggContractor binary

    linux/arm64 Docker image contains the x86_64 EggContractor binary

    Hey 👋 new Egg, Inc. fan and am amazed by the community/reverse engineering skills 🤩

    I just went to run the EggContractor Docker image on a Pi 4 (arm64) and received the dreaded exec format error.

    Looking at the image directly, the x86_64 binary has been included rather than the arm64 binary.

    I wonder if buildkit is reusing the same builder image for all architectures?

Go-serverless-eth-event-listener - Go serverless, ethereum contract event listener with a sample contract

go-serverless-eth-event-listener This repository is for showing how to listen sm

May 19, 2022
Cloud torrent: a self-hosted remote torrent client, written in Go (golang)
Cloud torrent: a self-hosted remote torrent client, written in Go (golang)

Cloud torrent is a a self-hosted remote torrent client, written in Go (golang).

Dec 21, 2021
Self Hosted Terraform Registry backed by S3

tf-registry Self Hosted Terraform Registry backed by S3 Usage tf-registry Provides a simple http server that implements the Terraform Module Registry

Jan 8, 2023
A Go client implementing a client-side distributed consumer group client for Amazon Kinesis.
A Go client implementing a client-side distributed consumer group client for Amazon Kinesis.

Kinesumer is a Go client implementing a client-side distributed consumer group client for Amazon Kinesis.

Jan 5, 2023
Clusterpedia-client - clusterpedia-client supports the use of native client-go mode to call the clusterpedia API

clusterpedia-client supports the use of native client-go mode to call the cluste

Jan 7, 2022
Client-go - Clusterpedia-client supports the use of native client-go mode to call the clusterpedia API

clusterpedia-client supports the use of native client-go mode to call the cluste

Dec 5, 2022
Mrrobot - A simple greetings bot for Slack that uses events api and hosted on AWS Lambda

Mr. Robot a greeter bot for your slack community build_docker

Aug 21, 2022
Metrics package helps to create ydb-go-sdk traces with monitoring internal state of driver

metrics metrics package helps to create ydb-go-sdk traces with monitoring internal state of driver Usage import ( "fmt" "sync/mutex" "time

Jan 7, 2023
💻 Quotable.io API Wrapper + CLI App
💻 Quotable.io API Wrapper + CLI App

?? Quotable.io API Wrapper + CLI App

Sep 27, 2022
A simple self-hostable Machine Translation service, powered by spaGO

A simple self-hostable Machine Translation service, powered by spaGO

Nov 9, 2022
Self-service account creation and credential reset for FreeIPA
Self-service account creation and credential reset for FreeIPA

Auri Auri stands for: Automated User Registration IPA Auri implements self service account creation and reset of credentials for FreeIPA Features Requ

Dec 21, 2022
Self-Reproducing Programs

Quines: Self-Reproducing Programs This is a repository containing different implementations of self-reproducing programs. It is not meant to be a show

Jan 31, 2022
lightweight, self-service AWS IAM management
lightweight, self-service AWS IAM management

Contents Overview Architecture Prerequisites Workflow What groups exist? Who do I ask for access? What groups am I in? How do I add group members? How

Jan 16, 2022
Trakt-cli - A CLI for trakt.tv using the trakt.tv API
Trakt-cli - A CLI for trakt.tv using the trakt.tv API

trakt-cli ████████╗██████╗ █████╗ ██╗ ██╗████████╗ ██████╗██╗ ██╗ ╚══

Dec 27, 2022
🌺 cross-platform haste CLI client

haste haste is a cross-platform hastebin CLI client. installation go install github.com/x6r/haste@latest usage $ haste # interactively prompts you for

Jan 6, 2023
Client for the cloud-iso-client

cloud-iso-client Client for the cloud-iso-client. Register an API token Before using this client library, you need to register an API token under your

Dec 6, 2021
Go-http-client: An enhanced http client for Golang
Go-http-client: An enhanced http client for Golang

go-http-client An enhanced http client for Golang Documentation on go.dev ?? This package provides you a http client package for your http requests. Y

Jan 7, 2023
Nutanix-client-go - Go client for the Nutanix Prism V3 API

nutanix-client-go This repository contains portions of the Nutanix API client code in nutanix/terraform-provider-nutanix. It has been extracted to red

Jan 6, 2022
Aoe4-client - Client library for aoe4 leaderboards etc

AOE4 Client Overview This is a go client used to query AOE4 data from either the

Jan 18, 2022