Contribute - delgatojr/AFK-Daily GitHub Wiki

Thank you for thinking about contributing! Help is always welcome.

Join the project

Here are the first steps to your first contributions. You can either use the command line or GitHub Desktop:

Editor

We use Visual Studio Code to develop this project.

Extensions

Mandatory extensions:

Some other useful extensions:

Settings

Visual Studio Code generates a custom file inside repositories (.vscode/settings.json) for settings regarding the IDE and extensions. If you want, you can use our settings:

{
    // Global > Ruller
    "workbench.colorCustomizations": {
        "editorRuler.foreground": "#333" // rulers color
    },
    // Global > EOL > LF
    "files.eol": "\n",
    // shellscript
    "[shellscript]": {
        // Ruller
        "editor.rulers": [
            80, // Terminal windows
            125 // GitHub diff view
        ],
        // Tab
        "editor.insertSpaces": true,
        "editor.tabSize": 4,
        // EOL > LF
        "files.eol": "\n"
    },
    // Extension - markdownlint > https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint
    "markdownlint.config": {
        "default": true,
        "MD033": false, // https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md033
        "MD036": false, // https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md036
        "MD041": false  // https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md041
    },
    // Extension - shellcheck > https://marketplace.visualstudio.com/items?itemName=timonwong.shellcheck
    "shellcheck.customArgs": [
        "-x" // https://github.com/koalaman/shellcheck/wiki/SC1091
    ],
    "shellcheck.exclude": [
        "1017", // https://github.com/koalaman/shellcheck/wiki/SC1017
        "1090", // https://github.com/koalaman/shellcheck/wiki/SC1090
        "1091", // https://github.com/koalaman/shellcheck/wiki/SC1091
        "2009", // https://github.com/koalaman/shellcheck/wiki/SC2009
        "2034", // https://github.com/koalaman/shellcheck/wiki/SC2034
        "2039", // https://github.com/koalaman/shellcheck/wiki/SC2039
        "2154", // https://github.com/koalaman/shellcheck/wiki/SC2154
        "3003", // https://github.com/koalaman/shellcheck/wiki/SC3003
        "3057", // https://github.com/koalaman/shellcheck/wiki/SC3057
        "3060"  // https://github.com/koalaman/shellcheck/wiki/SC3060
    ],
    // Extension - Todo Tree > https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.todo-tree
    "todo-tree.general.tags": [
        "FIXME",
        "TODO",
        "WARN"
    ],
    "todo-tree.highlights.customHighlight": {
        "FIXME": {
            "foreground": "white",
            "background": "red",
            "icon": "flame",
            "iconColour": "red"
        },
        "TODO": {
            "foreground": "black",
            "background": "green",
            "icon": "check",
            "iconColour": "green"
        },
        "WARN": {
            "foreground": "black",
            "background": "yellow",
            "icon": "alert",
            "iconColour": "yellow"
        }
    }
    // Extension - Guides > https://marketplace.visualstudio.com/items?itemName=spywhere.guides
    // Extension - shell-format > https://marketplace.visualstudio.com/items?itemName=foxundermoon.shell-format
    // Extension - Trailing Spaces > https://marketplace.visualstudio.com/items?itemName=shardulm94.trailing-spaces
}

Check before a pull request

Before doing a pull request, please check that everything is still working, and that your development is clean and has comments.

You can use tools like WinMerge to check every modification.

Clean code

The principles of Clean Code apply to Bash as well. It really helps in having a robust script.

Many people hack together shell scripts quickly to do simple tasks, but these soon take on a life of their own. Unfortunately shell scripts are full of subtle effects which result in scripts failing in unusual ways. It’s possible to write scripts which minimise these problems.

source

Markdown - MarkdownLint

It's a bit useless, but well, if we are trying to do robust code, why not have robust Markdown too?

We are using MarkdownLint. Please try to have 0 warnings and/or errors.

I did remove some rules because they are too restrictive for a good looking ReadMe on GitHub:

  • MD033: As you know, Markdown can't center elements. Because of this, we are using HTML instead.
  • MD036: Without removing it you can't do **Lorem ipsum dolor sit amet**.
  • MD041: We are using HTML header because it's sexy instead of the classic # AFK-Daily.

Shell - ShellCheck

We are using ShellCheck. Please try to have 0 warnings and/or errors.

