Class: Salesforce::ChatterFeed

Inherits:
Object
  • Object
show all
Defined in:
lib/salesforce/chatter_feed.rb

Overview

This is the abstract to the ‘XXXFeed’ table in Salesforce Chatter

Note: FeedPost cannot be directly queried. It must go through its parent. For example: SELECT Id, Type, FeedPost.Body FROM AccountFeed WHERE ParentId = AccountId ORDER BY CreatedDate DESC

SalesObject’s 3 digits code for the KeyPrefix:

ID   Prefix Entity Type
001 
006 Opportunity
003 Contact
00Q Lead
701 Campaign
00V Campaign Member
00D Organization
005 User
00E Profile
00N Custom Field Definition

0D5  FeedItem (post by everyone)
0F7  FeedPost (post made by this user)

See: eng.genius.com/blog/2009/05/17/salesforcecom-api-gotchas-2/

Constant Summary collapse

BASE_FRAG =

fields do

timestamps

end

"Id, CreatedDate, Type, CreatedBy.Name, CreatedBy.Id"
FEEDPOST_WITH_CONTENT_DATA_FRAG =
"FeedPost.Id, FeedPost.FeedItemId, FeedPost.ParentId, FeedPost.Type,\nFeedPost.CreatedById, FeedPost.CreatedDate, FeedPost.SystemModStamp,\nFeedPost.Title, FeedPost.Body, FeedPost.LinkUrl,\nFeedPost.ContentData, FeedPost.ContentFileName, FeedPost.ContentDescription,\nFeedPost.ContentType, FeedPost.ContentSize\n"
FEEDPOST_WITHOUT_CONTENT_DATA_FRAG =
"FeedPost.Id, FeedPost.FeedItemId, FeedPost.ParentId, FeedPost.Type,\nFeedPost.CreatedById, FeedPost.CreatedDate, FeedPost.SystemModStamp,\nFeedPost.Title, FeedPost.Body, FeedPost.LinkUrl, FeedPost.ContentSize\n"
CREATOR_FRAG =
"CreatedBy.FirstName, CreateBy.LastName, CreatedBy.Id"
FEED_TRACKED_CHANGE_FRAG =
"Select Id, FieldName, OldValue, NewValue From FeedTrackedChanges\n  ORDER BY Id Desc\n"
FEED_COMMENT_FRAG =
"Select Id, CommentBody, CreatedDate, CreatedBy.Id, CreatedBy.FirstName,\n  CreatedBy.LastName FROM FeedComments ORDER BY CreatedDate\n"

Instance Method Summary collapse

Constructor Details

#initializeChatterFeed

Returns a new instance of ChatterFeed.



25
26
27
28
29
30
31
# File 'lib/salesforce/chatter_feed.rb', line 25

def initialize
  #### define @logger
  # http://ruby-doc.org/core/classes/@logger.html
  # TODO use a log file, rather than Standout
  @logger = Logger.new(STDOUT)
  #@logger.level = @logger::WARN
end

Instance Method Details

#get_all_chatter_feeds_with_attachments(object_id, object_type, binding, directory_name, limit = 100, get_attachment = true, query_string = nil) ⇒ Object

  1. It returns the attached file.

  2. ‘object_id’ corresponds to the ‘parent_id’ column in the ‘XXXFeed’ table

  3. ‘object_type’ can be one of the followings

    , Asset, Campaign, Case, Lead, Contact, Contract, Opportunity,
    Product2, Solution, User
    **Note**: UserProfileFeed and NewsFeed are special cases.
      UserProfileFeed  -> select ... from UserProfileFeed with Userid='userid'
      NewsFeed -> select ... from NewsFeed where parentid = 'userid'
    
  4. ‘binding’ can be passed in directly or using the inherited binding from the ‘Salesforce::SfBase’ base class.

  5. ‘directory_name is the directory in ’public/tmp’ for saving the attachment

  6. ‘limit is the number of records to return

  7. ‘get_attachment’ is a boolean flag, true gets the attachment,

    false does not get the attachment
    
  8. query_string is used to search against the Salesforce. Note, if “object_id’ is specified, query_string is ignored.

  9. returns Ruby Array of matching records

  10. TODO add conditions, e.g.

    search -> where FeedPost.CreatedDate > 2007-08-06T03:23:00.000Z and FeedPost.Body like '%post%'
    pagination ->
    


