Google
 
Main Page
 The gatekeeper of reality is
 quantified imagination.

Stay notified when site changes by adding your email address:

Your Email:

Bookmark and Share
Coming Soon
Email Notification
Project "Facebook Wall Feed 2"
Purpose
The purpose of this project is to demonstrate how to create a feed from a public group wall on Facebook in ASP.NET (unfortunately I've not had time to write up equivalents in Perl or PHP). This particular version compensates for many code changes made to the wall code itself to September 2011, October 2011, November 2011 (updated again early December 2011 for another change at FB).

Introduction
This page will show you how to generate an RSS (or simple XML) feed from the wall of a public group on Facebook; this is a revision.

ASP.NET 3.5 Code:
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.Text" %>
<script runat="server">
' Call this page as: somepage.aspx?name=Group1&feedNumber=6
' name = the server cache object name
' feedNumber = number of posts on wall to accept
' Feed Customizaiton
Dim discussionGroupPage As String = "http://www.facebook.com/PUBLIC-GROUP?sk=wall" ' URL of the public group wall
Dim rssDescriptionLen As Integer = 60 ' Number of characters to allow in the poster's post (description)
Dim numberOfPostsShow As Integer = 6 ' Number of posts on the wall to show
Dim rssIncludeImg As Integer = 1 ' 0 = do not include the thumbnail image of posters in description, 1 = include
Dim rssIncludeHeader As Integer = 0 ' 0 = do not include RSS provider data (below), 1 = include
Dim rssShowErrors As Integer = 0 ' 0 = do not show server-side errors with wall data retrieval, 1 = show
Dim feed_title As String = "Your Feed Title"
Dim feed_link As String = "http://www.facebook.com/PUBLIC-GROUP/"
Dim feed_description As String = "Public Group Wall Feed"
Dim feed_language As String = "en-us"
Dim feed_pubdate As String = "20 Apr 2007 9:40:00 GMT"
Dim feed_copyright As String = String.Empty
Dim feed_webmaster As String = "you@yoursite.com"
' Maintenance
Dim rssCacheClear As Integer = 0 ' 1 = clear server-cache, 0 = do not clear server-cache
Dim rawDump As Integer = 0 ' 1 = show fetched content without reorganization/formatting, 0 = do not show fetched content
' Do Not Use
Dim crawlAgent As String = String.Empty
Dim crawlError As String = String.Empty
' TRAP CONNECT ERRORS IN CRAWLPAGE
Private Function crawlPage(ByVal URL As String) As String
Dim buffSize As Integer = 2048
Dim crawlOutput As String = String.Empty
Dim crawlMethod As String = "GET"
Dim crawlURL As String = URL
Try
Dim myRequest As HttpWebRequest = CType(WebRequest.Create(crawlURL), HttpWebRequest)
myRequest.UserAgent = crawlAgent
myRequest.Method = crawlMethod
Dim myResponse As HttpWebResponse = CType(myRequest.GetResponse(), HttpWebResponse)
Dim streamResponse As Stream = myResponse.GetResponseStream()
Dim streamRead As New StreamReader(streamResponse)
Dim readBuff(buffSize) As [Char]
Dim lineStep As Integer = streamRead.Read(readBuff, 0, buffSize)
While lineStep > 0
Dim outputData As New [String](readBuff, 0, lineStep)
crawlOutput = crawlOutput & outputData
lineStep = streamRead.Read(readBuff, 0, buffSize)
End While
streamRead.Close()
streamResponse.Close()
myResponse.Close()
Catch ex As Exception
crawlError = Server.HtmlEncode(ex.Message)
End Try
Return (crawlOutput)
End Function
Private Function contentFilter(ByVal data As String) As String
data = Replace(Replace(Replace(Replace(Replace(Replace(data, "\/", "/"), "\""", """"), "\u00253A", ":"), "\u00252F", "/"), "\u200e", ""), "\u003c", "<")
Return (data)
End Function
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim feedContent As String = String.Empty
Dim rssFeed As String = String.Empty
' Querystring Data
Dim feedName As String = CStr(Request.QueryString("name"))
If Len(feedName) = 0 Then : feedName = "default" : End If
' Handle Manual Cache Clearing
If rssCacheClear = 0 Then
Dim maxFeedsTotalAccept As Integer = CInt(Request.QueryString("feedNumber"))
If maxFeedsTotalAccept <= 0 Then : maxFeedsTotalAccept = numberOfPostsShow : End If
' Retrieve Page Since Cache Does Not Exist
If HttpContext.Current.Cache(feedName) Is Nothing OR rawDump = 1 Then
' Get User's Agent Data
crawlAgent = Request.UserAgent
' Load Wall Page
Dim discussionPageData As String = crawlPage(discussionGroupPage)
' Process Page
if Len(crawlError) = 0 Then
' Filter Content
discussionPageData = Replace(discussionPageData, vbCrLf, "")
' Break-up Content
Dim elemLinesRaw() As String = Split(discussionPageData, ">")
' Extract Useful Content
Dim elemLines(,) As String
Dim elemLinesCount As Integer = 0
Dim storyStartFlag As Integer = 0
Dim storyPhoto As String = String.Empty
Dim storyAuthorFlag As Integer = 0
Dim storyAuthor As String = String.Empty
Dim storyQuestionFlag As Integer = 0
Dim storyMsgBodyFlag As Integer = 0
Dim storyStatement As String = String.Empty
For S As Integer = 0 To UBound(elemLinesRaw)
if rawDump = 1 Then
Response.Write(elemLinesRaw(S) & vbcrlf)
Else
' New FB Compensator 11/3/2011 - added </h6 eval
if elemLinesRaw(S).indexOf("\u003c\/h6") > -1 OR elemLinesRaw(S).indexOf("</h6") > -1 Then
' Save Data
if Len(storyPhoto) > 0 AND Len(storyAuthor) > 0 AND Len(storyStatement) > 0 Then
storyAuthor = Server.HtmlDecode(storyAuthor)
storyStatement = Server.HtmlDecode(storyStatement)
' Filter out HTML inserted by the poster
if storyStatement.indexOf("<") > -1 OR storyStatement.indexOf(">") > -1 Then
Dim tmp_Filtered As String = String.Empty
Dim tmp_Flip As Integer = 0
For T As Integer = 0 TO Len(storyStatement)
Dim tmp_contentChar As String = Mid(storyStatement, T + 1, 1)
if tmp_contentChar = "<" Then : tmp_Flip = 1 : End if
if tmp_Flip = 0 Then : tmp_Filtered = tmp_Filtered & tmp_contentChar : End if
if tmp_contentChar = ">" Then : tmp_Flip = 0 : End if
Next
storyStatement = tmp_Filtered
End if
' Limit size of statement
if Len(storyStatement) > rssDescriptionLen Then
storyStatement = Mid(storyStatement, 1, rssDescriptionLen) & "..."
End if
ReDim Preserve elemLines(3, elemLinesCount)
elemLines(0, elemLinesCount) = storyPhoto
elemLines(1, elemLinesCount) = storyAuthor
elemLines(2, elemLinesCount) = storyStatement
elemLines(3, elemLinesCount) = feed_pubdate
elemLinesCount = elemLinesCount + 1
' New FB Compensator 12/13/2011 - variable clearing
storyPhoto = String.Empty : storyStatement = String.Empty : storyAuthor = String.Empty
storyStartFlag = 0 : storyQuestionFlag = 0 : storyMsgBodyFlag = 0 : storyAuthorFlag = 0
End if
' New FB Compensator 12/13/2011 - moved; no longer valid here since multiple ' storyPhoto = String.Empty : storyStatement = String.Empty : storyAuthor = String.Empty
' storyStartFlag = 0 : storyQuestionFlag = 0 : storyMsgBodyFlag = 0 : storyAuthorFlag = 0
End if
if storyStartFlag = 1 Then
' Grab Photo
if elemLinesRaw(S).indexOf("ProfilePhoto") > 0 OR elemLinesRaw(S).indexOf("profilePic") > 0 Then
storyPhoto = Split(Split(contentFilter(elemLinesRaw(S)), "src=""")(1), """")(0)
End if
' Grab Author Types
if storyAuthorFlag = 1 Then
storyAuthor = Split(contentFilter(elemLinesRaw(S)), "</a")(0)
storyAuthorFlag = 0
Elseif storyAuthorFlag = 2 Then
storyAuthor = Split(contentFilter(elemLinesRaw(S)), "</a")(0)
storyAuthorFlag = 3
Elseif storyAuthorFlag = 3 Then
storyAuthor = storyAuthor & " via "
storyAuthorFlag = 4
Elseif storyAuthorFlag = 4 Then
if elemLinesRaw(S).indexOf("\/span") > 0 Then
storyAuthor = storyAuthor & Split(contentFilter(elemLinesRaw(S)), "</span")(0)
Elseif elemLinesRaw(S).indexOf("\u003c\/a") > 0 Then
storyAuthor = storyAuthor & Split(contentFilter(elemLinesRaw(S)), "</a")(0)
End if
storyAuthorFlag = 0
Elseif storyAuthorFlag = 5 Then
if elemLinesRaw(S).indexOf("href=\""") > 0 Then
storyAuthorFlag = 6
Else
storyAuthor = Split(contentFilter(elemLinesRaw(S)), "</div")(0)
storyAuthorFlag = 0
End if
Elseif storyAuthorFLag = 6 Then
storyAuthor = Split(contentFilter(elemLinesRaw(S)), "</a")(0)
storyAuthorFlag = 0
End if
' New FB Compensator 11/3/2011
if storyAuthorFlag = 20 And elemLinesRaw(S).indexOf("<a") > -1 Then
storyAuthorFlag = 21
Elseif storyAuthorFlag = 20 And elemLinesRaw(S).indexOf("</div") > 0 Then
storyAuthor = Split(contentFilter(elemLinesRaw(S)), "</div")(0)
storyAuthorFlag = 0
Elseif storyAuthorFlag = 21 Then
storyAuthor = Split(contentFilter(elemLinesRaw(S)), "</a")(0)
storyAuthorFlag = 0
End if
' Grab Question
if storyQuestionFlag = 1 Then
storyStatement = Split(contentFilter(elemLinesRaw(S)), "</a")(0)
storyQuestionFlag = 0
End if
' Grab Regular Statement
if storyMsgBodyFlag = 1 Then
storyStatement = Split(contentFilter(elemLinesRaw(S)), "</span")(0)
storyMsgBodyFlag = 0
End if
' Start Grabbing Complex Statement Type 2 Data
if storyMsgBodyFlag = 3 Then
storyStatement = storyStatement & Split(contentFilter(elemLinesRaw(S)), "</")(0)
End if
' Grab Complex Statement Type 1
if storyMsgBodyFlag = 2 Then
if elemLinesRaw(S).indexOf("href=\""") > 0 And elemLinesRaw(S).indexOf("rel=\""nofollow") = -1 Then
' Some Type of Tag-Back; Complex Statement Type 2 Data
storyMsgBodyFlag = 3
Else
if elemLinesRaw(S).indexOf("\u003cbr") > 0 Then
storyStatement = Split(contentFilter(elemLinesRaw(S)), "<br")(0)
Elseif elemLinesRaw(S).indexOf("\u003ca") > 0 And elemLinesRaw(S).indexOf("rel=\""nofollow") > 0 Then
storyStatement = Split(contentFilter(elemLinesRaw(S)), "<a href")(0)
Else
storyStatement = Split(contentFilter(elemLinesRaw(S)), "</span")(0)
End if
storyMsgBodyFlag = 0
End if
End if
' New FB Compensator 11/3/2011
if storyMsgBodyFlag = 20 Then
storyStatement = Split(contentFilter(elemLinesRaw(S)), "</span")(0)
storyMsgBodyFlag = 0
End if
' Detect Author Types
if elemLinesRaw(S).indexOf("\""passiveName\""") > 0 Then
' Find Author Type 1
storyAuthorFlag = 1
Elseif elemLinesRaw(S).indexOf("\""actorName\""") > 0 AND storyAuthorFlag = 0 Then
' Find Author Type 2
storyAuthorFlag = 2
Elseif elemLinesRaw(S).indexOf("actorDescription") > 0 AND elemLinesRaw(S).indexOf("data-ft=\""") > 0 Then
' Find Author Type 3
storyAuthorFlag = 5
Elseif elemLinesRaw(S).indexOf("actorName") > 0 AND elemLinesRaw(S).indexOf("data-ft=""&#") > 0 Then
' New FB Change Compensator 11/3/2011
storyAuthorFlag = 20
End if
' Find Question
if elemLinesRaw(S).indexOf("sk=question") > 0 OR elemLinesRaw(S).indexOf("question_id=") > 0 Then
storyQuestionFlag = 1
End if
' Detect Statements
' FB has altered the class reference from \"messageBody\" to include additional classes; compensate for change
if elemLinesRaw(S).indexOf("\""messageBody") > 0 AND elemLinesRaw(S).indexOf("data-ft=\""") = -1 Then
' Find Regular Statement
storyMsgBodyFlag = 1
Elseif elemLinesRaw(S).indexOf("\""messageBody") > 0 AND elemLinesRaw(S).indexOf("data-ft=\""") > 0 Then
' Find Complex Statement
storyMsgBodyFlag = 2
Elseif elemLinesRaw(S).indexOf("""messageBody") > 0 AND elemLinesRaw(S).indexOf("data-ft=""&#") > 0 Then
' New FB Compensator 11/3/2011
storyMsgBodyFlag = 20
End if
End if
' New FB Change Compensator 11/3/2011 - added ""storyContent"" eval
if elemLinesRaw(S).indexOf("\""storyContent\""") > 0 OR elemLinesRaw(S).indexOf("""storyContent""") > 0 Then
storyStartFlag = 1
storyPhoto = String.Empty
storyAuthorFlag = 0
storyAuthor = String.Empty
storyQuestionFlag = 0
storyMsgBodyFlag = 0
storyStatement = String.Empty
End if
End if
Next
if rawDump = 0 Then
' Assemble Data into RSS
if elemLinesCount > 0 Then
' Content returned
Dim feedStep As Integer = 0
For R As Integer = 0 To elemLinesCount - 1
if R < maxFeedsTotalAccept Then
feedContent = feedContent & "<item>" & vbCrLf
feedContent = feedContent & "<title>" & feed_title & "</title>" & vbCrLf
feedContent = feedContent & "<link>" & feed_link & "</link>" & vbCrLf
if rssIncludeImg = 1 Then
feedContent = feedContent & "<description>" & Server.HtmlEncode("<img align=""left"" src=""" & elemLines(0, R) & """ border=""0"" /> ") & Server.HtmlEncode(Replace(elemLines(2, R), "'", "'")) & "</description>" & vbCrLf
Else
feedContent = feedContent & "<description>" & Server.HtmlEncode(Replace(elemLines(2, R), "'", "'")) & "</description>" & vbCrLf
End if
feedContent = feedContent & "<author>" & elemLines(1, R) & "</author>" & vbCrLf
feedContent = feedContent & "<date>" & elemLines(3, R) & "</date>" & vbCrLf
feedContent = feedContent & "</item>" & vbCrLf
End if
Next
Else
' No content found; target is reachable but the source code of the wall has possibly changed
feedContent = feedContent & "<item>" & vbCrLf
feedContent = feedContent & "<title>Page Found But Data Not Recognized</title>" & vbCrLf
feedContent = feedContent & "<link></link>" & vbCrLf
feedContent = feedContent & "<description>Page Found But Data Not Recognized</description>" & vbCrLf
feedContent = feedContent & "<author>Server</author>" & vbCrLf
feedContent = feedContent & "<date>" & feed_pubdate & "</date>" & vbCrLf
feedContent = feedContent & "</item>" & vbCrLf
End if
End if
Else
' No page found; target is unreachable; error
feedContent = feedContent & "<item>" & vbCrLf
feedContent = feedContent & "<title>Page Not Found/Error</title>" & vbCrLf
feedContent = feedContent & "<link></link>" & vbCrLf
if rssShowErrors = 0 Then
feedContent = feedContent & "<description>Either the page specified could not be found or an error has occurred.</description>" & vbCrLf
Else
feedContent = feedContent & "<description>" & crawlError & "</description>" & vbCrLf
End if
feedContent = feedContent & "<author>Server</author>" & vbCrLf
feedContent = feedContent & "<date>" & feed_pubdate & "</date>" & vbCrLf
feedContent = feedContent & "</item>" & vbCrLf
End if ' End Len(crawlError) = 0
if rawDump = 0 Then
' Add RSS Envelope, if specified
if rssIncludeHeader = 1 Then
rssFeed = rssFeed & "<rss version=""2.0"">" & vbCrLf
End if
rssFeed = rssFeed & "<channel>" & vbCrLf
If rssIncludeHeader = 1 Then
rssFeed = rssFeed & "<title>" & feed_title & "</title>" & vbCrLf
rssFeed = rssFeed & "<link>" & feed_link & "</link>" & vbCrLf
rssFeed = rssFeed & "<description>" & feed_description & "</description>" & vbCrLf
rssFeed = rssFeed & "<language>" & feed_language & "</language>" & vbCrLf
rssFeed = rssFeed & "<date>" & feed_pubdate & "</date>" & vbCrLf
rssFeed = rssFeed & "<copyright>" & feed_copyright & "</copyright>" & vbCrLf
rssFeed = rssFeed & "<webmaster>" & feed_webmaster & "</webmaster>" & vbCrLf
End If
rssFeed = rssFeed & feedContent
rssFeed = rssFeed & "</channel>" & vbCrLf
if rssIncludeHeader = 1 Then
rssFeed = rssFeed & "</rss>"
End if
' Add RSS to Server Cache
HttpContext.Current.Cache.Add(feedName, rssFeed, Nothing, DateTime.Now.AddDays(1), System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Normal, Nothing)
End if
Else
' Get Feed From Server Cache
rssFeed = CType(HttpContext.Current.Cache(feedName), String)
End if ' End HttpContext.Current.Cache(feedName) Is Nothing
Else
' Clear Server Cache
HttpContext.Current.Cache.Remove(feedName)
' Compile RSS Data
feedContent = "<item>" & vbCrLf
feedContent = feedContent & "<title>Server Cache Cleared</title>" & vbCrLf
feedContent = feedContent & "<link></link>" & vbCrLf
feedContent = feedContent & "<description>Server Cache Cleared</description>" & vbCrLf
feedContent = feedContent & "<author>Server</author>" & vbCrLf
feedContent = feedContent & "<date>" & feed_pubdate & "</date>" & vbCrLf
feedContent = feedContent & "</item>" & vbCrLf
if rssIncludeHeader = 1 Then
rssFeed = rssFeed & "<rss version=""2.0"">" & vbCrLf
End if
rssFeed = rssFeed & "<channel>" & vbCrLf
If rssIncludeHeader = 1 Then
rssFeed = rssFeed & "<title>" & feed_title & "</title>" & vbCrLf
rssFeed = rssFeed & "<link>" & feed_link & "</link>" & vbCrLf
rssFeed = rssFeed & "<description>" & feed_description & "</description>" & vbCrLf
rssFeed = rssFeed & "<language>" & feed_language & "</language>" & vbCrLf
rssFeed = rssFeed & "<date>" & feed_pubdate & "</date>" & vbCrLf
rssFeed = rssFeed & "<copyright>" & feed_copyright & "</copyright>" & vbCrLf
rssFeed = rssFeed & "<webmaster>" & feed_webmaster & "</webmaster>" & vbCrLf
End If
rssFeed = rssFeed & feedContent
rssFeed = rssFeed & "</channel>" & vbCrLf
if rssIncludeHeader = 1 Then
rssFeed = rssFeed & "</rss>"
End if
End if ' End rssCacheClear = 0
' Generate Output
Response.Buffer = False
If rssIncludeHeader = 1 Then
Response.ContentType = "application/rss+xml"
Else
Response.ContentType = "text/xml"
End If
Response.Write("<" & "?" & "xml version=""1.0"" encoding=""utf-8""" & "?" & ">" & vbCrLf)
Response.Write(rssFeed)
End Sub
</script>
About Joe