steamcmd

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 8, 2023 License: MIT Imports: 13 Imported by: 2

README

go-steamcmd

A Go wrapper for the SteamCMD CLI tool. Allows for interaction via SteamCMD's interactive mode as well as command-line arguments.

Requirements

The steamcmd executable must be installed, and placed on your PATH as steamcmd.

Status

At the moment the only commands that are supported are:

  • app_info_print: parses the output data into a map[string]any instance.
  • quit: will wait for the SteamCMD process to terminate.

I only use this module for scraping Steam games, hence the lack of command support for other things. Feel free to make a pull-request with new command implementations!

Documentation

Overview

Package steamcmd contains a wrapper for the Steam CLI client (aka. "steamcmd"). The main type to use here is SteamCMD, which can be instantiated using the New function. SteamCMD can execute the steamcmd commands in interactive and non-interactive modes.

Multiple Command or CommandType can be queued up in a SteamCMD. Commands can be user defined, but it is recommended that you use CommandType instead as they will be loaded from a binding mapping. A Command or a CommandType is executed immediately only if SteamCMD is in interactive mode.

One final thing to note is that you need the "steamcmd" binary installed on your path for the SteamCMD wrapper to work.

Index

Examples

Constants

View Source
const (
	// InteractivePrompt is the prompt that SteamCMD uses in interactive mode.
	InteractivePrompt = "Steam>"
	// ExpectTimeout is the timeout for the Expect calls.
	ExpectTimeout = time.Minute
	// WaitTimeout is the amount of time to wait for the process to shut down.
	WaitTimeout = time.Second * 5
)
View Source
const (
	DayShortMonthYear         = "2 Jan, 2006"
	DayShortMonthYearNoCommas = "2 Jan 2006"
	ShortMonthDayYear         = "Jan 2, 2006"
	DayShortMonthYearDots     = "2. Jan. 2006"
	// MonthDayNdOrdYear and the 3 subsequent SteamDateLayout(s) all parse the same dates with different ordinal chars.
	MonthDayNdOrdYear = "January 2nd, 2006"
	MonthDayRdOrdYear = "January 2rd, 2006"
	MonthDayStOrdYear = "January 2st, 2006"
	MonthDayThOrdYear = "January 2th, 2006"
	ShortMonthYear    = "Jan 2006"
	FullMonthYear     = "January 2006"
	// QuarterYear is actually parsed with the "Q" number as the day, this is converted in SteamDateLayout.Parse to the
	// correct date. The time.Time returned by SteamDateLayout.Parse will be a date to the first day of the quarter.
	QuarterYear = "Q2 2006"
	Year        = "2006"
)

Variables

SteamDateLayouts contains all the SteamDateLayout.

Functions

func ParseSteamDate

func ParseSteamDate(value string) (date time.Time, err error)

ParseSteamDate will parse the given string value to a date by attempting to parse it using each SteamDateLayout in SteamDateLayouts. If the date string cannot be parsed, then the error that is returned will be the merged error constructed from all the errors for each SteamDateLayout.

