diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 0000000..7c74cb2 --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "nbgv": { + "version": "3.6.133", + "commands": [ + "nbgv" + ] + } + } +} \ No newline at end of file diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..9e7531d --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,60 @@ +#------------------------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. +#------------------------------------------------------------------------------------------------------------- + +FROM squidfunk/mkdocs-material:latest + +# This Dockerfile adds a non-root user with sudo access. Use the "remoteUser" +# property in devcontainer.json to use it. On Linux, the container user's GID/UIDs +# will be updated to match your local UID/GID (when using the dockerFile property). +# See https://aka.ms/vscode-remote/containers/non-root-user for details. +ARG USERNAME=vscode +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +# install git iproute2, process tools +RUN apk add --no-cache \ + ca-certificates \ + less \ + ncurses-terminfo-base \ + krb5-libs \ + libgcc \ + libintl \ + libssl1.1 \ + libstdc++ \ + tzdata \ + userspace-rcu \ + zlib \ + icu-libs \ + curl \ + git \ + openssh-client \ + less \ + procps \ + gpg \ + bash \ + shadow \ + sudo && \ + apk -X https://dl-cdn.alpinelinux.org/alpine/edge/main add --no-cache lttng-ust && \ + # Download the powershell '.tar.gz' archive \ + curl -L https://github.com/PowerShell/PowerShell/releases/download/v7.4.1/powershell-7.4.1-linux-musl-x64.tar.gz -o /tmp/powershell.tar.gz && \ + # Create the target folder where powershell will be placed + mkdir -p /opt/microsoft/powershell/7 && \ + # Expand powershell to the target folder + tar zxf /tmp/powershell.tar.gz -C /opt/microsoft/powershell/7 && \ + # Set execute permissions + chmod +x /opt/microsoft/powershell/7/pwsh && \ + # Create the symbolic link that points to pwsh + ln -s /opt/microsoft/powershell/7/pwsh /usr/bin/pwsh && \ + # Create a non-root user to use if preferred - see https://aka.ms/vscode-remote/containers/non-root-user. + addgroup -g $USER_GID $USERNAME && \ + adduser -s /usr/bin/pwsh -u $USER_UID -G $USERNAME -D $USERNAME && \ + # [Optional] Add sudo support for the non-root user + echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME && \ + chmod 0440 /etc/sudoers.d/$USERNAME && \ + # Clean up + apk cache clean && \ + rm /tmp/powershell.tar.gz +USER $USERNAME +ENTRYPOINT [ "/usr/bin/pwsh" ] diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..e68c33d --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,29 @@ +{ + "name": "PowerShell", + "dockerFile": "Dockerfile", + "customizations": { + "vscode": { + "settings": { + "terminal.integrated.profiles.linux": { + "bash": { + "path": "usr/bin/bash", + "icon": "terminal-bash" + }, + "zsh": { + "path": "usr/bin/zsh" + }, + "pwsh": { + "path": "/usr/bin/pwsh", + "icon": "terminal-powershell" + } + }, + "terminal.integrated.defaultProfile.linux": "pwsh" + }, + "extensions": ["ms-vscode.powershell", "davidanson.vscode-markdownlint", "redhat.vscode-yaml"] + } + }, + "postCreateCommand": "git config --global --add safe.directory ${containerWorkspaceFolder}", + "postStartCommand": "pwsh -c 'sudo chown -R \"$(id -u):$(id -g)\" $PWD; ./build.ps1 -Task Init -Bootstrap'", + "forwardPorts": [8000], + "remoteUser": "vscode" +} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..af67531 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* -crlf diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..68c3864 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,62 @@ +# How to contribute + +Contributions to PSPushover are highly encouraged and desired. +Below are some guidelines that will help make the process as smooth as possible. + +## Getting Started + +- Make sure you have a [GitHub account](https://github.com/signup/free) +- Submit a new issue, assuming one does not already exist. + - Clearly describe the issue including steps to reproduce when it is a bug. + - Make sure you fill in the earliest version that you know has the issue. +- Fork the repository on GitHub + +## Suggesting Enhancements + +I want to know what you think is missing from PSPushover and how it can be made better. + +- When submitting an issue for an enhancement, please be as clear as possible about why you think the enhancement is needed and what the benefit of it would be. + +## Making Changes + +- From your fork of the repository, create a topic branch where work on your change will take place. +- To quickly create a topic branch based on master; `git checkout -b my_contribution master`. + Please avoid working directly on the `master` branch. +- Make commits of logical units. +- Check for unnecessary whitespace with `git diff --check` before committing. +- Please follow the prevailing code conventions in the repository. + Differences in style make the code harder to understand for everyone. +- Make sure your commit messages are in the proper format. + +``` + Add more cowbell to Get-Something.ps1 + + The functionality of Get-Something would be greatly improved if there was a little + more 'pizzazz' added to it. I propose a cowbell. Adding more cowbell has been + shown in studies to both increase one's mojo, and cement one's status + as a rock legend. +``` + +- Make sure you have added all the necessary Pester tests for your changes. +- Run _all_ Pester tests in the module to assure nothing else was accidentally broken. + +## Documentation + +I am infallible and as such my documenation needs no corectoin. +In the highly unlikely event that that is _not_ the case, commits to update or add documentation are highly apprecaited. + +## Submitting Changes + +- Push your changes to a topic branch in your fork of the repository. +- Submit a pull request to the main repository. +- Once the pull request has been reviewed and accepted, it will be merged with the master branch. +- Celebrate + +## Additional Resources + +- [General GitHub documentation](https://help.github.com/) +- [GitHub forking documentation](https://guides.github.com/activities/forking/) +- [GitHub pull request documentation](https://help.github.com/send-pull-requests/) +- [GitHub Flow guide](https://guides.github.com/introduction/flow/) +- [GitHub's guide to contributing to open source projects](https://guides.github.com/activities/contributing-to-open-source/) + diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..6b95148 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,31 @@ + + +## Expected Behavior + + + +## Current Behavior + + + +## Possible Solution + + + +## Steps to Reproduce (for bugs) + + +1. +2. +3. +4. + +## Context + + + +## Your Environment + +* Module version used: +* Operating System and PowerShell version: + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..78d0659 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,37 @@ + + +## Description + + +## Related Issue + + + + + +## Motivation and Context + + +## How Has This Been Tested? + + + + +## Screenshots (if appropriate): + +## Types of changes + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to change) + +## Checklist: + + +- [ ] My code follows the code style of this project. +- [ ] My change requires a change to the documentation. +- [ ] I have updated the documentation accordingly. +- [ ] I have read the **CONTRIBUTING** document. +- [ ] I have added tests to cover my changes. +- [ ] All new and existing tests passed. + diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml new file mode 100644 index 0000000..cf9ffa3 --- /dev/null +++ b/.github/workflows/CI.yml @@ -0,0 +1,28 @@ +name: CI +on: + push: + branches: + - main + paths-ignore: + - .github/workflows/Docs.yml + pull_request: + branches: + - main + paths-ignore: + - .github/workflows/Docs.yml + workflow_dispatch: + +jobs: + test: + name: Run Tests + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macOS-latest] + steps: + - uses: actions/checkout@v1 + - name: Test + shell: pwsh + run: ./build.ps1 -Task Test -Bootstrap + diff --git a/.github/workflows/Docs.yml b/.github/workflows/Docs.yml new file mode 100644 index 0000000..d6634c4 --- /dev/null +++ b/.github/workflows/Docs.yml @@ -0,0 +1,29 @@ +name: Publish Docs + +on: + push: + branches: + - main + paths-ignore: + - .github/workflows/CI.yml + - tests/** + - .vscode/** + +jobs: + DeployDocs: + # Grant the minimum permissions necessary for this job to publish to GitHub Pages + permissions: + contents: write + pages: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + # Setting fetch-depth to 0 forces checkout to pull _all_ commit history which takes longer but can be + # useful when using mkdocs plugins that use git history to apply published/updated timestamps on pages. + fetch-depth: 0 + + - name: MkDocs GH-Deploy + if: github.ref == 'refs/heads/main' + shell: pwsh + run: .\build.ps1 -Bootstrap -Task PublishDocs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4145222 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +# Don't check in the Output dir +Output/ + +scratch/ + +testResults.xml + +.dotnet/ + +.cache/ diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..4bfd516 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,8 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "ms-vscode.PowerShell", + "DavidAnson.vscode-markdownlint" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..17bb580 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "PowerShell: Launch Current File", + "type": "PowerShell", + "request": "launch", + "script": "${file}", + "args": [], + "createTemporaryIntegratedConsole": true + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..f34df78 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,20 @@ +{ + "files.autoSave": "onFocusChange", + "files.autoSaveWorkspaceFilesOnly": true, + "files.insertFinalNewline": true, + "files.trimTrailingWhitespace": true, + "editor.insertSpaces": true, + "editor.tabSize": 4, + "powershell.codeFormatting.preset": "OTBS", + "yaml.schemas": { + "https://squidfunk.github.io/mkdocs-material/schema.json": "mkdocs.yml" + }, + "yaml.customTags": [ + "!ENV scalar", + "!ENV sequence", + "!relative scalar", + "tag:yaml.org,2002:python/name:material.extensions.emoji.to_svg", + "tag:yaml.org,2002:python/name:material.extensions.emoji.twemoji", + "tag:yaml.org,2002:python/name:pymdownx.superfences.fence_code_format" + ] +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..f940e34 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,74 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + + // Start PowerShell (pwsh on *nix) + "windows": { + "options": { + "shell": { + "executable": "powershell.exe", + "args": [ "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command" ] + } + } + }, + "linux": { + "options": { + "shell": { + "executable": "/usr/bin/pwsh", + "args": [ "-NoProfile", "-Command" ] + } + } + }, + "osx": { + "options": { + "shell": { + "executable": "/usr/local/bin/pwsh", + "args": [ "-NoProfile", "-Command" ] + } + } + }, + + "tasks": [ + { + "label": "Clean", + "type": "shell", + "command": "${cwd}/build.ps1 -Task Clean -Verbose" + }, + { + "label": "Test", + "type": "shell", + "command": "${cwd}/build.ps1 -Task Test -Verbose", + "group": { + "kind": "test", + "isDefault": true + }, + "problemMatcher": "$pester" + }, + { + "label": "Analyze", + "type": "shell", + "command": "${cwd}/build.ps1 -Task Analyze -Verbose" + }, + { + "label": "Pester", + "type": "shell", + "command": "${cwd}/build.ps1 -Task Pester -Verbose", + "problemMatcher": "$pester" + }, + { + "label": "Build", + "type": "shell", + "command": "${cwd}/build.ps1 -Task Build -Verbose", + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "Publish", + "type": "shell", + "command": "${cwd}/build.ps1 -Task Publish -Verbose" + } + ] +} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..0c7915b --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, sexual identity and +orientation, or sexual proclivities between consenting adults. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at [joshooaj@gmail.com](mailto:joshooaj@gmail.com). All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4.1, +available at [http://contributor-covenant.org/version/1/4/1][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6c25b05 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2024 Josh Hendricks + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/PSScriptAnalyzerSettings.psd1 b/PSScriptAnalyzerSettings.psd1 new file mode 100644 index 0000000..de888b4 --- /dev/null +++ b/PSScriptAnalyzerSettings.psd1 @@ -0,0 +1,4 @@ +@{ + Severity = @('Error', 'Warning') + ExcludeRules = @('PSReviewUnusedParameter') +} diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..2f30465 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,65 @@ +[cmdletbinding(DefaultParameterSetName = 'Task')] +param( + # Build task(s) to execute + [parameter(ParameterSetName = 'task', position = 0)] + [ArgumentCompleter( { + param($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams) + $psakeFile = './psakeFile.ps1' + switch ($Parameter) { + 'Task' { + if ([string]::IsNullOrEmpty($WordToComplete)) { + Get-PSakeScriptTasks -buildFile $psakeFile | Select-Object -ExpandProperty Name + } + else { + Get-PSakeScriptTasks -buildFile $psakeFile | + Where-Object { $_.Name -match $WordToComplete } | + Select-Object -ExpandProperty Name + } + } + Default { + } + } + })] + [string[]]$Task = 'default', + + # Bootstrap dependencies + [switch]$Bootstrap, + + # List available build tasks + [parameter(ParameterSetName = 'Help')] + [switch]$Help, + + # Optional properties to pass to psake + [hashtable]$Properties, + + # Optional parameters to pass to psake + [hashtable]$Parameters +) + +$ErrorActionPreference = 'Stop' + +# Bootstrap dependencies +if ($Bootstrap.IsPresent) { + Get-PackageProvider -Name Nuget -ForceBootstrap | Out-Null + Set-PSRepository -Name PSGallery -InstallationPolicy Trusted + if ((Test-Path -Path ./requirements.psd1)) { + if (-not (Get-Module -Name PSDepend -ListAvailable)) { + Install-Module -Name PSDepend -Repository PSGallery -Scope CurrentUser -Force + } + Import-Module -Name PSDepend -Verbose:$false + Invoke-PSDepend -Path './requirements.psd1' -Install -Import -Force -WarningAction SilentlyContinue + } else { + Write-Warning 'No [requirements.psd1] found. Skipping build dependency installation.' + } +} + +# Execute psake task(s) +$psakeFile = './psakeFile.ps1' +if ($PSCmdlet.ParameterSetName -eq 'Help') { + Get-PSakeScriptTasks -buildFile $psakeFile | + Format-Table -Property Name, Description, Alias, DependsOn +} else { + Set-BuildEnvironment -Force + Invoke-psake -buildFile $psakeFile -taskList $Task -nologo -properties $Properties -parameters $Parameters + exit ([int](-not $psake.build_success)) +} diff --git a/debug.build.ps1 b/debug.build.ps1 new file mode 100644 index 0000000..da25f2c --- /dev/null +++ b/debug.build.ps1 @@ -0,0 +1 @@ +./build.ps1 -Bootstrap diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..d701d05 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,61 @@ +# PSPushover + +## Overview + +The PSPushover PowerShell module makes it a breeze to send notifications to any device using the +[Pushover](https://pushover.net) service. You can send push notifications to Android, iOS, and +desktop devices. + +Each notification is associated with an "application", and can be sent to an individual user, or +to a group of users. Get notified... + +- when backups fail +- when cron jobs run +- when servers restart +- when your GitHub Actions / Azure DevOps / Jenkins / GitLab pipelines fail +- when your home automation detects a leak +- __whenever and for whatever you want!__ + +## Getting started + +All Pushover notifications are sent from an __application__ to a __user__ or __group__. To send +your first push notification, you need an __application token__ and a __user key__. To receive +notifications, you need the Pushover app installed on a mobile device, or at least have the website +open with notifications enabled in a [compatible browser](https://pushover.net/clients/desktop). + +### Create an application + +Notifications need to come from _something_, and with Pushover, that something is an "application". +The application can be named anything you like. Naming things is hard though, so if you can't +decide on a name, use "PSPushover". + +1. Register and/or login at [pushover.net](https://pushover.net/login). +2. Take note of your __user key__. It looks like `ygzttgcfpab5wyrtstnxlrqllpr0et`. +3. Under __Your Applications__, click __Create an Application/API Token__, fill out the required + fields, and take note of the api key. + +### Install PSPushover + +```powershell +Install-Module joshooaj.PSPushover -Scope CurrentUser -Repository PSGallery +``` + +### Set default tokens + +You can choose to enter your app and user tokens each time you call `Send-Pushover`, but you +can also save them securely using `Set-PushoverConfig` and then they'll become the default values +when no alternate tokens are provided. + +```powershell +$appToken = Read-Host -Prompt 'Application token' -AsSecureString +$usrToken = Read-Host -Prompt 'User token' -AsSecureString +Set-PushoverConfig -Token $appToken -User $usrToken +``` + +### Send a message + +It's time to send your first push notification! + +```powershell +Send-Pushover -Message 'Hello from PSPushover!' +``` diff --git a/docs/en-US/Get-PushoverConfig.md b/docs/en-US/Get-PushoverConfig.md new file mode 100644 index 0000000..bab26ac --- /dev/null +++ b/docs/en-US/Get-PushoverConfig.md @@ -0,0 +1,79 @@ +--- +external help file: joshooaj.PSPushover-help.xml +Module Name: joshooaj.PSPushover +online version: https://www.joshooaj.com/PSPushover/en-US/Get-PushoverConfig/ +schema: 2.0.0 +--- + +# Get-PushoverConfig + +## SYNOPSIS + +Get the Pushover configuration from the PSPushover module + +## SYNTAX + +``` +Get-PushoverConfig [-ProgressAction ] [] +``` + +## DESCRIPTION + +Properties like the API URI and default application and user tokens can be read and written +using Get-PushoverConfig and Set-PushoverConfig. + +The location of the configuration file depends on your operating system. On Windows the path is +usually `C:\Users\\AppData\Roaming\joshooaj.PSPushover\config.xml` and on Linux the path may +be `/home//.config/joshooaj.PSPushover/config.xml`. PSPushover determines the application +data path using the command `[Environment]::GetFolderPath([System.Environment+SpecialFolder]::ApplicationData)` + +## EXAMPLES + +### Example 1 + +```powershell +Get-PushoverConfig | Format-List + +<# Sample output +ApiUri : https://api.pushover.net/1 +AppToken : System.Security.SecureString +UserToken : System.Security.SecureString +ConfigPath : /home/vscode/.config/PSPushover/config.xml +#> +``` + +Returns the PSPushover configuration for the current user which includes the default base URI for the Pushover API, the +default app and user tokens, and the location where the configuration is stored. + +## PARAMETERS + +### -ProgressAction + +Ignore this common parameter. PlatyPS is undergoing a rewrite and the current version does not recognize ProgressAction as a common parameter. + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None + +## OUTPUTS + +### PSCustomObject + +## NOTES + +## RELATED LINKS diff --git a/docs/en-US/Get-PushoverSound.md b/docs/en-US/Get-PushoverSound.md new file mode 100644 index 0000000..66cbdbf --- /dev/null +++ b/docs/en-US/Get-PushoverSound.md @@ -0,0 +1,92 @@ +--- +external help file: joshooaj.PSPushover-help.xml +Module Name: joshooaj.PSPushover +online version: https://www.joshooaj.com/PSPushover/en-US/Get-PushoverSound/ +schema: 2.0.0 +--- + +# Get-PushoverSound + +## SYNOPSIS + +Gets the sounds available to use for notifications associated with an application. + +## SYNTAX + +``` +Get-PushoverSound [[-Token] ] [-ProgressAction ] [] +``` + +## DESCRIPTION + +The `Get-PushoverSound` cmdlet gets the sounds available to use for notifications associated with +an application. There is a collection of sounds available to choose from, and you may add your own +sounds through your [Pushover.net](https://pushover.net) dashboard. + +## EXAMPLES + +### Example 1 + +```powershell +Get-PushoverSound +``` + +Gets a hashtable containing the sounds available for the default application in your environment. + +### Example 2 + +```powershell +$appToken = Read-Host -Prompt 'Application token' -AsSecureString +Get-PushoverSound -Token $appToken +``` + +Gets a hashtable containing the sounds available for the application represented by the token +stored in the $appToken variable. + +## PARAMETERS + +### -Token + +Specifies the Pushover application API token/key. The default value will be used if it has been +previously set with Set-PushoverConfig. + +```yaml +Type: SecureString +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ProgressAction + +Ignore this common parameter. PlatyPS is undergoing a rewrite and the current version does not recognize ProgressAction as a common parameter. + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### System.Collections.Hashtable + +## NOTES + +## RELATED LINKS diff --git a/docs/en-US/Get-PushoverStatus.md b/docs/en-US/Get-PushoverStatus.md new file mode 100644 index 0000000..99068cd --- /dev/null +++ b/docs/en-US/Get-PushoverStatus.md @@ -0,0 +1,133 @@ +--- +external help file: joshooaj.PSPushover-help.xml +Module Name: joshooaj.PSPushover +online version: https://www.joshooaj.com/PSPushover/en-US/Get-PushoverStatus/ +schema: 2.0.0 +--- + +# Get-PushoverStatus + +## SYNOPSIS + +Gets the status of a Pushover notification using the receipt from Send-Pushover. + +## SYNTAX + +``` +Get-PushoverStatus [[-Token] ] [-Receipt] [-ProgressAction ] + [] +``` + +## DESCRIPTION + +When sending a Pushover notification with MessagePriority of 'Emergency', a receipt is returned. +This receipt is a random string associated with the notification and can be used to check if and +when the notification was delivered and acknowledged, or if it has expired and is no longer +causing notifications to be sent to the user(s). + +When the notification is acknowledged, the user and device performing the acknowledgement will be +included in the returned `[PSPushoverNotificationStatus]` response. + +## EXAMPLES + +### EXAMPLE 1 + +```powershell +$receipt = Send-Pushover -Message 'Are we there yet?' -MessagePriority Emergency -Sound tugboat +Get-PushoverStatus -Receipt $receipt + +<# Sample output + +# Before acknowledgement +Receipt : ro3r26sualp9jb71azpp3eizrtfiir +Acknowledged : False +AcknowledgedAt : 01/01/1970 00:00:00 +AcknowledgedBy : +AcknowledgedByDevice : +LastDeliveredAt : 03/17/2024 21:47:44 +Expired : False +ExpiresAt : 03/17/2024 21:57:44 +CalledBack : False +CalledBackAt : 01/01/1970 00:00:00 + +# After acknowledgement +Receipt : ro3r26sualp9jb71azpp3eizrtfiir +Acknowledged : True +AcknowledgedAt : 03/17/2024 21:48:50 +AcknowledgedBy : +AcknowledgedByDevice : android +LastDeliveredAt : 03/17/2024 21:48:44 +Expired : False +ExpiresAt : 03/17/2024 21:57:44 +CalledBack : False +CalledBackAt : 01/01/1970 00:00:00 +#> +``` + +Sends an emergency Pushover message and then uses the receipt to check the status of that notification. + +## PARAMETERS + +### -Receipt + +Specifies the receipt returned by Send-Pushover when sending notifications with a +"MessagePriority" value of "Emergency". The receipt is a random string value in the same format +as an application or user token. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Token + +Specifies the Pushover application API token/key. The default value will be used if it has been +previously set with Set-PushoverConfig. + +```yaml +Type: SecureString +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ProgressAction + +Ignore this common parameter. PlatyPS is undergoing a rewrite and the current version does not recognize ProgressAction as a common parameter. + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### PSPushoverNotificationStatus + +## NOTES + +## RELATED LINKS diff --git a/docs/en-US/Reset-PushoverConfig.md b/docs/en-US/Reset-PushoverConfig.md new file mode 100644 index 0000000..6adde6c --- /dev/null +++ b/docs/en-US/Reset-PushoverConfig.md @@ -0,0 +1,95 @@ +--- +external help file: joshooaj.PSPushover-help.xml +Module Name: joshooaj.PSPushover +online version: https://www.joshooaj.com/PSPushover/en-US/Reset-PushoverConfig/ +schema: 2.0.0 +--- + +# Reset-PushoverConfig + +## SYNOPSIS + +Reset the PSPushover module configuration to default values for the current user. + +## SYNTAX + +``` +Reset-PushoverConfig [-ProgressAction ] [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION + +Use this cmdlet to reset your current user's PSPushover configuration to default values. This will +reset the Pushover API base URI to the default value, and remove your user and application tokens +if they were previously stored using `Set-PushoverConfig`. + +## EXAMPLES + +### Example 1 + +```powershell +Reset-PushoverConfig +``` + +Deletes the stored application and user tokens if present, and resets the base URI for the Pushover +API to the default value. + +## PARAMETERS + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ProgressAction + +Ignore this common parameter. PlatyPS is undergoing a rewrite and the current version does not recognize ProgressAction as a common parameter. + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES + +## RELATED LINKS diff --git a/docs/en-US/Send-Pushover.md b/docs/en-US/Send-Pushover.md new file mode 100644 index 0000000..2f37cd3 --- /dev/null +++ b/docs/en-US/Send-Pushover.md @@ -0,0 +1,330 @@ +--- +external help file: joshooaj.PSPushover-help.xml +Module Name: joshooaj.PSPushover +online version: https://www.joshooaj.com/PSPushover/en-US/Send-Pushover/ +schema: 2.0.0 +--- + +# Send-Pushover + +## SYNOPSIS + +Sends a message to one or more users using the Pushover API. + +## SYNTAX + +``` +Send-Pushover [-Message] [-Title ] [-Attachment ] [-FileName ] [-Url ] + [-UrlTitle ] [-MessagePriority ] [-RetryInterval ] + [-ExpireAfter ] [-Timestamp ] [-Sound ] [-Tags ] [-Token ] + [-User ] [-Device ] [-ProgressAction ] [] +``` + +## DESCRIPTION + +The `Send-Pushover` cmdlet sends a message to one or more users using the Pushover API. +Notifications require a message, and may be customized with a number of optional parameters +including a title, image, url, sound, timestamp, and priority. + +Notifications with a MessagePriority of "Emergency" can be customized with a retry interval, and +expiration. Emergency notifications can be monitored in order to track when and who has +acknowledged them. + +## EXAMPLES + +### EXAMPLE 1 + +```powershell +Send-PushoverMessage -Token $token -User $user -Title 'What time is it?' -Message 'It''s time for lunch' +``` + +Sends a notification to the user or group specified in the $user string variable, from the application designed by the application API token value in $token + +### EXAMPLE 2 + +```powershell +Send-PushoverMessage -Token $token -User $user -Title 'What time is it?' -Message 'It''s time for lunch' -MessagePriority Emergency -RetryInterval (New-TimeSpan -Seconds 60) -ExpireAfter (New-TimeSpan -Hours 1) +``` + +Sends the same notification as Example 1, except with emergency priority which results in the notification being repeated every 60 seconds, until an hour has passed or the message has been acknowledged. + +## PARAMETERS + +### -Attachment + +Optionally specifies an image in bytes to be attached to the message. + +```yaml +Type: Byte[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Device + +Optionally specifies one or more devices to which notifications should be sent. +Useful for sending notifications to a targetted device instead of all of the user's devices. + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ExpireAfter + +Specifies the amount of time unacknowledged notifications will be retried before Pushover stops sending notifications. +Valid only with MessagePriority of 'Emergency'. + +```yaml +Type: TimeSpan +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: (New-TimeSpan -Minutes 10) +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -FileName + +Optionally specifies the file name to associate with the attachment. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: Attachment.jpg +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Message + +Specifies the message to be sent with the Pushover notification. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName, ByValue) +Accept wildcard characters: False +``` + +### -MessagePriority + +Parameter help description + +```yaml +Type: MessagePriority +Parameter Sets: (All) +Aliases: +Accepted values: Normal, High, Emergency, Lowest, Low + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RetryInterval + +Specifies the interval between emergency Pushover notifications. +Pushover will retry until the message is acknowledged, or expired. +Valid only with MessagePriority of 'Emergency'. + +```yaml +Type: TimeSpan +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: (New-TimeSpan -Minutes 1) +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Sound + +Optionally specifies the notification sound to use + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Tags + +Optionally specifies one or more tags to associate with the Pushover notification. +Tags can be used to cancel emergency notifications in bulk. + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Timestamp + +Optionally specifies the timestamp associated with the message. +Default is DateTime.Now. + +```yaml +Type: DateTime +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: (Get-Date) +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Title + +Specifies the title of the Pushover notification. +The default will be the application name configured for the application API token supplied. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Token + +Specifies the application API token/key from which the Pushover notification should be sent. +Note: The default value will be used if it has been previously set with Set-PushoverConfig + +```yaml +Type: SecureString +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Url + +Optionally specifies a supplementary URL associated with the message. + +```yaml +Type: Uri +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -UrlTitle + +Optionally specifies a title for the supplementary URL if specified. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -User + +Specifies the User or Group identifier to which the Pushover message should be sent. +Note: The default value will be used if it has been previously set with Set-PushoverConfig + +```yaml +Type: SecureString +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ProgressAction + +Ignore this common parameter. PlatyPS is undergoing a rewrite and the current version does not recognize ProgressAction as a common parameter. + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### String + +## NOTES + +## RELATED LINKS diff --git a/docs/en-US/Set-PushoverConfig.md b/docs/en-US/Set-PushoverConfig.md new file mode 100644 index 0000000..6ed3c3b --- /dev/null +++ b/docs/en-US/Set-PushoverConfig.md @@ -0,0 +1,177 @@ +--- +external help file: joshooaj.PSPushover-help.xml +Module Name: joshooaj.PSPushover +online version: https://www.joshooaj.com/PSPushover/en-US/Set-PushoverConfig/ +schema: 2.0.0 +--- + +# Set-PushoverConfig + +## SYNOPSIS + +Sets the Pushover configuration in the PSPushover module + +## SYNTAX + +``` +Set-PushoverConfig [-ApiUri ] [-Token ] [-User ] [-Temporary] + [-ProgressAction ] [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION + +The Pushover API URI can be modified for the purpose of test automation, and application +and user tokens can be securely stored on disk so that you don't have to supply the tokens +with every call to Send-Pushover in case you are always sending notifications from the same +application and to the same user/group. + +The location of the configuration file depends on your operating system. On Windows the path is +usually `C:\Users\\AppData\Roaming\joshooaj.PSPushover\config.xml` and on Linux the path may +be `/home//.config/joshooaj.PSPushover/config.xml`. PSPushover determines the application +data path using the command `[Environment]::GetFolderPath([System.Environment+SpecialFolder]::ApplicationData)` + +## EXAMPLES + +### EXAMPLE 1 + +```powershell +Set-PushoverConfig -Token (Read-Host -AsSecureString) +Set-PushoverConfig -User (Read-Host -AsSecureString) +``` + +Prompts for the desired default application token and user token and persists it to disk to use as the default application and user tokens. + +### EXAMPLE 2 + +```powershell +Set-PushoverConfig -ApiUri http://localhost:8888 -Temporary +``` + +Sets the Pushover API URI to `http://localhost:8888` for the duration of the PowerShell session +or until the PSPushover module is forcefully imported again. + +## PARAMETERS + +### -ApiUri + +Species the base URI to which all HTTP requests should be sent. +Recommended to change this only for the purposes of test automation. + +```yaml +Type: Uri +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Temporary + +Specifies that the new settings should only be temporary and should not be saved to disk. The next time the PSPushover +module is imported, the temporary value will be lost and the default values will be loaded from disk. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Token + +The default application token to use when the token isn't otherwise specified. + +```yaml +Type: SecureString +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -User + +The default user or group token to use when the token isn't otherwise specified. + +```yaml +Type: SecureString +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ProgressAction + +Ignore this common parameter. PlatyPS is undergoing a rewrite and the current version does not recognize ProgressAction as a common parameter. + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES + +## RELATED LINKS diff --git a/docs/en-US/Test-PushoverUser.md b/docs/en-US/Test-PushoverUser.md new file mode 100644 index 0000000..e8ab41a --- /dev/null +++ b/docs/en-US/Test-PushoverUser.md @@ -0,0 +1,149 @@ +--- +external help file: joshooaj.PSPushover-help.xml +Module Name: joshooaj.PSPushover +online version: https://www.joshooaj.com/PSPushover/en-US/Test-PushoverUser/ +schema: 2.0.0 +--- + +# Test-PushoverUser + +## SYNOPSIS + +Validate a user token and optional device name against the Pushover API. + +## SYNTAX + +``` +Test-PushoverUser [[-Token] ] [[-User] ] [[-Device] ] + [[-InformationLevel] ] [-ProgressAction ] [] +``` + +## DESCRIPTION + +If you are collecting user tokens to register them to receive notifications, you may want to verify +that the key is valid before accepting it. Use the `Test-PushoverUser` cmdlet to ensure user tokens +are valid before sending notifications. + +The information returned is detailed by default and includes the error text returned from the +Pushover API. For example, the error message may read "device name is not valid for user". + +## EXAMPLES + +### EXAMPLE 1 + +```powershell +if ($null -eq (Get-PushoverConfig).AppToken) { + Set-PushoverConfig -Token (Read-Host -Prompt 'Pushover Application Token' -AsSecureString) +} +Test-PushoverUser -User (Read-Host -Prompt 'Pushover User Key' -AsSecureString) + +<# Sample output +Valid : False +IsGroup : False +Devices : +Licenses : +Error : user key is invalid +#> +``` + +Checks whether the current user's Pushover config includes a default application token. If not, request the user to enter the application token +and save it for future use. Then request the Pushover user key and test whether the key is valid. + +## PARAMETERS + +### -Device + +Optionally specifies the device on the user account to validate + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -InformationLevel + +Specifies the information level desired in the response. +Quiet means a boolean will be returned while Detailed will return an object with more information. + +```yaml +Type: PSPushoverInformationLevel +Parameter Sets: (All) +Aliases: +Accepted values: Detailed, Quiet + +Required: False +Position: 3 +Default value: Detailed +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Token + +Specifies the application API token/key from which the Pushover notification should be sent. +Note: The default value will be used if it has been previously set with Set-PushoverConfig + +```yaml +Type: SecureString +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -User + +Specifies the User or Group identifier to which the Pushover message should be sent. +Note: The default value will be used if it has been previously set with Set-PushoverConfig + +```yaml +Type: SecureString +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ProgressAction + +Ignore this common parameter. PlatyPS is undergoing a rewrite and the current version does not recognize ProgressAction as a common parameter. + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### PSPushoverUserValidation + +## NOTES + +## RELATED LINKS diff --git a/docs/en-US/Wait-Pushover.md b/docs/en-US/Wait-Pushover.md new file mode 100644 index 0000000..56dea81 --- /dev/null +++ b/docs/en-US/Wait-Pushover.md @@ -0,0 +1,114 @@ +--- +external help file: joshooaj.PSPushover-help.xml +Module Name: joshooaj.PSPushover +online version: https://www.joshooaj.com/PSPushover/en-US/Wait-Pushover/ +schema: 2.0.0 +--- + +# Wait-Pushover + +## SYNOPSIS + +Waits for a user to acknowledge receipt of the Pushover message or for the notification to expire. + +## SYNTAX + +``` +Wait-Pushover [[-Token] ] [-Receipt] [[-Interval] ] + [-ProgressAction ] [] +``` + +## DESCRIPTION + +Waits for a user to acknowledge receipt of the Pushover message or for the notification to expire +then returns the last `[PSPushoverNotificationStatus]` response object. + +## EXAMPLES + +### EXAMPLE 1 + +```powershell +Send-Pushover -Message 'Please clap' -MessagePriority Emergency | Wait-Pushover +``` + +Sends an emergency Pushover notification and then waits for the notification to expire or for at least one user to acknowledge it. + +## PARAMETERS + +### -Interval + +Specifies the interval between each Pushover API request for receipt status + +```yaml +Type: Int32 +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: 10 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Receipt + +Specifies the receipt received from emergency notifications sent using Send-Pushover + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Token + +Specifies the Pushover application API token/key. +Note: The default value will be used if it has been previously set with Set-PushoverConfig + +```yaml +Type: SecureString +Parameter Sets: (All) +Aliases: + +Required: False +Position: 0 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ProgressAction + +Ignore this common parameter. PlatyPS is undergoing a rewrite and the current version does not recognize ProgressAction as a common parameter. + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### PSPushoverNotificationStatus + +## NOTES + +## RELATED LINKS diff --git a/joshooaj.PSPushover/Classes/MessagePriority.ps1 b/joshooaj.PSPushover/Classes/MessagePriority.ps1 new file mode 100644 index 0000000..096ab2d --- /dev/null +++ b/joshooaj.PSPushover/Classes/MessagePriority.ps1 @@ -0,0 +1,7 @@ +enum MessagePriority { + Lowest = -2 + Low = -1 + Normal = 0 + High = 1 + Emergency = 2 +} \ No newline at end of file diff --git a/joshooaj.PSPushover/Classes/PSPushoverInformationLevel.ps1 b/joshooaj.PSPushover/Classes/PSPushoverInformationLevel.ps1 new file mode 100644 index 0000000..5c07c16 --- /dev/null +++ b/joshooaj.PSPushover/Classes/PSPushoverInformationLevel.ps1 @@ -0,0 +1,4 @@ +enum PSPushoverInformationLevel { + Detailed + Quiet +} diff --git a/joshooaj.PSPushover/Classes/PSPushoverNotificationStatus.ps1 b/joshooaj.PSPushover/Classes/PSPushoverNotificationStatus.ps1 new file mode 100644 index 0000000..5bd0528 --- /dev/null +++ b/joshooaj.PSPushover/Classes/PSPushoverNotificationStatus.ps1 @@ -0,0 +1,12 @@ +class PSPushoverNotificationStatus { + [string]$Receipt + [bool]$Acknowledged + [datetime]$AcknowledgedAt + [string]$AcknowledgedBy + [string]$AcknowledgedByDevice + [datetime]$LastDeliveredAt + [bool]$Expired + [datetime]$ExpiresAt + [bool]$CalledBack + [datetime]$CalledBackAt +} diff --git a/joshooaj.PSPushover/Classes/PSPushoverUserValidation.ps1 b/joshooaj.PSPushover/Classes/PSPushoverUserValidation.ps1 new file mode 100644 index 0000000..0fcd836 --- /dev/null +++ b/joshooaj.PSPushover/Classes/PSPushoverUserValidation.ps1 @@ -0,0 +1,7 @@ +class PSPushoverUserValidation { + [bool]$Valid + [bool]$IsGroup + [string[]]$Devices + [string[]]$Licenses + [string]$Error +} diff --git a/joshooaj.PSPushover/Private/ConvertTo-PlainText.ps1 b/joshooaj.PSPushover/Private/ConvertTo-PlainText.ps1 new file mode 100644 index 0000000..52d432a --- /dev/null +++ b/joshooaj.PSPushover/Private/ConvertTo-PlainText.ps1 @@ -0,0 +1,13 @@ +function ConvertTo-PlainText { + [CmdletBinding()] + param ( + # Specifies a securestring value to decrypt back to a plain text string + [Parameter(Mandatory, ValueFromPipeline)] + [securestring] + $Value + ) + + process { + ([pscredential]::new('unused', $Value)).GetNetworkCredential().Password + } +} \ No newline at end of file diff --git a/joshooaj.PSPushover/Private/Import-PushoverConfig.ps1 b/joshooaj.PSPushover/Private/Import-PushoverConfig.ps1 new file mode 100644 index 0000000..25287b0 --- /dev/null +++ b/joshooaj.PSPushover/Private/Import-PushoverConfig.ps1 @@ -0,0 +1,29 @@ +function Import-PushoverConfig { + <# + .SYNOPSIS + Imports the configuration including default API URI's and tokens + .DESCRIPTION + If the module has been previously used, the configuration should be present. If the config + can be imported, the function returns true. Otherwise it returns false. + #> + [CmdletBinding()] + [OutputType([bool])] + param () + + process { + if (Test-Path -Path $script:configPath) { + try { + Write-Verbose "Importing configuration from '$($script:configPath)'" + $script:config = Import-Clixml -Path $script:configPath + return $true + } + catch { + Write-Error "Failed to import configuration from '$script:configPath'." -Exception $_.Exception + } + } + else { + Write-Verbose "No existing module configuration found at '$($script:configPath)'" + } + $false + } +} \ No newline at end of file diff --git a/joshooaj.PSPushover/Private/Save-PushoverConfig.ps1 b/joshooaj.PSPushover/Private/Save-PushoverConfig.ps1 new file mode 100644 index 0000000..ab7c6df --- /dev/null +++ b/joshooaj.PSPushover/Private/Save-PushoverConfig.ps1 @@ -0,0 +1,17 @@ +function Save-PushoverConfig { + <# + .SYNOPSIS + Save module configuration to disk + #> + [CmdletBinding()] + param () + + process { + Write-Verbose "Saving the module configuration to '$($script:configPath)'" + $directory = ([io.fileinfo]$script:configPath).DirectoryName + if (-not (Test-Path -Path $directory)) { + $null = New-Item -Path $directory -ItemType Directory -Force + } + $script:config | Export-Clixml -Path $script:configPath -Force + } +} \ No newline at end of file diff --git a/joshooaj.PSPushover/Private/Send-MessageWithAttachment.ps1 b/joshooaj.PSPushover/Private/Send-MessageWithAttachment.ps1 new file mode 100644 index 0000000..7829853 --- /dev/null +++ b/joshooaj.PSPushover/Private/Send-MessageWithAttachment.ps1 @@ -0,0 +1,62 @@ +function Send-MessageWithAttachment { + <# + .SYNOPSIS + Sends an HTTP POST to the Pushover API using an HttpClient + .DESCRIPTION + When sending an image attachment with a Pushover message, you must use multipart/form-data + and there doesn't seem to be a nice way to do this using Invoke-RestMethod like we're doing + in the public Send-Message function. So when an attachment is provided to Send-Message, the + body hashtable is constructed, and then sent over to this function to keep the main + Send-Message function a manageable size. + #> + [CmdletBinding()] + param ( + # Specifies the various parameters and values expected by the Pushover messages api. + [Parameter(Mandatory)] + [hashtable] + $Body, + + # Specifies the image to attach to the message as a byte array + [Parameter(Mandatory)] + [byte[]] + $Attachment, + + # Optionally specifies a file name to associate with the attachment + [Parameter()] + [string] + $FileName = 'attachment.jpg' + ) + + begin { + $uri = $script:PushoverApiUri + '/messages.json' + } + + process { + try { + $client = [system.net.http.httpclient]::new() + try { + $content = [system.net.http.multipartformdatacontent]::new() + foreach ($key in $Body.Keys) { + $textContent = [system.net.http.stringcontent]::new($Body.$key) + $content.Add($textContent, $key) + } + $jpegContent = [system.net.http.bytearraycontent]::new($Attachment) + $jpegContent.Headers.ContentType = [system.net.http.headers.mediatypeheadervalue]::new('image/jpeg') + $jpegContent.Headers.ContentDisposition = [system.net.http.headers.contentdispositionheadervalue]::new('form-data') + $jpegContent.Headers.ContentDisposition.Name = 'attachment' + $jpegContent.Headers.ContentDisposition.FileName = $FileName + $content.Add($jpegContent) + + Write-Verbose "Message body:`r`n$($content.ReadAsStringAsync().Result.Substring(0, 2000).Replace($Body.token, "********").Replace($Body.user, "********"))" + $result = $client.PostAsync($uri, $content).Result + Write-Output ($result.Content.ReadAsStringAsync().Result | ConvertFrom-Json) + } + finally { + $content.Dispose() + } + } + finally { + $client.Dispose() + } + } +} \ No newline at end of file diff --git a/joshooaj.PSPushover/Public/Get-PushoverConfig.ps1 b/joshooaj.PSPushover/Public/Get-PushoverConfig.ps1 new file mode 100644 index 0000000..e103963 --- /dev/null +++ b/joshooaj.PSPushover/Public/Get-PushoverConfig.ps1 @@ -0,0 +1,14 @@ +function Get-PushoverConfig { + [CmdletBinding()] + param () + + process { + [pscustomobject]@{ + PSTypeName = 'PushoverConfig' + ApiUri = $script:config.PushoverApiUri + AppToken = $script:config.DefaultAppToken + UserToken = $script:config.DefaultUserToken + ConfigPath = $script:configPath + } + } +} diff --git a/joshooaj.PSPushover/Public/Get-PushoverSound.ps1 b/joshooaj.PSPushover/Public/Get-PushoverSound.ps1 new file mode 100644 index 0000000..ac24362 --- /dev/null +++ b/joshooaj.PSPushover/Public/Get-PushoverSound.ps1 @@ -0,0 +1,72 @@ +function Get-PushoverSound { + [CmdletBinding()] + [OutputType([hashtable])] + param ( + [Parameter()] + [ValidateNotNullOrEmpty()] + [securestring] + $Token + ) + + begin { + $config = Get-PushoverConfig + $uriBuilder = [uribuilder]($config.ApiUri + '/sounds.json') + } + + process { + if ($null -eq $Token) { + $Token = $config.AppToken + if ($null -eq $Token) { + throw "Token not provided and no default application token has been set using Set-PushoverConfig." + } + } + + try { + $uriBuilder.Query = "token=" + ($Token | ConvertTo-PlainText) + $response = Invoke-RestMethod -Method Get -Uri $uriBuilder.Uri + } + catch { + Write-Verbose 'Handling HTTP error in Invoke-RestMethod response' + $statusCode = $_.Exception.Response.StatusCode.value__ + Write-Verbose "HTTP status code $statusCode" + if ($statusCode -lt 400 -or $statusCode -gt 499) { + throw + } + + try { + Write-Verbose 'Parsing HTTP request error response' + $stream = $_.Exception.Response.GetResponseStream() + $reader = [io.streamreader]::new($stream) + $response = $reader.ReadToEnd() | ConvertFrom-Json + if ([string]::IsNullOrWhiteSpace($response)) { + throw $_ + } + Write-Verbose "Response body:`r`n$response" + } + finally { + $reader.Dispose() + } + } + + if ($response.status -eq 1) { + $sounds = @{} + foreach ($name in $response.sounds | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name) { + $sounds.$name = $response.sounds.$name + } + Write-Output $sounds + } + else { + if ($null -ne $response.error) { + Write-Error $response.error + } + elseif ($null -ne $response.errors) { + foreach ($problem in $response.errors) { + Write-Error $problem + } + } + else { + $response + } + } + } +} diff --git a/joshooaj.PSPushover/Public/Get-PushoverStatus.ps1 b/joshooaj.PSPushover/Public/Get-PushoverStatus.ps1 new file mode 100644 index 0000000..d941272 --- /dev/null +++ b/joshooaj.PSPushover/Public/Get-PushoverStatus.ps1 @@ -0,0 +1,84 @@ +function Get-PushoverStatus { + [CmdletBinding()] + [OutputType([PSPushoverNotificationStatus])] + param ( + [Parameter()] + [ValidateNotNullOrEmpty()] + [securestring] + $Token, + + [Parameter(Mandatory, ValueFromPipeline)] + [string] + $Receipt + ) + + begin { + $config = Get-PushoverConfig + $uriBuilder = [uribuilder]($config.ApiUri + '/receipts') + } + + process { + if ($null -eq $Token) { + $Token = $config.AppToken + if ($null -eq $Token) { + throw "Token not provided and no default application token has been set using Set-PushoverConfig." + } + } + $uriBuilder.Path += "/$Receipt.json" + $uriBuilder.Query = "token=" + ($Token | ConvertTo-PlainText) + try { + $uriBuilder.Query = "token=" + ($Token | ConvertTo-PlainText) + $response = Invoke-RestMethod -Method Get -Uri $uriBuilder.Uri + } + catch { + Write-Verbose 'Handling HTTP error in Invoke-RestMethod response' + $statusCode = $_.Exception.Response.StatusCode.value__ + Write-Verbose "HTTP status code $statusCode" + if ($statusCode -lt 400 -or $statusCode -gt 499) { + throw + } + + try { + Write-Verbose 'Parsing HTTP request error response' + $stream = $_.Exception.Response.GetResponseStream() + $reader = [io.streamreader]::new($stream) + $response = $reader.ReadToEnd() | ConvertFrom-Json + if ([string]::IsNullOrWhiteSpace($response)) { + throw $_ + } + Write-Verbose "Response body:`r`n$response" + } + finally { + $reader.Dispose() + } + } + + if ($response.status -eq 1) { + [PSPushoverNotificationStatus]@{ + Receipt = $Receipt + Acknowledged = [bool]$response.acknowledged + AcknowledgedAt = [datetimeoffset]::FromUnixTimeSeconds($response.acknowledged_at).DateTime.ToLocalTime() + AcknowledgedBy = $response.acknowledged_by + AcknowledgedByDevice = $response.acknowledged_by_device + LastDeliveredAt = [datetimeoffset]::FromUnixTimeSeconds($response.last_delivered_at).DateTime.ToLocalTime() + Expired = [bool]$response.expired + ExpiresAt = [datetimeoffset]::FromUnixTimeSeconds($response.expires_at).DateTime.ToLocalTime() + CalledBack = [bool]$response.called_back + CalledBackAt = [datetimeoffset]::FromUnixTimeSeconds($response.called_back_at).DateTime.ToLocalTime() + } + } + else { + if ($null -ne $response.error) { + Write-Error $response.error + } + elseif ($null -ne $response.errors) { + foreach ($problem in $response.errors) { + Write-Error $problem + } + } + else { + $response + } + } + } +} diff --git a/joshooaj.PSPushover/Public/Reset-PushoverConfig.ps1 b/joshooaj.PSPushover/Public/Reset-PushoverConfig.ps1 new file mode 100644 index 0000000..b44074a --- /dev/null +++ b/joshooaj.PSPushover/Public/Reset-PushoverConfig.ps1 @@ -0,0 +1,17 @@ +function Reset-PushoverConfig { + [CmdletBinding(SupportsShouldProcess)] + param () + + process { + if ($PSCmdlet.ShouldProcess("PSPushover Module Configuration", "Reset to default")) { + Write-Verbose "Using the default module configuration" + $script:config = @{ + PushoverApiDefaultUri = 'https://api.pushover.net/1' + PushoverApiUri = 'https://api.pushover.net/1' + DefaultAppToken = $null + DefaultUserToken = $null + } + Save-PushoverConfig + } + } +} diff --git a/joshooaj.PSPushover/Public/Send-Pushover.ps1 b/joshooaj.PSPushover/Public/Send-Pushover.ps1 new file mode 100644 index 0000000..0623822 --- /dev/null +++ b/joshooaj.PSPushover/Public/Send-Pushover.ps1 @@ -0,0 +1,180 @@ +function Send-Pushover { + [CmdletBinding()] + [OutputType([string])] + param ( + [Parameter(Mandatory, Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [string] + $Message, + + [Parameter()] + [string] + $Title, + + [Parameter()] + [byte[]] + $Attachment, + + [Parameter()] + [string] + $FileName = 'attachment.jpg', + + [Parameter()] + [ValidateNotNullOrEmpty()] + [uri] + $Url, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [string] + $UrlTitle, + + [Parameter()] + [MessagePriority] + $MessagePriority, + + [Parameter()] + [ValidateScript({ + if ($_.TotalSeconds -lt 30) { + throw 'RetryInterval must be at least 30 seconds' + } + if ($_.TotalSeconds -gt 10800) { + throw 'RetryInterval cannot exceed 3 hours' + } + $true + })] + [timespan] + $RetryInterval = (New-TimeSpan -Minutes 1), + + [Parameter()] + [ValidateScript({ + if ($_.TotalSeconds -le 30) { + throw 'ExpireAfter must be greater than the minimum RetryInterval value of 30 seconds' + } + if ($_.TotalSeconds -gt 10800) { + throw 'ExpireAfter cannot exceed 3 hours' + } + $true + })] + [timespan] + $ExpireAfter = (New-TimeSpan -Minutes 10), + + [Parameter()] + [datetime] + $Timestamp = (Get-Date), + + [Parameter()] + [ValidateNotNullOrEmpty()] + [string] + $Sound, + + [Parameter()] + [string[]] + $Tags, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [securestring] + $Token, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [securestring] + $User, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [string[]] + $Device + ) + + begin { + $config = Get-PushoverConfig + $uri = $config.ApiUri + '/messages.json' + } + + process { + if ($null -eq $Token) { + $Token = $config.AppToken + if ($null -eq $Token) { + throw "Token not provided and no default application token has been set using Set-PushoverConfig." + } + } + if ($null -eq $User) { + $User = $config.UserToken + if ($null -eq $User) { + throw "User not provided and no default user id has been set using Set-PushoverConfig." + } + } + + $deviceList = if ($null -ne $Device) { + [string]::Join(',', $Device) + } else { $null } + + $tagList = if ($null -ne $Tags) { + [string]::Join(',', $Tags) + } else { $null } + + $body = [ordered]@{ + token = $Token | ConvertTo-PlainText + user = $User | ConvertTo-PlainText + device = $deviceList + title = $Title + message = $Message + url = $Url + url_title = $UrlTitle + priority = [int]$MessagePriority + retry = [int]$RetryInterval.TotalSeconds + expire = [int]$ExpireAfter.TotalSeconds + timestamp = [int]([datetimeoffset]::new($Timestamp).ToUnixTimeMilliseconds() / 1000) + tags = $tagList + sound = $Sound + } + + try { + if ($Attachment.Length -eq 0) { + $bodyJson = $body | ConvertTo-Json + Write-Verbose "Message body:`r`n$($bodyJson.Replace($Body.token, "********").Replace($Body.user, "********"))" + $response = Invoke-RestMethod -Method Post -Uri $uri -Body $bodyJson -ContentType application/json -UseBasicParsing + } else { + $response = Send-MessageWithAttachment -Body $body -Attachment $Attachment -FileName $FileName + } + } catch { + Write-Verbose 'Handling HTTP error in Invoke-RestMethod response' + $statusCode = $_.Exception.Response.StatusCode.value__ + Write-Verbose "HTTP status code $statusCode" + if ($statusCode -lt 400 -or $statusCode -gt 499) { + throw + } + + try { + Write-Verbose 'Parsing HTTP request error response' + $stream = $_.Exception.Response.GetResponseStream() + $reader = [io.streamreader]::new($stream) + $response = $reader.ReadToEnd() | ConvertFrom-Json + if ([string]::IsNullOrWhiteSpace($response)) { + throw $_ + } + Write-Verbose "Response body:`r`n$response" + } finally { + $reader.Dispose() + } + } + + if ($response.status -ne 1) { + if ($null -ne $response.error) { + Write-Error $response.error + } elseif ($null -ne $response.errors) { + foreach ($problem in $response.errors) { + Write-Error $problem + } + } else { + $response + } + } + + if ($null -ne $response.receipt) { + Write-Output $response.receipt + } + } +} diff --git a/joshooaj.PSPushover/Public/Set-PushoverConfig.ps1 b/joshooaj.PSPushover/Public/Set-PushoverConfig.ps1 new file mode 100644 index 0000000..861e0e0 --- /dev/null +++ b/joshooaj.PSPushover/Public/Set-PushoverConfig.ps1 @@ -0,0 +1,42 @@ +function Set-PushoverConfig { + [CmdletBinding(SupportsShouldProcess)] + param ( + [Parameter()] + [uri] + $ApiUri, + + [Parameter(ParameterSetName = 'AsPlainText')] + [securestring] + $Token, + + [Parameter()] + [securestring] + $User, + + [Parameter()] + [switch] + $Temporary + ) + + process { + if ($PSBoundParameters.ContainsKey('ApiUri')) { + if ($PSCmdlet.ShouldProcess("Pushover ApiUri", "Set value to '$ApiUri'")) { + $script:config.PushoverAPiUri = $ApiUri.ToString() + } + } + if ($PSBoundParameters.ContainsKey('Token')) { + if ($PSCmdlet.ShouldProcess("Pushover Default Application Token", "Set value")) { + $script:config.DefaultAppToken = $Token + } + } + if ($PSBoundParameters.ContainsKey('User')) { + if ($PSCmdlet.ShouldProcess("Pushover Default User Key", "Set value")) { + $script:config.DefaultUserToken = $User + } + } + + if (-not $Temporary) { + Save-PushoverConfig + } + } +} diff --git a/joshooaj.PSPushover/Public/Test-PushoverUser.ps1 b/joshooaj.PSPushover/Public/Test-PushoverUser.ps1 new file mode 100644 index 0000000..89d62f8 --- /dev/null +++ b/joshooaj.PSPushover/Public/Test-PushoverUser.ps1 @@ -0,0 +1,102 @@ +function Test-PushoverUser { + [CmdletBinding()] + [OutputType([PSPushoverUserValidation])] + param ( + [Parameter()] + [ValidateNotNullOrEmpty()] + [securestring] + $Token, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [securestring] + $User, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [string] + $Device, + + [Parameter()] + [PSPushoverInformationLevel] + $InformationLevel = [PSPushoverInformationLevel]::Detailed + ) + + begin { + $config = Get-PushoverConfig + $uri = $config.ApiUri + '/users/validate.json' + } + + process { + if ($null -eq $Token) { + $Token = $config.AppToken + if ($null -eq $Token) { + throw "Token not provided and no default application token has been set using Set-PushoverConfig." + } + } + if ($null -eq $User) { + $User = $config.UserToken + if ($null -eq $User) { + throw "User not provided and no default user id has been set using Set-PushoverConfig." + } + } + + $body = [ordered]@{ + token = $Token | ConvertTo-PlainText + user = $User | ConvertTo-PlainText + device = $Device + } + + try { + $bodyJson = $body | ConvertTo-Json + Write-Verbose "Message body:`r`n$($bodyJson.Replace($Body.token, "********").Replace($Body.user, "********"))" + if (Get-Command Invoke-RestMethod -ParameterName SkipHttpErrorCheck -ErrorAction SilentlyContinue) { + $response = Invoke-RestMethod -Method Post -Uri $uri -Body $bodyJson -ContentType application/json -SkipHttpErrorCheck + } else { + $response = Invoke-RestMethod -Method Post -Uri $uri -Body $bodyJson -ContentType application/json -UseBasicParsing + } + + } catch { + Write-Verbose 'Handling HTTP error in Invoke-RestMethod response' + $statusCode = $_.Exception.Response.StatusCode.value__ + Write-Verbose "HTTP status code $statusCode" + if ($statusCode -lt 400 -or $statusCode -gt 499) { + throw + } + + try { + Write-Verbose 'Parsing HTTP request error response' + $stream = $_.Exception.Response.GetResponseStream() + $reader = [io.streamreader]::new($stream) + $response = $reader.ReadToEnd() | ConvertFrom-Json + if ([string]::IsNullOrWhiteSpace($response)) { + throw $_ + } + Write-Verbose "Response body:`r`n$response" + } finally { + $reader.Dispose() + } + } + + if ($null -ne $response.status) { + switch ($InformationLevel) { + ([PSPushoverInformationLevel]::Quiet) { + Write-Output ($response.status -eq 1) + } + + ([PSPushoverInformationLevel]::Detailed) { + [PSPushoverUserValidation]@{ + Valid = $response.status -eq 1 + IsGroup = $response.group -eq 1 + Devices = $response.devices + Licenses = $response.licenses + Error = $response.errors | Select-Object -First 1 + } + } + Default { throw "InformationLevel $InformationLevel not implemented." } + } + } else { + Write-Error "Unexpected response: $($response | ConvertTo-Json)" + } + } +} diff --git a/joshooaj.PSPushover/Public/Wait-Pushover.ps1 b/joshooaj.PSPushover/Public/Wait-Pushover.ps1 new file mode 100644 index 0000000..6121f2f --- /dev/null +++ b/joshooaj.PSPushover/Public/Wait-Pushover.ps1 @@ -0,0 +1,43 @@ +function Wait-Pushover { + [CmdletBinding()] + [OutputType([PSPushoverNotificationStatus])] + param ( + [Parameter()] + [ValidateNotNullOrEmpty()] + [securestring] + $Token, + + [Parameter(Mandatory, ValueFromPipeline)] + [string] + $Receipt, + + [Parameter()] + [ValidateRange(5, 10800)] + [int] + $Interval = 10 + ) + + begin { + $config = Get-PushoverConfig + } + + process { + if ($null -eq $Token) { + $Token = $config.Token + if ($null -eq $Token) { + throw "Token not provided and no default application token has been set using Set-PushoverConfig." + } + } + + $timeoutAt = (Get-Date).AddHours(3) + while ((Get-Date) -lt $timeoutAt.AddSeconds($Interval)) { + $status = Get-PushoverStatus -Token $Token -Receipt $Receipt -ErrorAction Stop + $timeoutAt = $status.ExpiresAt + if ($status.Acknowledged -or $status.Expired) { + break + } + Start-Sleep -Seconds $Interval + } + Write-Output $status + } +} diff --git a/joshooaj.PSPushover/joshooaj.PSPushover.psd1 b/joshooaj.PSPushover/joshooaj.PSPushover.psd1 new file mode 100644 index 0000000..79770e6 --- /dev/null +++ b/joshooaj.PSPushover/joshooaj.PSPushover.psd1 @@ -0,0 +1,25 @@ +@{ + RootModule = 'joshooaj.PSPushover.psm1' + # ModuleVersion is updated in the output directory using a PostAction on the StageFiles psake task. The version number is provided by nbgv. + ModuleVersion = '0.1.0' + GUID = '4db4b678-dc3f-47b1-bfe0-4ffc65ae03f4' + Author = 'joshooaj' + CompanyName = 'joshooaj' + Copyright = '(c) Joshua Hendricks. All rights reserved.' + Description = 'Send notifications to any device from PowerShell using pushover.net.' + # FunctionsToExport is updated in the output directory by PowerShellBuild + FunctionsToExport = '*' + CmdletsToExport = @() + VariablesToExport = @() + AliasesToExport = @() + PrivateData = @{ + PSData = @{ + Tags = @('notifications', 'pushover', 'push notifications') + LicenseUri = 'https://github.com/joshooaj/PSPushover/blob/main/LICENSE' + ProjectUri = 'https://github.com/joshooaj/PSPushover' + # IconUri = '' + # ReleaseNotes = '' + # Prerelease = '' + } + } +} diff --git a/joshooaj.PSPushover/joshooaj.PSPushover.psm1 b/joshooaj.PSPushover/joshooaj.PSPushover.psm1 new file mode 100644 index 0000000..cb917c8 --- /dev/null +++ b/joshooaj.PSPushover/joshooaj.PSPushover.psm1 @@ -0,0 +1,37 @@ +# Dot source public/private functions when importing from source +if (Test-Path -Path $PSScriptRoot/Public) { + $classes = @(Get-ChildItem -Path (Join-Path -Path $PSScriptRoot -ChildPath 'Classes/*.ps1') -Recurse -ErrorAction Stop) + $public = @(Get-ChildItem -Path (Join-Path -Path $PSScriptRoot -ChildPath 'Public/*.ps1') -Recurse -ErrorAction Stop) + $private = @(Get-ChildItem -Path (Join-Path -Path $PSScriptRoot -ChildPath 'Private/*.ps1') -Recurse -ErrorAction Stop) + foreach ($import in @(($classes + $public + $private))) { + try { + . $import.FullName + } catch { + throw "Unable to dot source [$($import.FullName)]" + } + } + + Export-ModuleMember -Function $public.Basename +} + +$script:PushoverApiDefaultUri = 'https://api.pushover.net/1' +$script:PushoverApiUri = $script:PushoverApiDefaultUri + +$appDataRoot = [environment]::GetFolderPath([System.Environment+SpecialFolder]::ApplicationData) +$script:configPath = Join-Path $appDataRoot 'joshooaj.PSPushover\config.xml' +$script:config = $null +if (-not (Import-PushoverConfig)) { + Reset-PushoverConfig +} + +$soundsCompleter = { + param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) + + $soundList = @('incoming', 'pianobar', 'climb', 'gamelan', 'bugle', 'vibrate', 'pushover', 'cosmic', 'spacealarm', 'updown', 'none', 'persistent', 'cashregister', 'mechanical', 'bike', 'classical', 'falling', 'alien', 'magic', 'siren', 'tugboat', 'intermission', 'echo') + $soundList | Where-Object { + $_ -like "$wordToComplete*" + } | Foreach-Object { + "'$_'" + } +} +Register-ArgumentCompleter -CommandName Send-Pushover -ParameterName Sound -ScriptBlock $soundsCompleter diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..30630ee --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,64 @@ +site_name: PSPushover +site_description: Send notifications to any device from PowerShell using pushover.net +site_dir: Output/site +repo_url: https://github.com/joshooaj/PSPushover +remote_branch: gh-pages + +theme: + name: material + icon: + repo: material/github + palette: + - scheme: default + toggle: + icon: material/toggle-switch-off-outline + name: Dark mode + - scheme: slate + toggle: + icon: material/toggle-switch + name: Light mode + +plugins: + - search + - awesome-pages + - privacy + +markdown_extensions: + - attr_list + - admonition + - md_in_html + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + - pymdownx.highlight: + linenums_style: pymdownx-inline + anchor_linenums: true + line_spans: __span + pygments_lang_class: true + - pymdownx.inlinehilite + - pymdownx.superfences + - pymdownx.tabbed: + alternate_style: true + combine_header_slug: true + slugify: !!python/object/apply:pymdownx.slugs.slugify + kwds: + case: lower + - pymdownx.tasklist: + custom_checkbox: true + +extra: + social: + - icon: fontawesome/brands/twitter + link: https://twitter.com/joshooaj + name: joshooaj on Twitter + - icon: fontawesome/brands/linkedin + link: https://www.linkedin.com/in/joshooaj + name: joshooaj on LinkedIn + - icon: fontawesome/brands/github + link: https://github.com/joshooaj + name: joshooaj on GitHub + +nav: + - Home: README.md + - Commands: + - ... | flat | en-US/*.md diff --git a/psakeFile.ps1 b/psakeFile.ps1 new file mode 100644 index 0000000..5831161 --- /dev/null +++ b/psakeFile.ps1 @@ -0,0 +1,33 @@ +properties { + & dotnet tool restore + # Set this to $true to create a module with a monolithic PSM1 + $PSBPreference.Build.CompileModule = $true + $PSBPreference.Docs.RootDir = './docs' + $PSBPreference.General.ModuleVersion = (dotnet nbgv get-version -f json | ConvertFrom-Json).NuGetPackageVersion + $PSBPreference.Help.DefaultLocale = 'en-US' + $PSBPreference.Test.OutputFile = 'out/testResults.xml' + $PSBPreference.Test.ScriptAnalysis.SettingsPath = Join-Path $psake.build_script_dir 'PSScriptAnalyzerSettings.psd1' + $psake.context.tasks.stagefiles.PostAction = { + $outputManifestPath = [io.path]::Combine($PSBPreference.Build.ModuleOutDir, "$($PSBPreference.General.ModuleName).psd1") + Update-Metadata -Path $outputManifestPath -PropertyName ModuleVersion -Value $PSBPreference.General.ModuleVersion + } +} + +task Default -depends Test +task Build -FromModule PowerShellBuild -minimumVersion '0.6.1' +task Test -FromModule PowerShellBuild -minimumVersion '0.6.1' + +task Serve -depends Build { + if ($null -eq (Get-Command mkdocs -ErrorAction SilentlyContinue)) { + throw "Cannot find the 'mkdocs' command. Install python and mkdocs, or consider using the dev container." + } + exec { + mkdocs serve -a 0.0.0.0:8000 + } +} + +task PublishDocs -depends Build { + exec { + docker run -v "$($psake.build_script_dir)`:/docs" -e 'CI=true' --entrypoint 'sh' squidfunk/mkdocs-material:latest -c 'pip install -r requirements.txt && mkdocs gh-deploy --force' + } +} diff --git a/requirements.psd1 b/requirements.psd1 new file mode 100644 index 0000000..0d05389 --- /dev/null +++ b/requirements.psd1 @@ -0,0 +1,35 @@ +@{ + PSDepend = @{ + Version = '0.3.8' + } + PSDependOptions = @{ + Target = 'CurrentUser' + } + 'Pester' = @{ + Version = '5.5.0' + Parameters = @{ + SkipPublisherCheck = $true + } + } + 'psake' = @{ + Version = '4.9.0' + } + 'BuildHelpers' = @{ + Version = '2.0.16' + } + 'PowerShellBuild' = @{ + Version = '0.6.1' + } + 'PSScriptAnalyzer' = @{ + Version = '1.21.0' + } + 'PythonRequirements' = @{ + DependencyType = 'Command' + Source = 'pip install -qr requirements.txt' + } + 'DotnetCLI' = @{ + DependencyType = 'DotnetSdk' + Version = '8.0.200' + Target = './.dotnet/' + } +} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..94b85f6 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +# This file defines python requirements to be installed with pip. + +mkdocs~=1.5 +mkdocs-material~=9.5 +mkdocs-awesome-pages-plugin~=2.9 diff --git a/tests/Help.tests.ps1 b/tests/Help.tests.ps1 new file mode 100644 index 0000000..d5de0d3 --- /dev/null +++ b/tests/Help.tests.ps1 @@ -0,0 +1,113 @@ +# Taken with love from @juneb_get_help (https://raw.githubusercontent.com/juneb/PesterTDD/master/Module.Help.Tests.ps1) + +BeforeDiscovery { + + function global:FilterOutCommonParams { + param ($Params) + $commonParams = @( + 'Debug', 'ErrorAction', 'ErrorVariable', 'InformationAction', 'InformationVariable', + 'OutBuffer', 'OutVariable', 'PipelineVariable', 'Verbose', 'WarningAction', + 'WarningVariable', 'Confirm', 'Whatif' + ) + $params | Where-Object { $_.Name -notin $commonParams } | Sort-Object -Property Name -Unique + } + + $outputModVerManifest = Join-Path -Path $env:BHBuildOutput -ChildPath "$($env:BHProjectName).psd1" + + # Get module commands + # Remove all versions of the module from the session. Pester can't handle multiple versions. + Get-Module $env:BHProjectName | Remove-Module -Force -ErrorAction Ignore + Import-Module -Name $outputModVerManifest -Verbose:$false -ErrorAction Stop + $params = @{ + Module = (Get-Module $env:BHProjectName) + CommandType = [System.Management.Automation.CommandTypes[]]'Cmdlet, Function' # Not alias + } + if ($PSVersionTable.PSVersion.Major -lt 6) { + $params.CommandType[0] += 'Workflow' + } + $commands = Get-Command @params + + ## When testing help, remember that help is cached at the beginning of each session. + ## To test, restart session. +} + +Describe "Test help for <_.Name>" -ForEach $commands { + + BeforeDiscovery { + # Get command help, parameters, and links + $command = $_ + $commandHelp = Get-Help $command.Name -ErrorAction SilentlyContinue + $commandParameters = global:FilterOutCommonParams -Params $command.ParameterSets.Parameters + $commandParameterNames = $commandParameters.Name + $helpLinks = $commandHelp.relatedLinks.navigationLink.uri + } + + BeforeAll { + # These vars are needed in both discovery and test phases so we need to duplicate them here + $command = $_ + $commandName = $_.Name + $commandHelp = Get-Help $command.Name -ErrorAction SilentlyContinue + $commandParameters = global:FilterOutCommonParams -Params $command.ParameterSets.Parameters + $commandParameterNames = $commandParameters.Name + $helpParameters = global:FilterOutCommonParams -Params $commandHelp.Parameters.Parameter + $helpParameterNames = $helpParameters.Name + } + + # If help is not found, synopsis in auto-generated help is the syntax diagram + It 'Help is not auto-generated' { + $commandHelp.Synopsis | Should -Not -BeLike '*`[``]*' + } + + # Should be a description for every function + It "Has description" { + $commandHelp.Description | Should -Not -BeNullOrEmpty + } + + # Should be at least one example + It "Has example code" { + ($commandHelp.Examples.Example | Select-Object -First 1).Code | Should -Not -BeNullOrEmpty + } + + # Should be at least one example description + It "Has example help" { + ($commandHelp.Examples.Example.Remarks | Select-Object -First 1).Text | Should -Not -BeNullOrEmpty + } + + It "Help link <_> is valid" -ForEach $helpLinks { + (Invoke-WebRequest -Uri $_ -UseBasicParsing).StatusCode | Should -Be '200' + } + + Context "Parameter <_.Name>" -Foreach $commandParameters { + + BeforeAll { + $parameter = $_ + $parameterName = $parameter.Name + $parameterHelp = $commandHelp.parameters.parameter | Where-Object Name -eq $parameterName + $parameterHelpType = if ($parameterHelp.ParameterValue) { $parameterHelp.ParameterValue.Trim() } + } + + # Should be a description for every parameter + It "Has description" { + $parameterHelp.Description.Text | Should -Not -BeNullOrEmpty + } + + # Required value in Help should match IsMandatory property of parameter + It "Has correct [mandatory] value" { + $codeMandatory = $_.IsMandatory.toString() + $parameterHelp.Required | Should -Be $codeMandatory + } + + # Parameter type in help should match code + It "Has correct parameter type" { + $parameterHelpType | Should -Be $parameter.ParameterType.Name + } + } + + Context "Test <_> help parameter help for " -Foreach $helpParameterNames { + + # Shouldn't find extra parameters in help. + It "finds help parameter in code: <_>" { + $_ -in $parameterNames | Should -Be $true + } + } +} diff --git a/tests/Manifest.tests.ps1 b/tests/Manifest.tests.ps1 new file mode 100644 index 0000000..546943a --- /dev/null +++ b/tests/Manifest.tests.ps1 @@ -0,0 +1,69 @@ +BeforeAll { + + # NEW: Pre-Specify RegEx Matching Patterns + $gitTagMatchRegEx = 'tag:\s?.(\d+(\.\d+)*)' # NOTE - was 'tag:\s*(\d+(?:\.\d+)*)' previously + + $moduleName = $env:BHProjectName + $outputManifestPath = Join-Path -Path $env:BHBuildOutput -ChildPath "$($env:BHProjectName).psd1" + $manifestData = Test-ModuleManifest -Path $outputManifestPath -Verbose:$false -ErrorAction Stop -WarningAction SilentlyContinue + + $script:manifest = $null +} +Describe 'Module manifest' { + + Context 'Validation' { + + It 'Has a valid manifest' { + $manifestData | Should -Not -BeNullOrEmpty + } + + It 'Has a valid name in the manifest' { + $manifestData.Name | Should -Be $moduleName + } + + It 'Has a valid root module' { + $manifestData.RootModule | Should -Be "$($moduleName).psm1" + } + + It 'Has a valid version in the manifest' { + $manifestData.Version -as [Version] | Should -Not -BeNullOrEmpty + } + + It 'Has a valid description' { + $manifestData.Description | Should -Not -BeNullOrEmpty + } + + It 'Has a valid author' { + $manifestData.Author | Should -Not -BeNullOrEmpty + } + + It 'Has a valid guid' { + {[guid]::Parse($manifestData.Guid)} | Should -Not -Throw + } + + It 'Has a valid copyright' { + $manifestData.CopyRight | Should -Not -BeNullOrEmpty + } + } +} + +Describe 'Git tagging' -Skip { + BeforeAll { + $gitTagVersion = $null + + # Ensure to only pull in a single git executable (in case multiple git's are found on path). + if ($git = (Get-Command git -CommandType Application -ErrorAction SilentlyContinue)[0]) { + $thisCommit = & $git log --decorate --oneline HEAD~1..HEAD + if ($thisCommit -match $gitTagMatchRegEx) { $gitTagVersion = $matches[1] } + } + } + + It 'Is tagged with a valid version' { + $gitTagVersion | Should -Not -BeNullOrEmpty + $gitTagVersion -as [Version] | Should -Not -BeNullOrEmpty + } + + It 'Matches manifest version' { + $manifestData.Version -as [Version] | Should -Be ( $gitTagVersion -as [Version]) + } +} diff --git a/tests/Meta.tests.ps1 b/tests/Meta.tests.ps1 new file mode 100644 index 0000000..ad98403 --- /dev/null +++ b/tests/Meta.tests.ps1 @@ -0,0 +1,50 @@ +BeforeAll { + + Set-StrictMode -Version latest + + # Make sure MetaFixers.psm1 is loaded - it contains Get-TextFilesList + Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath 'MetaFixers.psm1') -Verbose:$false -Force + + $projectRoot = $ENV:BHProjectPath + if (-not $projectRoot) { + $projectRoot = $PSScriptRoot + } + + $allTextFiles = Get-TextFilesList $projectRoot + $unicodeFilesCount = 0 + $totalTabsCount = 0 + foreach ($textFile in $allTextFiles) { + if (Test-FileUnicode $textFile) { + $unicodeFilesCount++ + Write-Warning ( + "File $($textFile.FullName) contains 0x00 bytes." + + " It probably uses Unicode/UTF-16 and needs to be converted to UTF-8." + + " Use Fixer 'Get-UnicodeFilesList `$pwd | ConvertTo-UTF8'." + ) + } + $unicodeFilesCount | Should -Be 0 + + $fileName = $textFile.FullName + (Get-Content $fileName -Raw) | Select-String "`t" | Foreach-Object { + Write-Warning ( + "There are tabs in $fileName." + + " Use Fixer 'Get-TextFilesList `$pwd | ConvertTo-SpaceIndentation'." + ) + $totalTabsCount++ + } + } +} + +Describe 'Text files formatting' { + Context 'File encoding' { + It "No text file uses Unicode/UTF-16 encoding" { + $unicodeFilesCount | Should -Be 0 + } + } + + Context 'Indentations' { + It "No text file use tabs for indentations" { + $totalTabsCount | Should -Be 0 + } + } +} diff --git a/tests/MetaFixers.psm1 b/tests/MetaFixers.psm1 new file mode 100644 index 0000000..6cee7fd --- /dev/null +++ b/tests/MetaFixers.psm1 @@ -0,0 +1,80 @@ +# Taken with love from https://github.com/PowerShell/DscResource.Tests/blob/master/MetaFixers.psm1 + +<# + This module helps fix problems, found by Meta.Tests.ps1 +#> + +$ErrorActionPreference = 'stop' +Set-StrictMode -Version latest + +function ConvertTo-UTF8() { + [CmdletBinding()] + [OutputType([void])] + param( + [Parameter(Mandatory, ValueFromPipeline)] + [System.IO.FileInfo]$FileInfo + ) + + process { + $content = Get-Content -Raw -Encoding Unicode -Path $FileInfo.FullName + [System.IO.File]::WriteAllText($FileInfo.FullName, $content, [System.Text.Encoding]::UTF8) + } +} + +function ConvertTo-SpaceIndentation() { + [CmdletBinding()] + [OutputType([void])] + param( + [Parameter(Mandatory, ValueFromPipeline)] + [IO.FileInfo]$FileInfo + ) + + process { + $content = (Get-Content -Raw -Path $FileInfo.FullName) -replace "`t", ' ' + [IO.File]::WriteAllText($FileInfo.FullName, $content) + } +} + +function Get-TextFilesList { + [CmdletBinding()] + [OutputType([IO.FileInfo])] + param( + [Parameter(Mandatory, ValueFromPipeline)] + [string]$Root + ) + + begin { + $txtFileExtentions = @('.gitignore', '.gitattributes', '.ps1', '.psm1', '.psd1', '.json', '.xml', '.cmd', '.mof') + } + + process { + Get-ChildItem -Path $Root -File -Recurse | + Where-Object { $_.Extension -in $txtFileExtentions } + } +} + +function Test-FileUnicode { + [CmdletBinding()] + [OutputType([bool])] + param( + [Parameter(Mandatory, ValueFromPipeline)] + [IO.FileInfo]$FileInfo + ) + + process { + $bytes = [IO.File]::ReadAllBytes($FileInfo.FullName) + $zeroBytes = @($bytes -eq 0) + return [bool]$zeroBytes.Length + } +} + +function Get-UnicodeFilesList() { + [CmdletBinding()] + [OutputType([IO.FileInfo])] + param( + [Parameter(Mandatory)] + [string]$Root + ) + + $root | Get-TextFilesList | Where-Object { Test-FileUnicode $_ } +} diff --git a/tests/ScriptAnalyzerSettings.psd1 b/tests/ScriptAnalyzerSettings.psd1 new file mode 100644 index 0000000..4bab713 --- /dev/null +++ b/tests/ScriptAnalyzerSettings.psd1 @@ -0,0 +1,3 @@ +@{ + +} diff --git a/version.json b/version.json new file mode 100644 index 0000000..7ed6af1 --- /dev/null +++ b/version.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1", + "publicReleaseRefSpec": [ + "^refs/heads/main$", + "^refs/heads/v\\d+(?:\\.\\d+)?$" + ], + "cloudBuild": { + "buildNumber": { + "enabled": true + }, + "setVersionVariables": true + }, + "release": { + "tagName": "v{version}", + "branchName": "v{version}", + "versionIncrement": "minor", + "firstUnstableTag": "alpha" + } +}