func checkMissingExchanges() []string {
	var tempArray []string
	for x := range usageData.Exchanges {
		tempArray = append(tempArray, usageData.Exchanges[x].Name)
	}
	supportedExchs := exchange.Exchanges
	for z := 0; z < len(supportedExchs); {
		if common.StringDataContainsInsensitive(tempArray, supportedExchs[z]) {
			supportedExchs = append(supportedExchs[:z], supportedExchs[z+1:]...)
			continue
		}
		z++
	}
	return supportedExchs
}
checkMissingExchanges checks if any supported exchanges are missing api checker functionality
package main
import (
	"context"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"
	"github.com/thrasher-corp/gocryptotrader/common"
	"github.com/thrasher-corp/gocryptotrader/common/crypto"
	exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
	"github.com/thrasher-corp/gocryptotrader/exchanges/request"
	"github.com/thrasher-corp/gocryptotrader/log"
	"golang.org/x/net/html"
)
const (
	githubPath           = "https://api.github.com/repos/%s/commits/master"
	jsonFile             = "updates.json"
	testJSONFile         = "testupdates.json"
	backupFile           = "backup.json"
	github               = "GitHub Sha Check"
	htmlScrape           = "HTML String Check"
	pathBinance          = "https://binance-docs.github.io/apidocs/spot/en/#change-log"
	pathOkCoin           = "https://www.okcoin.com/docs/en/#change-change"
	pathOkex             = "https://www.okex.com/docs/en/#change-change"
	pathFTX              = "https://github.com/ftexchange/ftx"
	pathBTSE             = "https://www.btse.com/apiexplorer/spot/#btse-spot-api"
	pathBitfinex         = "https://docs.bitfinex.com/docs/changelog"
	pathBitmex           = "https://www.bitmex.com/static/md/en-US/apiChangelog"
	pathANX              = "https://anxv3.docs.apiary.io/"
	pathPoloniex         = "https://docs.poloniex.com/#changelog"
	pathIbBit            = "https://api.itbit.com/docs"
	pathBTCMarkets       = "https://api.btcmarkets.net/openapi/info/index.yaml"
	pathEXMO             = "https://exmo.com/en/api/"
	pathBitstamp         = "https://www.bitstamp.net/api/"
	pathHitBTC           = "https://api.hitbtc.com/"
	pathBitflyer         = "https://lightning.bitflyer.com/docs?lang=en"
	pathKraken           = "https://www.kraken.com/features/api"
	pathAlphaPoint       = "https://alphapoint.github.io/slate/#introduction"
	pathYobit            = "https://www.yobit.net/en/api/"
	pathLocalBitcoins    = "https://localbitcoins.com/api-docs/"
	pathGetAllLists      = "https://api.trello.com/1/boards/%s/lists?cards=none&card_fields=all&filter=open&fields=all&key=%s&token=%s"
	pathNewCard          = "https://api.trello.com/1/cards?idList=%s&name=%s&key=%s&token=%s"
	pathChecklists       = "https://api.trello.com/1/checklists/%s/checkItems?%s&key=%s&token=%s"
	pathChecklistItems   = "https://api.trello.com/1/checklists/%s?fields=name&cards=all&card_fields=name&key=%s&token=%s"
	pathUpdateItems      = "https://api.trello.com/1/cards/%s/checkItem/%s?%s&key=%s&token=%s"
	pathCheckBoardID     = "https://api.trello.com/1/members/me/boards?key=%s&token=%s"
	pathNewChecklist     = "https://api.trello.com/1/checklists?idCard=%s&name=%s&key=%s&token=%s"
	pathNewList          = "https://api.trello.com/1/lists?name=%s&idBoard=%s&key=%s&token=%s"
	pathGetCards         = "https://api.trello.com/1/lists/%s/cards?key=%s&token=%s"
	pathGetChecklists    = "https://api.trello.com/1/cards/%s/checklists?&key=%s&token=%s"
	pathDeleteCheckitems = "https://api.trello.com/1/checklists/%s/checkItems/%s?key=%s&token=%s"
	complete             = "complete"
	incomplete           = "incomplete"
	createList           = "UpdatesList"
	createCard           = "UpdatesCard"
	createChecklist      = "UpdatesChecklist"
	btcMarkets           = "BTC Markets"
	okcoin               = "OkCoin International"
)
var (
	verbose, add, create, testMode bool
	apiKey, apiToken, trelloBoardID, trelloBoardName, trelloListID,
	trelloChecklistID, trelloCardID, exchangeName, checkType, tokenData,
	key, val, tokenDataEnd, textTokenData, dateFormat, regExp, path string
	configData, testConfigData, usageData Config
)
func main() {
	flag.StringVar(&apiKey, "apikey", "", "sets the API key for Trello board interaction")
	flag.StringVar(&apiToken, "apitoken", "", "sets the API token for Trello board interaction")
	flag.StringVar(&trelloChecklistID, "checklistid", "", "sets the checklist ID for Trello board interaction")
	flag.StringVar(&trelloCardID, "cardid", "", "sets the card ID for Trello board interaction")
	flag.StringVar(&trelloListID, "listid", "", "sets the list ID for Trello board interaction")
	flag.StringVar(&trelloBoardID, "boardid", "", "sets the board ID for Trello board interaction")
	flag.StringVar(&trelloBoardName, "boardname", "", "sets the board name for Trello board interaction")
	flag.StringVar(&exchangeName, "exchangename", "", "sets the exchangeName for the new exchange")
	flag.StringVar(&checkType, "checktype", "", "sets the checkType for the new exchange")
	flag.StringVar(&tokenData, "tokendata", "", "sets the tokenData for adding a new exchange")
	flag.StringVar(&key, "key", "", "sets the key for adding a new exchange")
	flag.StringVar(&val, "val", "", "sets the val for adding a new exchange")
	flag.StringVar(&tokenDataEnd, "tokendataend", "", "sets the tokenDataEnd for adding a new exchange")
	flag.StringVar(&textTokenData, "texttokendata", "", "sets the textTokenData for adding a new exchange")
	flag.StringVar(&regExp, "regexp", "", "sets the regExp for adding a new exchange")
	flag.StringVar(&dateFormat, "dateformat", "", "sets the dateFormat for adding a new exchange")
	flag.StringVar(&path, "path", "", "sets the path for adding a new exchange")
	flag.BoolVar(&add, "add", false, "used as a trigger to add a new exchange from command line")
	flag.BoolVar(&verbose, "verbose", false, "increases logging verbosity for API Update Checker")
	flag.BoolVar(&create, "create", false, "specifies whether to automatically create trello list, card and checklist in a given board")
	flag.Parse()
	var err error
	c := log.GenDefaultSettings()
	log.RWM.Lock()
	log.GlobalLogConfig = &c
	log.RWM.Unlock()
	log.SetupGlobalLogger()
	configData, err = readFileData(jsonFile)
	if err != nil {
		log.Error(log.Global, err)
		os.Exit(1)
	}
	testConfigData, err = readFileData(testJSONFile)
	if err != nil {
		log.Error(log.Global, err)
		os.Exit(1)
	}
	usageData = testConfigData
	if canUpdateTrello() || (create && areAPIKeysSet()) {
		usageData = configData
	}
	if add {
		switch checkType {
		case github:
			var data GithubData
			data.Repo = path
			err = addExch(exchangeName, checkType, data, false)
			if err != nil {
				log.Error(log.Global, err)
				os.Exit(1)
			}
		case htmlScrape:
			var data HTMLScrapingData
			data.TokenData = tokenData
			data.Key = key
			data.Val = val
			data.TokenDataEnd = tokenDataEnd
			data.TextTokenData = textTokenData
			data.DateFormat = dateFormat
			data.RegExp = regExp
			data.Path = path
			err = addExch(exchangeName, checkType, data, false)
			if err != nil {
				log.Error(log.Global, err)
				os.Exit(1)
			}
		}
	}
	var a string
	if canUpdateTrello() || create {
		setAuthVars()
		if trelloBoardName != "" {
			a, err = trelloGetBoardID()
			if err != nil {
				log.Error(log.Global, err)
				os.Exit(1)
			}
			trelloBoardID = a
		}
		if create {
			err = createAndSet()
			if err != nil {
				log.Error(log.Global, err)
				os.Exit(1)
			}
		}
		err = updateFile(backupFile)
		if err != nil {
			log.Error(log.Global, err)
			os.Exit(1)
		}
		err = checkUpdates(jsonFile)
		if err != nil {
			log.Error(log.Global, err)
			os.Exit(1)
		}
	} else {
		log.Warnln(log.Global, "This is a test update since API keys are not set.")
		err := checkUpdates(testJSONFile)
		if err != nil {
			log.Error(log.Global, err)
			os.Exit(1)
		}
		log.Infoln(log.Global, "API update check completed successfully")
	}
}
func createAndSet() error {
	var err error
	err = trelloCreateNewList()
	if err != nil {
		return err
	}
	err = trelloCreateNewCard()
	if err != nil {
		return err
	}
	err = trelloCreateNewChecklist()
	if err != nil {
		return err
	}
	setAuthVars()
	return nil
}
func setAuthVars() {
	if apiKey == "" {
		apiKey = configData.Key
		usageData.Key = configData.Key
	} else {
		configData.Key = apiKey
		usageData.Key = apiKey
	}
	if apiToken == "" {
		apiToken = configData.Token
		usageData.Token = configData.Token
	} else {
		configData.Token = apiToken
		usageData.Token = apiToken
	}
	if trelloCardID == "" {
		trelloCardID = configData.CardID
		usageData.CardID = configData.CardID
	} else {
		configData.CardID = trelloCardID
		usageData.CardID = trelloCardID
	}
	if trelloChecklistID == "" {
		trelloChecklistID = configData.ChecklistID
		usageData.ChecklistID = configData.ChecklistID
	} else {
		configData.ChecklistID = trelloChecklistID
		usageData.ChecklistID = trelloChecklistID
	}
	if trelloListID == "" {
		trelloListID = configData.ListID
		usageData.ListID = configData.ListID
	} else {
		configData.ListID = trelloListID
		usageData.ListID = trelloListID
	}
	if trelloBoardID == "" {
		trelloBoardID = configData.BoardID
		usageData.BoardID = configData.BoardID
	} else {
		configData.BoardID = trelloBoardID
		usageData.BoardID = trelloBoardID
	}
}
func writeAuthVars(testMode bool) error {
	setAuthVars()
	if testMode {
		return updateFile(testJSONFile)
	}
	return updateFile(jsonFile)
}
func canUpdateTrello() bool {
	return areAPIKeysSet() && isTrelloBoardDataSet()
}
func areAPIKeysSet() bool {
	return (apiKey != "" && apiToken != "") || (configData.Key != "" && configData.Token != "")
}
func isTrelloBoardDataSet() bool {
	if (trelloBoardID != "" && trelloListID != "" && trelloChecklistID != "" && trelloCardID != "") ||
		(configData.CardID != "" && configData.ChecklistID != "" && configData.BoardID != "" && configData.ListID != "") {
		return true
	}
	return false
}
func getSha(repoPath string) (ShaResponse, error) {
	var resp ShaResponse
	getPath := fmt.Sprintf(githubPath, repoPath)
	if verbose {
		log.Debugf(log.Global, "Getting SHA of this path: %v\n", getPath)
	}
	return resp, sendGetReq(getPath, &resp)
}
func checkExistingExchanges(exchName string) bool {
	for x := range usageData.Exchanges {
		if usageData.Exchanges[x].Name == exchName {
			return true
		}
	}
	return false
}