Example
fmt.Println(ParseSteamDate("8 Oct, 2019"))
fmt.Println(ParseSteamDate("8 Oct 2019"))
fmt.Println(ParseSteamDate("Oct 8, 2019"))
fmt.Println(ParseSteamDate("8. Oct. 2019"))
fmt.Println(ParseSteamDate("July 2nd, 2021"))
fmt.Println(ParseSteamDate("July 1st, 2021"))
fmt.Println(ParseSteamDate("July 3rd, 2021"))
fmt.Println(ParseSteamDate("July 30th, 2021"))
fmt.Println(ParseSteamDate("Sep 2021"))
fmt.Println(ParseSteamDate("Q1 2021"))
fmt.Println(ParseSteamDate("Q2 2021"))
fmt.Println(ParseSteamDate("Q3 2021"))
fmt.Println(ParseSteamDate("Q4 2021"))
fmt.Println(ParseSteamDate("2022"))
fmt.Println(ParseSteamDate("Coming Soon"))
Output:
2019-10-08 00:00:00 +0000 UTC <nil>
2019-10-08 00:00:00 +0000 UTC <nil>
2019-10-08 00:00:00 +0000 UTC <nil>
2019-10-08 00:00:00 +0000 UTC <nil>
2021-07-02 00:00:00 +0000 UTC <nil>
2021-07-01 00:00:00 +0000 UTC <nil>
2021-07-03 00:00:00 +0000 UTC <nil>
2021-07-30 00:00:00 +0000 UTC <nil>
2021-09-01 00:00:00 +0000 UTC <nil>
2021-01-01 00:00:00 +0000 UTC <nil>
2021-04-01 00:00:00 +0000 UTC <nil>
2021-07-01 00:00:00 +0000 UTC <nil>
2021-10-01 00:00:00 +0000 UTC <nil>
2022-01-01 00:00:00 +0000 UTC <nil>
0001-01-01 00:00:00 +0000 UTC could not parse Coming Soon using DayShortMonthYear: parsing time "Coming Soon" as "2 Jan, 2006": cannot parse "Coming Soon" as "2"; could not parse Coming Soon using DayShortMonthYearNoCommas: parsing time "Coming Soon" as "2 Jan 2006": cannot parse "Coming Soon" as "2"; could not parse Coming Soon using ShortMonthDayYear: parsing time "Coming Soon" as "Jan 2, 2006": cannot parse "Coming Soon" as "Jan"; could not parse Coming Soon using DayShortMonthYearDots: parsing time "Coming Soon" as "2. Jan. 2006": cannot parse "Coming Soon" as "2"; could not parse Coming Soon using MonthDayNdOrdYear: parsing time "Coming Soon" as "January 2nd, 2006": cannot parse "Coming Soon" as "January"; could not parse Coming Soon using MonthDayRdOrdYear: parsing time "Coming Soon" as "January 2rd, 2006": cannot parse "Coming Soon" as "January"; could not parse Coming Soon using MonthDayStOrdYear: parsing time "Coming Soon" as "January 2st, 2006": cannot parse "Coming Soon" as "January"; could not parse Coming Soon using MonthDayThOrdYear: parsing time "Coming Soon" as "January 2th, 2006": cannot parse "Coming Soon" as "January"; could not parse Coming Soon using ShortMonthYear: parsing time "Coming Soon" as "Jan 2006": cannot parse "Coming Soon" as "Jan"; could not parse Coming Soon using QuarterYear: parsing time "Coming Soon" as "Q2 2006": cannot parse "Coming Soon" as "Q"; could not parse Coming Soon using Year: parsing time "Coming Soon" as "2006": cannot parse "Coming Soon" as "2006"

Types

type Arg

type Arg struct {
	Name       string
	Type       ArgType
	Required   bool
	Validator  ArgValidator
	Serialiser ArgSerialiser
}

func (*Arg) Serialise

func (a *Arg) Serialise(value any) string

Serialise the given value to a string using the Serialiser for the Arg. If there is no Serialiser for the Arg then the ArgType.DefaultSerialiser will be used instead.

func (*Arg) Validate

func (a *Arg) Validate(value any) bool

Validate the given value against the Type of the Arg and the Validator for the Arg (if there is one).

type ArgSerialiser

type ArgSerialiser func(any) string

type ArgType

type ArgType int

ArgType is the type of an Arg. It represents how an Arg should be serialised and parsed.

const (
	// Number represents values of type: int, int8, int16, int32, int64, float32, float64.
	Number ArgType = iota
	// String represents string values.
	String
)

func ParseArgType

func ParseArgType(s string) (any, ArgType)

ParseArgType first checks if the given string can be parsed to an int, then whether it can be parsed to a float. If it can be parsed to either of these then Number is returned. Otherwise, String is returned. It also returns the value that the arg should have.

func (ArgType) DefaultSerialiser

func (at ArgType) DefaultSerialiser(value any) string

DefaultSerialiser serialises the given value to a string using the default logic for the ArgType.

func (ArgType) DefaultValidator

func (at ArgType) DefaultValidator(value any) bool

DefaultValidator checks if the given value fits the ArgType.

func (ArgType) String

func (at ArgType) String() string

String returns the string representation of the ArgType.

type ArgValidator

type ArgValidator func(any) bool

type Command

type Command struct {
	Type      CommandType
	Parser    CommandOutputParser
	Validator CommandOutputValidator
	Args      []*Arg
}

Command represents a command that can be executed in SteamCMD. User defined Command are possible, but users should stick to executing Commands via their CommandType instead.

func (*Command) Parse

func (c *Command) Parse(out []byte) (any, error)

Parse the Command's output using their Parser, if it is not nil. Otherwise, the output will just be converted to a string and returned.

func (*Command) Serialise

func (c *Command) Serialise(args ...any) string

Serialise will return the string that will be used to execute this Command via the steamcmd binary.

func (*Command) ValidateArgs

func (c *Command) ValidateArgs(args ...any) bool

ValidateArgs will validate the given args against the Arg.Validator for each Arg in Args. If the number of args given exceeds the number of Arg in Args, then this will count as invalid. If a required Arg is not provided, this will also count as invalid.

func (*Command) ValidateOutput

func (c *Command) ValidateOutput(tryNo int, out []byte) bool

