MVP.psm1

Function Get-MVPContribution {
<#
.SYNOPSIS
    Invoke the GetContributions REST API to retrieve your contributions
 
.DESCRIPTION
    Gets yours contributions without parameter or by specifying the id of a contribution
 
.PARAMETER Offset
    Page skip integer as int32
 
.PARAMETER Limit
    Page take integer as int32
 
.PARAMETER ID
    It's the id of a contribution
 
.EXAMPLE
    Get-MVPContribution
     
    It gets your most recent contributions from range 1 to 5
 
.EXAMPLE
    Get-MVPContribution -ID 631670
 
    It gets your contribution id 631670
 
.NOTES
    https://github.com/lazywinadmin/MVP
#>

[CmdletBinding(DefaultParameterSetName='All')]
Param(
    [parameter(ParameterSetName='All')]
    [int32]$Offset=0,

    [parameter(ParameterSetName='All')]
    [int32]$Limit=5,

    [parameter(ParameterSetName='ID',ValueFromPipeline,ValueFromPipelineByPropertyName)]
    [Alias('ContributionId')]
    [int32]$ID
)
Process {

    $Scriptname = (Get-Variable -name MyInvocation -Scope 0 -ValueOnly).MyCommand

    if (-not ($global:MVPPrimaryKey -and $global:MVPAuthorizationCode)) {
        Write-Warning -Message "[$Scriptname] You need to use Set-MVPConfiguration first to set the Primary Key"
        break
    }
    
    Try {
        Write-Verbose -message "[$Scriptname] Set Configuration"
        Set-MVPConfiguration -SubscriptionKey $MVPPrimaryKey

        Write-Verbose -message "[$Scriptname] Build Splatting"
        $Splat = @{
            Uri = "https://mvpapi.azure-api.net/mvp/api/contributions/$($Offset)/$($Limit)"
            Headers = @{
                'Ocp-Apim-Subscription-Key' = $global:MVPPrimaryKey ;
                Authorization = $Global:MVPAuthorizationCode
            }
            ErrorAction = 'Stop'
        }

        if ($PSBoundParameters['ID']) {
            Write-Verbose -message "[$Scriptname] ID Specified"
            $Splat.Uri = "https://mvpapi.azure-api.net/mvp/api/contributions/$($ID)"
            Write-Verbose -message "[$Scriptname] URI = $($Splat.Uri)"
        Write-Verbose -message "[$Scriptname] Querying Rest api..."
            Invoke-RestMethod @Splat
        }
        else{
            Write-Verbose -Message "[$Scriptname] Displaying contributions range from $($Offset) to $($($Offset)+$($Limit))"
            Write-Verbose -message "[$Scriptname] URI = $($Splat.Uri)"
            Write-Verbose -message "[$Scriptname] Querying Rest api..."
            (Invoke-RestMethod @Splat).Contributions
        }
    }
    catch {
        $PSCmdlet.ThrowTerminatingError($_)
    }   
}
}
Function Get-MVPContributionArea {
<#
    .SYNOPSIS
        Invoke the GetContributionAreas REST API to retrieve your contribution areas
 
    .DESCRIPTION
        Gets a list of Contribution areas grouped by Award Names
 
    .PARAMETER Other
        It gets the list of Other Award Categories
 
    .PARAMETER All
        It gets the list of all Award Category names
 
    .EXAMPLE
        Get-MVPContributionArea
 
        It gets the list of your awarded Categories
 
    .EXAMPLE
        Get-MVPContributionArea -Other
         
        It gets the list of Other award categories
#>

[CmdletBinding(DefaultParameterSetName='Mine')]
Param(
    [parameter(ParameterSetName='Other')]
    [switch]$Other,

    [parameter(ParameterSetName='All')]
    [switch]$All
)
Begin {}
Process {


    if (-not ($global:MVPPrimaryKey -and $global:MVPAuthorizationCode)) {
        Write-Warning -Message "You need to use Set-MVPConfiguration first to set the Primary Key"
    } else {

        Set-MVPConfiguration -SubscriptionKey $MVPPrimaryKey
        
        $Splat = @{
            Uri = 'https://mvpapi.azure-api.net/mvp/api/contributions/contributionareas'
            Headers = @{
                'Ocp-Apim-Subscription-Key' = $global:MVPPrimaryKey
                Authorization = $Global:MVPAuthorizationCode
            }
            ErrorAction = 'Stop'
        }
        try {
            $careas = (Invoke-RestMethod @Splat)

            Switch($PsCmdlet.ParameterSetName) {
                'Mine' {
                    ($careas | Where { $_.AwardCategory -eq 'My Awarded Category' }).Contributions
                    break
                }
                'Other' {
                    ($careas | Where { $_.AwardCategory -eq 'Other Award Category' }).Contributions.contributionarea
                    break
                }
                'All' {
                    $careas.Contributions.contributionarea
                    break
                }
                default{}

            }
        } catch {
            Write-Warning -Message "Failed to invoke the GetContributionAreas API because $($_.Exception.Message)"
        }
    }
}
End {}
}
Function Get-MVPContributionType {
<#
    .SYNOPSIS
        Invoke the GetContributionTypes REST API to retrieve contribution types
 
    .DESCRIPTION
        Gets a list of contribution types
 
 
    .EXAMPLE
        Get-MVPContributionType
 
        It gets the list of contribution types
#>

[CmdletBinding()]
Param()
Begin {}
Process {

    if (-not ($global:MVPPrimaryKey -and $global:MVPAuthorizationCode)) {
    
    Write-Warning -Message 'You need to use Set-MVPConfiguration first to set the Primary Key'
    
    } else {

        Set-MVPConfiguration -SubscriptionKey $MVPPrimaryKey

        $Splat = @{
            Uri = 'https://mvpapi.azure-api.net/mvp/api/contributions/contributiontypes'
            Headers = @{
                'Ocp-Apim-Subscription-Key' = $global:MVPPrimaryKey
                Authorization = $Global:MVPAuthorizationCode
            }
            ErrorAction = 'Stop'
        }
        try {
             [PSCustomObject[]](Invoke-RestMethod @Splat)
        } catch {
            Write-Warning -Message "Failed to invoke the GetContributionTypes API because $($_.Exception.Message)"
        }
    }
}
End {}
}
Function Get-MVPContributionVisibility {
<#
    .SYNOPSIS
        Invoke the GetSharingPreferences REST API to retrieve contribution visibility types
 
    .DESCRIPTION
        Gets a list of Sharing Preference / Visibility Types for Contributions
 
    .EXAMPLE
        Get-MVPContributionVisibility
 
#>

[CmdletBinding()]
Param()
Begin {}
Process {

    if (-not ($global:MVPPrimaryKey -and $global:MVPAuthorizationCode)) {
    
        Write-Warning -Message 'You need to use Set-MVPConfiguration first to set the Primary Key'
    
    } else {

        Set-MVPConfiguration -SubscriptionKey $MVPPrimaryKey

        $Splat = @{
            Uri = 'https://mvpapi.azure-api.net/mvp/api/contributions/sharingpreferences'
            Headers = @{
                'Ocp-Apim-Subscription-Key' = $global:MVPPrimaryKey
                Authorization = $Global:MVPAuthorizationCode
            }
            ErrorAction = 'Stop'
        }

        try {
            (Invoke-RestMethod @Splat)
        } catch {
            Write-Warning -Message "Failed to invoke the GetSharingPreferences API because $($_.Exception.Message)"
        }
    }
}
End {}
}
Function Get-MVPOnlineIdentity {
<#
    .SYNOPSIS
        Invoke the GetOnlineIdentities REST API
 
    .DESCRIPTION
        Gets a list of your online identities in your MVP profile
 
    .PARAMETER Id
        It's the id of the online identity in a int32 format
 
    .PARAMETER NominationsId
        It's your MVP Nomination Id in a GUID format a.k.a your OnlineIdentityId
 
    .EXAMPLE
        Get-MVPOnlineIdentity
 
        It gets the list of the online identities in your MVP profile
 
    .EXAMPLE
        Get-MVPOnlineIdentity -Id 55977
 
        It gets the online identity by its id
 
    .EXAMPLE
        Get-MVPOnlineIdentity -NominationsId c00b9dd2-a6a0-e411-8213-9cb654953450
 
        It gets the list of the online identities associated to your MVP nomination id
 
#>

[CmdletBinding(DefaultParameterSetName='All')]
Param(

    [parameter(ParameterSetName='ById',ValueFromPipeline,ValueFromPipelineByPropertyName)]
    [Alias('PrivateSiteId')]
    [int32]$ID,

    [parameter(ParameterSetName='ByNominationID')]
    [Alias('OnlineIdentityId')]
    [Guid]$NominationsId
)
Begin {}
Process {

    if (-not ($global:MVPPrimaryKey -and $global:MVPAuthorizationCode)) {
    
        Write-Warning -Message 'You need to use Set-MVPConfiguration first to set the Primary Key'
    
    } else {

        Set-MVPConfiguration -SubscriptionKey $MVPPrimaryKey

        $Splat = @{
            Uri = 'https://mvpapi.azure-api.net/mvp/api/onlineidentities'
            Headers = @{
                'Ocp-Apim-Subscription-Key' = $global:MVPPrimaryKey
                Authorization = $Global:MVPAuthorizationCode
            }
            ErrorAction = 'Stop'
        }

    
        if ($ID) {
            $Splat.Uri = "https://mvpapi.azure-api.net/mvp/api/onlineidentities/$($ID)"
        }
        if ($NominationID) {
            $Splat.Uri = "https://mvpapi.azure-api.net/mvp/api/onlineidentities/$($NominationID)"
        }

        try {
            [PSCustomObject[]](Invoke-RestMethod @Splat)
        } catch {
            Write-Warning -Message "Failed to invoke the GetOnlineIdentities API because $($_.Exception.Message)"
        }
    }
}
End {}
}
Function Get-MVPProfile {
<#
    .SYNOPSIS
        Invoke the GetMVPProfile REST API to retrieve an MVP profile summary
 
    .DESCRIPTION
        Gets a user public profile with the MVP id passed as a parameter or gets your MVP profile summary without parameter
 
    .PARAMETER ID
        It's an MVP id
 
    .EXAMPLE
        Get-MVPProfile
         
        It gets your MVP profile summary
 
    .EXAMPLE
        Get-MVPProfile -ID 5000475
 
        It gets the public profile of Francois-Xavier Cat
 
    .EXAMPLE
        Get-MVPProfile -ID '5000890'
         
        It gets the public profile of Emin Atac
#>

[CmdletBinding()]
Param(
    [Parameter()]
    [String]$ID
)
Begin {}
Process {
    if (-not ($global:MVPPrimaryKey -and $global:MVPAuthorizationCode)) {

        Write-Warning -Message 'You need to use Set-MVPConfiguration first to set the Primary Key'
        
    } else {
        
        Set-MVPConfiguration -SubscriptionKey $MVPPrimaryKey

        $Splat = @{
            Uri = 'https://mvpapi.azure-api.net/mvp/api/profile?'
            Headers = @{
                'Ocp-Apim-Subscription-Key' = $global:MVPPrimaryKey ;
                Authorization = $global:MVPAuthorizationCode
            }
            ErrorAction = 'Stop' ;
        }

        if ($ID) {
            $Splat.Uri = "https://mvpapi.azure-api.net/mvp/api/profile/$ID"
        }

        try {
            Invoke-RestMethod @Splat
        } catch {
            Write-Warning -Message "Failed to invoke the Get-MVPProfile API because $($_.Exception.Message)"
        }
    }
}
End {}
}
Function Get-MVPProfileImage {
<#
    .SYNOPSIS
        Invoke the GetMVPProfileImage REST API to retrieve your MVP profile image
 
    .DESCRIPTION
        Gets your MVP profile image
 
    .EXAMPLE
        Get-MVPProfileImage
         
        It gets your MVP profile image.
#>

[CmdletBinding()]
Param()

    if (-not ($global:MVPPrimaryKey -and $global:MVPAuthorizationCode)) {
        Write-Warning -Message 'You need to use Set-MVPConfiguration first to set the Primary Key'
    } else {
        Set-MVPConfiguration -SubscriptionKey $MVPPrimaryKey       

        $Splat = @{
            Uri = 'https://mvpapi.azure-api.net/mvp/api/profile/photo'
            Headers = @{
                'Ocp-Apim-Subscription-Key' = $global:MVPPrimaryKey ;
                Authorization = $Global:MVPAuthorizationCode
            }
            ErrorAction = 'Stop'
        }

        try {
            Invoke-RestMethod @Splat
        } catch {
            Write-Warning -Message "Failed to invoke the Get-MVPProfile API because $($_.Exception.Message)"
        }
    }
}
Function New-MVPContribution {
<#
    .SYNOPSIS
        Invoke the PostContribution REST API
 
    .DESCRIPTION
        Creates a new Contribution item
 
    .PARAMETER ContributionTechnology
        Specifies the Contribution technology
        This parameter is dynamic and is retrieving the information from Get-MVPContributionArea
 
    .PARAMETER AdditionalTechnologies
        Specifies an additional Contribution
        This parameter is dynamic and is retrieving the information from Get-MVPContributionArea
 
    .PARAMETER ContributionType
        Specifies the Contribution Type
        This parameter is dynamic and is retrieving the information from Get-MVPContributionType
 
    .PARAMETER StartDate
        Specifies the Date of the activity
 
    .PARAMETER Title
        Specifies the Title of the activity
 
    .PARAMETER Description
        Specifies the Description of the activity
 
    .PARAMETER ReferenceUrl
        Specifies the Url of the activity
 
    .PARAMETER AnnualQuantity
        Specifies the Annual quantity.
        Default is 1
 
    .PARAMETER SecondAnnualQuantity
        Specifies the Second Annual quantity.
        Default is 0
 
    .PARAMETER AnnualReach
        Specifies the Annual Reach
        Default is 0
 
    .PARAMETER Visibility
        Specifies the audience that will be able to see your activity
        Values: 'EveryOne','Microsoft','MVP Community','Microsoft Only'
        Default = 'Microsoft'
 
    .EXAMPLE
    $Splat = @{
        startdate ='2018/10/10'
        Title='Test from mvpapi.azure-api.net'
        Description = 'Description sample'
        ReferenceUrl='https://github.com/lazywinadmin/MVP'
        AnnualQuantity='1'
        SecondAnnualQuantity='0'
        AnnualReach = '0'
        Visibility = 'EveryOne' # Get-MVPContributionVisibility
        ContributionType = 'Blog Site Posts' # Get-MVPContributionType
        ContributionTechnology = 'PowerShell' # Get-MVPContributionArea
        AdditionalTechnologies = 'ARM & DevOps on Azure (Chef, Puppet, Salt, Ansible, Dev/Test Lab)' # Get-MVPContributionArea
    }
    New-MVPContribution @splat
 
    This will create a new MVP Contribution using the current session opened by Set-MVPConfiguration
 
    .NOTES
        https://github.com/lazywinadmin/MVP
#>

[CmdletBinding()]
Param(
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [String]$StartDate = (Get-Date -Format 'yyyy/MM/dd'),
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [String]$Title='Test from mvpapi.azure-api.net',

    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [String]$Description='Description sample',
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [String]$ReferenceUrl='https://github.com/lazywinadmin/MVP',
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [String]$AnnualQuantity='1',
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [String]$SecondAnnualQuantity='0',

    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [String]$AnnualReach = '0',
    
    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [ValidateSet('EveryOne','Microsoft','MVP Community','Microsoft Only')]
    [String]$Visibility = 'Microsoft'
)
DynamicParam {
    # Create dictionary
    $Dictionary = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameterDictionary

    # ContributionTechnology
    $ParameterName = 'ContributionTechnology'
    $AttribColl1 = New-Object -TypeName System.Collections.ObjectModel.Collection[System.Attribute]
    $Param1Att = New-Object -TypeName System.Management.Automation.ParameterAttribute
    $Param1Att.Mandatory = $true
    $Param1Att.ValueFromPipelineByPropertyName = $true
    $Param1Att.ParameterSetName = '__AllParameterSets'
    $AttribColl1.Add($Param1Att)
    $AttribColl1.Add((New-Object -TypeName System.Management.Automation.ValidateSetAttribute(Get-MVPContributionArea -All | Select-Object -ExpandProperty Name)))
    $Dictionary.Add($ParameterName,(New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttribColl1)))

    # ContributionType
    $ParameterID = 'ContributionType'
    $AttribColl2 = New-Object -TypeName System.Collections.ObjectModel.Collection[System.Attribute]
    $Param2Att = New-Object -TypeName System.Management.Automation.ParameterAttribute
    $Param2Att.Mandatory = $true
    $Param2Att.ValueFromPipelineByPropertyName=$true
    $Param2Att.ParameterSetName = '__AllParameterSets'
    $AttribColl2.Add($Param2Att)
    $AttribColl2.Add((New-Object -TypeName System.Management.Automation.ValidateSetAttribute(Get-MVPContributionType | Select-Object -ExpandProperty Name)))
    $Dictionary.Add($ParameterID,(New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter($ParameterID, [string], $AttribColl2)))

    # AdditionalTechnologies
    $ParameterName3 = 'AdditionalTechnologies'
    $AttribColl3 = New-Object -TypeName System.Collections.ObjectModel.Collection[System.Attribute]
    $Param3Att = New-Object -TypeName System.Management.Automation.ParameterAttribute
    $Param3Att.Mandatory = $false
    $Param3Att.ValueFromPipelineByPropertyName = $true
    $Param3Att.ParameterSetName = '__AllParameterSets'
    $AttribColl3.Add($Param3Att)
    $AttribColl3.Add((New-Object -TypeName System.Management.Automation.ValidateSetAttribute(Get-MVPContributionArea -All | Select-Object -ExpandProperty Name)))
    $Dictionary.Add($ParameterName3,(New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter($ParameterName3, [string], $AttribColl3)))

    #Return dictionary
    $Dictionary
}
Begin {}
Process {
    if (-not ($global:MVPPrimaryKey -and $global:MVPAuthorizationCode)) {
        Write-Warning -Message 'You need to use Set-MVPConfiguration first to set the Primary Key'
    } else {

        Set-MVPConfiguration -SubscriptionKey $MVPPrimaryKey
        
        $Splat = @{
            Uri = 'https://mvpapi.azure-api.net/mvp/api/contributions'
            Headers = @{
                'Ocp-Apim-Subscription-Key' = $global:MVPPrimaryKey
                Authorization = $Global:MVPAuthorizationCode
                ContentType = 'application/json'
                }
            Method = 'POST'
            ContentType = 'application/json'
            ErrorAction = 'Stop'
        }

        # Verify the Contribution Type
        $type = Get-MVPContributionType |
            Where-Object -FilterScript {$_.name -eq $PSBoundParameters['ContributionType']}

        # Verify the Contribution Technology
        $Technology = Get-MVPContributionArea -All |
            Where-Object -FilterScript {$_.name -eq $PSBoundParameters['ContributionTechnology']}

        # Verify the Additional Technology
        $AdditionalTechnologies = Get-MVPContributionArea -All |
            Where-Object -FilterScript {$_.name -eq $PSBoundParameters['AdditionalTechnologies']}

        # Get the Visibility
        $VisibilityObject = Get-MVPContributionVisibility |
            Where-Object -FilterScript {$_.Description -eq $Visibility }

        $Body = @"
{
  "ContributionId": 0,
  "ContributionTypeName": "$($type.name)",
  "ContributionType": {
    "Id": "$($type.id)",
    "Name": "$($type.name)",
    "EnglishName": "$($type.englishname)"
  },
  "ContributionTechnology": {
    "Id": "$($Technology.id)",
    "Name": "$($Technology.name)",
    "AwardName": "$($Technology.awardname)",
    "AwardCategory": "$($Technology.awardcategory)"
  },
  "AdditionalTechnologies": [
    {
        "Id": "$($AdditionalTechnologies.id)",
        "Name": "$($AdditionalTechnologies.name)",
        "AwardName": "$($AdditionalTechnologies.awardname)",
        "AwardCategory": "$($AdditionalTechnologies.awardcategory)"
    }
  ],
  "StartDate": "$StartDate",
  "Title": "$Title",
  "ReferenceUrl": "$ReferenceUrl",
  "Visibility": {
    "Id": $($VisibilityObject.id),
    "Description": "$($VisibilityObject.Description)",
    "LocalizeKey": "$($VisibilityObject.LocalizeKey)"
  },
  "AnnualQuantity": $AnnualQuantity,
  "SecondAnnualQuantity": $SecondAnnualQuantity,
  "AnnualReach": $AnnualReach,
  "Description": "$Description"
}
"@
  
        try {
            Write-Verbose -Message "About to create a new contribution with Body $($Body)"
            Invoke-RestMethod @Splat -Body $Body
        } catch {
            Write-Warning -Message "Failed to invoke the PostContribution API because $($_.Exception.Message)"
        }
    }     
}
End {}
}
Function New-MVPOnlineIdentity {
<#
    .SYNOPSIS
        Invoke the PostOnlineIdentity REST API
 
    .DESCRIPTION
        Creates a new online identity
 
    .PARAMETER ID
        Specify the Id of the online identity in a int32 format
 
    .PARAMETER SocialNetwork
        Specify the Social Network
 
    .PARAMETER URL
        Specify the URL
 
    .PARAMETER AllowMicrosoftToQueryMyId
        Specify if you want to allo Microsoft to query the ID
 
    .PARAMETER Visibility
        Specify the Visbility (see Get-MVPContributionVisibility)
         
    .EXAMPLE
        New-MVPOnlineIdentity -SocialNetwork Code -Url 'test' -Verbose
     
    .EXAMPLE
        New-MVPOnlineIdentity -SocialNetwork Code -Url 'c:\\windows\\test' -AllowMicrosoftToQueryMyId -Visibility Microsoft -Verbose
#>

[CmdletBinding()]
Param(
    
    [Parameter()]
    [ValidateSet('Blog','Code','Codeplex','Exchange DL Subscription Email','Facebook','GitHub','Google+','Instagram',
                 'Klout','LinkedIn','Meetup','Microsoft ASP.NET Forum','Microsoft IIS Forum','MS Community (MS Answers)',
                 'MSDN/Technet','Naver ID','Other','StackOverflow','Twitter','Website','Windows/Windows Phone Dev Center ID',
                 'Xbox Live gamertag','Xing','Yammer','YouTube')]
    [String]$SocialNetwork = 'Twitter',
        
    [Parameter()]
    [String]$URL='https://mvpapi.azure-api.net',
    
    [Parameter()]
    [Switch]$AllowMicrosoftToQueryMyId,

    [Parameter()]
    [ValidateSet('EveryOne','Microsoft','MVP Community','Microsoft Only')]
    [String]$Visibility = 'Microsoft'
)
Begin {}
Process {
    if (-not ($global:MVPPrimaryKey -and $global:MVPAuthorizationCode)) {
        Write-Warning -Message 'You need to use Set-MVPConfiguration first to set the Primary Key'
    } else {

        Set-MVPConfiguration -SubscriptionKey $MVPPrimaryKey
        
        $Splat = @{
            Uri = 'https://mvpapi.azure-api.net/mvp/api/onlineidentities'
            Headers = @{
                'Ocp-Apim-Subscription-Key' = $global:MVPPrimaryKey
                Authorization = $Global:MVPAuthorizationCode
                ContentType = 'application/json'
                }
            Method = 'POST'
            ContentType = 'application/json'
            ErrorAction = 'Stop'
        }

        # Get the Visibility
        $VisibilityObject = Get-MVPContributionVisibility | Where {$_.Description -eq $Visibility }

        if ($AllowMicrosoftToQueryMyId) { 
            $PrivacyConsentStatus  = 'true'
        } else {
            $PrivacyConsentStatus = 'false'
        }
        switch ($SocialNetwork) {
            # missing 'Microsoft Connect' requires an MS account
            # missing 'Microsoft Office 365 forum' requires a displayname

            'Blog'     { $SNid = '202a47c1-33ca-e211-9b1f-00155da65f6a' ; break }
            'Code'     { $SNid = 'a57a64ac-33ca-e211-9b1f-00155da65f6a' ; break }
            'Codeplex' { $SNid = '334c64f8-417f-e311-93ff-002dd80c017c' ; break }
            'Exchange DL Subscription Email' {
                         $SNid = 'c3fc56aa-4255-e211-811c-00155d2ee30b' ; break }
            'Facebook' { $SNid = 'c5fc56aa-4255-e211-811c-00155d2ee30b' ; break }
            'GitHub'   { $SNid = 'ddf7c919-8081-e311-9401-00155da64d68' ; break }
            'Google+'  { $SNid = 'fd2a7ec7-1b60-e611-80ef-fc15b428778c' ; break }
            'Instagram'{ $SNid = '0ba62aea-1b60-e611-80ef-fc15b428778c' ; break }
            'Klout'    { $SNid = 'c9fc56aa-4255-e211-811c-00155d2ee30b' ; break }
            'LinkedIn' { $SNid = 'cbfc56aa-4255-e211-811c-00155d2ee30b' ; break }
            'Meetup'   { $SNid = '2b93c914-089f-e511-8114-c4346bac0abc' ; break }
            'Microsoft ASP.NET Forum' { 
                         $SNid = '614bd123-4278-e311-9401-00155da64d68' ; break }
            'Microsoft IIS Forum' {
                         $SNid = 'ac372b19-4278-e311-9401-00155da64d68' ; break }
            'MS Community (MS Answers)' {
                         $SNid = 'cdfc56aa-4255-e211-811c-00155d2ee30b' ; break }
            'MSDN/Technet' {
                         $SNid = 'cffc56aa-4255-e211-811c-00155d2ee30b' ; break }
            'Naver ID' { $SNid = 'd1fc56aa-4255-e211-811c-00155d2ee30b' ; break }
            'Other'    { $SNid = 'ddfc56aa-4255-e211-811c-00155d2ee30b' ; break }
            'StackOverflow'  {
                         $SNid = '9aeda924-8081-e311-9401-00155da64d68' ; break }
            'Twitter'  { $SNid = 'd5fc56aa-4255-e211-811c-00155d2ee30b' ; break }
            'Website'  { $SNid = '222a47c1-33ca-e211-9b1f-00155da65f6a' ; break }
            'Windows/Windows Phone Dev Center ID' { 
                         $SNid = 'e673a268-8081-e311-9401-00155da64d68' ; break }
            'Xbox Live gamertag' { 
                         $SNid = 'c7fc56aa-4255-e211-811c-00155d2ee30b' ; break }
            'Xing'     { $SNid = 'd7fc56aa-4255-e211-811c-00155d2ee30b' ; break }
            'Yammer'   { $SNid = 'e473a268-8081-e311-9401-00155da64d68' ; break }
            'YouTube'  { $SNid = 'd9fc56aa-4255-e211-811c-00155d2ee30b' ; break }
            default    {}
        }

        $Body = @"
{
  "PrivateSiteId": 0,
  "SocialNetwork": {
    "Id": "$($SNid)",
    "Name": "$($SocialNetwork)",
    "IconUrl": "",
    "SystemCollectionEnabled": false
  },
 
  "Url": "$($URL)",
  "OnlineIdentityVisibility": {
    "Id": $($VisibilityObject.id),
    "Description": "$($VisibilityObject.Description)",
    "LocalizeKey": "$($VisibilityObject.LocalizeKey)"
  },
  "ContributionCollected": true,
  "DisplayName": "",
  "UserId": "",
  "MicrosoftAccount": "",
  "PrivacyConsentStatus": $($PrivacyConsentStatus),
  "PrivacyConsentCheckStatus": true,
  "PrivacyConsentCheckDate": "",
  "PrivacyConsentUnCheckDate": "",
  "Submitted": true
}
"@

        try {
            Write-Verbose "About to create a new indentity with Body $($Body)"
            Invoke-RestMethod @Splat -Body $Body
        } catch {
            Write-Warning -Message "Failed to invoke the PostOnlineIdentity API because $($_.Exception.Message)"
        }
    }     
}
End {}
}
Function Remove-MVPConfiguration {
<#
.SYNOPSIS
    Remove the current MVPConfiguration
.DESCRIPTION
    Remove the current MVPConfiguration
.PARAMETER ClientID
    Specify your ClientID
.EXAMPLE
    Remove-MVPConfiguration
#>

[CmdletBinding()]
Param(
    [Parameter()]
    [string]$ClientID='0000000048193351'
)
Begin {
    $RedirectUri  = 'https://login.live.com/oauth20_desktop.srf'
}
Process {
    If ($MVPOauth2) {
        # GET https://login.live.com/oauth20_logout.srf?client_id={client_id}&redirect_uri={redirect_uri}
        Write-Verbose -Message 'Attempt to gracefully sign out'
        $HashTable = @{
            Uri = 'https://login.live.com/oauth20_logout.srf?client_id={0}&redirect_uri={1}' -f $ClientID,$RedirectUri
            ErrorAction = 'Stop'
        }
        try {
            $r = Invoke-WebRequest @HashTable
            $global:MVPOauth2 = $null
            Write-Verbose -Message 'Successfully signed out'
        } catch {
            Throw $_
        }
    }
    If ($MVPPrimaryKey) {
        $global:MVPPrimaryKey = $null
    }
    If ($MVPAuthorizationCode) {
        $global:MVPAuthorizationCode = $null
    }
}
End {}
}
Function Remove-MVPContribution {
    <#
    .SYNOPSIS
        Invoke the DeleteContribution REST API
 
    .DESCRIPTION
        Deletes a Contribution item
 
    .PARAMETER ID
        It's the id of a contribution
     
    .EXAMPLE
        Remove-MVPContribution -ID 123456
 
    .NOTES
        https://github.com/lazywinadmin/MVP
#>

    [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
    Param(
        [Parameter(Mandatory)]
        [String]$ID
    )
    Begin {}
    Process {

        if (-not ($global:MVPPrimaryKey -and $global:MVPAuthorizationCode)) {
            Write-Warning -Message 'You need to use Set-MVPConfiguration first to set the Primary Key'
        }
        else {

            Set-MVPConfiguration -SubscriptionKey $MVPPrimaryKey

            $Splat = @{
                Uri         = "https://mvpapi.azure-api.net/mvp/api/contributions?id=$($ID)"
                Headers     = @{
                    'Ocp-Apim-Subscription-Key' = $global:MVPPrimaryKey
                    Authorization               = $Global:MVPAuthorizationCode
                }
                Method      = 'DELETE'
                ErrorAction = 'Stop'
            }

            if ($pscmdlet.ShouldProcess($ID, 'Remove item')) {

                try {
                    Invoke-RestMethod @Splat
                    Write-Verbose -Message "Contribution $($ID) deleted"
                }
                catch {
                    Write-Warning -Message "Failed to invoke the DeleteContribution API because $($_.Exception.Message)"
                }
            }
        }
    }
    End {}
}
Function Remove-MVPOnlineIdentity {
<#
    .SYNOPSIS
        Invoke the DeleteOnlineIdentity REST API
 
    .DESCRIPTION
        Deletes an online identity
 
    .PARAMETER ID
        It's the id of an online identity
 
    .EXAMPLE
#>

[CmdletBinding(SupportsShouldProcess,ConfirmImpact='High')]
Param(
    [Parameter(Mandatory)]
    [Alias('PrivateSiteId')]
    [int32]$ID
)
Begin {}
Process {

    if (-not ($global:MVPPrimaryKey -and $global:MVPAuthorizationCode)) {
        Write-Warning -Message 'You need to use Set-MVPConfiguration first to set the Primary Key'
    } else {

        Set-MVPConfiguration -SubscriptionKey $MVPPrimaryKey

        $Splat = @{
            Uri = "https://mvpapi.azure-api.net/mvp/api/onlineidentities?id=$($ID)"
            Headers = @{
                'Ocp-Apim-Subscription-Key' = $global:MVPPrimaryKey
                Authorization = $Global:MVPAuthorizationCode
            }
            Method = 'DELETE'
            ErrorAction = 'Stop'
        }

        if ($pscmdlet.ShouldProcess($ID,'Remove item')) {

            try {
                Invoke-RestMethod @Splat
                Write-Verbose -Message "Online Identity $($ID) deleted"
            } catch {
                Write-Warning -Message "Failed to invoke the DeleteOnlineIdentity API because $($_.Exception.Message)"
            }
        }
    }
}
End {}
}
Function Set-MVPConfiguration {
<#
.SYNOPSIS
    Get an Oauth Autorization code
 
.DESCRIPTION
    Call the private Get-MVPOAuthAutorizationCode function and define both an MVPPrimaryKey and MVPAuthorizationCode global variable
 
.PARAMETER SubscriptionKey
    It's the primary key or secondary key you get in your profile on this page https://mvpapi.portal.azure-api.net/developer
 
.PARAMETER ClientID
    It's the clientID you see in the url of the MVPAuth application on your https://account.live.com/consent/Manage page
 
.EXAMPLE
 
Set-MVPConfiguration -SubscriptionKey $myKey
 
.NOTES
    https://github.com/lazywinadmin/MVP
#>

[CmdletBinding()]
PARAM (
    [Parameter()]
    [System.String]$ClientID='0000000048193351',

    [Parameter(Mandatory)]
    [System.String]$SubscriptionKey
)
Process {
    Try{
        $Scriptname = (Get-Variable -name MyInvocation -Scope 0 -ValueOnly).MyCommand

        Write-Verbose -Message "[$Scriptname] Get OAuth Autorization code"
        Get-MVPOAuthAutorizationCode -ClientID $ClientID -SubscriptionKey $SubscriptionKey -ErrorAction Stop
        Write-Verbose -Message "[$Scriptname] Successfully call the Get-MVPOAuthAutorizationCode function"

        if ($MVPOauth2) {
            Write-Verbose -Message "[$Scriptname] OAuth Autorization code retrieved"
            Write-Verbose -Message "[$Scriptname] Set Variables 'MVPPrimaryKey' and 'MVPAuthorizationCode'"
            $global:MVPPrimaryKey = $SubscriptionKey
            $global:MVPAuthorizationCode = ('{0} {1}' -f $MVPOauth2.token_type,$MVPOauth2.access_token)
            Write-Verbose -Message "[$Scriptname] Successfully set the global variables MVPPrimaryKey and MVPAuthorizationCode"
        } else {
            Write-Error -Message "[$Scriptname] Failed to define an MVPAuthorizationCode variable"
        }

    }
    catch
    {
        # Return the last error
        $PSCmdlet.ThrowTerminatingError($_)
    }
}
}
Function Set-MVPContribution {
<#
    .SYNOPSIS
        Invoke the PutContribution REST API
 
    .DESCRIPTION
        Updates a Contribution item
 
    .PARAMETER ContributionID
        Specify the Contribution ID to modify
 
    .PARAMETER ContributionTechnology
        Specify the ContributionTechnology (see Get-MVPContributionArea)
 
    .PARAMETER ContributionType
        Specify the ContributionType (see Get-MVPContributionType)
 
    .PARAMETER StartDate
        Specify the StartDate of the contribution
 
        Example '2018/10/10'
    .PARAMETER Title
        Specify the Title of your contribution
 
    .PARAMETER Description
        Specify the Description of your contribution
 
    .PARAMETER ReferenceUrl
        Specifies the Url of the activity
 
    .PARAMETER AnnualQuantity
        Specifies the Annual quantity.
        Default is 1
 
    .PARAMETER SecondAnnualQuantity
        Specifies the Second Annual quantity.
        Default is 0
 
    .PARAMETER AnnualReach
        Specifies the Annual Reach
        Default is 0
 
    .PARAMETER Visibility
        Specifies the audience that will be able to see your activity
        Values: 'EveryOne','Microsoft','MVP Community','Microsoft Only'
        Default = 'Microsoft'
 
    .EXAMPLE
        Set-MVPContribution -ContributionID 691729 -Description 'wowwwwwww!!!'
 
    .EXAMPLE
        Get-MVPContribution -ContributionId 700210 | Set-MVPContribution -Description "wwooowww!!" -Verbose
#>

[CmdletBinding()]
Param(
    [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
    [int32]$ContributionID,

    [Parameter()]
    [string]$ContributionType='video',

    [Parameter()]
    [string]$ContributionTechnology='PowerShell',

    [Parameter()]
    [String]$StartDate = '2017/02/01',
    
    [Parameter()]
    [String]$Title='Test from mvpapi.azure-api.net',

    [Parameter()]
    [String]$Description='Description sample',
    
    [Parameter()]
    [String]$ReferenceUrl='https://github.com/lazywinadmin/MVP',
    
    [Parameter()]
    [String]$AnnualQuantity='0',
    
    [Parameter()]
    [String]$SecondAnnualQuantity='0',

    [Parameter()]    
    [String]$AnnualReach = '0',
    
    [Parameter()]
    [ValidateSet('EveryOne','Microsoft','MVP Community','Microsoft Only')]
    [String]$Visibility = 'Microsoft'
    )
Begin {}
Process {

    if (-not ($global:MVPPrimaryKey -and $global:MVPAuthorizationCode)) {

        Write-Warning -Message 'You need to use Set-MVPConfiguration first to set the Primary Key'
    
    } else {

        Set-MVPConfiguration -SubscriptionKey $MVPPrimaryKey

        $Splat = @{
            Uri = 'https://mvpapi.azure-api.net/mvp/api/contributions'
            Headers = @{
                'Ocp-Apim-Subscription-Key' = $global:MVPPrimaryKey
                Authorization = $Global:MVPAuthorizationCode
                ContentType = 'application/json'
            }
            Method = 'PUT'
            ContentType = 'application/json'
            ErrorAction = 'Stop'
        }

        # Retrieve contribution
        $CurrentContributionObject = Get-MVPContribution -ID $ContributionID

        if ($CurrentContributionObject) {

            if ($PSBoundParameters['ContributionType']) {
                # Verify the Contribution Type
                $type = Get-MVPContributionType |where {$_.name -eq $ContributionType}
            } else {
                $type = $CurrentContributionObject.ContributionType
            }

            if ($PSBoundParameters['ContributionTechnology']) {
                # Verify the Contribution Technology
                $Technology = Get-MVPContributionArea -All | where {$_.name -eq $ContributionTechnology}
            } else {
                $Technology = $CurrentContributionObject.ContributionTechnology
            }

            # Get the Visibility
            if ($PSBoundParameters['Visibility']) {
                $VisibilityObject =  Get-MVPContributionVisibility | Where {$_.Description -eq $Visibility }
            } else {
                $VisibilityObject=$CurrentContributionObject.Visibility
            }

            if (-not$PSBoundParameters['StartDate'])            { $StartDate=$CurrentContributionObject.StartDate }
            if (-not$PSBoundParameters['Title'])                { $Title=$CurrentContributionObject.Title }
            if (-not$PSBoundParameters['Description'])          { $Description=$CurrentContributionObject.Description }
            if (-not$PSBoundParameters['ReferenceUrl'])         { $ReferenceUrl=$CurrentContributionObject.ReferenceUrl }
            if (-not$PSBoundParameters['AnnualQuantity'])       { $AnnualQuantity=$CurrentContributionObject.AnnualQuantity }
            if (-not$PSBoundParameters['SecondAnnualQuantity']) { $SecondAnnualQuantity=$CurrentContributionObject.SecondAnnualQuantity }
            if (-not$PSBoundParameters['AnnualReach'])          { $AnnualReach=$CurrentContributionObject.AnnualReach }

            $Body = @"
{
  "ContributionId": $ContributionID,
  "ContributionTypeName": "$($type.name)",
  "ContributionType": {
    "Id": "$($type.id)",
    "Name": "$($type.name)",
    "EnglishName": "$($type.englishname)"
  },
  "ContributionTechnology": {
    "Id": "$($Technology.id)",
    "Name": "$($Technology.name)",
    "AwardName": "$($Technology.awardname)",
    "AwardCategory": "$($Technology.awardcategory)"
  },
  "StartDate": "$StartDate",
  "Title": "$Title",
  "ReferenceUrl": "$ReferenceUrl",
  "Visibility": {
    "Id": $($VisibilityObject.id),
    "Description": "$($VisibilityObject.Description)",
    "LocalizeKey": "$($VisibilityObject.LocalizeKey)"
  },
  "AnnualQuantity": $AnnualQuantity,
  "SecondAnnualQuantity": $SecondAnnualQuantity,
  "AnnualReach": $AnnualReach,
  "Description": "$Description"
}
"@

            if ($type -and $Technology) {
                try {
                    Write-Verbose "About to update contribution $($ContributionID) with Body $($Body)"
                    Invoke-RestMethod @Splat -Body $Body
                } catch {
                    Write-Warning -Message "Failed to invoke the PutContribution API because $($_.Exception.Message)"
                }
            } else {
                Write-Warning -Message "Either contributiontype or contributionarea isn't recognized"
            }
        } else {
            Write-Warning -Message "ContributionId $($ContributionID) probably not found"
        }
    }
}
End {}
}
Function Set-MVPOnlineIdentity {
<#
    .SYNOPSIS
        Invoke the PutOnlineIdentity REST API
 
    .DESCRIPTION
        Updates an Online Identity
 
    .PARAMETER ID
        Specify the Id of the online identity in a int32 format
 
    .PARAMETER SocialNetwork
        Specify the Social Network
 
    .PARAMETER URL
        Specify the URL
 
    .PARAMETER AllowMicrosoftToQueryMyId
        Specify if you want to allo Microsoft to query the ID
 
    .PARAMETER Visibility
        Specify the Visbility (see Get-MVPContributionVisibility)
 
    .EXAMPLE
        Get-MVPOnlineIdentity -ID 123872 |
            Set-MVPOnlineIdentity -Verbose -SocialNetwork Code
 
    .EXAMPLE
        Get-MVPOnlineIdentity -ID 123872 |
        Set-MVPOnlineIdentity -Verbose -URL 'https://facebook.com/myprofile'
 
#>

[CmdletBinding()]
Param(
    [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
    [Alias('PrivateSiteId')]
    [int32]$ID,

    [Parameter()]
    [ValidateSet('Blog','Code','Codeplex','Exchange DL Subscription Email','Facebook','GitHub','Google+','Instagram',
                 'Klout','LinkedIn','Meetup','Microsoft ASP.NET Forum','Microsoft IIS Forum','MS Community (MS Answers)',
                 'MSDN/Technet','Naver ID','Other','StackOverflow','Twitter','Website','Windows/Windows Phone Dev Center ID',
                 'Xbox Live gamertag','Xing','Yammer','YouTube')]
    [String]$SocialNetwork = 'Twitter',

    [Parameter()]    
    [String]$URL = 'https://mvpapi.azure-api.net',

    [Switch]$AllowMicrosoftToQueryMyId,
    
    [Parameter()]
    [ValidateSet('EveryOne','Microsoft','MVP Community','Microsoft Only')]
    [String]$Visibility = 'Microsoft'
    )
Begin {}
Process {

    if (-not ($global:MVPPrimaryKey -and $global:MVPAuthorizationCode)) {

        Write-Warning -Message 'You need to use Set-MVPConfiguration first to set the Primary Key'
    
    } else {

        Set-MVPConfiguration -SubscriptionKey $MVPPrimaryKey

        $Splat = @{
            Uri = 'https://mvpapi.azure-api.net/mvp/api/onlineidentities'
            Headers = @{
                'Ocp-Apim-Subscription-Key' = $global:MVPPrimaryKey
                Authorization = $Global:MVPAuthorizationCode
                ContentType = 'application/json'
            }
            Method = 'PUT'
            ContentType = 'application/json'
            ErrorAction = 'Stop'
        }

        # Retrieve online identity
        $CurrentIdentityObject = Get-MVPOnlineIdentity -ID $ID

        if ($CurrentIdentityObject) {

            # Get the Visibility
            if ($PSBoundParameters['Visibility']) {
                $VisibilityObject =  Get-MVPContributionVisibility | Where {$_.Description -eq $Visibility }
            } else {
                $VisibilityObject=$CurrentIdentityObject.OnlineIdentityVisibility
            }
            if (-not$PSBoundParameters['SocialNetwork'])  { $SocialNetwork=$CurrentIdentityObject.SocialNetwork.Name }
            if (-not$PSBoundParameters['URL'])            { $URL=$CurrentIdentityObject.URL }
            if ($AllowMicrosoftToQueryMyId) { 
                $PrivacyConsentStatus  = 'true'
            } else {
                $PrivacyConsentStatus = 'false'
            }
            
            switch ($SocialNetwork) {
                # missing 'Microsoft Connect' requires an MS account
                # missing 'Microsoft Office 365 forum' requires a displayname

                'Blog'     { $SNid = '202a47c1-33ca-e211-9b1f-00155da65f6a' ; break }
                'Code'     { $SNid = 'a57a64ac-33ca-e211-9b1f-00155da65f6a' ; break }
                'Codeplex' { $SNid = '334c64f8-417f-e311-93ff-002dd80c017c' ; break }
                'Exchange DL Subscription Email' {
                             $SNid = 'c3fc56aa-4255-e211-811c-00155d2ee30b' ; break }
                'Facebook' { $SNid = 'c5fc56aa-4255-e211-811c-00155d2ee30b' ; break }
                'GitHub'   { $SNid = 'ddf7c919-8081-e311-9401-00155da64d68' ; break }
                'Google+'  { $SNid = 'fd2a7ec7-1b60-e611-80ef-fc15b428778c' ; break }
                'Instagram'{ $SNid = '0ba62aea-1b60-e611-80ef-fc15b428778c' ; break }
                'Klout'    { $SNid = 'c9fc56aa-4255-e211-811c-00155d2ee30b' ; break }
                'LinkedIn' { $SNid = 'cbfc56aa-4255-e211-811c-00155d2ee30b' ; break }
                'Meetup'   { $SNid = '2b93c914-089f-e511-8114-c4346bac0abc' ; break }
                'Microsoft ASP.NET Forum' { 
                             $SNid = '614bd123-4278-e311-9401-00155da64d68' ; break }
                'Microsoft IIS Forum' {
                             $SNid = 'ac372b19-4278-e311-9401-00155da64d68' ; break }
                'MS Community (MS Answers)' {
                             $SNid = 'cdfc56aa-4255-e211-811c-00155d2ee30b' ; break }
                'MSDN/Technet' {
                             $SNid = 'cffc56aa-4255-e211-811c-00155d2ee30b' ; break }
                'Naver ID' { $SNid = 'd1fc56aa-4255-e211-811c-00155d2ee30b' ; break }
                'Other'    { $SNid = 'ddfc56aa-4255-e211-811c-00155d2ee30b' ; break }
                'StackOverflow'  {
                             $SNid = '9aeda924-8081-e311-9401-00155da64d68' ; break }
                'Twitter'  { $SNid = 'd5fc56aa-4255-e211-811c-00155d2ee30b' ; break }
                'Website'  { $SNid = '222a47c1-33ca-e211-9b1f-00155da65f6a' ; break }
                'Windows/Windows Phone Dev Center ID' { 
                             $SNid = 'e673a268-8081-e311-9401-00155da64d68' ; break }
                'Xbox Live gamertag' { 
                             $SNid = 'c7fc56aa-4255-e211-811c-00155d2ee30b' ; break }
                'Xing'     { $SNid = 'd7fc56aa-4255-e211-811c-00155d2ee30b' ; break }
                'Yammer'   { $SNid = 'e473a268-8081-e311-9401-00155da64d68' ; break }
                'YouTube'  { $SNid = 'd9fc56aa-4255-e211-811c-00155d2ee30b' ; break }
                default    {}
            }

            $Body = @"
{
  "PrivateSiteId": "$($ID)",
  "SocialNetwork": {
    "Id": "$($SNid)",
    "Name": "$($SocialNetwork)",
    "IconUrl": "",
    "SystemCollectionEnabled": false
  },
 
  "Url": "$($URL)",
  "OnlineIdentityVisibility": {
    "Id": $($VisibilityObject.id),
    "Description": "$($VisibilityObject.Description)",
    "LocalizeKey": "$($VisibilityObject.LocalizeKey)"
  },
  "ContributionCollected": true,
  "DisplayName": "",
  "UserId": "",
  "MicrosoftAccount": "",
  "PrivacyConsentStatus": $($PrivacyConsentStatus),
  "PrivacyConsentCheckStatus": true,
  "PrivacyConsentCheckDate": "",
  "PrivacyConsentUnCheckDate": "",
  "Submitted": true
}
"@


            try {
                Write-Verbose "About to update online identity $($ID) with Body $($Body)"
                Invoke-RestMethod @Splat -Body $Body
            } catch {
                Write-Warning -Message "Failed to invoke the PutOnlineIdentity API because $($_.Exception.Message)"
            }

        } else {
            Write-Warning -Message "Online Id $($ID) probably not found"
        }
    }
}
End {}
}
function Show-MVPProfile {
    <#
        .SYNOPSIS
            Displays the MVP Profile for $ID
 
        .DESCRIPTION
            Opens the profile of the ID(s) provided, or your profile if no ID is specified, in the default browser.
 
        .PARAMETER ID
            It's an MVP ID
 
        .EXAMPLE
            Show-MVPProfile
 
            It shows your MVP Profile
 
        .EXAMPLE
            Show-MVPProfile -ID 5000475, 5000890
 
            It shows the profiles for Francois-Xavier Cat and Emin Atac
 
        .EXAMPLE
            Get-MVPProfile -ID 4025267 | Show-MVPProfile
 
            It shows the profile for Joel Bennett
    #>

    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [Alias('MvpId')]
        [ValidateNotNullOrEmpty()]
        [string[]]$ID = (Get-MVPProfile).MvpId
    )
    process {
        foreach ($MVP in $ID.Where{$_}) {
            Start-Process "https://mvp.microsoft.com/en-us/PublicProfile/$MVP"
        }
    }
}
Function Test-MVPContribution {
<#
.SYNOPSIS
    Tests for matching MVP Contributions on your MVP profile
 
.DESCRIPTION
    The Test-MVPContribution function looks for contributions that match supplied criteria.
 
    It can either return a boolean value, or the matching object.
 
.PARAMETER ContributionTechnology
    Specifies the Contribution technology
    This parameter is dynamic and is retrieving the information from Get-MVPContributionArea
 
.PARAMETER AdditionalTechnologies
    Specifies an additional Contribution
    This parameter is dynamic and is retrieving the information from Get-MVPContributionArea
 
.PARAMETER ContributionType
    Specifies the Contribution Type
    This parameter is dynamic and is retrieving the information from Get-MVPContributionType
 
.PARAMETER StartDate
    Specifies the Date of the activity
 
.PARAMETER Title
    Specifies the Title of the activity
 
.PARAMETER ReferenceUrl
    Specifies the Url of the activity
 
.PARAMETER ReturnMatch
    Returns the matching contribution, rather than a boolean value
 
.EXAMPLE
    Test-MVPContribution -Title 'PowerShell Command Precedence' -ReferenceUrl 'https://lazywinadmin.com/2017/06/CommandPrecedence.html'
 
    This command returns $true if a contribution is found with both a matching title and url
 
.EXAMPLE
    Test-MVPContribution -Title 'User Group Presentation - FRPSUG' -ReturnMatch
 
    This command returns the matching contribution object if it is found
 
.NOTES
    https://github.com/lazywinadmin/MVP
#>

    [CmdletBinding()]
    Param(
        [Parameter(ValueFromPipelineByPropertyName=$true)]
        [String]$StartDate,

        [Parameter(ValueFromPipelineByPropertyName=$true)]
        [String]$Title,

        [Parameter(ValueFromPipelineByPropertyName=$true)]
        [String]$ReferenceUrl,

        [Switch]$ReturnMatch
    )
    DynamicParam {
        # Borrowing dynamic parameters from New-MVPContribution
        # Using this should mean that supplied values are valid and correct

        # Create dictionary
        $Dictionary = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameterDictionary

        # ContributionTechnology
        $ParameterName = 'ContributionTechnology'
        $AttribColl1 = New-Object -TypeName System.Collections.ObjectModel.Collection[System.Attribute]
        $Param1Att = New-Object -TypeName System.Management.Automation.ParameterAttribute
        $Param1Att.Mandatory = $false
        $Param1Att.ValueFromPipelineByPropertyName = $true
        $Param1Att.ParameterSetName = '__AllParameterSets'
        $AttribColl1.Add($Param1Att)
        $AttribColl1.Add((New-Object -TypeName System.Management.Automation.ValidateSetAttribute(Get-MVPContributionArea -All | Select-Object -ExpandProperty Name)))
        $Dictionary.Add($ParameterName,(New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttribColl1)))

        # ContributionType
        $ParameterID = 'ContributionType'
        $AttribColl2 = New-Object -TypeName System.Collections.ObjectModel.Collection[System.Attribute]
        $Param2Att = New-Object -TypeName System.Management.Automation.ParameterAttribute
        $Param2Att.Mandatory = $false
        $Param2Att.ValueFromPipelineByPropertyName=$true
        $Param2Att.ParameterSetName = '__AllParameterSets'
        $AttribColl2.Add($Param2Att)
        $AttribColl2.Add((New-Object -TypeName System.Management.Automation.ValidateSetAttribute(Get-MVPContributionType | Select-Object -ExpandProperty Name)))
        $Dictionary.Add($ParameterID,(New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter($ParameterID, [string], $AttribColl2)))

        # AdditionalTechnologies
        $ParameterName3 = 'AdditionalTechnologies'
        $AttribColl3 = New-Object -TypeName System.Collections.ObjectModel.Collection[System.Attribute]
        $Param3Att = New-Object -TypeName System.Management.Automation.ParameterAttribute
        $Param3Att.Mandatory = $false
        $Param3Att.ValueFromPipelineByPropertyName = $true
        $Param3Att.ParameterSetName = '__AllParameterSets'
        $AttribColl3.Add($Param3Att)
        $AttribColl3.Add((New-Object -TypeName System.Management.Automation.ValidateSetAttribute(Get-MVPContributionArea -All | Select-Object -ExpandProperty Name)))
        $Dictionary.Add($ParameterName3,(New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter($ParameterName3, [string], $AttribColl3)))

        #Return dictionary
        $Dictionary
    }
    Process {
        $Scriptname = (Get-Variable -name MyInvocation -Scope 0 -ValueOnly).MyCommand
        if (-not ($global:MVPPrimaryKey -and $global:MVPAuthorizationCode)) {
            Write-Warning -Message "[$Scriptname] You need to use Set-MVPConfiguration first to set the Primary Key"
            break
        }
        Try {
            Write-Verbose -message "[$Scriptname] Set Configuration"
            Set-MVPConfiguration -SubscriptionKey $MVPPrimaryKey

            Write-Verbose -message "[$Scriptname] Getting all contributions, using New-MVPContribution"
            $Contributions = [System.Collections.ArrayList]::new()
            $ContribLimit = 100
            $More = $true

            while ($More) {
                $Offset = $ContribLimit - 100
                Write-Verbose -message "[$Scriptname] Getting $ContribLimit contributions with an offset of $Offset"
                $ContribGroup = Get-MVPContribution -Limit $ContribLimit -Offset $Offset

                if (($ContribGroup | Measure-Object).Count -lt 100) {
                    Write-Verbose -message "[$Scriptname] Last set of contributions received"
                    $More = $false
                } else {
                    Write-Verbose -message "[$Scriptname] 100 contributions received, there may be more..."
                    $ContribLimit += 100
                }

                Write-Verbose -message "[$Scriptname] Adding contributions to collection"
                foreach ($Contrib in $ContribGroup) {
                    $null = $Contributions.Add($Contrib)
                }
            }

            Write-Verbose -message "[$Scriptname] Testing collection against supplied criteria"
            $MacthFound = $false
            foreach ($Contribution in $Contributions) {
                $PossibleMatch = $true
                foreach ($BoundParam in $PSBoundParameters.GetEnumerator()) {
                    $Key = $BoundParam.Key
                    if ($Contribution.$Key -notlike "$($BoundParam.Value)*") {
                        $PossibleMatch = $false
                        break
                    }
                }

                if ($PossibleMatch) {
                    $MacthFound = $true

                    if ($ReturnMatch) {
                        $Contribution
                    }

                    break
                }
            }

            if (!$ReturnMatch) {
                $MacthFound
            }
        }
        catch {
            $PSCmdlet.ThrowTerminatingError($_)
        }
    }
}
Function Get-MVPOAuthAutorizationCode {
<#
.SYNOPSIS
    Get an Oauth 2.0 autorization code
 
.DESCRIPTION
    Use the authorization code grant flow described on https://msdn.microsoft.com/en-us/library/hh243647.aspx
    Pop-up a window that asks you to grant permissions to the mvpapi.portal.azure-api.net application and
    parse the returned url to catch the authorization code
 
.PARAMETER SubscriptionKey
    It's the primary key or secondary key you get in your profile on this page https://mvpapi.portal.azure-api.net/developer
 
.PARAMETER ClientID
    It's the clientID you see in the url of the MVPAuth application on your https://account.live.com/consent/Manage page
 
.EXAMPLE
    Set-MVPConfiguration -CliendID '0000000048193351' -SubscriptionKey $myKey
#>

[CmdletBinding()]
Param(
    [Parameter(Mandatory)]
    [String]$ClientID,

    [Parameter(Mandatory)]
    [string]$SubscriptionKey
)
Begin {
    $Scriptname = (Get-Variable -name MyInvocation -Scope 0 -ValueOnly).MyCommand

    Write-Verbose -Message "[$ScriptName] Set Variables"
    $scope = 'wl.emails%20wl.basic%20wl.offline_access%20wl.signin'
    $RedirectUri  = 'https://login.live.com/oauth20_desktop.srf'
    $AuthorizeUri = 'https://login.live.com/oauth20_authorize.srf'
    $u1 = '{0}?client_id={1}&redirect_uri={2}&response_type=code&scope={3}' -f $AuthorizeUri,$ClientID,$RedirectUri,$scope

    Write-Verbose -Message "[$ScriptName] Scope = '$scope'"
    Write-Verbose -Message "[$ScriptName] RedirectUri = '$RedirectUri'"
    Write-Verbose -Message "[$ScriptName] AuthorizeUri = '$AuthorizeUri'"
    Write-Verbose -Message "[$ScriptName] u1 = '$u1'"
}
Process {
    if (-not($MVPOauth2)) {
        Write-Verbose -Message "[$Scriptname] No Ouath2 object detected, asking for permission"
        Show-MVPOAuthWindow -url $u1
        if ($AutorizationCode) {
            $HashTable = @{
                Uri = 'https://login.live.com/oauth20_token.srf'
                Method = 'Post'
                ContentType = 'application/x-www-form-urlencoded'
                Body = 'client_id={0}&redirect_uri={1}&client_secret={2}&code={3}&grant_type=authorization_code' -f  $ClientID,$RedirectUri,$SubscriptionKey,$AutorizationCode
            }
            try {
                $r = Invoke-RestMethod @HashTable -ErrorAction Stop
                Write-Verbose -Message "[$Scriptname] Successfully got oauth 2.0 access token"
            } catch {
                Throw $_
            }
            if ($r) {
                $global:MVPOauth2 = $r | 
                Add-Member -MemberType NoteProperty -Name ValidUntil -Value ((Get-Date).AddSeconds($r.expires_in-1)) -Force -PassThru
            }
        } else {
            Write-Warning -Message "[$Scriptname] No authorization code set"
        }        
    } elseif ((Get-Date) -ge ($MVPOauth2.ValidUntil)) {

        Write-Verbose -Message "[$Scriptname] Expired Ouath2 access token detected, refreshing it"
        $HashTable = @{
            Uri = 'https://login.live.com/oauth20_token.srf'
            Method = 'Post'
            ContentType = 'application/x-www-form-urlencoded'
            Body = 'client_id={0}&grant_type=refresh_token&redirect_uri={1}&refresh_token={2}' -f $ClientID,$RedirectUri,$MVPOauth2.refresh_token
        }

        try {
            $r = Invoke-RestMethod @HashTable -ErrorAction Stop
            Write-Verbose -Message "[$Scriptname] Successfully got oauth 2.0 refresh token"
        } catch {
            Throw $_
        }
        if ($r) {
            $global:MVPOauth2 = $r | 
            Add-Member -MemberType NoteProperty -Name ValidUntil -Value ((Get-Date).AddSeconds($r.expires_in-1)) -Force -PassThru
        }        
    } else {
        Write-Verbose -Message "[$Scriptname] The current Oauth2 access token is still valid"
    }
}
}
Function Show-MVPOAuthWindow {
<#
.SYNOPSIS
    Function to show the Microsoft Authentication window
.NOTES
    https://github.com/lazywinadmin/MVP
     
    #Credit to https://raw.githubusercontent.com/1RedOne/PSWordPress/master/Private/Show-oAuthWindow.ps1
#>

    [CmdletBinding()]
    Param(
        [Uri]$url
    )
    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"
            $form = New-Object -TypeName System.Windows.Forms.Form -Property @{Width=440;Height=640}

            Write-Verbose -Message "[$ScriptName] Create Web browser"
            $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"
            $DocComp  = {
                $global:uri = $web.Url.AbsoluteUri
                if ($global:uri -match 'error=[^&]*|code=[^&]*') {
                    $form.Close()
                }
            }
            $web.ScriptErrorsSuppressed = $true
            $web.Add_DocumentCompleted($DocComp)
            $form.Controls.Add($web)
            $form.Add_Shown({$form.Activate()})

            Write-Verbose -Message "[$ScriptName] Show Dialog"
            $null = $form.ShowDialog()
            # set a the autorization code globally
            $global:AutorizationCode = ([regex]'^\?code=(?<code>.+)&lc=\d{1,10}$').Matches(([uri]$uri).query).Groups |
                Select-Object -Last 1 -Expand value
            if ($global:AutorizationCode) {
                Write-Verbose -Message "[$ScriptName] Successfully got authorization code $($AutorizationCode)"
            } else {
                Write-Error "[$ScriptName] Authorization code not catched"
            }
        } catch {
            $PSCmdlet.ThrowTerminatingError($_)
        }
    }
}
# things to append at the end of the Psm1