posh-Brawl.psm1
Function Get-BrawlerIDIndexList { <# .Synopsis Gets a Brawler ID Index list. .DESCRIPTION Gets a list of brawler IDs. This is used for autocompletion and is not a public function. .EXAMPLE Get-BrawlerIDIndexList #> [CmdletBinding()] Param ( ) Process { $Path = "$Script:moduleBase\assets\BrawlerIndex.csv" $BrawlerIndex = Import-Csv -Path $Path $BrawlerIndex.id } } Function Get-BrawlerIndexList { <# .Synopsis Gets a Brawler list. .DESCRIPTION Gets a list of brawler names. This is used for autocompletion and is not a public function. .EXAMPLE Get-BrawlerIndexList #> [CmdletBinding()] Param ( ) Process { $BrawlerIndex = Import-Csv -Path "$Script:moduleBase\bin\BrawlerIndex.csv" $BrawlerIndex.name | Sort-Object } } Function Invoke-BrawlRequest { <# .SYNOPSIS Private function that is invoked when a command is ran .DESCRIPTION This essentially acts as a wrapper for an API call to the Brawl Stars API. It utilizes Invoke-Restmethod under the hood. This is a private function so it will not be available upon import. .EXAMPLE Invoke-BrawlRequest -uri $uri .PARAMETER Uri URI of the resource/endpoint for Brawl Stars API. .NOTES https://developer.brawlstars.com/#/documentation #> [CmdletBinding()] Param ( [Parameter(Mandatory, ValueFromPipeline)] [Uri]$Uri ) Begin { $ErrorActionPreference = "Stop" } Process { Write-Verbose -Message "Invoke-BrawlRequest: URI set to $URI" $Response = Invoke-RestMethod -Method Get -Uri $Uri -Headers $Script:headers -ContentType "application/json" -SkipHttpErrorCheck -StatusCodeVariable StatusCode if ($Response.Reason) { Write-Error -Message "$($Response.Reason),$($Response.Message),StatusCode: $StatusCode." } switch -wildcard ($URI) { "$Script:PlayersEndPoint/%23$PlayerTag/battlelog" { $Response.items } "$script:ClubsEndpoint/%23$ClubTag/members" { $Response.items } "$script:BrawlersEndpoint" { $Response.items } "$script:RankingsEndpoint*" {$Response.Items} Default { $Response } } } } Function Connect-BrawlStars { <# .SYNOPSIS Establishes Connection to Brawl Stars API. .DESCRIPTION Establishes Connection to Brawl Stars API. .PARAMETER KeyFile Specifies the key file which contains the token needed for authentication against the endpoints. -Default KeyFile is set $Script:DefaultKeyFile, found in $Script:KeysDirectory -Default originally set in PSM1 File. if specified, this function overrides it -If you want to use a different token, specify entire path E.G.: C:\Users\username\Documents\MyLittleSecret.Secret .EXAMPLE Connect-BrawlStars Connection Successful. .NOTES https://developer.brawlstars.com/#/getting-started #> [CmdletBinding()] Param ( [String]$KeyFile = "$Script:DefaultKeyFile" ) Process { If (Test-Path -Path $KeyFile) { Write-Verbose -Message "$Keyfile found..." Try { $Creds = Import-Clixml -Path $KeyFile $Token = $creds.Password | ConvertFrom-SecureString -AsPlainText -ErrorAction Stop } Catch [System.Security.Cryptography.CryptographicException] { Write-Error -Exception (System.Security.Cryptography.CryptographicException]::new("Unable to decrypt Credentials. Please generate new credentials file or specify a new KeyFile.")) -ErrorAction Stop } } Else { Write-Verbose -Message "`$KeyFile not specified. Trying to find another Key to use..." $Keys = Get-ChildItem -Path "$Script:KeysDirectory\*" -Include *.Secret If ($Keys) { Write-Verbose -Message "Found files, selecting most recently modified..." $KeyFile = $Keys | Sort-Object -Descending LastWriteTime | Select-Object -First 1 Try { $Creds = Import-Clixml -Path $KeyFile -ErrorAction Stop $Token = $creds.Password | ConvertFrom-SecureString -AsPlainText } Catch [System.Security.Cryptography.CryptographicException] { Write-Error -Exception ([System.Security.Cryptography.CryptographicException]::new("Unable to decrypt Credentials. Please generate new credentials file or specify a new KeyFile.")) -ErrorAction Stop } } Else { throw "No valid key files found, please create one manually or generate one with New-BrawlKeyFile" } } $Script:headers = @{ authorization = "Bearer $token" } $Response = Invoke-BrawlRequest -URI $script:BaseURI Write-Verbose -Message "$Reponse" If (-not ($Response.Reason)) { Write-Output "Connection Successful." } } } Function Get-BattleData { <# .Synopsis Get Battle Summary Data of last 25 games of player .DESCRIPTION Get Battle Summary Data of last 25 games of player .PARAMETER PlayerTag PlayerTag of a user/player .PARAMETER IgnoreDraws Ignore games that ended in a draw. This may mean the total count is less than 25. .EXAMPLE Get-BattleData -PlayerTag 'YGU20CRG' Player : VitalShark PlayerTag : YGU20CRG Wins : 24 RoyaleWins : 0 StarPlayerTotal : 12 StarPlayerPercentage : 50 Loses : 1 Draws : 0 WinPercent : 96 TotalRoyaleGames : TotalGames : 25 Modes : {@{GamesPlayed=3; Name=bounty}, @{GamesPlayed=22; Name=brawlBall}} .EXAMPLE Get-BattleData -PlayerTag '#YGU20CRG' -IgnoreDraws .NOTES https://developer.brawlstars.com/#/documentation #> [CmdletBinding()] Param ( [Parameter(ValueFromPipeline)] [String]$PlayerTag, [Switch]$IgnoreDraws ) Begin { #Need to be build a complete dataset for calculations $PlayerName = (Get-Player -PlayerTag $PlayerTag).name $response = Get-BattleLog -PlayerTag $PlayerTag [PSCustomObject]$ModesPlayed = $response.battle | Group-Object Mode | Select-Object @{ Name = 'GamesPlayed'; Expression = { $_.Count } }, Name $RoyaleGames = $Response.Battle | Where-Object { ($_.mode -like "*Showdown*") -or ($_.mode -like "*Lonestar*") -or ($_.mode -like "*Takedown*") } If ($RoyaleGames) { #Games where there can be more than 1 entity that wins. In this case, we calculate a win if there's a postive change in trophies $RoyaleCount = $RoyaleGames.Count $RoyaleWins = $Royalegames | Where-Object -Property trophychange -GT 0 $RoyaleDraws = $Royalegames | Where-Object -Property trophychange -EQ 0 $RoyaleLosses = $Royalegames | Where-Object -Property trophychange -LT 0 } $TotalGames = $response.count $Results = $response.battle.result $NonRoyaleWinCount = ($Results | Where-Object { $_ -eq "victory" }).count $WinCount = $NonRoyaleWinCount + $RoyaleWins.count $LoseCount = ($Results | Where-Object { $_ -eq "Defeat" }).count + $RoyaleLosses.count $DrawCount = ($Results | Where-Object { $_ -eq "draw" }).count + $RoyaleDraws.count $StarPlayerCount = ($response.battle.starplayer.tag | Where-Object { $_ -match "$PlayerTag" }).count } Process { switch ($IgnoreDraws) { { $IgnoreDraws } { Write-Verbose -Message "Draws will be thrown out" If ($DrawCount) { $CalculatedGames = $TotalGames - $DrawCount } $Percentage = ($WinCount / $CalculatedGames) * 100 # It's impossible to get Star Player when you lose, or if you are playing in a Royale so we focus on non royale wins $sTarPlayerPercentage = ($StarPlayerCount / $NonRoyaleWinCount) * 100 $Final = [math]::Round($Percentage, 2) $StarPlayerFinal = [math]::Round($StarPlayerPercentage, 2) $Properties = [ordered]@{ "Player" = $PlayerName "PlayerTag" = $PlayerTag "Wins" = $WinCount "RoyaleWins" = $RoyaleWins.count "StarPlayerTotal" = $StarPlayerCount "StarPlayerPercentage" = $StarPlayerFinal "Loses" = $LoseCount "Draws" = "Ignored" "WinPercent" = $Final "TotalRoyaleGames" = $RoyaleCount "TotalGames" = $TotalGames "TotalGames(No Draws)" = $CalculatedGames "Modes" = $ModesPlayed } } { (-not($IgnoreDraws)) } { If ($DrawCount) { Write-Verbose "Draws detected.." $Percentage = (($WinCount + (.5 * $DrawCount)) / $TotalGames) * 100 $Final = [math]::Round($Percentage, 2) } Else { $Percentage = ($WinCount / $TotalGames) * 100 $Final = [math]::Round($Percentage, 2) } $sTarPlayerPercentage = ($StarPlayerCount / ($NonRoyaleWinCount + $DrawCount)) * 100 $StarPlayerFinal = [math]::Round($StarPlayerPercentage, 2) $Properties = [ordered]@{ "Player" = $PlayerName "PlayerTag" = $PlayerTag "Wins" = $WinCount "RoyaleWins" = $RoyaleWins.count "StarPlayerTotal" = $StarPlayerCount "StarPlayerPercentage" = $StarPlayerFinal "Loses" = $LoseCount "Draws" = $DrawCount "WinPercent" = $Final "TotalRoyaleGames" = $RoyaleCount "TotalGames" = $TotalGames "Modes" = $ModesPlayed } } } New-Object -TypeName PSCustomObject -Property $Properties } } Function Get-BattleLog { <# .Synopsis Get list of recent battle results for a player .DESCRIPTION Get list of recent battle results for a player. If no recent matches have been played, may return a status 404 NOTE: It may take up to 30 minutes for a new battle to appear in the battlelog .PARAMETER PlayerTag Playertag .PARAMETER URI uri of endpoint.. .EXAMPLE Get-BattleLog -PlayerTag 'YGU20CRG' battleTime event battle ---------- ----- ------ 20220602T062543.000Z @{id=0; map=} @{mode=bounty; type=friendly; result=victory; duration=120; starPlayer=; teams=System.Object[]} 20220602T062245.000Z @{id=0; map=} @{mode=bounty; type=friendly; result=victory; duration=120; starPlayer=; teams=System.Object[]} 20220602T061942.000Z @{id=0; map=} @{mode=bounty; type=friendly; result=defeat; duration=120; starPlayer=; teams=System.Object[]} 20220602T061704.000Z @{id=15000531; mode=brawlBall; map=Extra Bouncy} @{mode=brawlBall; type=friendly; result=victory; duration=32; starPlayer=; teams=System.Object[]} 20220530T052241.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=118; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T051448.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=28; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T050909.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=65; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T050218.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=36; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T045627.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=90; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T044741.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=67; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T044120.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=45; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T043503.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=38; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T042350.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=120; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T041903.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=78; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T041218.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=67; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T040459.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=32; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T035916.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=150; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T034611.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=75; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T034033.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=106; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T033405.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=37; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T032729.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=88; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T032226.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=60; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T031550.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=63; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T030021.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=134; trophyChange=3; starPlayer=; teams=System.Object[]} 20220530T025445.000Z @{id=15000132; mode=brawlBall; map=Center Stage} @{mode=brawlBall; type=ranked; result=victory; duration=85; trophyChange=3; starPlayer=; teams=System.Object[]} .NOTES https://developer.brawlstars.com/#/documentation #> [CmdletBinding()] Param ( [Parameter(ValueFromPipeline)] [String]$PlayerTag, [uri]$Uri = "$Script:PlayersEndPoint/%23$PlayerTag/battlelog" ) Process { #Tags are all upper case $PlayerTag = $PlayerTag.ToUpper() If ($PlayerTag -match "^#") { $PlayerTag = $PlayerTag -replace "^#", "" $Uri = "$Script:PlayersEndPoint/%23$PlayerTag/battlelog" } Write-Verbose "Player Tag is set to $PlayerTag" Invoke-BrawlRequest -uri $Uri } } Function Get-Brawler { <# .Synopsis Get Brawler information .DESCRIPTION Get-Brawler, simply put, returns brawler information. .PARAMETER BrawlerID Part of the ParameterSet 'BrawlerID'. .PARAMETER Name The Name of the Brawler. Part of the ParameterSet 'Name'. This will use a local index to determine the ID to pass to the endpoint. .PARAMETER All Part of the default ParameterSet 'All'. If no parameters are passed and no pipeline data is pass, the all parameterset is used. This will return all brawlers from the /brawlers endpoint. .EXAMPLE Get-brawler id name starPowers gadgets -- ---- ---------- ------- 16000000 SHELLY {@{id=23000076; name=SHELL SHOCK}, @{id=23000135; name=BAND-AID}} {@{id=23000255; name=FAST FORWARD}, @{id=23000288; name=CLAY PIGEONS}} 16000001 COLT {@{id=23000077; name=SLICK BOOTS}, @{id=23000138; name=MAGNUM SPECIAL}} {@{id=23000273; name=SPEEDLOADER}, @{id=23000319; name=SILVER BULLET}} 16000002 BULL {@{id=23000078; name=BERSERKER}, @{id=23000137; name=TOUGH GUY}} {@{id=23000272; name=T-BONE INJECTOR}, @{id=23000310; name=STOMPER}} 16000003 BROCK {@{id=23000079; name=INCENDIARY}, @{id=23000150; name=ROCKET NO. 4}} {@{id=23000245; name=ROCKET LACES}, @{id=23000316; name=ROCKET FUEL}} 16000004 RICO {@{id=23000080; name=SUPER BOUNCY}, @{id=23000156; name=ROBO RETREAT}} {@{id=23000246; name=MULTIBALL LAUNCHER}} 16000005 SPIKE {@{id=23000081; name=FERTILIZE}, @{id=23000151; name=CURVEBALL}} {@{id=23000247; name=POPPING PINCUSHION}} 16000006 BARLEY {@{id=23000082; name=MEDICAL USE}, @{id=23000158; name=EXTRA NOXIOUS}} {@{id=23000250; name=STICKY SYRUP MIXER}, @{id=23000293; name=HERBAL TONIC}} 16000007 JESSIE {@{id=23000083; name=ENERGIZE}, @{id=23000149; name=SHOCKY}} {@{id=23000251; name=SPARK PLUG}, @{id=23000295; name=RECOIL SPRING}} 16000008 NITA {@{id=23000084; name=BEAR WITH ME}, @{id=23000136; name=HYPER BEAR}} {@{id=23000249; name=BEAR PAWS}, @{id=23000314; name=FAUX FUR}} 16000009 DYNAMIKE {@{id=23000085; name=DYNA-JUMP}, @{id=23000155; name=DEMOLITION}} {@{id=23000258; name=FIDGET SPINNER}, @{id=23000294; name=SATCHEL CHARGE}} 16000010 EL PRIMO {@{id=23000086; name=EL FUEGO}, @{id=23000140; name=METEOR RUSH}} {@{id=23000264; name=SUPLEX SUPPLEMENT}, @{id=23000292; name=ASTEROID BELT}} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Trimmed Response for Comment-based help~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .EXAMPLE Get-Brawler -BrawlerID "16000011" id name starPowers gadgets -- ---- ---------- ------- 16000011 MORTIS {@{id=23000087; name=CREEPY HARVEST}, @{id=23000154; name=COILED SNAKE}} {@{id=23000265; name=COMBO SPINNER}, @{id=23000290; name=SURVIVAL SHOVEL}} .EXAMPLE Get-Brawler -Name Brock id name starPowers gadgets -- ---- ---------- ------- 16000003 BROCK {@{id=23000079; name=INCENDIARY}, @{id=23000150; name=ROCKET NO. 4}} {@{id=23000245; name=ROCKET LACES}, @{id=23000316; name=ROCKET FUEL}} .EXAMPLE "El Primo" | Get-Brawler id name starPowers gadgets -- ---- ---------- ------- 16000010 EL PRIMO {@{id=23000086; name=EL FUEGO}, @{id=23000140; name=METEOR RUSH}} {@{id=23000264; name=SUPLEX SUPPLEMENT}, @{id=23000292; name=ASTEROID BELT}} .NOTES https://developer.brawlstars.com/#/documentation GET /brawlers/{brawlerId} GET /brawlers #> [CmdletBinding(DefaultParameterSetName = 'All')] Param ( [Alias("ID", "Identifier")] [Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'BrawlerID')] [String]$BrawlerID, [Alias("Brawler", "Hero")] [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = 'Name', Position = 0)] [String]$Name, [Parameter(ParameterSetName = 'All')] [Switch]$All ) Process { Write-Verbose -Message "ParameterSetName : $($PSCmdlet.ParameterSetName)" switch ($PSCmdlet.ParameterSetName) { BrawlerID { [Uri]$Uri = "$script:BrawlersEndpoint/$BrawlerID" Write-Verbose "Brawler ID is set to $BrawlerID" Invoke-BrawlRequest -URI $URI } Name { $Path = "$Script:moduleBase\bin\BrawlerIndex.csv" $BrawlerIndex = Import-Csv -Path $Path $BrawlerID = ($brawlerindex | Where-Object -Property Name -EQ $Name).id if ($BrawlerID) { [Uri]$Uri = "$script:BrawlersEndpoint/$BrawlerID" Invoke-BrawlRequest -URI $URI } } All { [Uri]$Uri = "$script:BrawlersEndpoint" Invoke-BrawlRequest -Uri $Uri } } } } Function Get-BrawlerRanking { <# .Synopsis Get brawler rankings for a country or global ranking. .DESCRIPTION Get brawler rankings for a country or global rankings. Brawler identifiers can be found by using the /v1/brawlers API endpoint. .PARAMETER Limit Type: INT Default Value: 200 Limit the number of items returned in the response. Valid value is between 1 and 200 .PARAMETER CountryCode Type: String Two letter country code .PARAMETER Global Type: Switch This parameter forces checking the Global endpoint .PARAMETER BrawlerID Type: INT Alias: ID Identifier of the brawler. Can be queried using Get-Brawler .EXAMPLE Get-BrawlerRanking -BrawlerID 16000011 -Limit 1 tag : #20288898G name : ☔︎LT|Rayy-Nex☔︎ nameColor : 0xffffffff icon : @{id=28000014} trophies : 1270 rank : 1 club : @{name=ReVant} .EXAMPLE Get-Brawler -Name Shelly | Get-BrawlerRanking .EXAMPLE 16000012 | Get-BrawlerRanking .EXAMPLE 16000013 | Get-BrawlerRanking -Limit 1 .NOTES https://developer.brawlstars.com/#/documentation To do: This endpoint supports before and after query strings, need to add logic and parameter sets to support this scenario. #> [CmdletBinding(DefaultParameterSetName = 'Global')] param ( [Parameter(ParameterSetName = 'CountryCode')] [AllowNull()] [ValidatePattern('^[A-Za-z]{2}$')] [String]$CountryCode, [Parameter(ParameterSetName = 'Global')] [Parameter(ParameterSetName = 'CountryCode')] [ValidateRange(1, 200)] [int]$Limit = 200, [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = 'Global')] [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = 'CountryCode')] [Alias('ID')] [int]$BrawlerID, [Parameter(ParameterSetName = 'Global')] [Switch]$Global ) process { if ($Global -or (-not ($CountryCode))) { Write-Verbose -Message "Running in global mode..." [Uri]$Uri = "$script:RankingsEndpoint/Global/brawlers/${brawlerid}?limit=$Limit" } else { Write-Verbose -Message "Running in country mode..." [Uri]$Uri = "$script:RankingsEndpoint/$CountryCode/${brawlerid}?limit=$limit" } Invoke-BrawlRequest -Uri $URI } } Function Get-Club { <# .Synopsis Get Infomration about a single club .DESCRIPTION Get information about a single club by tag. Club tags can be found in game. .PARAMETER ClubTag Club tag .EXAMPLE Get-Club -ClubTag "#2089L0PG2" tag : #2089L0PG2 name : CODEMAGIC description : Clan OFFICIEL de CODEMAGIC.web : codemagic.fr 🧙♂️ twitter : @_CODEMAGIC_ 🧙♂️ discord.gg/codemagic 🧙♂️youtube.com/codemagic type : closed badgeId : 8000025 requiredTrophies : 25000 trophies : 0 members : {} .NOTES GET /clubs/{clubTag} #> [CmdletBinding()] Param ( [Parameter(Mandatory)][ValidatePattern('[#0289PYLQGRJCUV]')] [String]$ClubTag ) Begin { [Uri]$Uri = "$script:ClubsEndpoint/%23$ClubTag" } Process { #Club tags start with hash character '#' and that needs to be URL-encoded properly to work in URL, so for example clan tag '#ABC' would become '%232ABC' in the URL. If ($ClubTag -match "^#") { $ClubTag = $ClubTag -replace "^#", "" $Uri = "$script:ClubsEndpoint/%23$ClubTag" } Write-Verbose "Player Tag is set to $ClubTag" Invoke-BrawlRequest -Uri $URI } } Function Get-ClubMember { <# .Synopsis List Club Members .DESCRIPTION This function gets a list of club members. .EXAMPLE Get-ClubMember -ClubTag "208UU822P" | Select-Object -First 2 tag : #90QUR2QY name : TQ | RaaFa nameColor : 0xfff9c908 role : member trophies : 54485 icon : @{id=28000038} tag : #VGQ0P2VU name : Uncle Carry nameColor : 0xff1ba5f5 role : president trophies : 51279 icon : @{id=28000011} .PARAMETER ClubTag tag of club .NOTES https://developer.brawlstars.com/#/documentation #> [CmdletBinding()] Param ( [Parameter(ValueFromPipeline, Mandatory)] [String]$ClubTag ) Begin { [Uri]$Uri = "$script:ClubsEndpoint/%23$ClubTag/members" } Process { If ($ClubTag -match "^#") { $ClubTag = $ClubTag -replace "^#", "" $Uri = "$script:ClubsEndpoint/%23$ClubTag/members" } Write-Verbose "Player Tag is set to $ClubTag" Invoke-BrawlRequest -uri $Uri } } Function Get-ClubRanking { <# .Synopsis Get information about a single player by player tag .DESCRIPTION Get information about a single player by player tag .PARAMETER CountryCode Type: String Two letter country code .PARAMETER limit Type: INT Default Value: 200 Limit the number of items returned in the response. Valid value is between 1 and 200 .PARAMETER global Global endpoint .EXAMPLE Get-ClubRanking tag : #2GUU9908V name : BC*|Family* badgeId : 8000006 trophies : 1504063 rank : 1 memberCount : 30 tag : #P8PV2YU9 name : Game.Tv ITA badgeId : 8000055 trophies : 1474250 rank : 2 memberCount : 30 .NOTES https://developer.brawlstars.com/#/documentation #> [CmdletBinding()] Param ( [Parameter(ValueFromPipeline)][AllowNull()][ValidatePattern('[A-Za-z]')] [String]$CountryCode, [ValidateRange(1, 200)] [int]$Limit = 200, [Switch]$Global ) Begin { [Uri]$Uri = "$script:RankingsEndpoint/Global/clubs?limit=$Limit" } Process { if ($Global -or (-not ($CountryCode))) { Write-Verbose -Message "Global Switch detected or country code is null, setting search to Global..." Invoke-BrawlRequest -Uri $URI } else { [Uri]$Uri = "$script:RankingsEndpoint/$CountryCode/clubs?limit=$limit" Invoke-BrawlRequest -Uri $URI } } } Function Get-Player { <# .Synopsis Get information about a single player by player tag .DESCRIPTION Get information about a single player by player tag .PARAMETER PlayerTag Player tag .Parameter BestBrawler Type: Switch outputs the brawler with the highest trophy this player has. .EXAMPLE Get-Player -PlayerTag '#C08UC2C' tag : #C08UC2C name : Imagine nameColor : 0xffffce89 icon : @{id=28000000} trophies : 27802 highestTrophies : 38103 highestPowerPlayPoints : 1123 expLevel : 264 expPoints : 357018 isQualifiedFromChampionshipChallenge : False 3vs3Victories : 20896 soloVictories : 569 duoVictories : 2744 bestRoboRumbleTime : 5 bestTimeAsBigBrawler : 0 club : brawlers : {@{id=16000000; name=SHELLY; power=9; rank=26; trophies=574; highestTrophies=807; gears=System.Object[]; starPowers=System.Object[]; gadgets=System.Object[]}, @{id=16000001; name=COLT; power=9; rank=27; trophies=524; highestTrophies=874; gears=System.Object[]; starPowers=System.Object[]; gadgets=System.Object[]}, @{id=16000002; name=BULL; power=9; rank=27; trophies=549; highestTrophies=858; gears=System.Object[]; starPowers=System.Object[]; gadgets=System.Object[]}, @{id=16000003; name=BROCK; power=9; rank=30; trophies=574; highestTrophies=1039; gears=System.Object[]; starPowers=System.Object[]; gadgets=System.Object[]}…} .EXAMPLE Get-Player -PlayerTag C08UC2C -BestBrawler tag : #C08UC2C name : Imagine nameColor : 0xffffce89 icon : @{id=28000000} trophies : 27802 highestTrophies : 38103 highestPowerPlayPoints : 1123 expLevel : 264 expPoints : 357018 isQualifiedFromChampionshipChallenge : False 3vs3Victories : 20896 soloVictories : 569 duoVictories : 2744 bestRoboRumbleTime : 5 bestTimeAsBigBrawler : 0 club : brawlers : {@{id=16000000; name=SHELLY; power=9; rank=26; trophies=574; highestTrophies=807; gears=System.Object[]; starPowers=System.Object[]; gadgets=System.Object[]}, @{id=16000001; name=COLT; power=9; rank=27; trophies=524; highestTrophies=874; gears=System.Object[]; starPowers=System.Object[]; gadgets=System.Object[]}, @{id=16000002; name=BULL; power=9; rank=27; trophies=549; highestTrophies=858; gears=System.Object[]; starPowers=System.Object[]; gadgets=System.Object[]}, @{id=16000003; name=BROCK; power=9; rank=30; trophies=574; highestTrophies=1039; gears=System.Object[]; starPowers=System.Object[]; gadgets=System.Object[]}…} bestbrawler : @{id=16000003; name=BROCK; power=9; rank=30; trophies=574; highestTrophies=1039; gears=System.Object[]; starPowers=System.Object[]; gadgets=System.Object[]} .NOTES https://developer.brawlstars.com/#/documentation #> [CmdletBinding(DefaultParameterSetName = 'PlayerTag')] param ( [Parameter(ValueFromPipeline, ParameterSetName = 'PlayerTag')][ValidatePattern('[#0289PYLQGRJCUV]')] [String]$PlayerTag, [Switch]$BestBrawler ) begin { $URI = "$Script:PlayersEndPoint/%23$PlayerTag" } process { Write-Verbose -Message "Get-Player : ParameterSet is set to $($PSCmdlet.ParameterSetName)" switch ($PSCmdlet.ParameterSetName) { PlayerTag { #Tags are all upper case $PlayerTag = $PlayerTag.ToUpper() If ($PlayerTag -match "^#") { $PlayerTag = $PlayerTag -replace "^#", "" $URI = "$Script:PlayersEndPoint/%23$PlayerTag" } Write-Verbose -Message "Player Tag is set to $PlayerTag" $Response = Invoke-BrawlRequest -URI $URI If ($BestBrawler) { $Maximum = ($Response.brawlers.highesttrophies | Measure-Object -Maximum).Maximum $HighestBrawler = $Response.Brawlers | Where-Object { $_.HighestTrophies -eq $Maximum } $Response | Add-Member -NotePropertyName bestbrawler -NotePropertyValue $HighestBrawler } $Response } } } } Function Get-PlayerRanking { <# .Synopsis Get player rankings for a country or global rankings. .DESCRIPTION Get player rankings for a country or global rankings. .PARAMETER CountryCode Type: String Two letter country code .PARAMETER limit Type: INT Default Value: 200 Limit the number of items returned in the response. Valid value is between 1 and 200 .PARAMETER Global Switches context to global endpoint. .EXAMPLE Get-PlayerRanking -Limit 1 tag : #YGU20CRG name : VitalShark nameColor : 0xffcb5aff icon : @{id=28000029} trophies : 64534 rank : 1 club : @{name=<c1>MERCY</c>} .NOTES https://developer.brawlstars.com/#/documentation #> [CmdletBinding()] Param ( [Parameter()] [AllowNull()] [ValidatePattern('^[A-Za-z]{2}$')] [String]$CountryCode, [ValidateRange(1, 200)] [int]$Limit = 200, [Switch]$Global ) Begin { [Uri]$Uri = "$script:RankingsEndpoint/Global/players?limit=$Limit" } Process { if ($Global -or (-not ($CountryCode))) { Write-Verbose -Message "Global Switch detected or country code is null, setting search to Global..." Invoke-BrawlRequest -Uri $URI } else { [Uri]$Uri = "$script:BaseUri/$script:RankingsEndpoint/$CountryCode/players?limit=$limit" Invoke-BrawlRequest -Uri $URI } } } Function Get-PowerPlayRanking { <# .Synopsis Coming Soon .DESCRIPTION Coming Soon .PARAMETER CountryCode Type: String Two letter country code .PARAMETER limit Type: INT Default Value: 200 Limit the number of items returned in the response. Valid value is between 1 and 200 .PARAMETER SeasonID ID of Season, found by running Get-PowerPlaySeasonID .PARAMETER URI Probably not needed but URI of endpoint .EXAMPLE Get-PowerPlayRanking Coming Soon .NOTES https://developer.brawlstars.com/#/documentation GET /rankings/{countryCode}/powerplay/seasons/{seasonId} #> [CmdletBinding()] Param ( [Parameter(ValueFromPipeline)][AllowNull()][ValidatePattern('^[A-Za-z]{2}$|^Global$')] [String]$CountryCode, [ValidateRange(1, 200)] [int]$Limit = 200, [Uri]$Uri = "$script:BaseUri/$script:RankingsEndpoint/Global/powerplay/seasons?limit=$Limit", [String]$SeasonID = "latest" ) Process { Write-Host "Coming Soon, this function isn't implemented yet!" } } Function Get-PowerPlaySeasonID { <# .Synopsis Get information about a single player by player tag .DESCRIPTION Get information about a single player by player tag .PARAMETER CountryCode Type: String Two letter country code or 'GLOBAL' to query global endpoint .PARAMETER LIMIT Type: INT Default Value: 200 Limit the number of items returned in the response. Valid value is between 1 and 200 .PARAMETER Date Date to query in MM-dd-yyyy OR M-d-yyyy format. .EXAMPLE Get-PowerPlaySeasonID -Limit 5 id startDate endDate -- --------- ------- 56 10-28-2019 11-11-2019 57 11-11-2019 11-25-2019 58 11-25-2019 12-09-2019 59 12-09-2019 12-23-2019 60 12-23-2019 01-06-2020 .EXAMPLE Get-PowerPlaySeasonID -CountryCode US -Date 6-2-2022 id startDate endDate -- --------- ------- 123 05-23-2022 06-06-2022 .NOTES https://developer.brawlstars.com/#/documentation #> [CmdletBinding()] Param ( [Parameter(ValueFromPipeline)][AllowNull()][ValidatePattern('^[A-Za-z]{2}$|^Global$')] [String]$CountryCode, [ValidateRange(1, 200)] [int]$Limit = 200, [String]$Date ) Begin { [Uri]$Uri = "$script:RankingsEndpoint/Global/powerplay/seasons?limit=$Limit" $pattern = '^(?<Year>\d{4})(?<Month>\d{2})(?<Day>\d{2}T\d{2})(?<Hour>\d{2})(?<Minute>\d{2})(?<Seconds>\.\d{3}Z)$' If ($Date) { If ($Date -notmatch '\d{1,2}-\d{1,2}-\d{4}') { Throw "`$Date value is not in the correct format. Please use the following formats: MM-dd-yyyy OR M-d-yyyy." } if (-not(Test-PowerPlayDate $Date)) { Write-Warning -Message "Date provided in `$Date variable is outside range of available dates. All SeasonIds within the given limit will be returned..." Remove-Variable -Name Date -Force } } $replacement = '${Year}-${Month}-${Day}:${Hour}:${Minute}${Seconds}' } Process { if ($Global -or (-not($CountryCode))) { Write-Verbose -Message "Global Switch detected or country code is null, setting search to Global..." Try { $Response = Invoke-BrawlRequest -Uri $URI ForEach ($Record in $Response) { $Record.startTime = Get-Date ($Record.startTime -replace $pattern, $replacement) -Format "MM-dd-yyyy" $Record.endTime = Get-Date ($Record.endTime -replace $pattern, $replacement) -Format "MM-dd-yyyy" } } catch { } } else { Try { [Uri]$Uri = "$script:RankingsEndpoint/$CountryCode/powerplay/seasons?limit=$limit" $Response = Invoke-BrawlRequest -Uri $URI ForEach ($Record in $Response) { $Record.startTime = Get-Date ($Record.startTime -replace $pattern, $replacement) -Format "MM-dd-yyyy" $Record.endTime = Get-Date ($Record.endTime -replace $pattern, $replacement) -Format "MM-dd-yyyy" } } catch { } } $object = $Response | Select-Object id, @{Name = "startDate"; Expression = { $_.Starttime } }, @{Name = "endDate"; Expression = { $_.Endtime } } if ($Date) { Write-Verbose "Date set to : [DateTime]$Date" $object | Where-Object { ([DateTime]$Date -ge [DateTime]$_.StartDate) -and ([DateTime]$Date -le [DateTime]$_.endDate) } } Else { $Object } } } Function New-BrawlKeyFile { <# .SYNOPSIS Creates a key file .DESCRIPTION Creates a key file. This is used to authenticate to the brawl stars API Under the hood it uses Export-CLIXML to utilize windows dpapi encryption. .PARAMETER Secretname Name of file .PARAMETER Directory directory to store file in .EXAMPLE New-BrawlKeyFile File ---- Test.Secret .NOTES Should make this a little cleaner. #> [CmdletBinding()] Param ( $Directory = "$Script:KeysDirectory", [String]$SecretName = "Default.Secret" ) Process { $Credential = Get-Credential -Message "Enter API Key" -UserName "API" If (-not (Test-Path -Path "$Directory\$SecretName")) { $Credential | Export-Clixml -Path "$Directory\$SecretName" | Out-Null } Else { Write-Warning -Message "File $SecretName already exists in $Directory... setting unique name" $SecretName = "Key-$(Get-Date -Format FileDateTime).Secret" Write-Host "File name Set to $SecretName" $Credential | Export-Clixml -Path "$Script:KeysDirectory\$SecretName" | Out-Null } $CredentialInfo = [PSCustomObject][ordered]@{ "File" = $SecretName } $CredentialInfo } } Function Test-PowerPlayDate { <# .Synopsis Tests to ensure the dates being checked is between the proper dates for powerplay .DESCRIPTION Tests to ensure the dates being checked is between the proper dates for powerplay .PARAMETER Date Date to query .EXAMPLE Test-PowerPlayDate -Date "$((Get-Date).date)" True .EXAMPLE Test-PowerPlayDate -Date 10/30/2019 True .EXAMPLE Test-PowerPlayDate -Date 10/01/2018 False #> [CmdletBinding()] Param ( [Parameter(ValueFromPipeline)] $Date ) Begin { $ScriptDate = (Get-Date $Date).Date $BeginDate = (Get-Date "10-28-2019").Date $EndDate = (Get-Date -Date ((Get-PowerPlaySeasonID)[-1].endDate)).Date } Process { #Write-Host "ScriptDate:$ScriptDate`nBeginDate:$BeginDate`nEndDate:$EndDate" if (($ScriptDate -ge $BeginDate) -and ($ScriptDate -le $EndDate)) { $true } else { $false } } } #Module base and region files $Script:moduleBase = (Resolve-Path -Path "$PSScriptRoot\..").Path $Script:Regions = "$Script:moduleBase\bin\regions.csv" #API Endpoints $script:baseUri = "https://api.brawlstars.com/v1" $script:PlayersEndPoint = "$script:baseUri/players" $script:ClubsEndpoint = "$script:baseUri/clubs" $script:RankingsEndpoint = "$script:baseUri/rankings" $script:BrawlersEndpoint = "$script:baseUri/brawlers" # Config $Script:ConfigBase = "$env:USERPROFILE\documents\.posh-brawl" $Script:KeysDirectory = "$Script:ConfigBase\Keys" $Script:DefaultKeyFile = "$Script:KeysDirectory\Default.secret" $Script:ConfigDirectory = "$Script:ConfigBase\Configs" $Script:DefaultConfig = "$Script:ConfigBase\Configs\Default.json" # Module Variables Resolve-Path "$PSScriptRoot\Variables\*.ps1" -ErrorAction Ignore | ForEach-Object { . $_.ProviderPath } # Module Functions Resolve-Path "$PSScriptRoot\Functions\Public\*.ps1" -ErrorAction Ignore | ForEach-Object{ . $_.ProviderPath } Resolve-Path "$PSScriptRoot\Functions\Private\*.ps1" -ErrorAction Ignore | ForEach-Object{ . $_.ProviderPath } #Auto Completers Resolve-Path "$PSScriptRoot\ArgumentCompleters\*.ps1" -ErrorAction Ignore | ForEach-Object{ . $_.ProviderPath } $WarningMessage = @" No credential files found in Config directory : $Script:ConfigBase\{0}. Please run New-BrawlConfig to generate credentials, or manually do so using Get-Credential. The Variable must be saved by using Export-CLIXML to the Keys directory with a .SECRET extension. You can also manually specify a credential when using Connect-BrawlStars "@ -f "Keys" if (-not (Test-Path $Script:KeysDirectory)) { Write-Warning -Message "Creating Keys directory..." New-Item -Name Keys -ItemType Directory -Path $Script:ConfigBase -Force } if (-not (Test-Path "$Script:ConfigDirectory")) { Write-Warning -Message "Creating Configs directory..." New-Item -Name Configs -ItemType Directory -Path $Script:ConfigBase -Force } If (-not (Get-ChildItem -Path $Script:KeysDirectory\* -Include *.Secret -ErrorAction SilentlyContinue)) { Write-Warning -Message $WarningMessage } |