ValidateOutput of the Command by using the Validator of the Command. It also must be given the current try for the Command. When SteamCMD is in interactive mode we might keep executing a Command until we can validate its output.

If the Command.Validator is nil, then we will return tryNo > 0. This is useful for the Quit command that should be executed at least once but has no output to validate.

type CommandOutputParser

type CommandOutputParser func(output []byte) (any, error)

CommandOutputParser parses the output of a Command to a more usable format. Usually, JSON (map[string]any).

type CommandOutputValidator

type CommandOutputValidator func(tryNo int, output []byte) bool

CommandOutputValidator validates whether a Command has completed successfully by validating the output of the Command as well as which try the command is currently on.

type CommandType

type CommandType int

CommandType represents a (sub)command that can be executed by SteamCMD.

const (
	// AppInfoPrint calls the "app_info_print" command. It takes a sole Number as an Arg.
	AppInfoPrint CommandType = iota
	// Quit calls the "quit" command. It takes no arguments.
	Quit
)

func CommandTypeFromString

func CommandTypeFromString(s string) (CommandType, error)

CommandTypeFromString looks up the given string as a CommandType.

func (CommandType) String

func (ct CommandType) String() string

String returns the SteamCMD representation of the CommandType that will be used to call the command in the steamcmd binary.

type CommandWithArgs

type CommandWithArgs struct {
	Command *Command
	Args    []any
}

CommandWithArgs simply serves as a wrapper for the arguments that are passed to SteamCMD.Flow.

func NewCommandWithArgs

func NewCommandWithArgs(commandType CommandType, args ...any) *CommandWithArgs

NewCommandWithArgs creates a new CommandWithArgs using the given CommandType and args. This is so you can just use the output of this function directly in the input to SteamCMD.Flow.

type SteamCMD

type SteamCMD struct {

	// ParsedOutputs is the list of parsed outputs from Command.Parse from each queued/executed Command. This means that
	// the output of the third command will lie at index 2.
	ParsedOutputs []any
	// contains filtered or unexported fields
}

SteamCMD is a wrapper for the Steam CLI client (steamcmd). It can run a sequence of Command in both interactive and non-interactive modes.

func New

func New(interactive bool) *SteamCMD

New creates a new SteamCMD. You can specify whether to run Command in interactive mode or not.

func NewDebug

func NewDebug(interactive bool, stdout, stderr io.Writer) *SteamCMD

func (*SteamCMD) AddCommand

func (sc *SteamCMD) AddCommand(command *Command, args ...any) (err error)

AddCommand will add the given Command to the serialised command string. The Command will not be executed unless SteamCMD is running in interactive mode.

func (*SteamCMD) AddCommandType

func (sc *SteamCMD) AddCommandType(commandType CommandType, args ...any) (err error)

AddCommandType will look up the given CommandType in the default command lookup, then add that command using AddCommand.

func (*SteamCMD) Close

func (sc *SteamCMD) Close() (err error)

Close will stop the SteamCMD process, if it is in interactive mode. Otherwise, the command will be executed all at once.

func (*SteamCMD) Flow

func (sc *SteamCMD) Flow(commandWithArgs ...*CommandWithArgs) (err error)

Flow will start the SteamCMD by running SteamCMD.Start, queue up a flow of CommandWithArgs one at a time, then finally call Close on the SteamCMD.

Example
var err error
cmd := New(true)

if err = cmd.Flow(
	NewCommandWithArgs(AppInfoPrint, 477160),
	NewCommandWithArgs(Quit),
); err != nil {
	fmt.Printf("Could not execute flow: %s\n", err.Error())
}
fmt.Println(cmd.ParsedOutputs[0].(map[string]any)["common"].(map[string]any)["name"])
Output:
Human: Fall Flat

func (*SteamCMD) Start

func (sc *SteamCMD) Start() (err error)

Start will start the SteamCMD process, if it is in interactive mode. Otherwise, nothing will happen.

type SteamDateLayout

type SteamDateLayout string

SteamDateLayout represents a format that a release date (or other date) can be in.

func (SteamDateLayout) Parse

func (sdf SteamDateLayout) Parse(value string) (date time.Time, err error)

Parse will attempt to parse the given date string value as a time.Time using the layout described by the SteamDateLayout.

For some SteamDateLayout, there is extra manipulation that takes place after the date string value has been successfully parsed. This is evident in the QuarterYear SteamDateLayout, where the day of the parsed time.Time is converted to the quarter number by setting the month and day to the correct values for that quarter.

func (SteamDateLayout) String

func (sdf SteamDateLayout) String() string

String returns the name of the SteamDateLayout.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL