Posted by: MC9000 - Tuesday, 3 December 2013 07:36:52
Is it possible to inject an external RSS feed into a topic?
Posted by: Zero2Cool - Tuesday, 3 December 2013 15:00:57
Outside of YAF, yes.
Here's a snippet to get you started off.
[code=csharp]
#region New Topic, Create It
protected bool CreateTopic(string Author, string Subject, string Message, string Description, string Link, int ForumID)
{
using (SqlConnection connection = new SqlConnection(conn.ConnectionString))
{
try
{
connection.Open();
SqlCommand command = new SqlCommand("yaf_topic_save", connection);
command.CommandType = CommandType.StoredProcedure;
Message = string.Format("[quote=[url={0}]{1}[/url]] {2}[/quote]", Link, Author, Message);
int Priority = 0;
command.Parameters.Add(new SqlParameter("@ForumID", ForumID));
command.Parameters.Add(new SqlParameter("@Subject", Subject));
command.Parameters.Add(new SqlParameter("@UserID", 2424));
command.Parameters.Add(new SqlParameter("@Message", Message));
command.Parameters.Add(new SqlParameter("@Description", Description));
//command.Parameters.Add(new SqlParameter("@Status", "RSS"));
command.Parameters.Add(new SqlParameter("@Priority", Priority));
command.Parameters.Add(new SqlParameter("@UserName", DBNull.Value));
command.Parameters.Add(new SqlParameter("@IP", "44.33.22.11"));
//command.Parameters.Add(new SqlParameter("@Posted", PublishedDate));
command.Parameters.Add(new SqlParameter("@Posted", DateTime.UtcNow.AddMinutes(-1)));
command.Parameters.Add(new SqlParameter("@BlogPostID", DBNull.Value));
command.Parameters.Add(new SqlParameter("@Flags", 22));
command.Parameters.Add(new SqlParameter("@UTCTIMESTAMP", DateTime.UtcNow.AddMinutes(-1)));
command.CommandTimeout = 5;
command.ExecuteNonQuery();
return true;
}
catch (Exception ex)
{
ErrorMessage = ex.Message + Environment.NewLine + ex.StackTrace;
return false;
}
}
}
#endregion
[/code]
Posted by: MC9000 - Tuesday, 3 December 2013 21:51:28
Thanks! - I was originally worried about dependencies on the SQL side, but the code is very easy to follow (even for a VB.Net guy)
I wrote a standalone feed reader (for another project) that I can modify to insert the retrieved feed data into the same message record. Simpler than I thought.
Glad to see stored procedures are used in YAF - other projects are eliminating stored procs & replaced everything w/LINQ, but they don't scale at all and run much slower.
Posted by: Zero2Cool - Wednesday, 4 December 2013 14:26:20
Do you have your feed reader as open source? The one I have is kind of a crapshoot. When I add a new feed I have to run it through step by step to ensure the date parser doesn't blow up lol
Posted by: MC9000 - Thursday, 5 December 2013 00:45:45
It's a work in progress and part of a bigger project (I'll probably open-source it eventually).
My code reads a list of RSS feeds from another XML file that loads in the FeedListParams containing the MessageID to update and some stuff to show pics, dates, etc. (I used a structure instead of a class for quick & dirty coding)
Public Structure FeedListParams
Public feeduri As String
Public feedtitle As String
Public messageid As Integer ' the MessageID of the SQL table
Public upperlimit As Integer 'how many RSS feed records to show
Public truncatetochars As Integer 'truncate the Description to this many chars
Public showdate As Boolean
Public showimages As Boolean
Public saveimageslocally As Boolean 'not implemented, but will grab any remote pics, resize& save
Public resizeimages As Boolean
Public maxpixels As Integer 'maximum width pixels - for formatting
Public showasseparatetopics As Boolean 'not implemented yet, but I plan on automatically putting in each feed record into their own separate topics
End Structure
'the FeedItem structure (you can use a class, but, once again, quick & dirty code)
Public Structure FeedItem
Public title As String
Public link As String
Public pubDate As String
Public description As String
Public enclosure As XmlNode 'this node usually has a picture URI - at least WordPress RSS feeds do
End Structure
'in another function, you can call Message = ProcessRSS(f) where f is the structure FeedListParams
'the Message string variable will contain the entire message.
You first have to create the initial topic (and put a filler character to start), make the topic "sticky", find the corresponding MessageID (for that Topic) from the table in the database so you know where to update it.
Public Function ProcessRSS(f As FeedListParams) As String
Dim request As WebRequest = WebRequest.Create(f.feeduri)
Dim response As WebResponse = request.GetResponse()
Dim sb As New StringBuilder("")
Dim rssStream As Stream = response.GetResponseStream()
Dim rssDoc As New XmlDocument()
rssDoc.Load(rssStream)
Dim rssItems As XmlNodeList = rssDoc.SelectNodes("rss/channel/item")
Dim Item As FeedItem
Dim totalCount As Integer = rssItems.Count
If totalCount > f.upperlimit Then
totalCount = f.upperlimit
End If
If totalCount > 0 Then
sb.Append("
" + f.feedtitle + "
")
sb.Append("
")
sb.Append("
")
Dim i As Integer = 0
While i < totalCount
sb.Append("
")
Dim imageURI As String = "../images/sp75.png" 'padding pic
If f.showimages Then
Item.enclosure = rssItems.Item(i).SelectSingleNode("enclosure")
If Item.enclosure IsNot Nothing Then
imageURI = ObjToStr(Item.enclosure.Attributes("url").Value)
End If
End If
sb.Append("")
Item.title = ObjToStr(rssItems.Item(i).SelectSingleNode("title").InnerXml.ToString.Trim).Replace("'", "''")
Item.link = ObjToStr(rssItems.Item(i).SelectSingleNode("link").InnerXml.ToString.Trim).Replace("'", "''")
sb.Append("
")
Item.pubDate = String.Empty
If f.showdate Then
Item.pubDate = ObjToDate(rssItems.Item(i).SelectSingleNode("pubDate").InnerXml.ToString.Trim).ToShortDateString
sb.Append("
Published On: " & Item.pubDate & "
")
End If
'NOTE: I replaced the CDATA tags via simple replace - there are better ways of doing this
Item.description = ObjToStr(rssItems.Item(i).SelectSingleNode("description").InnerXml.ToString.Trim).Replace("", "").Replace("’", "'").Replace("—", "--").Replace("'", "''")
sb.Append("
" & Item.description & "
")
sb.Append("
")
i += 1
End While
sb.Append("
")
End If
Return sb.ToString()
End Function
SOME CSS: (added into the theme css file)
#rsstitle {
color: #295885;
font-size: 12px;
}
.rsswrap {
font-family: Verdana;
line-height: 15px;
color: #000;
}
.rsswrap ul li {
background: none repeat scroll 0 0 rgba(0, 0, 0, 0);
border-bottom: 1px solid #E8E8E8;
display: block;
float: left;
font-size: 11px;
list-style-type: none;
padding: 10px 0;
width: 100%;
}
.rsswrap ul li img {
float: left;
margin-right: 5px;
margin-bottom: 30px;
width: 75px;
border: 0 none;
outline: medium none;
}
.rsswrap ul li a {
color: #295885;
text-decoration: none;
}
.rsswrap ul li a h3 {
color: #295885;
text-decoration: none;
font-size: 14px;
margin: 0;
padding: 0;
}
.rsspubdate {
color: #959595;
font-size: 10px;
}
.rsswrap ul li p {
padding-bottom: 14px;
font-size: 12px;
margin-top: 5px;
margin-bottom: 5px;
}
The stored proc:
CREATE PROCEDURE [dbo].[RSS_EXT_UpdateMessage]
(
@MessageID int,
@Message ntext
)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
update yaf_Message
set [Message]=@Message
where messageID=@MessageID;
SELECT 'SUCCESS';
END TRY
BEGIN CATCH
SELECT 'ERROR';
END CATCH;
END
Posted by: MC9000 - Thursday, 5 December 2013 00:47:32
the winking smileys are supposed to be right parenthesis
Posted by: MC9000 - Thursday, 5 December 2013 00:51:51
Oh, the helper functions: I use these for safely converting objects with optional defaults (been using for years)
Public Shared Function ObjToInt(ByVal o As Object, Optional ByVal DefaultValue As Integer = 0I) As Integer
Dim retval As Integer = DefaultValue
If IsDBNull(o) OrElse IsNothing(o) Then
retval = DefaultValue
Else
Try
If IsNumeric(o) Then
retval = Convert.ToInt32(o)
End If
Catch ex As InvalidCastException
retval = DefaultValue
End Try
End If
Return retval
End Function
Public Shared Function ObjToBoo(ByVal o As Object, Optional ByVal DefaultValue As Boolean = False) As Boolean
Dim retval As Boolean = DefaultValue
If IsDBNull(o) OrElse IsNothing(o) Then
retval = DefaultValue
Else
Try
If TypeOf o Is String Then
Dim s As String = DirectCast(o, String)
Select Case s.ToLower
Case "y", "yes", "t", "true", "1", "-1"
retval = True
Case Else
retval = False
End Select
Else
retval = Convert.ToBoolean(o)
End If
Catch ex As InvalidCastException
retval = DefaultValue
End Try
End If
Return retval
End Function
Public Shared Function ObjToStr(ByVal o As Object, Optional ByVal DefaultValue As String = "") As String
Dim retval As String = DefaultValue
If IsDBNull(o) OrElse IsNothing(o) Then
retval = DefaultValue
Else
Try
retval = Convert.ToString(o)
Catch ex As InvalidCastException
retval = DefaultValue
End Try
End If
Return retval
End Function
Public Shared Function ObjToDate(ByVal o As Object, Optional ByVal DefaultValue As Date = #1/1/1900#) As Date
Dim retval As Date = DefaultValue
If IsDBNull(o) OrElse IsNothing(o) Then
retval = DefaultValue
Else
Try
retval = CType(o, DateTime)
Catch ex As InvalidCastException
retval = DefaultValue
End Try
End If
Return retval
End Function
Posted by: MC9000 - Thursday, 5 December 2013 01:01:12
Here is the feed inside the topic live:
[url=http://goammo.com/default.aspx?g=posts&t=3#post3]RSS feed inside topic message[/url]
warning: it looks like crap if you are in edit mode due to the CSS
Posted by: Zero2Cool - Thursday, 5 December 2013 01:31:28
Cool cool. I'll have to look into this more when I have time. I like the page you created, nice touch with images. The feeds I'm reading I don't believe have a image in the data.
With my RSS feeds, I'm collecting them, storing them in a table, then on this page [url=http://packershome.com/latest.aspx]HERE [/url]I display the 15 most recent articles. If you're logged in, you can see a "Discuss" button and once clicked, it'll create a topic in the forums for discussion. The actual page is all hard coded and needs to be redesigned. If I won the dang lottery I'd have enough time to do this how I want instead of just 'get it done' lol
btw, if you weren't already aware, there's a code BBCode to stop those pesky smilies in YAF. :)
[code=vb]
Public Shared Function ObjToInt(ByVal o As Object, Optional ByVal DefaultValue As Integer = 0I) As Integer
Dim retval As Integer = DefaultValue
If IsDBNull(o) OrElse IsNothing(o) Then
retval = DefaultValue
Else
Try
If IsNumeric(o) Then
retval = Convert.ToInt32(o)
End If
Catch ex As InvalidCastException
retval = DefaultValue
End Try
End If
Return retval
End Function
Public Shared Function ObjToBoo(ByVal o As Object, Optional ByVal DefaultValue As Boolean = False) As Boolean
Dim retval As Boolean = DefaultValue
If IsDBNull(o) OrElse IsNothing(o) Then
retval = DefaultValue
Else
Try
If TypeOf o Is String Then
Dim s As String = DirectCast(o, String)
Select Case s.ToLower
Case "y", "yes", "t", "true", "1", "-1"
retval = True
Case Else
retval = False
End Select
Else
retval = Convert.ToBoolean(o)
End If
Catch ex As InvalidCastException
retval = DefaultValue
End Try
End If
Return retval
End Function
Public Shared Function ObjToStr(ByVal o As Object, Optional ByVal DefaultValue As String = "") As String
Dim retval As String = DefaultValue
If IsDBNull(o) OrElse IsNothing(o) Then
retval = DefaultValue
Else
Try
retval = Convert.ToString(o)
Catch ex As InvalidCastException
retval = DefaultValue
End Try
End If
Return retval
End Function
Public Shared Function ObjToDate(ByVal o As Object, Optional ByVal DefaultValue As Date = #1/1/1900#) As Date
Dim retval As Date = DefaultValue
If IsDBNull(o) OrElse IsNothing(o) Then
retval = DefaultValue
Else
Try
retval = CType(o, DateTime)
Catch ex As InvalidCastException
retval = DefaultValue
End Try
End If
Return retval
End Function
[/code]
Posted by: MC9000 - Thursday, 5 December 2013 09:28:27
Nice site! I still have to figure out how I'm going to seed my forum :)
Posted by: Zero2Cool - Thursday, 5 December 2013 14:11:43
[quote=MC9000;62103]Nice site! I still have to figure out how I'm going to seed my forum :) [/quote]
Thanks.
I have a table of RSS Links that a separate program reads every X minutes. If it finds a new Summary greater than the date of the last one, it inserts into a database. Then the page above just grabs the top 15.
I'm wanting to move it from an EXE and have it done via web service, but I have zero experience with that so it might not even be possible.
Posted by: MC9000 - Saturday, 7 December 2013 02:38:20
check out NopCommerce's scheduled tasks feature (on the admin side) - the source code is free. www.nopcommerce.com,
it's probably a good start since it will run background tasks in asp.net