Skip to content

Commit 5655eb7

Browse files
Merge pull request #9 from PowerShellWeb/Neocities-PowerShell
Neocities 0.1
2 parents 484702d + 41d71c7 commit 5655eb7

39 files changed

+1881
-1
lines changed

.github/FUNDING.yml

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
github: [StartAutomating]

.github/workflows/Build.yml

+512
Large diffs are not rendered by default.

Build/GitHub/Jobs/BuildNeocities.psd1

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
@{
2+
"runs-on" = "ubuntu-latest"
3+
if = '${{ success() }}'
4+
steps = @(
5+
@{
6+
name = 'Check out repository'
7+
uses = 'actions/checkout@v2'
8+
},
9+
@{
10+
name = 'GitLogger'
11+
uses = 'GitLogging/GitLoggerAction@main'
12+
id = 'GitLogger'
13+
},
14+
@{
15+
name = 'Use PSSVG Action'
16+
uses = 'StartAutomating/PSSVG@main'
17+
id = 'PSSVG'
18+
},
19+
@{
20+
name = 'Use PipeScript Action'
21+
uses = 'StartAutomating/PipeScript@main'
22+
id = 'PipeScript'
23+
},
24+
'RunEZOut',
25+
'RunHelpOut',
26+
@{
27+
name = 'Use PSJekyll Action'
28+
uses = 'PowerShellWeb/PSJekyll@main'
29+
id = 'PSJekyll'
30+
}
31+
<#@{
32+
name = 'Run WebSocket (on branch)'
33+
if = '${{github.ref_name != ''main''}}'
34+
uses = './'
35+
id = 'WebSocketAction'
36+
},#>
37+
# 'BuildAndPublishContainer'
38+
)
39+
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@{
2+
name = 'PublishTestResults'
3+
uses = 'actions/upload-artifact@main'
4+
with = @{
5+
name = 'PesterResults'
6+
path = '**.TestResults.xml'
7+
}
8+
if = '${{always()}}'
9+
}
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#requires -Module PSDevOps
2+
Import-BuildStep -SourcePath (
3+
Join-Path $PSScriptRoot 'GitHub'
4+
) -BuildSystem GitHubWorkflow
5+
6+
Push-Location ($PSScriptRoot | Split-Path)
7+
8+
New-GitHubWorkflow -Name "Build Module" -On Push,
9+
PullRequest, Demand -Job TestPowerShellOnLinux,
10+
TagReleaseAndPublish, BuildNeocities -Environment ([Ordered]@{
11+
REGISTRY = 'ghcr.io'
12+
IMAGE_NAME = '${{ github.repository }}'
13+
}) -OutputPath .\.github\workflows\Build.yml
14+
15+
Pop-Location

Build/Neocities.HelpOut.ps1

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#requires -Module HelpOut
2+
3+
#region Load the Module
4+
$ModuleName = 'Neocities'
5+
Push-Location ($PSScriptRoot | Split-Path)
6+
if (-not (Get-Module $ModuleName)) {
7+
Import-Module .\ -Global -PassThru | Out-Host
8+
}
9+
#endregion Load the Module
10+
11+
# This will save the MarkdownHelp to the docs folder, and output all of the files created.
12+
Save-MarkdownHelp -PassThru -Module $ModuleName -ExcludeCommandType Alias
13+
14+
Pop-Location

