Implementing a Coffee-Chat Bot for RocketChat in Ruby
I’ve been helping my husband with his project lately. I’m building small scripts that collect data, process it and send it to RocketChat as notifications.
We are using self hosted RocketChat, with the help of a good friend.
Short story
My husband has an education project, around how to make informed investments in Bucharest Stocks Market.
Currently there are about 400 users in the community, from which maybe around 20 are actively contributing in the RocketChat group channels.
A while ago we had a discussion and we did a brainstorming of how we could improve collaboration in the community my husband is building.
In order to facilitate and help members to know each other and share ideas we would need an environment for them to socialize.
Inspired by Donut I started to look for something similar for RocketChat. I did not find something similar.
I started to look for how this can be implemented as RocketChat has a powerful API on which I already used successfully for other scripts in combination with GitLab CI/CD
Proposal
Steps for implementing a Coffee Chat Bot:
- On a weekly base get all members of a given channel.
- Match the members in pairs.
- Send each member a private message from the coffee-chat bot to inform about the person to have a chat with the current week.
- Send a message in the coffee channel to summarize how many coffee chat were set that week.
- Consider the odd case of number of members, in our case we choose to have a fallback user which will be removed from the list.
- Remove the coffee-chat bot user from the members list.
- Set up the CI/CD scheduled job in GitLab.
Using rocketchat-ruby gem
I’ve been already using successfully rocketchat-ruby gem for a couple of small projects, many thanks to the author Andrew Bromwich.
For the Coffee Chat Bot I need the list of members for a given channel. There is no API currently so I had to add my own method.
I opend an issue to contribute to the gem with adding this method. Meanwhile the method lives under the Rocket::Channel
class.
module Rocket
class Channel < RocketChat::Messages::Channel
def members(offset: nil, count: nil, sort: nil, fields: nil, query: {})
response = session.request_json(
"/api/v1/channels.members",
body: build_list_body(offset, count, sort, fields, query).merge(coffee_channel_params(query))
)
response['members'].map { |hash| RocketChat::User.new hash } if response['success']
end
private
def coffee_channel_params(query)
room_params(query[:room_id],query[:room_name])
end
end
end
Later using the members
method we can get the full list of members of a given channel, shuffle and pair it.
# coffee.rb
require 'rocketchat'
require_relative 'lib/rocket/channel'
ROCKET_LOGIN = ARGV[0]
ROCKET_PASSWORD = ARGV[1]
ROCKET_CHANNEL = ARGV[2]
ROCKET_URL = ARGV[3]
FALLBACK_USER = ARGV[4]
rocket_server = RocketChat::Server.new(ROCKET_URL)
session = rocket_server.login(ROCKET_LOGIN, ROCKET_PASSWORD)
channel = Rocket::Channel.new(session)
members = channel.members(offset: offset, count: count, query: { room_name: ROCKET_CHANNEL })
# Remove the bot user
members.reject!{ |member| member.username == ROCKET_LOGIN}
# Remove the fallback user in case of odd number of members
# in order to avoid matching with nil
if members.size.odd?
members.reject!{ |member| member.username == FALLBACK_USER }
End
shuffled = members.shuffle.each_slice(2).to_a
shuffled.each do |member1, member2|
session.chat.post_message(room_id: member1.id, text: "Hello, @#{member1.username}! Your coffee-chat partner for this week is @{member2.username}#")
session.chat.post_message(room_id: member2.id, text: "Hello, @#{member2.username}! Your coffee-chat partner for this week is @{member1.username}#")
end
# Post summary message in coffee-chat channel
session.chat.post_message(room_id: ROCKET_CHANNEL, text: "There were #{shuffled.size} coffee-chats set up this week")
Use of this would be
ruby coffee.rb 'coffee.bot.username' 'coffeebotpass' coffee-chat-channel https://your.rocketchat.url/ fallback.username
This will take all members in coffee-chat-channel
shuffle them, match them into pairs and remove if necessary the fallback username and the coffee.bot.username
Setting up a scheduled job in GitLab
Add the gitlab-ci.yml
file to your repo with job:on-schedule:
default:
image: ruby:2.7.2
before_script:
- apt-get update
- ruby -v
- which ruby
- gem install bundler --no-document
- bundle install --jobs $(nproc) "${FLAGS[@]}"
job:on-schedule:
only:
- schedules
script:
- >
ruby coffee.rb $ROCKET_LOGIN $ROCKET_PASSWORD $ROCKET_CHANNEL $ROCKET_URL $FALLBACK_USER;
artifacts:
paths:
- public
From the Menu: CI/CD
-> Schedules
-> New Schedule
create a new schedule
Add the ENV vars $ROCKET_LOGIN $ROCKET_PASSWORD $ROCKET_CHANNEL $ROCKET_URL $FALLBACK_USER;
Good to know
coffee.bot.username
should be a RocketChat bot user, not special permissions needed.coffee.bot.username
should be member of thecoffee-chat-channel
channel.- I have used a public channel as a coffee-chat-channel` channel.
- You might want to have a test channel to test first if the script is behaving as intended.
- As I have multiple custom integrations I build for RocketChat I prefer to have separte bot users.
Toughts
Using GitLab for these simple tasks is so easy and free. I have a couple of more examples to share with you in future.
I used ruby
as it is the programming language I’m most familiar with and I use it on a daily basis. The same result can be achived in other programming languages or using shell scripting(I might try this too).
Reach out on my email, happy to help setting up your own coffee-chat bot and answer to your questions.
🐞Stay safe and be kind!🐞
💜Alina