├── PSReddit.format.ps1xml ├── PSReddit.ps1xml ├── PSReddit.psd1 ├── PSReddit.psm1 ├── PowerReddit_old ├── PowerReddit.format.ps1xml ├── PowerReddit.ps1xml ├── PowerReddit.psd1 └── PowerReddit.psm1 ├── Private ├── Get-DecryptedValue.ps1 └── Show-oAuthWindow.ps1 ├── Public ├── Connect-RedditAccount.ps1 ├── Get-RedditAccount.ps1 ├── Get-RedditComment.ps1 ├── Get-RedditPost.ps1 ├── New-RedditPost.ps1 ├── Refresh-RedditToken.ps1 └── Send-RedditMessage.ps1 ├── README.md ├── img ├── API.png └── Approve.png └── license /PSReddit.format.ps1xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PowerReddit.Link 6 | 7 | PSReddit.Link 8 | 9 | 10 | 11 | 12 | 5 13 | 14 | 15 | 14 16 | 17 | 18 | 18 19 | 20 | 21 | 5 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | id 30 | 31 | 32 | subreddit 33 | 34 | 35 | author 36 | 37 | 38 | score 39 | 40 | 41 | title 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | PSReddit.Comment 51 | 52 | PSReddit.Comment 53 | 54 | 55 | 56 | 57 | 7 58 | 59 | 60 | 18 61 | 62 | 63 | 5 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | id 72 | 73 | 74 | author 75 | 76 | 77 | Score 78 | 79 | 80 | body 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | PSReddit.User 89 | 90 | PSReddit.User 91 | 92 | 93 | 94 | 95 | 7 96 | 97 | 98 | 18 99 | 100 | 101 | 5 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | name 110 | 111 | 112 | created 113 | 114 | 115 | comment_karma 116 | 117 | 118 | link_karma 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /PSReddit.ps1xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | PowerReddit.Link 5 | 6 | 7 | GetComments 8 | 9 | 10 | 11 | OpenUrl 12 | 13 | 14 | 15 | 16 | 17 | PowerReddit.Comment 18 | 19 | 20 | score 21 | 22 | $this.ups - $this.downs 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /PSReddit.psd1: -------------------------------------------------------------------------------- 1 | # 2 | # Module manifest for module 'PowerReddit' 3 | # 4 | 5 | @{ 6 | 7 | # Script module or binary module file associated with this manifest 8 | RootModule = 'PSReddit.psm1' 9 | 10 | # Version number of this module. 11 | ModuleVersion = '1.0' 12 | 13 | # ID used to uniquely identify this module 14 | GUID = '3dede632-fde4-4cc6-85df-9f5cfd6cd124' 15 | 16 | # Author of this module 17 | Author = 'Tobin Jones', 'Stephen Owen' 18 | 19 | # Copyright statement for this module 20 | Copyright = 'Licensed under the MIT license' 21 | 22 | # Description of the functionality provided by this module 23 | Description = 'Browsing and interacting with the Reddit API' 24 | 25 | # Minimum version of the Windows PowerShell engine required by this module 26 | PowerShellVersion = '3.0' 27 | 28 | # Name of the Windows PowerShell host required by this module 29 | # PowerShellHostName = '' 30 | 31 | # Minimum version of the Windows PowerShell host required by this module 32 | # PowerShellHostVersion = '' 33 | 34 | # Minimum version of the .NET Framework required by this module 35 | # DotNetFrameworkVersion = '' 36 | 37 | # Minimum version of the common language runtime (CLR) required by this module 38 | # CLRVersion = '' 39 | 40 | # Processor architecture (None, X86, Amd64) required by this module 41 | # ProcessorArchitecture = '' 42 | 43 | # Modules that must be imported into the global environment prior to importing this module 44 | # RequiredModules = @() 45 | 46 | # Assemblies that must be loaded prior to importing this module 47 | # RequiredAssemblies = @() 48 | 49 | # Script files (.ps1) that are run in the caller's environment prior to importing this module 50 | # ScriptsToProcess = @() 51 | 52 | # Type files (.ps1xml) to be loaded when importing this module 53 | TypesToProcess = @('PSReddit.ps1xml') 54 | 55 | # Format files (.ps1xml) to be loaded when importing this module 56 | FormatsToProcess = @('PSReddit.format.ps1xml') 57 | 58 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 59 | # NestedModules = @() 60 | 61 | # Functions to export from this module 62 | FunctionsToExport = '*' 63 | 64 | # Cmdlets to export from this module 65 | CmdletsToExport = '*' 66 | 67 | # Variables to export from this module 68 | VariablesToExport = '*' 69 | 70 | # Aliases to export from this module 71 | AliasesToExport = '*' 72 | 73 | # Commands to export from this module as Workflows 74 | # ExportAsWorkflow = @() 75 | 76 | # List of all modules packaged with this module 77 | # ModuleList = @() 78 | 79 | # List of all files packaged with this module 80 | # FileList = @() 81 | 82 | # Private data to pass to the module specified in RootModule/ModuleToProcess 83 | # PrivateData = '' 84 | 85 | # HelpInfo URI of this module 86 | # HelpInfoURI = '' 87 | 88 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 89 | # DefaultCommandPrefix = '' 90 | 91 | } 92 | -------------------------------------------------------------------------------- /PSReddit.psm1: -------------------------------------------------------------------------------- 1 | [CmdletBinding()] 2 | #Get public and private function definition files. 3 | $PublicFunction = @( Get-ChildItem -Path $PSScriptRoot\Public\*.ps1 -Exclude *tests* -ErrorAction SilentlyContinue ) 4 | $PrivateFunction = @( Get-ChildItem -Path $PSScriptRoot\Private\*.ps1 -Exclude *tests* -ErrorAction SilentlyContinue ) 5 | 6 | #Dot source the files 7 | Foreach($import in @($PublicFunction + $PrivateFunction)) 8 | { 9 | write-verbose "importing $import" 10 | Try 11 | { 12 | . $import.fullname 13 | } 14 | Catch 15 | { 16 | Write-Error -Message "Failed to import function $($import.fullname): $_" 17 | } 18 | } 19 | 20 | #Initialize our variables. I know, I know... 21 | 22 | $configDir = "$Env:AppData\WindowsPowerShell\Modules\PSReddit\0.1\Config.ps1xml" 23 | $refreshToken = "$Env:AppData\WindowsPowerShell\Modules\PSReddit\0.1\Config.Refresh.ps1xml" 24 | 25 | 26 | Try 27 | { 28 | #Import the config 29 | $password = Import-Clixml -Path $configDir -ErrorAction STOP | ConvertTo-SecureString 30 | 31 | } 32 | catch { 33 | Write-Warning "Corrupt Password file found, rerun with -Force to fix this" 34 | } 35 | 36 | Try 37 | { 38 | #Import the config 39 | 40 | $refreshToken = Import-Clixml -Path $refreshToken -ErrorAction STOP | ConvertTo-SecureString 41 | } 42 | catch { 43 | Write-Warning "Corrupt refresh token file found, rerun with -Force to fix this" 44 | } 45 | 46 | if ($password){Get-DecryptedValue -inputObj $password -name PSReddit_accessToken} 47 | if($refreshToken){Get-DecryptedValue -inputObj $refreshToken -name PSReddit_refreshToken} 48 | 49 | 50 | 51 | # Here I might... 52 | # Read in or create an initial config file and variable 53 | # Export Public functions ($Public.BaseName) for WIP modules 54 | # Set variables visible to the module and its functions only 55 | 56 | Export-ModuleMember -Function $PublicFunction.Basename -------------------------------------------------------------------------------- /PowerReddit_old/PowerReddit.format.ps1xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PowerReddit.Link 6 | 7 | PowerReddit.Link 8 | 9 | 10 | 11 | 12 | 5 13 | 14 | 15 | 14 16 | 17 | 18 | 18 19 | 20 | 21 | 5 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | id 30 | 31 | 32 | subreddit 33 | 34 | 35 | author 36 | 37 | 38 | score 39 | 40 | 41 | title 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | PowerReddit.Comment 51 | 52 | PowerReddit.Comment 53 | 54 | 55 | 56 | 57 | 7 58 | 59 | 60 | 18 61 | 62 | 63 | 5 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | id 72 | 73 | 74 | author 75 | 76 | 77 | Score 78 | 79 | 80 | body 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /PowerReddit_old/PowerReddit.ps1xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | PowerReddit.Link 5 | 6 | 7 | GetComments 8 | 9 | 10 | 11 | OpenUrl 12 | 13 | 14 | 15 | 16 | 17 | PowerReddit.Comment 18 | 19 | 20 | score 21 | 22 | $this.ups - $this.downs 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /PowerReddit_old/PowerReddit.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1RedOne/PSReddit/5d887c04525409d3ff069ca66e29dea39cba9a55/PowerReddit_old/PowerReddit.psd1 -------------------------------------------------------------------------------- /PowerReddit_old/PowerReddit.psm1: -------------------------------------------------------------------------------- 1 | <# 2 | Script Variables 3 | #> 4 | [Microsoft.PowerShell.Commands.WebRequestSession] $script:currentRedditSession; 5 | [Uri] $script:loginUri = [uri] "http://www.reddit.com/api/login" 6 | 7 | 8 | <# 9 | .SYNOPSIS 10 | Authenticates to the Reddit API with provided credentials 11 | 12 | .DESCRIPTION 13 | After running this, all cmdlets will run in the scope of the logged in user 14 | 15 | .PARAMETER Credential 16 | Provide a PSCredential 17 | 18 | #> 19 | function Connect-RedditSession 20 | { 21 | [CmdletBinding()] 22 | Param ( 23 | [Parameter(Position=1, Mandatory=$false, ValueFromPipelineByPropertyName=$true)] 24 | [System.Management.Automation.PSCredential] 25 | $credential 26 | ) 27 | 28 | if( $credential -eq $null ) 29 | { 30 | $credential = Get-Credential -Message "Enter your Reddit login details:" 31 | } 32 | 33 | $userName = $credential.GetNetworkCredential().UserName 34 | $password = $credential.GetNetworkCredential().Password 35 | 36 | $parameters = "user={0}&passwd={1}" -f $userName, $password 37 | $buffer = [System.Text.Encoding]::UTF8.GetBytes($parameters); 38 | 39 | $request = [System.Net.HTTPWebRequest]::Create($script:loginUri) 40 | $request.CookieContainer = New-Object System.Net.CookieContainer 41 | $request.ContentType = "application/x-www-form-urlencoded" 42 | $request.Method = "POST" 43 | $request.ContentLength = $buffer.Length; 44 | 45 | $stream = $request.GetRequestStream() 46 | Try { $stream.Write($buffer, 0, $buffer.Length) } 47 | Finally{ $stream.Dispose() } 48 | 49 | $response = $request.GetResponse() 50 | 51 | $successCookie = $response.Cookies | Where Name -eq 'reddit_session' 52 | 53 | if( $successCookie -eq $null ) 54 | { 55 | Write-Error -Message "Authentication Failed" ` 56 | -Category PermissionDenied ` 57 | -RecommendedAction "Check username and password" 58 | } 59 | else 60 | { 61 | Write-Host "Successfully Authenticated user ""$userName""" 62 | $script:currentRedditSession = New-Object Microsoft.PowerShell.Commands.WebRequestSession 63 | $script:currentRedditSession.Cookies.Add($successCookie) 64 | } 65 | 66 | return $script:currentRedditSession 67 | } 68 | 69 | 70 | <# 71 | .SYNOPSIS 72 | Logs out Reddit session 73 | 74 | .DESCRIPTION 75 | Logs out reddit session by forgetting cookie 76 | 77 | #> 78 | function Disconnect-RedditSession 79 | { 80 | [CmdletBinding()] 81 | Param () 82 | 83 | $script:currentRedditSession = $null 84 | 85 | } 86 | 87 | 88 | <# 89 | .SYNOPSIS 90 | Gets a list of Reddit links 91 | 92 | .DESCRIPTION 93 | Uses the Reddit API to get Reddit links from given subreddit(s) 94 | 95 | .PARAMETER Name 96 | Name of the Subreddit to fetch from. Can be an array. 97 | 98 | #> 99 | function Get-RedditLink 100 | { 101 | [CmdletBinding()] 102 | Param ( 103 | [Parameter(Position=1, Mandatory=$false, ValueFromPipelineByPropertyName=$true)] 104 | [Alias("r","Subreddit")] 105 | [string[]] 106 | $Name = 'frontpage' 107 | ) 108 | 109 | # Construct the Uri. Multiple subreddits can be joined with plusses 110 | $uri = 'http://www.reddit.com/r/{0}.json' -f [string]::Join('+', $Name) 111 | 112 | # Run the RestMethod in the current user context 113 | $response = (Invoke-RestMethod $uri -WebSession $script:currentRedditSession) 114 | 115 | # This is the listing. Contains before/after for pagination, and links 116 | $listing = $response | Where kind -eq 'Listing' | Select -Expand data 117 | 118 | # Links have type "t3" in Reddit API 119 | $links = $listing.children | Where kind -eq 't3' | select -expand data 120 | 121 | # Return the links with a custom type of [PowerReddit.Link]. We do this so 122 | # that they can be extended by psxml files, etc. 123 | $links | %{ $_.PSObject.TypeNames.Insert(0,'PowerReddit.Link'); $_ } 124 | 125 | } 126 | 127 | 128 | <# 129 | .SYNOPSIS 130 | Gets comments of a Reddit link 131 | 132 | .DESCRIPTION 133 | Uses the Reddit API to get comments made on a given link 134 | 135 | .PARAMETER id 136 | Internal id of the Reddit link 137 | 138 | #> 139 | function Get-RedditComment 140 | { 141 | [CmdletBinding()] 142 | Param ( 143 | [Parameter( 144 | Position = 1, 145 | Mandatory = $true, 146 | ValueFromPipelineByPropertyName = $true 147 | )] 148 | [Alias("Link")] 149 | [string] 150 | $id 151 | ) 152 | 153 | Process 154 | { 155 | $uri = 'http://www.reddit.com/comments/{0}.json' -f $id 156 | 157 | $listings = (Invoke-RestMethod $uri) | Where kind -eq 'Listing' 158 | 159 | # Comments have a type 't1' in Reddit API 160 | $comments = $listings | %{ $_.data.children } | Where kind -eq 't1' | Select -Expand data 161 | 162 | $comments | %{ $_.PSObject.TypeNames.Insert(0,'PowerReddit.Comment'); $_ } 163 | } 164 | } 165 | 166 | 167 | <# 168 | .SYNOPSIS 169 | Gets information about the currently logged in user 170 | 171 | .PARAMETER redditSession 172 | An optional session to use (like that returned from Connect-RedditSession) 173 | 174 | #> 175 | function Get-RedditUserInfo 176 | { 177 | [CmdletBinding()] 178 | Param ( 179 | [Parameter( 180 | Position = 1, 181 | Mandatory = $false, 182 | ValueFromPipelineByPropertyName = $true 183 | )] 184 | [Alias("Link")] 185 | [Microsoft.PowerShell.Commands.WebRequestSession] 186 | $redditSession 187 | ) 188 | 189 | if ($redditSession -ne $null) 190 | { 191 | $thisSession = $redditSession 192 | } 193 | elseif ($script:currentRedditSession -ne $null) 194 | { 195 | $thisSession = $script:currentRedditSession 196 | } 197 | else 198 | { 199 | Write-Error -Message "No active session" ` 200 | -Category PermissionDenied ` 201 | -RecommendedAction "Log in or provide a session object" 202 | return 203 | } 204 | 205 | $uri = 'http://www.reddit.com/api/me.json' 206 | $response = (Invoke-RestMethod $uri -WebSession $thisSession) 207 | 208 | $user = $response | Select -Expand data 209 | $user | %{ $_.PSObject.TypeNames.Insert(0,'PowerReddit.User'); $_ } 210 | } 211 | 212 | 213 | <# 214 | Export public functions 215 | #> 216 | Export-ModuleMember -function ` 217 | Get-RedditLink, 218 | Get-RedditComment, 219 | Connect-RedditSession, 220 | Disconnect-RedditSession, 221 | Get-RedditUserInfo 222 | -------------------------------------------------------------------------------- /Private/Get-DecryptedValue.ps1: -------------------------------------------------------------------------------- 1 | Function Get-DecryptedValue{ 2 | param($inputObj,$name) 3 | 4 | $Ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($inputObj) 5 | $result = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($Ptr) 6 | [System.Runtime.InteropServices.Marshal]::ZeroFreeCoTaskMemUnicode($Ptr) 7 | New-Variable -Scope Global -Name $name -Value $result -PassThru -Force 8 | 9 | } -------------------------------------------------------------------------------- /Private/Show-oAuthWindow.ps1: -------------------------------------------------------------------------------- 1 |  #region mini window, made by (Insert credits here) 2 | Function Show-OAuthWindow { 3 | param($url) 4 | Add-Type -AssemblyName System.Windows.Forms 5 | 6 | $form = New-Object -TypeName System.Windows.Forms.Form -Property @{Width=820;Height=920} 7 | $web = New-Object -TypeName System.Windows.Forms.WebBrowser -Property @{Width=800;Height=900;Url=($url -f ($Scope -join "%20")) } 8 | $DocComp = { 9 | $Global:uri = $web.Url.AbsoluteUri 10 | if ($Global:Uri -match "error=[^&]*|code=[^&]*") {$form.Close() } 11 | } 12 | 13 | $web.ScrollBarsEnabled = $false 14 | $web.ScriptErrorsSuppressed = $true 15 | $web.Add_DocumentCompleted($DocComp) 16 | $form.Controls.Add($web) 17 | $form.Add_Shown({$form.Activate()}) 18 | $form.ShowDialog() | Out-Null 19 | } 20 | #endregion 21 | 22 | #login to get an access code -------------------------------------------------------------------------------- /Public/Connect-RedditAccount.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Use this cmdlet to connect to your Reddit account from PowerShell 4 | .DESCRIPTION 5 | Use this cmdlet to connect to your Reddit account from PowerShell.You'll first need to register for an Register for a Reddit API account here, https://www.reddit.com/prefs/apps, and choose a Script based Application. 6 | 7 | Make note of your ClientSecret, ClientID and RedirectURI (which can be anything). This cmdlet displays a login window to allow a user to provision access to their account by means of oAuth. 8 | 9 | The permissions requested are: identity, history, mysubreddits, read, report, save, submit 10 | .EXAMPLE 11 | Connect-RedditAccount -ClientID $ClientID -ClientSecret $ClientSecret -RedirectURI $RedirectURI 12 | .EXAMPLE 13 | Another example of how to use this cmdlet 14 | .INPUTS 15 | Inputs to this cmdlet (if any) 16 | .OUTPUTS 17 | Output from this cmdlet (if any) 18 | .NOTES 19 | You'll first need to register for an Register for a Reddit API account here, https://www.reddit.com/prefs/apps, and choose a Script based Application. Make note of your ClientSecret, ClientID and RedirectURI (which can be anything). 20 | .COMPONENT 21 | The component this cmdlet belongs to 22 | .ROLE 23 | The role this cmdlet belongs to 24 | .FUNCTIONALITY 25 | The functionality that best describes this cmdlet 26 | .LINK 27 | https://www.reddit.com/dev/api 28 | For Reference for the API 29 | https://github.com/1RedOne/PSReddit/ 30 | The project homepage on GitHub 31 | 32 | #> 33 | Function Connect-RedditAccount { 34 | [CmdletBinding()] 35 | param( 36 | $ClientSecret, 37 | $ClientID, 38 | $redirectURI, 39 | [Switch]$force) 40 | 41 | $configDir = "$Env:AppData\WindowsPowerShell\Modules\PSReddit\0.1\Config.ps1xml" 42 | $refreshTokenPath = "$Env:AppData\WindowsPowerShell\Modules\PSReddit\0.1\Config.Refresh.ps1xml" 43 | #look for a stored password 44 | 45 | 46 | if (-not (Test-Path $configDir) -or $force){ 47 | if ($force){Write-verbose "`$force detected"} 48 | #create the file to store our Access Token 49 | Write-Verbose "cached Access Code not found, or the user instructed us to refresh" 50 | 51 | if (-not (Test-Path $refreshTokenPath)){New-item -Force -Path $refreshTokenPath -ItemType file } 52 | New-item -Force -Path "$configDir" -ItemType File 53 | 54 | $guid = [guid]::NewGuid() 55 | $URL = "https://www.reddit.com/api/v1/authorize?client_id=$clientID&response_type=code&state=$GUID&redirect_uri=$redirectURI&duration=permanent&scope=identity,history,mysubreddits,read,report,privatemessages,save,submit" 56 | 57 | #Display an oAuth login prompt for the user to user authorize our application, returns uri 58 | Show-OAuthWindow -url $URL 59 | 60 | #attempt to parse $uri to retrieve our AuthCode 61 | $regex = '(?<=code=)(.*)' 62 | 63 | try {$Reddit_authCode = ($uri | Select-string -pattern $regex).Matches[0].Value} 64 | catch {Write-Warning "did not receive an authCode, check ClientID and RedirectURi" 65 | return} 66 | 67 | $global:Reddit_authCode = $Reddit_authCode 68 | Write-Verbose "Received an authCode, $Reddit_authCode" 69 | 70 | write-debug "Pause here to test value of `$uri" 71 | Write-Verbose "Exchanging authCode for Access Token" 72 | 73 | try { 74 | #reddit uses basic auth, which means in PowerShell that we can provide our creds using a credential object 75 | $secpasswd = ConvertTo-SecureString $ClientSecret -AsPlainText -Force 76 | $credential = New-Object System.Management.Automation.PSCredential ($ClientID, $secpasswd) 77 | 78 | #retrieve Access Token 79 | $result = Invoke-RestMethod https://ssl.reddit.com/api/v1/access_token -Method Post -Body @{client_id=$clientId; state=$guid ; redirect_uri=$redirectURI; grant_type="authorization_code"; code=$Reddit_authCode} -ContentType "application/x-www-form-urlencoded" -ErrorAction STOP -Credential $credential 80 | } 81 | catch { 82 | Write-Warning "Something didn't work, this is normally caused by an internet flub, try again in a few minutes" 83 | Write-debug "Test the -body params for the Rest command" 84 | } 85 | 86 | Write-Debug 'go through the results of $result, looking for our token' 87 | if ($result.access_token){ 88 | Write-Output "Updated Authorization Token" 89 | $global:PSReddit_accessToken = $result.access_token} 90 | 91 | Write-Verbose "Storing token in $configDir" 92 | #store the token 93 | $password = ConvertTo-SecureString $result.access_token -AsPlainText -Force 94 | $password | ConvertFrom-SecureString | Export-Clixml $configDir -Force 95 | 96 | Write-verbose "Storing refresh token in $refreshTokenPath" 97 | $refresh = ConvertTo-SecureString $result.refresh_token -AsPlainText -Force 98 | $refresh | ConvertFrom-SecureString | Export-Clixml $refreshTokenPath -Force 99 | 100 | } 101 | else{ 102 | #if the user did not specify -Force, or if the file path for a stored token already exists 103 | Write-Verbose "We're looking for a stored token in $configDir" 104 | try { 105 | $password = Import-Clixml -Path $configDir -ErrorAction STOP | ConvertTo-SecureString 106 | $refreshToken = Import-Clixml -Path $refreshTokenPath -ErrorAction STOP | ConvertTo-SecureString 107 | } 108 | catch { 109 | Write-Warning "Corrupt Password file found, rerun with -Force to fix this" 110 | BREAK 111 | } 112 | 113 | Get-DecryptedValue -inputObj $password -name PSReddit_accessToken 114 | Get-DecryptedValue -inputObj $refreshToken -name PSReddit_refreshToken 115 | 116 | 'Found cached Cred' 117 | continue 118 | } 119 | 120 | } -------------------------------------------------------------------------------- /Public/Get-RedditAccount.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Gets information about the currently logged in user 4 | .Description 5 | After you've connected using Connect-RedditAccount, you can use this cmdlet to get information about the currently logged in user 6 | .PARAMETER redditSession 7 | An optional session to use (like that returned from Connect-RedditSession) 8 | .Example 9 | Get-RedditAccount 10 | 11 | name : 1RedOne 12 | hide_from_robots : False 13 | gold_creddits : 0 14 | link_karma : 2674 15 | comment_karma : 19080 16 | over_18 : True 17 | is_gold : False 18 | is_mod : False 19 | gold_expiration : 20 | has_verified_email : True 21 | inbox_count : 2 22 | Created Date : 1/20/2010 6:44:21 PM 23 | .LINK 24 | https://github.com/1RedOne/PSReddit 25 | #> 26 | function Get-RedditAccount 27 | { 28 | [CmdletBinding()] 29 | Param ( 30 | [Parameter( 31 | Position = 1, 32 | Mandatory = $false, 33 | ValueFromPipelineByPropertyName = $true 34 | )] 35 | [Alias("Link")] 36 | $accessToken=$Global:PSReddit_accessToken 37 | ) 38 | 39 | 40 | $defaultDisplaySet = 'ID','name','Created Date','comment_karma','link_karma','gold_credits' 41 | 42 | #Create the default property display set 43 | $defaultDisplayPropertySet = New-Object System.Management.Automation.PSPropertySet(‘DefaultDisplayPropertySet’,[string[]]$defaultDisplaySet) 44 | $PSStandardMembers = [System.Management.Automation.PSMemberInfo[]]@($defaultDisplayPropertySet) 45 | 46 | $uri = 'https://oAuth.reddit.com/api/v1/me' 47 | try {$response = (Invoke-RestMethod $uri -Headers @{"Authorization" = "bearer $accessToken"}) } 48 | catch{write-warning "Authentication failed, we should do something here"} 49 | 50 | $origin = New-Object -Type DateTime -ArgumentList 1970, 1, 1, 0, 0, 0, 0 51 | $created = $origin.AddSeconds($response.created) 52 | 53 | $response | select -ExcludeProperty created* -Property *,@{Name="Created Date";exp={$created}} 54 | 55 | $response.PSObject.TypeNames.Insert(0,'PSReddit.User') 56 | $response | Add-Member MemberSet PSStandardMembers $PSStandardMembers 57 | 58 | } 59 | -------------------------------------------------------------------------------- /Public/Get-RedditComment.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Gets the comments of a Reddit link, or several. 4 | .DESCRIPTION 5 | Uses the Reddit API to get comments made on a given link, collection of posts or the id. 6 | .EXAMPLE 7 | Get-RedditComment -id "3i9psm" 8 | .EXAMPLE 9 | "https://www.reddit.com/r/redditdev/comments/3i9psm/how_can_i_find_the_id_of_the_original_post_in_a/" | Get-RedditComment 10 | .EXAMPLE 11 | Get-RedditPost -Name PowerShell | Select-Object -First 1 | Get-RedditComment 12 | #> 13 | function Get-RedditComment 14 | { 15 | [CmdletBinding()] 16 | Param ( 17 | [Parameter( 18 | Position = 1, 19 | Mandatory = $true, 20 | ValueFromPipeline = $true, 21 | ValueFromPipelineByPropertyName = $true 22 | )] 23 | [Alias("Link", "Name")] 24 | [string] 25 | $id 26 | ) 27 | 28 | Process 29 | { 30 | ## Depending on how we passed the id to the function, we need to 31 | ## strip some characters. 32 | switch ($id) 33 | { 34 | {($id -like "t3_*")} 35 | { 36 | $id = $id -replace "t3_", "" 37 | break 38 | } 39 | {($id -like "http*")} 40 | { 41 | $id = $id.Split("/")[6] 42 | break 43 | } 44 | } 45 | 46 | $uri = 'http://www.reddit.com/comments/{0}.json' -f $id 47 | 48 | Write-Verbose "Sending request to $uri" 49 | $listings = (Invoke-RestMethod $uri) | Where kind -eq 'Listing' 50 | 51 | # Comments have a type 't1' in Reddit API 52 | $comments = $listings | ForEach-Object { $_.data.children } | Where-Object kind -eq 't1' | Select-Object -Expand data 53 | $comments | ForEach-Object { $_.PSObject.TypeNames.Insert(0,'PowerReddit.Comment'); $_ } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Public/Get-RedditPost.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Retrieve a listing of the top 50 posts by popularity in a given subreddit. Supports -Subreddit to specify a particular subreddit 4 | .DESCRIPTION 5 | Currently the objects are a bit boned, and you can't get into too much detail, so that's no good. Trust me when I say it will get better. 6 | .EXAMPLE 7 | Get-RedditPost 8 | ups : 4819 9 | title : You know what.. Fuck you! 10 | url : http://i.imgur.com/ln1PIuI.gifv 11 | name : t3_3lfds5 12 | permalink : /r/Unexpected/comments/3lfds5/you_know_what_fuck_you/ 13 | Created Date : 3 hours ago 14 | 15 | ups : 5215 16 | title : It must have been a rough divorce 17 | url : http://imgur.com/fXdbGtd.jpeg 18 | name : t3_3lfbd9 19 | permalink : /r/funny/comments/3lfbd9/it_must_have_been_a_rough_divorce/ 20 | Created Date : 2 hours ago 21 | .EXAMPLE 22 | Get-RedditPost -Name PowerShell | select -First 5 23 | 24 | 25 | ups : 4 26 | title : List All printers that were /ga from PrintUI 27 | url : http://www.reddit.com/r/PowerShell/comments/3lgj6a/list_all_printers_that_were_ga_from_printui/ 28 | name : t3_3lgj6a 29 | created : 1442627254.0 30 | permalink : /r/PowerShell/comments/3lgj6a/list_all_printers_that_were_ga_from_printui/ 31 | 32 | ups : 10 33 | title : Combine directories. 34 | url : http://www.reddit.com/r/PowerShell/comments/3lf9ny/combine_directories/ 35 | name : t3_3lf9ny 36 | created : 1442607409.0 37 | permalink : /r/PowerShell/comments/3lf9ny/combine_directories/ 38 | .EXAMPLE 39 | Get-RedditPost -Name PowerShell | select -First 1 | Get-RedditPostComments 40 | 41 | This will eventually work 42 | #> 43 | Function Get-RedditPost { 44 | [CmdletBinding()] 45 | Param ( 46 | [Parameter(Position=1, Mandatory=$false, ValueFromPipelineByPropertyName=$true)] 47 | [Alias("r","Subreddit")] 48 | [string[]] 49 | $Name = 'all', 50 | [Parameter( 51 | Position = 0, 52 | Mandatory = $false, 53 | ValueFromPipelineByPropertyName = $true 54 | )] 55 | [Alias("Link")] 56 | $accessToken=$Global:PSReddit_accessToken 57 | ) 58 | #needs to be updated to reflect properties on line 36, also need to add new type to .ps1xml file for this 59 | $defaultDisplaySet = 'ID','name','Created Date','comment_karma','link_karma','gold_credits' 60 | # Construct the Uri. Multiple subreddits can be joined with plusses 61 | #$uri = 'http://www.reddit.com/r/{0}.json' -f [string]::Join('+', $Name) 62 | 63 | $uri = "https://oAuth.reddit.com/r/$Name/hot" ; 64 | try {$response = (Invoke-RestMethod $uri -Headers @{"Authorization" = "bearer $accessToken"} -ErrorAction STOP) } 65 | catch{write-warning "Authentication failed, we should do something here"} 66 | 67 | $response.data.children.data | Select ups,Title,URL,name,created,permalink 68 | 69 | #Figure out the age of a post 70 | write-debug "figure out select logic for age of post" 71 | 72 | $origin = New-Object -Type DateTime -ArgumentList 1970, 1, 1, 0, 0, 0, 0 73 | $now = get-date 74 | $created = $origin.AddSeconds($response.created) 75 | 76 | $response.data.children.data | select -ExcludeProperty created* -Property ups,Title,URL,name,created,permalink,@{Name="Created Date";exp={ 77 | "$($origin.AddSeconds($_.created) - $now | select -expandProperty Hours) hours ago" 78 | } 79 | } 80 | 81 | 82 | <# 83 | Write-debug "test out response" 84 | # This is the listing. Contains before/after for pagination, and links 85 | $listing = $response | Where kind -eq 'Listing' | Select -Expand data 86 | 87 | # Links have type "t3" in Reddit API 88 | $links = $listing.children | Where kind -eq 't3' | select -expand data 89 | 90 | # Return the links with a custom type of [PowerReddit.Link]. We do this so 91 | # that they can be extended by psxml files, etc. 92 | $links | %{ $_.PSObject.TypeNames.Insert(0,'PowerReddit.Link'); $_ } 93 | 94 | #> 95 | } -------------------------------------------------------------------------------- /Public/New-RedditPost.ps1: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | <# 6 | POST /api/submitsubmit 7 | 8 | 9 | 10 | Submit a link to a subreddit. 11 | 12 | Submit will create a link or self-post in the subreddit sr with the title title. If kind is "link", then url is expected to be a valid URL to link to. Otherwise, text, if present, will be the body of the self-post. 13 | 14 | If a link with the same URL has already been submitted to the specified subreddit an error will be returned unless resubmit is true. extension is used for determining which view-type (e.g. json, compact etc.) to use for the redirect that is generated if the resubmit error occurs. 15 | 16 | 17 | api_type 18 | 19 | the string json 20 | 21 | 22 | captcha 23 | 24 | the user's response to the CAPTCHA challenge 25 | 26 | 27 | extension 28 | 29 | extension used for redirects 30 | 31 | 32 | iden 33 | 34 | the identifier of the CAPTCHA challenge 35 | 36 | 37 | kind 38 | 39 | one of (link, self) 40 | 41 | 42 | resubmit 43 | 44 | boolean value 45 | 46 | 47 | sendreplies 48 | 49 | boolean value 50 | 51 | 52 | sr 53 | 54 | name of a subreddit 55 | 56 | 57 | text 58 | 59 | raw markdown text 60 | 61 | 62 | title 63 | 64 | title of the submission. up to 300 characters long 65 | 66 | 67 | uh / X-Modhash header 68 | 69 | a modhash 70 | 71 | 72 | url 73 | 74 | a valid URL 75 | 76 | 77 | #> -------------------------------------------------------------------------------- /Public/Refresh-RedditToken.ps1: -------------------------------------------------------------------------------- 1 | Function Refresh-RedditToken{param($settings) 2 | 3 | 4 | $body = @{ 5 | client_id = $settings.client_id 6 | grant_type = 'refresh_token' 7 | refresh_token = $settings.refresh_token 8 | redirect_uri = $settings.redirect_uri 9 | duration= $settings.duration 10 | scope= $settings.scope # 'identity','history','mysubreddits','read','report','privatemessages','save','submit' 11 | 12 | } 13 | $tempPW = ConvertTo-SecureString $settings.secret -AsPlainText -Force 14 | $credential = New-Object System.Management.Automation.PSCredential ($settings.client_id, $tempPW) 15 | 16 | Invoke-RestMethod https://www.reddit.com/api/v1/access_token -Body $body -Method Post -Credential $credential #-ContentType "application/x-www-form-urlencoded" 17 | 18 | 19 | } -------------------------------------------------------------------------------- /Public/Send-RedditMessage.ps1: -------------------------------------------------------------------------------- 1 | Function Send-RedditMessage {param( 2 | $AccessToken, 3 | $Recipient, 4 | $subject, 5 | $post, 6 | $userAgent = 'AzureFunction-SubredditBot:0.0.2 (by /u/1RedOne)' 7 | ) 8 | 9 | $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" 10 | $headers.Add("User-Agent", 'AzureFunction-SubredditBot:0.0.2 (by /u/1RedOne)') 11 | $headers.Add("Authorization", "bearer $AccessToken") 12 | 13 | $bodyMarkdown = " 14 | Hi Stephen, 15 | 16 | A new post was submitted on [/r/FoxDeploy](http://www.reddit.com/r/FoxDeploy), you should check it out. 17 | 18 | 19 | Post Title: $($post.data.title) 20 | 21 | Post link here: [Click here for the link]($($post.data.url)) 22 | 23 | ---------- 24 | 25 | 26 | This alert was generated at $time." 27 | 28 | $body = @{ 29 | api_type = 'json' 30 | to = $Recipient #@'1RedOne' 31 | subject = $subject 32 | text=$bodyMarkdown 33 | } 34 | 35 | 36 | $Request = Invoke-RestMethod -Headers $headers -Uri https://oauth.reddit.com/api/compose -Method Post -Body $body -ContentType 'application/x-www-form-urlencoded' 37 | 38 | If ($Request.json.errors.Count -eq 0){ 39 | Write-Host -ForegroundColor Green 'Message sent' 40 | } 41 | else{ 42 | Write-Warning 'Error' 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PSReddit 2 | =========== 3 | This is a set of tools for browsing Reddit using the Powershell command line. 4 | 5 | Installation 6 | ------------ 7 | * Copy the "PSReddit" folder into your module path. Note: You can find an 8 | appropriate directory by running `$ENV:PSModulePath.Split(';')`. 9 | * Run `Import-Module PSReddit` from your PowerShell command prompt. 10 | 11 | Usage 12 | ----- 13 | 14 | Register for a Reddit API account here, [Reddit Application Preferences](https://www.reddit.com/prefs/apps), and choose a Script based Application. Make note of your ClientSecret, ClientID and RedirectURI (which can be anything). 15 | ![Copy these values](https://github.com/1RedOne/PSReddit/blob/master/img/API.png) 16 | 17 | ###Connecting your Account### 18 | Connect-RedditAccount -ClientID $clientID -redirectURI $redirectURI -force -ClientSecret $ClientSecret 19 | #oAuth Window will be displayed 20 | 21 | ![approve oAuth and away you go!](https://github.com/1RedOne/PSReddit/blob/master/img/Approve.png) 22 | 23 | Credentials persist in secure storage and are automatically imported when you use a cmdlet in this module. 24 | 25 | Once connected, you can connect to any of the endpoints [listed in the Reddit API Documentation here.](https://www.reddit.com/dev/api) 26 | 27 | Get-RedditAccount 28 | 29 | name : 1RedOne 30 | hide_from_robots : False 31 | gold_creddits : 0 32 | link_karma : 2674 33 | comment_karma : 19080 34 | over_18 : True 35 | is_gold : False 36 | is_mod : False 37 | gold_expiration : 38 | has_verified_email : True 39 | inbox_count : 2 40 | Created Date : 1/20/2010 6:44:21 PM 41 | 42 | ... gets you information about your account including karma and account creation date 43 | 44 | ####Links#### 45 | 46 | **Most of these are out of date with the new Rest method, and will be revamped** 47 | 48 | Get-RedditPost 49 | 50 | ... gets you a nicely formatted table of the current front page links. 51 | 52 | Get-RedditLink -r Powershell 53 | 54 | ... does the same but for the subreddits listed. 55 | 56 | Get-RedditLink -r Powershell | Where is_self | Format-List title, selftext | Out-Host -Paging 57 | 58 | ... will let you read the front-page self posts from the Powershell subreddit, 59 | in a nicely paginated format. 60 | 61 | $top = Get-RedditLink | Sort -Descending score 62 | $top[0].OpenUrl() 63 | 64 | ... will open the link with the top score on the front page in your default 65 | browser 66 | 67 | ###Comments - coming soon!### 68 | 69 | Get-RedditLink | Get-RedditComment 70 | 71 | ... gets you all the top-level comments of all the posts on the front page 72 | 73 | $top[0] | Get-RedditComment 74 | 75 | ... gets you the comments on just that top post 76 | 77 | ##Authentication## 78 | 79 | <<<<<<< HEAD 80 | Connect-RedditAccount 81 | Get-RedditAccount 82 | Disconnect-RedditAccount - coming soon 83 | 84 | ======= 85 | Authentication is handled using oAuth via two private function cmdlets, Show-oAuthWindow being the most important of the two. If you've got another project and you're here because you need some reference for handling oAuth using PowerShell, this will be the cmdlet you want. It's found in the Module\Private folder. 86 | Connect-RedditAccount 87 | 88 | >>>>>>> origin/master 89 | ... logs you in, gets information about the logged in user, then logs out. 90 | 91 | ###To come### 92 | 93 | * Making Posts 94 | * imgur uploads 95 | * Your suggestions? 96 | * Multiple Account Support 97 | -------------------------------------------------------------------------------- /img/API.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1RedOne/PSReddit/5d887c04525409d3ff069ca66e29dea39cba9a55/img/API.png -------------------------------------------------------------------------------- /img/Approve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1RedOne/PSReddit/5d887c04525409d3ff069ca66e29dea39cba9a55/img/Approve.png -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------