Build/Neocities.ezout.ps1

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#requires -Module EZOut
2+
# Install-Module EZOut or https://github.com/StartAutomating/EZOut
3+
$myFile = $MyInvocation.MyCommand.ScriptBlock.File
4+
$myRoot = $myFile | Split-Path | Split-Path
5+
$myModuleName = $myFile | Split-Path | Split-Path | Split-Path -Leaf
6+
Push-Location $myRoot
7+
$formatting = @(
8+
# Add your own Write-FormatView here,
9+
# or put them in a Formatting or Views directory
10+
foreach ($potentialDirectory in 'Formatting','Views','Types') {
11+
Join-Path $myRoot $potentialDirectory |
12+
Get-ChildItem -ea ignore |
13+
Import-FormatView -FilePath {$_.Fullname}
14+
}
15+
)
16+
17+
$destinationRoot = $myRoot
18+
19+
if ($formatting) {
20+
$myFormatFilePath = Join-Path $destinationRoot "$myModuleName.format.ps1xml"
21+
# You can also output to multiple paths by passing a hashtable to -OutputPath.
22+
$formatting | Out-FormatData -Module $MyModuleName -OutputPath $myFormatFilePath
23+
}
24+
25+
$types = @(
26+
# Add your own Write-TypeView statements here
27+
# or declare them in the 'Types' directory
28+
Join-Path $myRoot Types |
29+
Get-Item -ea ignore |
30+
Import-TypeView
31+
32+
)
33+
34+
if ($types) {
35+
$myTypesFilePath = Join-Path $destinationRoot "$myModuleName.types.ps1xml"
36+
# You can also output to multiple paths by passing a hashtable to -OutputPath.
37+
$types | Out-TypeData -OutputPath $myTypesFilePath
38+
}
39+
Pop-Location

Commands/Connect-Neocities.ps1

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
function Connect-Neocities
2+
{
3+
<#
4+
.SYNOPSIS
5+
Connect to Neocities
6+
.DESCRIPTION
7+
Connect to Neocities using a credential object.
8+
9+
This will create a session that can be used to authenticate to the Neocities API.
10+
.LINK
11+
Get-Neocities
12+
#>
13+
param(
14+
# The Neocities credential
15+
[Parameter(ValueFromPipelineByPropertyName)]
16+
[Alias(
17+
'Credentials', # Plural aliases are nice
18+
'PSCredential', # so are parameters that match the type name.
19+
'NeocitiesCredential', # A contextual alias is a good idea, too.
20+
'NeocitiesCredentials' # And you may need to pluralize that contextual alias.
21+
)]
22+
[PSCredential]
23+
$Credential
24+
)
25+
26+
begin {
27+
$NeocitiesApi = "https://neocities.org/api"
28+
}
29+
30+
process {
31+
Invoke-RestMethod -Uri ($NeocitiesApi,'key' -join '/') -Credential $Credential -Authentication Basic
32+
}
33+
}

