PoshCode Logo PowerShell Code Repository

DekiWiki Module 1.5 (modification of post by view diff)
embed code: <script type="text/javascript" src="http://PoshCode.org/embed/692"></script>download | new post

The first of many script cmdlets for working with DekiWiki
Depends on the HttpRest script-module: http://poshcode.org/691

  1. ## DekiWiki Module 1.5
  2. #require -version 2.0
  3. ## Depends on the HttpRest script-module:
  4. ##              http :// huddledmasses.org/using-rest-apis-from-powershell-with-the-dream-sdk/
  5. ####################################################################################################
  6. ## The first of many script cmdlets for working with DekiWiki, based on the HttpREST module
  7. ##
  8. ## For documentation of the DekiWiki REST API:
  9. ## http :// wiki.developer.mindtouch.com/MindTouch_Deki/API_Reference
  10. ####################################################################################################
  11. ## USAGE:
  12. ##   Add-Module DekiWiki
  13. ##   Set-DekiUrl http`://powershell.wik.is
  14. ##   ...
  15. ## ## For usage of each cmdlet, see the comments above each individual function ## ## ## ## ## ## ##
  16. ####################################################################################################
  17. ## History:
  18. ## v 1.5 Rewrite with the "Dream" specific code extracted to the HttpRest module
  19. ## v 1.2 Remove-DekiFile
  20. ## v 1.0 Set-DekiCredential, Get-DekiContent, Set-DekiContent, New-DekiContent, Set-DekiFile
  21. ##
  22. $hr = Add-Module HttpRest -Passthru
  23. Add-Module "$PSScriptRoot\Utilities.ps1"
  24.  
  25. $url = "http://powershell.wik.is"
  26. $api = "$url/@api/deki"
  27.  
  28. #New-Alias Set-DekiCredential Set-HttpCredential -EA "SilentlyContinue"
  29. #New-Alias Set-DekiUrl Set-HttpDefaultUrl -EA "SilentlyContinue"
  30.  
  31. FUNCTION Set-DekiUrl {
  32.    PARAM ([uri]$baseUri=$(Read-Host "Please enter the base Uri for your RESTful web-service"))
  33.    Set-HttpDefaultUrl $baseUri
  34. }
  35.  
  36. FUNCTION Set-DekiCredential {
  37.    PARAM($Credential=$(Get-Credential -Title "Http Authentication Request - $($global:url.Host)" `
  38.                                       -Message "Your login for $($global:url.Host)" `
  39.                                       -Domain $global:url.Host ))
  40.    Set-HttpCredential $Credential
  41. }
  42.  
  43. New-Alias e2 Encode-Twice -EA "SilentlyContinue"
  44.  
  45.  
  46. Add-Type '
  47. public class ModuleInfo {
  48.   public string Name;
  49.   public string[] Author;
  50.   public string CompanyName;
  51.   public string[] Copyright;
  52.   public string[] Description;
  53.   public System.Version ModuleVersion;
  54.   public string[] RequiredAssemblies;
  55.   public string[] Dependencies;
  56.   public System.Guid GUID = System.Guid.NewGuid();
  57.   public string[] PowerShellVersion;
  58.   public string[] ModulesToProcess;
  59.   public System.Version CLRVersion;
  60.   public string[] FormatsToProcess;
  61.   public string[] TypesToProcess;
  62.   public string[] OtherItems;
  63.   public string ModuleFile;
  64. }
  65. ' -EA "SilentlyContinue"
  66.  
  67. # Retrieve a sitemap of all the pages in a wiki,
  68. # OR Retrieve all the subpages of a page as a sitemap
  69. # Added by Mark E. Schill
  70. CMDLET Get-DekiSiteMap {
  71. PARAM(
  72.         [Parameter(Position=0, Mandatory=$false)]
  73.         [string]
  74.         $StartPage
  75. ,
  76.         [Parameter(Position=1, Mandatory=$false)]
  77.         [ValidateSet("xml","html","google")]
  78.         [string]
  79.         $Format = "xml"
  80. )
  81.    if($StartPage) {
  82.       Invoke-Http GET "pages/=$(e2 $StartPage)/tree" @{"format"=$format} | Receive-Http -Out Xml
  83.    } else {
  84.       Invoke-Http GET "pages" @{"format"=$format} | Receive-Http -Out Xml
  85.    }
  86. }
  87.  
  88.  
  89. # Get the contents of a page from a DekiWiki
  90. # Note that by default you retrieve the "view" (rendered) markup
  91. # If you want to see it before the extensions run, you should specify at least -mode viewnoexecute
  92. # If you want to see the source so you can make changes, be sure to specify -mode edit
  93. CMDLET Get-DekiContent {
  94. PARAM(
  95.    [Parameter(Position=0, Mandatory=$true)]
  96.    [string]
  97.    $pageName
  98. ,
  99.    [Parameter(Position=1, Mandatory=$false)]
  100.    [int]
  101.    $section
  102. ,
  103.    [Parameter(Position=5, Mandatory=$false)]
  104.    [ValidateSet("edit", "raw", "view", "viewnoexecute")]
  105.    [string]
  106.    $mode="view"
  107. )
  108.    Invoke-Http "GET" "pages/=$(e2 $pageName)/contents" @{mode=$mode;section=$section} | Receive-Http -Out Xml
  109. }
  110.  
  111. # Get-DekiFile will LIST all files if called with just a PageName
  112. # Otherwise, fileName can be a single fileName, or wildcards
  113. # To download all the attachments on a page, try:
  114. # Get-DekiFile PageName | Get-DekiFile
  115. CMDLET Get-DekiFile {
  116. PARAM(
  117.    [Parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
  118.    [string]
  119.    $pageName
  120. ,
  121.    [Parameter(Position=1, Mandatory=$false, ValueFromPipelineByPropertyName=$true)]
  122.    [string]
  123.    $fileName
  124. ,
  125.    [Parameter(Position=2, Mandatory=$false)]
  126.    [string]
  127.    $destination
  128. )
  129. PROCESS {
  130.    ## Remember, we can get both on the pipeline, so ...
  131.    $files = Invoke-Http "GET" "pages/=$(e2 $pageName)/files" | Receive-Http Xml //file
  132.    
  133.    Write-Verbose "Fetching $($fileName) from the $($files.Count) in $pageName"
  134.    if(!$fileName) {
  135.       ## Add a PageName property, because then you can pipe the output back to Get-DekiFile after filtering...
  136.       write-output $files | Add-Member NoteProperty PageName $pageName -passthru
  137.    } else {
  138.       ## Using -like means $fileName allows globbing
  139.       foreach($file in $($files | where { $_.filename -like $fileName } )) {
  140.          Invoke-Http "GET" "pages/=$(e2 $pageName)/files/=$(e2 $file.filename)" | Receive-Http File $(Get-FileName $file.filename $destination)
  141.       }
  142.    }
  143. }
  144. }
  145.  
  146. # Set the contents of a DekiWiki page
  147. # Note that you can pass the content as an XML document, plain text, or a filename...
  148. CMDLET Set-DekiContent {
  149. PARAM(
  150.    [Parameter(Position=0, Mandatory=$true)]
  151.    [string]
  152.    $pageName
  153. ,
  154.    [Parameter(Position=1, Mandatory=$true,
  155.                           ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
  156.    [Alias("FullName")]
  157.    [string]
  158.    $content
  159. ,
  160.    [Parameter(Position=2, Mandatory=$false)]
  161.    $section
  162. ,
  163.    [switch]$new
  164. ,
  165.    [switch]$append
  166. )
  167.    $with = @{"edittime"=$(Get-UtcTime "yyyyMMddhhmmss")}
  168.    
  169.    if($new) {
  170.       $with.abort = "exists"
  171.    }
  172.    if($append) {
  173.       $with.section = "0"
  174.    } elseif($section) {
  175.       $with.section = $section
  176.    }
  177.  
  178.    $result = Invoke-Http POST "pages/=$(e2 $pageName)/contents" -With $with -Content $content -Auth $true -Wait
  179.    if($result.IsSuccessful) {
  180.       return "$url/$($result | Receive-Http Text //edit/page/path)"
  181.    } else {
  182.       return $result
  183.    }
  184. }
  185.  
  186. # Same as Set-DekiContent, except this one crashes if the page already exists.
  187. # This is technically the only safe way to create new pages without fear of conflicts...
  188. CMDLET New-DekiContent {
  189. PARAM(
  190.    [Parameter(Position=0, Mandatory=$true)]
  191.    [string]$pageName
  192. ,
  193.    [Parameter(Position=1, Mandatory=$true,
  194.               ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
  195.    [Alias("FullName")]
  196.    [string]
  197.    $content
  198. )
  199. PROCESS {
  200.    Set-DekiContent $pageName $content -new
  201. }
  202. }
  203.  
  204. # Add a new attachment (or a new version of an existing attachment)
  205. # You can use wildcards, and specify arrays.  But you could also include descriptions
  206. # USAGE:
  207. ## Set-DekiFile Path/PageName *.ps1,*.psm1
  208. ## Set-DekiFile Path/PageName @{"Neat.jpg"="A really cool screenshot";"Source.zip"="The source code"}
  209. ## Set-DekiFile Path/PageName Something.png
  210. ## ls *.png | Set-DekiFile Path/PageName
  211. CMDLET Set-DekiFile {
  212. param(
  213.    [Parameter(Position=0, Mandatory=$true)]
  214.    [string]$pageName
  215. ,
  216.    [Parameter(Position=1, Mandatory=$true,
  217.               ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
  218.    [Alias("FullName")]
  219.    $Files
  220. )
  221.    # Two ways to specify files: 1) hashtable: file = "description" 1) array: file, file, file
  222.    $hasDescriptions = $false;
  223.    if($files -is [Hashtable]) {
  224.       $hasDescriptions = $true;
  225.       $fileNames = $files.Keys
  226.    } else {
  227.       $fileNames = $files
  228.    }
  229.    
  230.    foreach($fileName in $fileNames) {
  231.       foreach($file in (gci $fileName)) {
  232.          $with = @{}
  233.          if($hasDescriptions) {
  234.             $With.description = $files[$fileName]
  235.          }
  236.  
  237.          $result = Http-Invoke PUT "pages/=$(e2 $pageName)/files/=$($file.Name)" $With $file.FullName -Wait
  238.          if($result.IsSuccessful) {
  239.             return ($result | Receive-Http Text //file/href)
  240.          } else {
  241.             return $result.Response
  242.          }
  243.       }
  244.    }
  245. }
  246.  
  247. ## Move a page from one place to another (leaving an "alias" placeholder)
  248.  
  249. CMDLET Move-DekiContent {
  250. PARAM(
  251.    [Parameter(Position=0, Mandatory=$true)]
  252.    [string]
  253.    $pageName
  254. ,
  255.    [Parameter(Position=1, Mandatory=$true)]
  256.    [string]
  257.    $newPageName
  258. )
  259.    $with = @{"to"="$newPageName"}
  260.    
  261.    $result = Invoke-Http POST "pages/=$(e2 $pageName)/move" -With $with -Auth $true -Wait
  262.    if($result.IsSuccessful) {
  263.       return "$url/$($result | Receive-Http Text '//page[1]/path' )"
  264.    } else {
  265.       return $result
  266.    }
  267. }
  268.  
  269. CMDLET New-DekiAlias {
  270. PARAM(
  271.    [Parameter(Position=0, Mandatory=$true)]
  272.    [string]
  273.    $pageName
  274. ,
  275.    [Parameter(Position=1, Mandatory=$true)]
  276.    [string]
  277.    $Alias
  278. )
  279.  
  280.    $result = Invoke-Http POST "pages/=$(e2 $pageName)/move" @{"to"="$Alias"} -Auth $true -Wait
  281.    if($result.IsSuccessful) {
  282.       $aliasPage = "$url/$($result | Receive-Http Text '//page[1]/path' )"
  283.       $result = Invoke-Http POST "pages/=$(e2 $Alias)/move" @{"to"="$pageName"} -Auth $true -Wait
  284.       if($result.IsSuccessful) {
  285.          return $aliasPage
  286.       } else {
  287.          return $result
  288.       }
  289.    } else {
  290.       return $result
  291.    }
  292. }
  293.  
  294. # Delete a page from a dekiwiki, with an option to RECURSIVELY delete all child pages.
  295. # NOTE: if you delete a page that has children, and don't recurse, the contents are removed
  296. #       and then replaced with template text, because they can't go away completely
  297. # NOTE: if you delete a page, it is actually put in the archive
  298. # TODO: add a -Force parameter to allow them to be permanently deleted from the archive
  299. CMDLET Remove-DekiContent {
  300. PARAM(
  301.    [Parameter(Position=0, Mandatory=$true,ValueFromPipelineByPropertyName=$true)][string]$pageName
  302. ,
  303.    [Parameter(Position=2, Mandatory=$false)][switch]$recurse
  304. )
  305.  
  306.    Http-Invoke DELETE "pages/=$(e2 $pageName)" @{recursive=$($recurse.ToBool())}
  307.    if($result.IsSuccessful) {
  308.       return "DELETED $url/$PageName"
  309.    } else {
  310.       return $result.Response
  311.    }
  312. }
  313.  
  314. # Delete a file attachment from a dekiwiki page
  315. # You can use wildcards, and specify arrays:
  316. ## USAGE:
  317. ## Remove-DekiFile Path/PageName *.ps1,*.psm1
  318. ## Remove-DekiFile Path/PageName Something.png
  319. ## ls *.png | Remove-DekiFile Path/PageName
  320. CMDLET Remove-DekiFile {
  321. PARAM(
  322.    [Parameter(Position=0, Mandatory=$true,ValueFromPipelineByPropertyName=$true)][string]$pageName
  323. ,
  324.    [Parameter(Position=1, Mandatory=$true,
  325.               ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
  326.    [Alias("Name")]
  327.    $fileNames
  328. )
  329.    $files = Invoke-Http GET "pages/=$(e2 $pageName)/files" | Receive-Http Text //file/filename
  330.    foreach($fileName in $fileNames) {
  331.       foreach($file in $($files -like $fileName)) {
  332.          $path = "pages/=$(e2 $pageName)/files/=$(e2 $file)"
  333.          Write-Host $path -fore cyan
  334.          $result = Invoke-Http DELETE $path -Auth $true -Wait
  335.      
  336.          if($result.IsSuccessful) {
  337.             "DELETED: $api/$path"
  338.          } else {
  339.             $result.Response
  340.          }
  341.       }
  342.    }
  343. }
  344.  
  345. Export-ModuleMember Set-DekiCredential, Set-DekiUrl,
  346.                     Get-HtmlHelp, Get-DekiFile, Get-DekiSiteMap, Get-DekiContent,
  347.                     Set-DekiContent, New-DekiContent,
  348.                     Move-DekiContent, New-DekiAlias,
  349.                     Remove-DekiContent, Remove-DekiFile,
  350.                     Set-DekiFile

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me