97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/salesforce/chatter_feed.rb', line 97

def get_all_chatter_feeds_with_attachments(object_id, object_type, binding, directory_name, limit=100, get_attachment=true, query_string=nil)
  begin
    #e.g. select Id, type, FeedPost.body from UserProfileFeed WITH UserId = '005A0000000S8aIIAS'
    if !object_id.nil?
      qstring = "      SELECT \#{BASE_FRAG}, \#{FEEDPOST_WITHOUT_CONTENT_DATA_FRAG},\n      (\#{FEED_TRACKED_CHANGE_FRAG}), (\#{FEED_COMMENT_FRAG} LIMIT \#{limit})\n      FROM \#{object_type}Feed where parentid = \\'\#{object_id}\\'\n      ORDER BY CreatedDate DESC limit \#{limit}\n      HERE\n    elsif !query_string.nil?\n      # this is more like a search....\n      qstring = <<-HERE\n      SELECT \#{BASE_FRAG}, \#{FEEDPOST_WITHOUT_CONTENT_DATA_FRAG},\n      (\#{FEED_TRACKED_CHANGE_FRAG}), (\#{FEED_COMMENT_FRAG} LIMIT \#{limit})\n      FROM \#{object_type}Feed where FeedPost.Body like \\'%\#{query_string}%\\'\n      ORDER BY CreatedDate DESC limit \#{limit}\n      HERE\n    else\n      qstring = <<-HERE\n      SELECT \#{BASE_FRAG}, \#{FEEDPOST_WITHOUT_CONTENT_DATA_FRAG},\n      (\#{FEED_TRACKED_CHANGE_FRAG}), (\#{FEED_COMMENT_FRAG} LIMIT \#{limit})\n      FROM \#{object_type}Feed ORDER BY CreatedDate DESC limit \#{limit}\n      HERE\n    end\n\n\n    @logger.info('qstring: ' + qstring)\n    # Note, if query FeedPost.ContentData, Salesforce only returns 1 entry at\n    # a time, you will get a 'queryLocator', which can be used by calling\n    # 'queryMore(queryLocator)'\n\n    feed_results = Array.new\n\n    results = binding.query(:queryString => qstring)\n    if results.queryResponse.result.records.is_a?(Hash)\n      # User has made only one feedpost\n      feed = Hash.new\n      feed = results.queryResponse.result.records\n      if (!feed.FeedPost.nil?) && (feed.FeedPost.ContentSize.to_i > 0)\n        feed = get_single_chatter_feed_with_attachment(feed.FeedPost.Id, feed[:type], binding, directory_name)\n      end\n      feed_results << feed\n    elsif results.queryResponse.result.records.is_a?(Array)\n      results.queryResponse.result.records.each do |an_feed_entry|\n        if (an_feed_entry.is_a?(Hash))\n          if (an_feed_entry[:Type] == \"TrackedChange\")\n            # This is a TrackedChange Feed, the FeedPost Body is nil\n            feed = Hash.new\n            feed = an_feed_entry\n            feed_results << feed\n          elsif (!an_feed_entry.FeedPost.nil?) && (an_feed_entry.FeedPost.ContentSize.to_i > 0) && (get_attachment)\n            # This signifies that:\n            #   1. results.queryResponse.result.records.FeedPost.Type is of \"ContentPost\"\n            #   2. results.queryResponse.result.records.FeedPost.type should be of \"FeedPost\"\n            an_entry_with_attachment = get_single_chatter_feed_with_attachment(an_feed_entry.FeedPost.Id, an_feed_entry[:type], binding, directory_name)\n            feed_results << an_entry_with_attachment\n          else\n            feed = Hash.new\n            feed = an_feed_entry\n            feed_results << feed\n          end\n        else\n          @logger.info \"Result \#{object_id} has a results.queryResponse that is either not a valid Hash, or with nil FeedPost.\"\n        end\n      end\n    end\n\n    #if there are more entries, query it again and show it all\n    while results.queryResponse.result.done.to_s.upcase != 'TRUE'\n      results = binding.queryMore(:queryString => results.queryResponse.result.queryLocator)\n      if results.queryResponse.result.records.is_a?(Hash)\n        # User has made only one feedpost\n        feed = Hash.new\n        feed = results.queryResponse.result.records\n        if (!feed.FeedPost.nil?) && (feed.FeedPost.ContentSize.to_i > 0)\n          feed = get_single_chatter_feed_with_attachment(feed.FeedPost.Id, feed[:type], binding, directory_name)\n        end\n        feed_results << feed\n      elsif results.queryResponse.result.records.is_a?(Array)\n        results.queryResponse.result.records.each do |an_feed_entry|\n          if (an_feed_entry.is_a?(Hash))\n            if (an_feed_entry[:Type] == \"TrackedChange\")\n              # This is a TrackedChange Feed, the FeedPost Body is nil\n              feed = Hash.new\n              feed = an_feed_entry\n              feed_results << feed\n              # check to see if it has attachments\n            elsif  (!an_feed_entry.FeedPost.nil?) && (an_feed_entry.FeedPost.ContentSize.to_i > 0) && (get_attachment)\n              # This signifies that:\n              #   1. results.queryResponse.result.records.FeedPost.Type is of \"ContentPost\"\n              #   2. results.queryResponse.result.records.FeedPost.type should be of \"FeedPost\"\n              an_entry_with_attachment = get_single_chatter_feed_with_attachment(an_feed_entry.FeedPost.Id, an_feed_entry[:type], binding, directory_name)\n              feed_results << an_entry_with_attachment\n            else\n              feed = Hash.new\n              feed = an_feed_entry\n              feed_results << feed\n            end\n\n          else\n            @logger.info \"Result \#{object_id} has a results.queryResponse that is either an invalid Hash or a nil FeedPost.\"\n          end\n        end\n      end\n    end\n\n    return feed_results\n  rescue Exception => exception\n    @logger.info 'get_all_feed_posts_with_attachments: ' + exception.message\n    return feed_results\n  end\nend\n"

