A Slack Bot that pulls Pixiv information and posts the full image(s) into Slack, with iOS shortcuts.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
3.5 KiB

9 years ago
  1. module SlackRubyBot
  2. module Commands
  3. class Base
  4. class_attribute :routes
  5. def self.send_message(client, channel, text, options = {})
  6. if text && text.length > 0
  7. send_client_message(client, { channel: channel, text: text }.merge(options))
  8. else
  9. send_message_with_gif client, channel, 'Nothing to see here.', 'nothing', options
  10. end
  11. end
  12. def self.send_message_with_gif(client, channel, text, keywords, options = {})
  13. get_gif_and_send({
  14. client: client,
  15. channel: channel,
  16. text: text,
  17. keywords: keywords
  18. }.merge(options))
  19. end
  20. def self.send_gif(client, channel, keywords, options = {})
  21. get_gif_and_send({
  22. client: client,
  23. channel: channel,
  24. keywords: keywords
  25. }.merge(options))
  26. end
  27. def self.logger
  28. @logger ||= begin
  29. $stdout.sync = true
  30. Logger.new(STDOUT)
  31. end
  32. end
  33. def self.default_command_name
  34. name && name.split(':').last.downcase
  35. end
  36. def self.operator(*values, &block)
  37. values.each do |value|
  38. match Regexp.new("^(?<operator>\\#{value})(?<expression>.*)$", Regexp::IGNORECASE), &block
  39. end
  40. end
  41. def self.command(*values, &block)
  42. values.each do |value|
  43. match Regexp.new("^(?<bot>[\\w[:punct:]@<>]*)[\\s]+(?<command>#{value})$", Regexp::IGNORECASE), &block
  44. match Regexp.new("^(?<bot>[\\w[:punct:]@<>]*)[\\s]+(?<command>#{value})[\\s]+(?<expression>.*)$", Regexp::IGNORECASE), &block
  45. end
  46. end
  47. def self.invoke(client, data)
  48. self.finalize_routes!
  49. expression = parse(data)
  50. called = false
  51. routes.each_pair do |route, method|
  52. match = route.match(expression)
  53. next unless match
  54. next if match.names.include?('bot') && !SlackRubyBot.config.name?(match['bot'])
  55. called = true
  56. if method
  57. method.call(client, data, match)
  58. elsif self.respond_to?(:call)
  59. send(:call, client, data, match)
  60. else
  61. fail NotImplementedError, data.text
  62. end
  63. break
  64. end
  65. called
  66. end
  67. def self.match(match, &block)
  68. self.routes ||= {}
  69. self.routes[match] = block
  70. end
  71. private
  72. def self.parse(data)
  73. text = data.text
  74. return text unless data.channel && data.channel[0] == 'D' && data.user && data.user != SlackRubyBot.config.user_id
  75. SlackRubyBot.config.names.each do |name|
  76. text.downcase.tap do |td|
  77. return text if td == name || td.starts_with?("#{name} ")
  78. end
  79. end
  80. "#{SlackRubyBot.config.user} #{text}"
  81. end
  82. def self.finalize_routes!
  83. return if self.routes && self.routes.any?
  84. command default_command_name
  85. end
  86. def self.get_gif_and_send(options = {})
  87. options = options.dup
  88. gif = begin
  89. keywords = options.delete(:keywords)
  90. Giphy.random(keywords)
  91. rescue StandardError => e
  92. logger.warn "Giphy.random: #{e.message}"
  93. nil
  94. end
  95. client = options.delete(:client)
  96. text = options.delete(:text)
  97. text = [text, gif && gif.image_url.to_s].compact.join("\n")
  98. send_client_message(client, { text: text }.merge(options))
  99. end
  100. def self.send_client_message(client, data)
  101. client.message(data)
  102. end
  103. end
  104. end
  105. end