jabber_agent.rb 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. module Agents
  2. class JabberAgent < Agent
  3. include LongRunnable
  4. include FormConfigurable
  5. cannot_be_scheduled!
  6. gem_dependency_check { defined?(Jabber) }
  7. description <<~MD
  8. The Jabber Agent will send any events it receives to your Jabber/XMPP IM account.
  9. #{'## Include `xmpp4r` in your Gemfile to use this Agent!' if dependencies_missing?}
  10. Specify the `jabber_server` and `jabber_port` for your Jabber server.
  11. The `message` is sent from `jabber_sender` to `jaber_receiver`. This message
  12. can contain any keys found in the source's payload, escaped using double curly braces.
  13. ex: `"News Story: {{title}}: {{url}}"`
  14. When `connect_to_receiver` is set to true, the JabberAgent will emit an event for every message it receives.
  15. Have a look at the [Wiki](https://github.com/huginn/huginn/wiki/Formatting-Events-using-Liquid) to learn more about liquid templating.
  16. MD
  17. event_description <<~MD
  18. `event` will be set to either `on_join`, `on_leave`, `on_message`, `on_room_message` or `on_subject`
  19. {
  20. "event": "on_message",
  21. "time": null,
  22. "nick": "Dominik Sander",
  23. "message": "Hello from huginn."
  24. }
  25. MD
  26. def default_options
  27. {
  28. 'jabber_server' => '127.0.0.1',
  29. 'jabber_port' => '5222',
  30. 'jabber_sender' => 'huginn@localhost',
  31. 'jabber_receiver' => 'muninn@localhost',
  32. 'jabber_password' => '',
  33. 'message' => 'It will be {{temp}} out tomorrow',
  34. 'expected_receive_period_in_days' => "2"
  35. }
  36. end
  37. form_configurable :jabber_server
  38. form_configurable :jabber_port
  39. form_configurable :jabber_sender
  40. form_configurable :jabber_receiver
  41. form_configurable :jabber_password
  42. form_configurable :message, type: :text
  43. form_configurable :connect_to_receiver, type: :boolean
  44. form_configurable :expected_receive_period_in_days
  45. def working?
  46. last_receive_at && last_receive_at > interpolated['expected_receive_period_in_days'].to_i.days.ago && !recent_error_logs?
  47. end
  48. def receive(incoming_events)
  49. incoming_events.each do |event|
  50. log "Sending IM to #{interpolated['jabber_receiver']} with event #{event.id}"
  51. deliver body(event)
  52. end
  53. end
  54. def validate_options
  55. errors.add(:base, "server and username is required") unless credentials_present?
  56. end
  57. def deliver(text)
  58. client.send Jabber::Message.new(interpolated['jabber_receiver'], text).set_type(:chat)
  59. end
  60. def start_worker?
  61. boolify(interpolated[:connect_to_receiver])
  62. end
  63. private
  64. def client
  65. Jabber::Client.new(Jabber::JID.new(interpolated['jabber_sender'])).tap do |sender|
  66. sender.connect(interpolated['jabber_server'], interpolated['jabber_port'] || '5222')
  67. sender.auth interpolated['jabber_password']
  68. end
  69. end
  70. def credentials_present?
  71. options['jabber_server'].present? && options['jabber_sender'].present? && options['jabber_receiver'].present?
  72. end
  73. def body(event)
  74. interpolated(event)['message']
  75. end
  76. class Worker < LongRunnable::Worker
  77. IGNORE_MESSAGES_FOR = 5
  78. def setup
  79. require 'xmpp4r/muc/helper/simplemucclient'
  80. end
  81. def run
  82. @started_at = Time.now
  83. @client = client
  84. muc = Jabber::MUC::SimpleMUCClient.new(@client)
  85. [:on_join, :on_leave, :on_message, :on_room_message, :on_subject].each do |event|
  86. muc.__send__(event) do |*args|
  87. message_handler(event, args)
  88. end
  89. end
  90. muc.join(agent.interpolated['jabber_receiver'])
  91. sleep(1) while @client.is_connected?
  92. end
  93. def message_handler(event, args)
  94. return if Time.now - @started_at < IGNORE_MESSAGES_FOR
  95. time, nick, message = normalize_args(event, args)
  96. AgentRunner.with_connection do
  97. agent.create_event(payload: { event:, time:, nick:, message: })
  98. end
  99. end
  100. def stop
  101. @client.close
  102. @client.stop
  103. thread.terminate
  104. end
  105. def client
  106. agent.send(:client)
  107. end
  108. private
  109. def normalize_args(event, args)
  110. case event
  111. when :on_join, :on_leave
  112. [args[0], args[1]]
  113. when :on_message, :on_subject
  114. args
  115. when :on_room_message
  116. [args[0], nil, args[1]]
  117. end
  118. end
  119. end
  120. end
  121. end