#get_all_chatter_feeds_without_attachments(object_id, object_type, binding, directory_name, limit = 100) ⇒ Object

  1. It does not return the attached file.

  2. See get_all_feed_posts_with_attachments(object_id, object_type, binding, directory_name, limit=100, get_attachment=true, query_string=nil)

  3. returns Ruby Array of matching records



73
74
75
# File 'lib/salesforce/chatter_feed.rb', line 73

def get_all_chatter_feeds_without_attachments(object_id, object_type, binding, directory_name, limit=100)
  return get_all_chatter_feeds_with_attachments(object_id, object_type, binding, directory_name, limit, false, nil)
end

#get_single_chatter_feed_with_attachment(feedpost_id, feed_type, binding, directory_name, limit = 100) ⇒ Object

  1. Returns a single feed with attachment.

  2. ‘feedpost_id is the id corresponding to this feedpost

  3. ‘feed_type’ can be one of the followings

    , Asset, Campaign, Case, Lead, Contact, Contract, Opportunity,
    Product2, Solution, User
    **Note**: UserProfileFeed and NewsFeed are not included here, as they
    are special cases.
    
  4. ‘binding’ can be passed in directly or using the inherited binding from the

    'Salesforce::SfBase' base class.
    
  5. ‘directory_name is the directory in ’public/tmp’ for saving the attachment

  6. ‘limit’ is the number of feed comments to retrieve at a time



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# File 'lib/salesforce/chatter_feed.rb', line 222

