Sử dụng gem ChatWork
Bài đăng này đã không được cập nhật trong 8 năm
Mở đầu
Hiện tại ChatWork đã cho phép sử dụng API của họ cho đối tượng chính là lập trình viên. Qua việc sử dụng API, một số tác vụ như:
- Thêm thành viên vào một danh sách các group chat
- Gửi tin nhắn thông báo cho các thành viên trong một group chat khi task được cập nhật
- ...
đều có thể được tự động hoá, thay vì phải thực hiện một cách thủ công. Với mục đích bổ sung và mở rộng một bài viết về cách sử dụng ChatWork API trong Ruby, sau đây mình xin giới thiệu cách sử dụng gem ChatWork trong một ứng dụng Rails, để có thể tích hợp chức năng của ChatWork vào Rails một cách đơn giản và hiệu quả hơn.
Chuẩn bị
- Đầu tiên ta sẽ cần phải đăng ký sử dụng ChatWork API tại đây. Theo kinh nghiệm của mình thì yêu cầu sử dụng API sẽ được chấp nhận sau khoảng 4-5h. Sau khi đã nhận được một email thông báo, ta có thể bắt đầu sinh ra API token để sử dụng trong ứng dụng của mình.
-
Sơ lược về API token: Như API documentation giải thích thì mỗi API request đều cần phải chứa một API token trong HTTP header. API token là cách để ChatWork xác thực rằng chính mình là người đã gửi yêu cầu thực thi một hành động nào đó. Dĩ nhiên là với API token thì mình chỉ có thể thực hiện những hành động mà tài khoản của mình có quyền; mình sẽ không thể gửi tin nhắn vào một group chat mà mình không là thành viên chẳng hạn.
-
Khi sử dụng gem ChatWork cũng vậy, trước khi có thể sử dụng bất kỳ một phương thức nào của gem, ta cũng đều phải gán API token đó vào
ChatWork.api_key
. -
Bây giờ ta có thể cái đặt gem ChatWork:
Thêm dòng dưới vào Gemfile
gem "chatwork"
rồi chạy Bundle
$ bundle
Vọc thôi!
Cách dễ nhất để bắt đầu thử nghiệm với gem ChatWork là sử dụng Rails console:
$ rails c
Việc đầu tiên cần làm là gán API token của mình cho biến ChatWork.api_key
:
irb(main):001:0> ChatWork.api_key = "YOUR_API_TOKEN"
=> "YOUR_API_TOKEN"
- Chú ý:
ChatWork.api_key
mặc định nhận giá trị nil, nhưng nếu tồn tại một biến môi trường (environment variable) với tênCHATWORK_API_TOKEN
thì giá trị của biến ấy sẽ được gán luôn choChatWork.api_key
khi chạy Rails console. Trích đoạn code của gem:
def api_key
@api_key || ENV['CHATWORK_API_TOKEN']
end
GET thông tin cá nhân
irb(main):002:0> ChatWork::Me.get
=> {"account_id"=>1700484, "room_id"=>43643696, "name"=>"Tran Trung Hieu", "chatwork_id"=>"framgiavn_hieutt", "organization_id"=>829296, "organization_name"=>"Framgia Vietnam", "department"=>"Education", "title"=>"Intern Ruby", "url"=>"", "introduction"=>"", "mail"=>"kagoromo@gmail.com / tran.trung.hieu@framgia.com", "tel_organization"=>"", "tel_extension"=>"", "tel_mobile"=>"01696441994", "skype"=>"hieuhedspik57a", "facebook"=>"HieuTT.5246", "twitter"=>"", "avatar_image_url"=>"https://tky-chat-work-appdata.s3.amazonaws.com/avatar/948/948256.rsz.jpg"}
irb(main):003:0>
Có thể thấy kết quả trả về của #get là một hash chứa các thông tin cá nhân của mình. Đáng lưu ý nhất là khoá account_id
vì đây là một thông tin bị ẩn khi ta sử dụng ChatWork. Profile, Personal Settings, Admin Settings... không hề hiển thị account_id
; cách duy nhất mà mình biết để có thể thấy được account_id
của một người là quote lại một tin nhắn có To đến người đó.
Cũng cần nói thêm là room_id
ở trên là id của một group chat đặc biệt có tên là My Chat (Nói là đặc biệt vì My Chat được tự động tạo ra khi ta tạo tài khoản và không cho phép ta thêm thành viên khác vào). Đúng vậy, khi mình mở My Chat lên và nhìn thấy URL có dạng như thế này https://www.chatwork.com/#!rid43643696
thì số đằng sau rid chính là room_id
của My Chat, chứ không phải là account_id
như mình đã từng nghĩ.
GET thông tin group chat
irb(main):003:0> ChatWork::Room.get.first
=> {"room_id"=>5126753, "name"=>"FramgiaAll", "type"=>"group", "role"=>"member", "sticky"=>true, "unread_num"=>43, "mention_num"=>0, "mytask_num"=>0, "message_num"=>67101, "file_num"=>358, "task_num"=>12, "icon_path"=>"https://tky-chat-work-appdata.s3.amazonaws.com/icon/38/38686.rsz.png", "last_update_time"=>1469888294}
irb(main):004:0>
Có lẽ không cần giải thích nhiều ngoài một chú ý duy nhất là nếu chạy ChatWork::Room.get
thì kết quả trả về sẽ là một mảng các hash kết quả.
GET thông tin thành viên
irb(main):006:0> ChatWork::Member.get(room_id: "5126753").find {|member| member["name"] == "Tran Trung Hieu"}
=> {"account_id"=>1700484, "role"=>"member", "name"=>"Tran Trung Hieu", "chatwork_id"=>"framgiavn_hieutt", "organization_id"=>829296, "organization_name"=>"Framgia Vietnam", "department"=>"Education", "avatar_image_url"=>"https://tky-chat-work-appdata.s3.amazonaws.com/avatar/948/948256.rsz.jpg"}
irb(main):007:0>
ChatWork::Member.get
trả lại một mảng các hash thông tin thành viên của group chat có id là 5126753. Ta gọi #find trên mảng kết quả ấy để tìm thành viên có tên là "Tran Trung Hieu" và nhận được kết quả như trên. Chú ý sự khác biệt giữa kết quả khi gọi ChatWork::Me.get
và ChatWork::Member.get
: ChatWork::Member.get
trả lại hash kết quả đã bị giảm lược đi rất nhiều thông tin, ví dụ như địa chỉ mail và số điện thoại.
POST tin nhắn mới vào một group chat
irb(main):008:0> ChatWork::Message.create room_id: "43643696", body: "New message sent with ChatWork API!"
=> {"message_id"=>1359692676}
irb(main):009:0>
Để gửi một tin nhắn mới chỉ cần 2 thông tin là room_id
của group chat và body
là nội dung tin nhắn. Khá đơn giản đúng không?
Vậy nếu muốn To ai đó thì sao?
irb(main):009:0> ChatWork::Message.create room_id: "43643696", body: "[To:1700484] Tran Trung Hieu\nNew message sent with a To tag!"
=> {"message_id"=>1359693415}
irb(main):010:0>
Một method to all đơn giản
irb(main):032:0> def to_all room_id
irb(main):033:1> body = ""
irb(main):034:1> ChatWork::Member.get(room_id: room_id).each do |member|
irb(main):035:2* body += "[To:#{member["account_id"]}] "
irb(main):036:2> end
irb(main):037:1> body
irb(main):038:1> end
=> :to_all
irb(main):039:0> to_all 5126753
=> "[To:443536] [To:452830] [To:486624] [To:525092] [To:538118] ... "
Trả về một string chứa các thẻ To cho mọi thành viên của một group chat, tương tự như chức năng @all
của Chat++
PUT thay đổi danh sách thành viên của một group chat
Hiện tại gem ChatWork chưa định nghĩa #create cho ChatWork::Member
nên ta sẽ cần phải tự chỉnh sửa một chút như sau:
irb(main):013:0> module ChatWork
irb(main):014:1> class Member < Entity
irb(main):015:2> install_class_operations :create, :get
irb(main):016:2>
irb(main):017:2* def self.path
irb(main):018:3> "/rooms/%d/members"
irb(main):019:3> end
irb(main):020:2> end
irb(main):021:1> end
=> :path
irb(main):022:0>
irb(main):023:0> ChatWork::Member.create room_id: 54413631, members_admin_ids: "1700484", members_member_ids: "1562784", method: :put
=> {"admin"=>[1700484], "member"=>[1562784], "readonly"=>[]}
irb(main):024:0>
Kết quả sau khi thực hiện ChatWork::Member.create
: group chat với id là 54413631 có 2 thành viên, một thành viên có quyền admin với id 1700484 và một thành viên bình thường với id 1562784. Chú ý method: :put
và phải nhập ít nhất một thành viên vào danh sách có quyền admin.
Áp dụng vào một Rails app
Tạo mới một Rails app
$ rails new try-chatwork
Gemfile
gem "chatwork"
$ bundle
Tạo và sửa một số file như sau:
config/routes.rb
root to: "chatwork#index"
post "/chatwork", to: "chatwork#send_message"
app/controllers/chatwork_controller.rb
class ChatworkController < ApplicationController
def index
end
def send_message
ChatWork.api_key = params[:chatwork_api_token]
name = ChatWork::Me.get["name"]
account_id = ChatWork::Me.get["account_id"]
room_id = ChatWork::Me.get["room_id"]
message_body = "[To:#{account_id}] #{name}\nWell done! You have successfully sent a message using ChatWork's API!"
ChatWork::Message.create room_id: room_id, body: message_body
redirect_to :root
end
end
app/views/chatwork/index.html.erb
<% link_to "Send message", {controller: "chatwork", action: "send_message"}, method: :post %>
<%= form_tag "/chatwork", method: :post do %>
<%=label_tag "chatwork_api_token" %>
<%=text_field_tag "chatwork_api_token"%>
<div><%= submit_tag "Send Message" %></div>
<% end %>
Khởi động Rails server
$ rails c
truy cập vào localhost:3000 và màn hình dưới sẽ hiện lên
Click Send Message sau khi đã điền API token vào khung nhập và My Chat của bạn sẽ nhận được một tin nhắn mới!
Điều gì vừa mới xảy ra?
- Ta đã định nghĩa #send_message trong ChatworkController và đó chính là method thực hiện gửi tin nhắn mới.
- Đầu tiên,
ChatWork.api_key
sẽ được gán cho giá trị API token nhận được qua khung nhập trong view. - Sau đó, lần lượt GET một số thông tin cần thiết như
name
,account_id
vàroom_id
thông quaChatWork::Me.get
. Vì là ChatWork::Me nênname
vàaccount_id
sẽ là tên và id tài khoản của chính mình, cũng nhưroom_id
sẽ chỉ đến My Chat. - Sử dụng các thông tin trên để tạo nên nội dung cho tin nhắn:
account_id
vàroom_id
tạo nên thẻ To. - Tạo tin nhắn mới cho My Chat với
ChatWork::Message.create
Mở rộng hơn một chút nào!
Hãy hình dung một hệ thống làm bài thi trực tuyến. Người dùng khi tạo tài khoản sẽ được yêu cầu nhập tên hiển thị trong ChatWork của mình và join vào một group chat tương ứng với môn học mà họ muốn làm bài thi.
def send_score_to_chatwork admin
ChatWork.api_key = admin.chatwork_api_key
room_id = subject.chatwork_room_id
to_account_id = ChatWork::Member.get(room_id: room_id).find {|member|
member["name"] == user.chatwork_name}["account_id"]
body = I18n.t "exam.chatwork_message", id: to_account_id, name: user.chatwork_name,
score: score, total: subject.number_of_questions, subject: subject.content
ChatWork::Message.create room_id: room_id, body: body
end
Method #send_score_to_chatwork sẽ tìm account_id
của người làm bài thi trong group chat của môn học. Vì sao phải thực hiện tìm account_id
thông qua name
? Như mình đã nói ở trên, để lấy được account_id
thì người dùng sẽ phải nhờ ai đó To mình để, hoặc lục lại một tin nhắn đã To mình nào đó để quote. Theo mình nghĩ thì yêu cầu người dùng nhập tên hiển thị sẽ bớt phiền phức hơn cho họ, mặc dù cách làm này có thể dẫn đến một số lỗi khác mình sẽ trình bày ở dưới đây.
Lỗi tiềm tàng
với API token thì mình chỉ có thể thực hiện những hành động mà tài khoản của mình có quyền
vì vậy, nếu mình thực hiện ChatWork::Member.get
với room_id của một group chat nào đó mình không là thành viên thì sẽ xảy ra lỗi:
irb(main):030:0> ChatWork::Member.get room_id: 999999999
=> #<ChatWork::APIError: You don't have permission to get members in this room>
irb(main):031:0>
irb(main):032:0* ChatWork::Member.get(room_id: 999999999).class
=> ChatWork::APIError
irb(main):033:0>
Khi xảy ra lỗi, hầu hết các method của gem ChatWork đều trả về một Object thuộc class ChatWork::APIError
. Kiểm tra class của kết quả trả về có thể là một cách để xử lý lỗi khi sử dụng gem ChatWork.
Ngoài ra, trong trường hợp tìm kiếm thành viên bằng name
trong mảng kết quả của ChatWork::Member.get
thì rất có thể xảy ra trường hợp không tìm thấy kết quả, thay vì thông tin của thành viên mà ta cần tìm thì ta sẽ nhận được nil
. Cách xử lỹ cùng vẫn là kiểm tra kết quả trước khi sử dụng cho các thao tác tiếp theo.
Một chú ý quan trọng về bảo mật: Chỉ cần có API token của bạn là một người khác có thể làm mọi thứ bạn có quyền làm với tài khoản ChatWork của mình nên việc giữ kín thông tin API token của bản thân là rất quan trọng. Chính vì vậy nên việc lưu trữ API token trong CSDL sẽ không phải là một ý hay, thay vào đó chúng ta có thể lưu API token vào trong biến môi trường CHATWORK_API_TOKEN
. API documentation có nói về vấn đề này và khuyến cáo sử dụng phương thức OAuth2 cho web app thay vì API token khi OAuth2 chính thức được ChatWork hỗ trợ.
Kết luận
Hi vọng bài viết này đã giúp cho các bạn hiểu cách sử dụng gem ChatWork. Mong nhận được đóng góp của các bạn về nội dụng cũng như cách viết của bài viết này nhé. Thân!
Tài liệu tham khảo:
- gem ChatWork: Github, Rubydoc
- API documentation
All rights reserved