Commands/Get-Neocities.ps1

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
function Get-Neocities
2+
{
3+
<#
4+
.SYNOPSIS
5+
Gets neocities information
6+
.DESCRIPTION
7+
Gets neocities information from the neocities API, or lists the files in your neocities site.
8+
.EXAMPLE
9+
Get-Neocities
10+
.EXAMPLE
11+
Get-Neocities -Credential $neocitiesCredential
12+
.EXAMPLE
13+
Get-Neocities -List
14+
#>
15+
[Alias('neocities')]
16+
[CmdletBinding(DefaultParameterSetName='info')]
17+
param(
18+
# If set, will list the files in your neocities site
19+
[Parameter(Mandatory,ValueFromPipelineByPropertyName,ParameterSetName='list')]
20+
[switch]
21+
$List,
22+
23+
# The credential used to connect.
24+
# This only needs to be provided once per module session
25+
# (every time the module is imported)
26+
[Parameter(ValueFromPipelineByPropertyName)]
27+
[Alias(
28+
'Credentials', # Plural aliases are nice
29+
'PSCredential', # so are parameters that match the type name.
30+
'NeocitiesCredential', # A contextual alias is a good idea, too.
31+
'NeocitiesCredentials' # And you may need to pluralize that contextual alias.
32+
)]
33+
[PSCredential]
34+
$Credential,
35+
36+
# The access token used to connect.
37+
# This only needs to be provided once per module session
38+
# (every time the module is imported)
39+
[Parameter(ValueFromPipelineByPropertyName)]
40+
[string]
41+
$AccessToken
42+
)
43+
44+
begin {
45+
$NeocitiesApi = "https://neocities.org/api"
46+
}
47+
48+
process {
49+
# The parameter set name contains the route
50+
$parameterSet = $PSCmdlet.ParameterSetName
51+
# and we want to use this to decorate all returned values with a type name
52+
$psuedoNamespace = "neocities"
53+
$pseudoType = "$parameterSet"
54+
# Start by constructing the parameters for Invoke-RestMethod
55+
$InvokeSplat = [Ordered]@{
56+
Uri = "$NeocitiesApi", $PSCmdlet.ParameterSetName -join '/'
57+
}
58+
59+
# If an access token was provided
60+
if ($AccessToken)
61+
{
62+
# use it
63+
$InvokeSplat.Headers = @{Authorization = "Bearer $AccessToken"}
64+
# and cache it for later use
65+
$script:NeocitiesAccessToken = $AccessToken
66+
}
67+
elseif ($Credential)
68+
{
69+
# If a credential was provided, use it
70+
$InvokeSplat.Credential = $Credential
71+
# and cache it for later use
72+
$script:NeoCitiesCredential = $Credential
73+
# (don't forget to set authentication to basic)
74+
$InvokeSplat.Authentication = 'Basic'
75+
}
76+
elseif ($script:NeocitiesAccessToken) {
77+
# If we had a cached access token, use it
78+
$InvokeSplat.Headers = @{Authorization = "Bearer $($script:NeocitiesAccessToken)"}
79+
}
80+
elseif ($script:NeoCitiesCredential) {
81+
# If we had a cached credential, use it
82+
$InvokeSplat.Credential = $script:NeoCitiesCredential
83+
# and don't forget to set authentication to basic.
84+
$InvokeSplat.Authentication = 'Basic'
85+
}
86+
87+
# If neither an access token nor a credential was provided, we can't do anything.
88+
if (-not $InvokeSplat.Credential -and -not $InvokeSplat.Headers)
89+
{
90+
# so error out.
91+
Write-Error "No -Credential provided"
92+
return
93+
}
94+
95+
96+
# Write a little verbose message to let the user know what we're doing
97+
Write-Verbose "Requesting $($InvokeSplat.Uri)"
98+
# and get a response from neocities.
99+
$neocitiesResponse = Invoke-RestMethod @InvokeSplat
100+
switch ($parameterSet) {
101+
info {
102+
# If we're getting info, we want to return the info object
103+
$neocitiesResponse = $neocitiesResponse.info
104+
}
105+
list {
106+
# If we're listing files, we want to return the files object
107+
$neocitiesResponse = @($neocitiesResponse.files)
108+
# and we want to return each as a 'file', not a 'list'
109+
$pseudoType = 'file'
110+
}
111+
}
112+
113+
# Go over each response
114+
foreach ($neoResponse in $neocitiesResponse) {
115+
# and decorate them with the type name
116+
$neoResponse.pstypenames.clear()
117+
$neoResponse.pstypenames.insert(0, ($psuedoNamespace, $pseudoType -join '.'))
118+
# and output the response.
119+
$neoResponse
120+
}
121+
}
122+
}