def get_single_chatter_feed_with_attachment(feedpost_id, feed_type, binding, directory_name, limit=100)
  begin
    expanded_qstring = "    SELECT \#{BASE_FRAG}, \#{FEEDPOST_WITH_CONTENT_DATA_FRAG},\n    (\#{FEED_TRACKED_CHANGE_FRAG}), (\#{FEED_COMMENT_FRAG} LIMIT \#{limit})\n    FROM \#{feed_type} where FeedPost.Id= \\'\#{feedpost_id}\\' ORDER BY CreatedDate DESC Limit 1\n    HERE\n\n    @logger.info('expanded_string: ' + expanded_qstring)\n    deep_result = binding.query(:queryString => expanded_qstring)\n\n    ######### queryMore does not work on FeedPost with Content.##########\n    # locator = deep_result.queryResponse.result.queryLocator\n    # while !locator.nil?\n    #  query_again = binding.queryMore(:queryLocator => locator)\n    #  locator = query_again.queryMoreResponse.result.queryLocator\n    # end\n    #####################################################################\n\n    if !deep_result.Fault.nil?\n      raise ChatterFeedError.new(@logger, deep_result.Fault.faultstring.to_s)\n    end\n    if !deep_result.queryResponse.result.records.FeedComments.nil? && deep_result.queryResponse.result.records.FeedComments[:size].to_i > 1\n      # There are more than one feed comments. Therefore, search again without content-data.\n      # This is done, because having ContentData in the query string, it will only return only the 1st record of the feed comments.\n      qstring_without_content_data = <<-HERE\n      SELECT \#{BASE_FRAG},\n      (\#{FEED_TRACKED_CHANGE_FRAG}), (\#{FEED_COMMENT_FRAG} LIMIT 20)\n      FROM \#{feed_type} where FeedPost.Id= \\'\#{feedpost_id}\\' ORDER BY CreatedDate DESC Limit 1\n      HERE\n      result_without_content_data = binding.query(:queryString => qstring_without_content_data)\n      list_of_feed_comments = result_without_content_data.queryResponse.result.records.FeedComments\n      deep_result.queryResponse.result.records.FeedComments[:records] = list_of_feed_comments[:records]\n    end\n\n    filename = deep_result.queryResponse.result.records.FeedPost.ContentFileName\n    filesize = deep_result.queryResponse.result.records.FeedPost.ContentSize\n    filedata = deep_result.queryResponse.result.records.FeedPost.ContentData\n    result_with_attachment = deep_result.queryResponse.result.records\n\n    local_file_name = nil\n\n    if filename.nil?\n      # remote filename is nil, do not write the local file\n      @logger.info(\"remote filename is nil, do not write the local file.\")\n    else\n      # Downloaded files are put in the subdirectory matching each session-id in the /public/tmp directory.\n      # creates dir, if it does not exists\n      file_writer = Salesforce::FileWriter.new\n      local_file_name = file_writer.do_write_file(filename, filesize, filedata, directory_name)\n      result_with_attachment.FeedPost.store(:Attachment, local_file_name)\n    end\n\n    return result_with_attachment\n  end\nrescue Exception => exception\n  @logger.info \"Cannot create the file: \" + exception.message\n  result_with_attachment.FeedPost[:attachment] = nil\n  return result_with_attachment\nend\n"

#search_chatter_feeds(object_type, query_string, binding, limit = 100) ⇒ Object

find all chatter feeds based on object_type, query_string, and given binding



66
67
68
# File 'lib/salesforce/chatter_feed.rb', line 66

def search_chatter_feeds(object_type, query_string, binding, limit=100)
  return get_all_chatter_feeds_with_attachments(nil, object_type, binding, 'no-attachment-for-search', limit, false, query_string)
end