~xenrox/faceit_checker

f2931a76033915b625674d7bdf5d9f4853857d0f — Thorben Günther 8 months ago 4256b50
Forward account list with context between handlers
2 files changed, 47 insertions(+), 66 deletions(-)

M faceit.go
M steam.go
M faceit.go => faceit.go +23 -58
@@ 107,6 107,8 @@ type faceitChecker struct {
	templates   *template.Template
}

type accountsContextKey struct{}

func main() {
	var configPath string
	flag.StringVar(&configPath, "config", "/etc/faceit_checker/config.scfg", "config file path")


@@ 148,7 150,6 @@ func main() {

	r := http.NewServeMux()
	r.HandleFunc("/", fc.faceitHandler)
	r.HandleFunc("/search", fc.requestHandler)
	r.HandleFunc("/api/elo/", fc.getElo)
	fs := http.FileServer(http.FS(css))
	r.Handle("/css/", fs)


@@ 395,10 396,11 @@ func (fc *faceitChecker) faceitHandler(w http.ResponseWriter, r *http.Request) {
	logger.Debug("Received input",
		slog.Any("input", input))
	status := r.FormValue("status")
	var steamAccountList []string
	var steamAccountList []steamAccount

	if status == "status" {
		steamMap, err := parseStatus(input)
		var err error
		steamAccountList, err = fc.parseStatus(input)
		if err != nil {
			logger.Debug("Failed to parse status")
			if err := fc.templates.ExecuteTemplate(w, "error.html", err); err != nil {


@@ 408,17 410,6 @@ func (fc *faceitChecker) faceitHandler(w http.ResponseWriter, r *http.Request) {
			}
			return
		}

		for steamID, nickname := range steamMap {
			id64, err := parseSteamID(steamID)
			if err != nil {
				logger.Error("Failed to parse SteamID",
					slog.String("ID", steamID),
					slog.String("error", err.Error()))
				continue
			}
			steamAccountList = append(steamAccountList, fmt.Sprintf("%s_%s", id64, nickname))
		}
	} else {
		steamLinks := strings.Fields(input)
		for _, steamLink := range steamLinks {


@@ 431,48 422,30 @@ func (fc *faceitChecker) faceitHandler(w http.ResponseWriter, r *http.Request) {
				}
				return
			}
			steamAccountList = append(steamAccountList, fmt.Sprintf("%s_%s", steamProfile.ID64, sanitizeName(steamProfile.Name)))

			steamAccountList = append(steamAccountList, steamAccount{
				id:   steamProfile.ID64,
				name: steamProfile.Name,
			})
		}
	}

	redirect(w, r, strings.Join(steamAccountList, "+"))
	r = r.WithContext(context.WithValue(r.Context(), accountsContextKey{}, steamAccountList))
	fc.requestHandler(w, r)
}

func (fc *faceitChecker) requestHandler(w http.ResponseWriter, r *http.Request) {
	logger := fc.logger.With(slog.String("handler", "/search"))

	if err := r.ParseForm(); err != nil {
		logger.Error("Failed to parse form",
			slog.String("error", err.Error()))
		if err := fc.templates.ExecuteTemplate(w, "error.html", "Internal error with parsing form"); err != nil {
			logger.Error("Failed to execute template",
				slog.String("error", err.Error()))
			http.Error(w, internalError, http.StatusInternalServerError)
		}
		return
	}
	accounts := r.FormValue("accounts")
	if accounts == "" {
		if err := fc.templates.ExecuteTemplate(w, "error.html", "Wrong input"); err != nil {
			logger.Error("Failed to execute template",
				slog.String("error", err.Error()))
			http.Error(w, internalError, http.StatusInternalServerError)
		}
		return
	}

	if strings.Contains(accounts, "error") {
		if err := fc.templates.ExecuteTemplate(w, "error.html", "Internal error"); err != nil {
			logger.Error("Failed to execute template",
				slog.String("error", err.Error()))
			http.Error(w, internalError, http.StatusInternalServerError)
		}
	accountsFromContext := r.Context().Value(accountsContextKey{})
	if accountsFromContext == nil {
		logger.Error("Could not retrieve account list from context")
		http.Error(w, internalError, http.StatusInternalServerError)
		return
	}

	var playerList []*FaceitPlayer
	accountList := strings.Split(accounts, " ")
	accountList := accountsFromContext.([]steamAccount)
	length := len(accountList)
	var playerList []*FaceitPlayer

	for _, account := range accountList {
		select {


@@ 484,25 457,17 @@ func (fc *faceitChecker) requestHandler(w http.ResponseWriter, r *http.Request) 
			player := &FaceitPlayer{}
			playerList = append(playerList, player)

			// parsed[0] is ID64 , parsed[1] is nickname
			parsed := strings.Split(account, "_")
			if len(parsed) != 2 {
				logger.Error("Failed to parse account",
					slog.String("account", account))
				continue
			}

			// Information is only needed if multiple accounts are displayed
			if length > 1 {
				player.SteamLink = "https://steamcommunity.com/profiles/" + parsed[0]
				player.SteamName = parsed[1]
				player.SteamLink = "https://steamcommunity.com/profiles/" + account.id
				player.SteamName = account.name
			}

			playerLogger := logger.With(slog.String("ID", parsed[0]),
				slog.String("name", parsed[1]))
			playerLogger := logger.With(slog.String("ID", account.id),
				slog.String("name", account.name))
			playerLogger.Debug("Checking player")

			data, err := fc.getFaceitPlayer(r.Context(), parsed[0])
			data, err := fc.getFaceitPlayer(r.Context(), account.id)
			if err != nil {
				playerLogger.Error("Failed to get Faceit player",
					slog.String("error", err.Error()))

M steam.go => steam.go +24 -8
@@ 3,6 3,7 @@ package main
import (
	"errors"
	"fmt"
	"log/slog"
	"regexp"
	"strconv"
	"strings"


@@ 10,6 11,11 @@ import (

const baseID64 int64 = 76561197960265728

type steamAccount struct {
	name string
	id   string
}

// https://developer.valvesoftware.com/wiki/SteamID
func parseSteamID(steamID string) (string, error) {
	trimmed := strings.TrimPrefix(steamID, "STEAM_")


@@ 33,7 39,7 @@ func parseSteamID(steamID string) (string, error) {
	return strconv.FormatInt(id64, 10), nil
}

func parseStatus(status string) (map[string]string, error) {
func (fc *faceitChecker) parseStatus(status string) ([]steamAccount, error) {
	lineRegex, err := regexp.Compile(`^#.*"(.*)" (STEAM_[0-9:]*).*$`)
	if err != nil {
		return nil, err


@@ 49,18 55,28 @@ func parseStatus(status string) (map[string]string, error) {
	// Remove first and last line
	playerSlice = playerSlice[1 : len(playerSlice)-1]

	players := make(map[string]string)
	// This list could potentially contain less accounts than the playerSlice.
	// It happens for example for bots, which do not have a valid Steam ID.
	var steamAccountList []steamAccount
	for _, player := range playerSlice {
		match := lineRegex.FindStringSubmatch(player)
		if len(match) != 3 {
			continue
		}
		players[match[2]] = sanitizeName(match[1])
	}

	return players, nil
}
		id, err := parseSteamID(match[2])
		if err != nil {
			fc.logger.Error("Failed to parse SteamID",
				slog.String("ID", match[2]),
				slog.String("error", err.Error()))
			continue
		}

		steamAccountList = append(steamAccountList, steamAccount{
			name: match[1],
			id:   id,
		})
	}

func sanitizeName(name string) string {
	return strings.ReplaceAll(name, " ", "")
	return steamAccountList, nil
}