The DEV community has become one of the fastest-growing developer blogging platforms. Whether you are posting primarily on the DEV blog or cross-posting your content there from your primary content source, keeping on top of the comments left by users is critical. Few things can be more frustrating to someone trying to engage than receiving no response.
In this step-by-step tutorial, we are going to use both the DEV API and the Orbit API to retrieve blog post comments and add them as a custom activity into Orbit.
tl;dr If you wish to skip the tutorial, the entire code for this project as a Ruby gem that can be installed in your project can be found on GitHub.
You will need the following to complete the steps in this tutorial:
There are two separate API endpoints we need to access on the DEV API in order to get our blog posts comments. Namely, we need to retrieve a list of our articles, and then, we need to retrieve the comments for each article.
The first operation, GET Published Articles, accepts several query parameters. We will be using the username parameter. The username parameter allows us to narrow our article search for a specific user's articles.
The following is the HTTP request for our DEV articles:
{% c-block language="ruby" %}
url = URI("https://dev.to/api/articles?username=#{@username}")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Get.new(url)
response = https.request(request)
articles = JSON.parse(response.body)
{% c-block-end %}
In your code, replace #{@username} with the username of the DEV user you are searching for.
We are now ready to use the articles list to retrieve the comments for each article.
Once we have our list of articles from DEV, we can go ahead and access the next DEV API endpoint of GET Comments by Article ID. This endpoint requires the article ID as a query parameter.
We will build an iterator in our code to loop through the list of articles and request the comments for each one:
{% c-block language="ruby" %}
comments = articles.each do |article|
get_article_comments(article["id"])
end
def get_article_comments(id)
url = URI("https://dev.to/api/comments?a_id=#{id}")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Get.new(url)
response = https.request(request)
comments = JSON.parse(response.body)
return if comments.nil? || comments.empty?
filter_comments(comments)
end
{% c-block-end %}
First, we iterate through each article in articles invoking a method called #get_article_comments passing in the article's ID as the method's parameter.
Next, we create the #get_article_comments method. The method makes an HTTP request to the DEV API endpoint. At the end of the method, we execute another method that we have not yet created called #filter_comments. Inside this next method, we can add any sort of datetime filtering we want to the data as a way to limit the scope if we are working with a lot of DEV blog post comments. In the following example, I restrict the data set to anything less than or equal to one day ago:
{% c-block language="ruby" %}
def filter_comments(comments)
comments.select do |comment|
comment["created_at"] <= 1.day.ago
end
end
{% c-block-end %}
Note: The 1.day.ago functionality in the code snippet above comes from ActiveSupport. To take advantage of it you need to add require "active_support/time" at the top of your Ruby script.
We now have all of the comments that we want to add as custom activities to our Orbit workspace! Let's go ahead and start doing that.
The Orbit API lets you perform a wide range of activities in your Orbit workspace programmatically. The API reference guide is a good starting point for exploration. For our purposes, we will be using the create a new activity for existing or new member API operation.
API access is included with every account! Try it out by signing up today.
The Orbit documentation informs us that when we send a new activity to Orbit through the API, it will also either retrieve an existing member in our workspace or create a new member if an existing one cannot be found. This means we only need to send one HTTP request to Orbit to both create the blog post comment as an activity and attach it to a member!
According to the API reference we need to define an activity_type and a title for the activity, along with member identity information. We will also send more descriptive information to further supplement the record in the workspace, such as a description and a link.
Let's first construct the request body that we will send in the HTTP request. We will create two methods first, #sanitize_commentand #construct_commenter. They both will clean the data we received from the DEV API and put it in the proper format for Orbit.
The #sanitize_comment method removes all the HTML tags from the comments to leave us with just the body of the message.
The #construct_commenter method forms a hash representing the identifying information of the commenter. If the DEV commenter has a Twitter or GitHub username in their DEV profile we add it to the information we send to Orbit.
{% c-block language="ruby" %}
def sanitize_comment(comment)
comment = ActionView::Base.full_sanitizer.sanitize(comment)
comment.gsub("\n", " ")
end
def construct_commenter(commenter)
hash = {
'name': commenter[:name],
'username': commenter[:username]
}
unless commenter[:twitter_username].nil? || commenter[:twitter_username] == ""
hash.merge!('twitter': commenter[:twitter_username])
end
unless commenter[:github_username].nil? || commenter[:github_username] == ""
hash.merge!('github': commenter[:github_username])
end
hash
end
def construct_body
@commenter = construct_commenter(@commenter)
hash = {
activity: {
activity_type: "dev:comment",
key: "dev-comment-#{@comment[:id]}",
title: "Commented on the DEV blog post: #{@article_title}",
description: sanitize_comment(@comment[:body_html]),
occurred_at: @article[:created_at],
link: @article[:url],
member: {
name: @commenter[:name],
devto: @commenter[:username]
}
},
identity: {
source: "devto",
username: @commenter[:username]
}
}
hash[:activity][:member].merge!(twitter: @commenter[:twitter]) if @commenter[:twitter]
hash[:activity][:member].merge!(github: @commenter[:github]) if @commenter[:github]
hash
end
{% c-block-end %}
In the #construct_body method we create a hash with all the data we plan to send to Orbit.
We are now ready to make the POST request to Orbit with our data. This will be a standard Ruby HTTP request using the net/http library:
{% c-block language="ruby" %}
url = URI("https://app.orbit.love/api/v1/#{@workspace_id}/activities")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
req = Net::HTTP::Post.new(url)
req["Accept"] = "application/json"
req["Content-Type"] = "application/json"
req["Authorization"] = "Bearer #{@api_key}"
req.body = construct_body
req.body = req.body.to_json
response = http.request(req)
JSON.parse(response.body)
{% c-block-end %}
Once the activity has been sent to the Orbit API, you should see it soon after in your workspace!
The code in this tutorial comes from a fully-featured Ruby gem that abstracts a lot of the work for you. It also includes a command-line interface (CLI) to make execution even more straightforward.
The code for the gem can be found on GitHub. To install the gem in your project add it to your Gemfile:
{% c-block language="ruby" %}
# Gemfile
gem 'dev_orbit'
{% c-block-end %}
Then, run bundle install from the command line. Once the gem has been included into your project, you can instantiate a client by passing in your relevant DEV and Orbit API credentials:
{% c-block language="ruby" %}
client = DevOrbit::Client.new(
orbit_api_key: '...',
orbit_workspace: '...',
dev_api_key: '...',
dev_username: '...'
)
{% c-block-end %}
To fetch all new comments on your DEV blog posts within the past day, you can invoke the #comments instance method on your client:
{% c-block language="ruby" %}
client.comments
{% c-block-end %}
This method will gather all the comments in the past day from DEV, format them for activities in your Orbit workspace, and make the POST request to the Orbit API to add them.
What if you would like to run this gem once a day to fetch all your latest DEV comments and add them to your Orbit workspace? You could manually run it daily, or you can use GitHub Actions to automate it for you!
GitHub Actions is an environment to run all your software workflows provided by GitHub for free for any public repository. You can use it to run your code's testing suite, to deploy to the cloud or any one of numerous use cases. In our example, we will use GitHub Actions to run this gem once a day on a cron schedule.
Inside your GitHub repository create a folder called .github, and another one called workflows inside the first one. Within the workflows folder create a YAML file called dev_comments.yml. Add the following YAML text into the file:
{% c-block language="ruby" %}
name: Check For New DEV Blog Post Comments and Add to Orbit Workspace
on:
schedule:
- cron: "0 0 */1 * *"
workflow_dispatch:
branches:
- main
jobs:
comments-workflow:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
submodules: recursive
- name: Set up Ruby 2.7.2
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7.2
- name: Ruby gem cache
uses: actions/cache@v1
with:
path: vendor/bundle
key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
restore-keys: |
${{ runner.os }}-gems-
- name: Bundle Install
run: |
gem update --system 3.1.4 -N
gem install --no-document bundler
bundle config path vendor/bundle
bundle install --jobs 4 --retry 3
- name: Check for New Comments
run: |
bundle exec dev_orbit --check-comments
env:
DEV_API_KEY: ${{ secrets.DEV_API_KEY }}
DEV_USERNAME: ${{ secrets.DEV_USERNAME }}
ORBIT_API_KEY: ${{ secrets.ORBIT_API_KEY }}
ORBIT_WORKSPACE_ID: ${{ secrets.ORBIT_WORKSPACE_ID }}
{% c-block-end %}
This YAML workflow assumes that you have uploaded your Gemfile with the dev_orbit gem listed inside of it.
The above workflow creates a Ruby developer environment inside your GitHub Actions instance. It then installs the dependencies listed in your Gemfile, and finally, uses the gem's CLI to check for new blog post comments and add them to your Orbit workspace.
The only other task you need to do in order for this automation to work is to add your credentials for DEV and Orbit into your GitHub repository's secrets settings. You can find your secrets by navigating to "Settings" from within your repository and clicking on "Secrets" in the side navigation bar.
Once your secrets have been added, this workflow will automatically run once a day for you! You can simply go to your Orbit workspace and find the latest DEV blog comments in your member activities without needing to do anything else.
Want to learn more about using the Orbit API? Check out these other resources: