distribution_wrappers 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +102 -0
  3. data/Gemfile.lock +295 -0
  4. data/README.md +22 -0
  5. data/Rakefile +53 -0
  6. data/VERSION +1 -0
  7. data/distribution_wrappers.gemspec +173 -0
  8. data/lib/config/key_chain.yml +70 -0
  9. data/lib/config/key_chain_dev.yml +71 -0
  10. data/lib/distribution_wrappers.rb +64 -0
  11. data/lib/distribution_wrappers/_base.rb +68 -0
  12. data/lib/distribution_wrappers/backstitch/backstitch.rb +267 -0
  13. data/lib/distribution_wrappers/email/_email.rb +48 -0
  14. data/lib/distribution_wrappers/email/template.html.haml +29 -0
  15. data/lib/distribution_wrappers/google/google.rb +129 -0
  16. data/lib/distribution_wrappers/hipchat/hipchat.rb +80 -0
  17. data/lib/distribution_wrappers/office365/office365.rb +51 -0
  18. data/lib/distribution_wrappers/sendgrid/sendgrid.rb +35 -0
  19. data/lib/distribution_wrappers/slack/slack.rb +87 -0
  20. data/lib/helpers/keys.rb +10 -0
  21. data/lib/helpers/text_helper.rb +9 -0
  22. data/lib/models/device_session_distro.rb +5 -0
  23. data/lib/models/distribution_channel_distro.rb +4 -0
  24. data/lib/models/feed_distro.rb +11 -0
  25. data/lib/models/organization_admin_distro.rb +5 -0
  26. data/lib/models/organization_distro.rb +10 -0
  27. data/lib/models/studio_post_version_contact_distro.rb +5 -0
  28. data/lib/models/studio_post_version_distro.rb +5 -0
  29. data/lib/models/team_distro.rb +13 -0
  30. data/lib/models/team_feed_distro.rb +5 -0
  31. data/lib/models/team_member_distro.rb +6 -0
  32. data/lib/models/topic_distro.rb +11 -0
  33. data/lib/models/topic_feed_distro.rb +5 -0
  34. data/lib/models/topic_subscription_distro.rb +9 -0
  35. data/lib/models/user_distro.rb +34 -0
  36. data/test/helper.rb +34 -0
  37. data/test/test_distribution_wrappers.rb +7 -0
  38. metadata +556 -0
@@ -0,0 +1,80 @@
1
+ module DistributionWrappers
2
+ class HipChatWrapper < DistributionWrappers::Base
3
+
4
+ def send_message(recipient)
5
+ super
6
+ client = get_access(@auth[:key])
7
+
8
+ case recipient['contact_type']
9
+ when 'channel'
10
+ client[recipient['identifier']].send('backstitch', @message, :color => "purple", :message_format => "html")
11
+ when 'user'
12
+ client.user(recipient['identifier']).send(@message, :color => "purple", :message_format => "html")
13
+ end
14
+ end
15
+
16
+ def get_contacts
17
+ client = get_access(@auth[:key])
18
+ rooms = client.rooms
19
+
20
+ users = client.users
21
+
22
+ return nil if (rooms.nil? || rooms.length == 0) && (users.nil? || users.length == 0)
23
+
24
+ csv_sting = ""
25
+
26
+ # Loop through the channels just grabbing the names of them (that's all we need for the user)
27
+ rooms.each_with_index do |room, index|
28
+ csv_sting += CSV.generate_line [room.name, room.name, '{"url": null}', 'channel', @params[:channel_id]]
29
+
30
+ if index % 100 == 0
31
+ @params[:temp_file].write(csv_sting)
32
+ csv_sting = ""
33
+ end
34
+ end
35
+
36
+ @params[:temp_file].write(csv_sting)
37
+
38
+ csv_sting = ""
39
+
40
+ users.each_with_index do |user, index|
41
+ icon_url = user.photo_url ? user.photo_url : "null"
42
+ csv_sting += CSV.generate_line [user.name, user.user_id, "{\"url\": \"#{icon_url}\"}", 'user', @params[:channel_id]]
43
+
44
+ if index % 100 == 0
45
+ @params[:temp_file].write(csv_sting)
46
+ csv_sting = ""
47
+ end
48
+ end
49
+
50
+ @params[:temp_file].write(csv_sting)
51
+
52
+ return true
53
+ end
54
+
55
+ private
56
+
57
+ def prepare(identifier=nil)
58
+ base_url = ""
59
+ if ENV['ENVIRONMENT'] == "development"
60
+ base_url = "http://localhost:3000"
61
+ else
62
+ base_url = "https://studio.backstit.ch"
63
+ end
64
+
65
+ params = "contact_id=#{@version_contact.id}&version_id=#{@version_contact.studio_post_version_id}&organization_id=#{@params[:organization_id]}"
66
+
67
+ body_text = "<a href='#{base_url}/posts/#{@params[:post].id}?#{params}'><strong>#{@params[:post].title}</strong></a>"
68
+ body_text += "<br><br>#{TextHelper.clean_text(@params[:post].draft_content)[0..280]}..."
69
+ body_text += "<br><br><a href='#{base_url}/posts/#{@params[:post].id}?#{params}'><img src='#{@params[:post].screenshot_url}'/></a>"
70
+ body_text += "<br><a href='#{base_url}/posts/#{@params[:post].id}?#{params}'><strong>Read More...</strong></a>"
71
+
72
+ return body_text
73
+ end
74
+
75
+ def get_access(key)
76
+ client = HipChat::Client.new(key, :api_version => 'v2')
77
+ client
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,51 @@
1
+ module DistributionWrappers
2
+ class Office365 < DistributionWrappers::Email
3
+
4
+ def send_message(email)
5
+ super
6
+ key = @auth[:key]
7
+ recipients = []
8
+
9
+ # Office 365's API takes addresses in a specific way, so we have to build up an array
10
+ # of recipients before we hit their API
11
+ recipients << {'emailAddress' => {"address" => email['identifier']}}
12
+
13
+ message = {
14
+ 'subject' => @params[:subject],
15
+ 'body' => {
16
+ 'contentType' => 'HTML',
17
+ 'content' => @message
18
+ },
19
+ "toRecipients" => recipients,
20
+ "sender" => {
21
+ "emailAddress" => {
22
+ "address" => @params[:custom_opts]['send_from']
23
+ }
24
+ }
25
+ }
26
+
27
+ send_response = Curl.post('https://graph.microsoft.com/v1.0/me/sendMail', {"Message" => message}.to_json) do |http|
28
+ http.headers['Authorization'] = "Bearer #{key}"
29
+ http.headers['Content-Type'] = 'application/json'
30
+ end
31
+ end
32
+
33
+ def get_contacts
34
+ key = @auth[:key]
35
+ results = []
36
+
37
+ response = RestClient.get('https://graph.microsoft.com/v1.0/me/contacts', {"Authorization" => "Bearer #{key}"})
38
+ contacts = JSON.parse(response.body)
39
+
40
+ csv_string = ""
41
+
42
+ contacts['value'].each do |contact|
43
+ csv_string += CSV.generate_line [contact['displayName'], contact['emailAddresses'].first['address'], '{"url": null}', 'email', @params[:channel_id]]
44
+ end
45
+
46
+ @params[:temp_file].write(csv_string)
47
+
48
+ return true
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,35 @@
1
+ module DistributionWrappers
2
+ class Sendgrid < DistributionWrappers::Email
3
+ include SendGrid
4
+
5
+ def send_message(recipient)
6
+ super
7
+ email = recipient['identifier']
8
+ metadata = {}
9
+ metadata["user_id"] = @params[:user].id if @params[:user]
10
+
11
+ ### Send Sendgrid Email ###
12
+
13
+ # Build request
14
+ data = {"metadata" => metadata}
15
+
16
+ # Post to SendGrid
17
+ api_key = Keys.sendgrid.studio.api_key
18
+ client = SendGrid::API.new(:api_key => api_key)
19
+
20
+ send_from = {
21
+ :email => "#{@params[:custom_opts]['send_from']}@#{Keys.sendgrid.studio.send_from_domain}",
22
+ :name => @params[:user].display_name
23
+ }
24
+
25
+ from = SendGrid::Email.new(send_from)
26
+ subject = @params[:subject]
27
+ to = SendGrid::Email.new(email: email)
28
+ content = SendGrid::Content.new(type: 'text/html', value: @message)
29
+ mail = Mail.new(from, subject, to, content)
30
+
31
+
32
+ response = client.client.mail._('send').post(request_body: mail.to_json)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,87 @@
1
+ module DistributionWrappers
2
+ class SlackWrapper < DistributionWrappers::Base
3
+
4
+ def send_message(recipient)
5
+ super
6
+ client = get_access(@auth[:key])
7
+
8
+ client.chat_postMessage(channel: recipient['identifier'], attachments: [@message], as_user: true)
9
+ end
10
+
11
+ def get_contacts
12
+ url = "https://slack.com/api/channels.list?token=#{@auth[:key]}"
13
+ channels = JSON.parse(RestClient.get(url))['channels']
14
+
15
+ url = "https://slack.com/api/users.list?token=#{@auth[:key]}"
16
+ members = JSON.parse(RestClient.get(url))["members"]
17
+
18
+ return nil if (channels.nil? || channels.length == 0) && (members.nil? || members.length == 0)
19
+
20
+ csv_sting = ""
21
+
22
+ # Loop through the channels just grabbing the names of them (that's all we need for the user)
23
+ channels.each_with_index do |channel, index|
24
+ csv_sting += CSV.generate_line [channel["name"], channel["name"], '{"url": null}', 'channel', @params[:channel_id]]
25
+
26
+ if index % 100 == 0
27
+ @params[:temp_file].write(csv_sting)
28
+ csv_sting = ""
29
+ end
30
+ end
31
+
32
+ @params[:temp_file].write(csv_sting)
33
+
34
+ csv_sting = ""
35
+
36
+ members.each_with_index do |member, index|
37
+ icon_url = member['profile']['image_192'] ? member['profile']['image_192'] : "null"
38
+ csv_sting += CSV.generate_line [member["real_name"], member["id"], "{\"url\": #{icon_url}}", 'user', @params[:channel_id]]
39
+
40
+ if index % 100 == 0
41
+ @params[:temp_file].write(csv_sting)
42
+ csv_sting = ""
43
+ end
44
+ end
45
+
46
+ @params[:temp_file].write(csv_sting)
47
+
48
+ return true
49
+ end
50
+
51
+ private
52
+
53
+ def prepare(identifier=nil)
54
+ base_url = ""
55
+ if ENV['ENVIRONMENT'] == "development"
56
+ base_url = "http://localhost:3000"
57
+ else
58
+ base_url = "https://studio.backstit.ch"
59
+ end
60
+
61
+ params = "contact_id=#{@version_contact.id}&version_id=#{@version_contact.studio_post_version_id}&organization_id=#{@params[:organization].id}"
62
+
63
+ return {
64
+ title: @params[:post].title,
65
+ title_link: "#{base_url}/posts/#{@params[:post].id}?#{params}",
66
+ author_name: @params[:user].display_name,
67
+ color: @params[:organization].highlight_color,
68
+ fallback: @params[:post].title,
69
+ image_url: @params[:post].screenshot_url,
70
+ fields: [
71
+ {
72
+ value: "#{TextHelper.clean_text(@params[:post].draft_content)[0..280]}...",
73
+ short: false
74
+ }
75
+ ]
76
+ }
77
+ end
78
+
79
+ def get_access(key)
80
+ Slack.configure do |config|
81
+ config.token = key
82
+ end
83
+
84
+ return Slack::Web::Client.new
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,10 @@
1
+ require 'settingslogic'
2
+ module DistributionWrappers
3
+ class Keys < Settingslogic
4
+ if ENV['RAILS_ENV'] == 'production'
5
+ source File.join(File.dirname(__FILE__), '..', 'config/key_chain.yml')
6
+ else
7
+ source File.join(File.dirname(__FILE__), '..', 'config/key_chain_dev.yml')
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ class TextHelper
2
+ def self.clean_text(text)
3
+ clean_text = Sanitize.clean(text)
4
+ clean_text.gsub!("\n", " ")
5
+ clean_text.gsub!("\t", " ")
6
+ clean_text.gsub!(/((http|https|ftp|ftps):\/\/)?([a-zA-Z0-9\-]*\.)+[a-zA-Z0-9]{2,4}(\/[a-zA-Z0-9=.?&-]*)?/i, "")
7
+ return clean_text.strip.gsub("&amp;", "&")
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class DeviceSessionDistro < ActiveRecord::Base
2
+ self.table_name = "device_sessions"
3
+
4
+ belongs_to :user, :class_name => "UserDistro", :foreign_key => :user_id
5
+ end
@@ -0,0 +1,4 @@
1
+ class DistributionChannelDistro < ActiveRecord::Base
2
+ self.table_name = 'distribution_channels'
3
+ belongs_to :owner, polymorphic: true
4
+ end
@@ -0,0 +1,11 @@
1
+ class FeedDistro < ActiveRecord::Base
2
+ self.table_name = "feeds"
3
+ serialize :params, JSON
4
+
5
+ belongs_to :owner, polymorphic: true
6
+
7
+ has_many :team_feeds, :class_name => "TeamFeedDistro", :foreign_key => :feed_id
8
+ has_many :teams, :through => :team_feeds
9
+
10
+ has_many :topic_feeds, :class_name => "TopicFeedDistro", :foreign_key => :feed_id
11
+ end
@@ -0,0 +1,5 @@
1
+ class OrganizationAdminDistro < ActiveRecord::Base
2
+ self.table_name = 'organization_admins'
3
+ belongs_to :organization, :class_name => "OrganizationDistro", :foreign_key => :organization_id
4
+ belongs_to :user, :class_name => "UserDistro", :foreign_key => :user_id
5
+ end
@@ -0,0 +1,10 @@
1
+ class OrganizationDistro < ActiveRecord::Base
2
+ self.table_name = 'organizations'
3
+
4
+ has_many :feeds, :as => :owner, :class_name => "FeedDistro"
5
+ has_many :topics, :as => :owner, :class_name => "TopicDistro"
6
+
7
+ has_many :teams, -> { order("is_primary DESC, name") }, :class_name => "TeamDistro", :foreign_key => :organization_id
8
+ has_many :team_members, :through => :teams
9
+ has_many :members, :through => :team_members
10
+ end
@@ -0,0 +1,5 @@
1
+ class PostVersionContactDistro < ActiveRecord::Base
2
+ self.table_name = "studio_post_version_contacts"
3
+
4
+ belongs_to :version, :foreign_key => "studio_post_version_id", :class_name => "PostVersionDistro"
5
+ end
@@ -0,0 +1,5 @@
1
+ class PostVersionDistro < ActiveRecord::Base
2
+ self.table_name = "studio_post_versions"
3
+
4
+ has_many :contacts, :foreign_key => 'studio_post_version_id', :class_name => "PostVersionContact"
5
+ end
@@ -0,0 +1,13 @@
1
+ class TeamDistro < ActiveRecord::Base
2
+ self.table_name = "teams"
3
+ belongs_to :organization, :class_name => "OrganizationDistro", :foreign_key => :organization_id
4
+
5
+ has_many :team_members, :class_name => "TeamMemberDistro", :foreign_key => :team_id
6
+ has_many :members, :through => :team_members
7
+
8
+ has_many :team_feeds, :class_name => "TeamFeedDistro", :foreign_key => :team_id
9
+ has_many :feeds, :through => :team_feeds
10
+
11
+ has_many :owned_feeds, :class_name => 'FeedDistro', :as => :owner
12
+
13
+ end
@@ -0,0 +1,5 @@
1
+ class TeamFeedDistro < ActiveRecord::Base
2
+ self.table_name = 'team_feeds'
3
+ belongs_to :team, :class_name => "TeamDistro", :foreign_key => :team_id
4
+ belongs_to :feed, :class_name => "FeedDistro", :foreign_key => :feed_id
5
+ end
@@ -0,0 +1,6 @@
1
+ class TeamMemberDistro < ActiveRecord::Base
2
+ self.table_name = "team_members"
3
+ belongs_to :team, :class_name => "TeamDistro", :foreign_key => :team_id
4
+ delegate :organization, :to => :team
5
+ belongs_to :member, :class_name => "UserDistro", :foreign_key => :user_id
6
+ end
@@ -0,0 +1,11 @@
1
+ class TopicDistro < ActiveRecord::Base
2
+ self.table_name = "topics"
3
+ serialize :icon, JSON
4
+ serialize :banner, JSON
5
+ serialize :serialized_alias, JSON
6
+ serialize :serialized_promoted_alias, JSON
7
+
8
+ belongs_to :owner, polymorphic: true
9
+ has_many :topic_feeds, :class_name => "TopicFeedDistro", :foreign_key => :topic_id
10
+ has_many :feeds, :through => :topic_feeds
11
+ end
@@ -0,0 +1,5 @@
1
+ class TopicFeedDistro < ActiveRecord::Base
2
+ self.table_name = "topic_feeds"
3
+ belongs_to :topic, :class_name => "TopicDistro", :foreign_key => :topic_id
4
+ belongs_to :feed, :class_name => "FeedDistro", :foreign_key => :feed_id
5
+ end
@@ -0,0 +1,9 @@
1
+ class TopicSubscriptionDistro < ActiveRecord::Base
2
+ self.table_name = "topic_subscriptions"
3
+
4
+ serialize :serialized_alias, JSON
5
+ serialize :serialized_promoted_alias, JSON
6
+
7
+ belongs_to :user, :foreign_key => "user_id", :class_name => "UserDistro"
8
+ belongs_to :topic, :foreign_key => "topic_id", :class_name => "TopicDistro"
9
+ end
@@ -0,0 +1,34 @@
1
+ class UserDistro < ActiveRecord::Base
2
+ self.table_name = "users"
3
+
4
+ has_many :team_memberships, :foreign_key => "user_id", :class_name => "TeamMemberDistro"
5
+ has_many :teams, :through => :team_memberships
6
+
7
+ has_many :organizations, :through => :teams
8
+
9
+ has_many :organization_admins, :foreign_key => "user_id", :class_name => "OrganizationAdminDistro"
10
+ has_many :managed_organizations, :through => :organization_admins, :source => :organization
11
+
12
+ has_many :topic_subscriptions, :class_name => 'TopicSubscriptionDistro', :foreign_key => "user_id"
13
+ has_many :topics, :through => :topic_subscriptions
14
+ has_many :owned_topics, :class_name => 'TopicDistro', :as => :owner
15
+
16
+ def managed_feeds
17
+ self.managed_organizations
18
+ .select("team_feeds.id, feeds.id AS feed_id, teams.id AS team_id, organizations.id AS organization_id, feeds.name, organizations.highlight_color, team_feeds.feed_type")
19
+ .joins({:teams => {:team_feeds => :feed}}).where("team_feeds.feed_type = 'manual'").uniq
20
+ end
21
+
22
+ def avatar_url
23
+ avatar = ""
24
+ if self.avatar != nil
25
+ avatar = self.avatar
26
+ else
27
+ hash = Digest::MD5.hexdigest(self.email)
28
+ default = "https://images-backstitch.s3.amazonaws.com/next/logos/backstitch_purple_icon.png"
29
+ avatar = "https://www.gravatar.com/avatar/#{hash}?d=#{default}"
30
+ # "http://unicornify.appspot.com/avatar/#{hash}?s=128"
31
+ end
32
+ avatar
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ require 'simplecov'
2
+
3
+ module SimpleCov::Configuration
4
+ def clean_filters
5
+ @filters = []
6
+ end
7
+ end
8
+
9
+ SimpleCov.configure do
10
+ clean_filters
11
+ load_adapter 'test_frameworks'
12
+ end
13
+
14
+ ENV["COVERAGE"] && SimpleCov.start do
15
+ add_filter "/.rvm/"
16
+ end
17
+ require 'rubygems'
18
+ require 'bundler'
19
+ begin
20
+ Bundler.setup(:default, :development)
21
+ rescue Bundler::BundlerError => e
22
+ $stderr.puts e.message
23
+ $stderr.puts "Run `bundle install` to install missing gems"
24
+ exit e.status_code
25
+ end
26
+ require 'test/unit'
27
+ require 'shoulda'
28
+
29
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
30
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
31
+ require 'distribution_wrappers'
32
+
33
+ class Test::Unit::TestCase
34
+ end