Public/Send-PicTweet.ps1
function Send-PicTweet { <# .SYNOPSIS This uploads a picture using the chunked Twitter upload and sends a tweet witht the message. .DESCRIPTION Unlike tweeting with from browser or smartphone Media Upload is handled seperately from the tweet process in the TwitterAPI. The media data must be uploaded first and the provided media_id is used in the tweet. This function combines both mechanisms to one function. .PARAMETER Message Enter the message that the tweet should include Example: '-message "Hello World"' .PARAMETER PathtoPic Enter the Path to the image you want to include in the tweet. File must be smaller than 5MB. (Twitter Restriction) Example: '-PathtoPic "C:\temp\test.jpg"' .EXAMPLE Send-PicTweet -Message "Hello World" -PathtoPic "C:\temp\test.jpg" This uploads the test.jpg file to twitter and then sends a tweet with the provided message as well as the media_id received by the upload #> [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [ValidateLength(1, 140)] [string]$Message, [Parameter(Mandatory)] [ValidateScript({ (Get-ChildItem $_).Length -le 5MB })] [string]$PathtoPic ) process { $TotalBytes = (Get-ChildItem $PathtoPic).Length ###### ### Splitting the Picture in 900KB-sized Base64encoded Strings. (better performance and can be directly combined with chunked upload to twitter) ### For the splitting of the Base64Encoding I used this wonderful solution: ### https://mnaoumov.wordpress.com/2013/08/20/efficient-base64-conversion-in-powershell/ ###### $bufferSize = 900000 # should be a multiplier of 3 $buffer = New-Object byte[] $bufferSize $reader = [System.IO.File]::OpenRead($PathtoPic) [System.Collections.ArrayList]$img = @() do { $bytesread = $reader.Read($buffer, 0, $bufferSize) $null = $img.Add([Convert]::ToBase64String($Buffer, 0, $bytesread)) } while ($bytesread -eq $bufferSize) $reader.Dispose() # Create OAuth for Upload $PICUploadEndPoint = 'https://upload.twitter.com/1.1/media/upload.json' $AuthorizationString = Get-OAuthAuthorization -ApiParameters @{ } -HttpEndPoint $PICUploadEndPoint -HttpVerb 'POST' ###### ### Using Chunked Media Upload, as suggested by Twitter. ### See TwitterAPI Refernce for...well...Reference: https://developer.twitter.com/en/docs/media/upload-media/uploading-media/chunked-media-upload ###### ## INIT Chunked Upload try { $INITBody = @{ command="INIT"; total_bytes=$TotalBytes; media_type="image/jpeg" } $INITResponse = Invoke-RestMethod -URI $PICUploadEndPoint -Method Post -Form $INITBody -Headers @{ 'Authorization' = $AuthorizationString } -ErrorAction Stop } catch { throw 'Error during Upload INIT' } ## APPEND Body try { $x = 0 foreach ($chunk in $img) { $AppendBody = @{ command="APPEND"; media_id=$INITResponse.media_id; media_data=$img[$x]; segment_index=$x } $null = Invoke-RestMethod -URI $PICUploadEndPoint -Method Post -Form $AppendBody -Headers @{ 'Authorization' = $AuthorizationString } -ErrorAction Stop $x++ } } catch { throw 'Error during Upload APPEND' } ### FINALIZE Body try { $FINALIZEBody = @{ command="FINALIZE"; media_id=$INITResponse.media_id } $null = Invoke-RestMethod -URI $PICUploadEndPoint -Method Post -Form $FINALIZEBody -Headers @{ 'Authorization' = $AuthorizationString } -ErrorAction Stop } catch { throw 'Error during Upload FINALIZE' } ### from here it is similar to function send-tweet $HttpEndPoint = 'https://api.twitter.com/1.1/statuses/update.json' ####Added following line/function to properly escape !,*,(,) special characters $Message = $(Add-SpecialCharacters -Message $Message) $MediaID = $INITResponse.media_id $Body = "status=$Message&media_ids=$MediaID" $AuthorizationString = Get-OAuthAuthorization -ApiParameters @{'status'=$message; 'media_ids'=$MediaID } -HttpEndPoint $HttpEndPoint -HttpVerb 'POST' Write-Verbose "Using POST body '$Body'" Invoke-RestMethod -URI $HttpEndPoint -Method Post -Body $Body -Headers @{ 'Authorization' = $AuthorizationString } -ContentType "application/x-www-form-urlencoded" } } |