Make an RSS alarm clock
Make an RSS alarm clock
Making your own RSS alarm clock
This is a small tutorial on how to make your own speaking RSS reader using the windows scripting host. Don't worry, it's in JScipt, not VBScipt so if you know JavaScipt this will be pretty easy to understand. I saw a similar idea on Hak5.org but they used a sort of patchwork of scripts and programs so I decided to write an all-in-one script. If parts are a little unclear sorry, I'm used to writing code, not tutorials.
function say(phrase)
{
for(var i=0;i<phrase.length;i++)
{
if(phrase.charCodeAt(i)<32||phrase.charCodeAt(i)>126) phrase=phrase.substr(0,i-1)+phrase.substr(i+1);
phrase=phrase.replace(\'@\',\' \');
phrase=phrase.replace(\'[\',\' \');
phrase=phrase.replace(\']\',\' \');
phrase=phrase.replace(\'(\',\' \');
phrase=phrase.replace(\')\',\' \');
phrase=phrase.replace(\'{\',\' \');
phrase=phrase.replace(\'}\',\' \');
phrase=phrase.replace(\'_\',\' \');
phrase=phrase.replace(\'-\',\' \');
phrase=phrase.replace(\'^\',\' \');
phrase=phrase.replace(\'`\',\' \');
phrase=phrase.replace(\'\"\',\' \');
phrase=phrase.replace(\"\'\",\' \');
phrase=phrase.replace(\'|\',\' \');
phrase=phrase.replace(\'~\',\' \');
}
var vt=WScript.CreateObject(\"Speech.VoiceText\");
vt.Register(\"\",WScript.ScriptName);
vt.Speak(phrase,1);
while(vt.IsSpeaking) WScript.Sleep(100);
}
This is the function that actually does the speaking using the windows text-to-speech API. The first thing it does is check every character in the string to make sure it is a pronouncable ASCII character. It took me 2 reboots to find out that if you try to make it speak a non-pronouncable character it won't crash, it will just slow down the system almost to a standstill. Next it creates a Speech.VoiceText object to speak through and registers it to this script. Now it will actually speak the words that have been put into it, while it is speaking you don't want the script to go do something else so that's why the is while(vt.IsSpeaking) WScript.Sleep(100); line is added.
function getfeed(url)
{
var tmp=url.substr(7);
tmp=tmp.substr(0,tmp.indexOf(\'/\'));
if(tmp.indexOf(\'www.\')==0) tmp=tmp.substr(4);
tmp=tmp.split(\'.\');
tmp=tmp.join(\' dot \');
var site=tmp;
The getfeed function grabs and formats the news feed from the url passed to it. The first thing it does is get the site name and format it so that the TTS engine can pronounce it.
var text=\'Headline from \'+site+\',,,,,,\';
var x=new ActiveXObject(\"Microsoft.XMLHTTP\");
x.open(\'GET\',url,false);
x.send(null);
You should recognize this part if you read my AJAX tutorial, if not I suggest you go learn AJAX, it is really very useful for a lot of applications. Because this script is run from the windows scripting host the it doesn't have the same security procedures as a browser so you can do inter-domain AJAX. In this case you may notice a difference from conventional AJAX, this is SJAX or Synchronous JavaScript and XML. To do this just make the 3rd argument for the x.open function false and don't define an onStateChangeHandler function, just put the handler code right after the x.send.
if(x.status==200)
{
r=x.responseText.toLowerCase();
r=r.substr(r.indexOf(\'<item>\')+6);
tmp=r.split(\'<title>\');
tmp=tmp[1];
tmp=tmp.split(\'</title>\');
text+=tmp[0]+\',,,,,,,\';
text=text.replace(/</g,\'<\');
text=text.replace(/>/g,\'>\');
text=text.replace(/<\\S[^>]*>/g,\"\");
}
else
{
text=\"Error: could not get rss feed from \"+site;
}
return text;
}
The code here is vogon poetry but it works pretty well. I couldn't figure out how to get the XML navigation functions to work, they always siad there was no data so I'm using a text based method instead. If the RSS grab was not succesful, speak an error message, if it was then convert it to lower case so the following functions will work. Throw away everything before the first tag. Get everything between and . You can make it get the description as well, just copy the tmp=r.split… code piece again and change the title's to description's. Strip out all HTML entities and return text.
var fs=new ActiveXObject(\"Scripting.FileSystemObject\");
var f=fs.GetFile(\"rssalarm.ini\");
var is=f.OpenAsTextStream(1,0);
var rsstext=\'\';
while(!is.AtEndOfStream)
{
var url=is.ReadLine();
if(url)
{
rsstext+=getfeed(url);
}
}
is.Close();
say(rsstext);
WScript.Quit();
Open rssalarm.ini and read out each line as a URL to be passed to getfeed. Close the fle pointer and speak whatever news has been gatthered. End script.
Name the script rssalarm.js and double click it to make sure it works. If it doesn't work immediatly give it a moment, remember, it needs to retrieve all the RSS feeds before it can soeak them. To add feeds to this script just add the full feed URL to a line in rssalarm.ini. To make it into an alarm clock just add a scheduled task to run the script every morning.
Hope this was helpful to someone, or at least fun. –download