RSS Feed for Memes in C#

Article

This is a project I had on a todo list for a while and I finally made the time to do it. The idea is I want bots to post daily memes automatically on platforms like Discord. I decided the mechanism to distribute memes would be an RSS feed, since it is platform agnostic. However, I will be focusing on Discord for the scope of this write-up.

First RSS Feed

I decided to host the RSS feed on this site, fracturedcode.net. I had to create some database schema to facilitate this. I decided to move all content on the site from the filesystem to the database, in a Content table. Each Post referenced some Content. The actual content was stored in a bytea column which just holds binary data. This means it can hold text, images, executables...pretty much anything.

insert into "Content" values (
	'edb5ef4c-8cc2-46ff-a0d2-f215f43063d6',
	'2021-09-18T08:44:52+0000',
	0,
	pg_read_binary_file('/fractured-code-net/sysadmin/vps-config-ssh-tunnels-docker-nginx')::bytea
)
Migrating the text content from files to the new Content table

I then created a PostType table to differentiate between different types of posts, like blog vs meme. Each Post has a PostTypeId.

https://i.imgur.com/Z9r1XoQ.png

The PostType table.

Retrieving the necessary data to construct the RSS feed involves fetching all published posts of type Meme, and prefetching their Content. Encoding images in base64 and returning them would be impractical considering all the bandwidth required. Instead, the RSS items contain a url. Just like any post, the post topic ("meme") followed by it's SeoName will take you to the image:

https://fracturedcode.net/meme/text-editor-alignments

https://fracturedcode.net/meme/text-editor-alignments as an example of the /meme/seo-name format

Tying Into the Feed

Originally, I tried to use the Socialfeeds Discord bot, which was already in my server for posting certain tweets. The process seemed straightforward enough, but I couldn't get it to work. I tried adding other feeds in case it was just my feed that was causing the issue. Then, I tried contacting their support, but they didn't seem to think it was on their end. This kind of frustrated me, so I just gave up and moved onto something else for a bit.

In the meantime, I setup the Integromat bot to read and post new items from the RSS feed as a stopgap.

Submit Your Own Memes

At this point I had decided I was going to present this topic for my computer science club meeting. I wanted to get other students involved, so I set up a page for students to submit their own memes for the bot to post. I added a MemeProposal table to the database to facilitate this. I didn't really put a lot of effort into the page.

https://i.imgur.com/KZG4mh8.png

The SubmitMeme page

I also have a super-secret dashboard to approve the memes and queue them up to be posted to the RSS feed. It doesn't look the greatest, but I really just needed something to make my life on the backend a little easier.

https://i.imgur.com/tIIEWDZ.png

The meme submittal management page.

Latest Meme Sidebar

At around this point I created a "Latest Meme" sidebar for the site. It simply displays the last posted meme.

https://i.imgur.com/v2wbIye.png

CS Club Presentation

This was the first CS club meeting of the year, which meant it was important to draw in as many students as possible. I already had a pretty good topic, that is, memes. I decided that hosting the meeting with Discord would also be a good idea because every student has it, especially CS students.

https://i.imgur.com/ic4MSrN.png

The CS club flyer

The turnout was actually really great, but only two memes have been submitted so far! Feel free to submit your own.

Getting Rid of Integromat

I had spun up an instance of the Red Discord Bot for other reasons. There is a third party plugin that allows posting of RSS feeds, so I installed that. Unfortunately, it didn't seem to like my RSS feed.

https://i.imgur.com/CO2DIhQ.png

The RSS feed parsing error.

So I corrected the issues, which were encoding related to encoding. This is the code I ended up with that spits out the feed. For this I used the RssSyndication library.

[HttpGet]
[Route("Feed/GetMemeFeed")]
public async Task<IActionResult> GetMemeFeed()
{
    Feed feed = new()
    {
        Title = "FracturedCode's Meme Feed",
        Description = "The best technology and programming related memes served daily",
        Language = "English",
        Link = new Uri("https://fracturedcode.net/Feed/GetMemeFeed"),
    };n

    feed.Items = (await _dbContext.Post
        .Where(p => p.PostTypeId == (int)PostTypeEnum.Meme
            && p.IsPublished
	            && p.PublishedDate <= DateTime.Now
        )
        .Include(p => p.Topic)
        .OrderByDescending(p => p.PublishedDate)
        .ToListAsync()
        .ConfigureAwait(false))
        .ConvertAll(p =>
            {
                string contentUrl = $"https://{Request.Host.Value}/{p.Topic.SeoKeyword}/{p.SeoName}";
                return new Item
                {
                    Title = p.Name,
                    Guid = p.PostGuid.ToString(),
                    Body = contentUrl,
                    Permalink = contentUrl,
                    PublishDate = p.PublishedDate
                };
            }
        );

    return File(Encoding.GetEncoding("UTF-16").GetBytes(feed.Serialize()), "application/rss+xml; charset=utf-16");
}
the endpoint /Feed/GetMemeFeed

Socialfeeds still wouldn't work after I corrected some of the issues, but Red did!

https://i.imgur.com/aZFmz25.png

The moment I successfully got the bot to post the feed.

I disconnected Integromat, and now Red posts to both the CS club discord and my personal server.

Conclusion

I am very pleased with these results. This experiment has paved the path for future plans I have for this site. The work that was done on the backend to abstract posts into any type of post and the new way of fetching content will make things much easier in the future. I will be sure to post about those activities when they happen.

You can use the feed yourself at this endpoint:

https://fracturedcode.net/Feed/GetMemeFeed