We're just few days after launching chessvision.ai and people reached me out both privately and in the comments suggesting that it'd be nice to build a bot for r/chess that can work with the app and analyze chess images posted on Reddit.
All of us love the awesome u/ChessFenBot that was doing just that, but for some reason, it hasn't been working recently. Perhaps this is why I received some many request to make chessvision.ai working for that use case.
so from now u/chessvision-ai-bot will be pleased to serve you!
Launch on Reddit:
[P] I'm a bot and will serve people analyzing chess positions from images posted on /r/chess
/u/chessvision-ai-bot will serve you to analyze chess positions posted on /r/chess
How to build a bot for Reddit
In this case, the only thing I needed was a part that can observe what's being posted on r/chess subreddit, and for each new published post, extract an image from it, if any, and analyze it with existing chessvision.ai service that I built for the purpose of the Chrome extension.
Fortunately, there is an PRAW which is an awesome wrapper for Reddit API for Python.
Fetching posts
PRAW makes fetching new posts as easy as:
submissions = reddit.subreddit('chess').new(limit=5)
I simply fetch new submissions every 5 minutes or so. For each new submission, first, we check if the bot already analyzed it - it's an important check because we don't want the bot to analyze the same post more than once. If it has not been yet analyzed, we fetch it:
submission = reddit.submission(id=submission_id)
where submission_id
is a unique identifier of a submission.
Extracting image from a post
Next, we need to check if the submission has any images. It's the tricky part because I wanted to handle all reasonable methods of attaching an image to the post - and there can be many!
- Post can be a link type post
- Post can be a text post that has a link to an image in its text part
The first case is easier as PRAW provides an easy way to access the URL of a submission, if any:
url = submission.url
But we need to determine if this url is an url of an image - and don't be tempted to just check if the URL ends with .jpg
or .png
!
The method I ended up with relies on checking the Content-Type
header of server response. The code uses requests
and HTTP HEAD method request to check the Content-Type
without fetching the resource itself.
def is_image_url(url):
# we don't use image/* in order to omit
# .gif and other non-static image types
image_types = (
"image/png",
"image/jpeg",
"image/jpg",
)
try:
r = requests.head(url)
except requests.exceptions.MissingSchema:
return False
try:
return r.headers["content-type"] in image_types
except KeyError:
return False
For the second case, i.e. when the post is a text post and it contains a link to an image, the bot uses a regular expression that finds all urls in submission's text and check each using the approach for the first case.
Once the bot has an image, it gives it to the chessvision.ai service to analyze and if it finds a chess position in the image, the bot posts its response to Reddit. Again, PRAW makes it easy:
submission.reply(message)
where message
is the bot's reply.
Deploying the bot
There are many options here. I heard many people run their bots on their local machines which is fine if the bot doesn't have to run 24/7, but it my case I wanted it to be properly deployed on a server so I went for Google Cloud deploy. Heroku is another choice which is very popular.
What's next
I have plans to add more useful features for the bot. Stay tuned!