MeetupPS.psm1
function Get-MeetupEvent { <# .SYNOPSIS Retrieve Meetup event for a specific group .DESCRIPTION Retrieve Meetup event for a specific group .PARAMETER GroupName Specify the name of the group .PARAMETER Status Specify the status of the event(s). Values accepted: "cancelled", "draft", "past", "proposed", "suggested", "upcoming" Default is 'upcoming'. .PARAMETER Page Number of entries to retrieve. Default is 200 .EXAMPLE Get-MeetupEvent -GroupName FrenchPSUG -Status past .NOTES https://github.com/lazywinadmin/MeetupPS #> [CmdletBinding()] PARAM( [Parameter(Mandatory = $true)] $GroupName, [ValidateSet("cancelled", "draft", "past", "proposed", "suggested", "upcoming")] $Status = 'upcoming', $page = 200 ) TRY { $FunctionName = (Get-Variable -name MyInvocation -Scope 0 -ValueOnly).MyCommand $Url = "https://api.meetup.com/$GroupName/events?status=$Status&page=$page" Write-Verbose -Message "[$FunctionName] Querying API '$Url'..." (invoke-restmethod -uri $Url -UseDefaultCredentials) } catch {$PSCmdlet.ThrowTerminatingError($_)} } function Get-MeetupEventAttendance { <# .SYNOPSIS Get the attendance of an event .DESCRIPTION Get the attendance of an event .PARAMETER GroupName Specify GroupName .PARAMETER ID Specify the Event ID .EXAMPLE Get-MeetupEventAttendance -GroupName FrenchPSUG -id 232807877 .EXAMPLE Get-MeetupEvent -GroupName FrenchPSUG -Status past |select -first 5 |Get-MeetupEventAttendance .NOTES https://github.com/lazywinadmin/MeetupPS #https://www.meetup.com/meetup_api/docs/:urlname/events/:id/attendance/#list #> [Cmdletbinding()] PARAM( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] $GroupName = "FrenchPSUG", [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('EventID')] $Id ) PROCESS { try { $FunctionName = (Get-Variable -name MyInvocation -Scope 0 -ValueOnly).MyCommand if (-not ($script:MeetupAccessToken)) { Write-Warning -Message 'You need to use Set-MeetupConfiguration first to authenticate against the Rest API' } #$PSCmdlet.MyInvocation.ExpectingInput IF ($PSCmdlet.MyInvocation.ExpectingInput) { $GroupName = $Groupname.group.urlname Write-Verbose -Message "[$FunctionName] GroupName '$GroupName' - Values from Pipeline" } ELSE {Write-Verbose -Message "[$FunctionName] GroupName '$GroupName' - Values from Parameters"} Write-Verbose -Message "[$FunctionName] Prepare Splatting" $Splat = @{ Headers = @{Authorization = 'Bearer ' + $($script:MeetupAccessToken.access_token)} Method = 'GET' Uri = "https://api.meetup.com/$GroupName/events/$id/attendance" } Write-Verbose -Message "[$FunctionName] Querying API '$($Splat.uri)'..." (Invoke-RestMethod @splat) } catch { $PSCmdlet.ThrowTerminatingError($_) } } } function Get-MeetupGroup { <# .SYNOPSIS Retrieve Meetup group information .DESCRIPTION Retrieve Meetup group information .PARAMETER GroupName Specify the name of the group name .EXAMPLE Get-MeetupGroup -GroupName FrenchPSUG .NOTES https://github.com/lazywinadmin/MeetupPS #> [CmdletBinding()] PARAM( [Parameter(Mandatory = $true)] $GroupName) TRY { $FunctionName = (Get-Variable -name MyInvocation -Scope 0 -ValueOnly).MyCommand $Url = "https://api.meetup.com/$GroupName" Write-Verbose -Message "[$FunctionName] Querying Url = '$Url'" $GroupObject = invoke-restmethod -uri $Url -UseDefaultCredentials Write-Output -InputObject $GroupObject } Catch {$PSCmdlet.ThrowTerminatingError($_)} } function Get-MeetupGroupMember { <# .SYNOPSIS Get the member of a meetup group .DESCRIPTION Get the member of a meetup group .PARAMETER GroupName Specify GroupName .PARAMETER Page Number of requested members to return. Defaults to 200 .PARAMETER Order Orders results according to definitions listed below. May be one of "interesting", "name", "joined", or "stepup_recommended" -interesting Order which may be interesting to the authorized member -joined Time member joined this group -name The name of the member -stepup_recommended Sorts by likelikhood to step up as organizer .EXAMPLE Get-MeetupGroupMember -Groupname FrenchPSUG .EXAMPLE Get-MeetupGroupMember -Groupname FrenchPSUG -Page 500 -order joined .NOTES https://github.com/lazywinadmin/MeetupPS https://www.meetup.com/meetup_api/docs/:urlname/members/#list # desc Boolean value controling sort order of results. Currently this parameter is only supported for "joined" and "name" sorted results. Defaults to true # fields A comma-delimited list of optional fields to append to the response # filter May be set to 'stepup_eligible' to return only members eligible to step up as organizer # order "interesting", "name", "joined", or "stepup_recommended" # page Number of requested members to return. Defaults to 200 # role May be set to "leads" to filter returned members on the lead team # status A comma-delimited list of member statuses. Valid values include "active" or "pending". Defaults to "active". Organizers may request pending #> [Cmdletbinding()] PARAM( [Parameter(Mandatory = $true)] $GroupName = "FrenchPSUG", [Alias('Limit')] $Page=200, [ValidateSet('interesting', 'name', 'joined', 'stepup_recommended')] $Order='joined' ) try { $FunctionName = (Get-Variable -name MyInvocation -Scope 0 -ValueOnly).MyCommand if (-not ($script:MeetupAccessToken)) { Write-Warning -Message 'You need to use Set-MeetupConfiguration first to authenticate against the Rest API' } Write-Verbose -Message "[$FunctionName] Prepare Splatting" $Splat = @{ Headers = @{Authorization = 'Bearer ' + $($script:MeetupAccessToken.access_token)} Method = 'GET' Uri = "https://api.meetup.com/$GroupName/members?order=$order&page=$page" } Write-Verbose -Message "[$FunctionName] Querying API '$($Splat.uri)'..." (Invoke-RestMethod @splat) } catch { $PSCmdlet.ThrowTerminatingError($_) } } function Get-MeetupPhoto { <# .SYNOPSIS Retrieve photos for a specific Meetup group. .DESCRIPTION Retrieve photos for a specific Meetup group. .PARAMETER GroupName Specify the name of the group. .PARAMETER AlbumId Specify the unique identifier of a specific photo album. .PARAMETER Page Number of photos to retrieve. Default is 200 .PARAMETER Descending Reverses the order in which returned photos are listed. .EXAMPLE Get-MeetupPhoto -GroupName FrenchPSUG This command returns all of the French PowerShell User Group's photos. .EXAMPLE Get-MeetupPhoto -GroupName FrenchPSUG -AlbumId 28555599 This command returns only the photos from the specified album belonging to the French PowerShell User Group. .EXAMPLE Get-MeetupPhotoAlbum -GroupName FrenchPSUG -Page 2 | Get-MeetupPhoto -GroupName FrenchPSUG This command returns only the photos from the first 2 albums belonging to the French PowerShell User Group. .NOTES https://github.com/lazywinadmin/MeetupPS #> [CmdletBinding()] PARAM( [Parameter(Mandatory = $true)] [string] $GroupName, [Parameter(ValueFromPipelineByPropertyName = $true)] [Alias('Id')] [uint64] $AlbumId, [int] $Page = 200, [switch] $Descending ) BEGIN { $FunctionName = (Get-Variable -name MyInvocation -Scope 0 -ValueOnly).MyCommand } PROCESS { TRY { if ($AlbumId) { $Url = "https://api.meetup.com/$GroupName/photo_albums/$AlbumId/photos?page=$Page" } else { $Url = "https://api.meetup.com/$GroupName/photos?page=$Page" } if ($Descending) { $Url = "$Url&desc=true" } Write-Verbose -Message "[$FunctionName] Querying Url = '$Url'" $Photos = invoke-restmethod -uri $Url -UseDefaultCredentials Write-Output -InputObject $Photos } catch {$PSCmdlet.ThrowTerminatingError($_)} } } function Get-MeetupPhotoAlbum { <# .SYNOPSIS Retrieve photo albums for a specific Meetup group. .DESCRIPTION Retrieve photo albums for a specific Meetup group. .PARAMETER GroupName Specify the name of the group. .PARAMETER AlbumId Specify the unique identifier of a specific photo album. .PARAMETER Page Number of entries to retrieve. Default is 200. Cannot be used in conjunction with AlbumId. .PARAMETER Offset Offsets the number of entries to return for pagination in conjunction with Page. Cannot be used in conjunction with AlbumId. .EXAMPLE Get-MeetupPhotoAlbum -GroupName FrenchPSUG This command returns all of the French PowerShell User Group's photo albums. .EXAMPLE Get-MeetupPhotoAlbum -GroupName FrenchPSUG -AlbumId 28555599 This command returns only the specified photo album belonging to the French PowerShell User Group. .NOTES https://github.com/lazywinadmin/MeetupPS #> [CmdletBinding(DefaultParameterSetName = 'AllAlbums')] PARAM( [Parameter(Mandatory = $true)] [string] $GroupName, [Parameter(Mandatory = $true, ParameterSetName = 'SpecificAlbum')] [Alias('Id')] [uint64] $AlbumId, [Parameter(ParameterSetName = 'AllAlbums')] [int] $Page = 200, [Parameter(ParameterSetName = 'AllAlbums')] [int] $Offset ) TRY { $FunctionName = (Get-Variable -name MyInvocation -Scope 0 -ValueOnly).MyCommand if ($AlbumId) { $Url = "https://api.meetup.com/$GroupName/photo_albums/$AlbumId" } else { $Url = "https://api.meetup.com/$GroupName/photo_albums?page=$Page" if ($Offset) { $Url = "$Url&offset=$Offset" } } Write-Verbose -Message "[$FunctionName] Querying Url = '$Url'" $Albums = invoke-restmethod -uri $Url -UseDefaultCredentials Write-Output -InputObject $Albums } catch {$PSCmdlet.ThrowTerminatingError($_)} } function New-MeetupEvent { <# .SYNOPSIS Create a Meetup event .DESCRIPTION Create a Meetup event .PARAMETER GroupName Specify GroupName .PARAMETER Title Specify the Title of the event .PARAMETER Time Specify the date and time to the event This will take the local time of the event. .PARAMETER Description Specify the Description of the event .PARAMETER Announce Specify this switch to announce the event to your group members .PARAMETER PublishStatus Specify the Publish status of the event. Values accepted: draft or published .EXAMPLE New-MeetupEvent ` -GroupName FrenchPSUG ` -Title 'New Event from MeetupPS' ` -Time '2018/06/01 3:00pm' ` -Description "PowerShell WorkShop<br><br>In this session we'll talk about ..." ` -PublishStatus draft .NOTES https://github.com/lazywinadmin/MeetupPS #> [Cmdletbinding()] PARAM( [Parameter(Mandatory = $true)] $GroupName = "FrenchPSUG", [Parameter(Mandatory = $true)] $Title, $Time, $Description = "Description:<br><br>New Event from MeetupPS PowerShell module<br><br>Speaker:<br>", [switch]$Announce = $false, [ValidateSet('draft', 'published')] $PublishStatus = 'draft' ) try { $FunctionName = (Get-Variable -name MyInvocation -Scope 0 -ValueOnly).MyCommand if (-not ($script:MeetupAccessToken)) { Write-Warning -Message 'You need to use Set-MeetupConfiguration first to authenticate against the Rest API' } Write-Verbose -Message "[$FunctionName] Format date to unix time" $Time = Get-Date -date ((Get-Date -Date $Time).ToUniversalTime()) -UFormat %s # Append Trailing Zeros (it needs to be 13 digits if ($Time.Length -lt 13) { $diff = 13 - $Time.Length $Time = "{0}{1:$('0'*$diff)}" -f $Time, 0 } Write-Verbose -Message "[$FunctionName] Prepare Splatting" $Splat = @{ Headers = @{Authorization = 'Bearer ' + $($script:MeetupAccessToken.access_token)} Method = 'POST' Uri = "https://api.meetup.com/2/event" Body = "group_urlname=$groupName&name=$Title&time=$Time&publish_status=$PublishStatus&announce=$Announce&description=$description" } Write-Verbose -Message "[$FunctionName] Creating Event..." Invoke-RestMethod @splat } catch { $PSCmdlet.ThrowTerminatingError($_) } } function Set-MeetupConfiguration { <# .SYNOPSIS Authenticate against the Rest API .DESCRIPTION Authenticate against the Rest API .PARAMETER ClientID Specify the Key of the Oauth Consumer .PARAMETER Secret Specify the Secret of the Oauth Consumer .PARAMETER RedirectUri Specify the RedirectUri to use .PARAMETER Scope Specify the scope Default are the following ("basic", "reporting", "event_management") .EXAMPLE # Connect against Meetup.com API $Key = '<Your Oauth Consumer Key>' $Secret = '<Your Oauth Consumer Secret>' Set-MeetupConfiguration -ClientID $Key -Secret $Secret .NOTES https://github.com/lazywinadmin/MeetupPS #> [CmdletBinding()] PARAM( [Parameter(Mandatory=$true)] $ClientID, [Parameter(Mandatory = $true)] $Secret, $RedirectUri = 'https://github.com/lazywinadmin/MeetupPS', $Scope = ("basic", "reporting", "event_management") ) TRY{ $FunctionName = (Get-Variable -name MyInvocation -Scope 0 -ValueOnly).MyCommand # Retrieve Code $Url = "https://secure.meetup.com/oauth2/authorize?client_id=$ClientID&response_type=code&redirect_uri=$RedirectUri" Write-Verbose -Message "[$FunctionName] Querying Url = '$Url'" # Ask user to authenticate and return Code only $OAuthCode = Get-OauthCode -url $Url Write-Verbose -Message "[$FunctionName] Retrieving Code from '$OAuthCode'" $Code = ($OAuthCode -split "\?code=")[1] Write-Verbose -Message "[$FunctionName] Code '$Code'" # Retrieve Access Token Write-Verbose -Message "[$FunctionName] Querying Access Token with ClientID '$ClientId'" $script:MeetupAccessToken = Get-OAuthAccessToken -ClientID $clientID -Secret $Secret -Code $Code -RedirectUri $RedirectUri -Scopes $Scope }Catch { $PSCmdlet.ThrowTerminatingError($_) } } function Get-OAuthAccessToken { <# .SYNOPSIS Retrieve Oauth Access Token .DESCRIPTION Retrieve Oauth Access Token .NOTES https://github.com/lazywinadmin/MeetupPS #> [CmdletBinding()] PARAM( $ClientID, $Secret, $Code, $RedirectUri = 'https://github.com/lazywinadmin/MeetupPS', $AccessUri = 'https://secure.meetup.com/oauth2/access', $Scopes = ("basic", "reporting", "event_management") ) try { # Build Body $body = "client_id=$ClientID&client_secret=$Secret&grant_type=authorization_code&redirect_uri=$RedirectUri&code=$code" # Build Header $Headers = @{ 'X-OAuth-Scopes' = $Scopes 'X-Accepted-OAuth-Scopes' = $Scopes } # Build splatting $Splatting = @{ Uri = $AccessUri Method = 'Post' ContentType = 'application/x-www-form-urlencoded' Body = $Body headers = $Headers } Invoke-RestMethod @Splatting } catch { $PSCmdlet.ThrowTerminatingError($_) } } Function Get-OauthCode { <# .SYNOPSIS Function to show the Microsoft Authentication window .NOTES https://github.com/lazywinadmin/MVP #Credit to Stephen Owen: https://raw.githubusercontent.com/1RedOne/PSWordPress/master/Private/Show-oAuthWindow.ps1 #> [CmdletBinding()] Param( [Uri]$url, $Width = 440, $Height = 640 ) Process { $Scriptname = (Get-Variable -name MyInvocation -Scope 0 -ValueOnly).MyCommand try { Write-Verbose -Message "[$ScriptName] Load assembly System.Windows.Forms" Add-Type -AssemblyName System.Windows.Forms -ErrorAction Stop Write-Verbose -Message "[$ScriptName] Create Form" $global:form = New-Object -TypeName System.Windows.Forms.Form -Property @{Width = $Width; Height = $Height} Write-Verbose -Message "[$ScriptName] Create Web browser" $global:web = New-Object -TypeName System.Windows.Forms.WebBrowser -Property @{Width = 420; Height = 600; Url = $url} # define $uri in the immediate parent scope: 1 Write-Verbose -Message "[$ScriptName] Define DocumentCompleted scriptblock" $global:DocComp = { $global:uri = $web.Url.AbsoluteUri if ($global:uri -match 'error=[^&]*|code=[^&]*') { $global:form.Close() } } $global:web.ScriptErrorsSuppressed = $true $global:web.Add_DocumentCompleted($DocComp) $global:form.Controls.Add($web) $global:form.Add_Shown( {$form.Activate()}) Write-Verbose -Message "[$ScriptName] Show Dialog" $null = $form.ShowDialog() $uri } catch { $PSCmdlet.ThrowTerminatingError($_) } } } # things to append at the end of the Psm1 |