While working on a Microsoft Flow to automate some tweeting for the O365Eh! Podcast, I ran into a known restriction when using @mention in the available Twitter connector.
Mentioning an @user while posting a tweet is not supported. Specifically, the “@” characters will be stripped while posting a tweet. - https://docs.microsoft.com/en-us/connectors/twitter/
I run this podcast with 3 other Canadian MVPs and the goal of this flow was to link to all our Twitter accounts. I tried many workarounds; adding more @ symbols in a row, encoding the @ and even looked if I could build my own Microsoft Flow Twitter connector, but ran into Oauth 1.0 limitations.
I landed on building an PowerShell Azure Function API and calling it via the flow HTTP Action. Could it still be considered low-code if I sourced most of the pieces?
I tried a number of PowerShell Twitter API scripts before settling on Shannon Conley & Mehmet Kaya’s GITHub Project: InvokeTwitterAPIs.
To use the Twitter API, you must obtain a Twitter API Key + Secret and User Access Token + Secret:
- Head over to https://apps.twitter.com/ and “Create New App” after signing in to your Twitter account.
- Define the Application Name, Description, Website, agree to the Developer Agreement and Click “Create your Twitter application”.
- Click the “Keys and Access Tokens” tab and Click “Create my access token”.
- In my testing, I would get an error “Sorry, that page does not exist” but didn’t seem to cause any issues.
- Document the API Key, API Secret, Access Token and Access Token Secret.
I won’t go into the step by step to create a PowerShell Azure Function HTTP trigger, Brain Bunke has a great blog around this: http://www.brianbunke.com/blog/2018/02/27/powershell-in-azure-functions/.
Key is to turn on “Experimental Language Support” and Select “PowerShell” on the “HTTP trigger” Azure Functions template.
I also added the API Key, API Secret, Access Token and Access Token Secret as Application settings for the Function Apps.
For the run.ps1 of the Twitter function, I have three parts:
- A block of code at the top to deal with the HTTP trigger’s JSON input and Twitter API application settings.
$response = $null
Write-Output "http trigger executed: $(get-date)"
$requestBody = Get-Content $req -raw -Encoding utf8 | ConvertFrom-Json
$OAuth = @{
'ApiKey' = $env:TwitterApiKey
'ApiSecret' = $env:TwitterApiSecret
'AccessToken' = $env:TwitterAccessToken
'AccessTokenSecret' = $env:TwitterAccessTokenSecret
}
$ResourceURL = "https://api.twitter.com/1.1/$($requestBody.Resource)"
$Method = $requestBody.Method.toupper()
$Parameters = @{}
$requestBody.Parameters.psobject.Properties | Foreach { $Parameters[$_.Name] = $($_.Value -replace 'http.*://',"" -replace ':',"") }
-
The raw PowerShell code for the InvokeTwitterAPIs.psm1 (I only kept the Get-Oauth and Invoke-TwitterRestMethod functions). I could have used FTP to upload the complete .psm1 module to the Azure Function, but wasn’t sure if I needed to modify the functions or not.
- InvokeTwitterAPIs.psm1: InvokeTwitterAPIs.psm1
-
A block of code at the bottom to call the functions and return data to the HTTP trigger.
$Tweet = Invoke-TwitterRestMethod -ResourceURL $ResourceURL -RestVerb $Method -Parameters $Parameters -OAuthSettings $OAuth
$response = $Tweet | ConvertTo-Json -depth 5 | Out-String
$response | Out-File -Encoding Ascii -FilePath $res
Write-Output "http message response '$response'"
Write-Output "http trigger completed: $(get-date)"
I leveraged two tests when building the Azure Function.
- A simple query of my Twitter handle grabbing the latest tweet:
{
"Resource": "search/tweets.json",
"Method": "Get",
"Parameters": {"q":"realtimeuc","count": "1"}
}
- Post a tweet that included mentions, emoji and a URL. Warning: Don’t run a post test too many times in a row with the same data. My first Twitter API got locked out and had to create a new one. I was running this test many times to figure out the code required to get URLs and encoding correct. Many hours wasted trying to figure what change I did that broke everything. Finally logged into https://apps.twitter.com to find the API was blocked.
{
"Resource": "statuses/update.json",
"Method": "POST",
"Parameters": {
"status": "O365Eh! 🇨🇦 Episode #6 - Direct Routing http://o365eh.com/2018/04/03/episode-6-direct-routing/ @RealTimeUC @HabibMankal @dinocaputo @InsideSkype Also available on #iTunes #Googlemusic #MicrosoftTeams #MSTeams #Skype4b #Office365"
}
}
On the Microsoft Flow side, I created a simple Flow Button Trigger and added the HTTP-HTTP action with “Method” set to Post, I placed the Azure Function URL as the “Uri” and my desired JSON as the “Body”. I’m also able to leverage Dynamic Content in more complex flows.