Commands/Remove-Neocities.ps1

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
function Remove-Neocities
2+
{
3+
<#
4+
.SYNOPSIS
5+
Removes files from neocities
6+
.DESCRIPTION
7+
Removes files from a neocities site using the neocities API.
8+
#>
9+
[CmdletBinding(DefaultParameterSetName='delete',SupportsShouldProcess,ConfirmImpact='High')]
10+
param(
11+
# The name of the file to remove.
12+
[Parameter(Mandatory,ValueFromPipelineByPropertyName)]
13+
[Alias('FullName','Path')]
14+
[string[]]
15+
$FileName,
16+
17+
18+
# The neocities credential
19+
[Parameter(ValueFromPipelineByPropertyName)]
20+
[Alias(
21+
'Credentials', # Plural aliases are nice
22+
'PSCredential', # so are parameters that match the type name.
23+
'NeocitiesCredential', # A contextual alias is a good idea, too.
24+
'NeocitiesCredentials' # And you may need to pluralize that contextual alias.
25+
)]
26+
[PSCredential]
27+
$Credential,
28+
29+
# The neocities access token.
30+
[Parameter(ValueFromPipelineByPropertyName)]
31+
[string]
32+
$AccessToken
33+
)
34+
35+
begin {
36+
$NeocitiesApi = "https://neocities.org/api"
37+
}
38+
39+
process {
40+
$parameterSet = $PSCmdlet.ParameterSetName
41+
$psuedoNamespace = "neocities"
42+
$pseudoType = "$parameterSet"
43+
$InvokeSplat = [Ordered]@{
44+
Uri = "$NeocitiesApi", $PSCmdlet.ParameterSetName -join '/'
45+
Method = 'POST'
46+
}
47+
48+
# If an access token was provided
49+
if ($AccessToken)
50+
{
51+
# use it
52+
$InvokeSplat.Headers = @{Authorization = "Bearer $AccessToken"}
53+
# and cache it for later use
54+
$script:NeocitiesAccessToken = $AccessToken
55+
}
56+
elseif ($Credential)
57+
{
58+
# If a credential was provided, use it
59+
$InvokeSplat.Credential = $Credential
60+
# and cache it for later use
61+
$script:NeoCitiesCredential = $Credential
62+
# (don't forget to set authentication to basic)
63+
$InvokeSplat.Authentication = 'Basic'
64+
}
65+
elseif ($script:NeocitiesAccessToken) {
66+
# If we had a cached access token, use it
67+
$InvokeSplat.Headers = @{Authorization = "Bearer $($script:NeocitiesAccessToken)"}
68+
}
69+
elseif ($script:NeoCitiesCredential) {
70+
# If we had a cached credential, use it
71+
$InvokeSplat.Credential = $script:NeoCitiesCredential
72+
# and don't forget to set authentication to basic.
73+
$InvokeSplat.Authentication = 'Basic'
74+
}
75+
76+
# If neither an access token nor a credential was provided, we can't do anything.
77+
if (-not $InvokeSplat.Credential -and -not $InvokeSplat.Headers)
78+
{
79+
# so error out.
80+
Write-Error "No -Credential provided"
81+
return
82+
}
83+
84+
# For every file name provided, we need to remove it from the neocities site.
85+
foreach ($file in $fileName) {
86+
# Despite the name taking an array, we need to remove one file at a time.
87+
$InvokeSplat.Body =
88+
[web.httputility]::UrlEncode("filenames[]"),'=',[web.httputility]::UrlEncode($file) -join ''
89+
Write-Verbose "Requesting $($InvokeSplat.Uri)"
90+
# If -WhatIf was specified, we need to remove the credential and headers from the splat
91+
if ($WhatIfPreference) {
92+
$splatCopy = [Ordered]@{} + $InvokeSplat
93+
$splatCopy.Remove('Credential')
94+
$splatCopy.Remove('Headers')
95+
# and then output the splat to the pipeline
96+
$splatCopy
97+
continue
98+
}
99+
# If we did not confirm the deletion
100+
if (-not $PSCmdlet.ShouldProcess("Delete $file")) {
101+
# skip it.
102+
continue
103+
}
104+
105+
# Get the response from neocities.
106+
$neocitiesResponse = Invoke-RestMethod @InvokeSplat
107+
# and decorate any response so that we know it was a deletion.
108+
foreach ($neoResponse in $neocitiesResponse) {
109+
$neoResponse.pstypenames.clear()
110+
$neoResponse.pstypenames.insert(0, ($psuedoNamespace, $pseudoType -join '.'))
111+
$neoResponse
112+
}
113+
}
114+
}
115+
}

0 commit comments

Comments
 (0)