This a C# .NET 8 project I made to have a "YouTube bot" reddit account submit new videos from the Astrogoblin YouTube channel to the Astrogoblin subreddit.
YouTube supports push notifications via PubSubHubbub (also called WebSub), a server-to-server publish/subscribe protocol, where this project specifically uses the "Google PubSubHubbub Hub" to get HTTP POST requests for when new videos are uploaded to the channel and then submitting them to subreddit via the Reddit API.
- Moderation of the 2nd and 3rd latest submission by unsticking 3rd most recent video submission and stickying the 2nd submission.
- Prevention of submitting the same video multiple times by storing the submission and video details in a SQLite database.
- The ability to get details of all previous reddit submissions by using Reddit's JSON URL feature. This URL is set in the "UserPostsInfo" in the config.json file.
- A front-end, where the
/authorize
endpoint has a HTML form to make a "Reddit Authorize url" where the submit button takes you to the Reddit OAuth2 page to authorize the bot account to submit and moderate submissions. - HMAC signature verification to verify the authenticity of the PubSubHubbub Hub POST requests.
- Usage of submission flairs to flair the new submission with a specific flair. Use the Reddit API to get the flair ids for your subreddit.
- Automatic refreshing of the Reddit OAuth2 access token when it expires.
- Automatic refreshing of the PubSubHubbub Hub subscription when it expires.
- Support for running with a --enable-http-logging to enable HTTP Logging
- Support for saving the logs into a "logs" directory with --save-logs flag, with a month-long rollover.
- Support for saving the PubSub and Reddit submission + sticky/unsticky responses with the --save-responses flag.
- / - The Frontend/Index.cshtml page.
- /authorize - The Frontend/Authorize.cshtml page, used to make the reddit authorize url with an HTML form. Has a " state string" that is used in tandem with the /redditRedirect endpoint to verify the authenticity of the Reddit OAuth2 authorization.
- /redditRedirect - A
GET
endpoint that takes the Reddit OAuth2 authorization redirect back to the project and with the code gets the Reddit OAuth2 access token and with the state string verifies the authenticity of the Reddit OAuth2 redirect. - /youtube - A
GET
endpoint that is used by the PubSubHubbub Hub to verify the subscription. - /youtube - A
POST
endpoint that is used by the PubSubHubbub Hub to send the new video details to.
If you want to use this project, you will need:
-
Either the .NET 8 SDK or Docker to run the project.
-
To create a Reddit account and create a Reddit app to get the RedditClientId and RedditSecret. I would recommend using the Postman Reddit API collection and read the Reddit API documentation on GitHub and on Reddit how the Reddit API authorization and authentication works.
-
The YouTube channel ID for the GooglePubSubTopic value in the config.json file. You can get the channel ID by going to this website: https://www.streamweasels.com/tools/youtube-channel-id-and-user-id-convertor/
-
To edit the config.json file with your own UserAgent, UserSubmissionsInfo url and Subreddit values.
-
To create a .NET User Secret using the following JSON format and replace the values with your own:
{ "RedditClientId": "RedditClientId", "RedditRedirectUrl": "RedditRedirectUrl/redditRedirect", "RedditSecret": "RedditSecret", "SubmitFlairId": "SubmitFlairId", "YoutubeCallbackUrl": "YoutubeCallbackUrl/youtube", "HmacSecret": "HmacSecret" }
If you want to run this project locally, like for example using Docker, you will need to use services like localhost.run (uses SSH) or localtunnel (uses npm) to expose the local server to the internet so the PubSubHubbub Hub subscription can get verified and send POST requests to your local server.
In the project directory run the following commands:
docker build -t astrogoblin-youtube-bot .
docker run -d -p 8080:8080 astrogoblin-youtube-bot
Go to http://localhost:8080/ to see the Frontend/Index.cshtml page.
Here is an example the XML data PubSubHubbub sends to server when a new video is uploaded:
<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns:yt="http://www.youtube.com/xml/schemas/2015" xmlns="http://www.w3.org/2005/Atom"><link rel="hub" href="https://pubsubhubbub.appspot.com"/><link rel="self" href="https://www.youtube.com/xml/feeds/videos.xml?channel_id=UCRb4V8WHojbGqEvzL_9g03Q"/><title>YouTube video feed</title><updated>2024-08-26T12:00:12.863874898+00:00</updated><entry>
<id>yt:video:7NyIKlfkznM</id>
<yt:videoId>7NyIKlfkznM</yt:videoId>
<yt:channelId>UCRb4V8WHojbGqEvzL_9g03Q</yt:channelId>
<title>It's... a Ubisoft Game - Star Wars Outlaws PREVIEW #ubisoftpartner #ad</title>
<link rel="alternate" href="https://www.youtube.com/watch?v=7NyIKlfkznM"/>
<author>
<name>astrogoblin</name>
<uri>https://www.youtube.com/channel/UCRb4V8WHojbGqEvzL_9g03Q</uri>
</author>
<published>2024-08-26T12:00:06+00:00</published>
<updated>2024-08-26T12:00:12.863874898+00:00</updated>
</entry></feed>
Here is an example of the JSON response after making a successful Reddit submission:
{"json": {"errors": [], "data": {"url": "https://www.reddit.com/r/astrogoblin/comments/1f50b8d/this_is_a_dumb_game_for_babies/", "drafts_count": 0, "id": "1f50b8d", "name": "t3_1f50b8d"}}}