twitter_publish_agent.rb 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. module Agents
  2. class TwitterPublishAgent < Agent
  3. include TwitterConcern
  4. cannot_be_scheduled!
  5. description <<~MD
  6. The Twitter Publish Agent publishes tweets from the events it receives.
  7. #{twitter_dependencies_missing if dependencies_missing?}
  8. To be able to use this Agent you need to authenticate with Twitter in the [Services](/services) section first.
  9. You must also specify a `message` parameter, you can use [Liquid](https://github.com/huginn/huginn/wiki/Formatting-Events-using-Liquid) to format the message.
  10. Additional parameters can be passed via `parameters`.
  11. Set `expected_update_period_in_days` to the maximum amount of time that you'd expect to pass between Events being created by this Agent.
  12. If `output_mode` is set to `merge`, the emitted Event will be merged into the original contents of the received Event.
  13. MD
  14. event_description <<~MD
  15. Events look like this:
  16. {
  17. "success": true,
  18. "published_tweet": "...",
  19. "tweet_id": ...,
  20. "tweet_url": "...",
  21. "agent_id": ...,
  22. "event_id": ...
  23. }
  24. {
  25. "success": false,
  26. "error": "...",
  27. "failed_tweet": "...",
  28. "agent_id": ...,
  29. "event_id": ...
  30. }
  31. Original event contents will be merged when `output_mode` is set to `merge`.
  32. MD
  33. def validate_options
  34. errors.add(:base,
  35. "expected_update_period_in_days is required") unless options['expected_update_period_in_days'].present?
  36. if options['output_mode'].present? && !options['output_mode'].to_s.include?('{') && !%(clean merge).include?(options['output_mode'].to_s)
  37. errors.add(:base, "if provided, output_mode must be 'clean' or 'merge'")
  38. end
  39. end
  40. def working?
  41. event_created_within?(interpolated['expected_update_period_in_days']) && most_recent_event && most_recent_event.payload['success'] == true && !recent_error_logs?
  42. end
  43. def default_options
  44. {
  45. 'expected_update_period_in_days' => "10",
  46. 'message' => "{{text}}",
  47. 'parameters' => {},
  48. 'output_mode' => 'clean'
  49. }
  50. end
  51. def receive(incoming_events)
  52. # if there are too many, dump a bunch to avoid getting rate limited
  53. if incoming_events.count > 20
  54. incoming_events = incoming_events.first(20)
  55. end
  56. incoming_events.each do |event|
  57. tweet_text, parameters = interpolated(event).values_at('message', 'parameters')
  58. new_event = interpolated['output_mode'].to_s == 'merge' ? event.payload.dup : {}
  59. begin
  60. tweet = publish_tweet(tweet_text, parameters.presence || {})
  61. rescue Twitter::Error => e
  62. new_event.update(
  63. 'success' => false,
  64. 'error' => e.message,
  65. 'failed_tweet' => tweet_text,
  66. 'agent_id' => event.agent_id,
  67. 'event_id' => event.id
  68. )
  69. else
  70. new_event.update(
  71. 'success' => true,
  72. 'published_tweet' => tweet_text,
  73. 'tweet_id' => tweet.id,
  74. 'tweet_url' => tweet.url,
  75. 'agent_id' => event.agent_id,
  76. 'event_id' => event.id
  77. )
  78. end
  79. create_event payload: new_event
  80. end
  81. end
  82. def publish_tweet(text, parameters = {})
  83. twitter.update(text, parameters)
  84. end
  85. end
  86. end