AppleScript RSS and Speech?

I would like to write an Applescript that takes a RSS feed and returns the top 3 headlines. Basicly when I run it I would like my computer to just ‘read’ me (using Apple Speech) the top 3 headlines rom that particular feed. Is this a possible task, I would assume Applescript could do this however I dont know how to grab information over a network. Any help would be great! Thanks

When you say headline, do you mean the actual headline/title, or the whole article (headline and text)?

If you only want the headlines, then something like this should work:

property RSSURL : "http://scriptbuilders.net/scriptbuilders.xml"

try
	do shell script "curl -sS " & quoted form of RSSURL & " | grep ' <title>' | head -n 3 | colrm 1 15 | cut -d \\< -f 1"
	get paragraphs of result
	
	repeat with thisLine in result
		delay 2
		say thisLine
	end repeat
on error errorMsg number errorNum
	display dialog "Error (" & errorNum & "):" & return & return & errorMsg buttons "Cancel" default button 1 with icon caution
end try

How can I change that so it only read the top 3, most recent, headlines from a given feed?

What feed are you trying to use?

I am using the top news headlines from CNN.
feed://rss.cnn.com/rss/cnn_topstories.rss
How can I extend it so it reads say the first paragraph or so of the article.

What I would like is a script that, when run, will greet me and say “These are the top news headlines for today”, reads me the top 3 headlines and articles and then tells me any items i have left on my ical to-do list.

What I have compiled so far looks like this:

property RSSURL : "feed://rss.cnn.com/rss/cnn_topstories.rss"
try
	do shell script "curl -sS " & quoted form of RSSURL & " | grep ' <title>' | head -n 3 | colrm 1 15 | cut -d \\< -f 1"
	get paragraphs of result
copy the (current date) to thedate
set theweekday to weekday of (current date)
set theday to day of (current date)
set themonth to month of (current date)
set theyear to year of (current date)
set todaydate to theweekday & themonth & theday & theyear
set thetime to time of (current date)
if thetime < 43200 then
	set thegreeting to "Good Morning"
else if thetime < 64800 then
	set thegreeting to "Good Afternoon"
else
	set thegreeting to "Good Evening"
	
	say thegreeting & "This is the current report for. " & todaydate & "The Current time is" & thetime
	delay 2
	say "Today's top news headlines are"
	
	repeat with thisLine in result
		delay 2
		say thisLine
	end repeat
	set theCalendar to "TODO" -- change to your calendar name
set myList to {}
tell application "iCal"
	set {myComps, mySumms} to {completion date, summary} of todos of calendar theCalendar
	repeat with myItem from 1 to count of myComps
		if (item myItem of myComps) contains missing value then set the end of myList to (item myItem of mySumms)
	end repeat
end tell
	say myList

In parts this works, but I would like to get the entire feed description and have the TODO items spoken in order. I cant figure out how to to that.
I appriciate this, I am new to Applescript, but am finding it a great and explorable proramming language for everything!

Real chore to do it with AppleScript unless you’re using a scriptable RSS reader application as there’s no good RSS libraries for AS. Easy if you use Python and the excellent Universal Feed Parser module:

#!/usr/bin/env python

import os, time
import feedparser

d = feedparser.parse('http://rss.cnn.com/rss/cnn_topstories.rss')

def say(s):
	os.system("say '%s'" % s.replace("'", "''\\'''"))

for entry in d.entries[0:3]:
	say(entry.title)
	say(entry.summary)
	time.sleep(1)

HTH

Try something like this:

property RSSURL : "http://rss.cnn.com/rss/cnn_topstories.rss"

set ASTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to {("<item>" & (ASCII character 13))}
try
	do shell script "curl -sS " & quoted form of RSSURL
	set rssFeed to every text item of result
	set AppleScript's text item delimiters to ASTID
	
	if (count rssFeed) is greater than or equal to 4 then
		set rssFeed to items 2 thru 4 of rssFeed
	else
		set rssFeed to items 2 thru (count rssFeed) of rssFeed
	end if
on error errorMsg number errorNum
	set AppleScript's text item delimiters to ASTID
	display dialog "Error (" & errorNum & "):" & return & return & errorMsg buttons "Cancel" default button 1 with icon caution
end try

say "These are the top news headlines for today."
delay 2
repeat with thisPiece in rssFeed
	say (text 8 thru -9 of (first paragraph of thisPiece))
	delay 1
	say (text 14 thru -15 of (third paragraph of thisPiece))
	delay 2
end repeat
say "End of headlines."

Unfortunately, items inside RSS feeds are not always sorted by publication date. I’m not sure how to handle that.

If you want to see the results of this script, replace the end of the script with something like this:

set newsList to {}
repeat with thisPiece in rssFeed
	set newsList's end to (text 8 thru -9 of (first paragraph of thisPiece))
	set newsList's end to (text 14 thru -15 of (third paragraph of thisPiece))
end repeat

return newsList

set newsList to {}
repeat with thisPiece in rssFeed
	set newsList's end to {title:(text 8 thru -9 of (first paragraph of thisPiece)), summmary:(text 14 thru -15 of (third paragraph of thisPiece))}
end repeat

return newsList

Note that this code assumes each RSS item contains a title, link, and description element (in that order).

Note that AS’s built-in text handling facilities and tools like grep are seriously inadequate for processing XML. If you must use AppleScript for XML work (other languages are much better), at least use something like System Events’ XML Suite (10.4+) or XMLLib.osax.

Using System Events’ XML Suite:

property RSSURL : "http://rss.cnn.com/rss/cnn_topstories.rss"
property RSSFile : POSIX path of ((path to temporary items as Unicode text) & "rss.xml")

tell application "System Events"
	activate
	try
		do shell script "curl -sS " & quoted form of RSSURL & " > " & quoted form of RSSFile
		set rssFeed to XML file RSSFile
		
		set rssItems to XML elements 1 thru 3 of XML element "channel" of XML element "rss" of contents of rssFeed whose name is "item"
		
		get value of XML element "title" of XML element "channel" of XML element "rss" of contents of rssFeed
		say "These are today's top news headlines from " & result
		delay 2
	on error errorMsg number errorNum
		display alert "Error " & errorNum message errorMsg buttons "Cancel" default button 1
		return false
	end try
	
	repeat with thisItem in rssItems
		try
			say (get value of XML element "title" of thisItem)
		on error
			say "No title for this item."
		end try
		delay 1
		
		try
			say (get value of XML element "description" of thisItem)
		on error
			say "No description for this item."
		end try
		delay 2
	end repeat
	say "End of headlines."
end tell

I’m still not sure how to sort by date.

Google for “Schwartzian transform”. Example using AppleMods’ List library:

property _Loader : run application "LoaderServer"

----------------------------------------------------------------------
-- DEPENDENCIES

property _List : missing value

on __load__(loader)
	set _List to loader's loadLib("List")
end __load__

----------------------------------------------------------------------

__load__(_Loader's makeLoader())

tell application "Finder"
	tell every item of home
		set itemDates to its modification date
		set itemRefs to it
	end tell
end tell

set lst to _List's recomposeList({itemDates, itemRefs})
set lst to _List's sortListOfLists(lst, {1})
set sortedItemRefs to _List's recomposeList(lst)'s item 2

(Feel free to add the above to Code Exchange if you like; it seems to be a fairly regular question.)

Interesting.