Monday, November 08, 2010 at 12:01 AM.

system.verbs.apps.FriendFeed.getUserUpdates

on getUserUpdates (who, adrtable, flNewOnly=false, appName="", flRoom=false, username=nil, remotekey=nil) {
	<<Changes
		<<1/27/09; 10:29:01 AM by DW
			<<Make it possible for this routine to be used to access rooms and private spaces.
				<<Changed the name of the first parameter from username to who -- this is whose updates we're going to retrieve.
				<<Add new optional parameter, flRoom, defaults false. If true, "who" is the name of FriendFeed room.
				<<Add two optional parameters, username and remotekey, default to nil, allows this to be used for authenticated requests.
		<<7/21/08; 6:01:09 AM by DW
			<<No messages on tcp.httpreadurl call.
		<<7/15/08; 1:02:27 PM by DW
			<<Only call filemenu.savemyroot if flNewOnly is true.
		<<7/15/08; 12:33:20 PM by DW
			<<Add call to filemenu.savemyroot at the end to make sure all the saved guids are safe on disk.
		<<7/15/08; 12:06:56 PM by DW
			<<Change the name of the data file to friendFeedData.root.
		<<7/15/08; 9:31:39 AM by DW
			<<Created. If flNewOnly is true, we do something really neat. We keep a data file around that tracks which items have been seen and which haven't. You must give us an appname, so your getting doesn't interfere with other app's.
	local (url, adruser);
	bundle { //set url, 1/27/09 by DW
		if flRoom {
			url = "http://friendfeed.com/api/feed/room/" + who + "?output=rss"}
		else {
			url = "http://friendfeed.com/api/feed/user/" + who + "?output=rss"}};
	bundle { //open data file, if we're only returning new items
		if appname == "" {
			flNewOnly = false};
		if flNewOnly {
			local (adrdata = frontier.opendatafile ("friendFeedData"));
			if not defined (adrdata^.userUpdates) {
				new (tabletype, @adrdata^.userUpdates)};
			local (adrapp = @adrdata^.userUpdates.[appName]);
			if not defined (adrapp^) {
				new (tabletype, adrapp)};
			adruser = @adrapp^.[who];
			if not defined (adruser^) {
				new (tabletype, adruser)}}};
	new (tabletype, adrtable); //start with an empty result
	local (xmltext = tcp.httpreadurl (url, flMessages:false, username:username, password:remotekey), xstruct, now = clock.now ());
	xml.compile (xmltext, @xstruct);
	<<scratchpad.xstruct = xstruct
	local (adrrss = xml.getaddress (@xstruct, "rss"));
	local (adrchannel = xml.getaddress (adrrss, "channel"), adritem);
	for adritem in adrchannel {
		if nameof (adritem^) endswith "item" {
			local (guid = xml.getvalue (adritem, "guid"));
			<<msg (guid)
			if flNewOnly {
				local (adrguid = @adruser^.[guid]);
				if defined (adrguid^) { //already seen
					continue};
				adrguid^ = now};
			local (adrsub = @adrtable^.[guid]);
			new (tabletype, adrsub);
			adrsub^.title = xml.getvalue (adritem, "title");
			adrsub^.link = xml.getvalue (adritem, "link");
			adrsub^.pubDate = date (xml.getvalue (adritem, "pubDate"));
			
			local (adruser = xml.getaddress (adritem, "user"));
			adrsub^.userName = xml.getvalue (adruser, "name");
			adrsub^.userNickname = xml.getvalue (adruser, "nickname");
			adrsub^.userProfileUrl = xml.getvalue (adruser, "profileUrl");
			
			local (adrservice = xml.getaddress (adritem, "service"));
			adrsub^.serviceId = xml.getvalue (adrservice, "id");
			adrsub^.serviceName = xml.getvalue (adrservice, "name");
			adrsub^.serviceIconUrl = xml.getvalue (adrservice, "iconUrl");
			adrsub^.serviceProfileUrl = xml.getvalue (adrservice, "profileUrl");
			bundle { //entryType -- some services don't have them
				try {
					adrsub^.serviceEntryType = xml.getvalue (adrservice, "entryType")}
				else {
					adrsub^.serviceEntryType = ""}}}};
	if flNewOnly {
		filemenu.savemyroot (adruser)}};
bundle { //test code
	getuserupdates ("instant-outline-beta", @scratchpad.ffupdates, flRoom:true, username:"davew", remotekey:user.FriendFeed.prefs.remotekey);
	<<getuserupdates ("davew", @scratchpad.ffupdates)
	<<getuserupdates ("davew", @scratchpad.ffupdates, true, "testing")
	edit (@scratchpad.ffupdates)}



This listing is for code that runs in the OPML Editor environment. I created these listings because I wanted the search engines to index it, so that when I want to look up something in my codebase I don't have to use the much slower search functionality in my object database. Dave Winer.