How to drive Twitter (or other web tools) with PowerShell

history76156222.jpg

First of all since I’ve mentioned twitter a few times recently I should say I have this cartoon of Hugh’s in my head as a warning.

After a 10 days on Twitter I’m qualified to talk about it like an expert … There are some obvious points of interest.

(1) Twitter Provides a web interface, it’s not great but there is a an API which is reasonably easy to code to. Hence there are a plethora of clients out there. Not all the clients follow the API as well as they might….

(2) A major issue for me is clients which don’t include “In Reply to” information - I see only part of a conversation. It’s not surprising that clients don’t bother with it because, there’s no documented way to search for “messages in reply to this one”. Worse, since there is no “conversation ID” (as there has been in Mail clients since the 1980s) when the web server can reconstruct a conversation it is not efficient. Reto-fitting one would require the clients to be updated…

(3) A major part of the value for me is not in following people as such but in watching topics.  I’m mildly amazed that  (a) There’s no search box visible, no Open Search Discovery, and the search link is at the bottom of the page so you don’t even know its there (b) Twitter itself doesn’t save your searches (c) not all clients save searches.

And so on.

I decided to that I’d write a little PowerShell so I could download information, and after pushing it around for a bit I’m ready to share the results, which is the following set of functions:

Get-TinyUrl – Gets a tiny URL for the a long URL
Publish-Tweet  - Publishes a new tweet (and shame on me, doesn’t bother with in reply to fields)
Get-Tweet  - Gets a tweet byID

Get-TwitterTimeLine – Gets my recent posts and those of the people I’m following
Get-TwitterReply – Gets replies sent to me

Get-TwitterSearch – runs a search has a -DEEP option to search back 1500 messages.
Get-TwitterPublicTimeLine – Gets recent non-private postings
Get-TwitterUserTimeLine – Gets the postings of a particular user

Get-TwitterFollower – Gets a list of who is following me (or someone else)
Get-TwitterFriend – Gets a list of my friends (or someone else)
Add-TwitterFriend – Adds someone to my friends list 

Here’s an example which shows just how easy the functions are to code  in PowerShell 

 Function Get-TwitterReply { 
 param ($username, $password, $Page=1)
 if ($WebClient -eq $null) {$Global:WebClient=new-object System.Net.WebClient  }
 $WebClient.Credentials = (New-Object System.Net.NetworkCredential -argumentList $username, $password)
 ([xml]$webClient.DownloadString("https://twitter.com/statuses/replies.xml?page=$Page")  ).statuses.status 
}

– essentially 3 lines: (1) Get a new WebClient object (2) Set its credentials, and (3) Tell it to download a page of XML; force that from a text string to an XML document and get the /statuses/status XML elements. Each one looks like this (it’s not obvious but USER is a sub-element in XML). I can pretty up the output including displaying the name from the user XML element.

 created_at              : Thu Feb 05 13:20:39 +0000 2009
id                      : 1179608029
text                    : @jamesoneill is on twitter too... Welcome!!!!
source                  : web
truncated               : false
in_reply_to_status_id   :
in_reply_to_user_id     : 20140468
favorited               : false
in_reply_to_screen_name : jamesoneill
user                    : user

Functions which POST to twitter need a bit more care, and I lifted Mike Ormond’s  code for this. If you are writing your own code note that twitter returns an error in response to POST commands "The remote server returned an error: (417) Expectation Failed.", to avoid this there is a line in mike’s code

 [System.Net.ServicePointManager]::Expect100Continue = $false 

Which tells the .net object not to send data in two stages with the server sending a “100 Continue” message between. Twitters server  doesn’t support that and responds with a 417 error. As far as I can tell the simpler WebClient object won’t work with this so I kept Mikes’s code for the WebRequest Object

My first use of this add the top ten posters about PowerShell to my friends list. With these functions I can do it 3 lines 

 $f=Get-TwitterFriend $UserName $Password | ForEach-Object {$_.Screen_name}
$ps=Get-TwitterSearch "Powershell" -deep
$ps | group Author | sort count -desc | select @{name="author"; expression={$_.name.split("@")[0]}}, count -first 10 | 
       ForEach-Object {if ($f -notcontains $_.author) {Add-twitterFreind -id $_.author -user $user -pass $password} } 

The first line gets my existing twitter friends and reduces the XML elements to an array of names.

The next line gets as many PowerShell posts as Twitter will allow – could export these to a CSV file and use them for something else; but here I group the posts by the author and sort them in descending order with most posts first.

The 3rd line is several commands piped together, and the most complicated piece is in the select:  the AUTHOR field, becomes the NAME in the output of the Group, operation  but it is the form UserName@twitter.com (Display Name). So select splits it at the @ sign, and names the result author, and returns the 10 ten. For each one if the Author isn’t already in my friends list, it calls add-twitter friend.

The next obvious thing was to Post to twitter from something on my blog, with $WebClient already set I can get the RssFeed for my blog, build the tweet text and Post it.

 $x=[xml]($WebClient.DownloadString("https://blogs.technet.com/jamesone/rss.xml").replace("item","rssItem"))
$tweet= $x.rss.channel.title+  " : "+$x.rss.channel.rssitem[0].title + " - " + (Get-TinyURL $x.rss.channel.rssitem[0].link)
Publish-Tweet -TweetText $tweet -Username $user -Password $password

 

The whole lot is attached. As usual with these samples it is for illustration and is light on the error checking, and comes with absolutely no warranty whatsoever. (Check the site Terms and conditions)

twitter.zip