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.

88 lines
2.2KB

  1. require 'twitter'
  2. require 'twitter-text'
  3. require 'sanitize'
  4. require 'cgi'
  5. require 'ostruct'
  6. ::Twitter::Validation::MAX_LENGTH = 280
  7. class CrossPost
  8. class Twitter
  9. def initialize(config)
  10. settings = config[:settings]
  11. @posts = config[:posts]
  12. config = {
  13. consumer_key: settings['twitter.consumer.key'],
  14. consumer_secret: settings['twitter.consumer.secret'],
  15. access_token: settings['twitter.access.token'],
  16. access_token_secret: settings['twitter.access.secret']
  17. }
  18. @client = ::Twitter::REST::Client.new config
  19. @stream = ::Twitter::Streaming::Client.new config
  20. end
  21. def post(content, media = [], id:, reply_to:)
  22. reply_to = OpenStruct.new id: reply_to unless reply_to.respond_to? :id
  23. media = media.collect { |f| @client.upload f }
  24. parts = split content
  25. unless media.empty?
  26. first, *parts = parts
  27. reply_to = @client.update first, media_ids: media.join(','), in_reply_to_status: reply_to
  28. end
  29. parts.each { |p| reply_to = @client.update p, in_reply_to_status: reply_to }
  30. reply_to = reply_to.id if reply_to.respond_to? :id
  31. @posts.put id, reply_to, save: true
  32. end
  33. WHITESPACE_TAGS = {
  34. 'br' => { before: "\n", after: '' },
  35. 'div' => { before: "\n", after: "\n" },
  36. 'p' => { before: "\n", after: "\n" }
  37. }.freeze
  38. def post_status(status)
  39. content = status.content
  40. content = Sanitize.clean(content, whitespace_elements: WHITESPACE_TAGS).strip
  41. content = CGI.unescape_html content
  42. media = status.media_attachments.collect { |f| open f.url }
  43. LOGGER.info { 'Sending to twitter' }
  44. LOGGER.debug { " Content: #{content}" }
  45. LOGGER.debug { " Attachments: #{media.size}" }
  46. reply = status.in_reply_to_id
  47. reply_to = reply ? @posts[reply] : nil
  48. self.post content, media, id: status.id, reply_to: reply_to
  49. media.each do |f|
  50. f.close
  51. f.unlink
  52. end
  53. end
  54. private
  55. def split(text)
  56. parts = []
  57. part = ''
  58. words = text.split /\ /
  59. words.each do |word|
  60. old_part = part
  61. part += ' ' unless part == ''
  62. part += word
  63. invalid = ::Twitter::Validation.tweet_invalid? part
  64. if invalid
  65. parts << old_part
  66. part = word
  67. end
  68. end
  69. parts << part unless part == ''
  70. parts
  71. end
  72. end
  73. end