· 7 years ago · Apr 16, 2018, 12:54 AM
1<#
2 ===========================================================================
3 Created on: 8/31/2014 3:11 PM
4 Created by: Adam Bertram
5 Filename: MyTwitter.psm1
6
7#>
8
9function Get-OAuthAuthorization {
10 <#
11 .SYNOPSIS
12 This function is used to setup all the appropriate security stuff needed to issue
13 API calls against Twitter's API. It has been tested with v1.1 of the API. It currently
14 includes support only for sending tweets from a single user account and to send DMs from
15 a single user account.
16 .EXAMPLE
17 Get-OAuthAuthorization -DmMessage 'hello' -HttpEndPoint 'https://api.twitter.com/1.1/direct_messages/new.json' -Username adam
18
19 This example gets the authorization string needed in the HTTP POST method to send a direct
20 message with the text 'hello' to the user 'adam'.
21 .EXAMPLE
22 Get-OAuthAuthorization -TweetMessage 'hello' -HttpEndPoint 'https://api.twitter.com/1.1/statuses/update.json'
23
24 This example gets the authorization string needed in the HTTP POST method to send out a tweet.
25 .PARAMETER HttpEndPoint
26 This is the URI that you must use to issue calls to the API.
27 .PARAMETER TweetMessage
28 Use this parameter if you're sending a tweet. This is the tweet's text.
29 .PARAMETER DmMessage
30 If you're sending a DM to someone, this is the DM's text.
31 .PARAMETER Username
32 If you're sending a DM to someone, this is the username you'll be sending to.
33 .PARAMETER ApiKey
34 The API key for the Twitter application you previously setup.
35 .PARAMETER ApiSecret
36 The API secret key for the Twitter application you previously setup.
37 .PARAMETER AccessToken
38 The access token that you generated within your Twitter application.
39 .PARAMETER
40 The access token secret that you generated within your Twitter application.
41 #>
42 [CmdletBinding(DefaultParameterSetName = 'None')]
43 [OutputType('System.Management.Automation.PSCustomObject')]
44 param (
45 [Parameter(Mandatory)]
46 [string]$HttpEndPoint,
47 [Parameter(Mandatory, ParameterSetName = 'NewTweet')]
48 [string]$TweetMessage,
49 [Parameter(Mandatory, ParameterSetName = 'DM')]
50 [string]$DmMessage,
51 [Parameter(Mandatory, ParameterSetName = 'DM')]
52 [string]$Username,
53 [Parameter()]
54 [string]$ApiKey = '2R3aJXohHmSABPaiQGaeprny7',
55 [Parameter()]
56 [string]$ApiSecret = '',
57 [Parameter()]
58 [string]$AccessToken = '',
59 [Parameter()]
60 [string]$AccessTokenSecret = ''
61 )
62
63 begin {
64 $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop
65 Set-StrictMode -Version Latest
66 try {
67 [Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null
68 [Reflection.Assembly]::LoadWithPartialName("System.Net") | Out-Null
69 } catch {
70 Write-Error $_.Exception.Message
71 }
72 }
73
74 process {
75 try {
76 ## Generate a random 32-byte string. I'm using the current time (in seconds) and appending 5 chars to the end to get to 32 bytes
77 ## Base64 allows for an '=' but Twitter does not. If this is found, replace it with some alphanumeric character
78 $OauthNonce = [System.Convert]::ToBase64String(([System.Text.Encoding]::ASCII.GetBytes("$([System.DateTime]::Now.Ticks.ToString())12345"))).Replace('=', 'g')
79 Write-Verbose "Generated Oauth none string '$OauthNonce'"
80
81 ## Find the total seconds since 1/1/1970 (epoch time)
82 $EpochTimeNow = [System.DateTime]::UtcNow - [System.DateTime]::ParseExact("01/01/1970", "dd/MM/yyyy", $null)
83 Write-Verbose "Generated epoch time '$EpochTimeNow'"
84 $OauthTimestamp = [System.Convert]::ToInt64($EpochTimeNow.TotalSeconds).ToString();
85 Write-Verbose "Generated Oauth timestamp '$OauthTimestamp'"
86
87 ## Build the signature
88 $SignatureBase = "$([System.Uri]::EscapeDataString($HttpEndPoint))&"
89 $SignatureParams = @{
90 'oauth_consumer_key' = $ApiKey;
91 'oauth_nonce' = $OauthNonce;
92 'oauth_signature_method' = 'HMAC-SHA1';
93 'oauth_timestamp' = $OauthTimestamp;
94 'oauth_token' = $AccessToken;
95 'oauth_version' = '1.0';
96 }
97 if ($TweetMessage) {
98 $SignatureParams.status = $TweetMessage
99 } elseif ($DmMessage) {
100 $SignatureParams.screen_name = $Username
101 $SignatureParams.text = $DmMessage
102 }
103
104 ## Create a string called $SignatureBase that joins all URL encoded 'Key=Value' elements with a &
105 ## Remove the URL encoded & at the end and prepend the necessary 'POST&' verb to the front
106 $SignatureParams.GetEnumerator() | sort name | foreach {
107 Write-Verbose "Adding '$([System.Uri]::EscapeDataString(`"$($_.Key)=$($_.Value)&`"))' to signature string"
108 $SignatureBase += [System.Uri]::EscapeDataString("$($_.Key)=$($_.Value)&".Replace(',','%2C').Replace('!','%21'))
109 }
110 $SignatureBase = $SignatureBase.TrimEnd('%26')
111 $SignatureBase = 'POST&' + $SignatureBase
112 Write-Verbose "Base signature generated '$SignatureBase'"
113
114 ## Create the hashed string from the base signature
115 $SignatureKey = [System.Uri]::EscapeDataString($ApiSecret) + "&" + [System.Uri]::EscapeDataString($AccessTokenSecret);
116
117 $hmacsha1 = new-object System.Security.Cryptography.HMACSHA1;
118 $hmacsha1.Key = [System.Text.Encoding]::ASCII.GetBytes($SignatureKey);
119 $OauthSignature = [System.Convert]::ToBase64String($hmacsha1.ComputeHash([System.Text.Encoding]::ASCII.GetBytes($SignatureBase)));
120 Write-Verbose "Using signature '$OauthSignature'"
121
122 ## Build the authorization headers using most of the signature headers elements. This is joining all of the 'Key=Value' elements again
123 ## and only URL encoding the Values this time while including non-URL encoded double quotes around each value
124 $AuthorizationParams = $SignatureParams
125 $AuthorizationParams.Add('oauth_signature', $OauthSignature)
126
127 ## Remove any API call-specific params from the authorization params
128 $AuthorizationParams.Remove('status')
129 $AuthorizationParams.Remove('text')
130 $AuthorizationParams.Remove('screen_name')
131
132 $AuthorizationString = 'OAuth '
133 $AuthorizationParams.GetEnumerator() | sort name | foreach { $AuthorizationString += $_.Key + '="' + [System.Uri]::EscapeDataString($_.Value) + '", ' }
134 $AuthorizationString = $AuthorizationString.TrimEnd(', ')
135 Write-Verbose "Using authorization string '$AuthorizationString'"
136
137 $AuthorizationString
138
139 } catch {
140 Write-Error $_.Exception.Message
141 }
142 }
143}
144
145function Send-Tweet {
146 <#
147 .SYNOPSIS
148 This sends a tweet under a username.
149 .EXAMPLE
150 Send-Tweet -Message 'hello, world'
151
152 This example will send a tweet with the text 'hello, world'.
153 .PARAMETER Message
154 The text of the tweet.
155 #>
156 [CmdletBinding()]
157 [OutputType('System.Management.Automation.PSCustomObject')]
158 param (
159 [Parameter(Mandatory)]
160 [ValidateLength(1, 140)]
161 [string]$Message
162 )
163
164 process {
165 $HttpEndPoint = 'https://api.twitter.com/1.1/statuses/update.json'
166
167 $AuthorizationString = Get-OAuthAuthorization -TweetMessage $Message -HttpEndPoint $HttpEndPoint
168
169 ## Convert the message to a Byte array
170 #$Body = [System.Text.Encoding]::ASCII.GetBytes("status=$Message");
171 $Body = "status=$Message"
172 Write-Verbose "Using POST body '$Body'"
173 Invoke-RestMethod -URI $HttpEndPoint -Method Post -Body $Body -Headers @{ 'Authorization' = $AuthorizationString } -ContentType "application/x-www-form-urlencoded"
174 }
175}
176
177function Send-TwitterDm {
178 <#
179 .SYNOPSIS
180 This sends a DM to another Twitter user. NOTE: You can only send up to
181 250 DMs in a 24 hour period.
182 .EXAMPLE
183 Send-TwitterDm -Message 'hello, Adam' -Username 'adam','bill'
184
185 This sends a DM with the text 'hello, Adam' to the username 'adam' and 'bill'
186 .PARAMETER Message
187 The text of the DM.
188 .PARAMETER Username
189 The username(s) you'd like to send the DM to.
190 #>
191 [CmdletBinding()]
192 [OutputType('System.Management.Automation.PSCustomObject')]
193 param (
194 [Parameter(Mandatory)]
195 [ValidateLength(1, 140)]
196 [string]$Message,
197 [Parameter(Mandatory)]
198 [string[]]$Username
199 )
200
201 process {
202 $HttpEndPoint = 'https://api.twitter.com/1.1/direct_messages/new.json'
203
204 ## Convert the message to a Byte array
205 #$Message = [System.Uri]::EscapeDataString($Message)
206 foreach ($User in $Username) {
207 $AuthorizationString = Get-OAuthAuthorization -DmMessage $Message -HttpEndPoint $HttpEndPoint -Username $User -Verbose
208 $User = [System.Uri]::EscapeDataString($User)
209 $Body ="text=$Message&screen_name=$User"
210 Write-Verbose "Using POST body '$Body'"
211 Invoke-RestMethod -URI $HttpEndPoint -Method Post -Body $Body -Headers @{ 'Authorization' = $AuthorizationString } -ContentType "application/x-www-form-urlencoded"
212 }
213
214 }
215}
216
217Export-ModuleMember Send-Tweet
218Export-ModuleMember Send-TwitterDm