If you need to remove rules, please be certain that is your only choice. Here the list of the already removes rules:

  • 1090: Can't follow non-constant source
  • 1091: Not following (Source not found) -> link to the previous one
  • 2009: pgrep doesn't exixts in Git Bash
  • 2034: foo appears unused. Verify it or export it
  • 2039: In POSIX sh, string ... is undefined.
  • 2154: var is referenced but not assigned -> link to the previous one
  • 3057: In POSIX sh, string $'..' is undefined (Well, it works, required for Nox)
  • 3057: In POSIX sh, string indexing is undefined (Well, it works)
  • 3060: In POSIX sh, string replacement is undefined (Well, it works)

Best Practices

Here is the source of our best practices. We edited some of it for more portability and maintainability.

  1. Use functions

    Unless you’re writing a very small script, use functions to modularise your code and make it more readable, reusable and maintainable.

    myfunc() {
        logDebug "myfunc" 3 "ENTER"
        
        # Your code
    
        logDebug "myfunc" 3 "EXIT"
    }

    If you want more info: source.

  2. Document your functions

    Add sufficient documentation to your functions to specify what they do and what arguments are required to invoke them.

    Please complete this comment to explain every function:

    # ##############################################################################
    # Function Name  : myfunc
    # Description    : Test function
    # Args           :
    # Return         :
    # Remark         :
    # ##############################################################################
    myfunc() {
        logDebug "myfunc" 3 "ENTER"
    
        test 800 600            # do test
    
        logDebug "myfunc" 3 "EXIT"
    }

    Or at least:

    # myfunc <Args>
    # description if not explicit name
    # return values
    myfunc() {
        logDebug "myfunc" 3 "ENTER"
    
        test 800 600            # do test
    
        logDebug "myfunc" 3 "EXIT"
    }
    • Try to comment everything, every click, condition, loop. It really helps maintain the code.
    • Try to align comments, it helps for the visibility of them.
  3. Use shift to read function arguments

  4. Declare your variables

    Instead of local, prefix your variable with the name of the function (local is undefined in sh).

    myfunc() {
        _myfunc_local=0
    }
  5. Quote all parameter expansions

    To prevent word-splitting and file globbing you must quote all variable expansions. In particular, you must do this if you are dealing with filenames that may contain whitespace (or other special characters).

  6. Use arrays where appropriate

  7. Use "$@" to refer to all arguments

    Don’t use $*.

    The only exception is a direct output like in Debug ($@ is an array where $* is a string).

  8. Use uppercase variable names for environment variables only

    My personal preference is that all variables should be lowercase, except for environment variables.

  9. Prefer shell builtins over external programs

    The shell has the ability to manipulate strings and perform simple arithmetic...

  10. Avoid unnecessary pipelines

    Pipelines add extra overhead to your script so try to keep your pipelines small. Common examples of useless pipelines are cat and echo...

  11. Avoid parsing ls

  12. Use globbing

  13. Use null delimited output where possible

  14. Don’t use backticks

    Use $(command) instead of `command` because it is easier to nest multiple commands and makes your code more readable.

  15. Use process substitution instead of creating temporary files

  16. Use mktemp if you have to create temporary files

    Try to avoid creating temporary files. If you must, use mktemp to create a temporary directory and then write your files to it. Make sure you remove the directory after you are done.

  17. Use [[ and (( for test conditions

    Note that if you desire portability, you have to stick to the old-fashioned [ ... ]

    If you want more info: source.

  18. Use commands in test conditions instead of exit status

    If you want to check whether a command succeeded before doing something, use the command directly in the condition of your if-statement instead of checking the command’s exit status.

  19. Use set -e

  20. Write error messages to stderr

    Error messages belong on stderr not stdout.

    echo "[ERROR]" >&2

Some other useful documentation:

If you have any doubt, just ask, there will always be someone to answer (well, I hope so)!

Useful config files

config-Debug.ini
# --- CONFIG: Modify accordingly to your game! --- #
# --- Use this link for help: https://github.com/delgatojr/AFK-Daily/wiki/Config --- #
# Player
canOpenSoren=false
arenaHeroesOpponent=5

# General
waitForUpdate=false
endAt=mail
guildBattleType=quick
allowCrystalLevelUp=false

# Repetitions
maxCampaignFights=0
maxKingsTowerFights=0
totalAmountArenaTries=0
totalAmountTournamentTries=0
totalAmountGuildBossTries=0
totalAmountTwistedRealmBossTries=0

# Store
buyStoreDust=false
buyStorePoeCoins=false
buyStorePrimordialEmblem=false
buyStoreAmplifyingEmblem=false
buyStoreSoulstone=false
buyStoreLimitedElementalShard=false
buyStoreLimitedElementalCore=false
buyStoreLimitedTimeEmblem=false
buyWeeklyGuild=false
buyWeeklyLabyrinth=false

# Towers
doMainTower=false
doTowerOfLight=false
doTheBrutalCitadel=false
doTheWorldTree=false
doCelestialSanctum=false
doTheForsakenNecropolis=false
doInfernalFortress=false

# --- Actions --- #
# Campaign
doLootAfkChest=false
doChallengeBoss=false
doFastRewards=false
doCollectFriendsAndMercenaries=false

# Dark Forest
doSoloBounties=false
doTeamBounties=false
doArenaOfHeroes=false
doLegendsTournament=false
doKingsTower=false

# Ranhorn
doGuildHunts=false
doTwistedRealmBoss=false
doBuyFromStore=false
doStrengthenCrystal=false
doTempleOfAscension=false
doCompanionPointsSummon=false
doCollectOakPresents=false

# End
doCollectQuestChests=false
doCollectMail=false
doCollectMerchantFreebies=false
config-Test_Campaign.ini
# --- CONFIG: Modify accordingly to your game! --- #
# --- Use this link for help: https://github.com/delgatojr/AFK-Daily/wiki/Config --- #
# Player
canOpenSoren=false
arenaHeroesOpponent=5

# General
waitForUpdate=true
endAt=campaign
guildBattleType=quick
allowCrystalLevelUp=false

# Repetitions
maxCampaignFights=500
maxKingsTowerFights=0
totalAmountArenaTries=0
totalAmountTournamentTries=0
totalAmountGuildBossTries=0
totalAmountTwistedRealmBossTries=0

# Store
buyStoreDust=false
buyStorePoeCoins=false
buyStorePrimordialEmblem=false
buyStoreAmplifyingEmblem=false
buyStoreSoulstone=false
buyStoreLimitedElementalShard=false
buyStoreLimitedElementalCore=false
buyStoreLimitedTimeEmblem=false
buyWeeklyGuild=false
buyWeeklyLabyrinth=false

# Towers
doMainTower=false
doTowerOfLight=false
doTheBrutalCitadel=false
doTheWorldTree=false
doCelestialSanctum=false
doTheForsakenNecropolis=false
doInfernalFortress=false

# --- Actions --- #
# Campaign
doLootAfkChest=false
doChallengeBoss=true
doFastRewards=false
doCollectFriendsAndMercenaries=false

# Dark Forest
doSoloBounties=false
doTeamBounties=false
doArenaOfHeroes=false
doLegendsTournament=false
doKingsTower=false

# Ranhorn
doGuildHunts=false
doTwistedRealmBoss=false
doBuyFromStore=false
doStrengthenCrystal=false
doTempleOfAscension=false
doCompanionPointsSummon=false
doCollectOakPresents=false

# End
doCollectQuestChests=false
doCollectMail=false
doCollectMerchantFreebies=false
config-Test_Dark_Forest.ini
# --- CONFIG: Modify accordingly to your game! --- #
# --- Use this link for help: https://github.com/delgatojr/AFK-Daily/wiki/Config --- #
# Player
canOpenSoren=false
arenaHeroesOpponent=5

# General
waitForUpdate=true
endAt=mail
guildBattleType=quick
allowCrystalLevelUp=false

# Repetitions
maxCampaignFights=0
maxKingsTowerFights=10
totalAmountArenaTries=2+6+2
totalAmountTournamentTries=5
totalAmountGuildBossTries=0
totalAmountTwistedRealmBossTries=0

# Store
buyStoreDust=false
buyStorePoeCoins=false
buyStorePrimordialEmblem=false
buyStoreAmplifyingEmblem=false
buyStoreSoulstone=false
buyStoreLimitedElementalShard=false
buyStoreLimitedElementalCore=false
buyStoreLimitedTimeEmblem=false
buyWeeklyGuild=false
buyWeeklyLabyrinth=false

# Towers
doMainTower=true
doTowerOfLight=true
doTheBrutalCitadel=true
doTheWorldTree=true
doCelestialSanctum=true
doTheForsakenNecropolis=true
doInfernalFortress=true

# --- Actions --- #
# Campaign
doLootAfkChest=false
doChallengeBoss=false
doFastRewards=false
doCollectFriendsAndMercenaries=false

# Dark Forest
doSoloBounties=true
doTeamBounties=true
doArenaOfHeroes=true
doLegendsTournament=true
doKingsTower=true

# Ranhorn
doGuildHunts=false
doTwistedRealmBoss=false
doBuyFromStore=false
doStrengthenCrystal=false
doTempleOfAscension=false
doCompanionPointsSummon=false
doCollectOakPresents=false

# End
doCollectQuestChests=false
doCollectMail=false
doCollectMerchantFreebies=false
config-Test_Ranhorn.ini
# --- CONFIG: Modify accordingly to your game! --- #
# --- Use this link for help: https://github.com/delgatojr/AFK-Daily/wiki/Config --- #
# Player
canOpenSoren=false
arenaHeroesOpponent=5

# General
waitForUpdate=true
endAt=mail
guildBattleType=quick
allowCrystalLevelUp=true

# Repetitions
maxCampaignFights=0
maxKingsTowerFights=0
totalAmountArenaTries=0
totalAmountTournamentTries=0
totalAmountGuildBossTries=3
totalAmountTwistedRealmBossTries=3

# Store
buyStoreDust=true
buyStorePoeCoins=true
buyStorePrimordialEmblem=true
buyStoreAmplifyingEmblem=true
buyStoreSoulstone=true
buyStoreLimitedElementalShard=true
buyStoreLimitedElementalCore=true
buyStoreLimitedTimeEmblem=false
buyWeeklyGuild=true
buyWeeklyLabyrinth=true

# Towers
doMainTower=false
doTowerOfLight=false
doTheBrutalCitadel=false
doTheWorldTree=false
doCelestialSanctum=false
doTheForsakenNecropolis=false
doInfernalFortress=false

# --- Actions --- #
# Campaign
doLootAfkChest=false
doChallengeBoss=false
doFastRewards=false
doCollectFriendsAndMercenaries=false

# Dark Forest
doSoloBounties=false
doTeamBounties=false
doArenaOfHeroes=false
doLegendsTournament=false
doKingsTower=false

# Ranhorn
doGuildHunts=true
doTwistedRealmBoss=true
doBuyFromStore=true
doStrengthenCrystal=true
doTempleOfAscension=true
doCompanionPointsSummon=true
doCollectOakPresents=true

# End
doCollectQuestChests=false
doCollectMail=false
doCollectMerchantFreebies=false
config-Test_End.ini
# --- CONFIG: Modify accordingly to your game! --- #
# --- Use this link for help: https://github.com/delgatojr/AFK-Daily/wiki/Config --- #
# Player
canOpenSoren=false
arenaHeroesOpponent=5

# General
waitForUpdate=true
endAt=mail
guildBattleType=quick
allowCrystalLevelUp=false

# Repetitions
maxCampaignFights=0
maxKingsTowerFights=0
totalAmountArenaTries=0
totalAmountTournamentTries=0
totalAmountGuildBossTries=0
totalAmountTwistedRealmBossTries=0

# Store
buyStoreDust=false
buyStorePoeCoins=false
buyStorePrimordialEmblem=false
buyStoreAmplifyingEmblem=false
buyStoreSoulstone=false
buyStoreLimitedElementalShard=false
buyStoreLimitedElementalCore=false
buyStoreLimitedTimeEmblem=false
buyWeeklyGuild=false
buyWeeklyLabyrinth=false

# Towers
doMainTower=false
doTowerOfLight=false
doTheBrutalCitadel=false
doTheWorldTree=false
doCelestialSanctum=false
doTheForsakenNecropolis=false
doInfernalFortress=false

# --- Actions --- #
# Campaign
doLootAfkChest=false
doChallengeBoss=false
doFastRewards=false
doCollectFriendsAndMercenaries=false

# Dark Forest
doSoloBounties=false
doTeamBounties=false
doArenaOfHeroes=false
doLegendsTournament=false
doKingsTower=false

# Ranhorn
doGuildHunts=false
doTwistedRealmBoss=false
doBuyFromStore=false
doStrengthenCrystal=false
doTempleOfAscension=false
doCompanionPointsSummon=false
doCollectOakPresents=false

# End
doCollectQuestChests=true
doCollectMail=true
doCollectMerchantFreebies=true
⚠️ **GitHub.com Fallback** ⚠️