Skip to content

Commit

Permalink
Added support to new Direct Messages Events endpoint (rebased) (#919)
Browse files Browse the repository at this point in the history
* Accepts cursor that now has string format and last page cursor is blank

* added direct message events endpoint

* build direct message object on direct message event

* fix test

* improve documentation

* code formatting conform

* added sender_id and recipient_id on direct message object
  • Loading branch information
FabienChaynes authored and sferik committed Jun 11, 2018
1 parent d6c5100 commit 38f6aaa
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 2 deletions.
4 changes: 3 additions & 1 deletion lib/twitter/cursor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@ def initialize(key, klass, request)

# @return [Integer]
def next_cursor
@attrs[:next_cursor] || -1
@attrs[:next_cursor]
end
alias next next_cursor

# @return [Boolean]
def last?
return false if next_cursor.is_a?(String)
return true if next_cursor.nil?
next_cursor.zero?
end

Expand Down
2 changes: 2 additions & 0 deletions lib/twitter/direct_message.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class DirectMessage < Twitter::Identity
include Twitter::Entities
# @return [String]
attr_reader :text
attr_reader :sender_id
attr_reader :recipient_id
alias full_text text
object_attr_reader :User, :recipient
object_attr_reader :User, :sender
Expand Down
38 changes: 38 additions & 0 deletions lib/twitter/direct_message_event.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
require 'twitter/creatable'
require 'twitter/entities'
require 'twitter/identity'

module Twitter
class DirectMessageEvent < Twitter::Identity
include Twitter::Creatable
include Twitter::Entities

attr_reader :created_timestamp

object_attr_reader :DirectMessage, :direct_message

def initialize(attrs)
text = attrs[:message_create][:message_data][:text]
urls = attrs[:message_create][:message_data][:entities][:urls]

text.gsub!(urls[0][:url], urls[0][:expanded_url]) if urls.any?

attrs[:direct_message] = build_direct_message(attrs, text)
super
end

private

def build_direct_message(attrs, text)
recipient_id = attrs[:message_create][:target][:recipient_id].to_i
sender_id = attrs[:message_create][:sender_id].to_i
{id: attrs[:id].to_i,
created_at: Time.at(attrs[:created_timestamp].to_i / 1000.0),
sender: {id: sender_id},
sender_id: sender_id,
recipient: {id: recipient_id},
recipient_id: recipient_id,
text: text}
end
end
end
15 changes: 15 additions & 0 deletions lib/twitter/rest/direct_messages.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require 'twitter/arguments'
require 'twitter/direct_message'
require 'twitter/direct_message_event'
require 'twitter/rest/utils'
require 'twitter/user'
require 'twitter/utils'
Expand Down Expand Up @@ -27,6 +28,20 @@ def direct_messages_received(options = {})
perform_get_with_objects('/1.1/direct_messages.json', options, Twitter::DirectMessage)
end

# Returns the 20 most recent direct messages events sent to the authenticating user
# @see https://dev.twitter.com/rest/reference/get/direct_messages/events/list
# @note This method requires an access token with RWD (read, write & direct message) permissions. Consult The Application Permission Model for more information.
# @rate_limited Yes
# @authentication Requires user context
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
# @return [Array<Twitter::DirectMessageEvent>] Direct messages sent to and received by the authenticating user.
# @param options [Hash] A customizable set of options.
# @option options [Integer] :count Specifies the number of records to retrieve. Must be less than or equal to 50. Default is 20
# @option options [String] :cursor Specifies the cursor position of results to retrieve.
def direct_messages_events(options = {})
perform_get_with_cursor('/1.1/direct_messages/events/list.json', options.merge!(no_default_cursor: true), :events, Twitter::DirectMessageEvent)
end

# Returns the 20 most recent direct messages sent by the authenticating user
#
# @see https://dev.twitter.com/rest/reference/get/direct_messages/sent
Expand Down
7 changes: 6 additions & 1 deletion lib/twitter/rest/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,12 @@ def perform_request_with_objects(request_method, path, options, klass)
# @param collection_name [Symbol]
# @param klass [Class]
def perform_get_with_cursor(path, options, collection_name, klass = nil)
merge_default_cursor!(options)
if options[:no_default_cursor]
options.delete(:no_default_cursor)
else
merge_default_cursor!(options)
end

request = Twitter::REST::Request.new(self, :get, path, options)
Twitter::Cursor.new(collection_name.to_sym, klass, request)
end
Expand Down
1 change: 1 addition & 0 deletions spec/fixtures/events.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"events":[{"type":"message_create","id":"856574281366605831","created_timestamp":"1493058197715","message_create":{"target":{"recipient_id":"22095868"},"sender_id":"358486183","message_data":{"text":"Thanks https://t.co/ZxBEw35k5z","entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[{"url":"https://t.co/ZxBEw35k5z","expanded_url":"https://twitter.com/i/stickers/image/10011","display_url":"twitter.com/i/stickers/ima…","indices":[1,24]}]}}}},{"type":"message_create","id":"856571192978927619","created_timestamp":"1493057461386","message_create":{"target":{"recipient_id":"22095868"},"sender_id":"311650899","message_data":{"text":"❤️","entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[]}}}},{"type":"message_create","id":"856554872984018948","created_timestamp":"1493053570396","message_create":{"target":{"recipient_id":"22095868"},"sender_id":"422190131","message_data":{"text":"😍","entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[]}}}},{"type":"message_create","id":"856538753409703939","created_timestamp":"1493049727190","message_create":{"target":{"recipient_id":"22095868"},"sender_id":"759849327200047104","message_data":{"text":"obrigada!!! bj","entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[]}}}},{"type":"message_create","id":"856533644445396996","created_timestamp":"1493048509118","message_create":{"target":{"recipient_id":"22095868"},"sender_id":"73660881","message_data":{"text":" https://t.co/ZxBEw35k5z","entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[{"url":"https://t.co/ZxBEw35k5z","expanded_url":"https://twitter.com/i/stickers/image/10011","display_url":"twitter.com/i/stickers/ima…","indices":[1,24]}]}}}},{"type":"message_create","id":"856526573545062407","created_timestamp":"1493046823284","message_create":{"target":{"recipient_id":"22095868"},"sender_id":"328677087","message_data":{"text":"OBRIGADO MINHA LINDA SERÁ INCRÍVEL ASSISTIR O TEU SHOW, VOU FAZER O POSSÍVEL PARA TE PRESTIGIAR. SUCESSO","entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[]}}}},{"type":"message_create","id":"856523843892129796","created_timestamp":"1493046172484","message_create":{"target":{"recipient_id":"422190131"},"sender_id":"22095868","message_data":{"text":" https://t.co/KQcQAF6hVS","entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[{"url":"https://t.co/KQcQAF6hVS","expanded_url":"https://twitter.com/i/stickers/image/10018","display_url":"twitter.com/i/stickers/ima…","indices":[1,24]}]}}}},{"type":"message_create","id":"856523768910544899","created_timestamp":"1493046154607","message_create":{"target":{"recipient_id":"4374876088"},"sender_id":"22095868","message_data":{"text":" https://t.co/MG2QdVuPGa","entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[{"url":"https://t.co/MG2QdVuPGa","expanded_url":"https://twitter.com/i/stickers/image/10017","display_url":"twitter.com/i/stickers/ima…","indices":[1,24]}]}}}},{"type":"message_create","id":"856516885524951043","created_timestamp":"1493044513480","message_create":{"target":{"recipient_id":"22095868"},"sender_id":"4374876088","message_data":{"text":"Obrigado. Vou adquiri-lo. Muito sucesso!","entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[]}}}},{"type":"message_create","id":"856502352299405315","created_timestamp":"1493041048489","message_create":{"target":{"recipient_id":"22095868"},"sender_id":"422190131","message_data":{"text":"COM CERTEZA QDO ESTIVER EM SAO PAUÇO IREI COM O MAIOR PRAZER SUCESSO LINDA","entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[]}}}},{"type":"message_create","id":"856480385957548035","created_timestamp":"1493035811305","message_create":{"target":{"recipient_id":"2924245126"},"sender_id":"22095868","message_data":{"text":"Obrigada Jacques","entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[]}}}},{"type":"message_create","id":"856480124421771268","created_timestamp":"1493035748950","message_create":{"target":{"recipient_id":"22095868"},"sender_id":"2924245126","message_data":{"text":"😍 Música boa para seu espetáculo em São-Paulo com seu amigo","entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[]}}}},{"type":"message_create","id":"856478933260410883","created_timestamp":"1493035464955","message_create":{"target":{"recipient_id":"22095868"},"sender_id":"2924245126","message_data":{"text":"Jardim urbano","entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[]}}}},{"type":"message_create","id":"856478621090942979","created_timestamp":"1493035390528","message_create":{"target":{"recipient_id":"22095868"},"sender_id":"2924245126","message_data":{"text":" https://t.co/1ojXzm8bKx","entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[{"url":"https://t.co/1ojXzm8bKx","expanded_url":"https://twitter.com/messages/media/856478621090942979","display_url":"pic.twitter.com/1ojXzm8bKx","indices":[1,24]}]},"attachment":{"type":"media","media":{"id":856478542527385601,"id_str":"856478542527385601","indices":[1,24],"media_url":"https://ton.twitter.com/1.1/ton/data/dm/856478621090942979/856478542527385601/d3LfgVMN.jpg","media_url_https":"https://ton.twitter.com/1.1/ton/data/dm/856478621090942979/856478542527385601/d3LfgVMN.jpg","url":"https://t.co/1ojXzm8bKx","display_url":"pic.twitter.com/1ojXzm8bKx","expanded_url":"https://twitter.com/messages/media/856478621090942979","type":"photo","sizes":{"small":{"w":340,"h":255,"resize":"fit"},"medium":{"w":600,"h":450,"resize":"fit"},"thumb":{"w":150,"h":150,"resize":"crop"},"large":{"w":997,"h":748,"resize":"fit"}}}}}}},{"type":"message_create","id":"856477958885834755","created_timestamp":"1493035232646","message_create":{"target":{"recipient_id":"22095868"},"sender_id":"2924245126","message_data":{"text":"Os amantes em face a o mar","entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[]}}}},{"type":"message_create","id":"856477710595624963","created_timestamp":"1493035173449","message_create":{"target":{"recipient_id":"22095868"},"sender_id":"2924245126","message_data":{"text":" https://t.co/RrE2qo9upr","entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[{"url":"https://t.co/RrE2qo9upr","expanded_url":"https://twitter.com/messages/media/856477710595624963","display_url":"pic.twitter.com/RrE2qo9upr","indices":[1,24]}]},"attachment":{"type":"media","media":{"id":856477689447841792,"id_str":"856477689447841792","indices":[1,24],"media_url":"https://ton.twitter.com/1.1/ton/data/dm/856477710595624963/856477689447841792/i3ViseFg.jpg","media_url_https":"https://ton.twitter.com/1.1/ton/data/dm/856477710595624963/856477689447841792/i3ViseFg.jpg","url":"https://t.co/RrE2qo9upr","display_url":"pic.twitter.com/RrE2qo9upr","expanded_url":"https://twitter.com/messages/media/856477710595624963","type":"photo","sizes":{"small":{"w":340,"h":453,"resize":"fit"},"thumb":{"w":150,"h":150,"resize":"crop"},"large":{"w":502,"h":669,"resize":"fit"},"medium":{"w":502,"h":669,"resize":"fit"}}}}}}}],"next_cursor":"ODU2NDc3NzEwNTk1NjI0OTYz"}
1 change: 1 addition & 0 deletions spec/fixtures/ids_list_new_cursor.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"previous_cursor":0,"next_cursor_str":"1305102810874389703","ids":[20009713,22469930,351223419],"previous_cursor_str":"0","next_cursor":"ODU2NDc3NzEwNTk1NjI0OTYz"}
1 change: 1 addition & 0 deletions spec/fixtures/ids_list_new_cursor2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"ids":[20009713,22469930,351223419]}
27 changes: 27 additions & 0 deletions spec/twitter/cursor_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,31 @@
end
end
end

describe '#cursor new format' do
before do
@client = Twitter::REST::Client.new(consumer_key: 'CK', consumer_secret: 'CS', access_token: 'AT', access_token_secret: 'AS')
stub_get('/1.1/followers/ids.json').with(query: {cursor: '-1', screen_name: 'sferik'}).to_return(body: fixture('ids_list_new_cursor.json'), headers: {content_type: 'application/json; charset=utf-8'})
stub_get('/1.1/followers/ids.json').with(query: {cursor: 'ODU2NDc3NzEwNTk1NjI0OTYz', screen_name: 'sferik'}).to_return(body: fixture('ids_list_new_cursor2.json'), headers: {content_type: 'application/json; charset=utf-8'})
end

it 'requests the correct resources' do
@client.follower_ids('sferik').each {}
expect(a_get('/1.1/followers/ids.json').with(query: {cursor: '-1', screen_name: 'sferik'})).to have_been_made
expect(a_get('/1.1/followers/ids.json').with(query: {cursor: 'ODU2NDc3NzEwNTk1NjI0OTYz', screen_name: 'sferik'})).to have_been_made
end

it 'iterates' do
count = 0
@client.follower_ids('sferik').each { count += 1 }
expect(count).to eq(6)
end
context 'with start' do
it 'iterates' do
count = 0
@client.follower_ids('sferik').each(5) { count += 1 }
expect(count).to eq(1)
end
end
end
end
24 changes: 24 additions & 0 deletions spec/twitter/rest/direct_messages_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,30 @@
end
end

describe '#direct_messages_events' do
before do
stub_get('/1.1/direct_messages/events/list.json').to_return(body: fixture('events.json'), headers: {content_type: 'application/json; charset=utf-8'})
end

it 'requests the correct resource' do
@client.direct_messages_events
expect(a_get('/1.1/direct_messages/events/list.json')).to have_been_made
end

it 'returns messages' do
direct_messages = @client.direct_messages_events

expect(direct_messages).to be_a Twitter::Cursor
expect(direct_messages.first).to be_a Twitter::DirectMessageEvent
expect(direct_messages.first.id).to eq('856574281366605831')
expect(direct_messages.first.created_timestamp).to eq('1493058197715')
expect(direct_messages.first.direct_message.text).to eq('Thanks https://twitter.com/i/stickers/image/10011')
expect(direct_messages.first.direct_message.sender_id).to eq(358_486_183)
expect(direct_messages.first.direct_message.recipient_id).to eq(22_095_868)
expect(direct_messages.first.direct_message.sender.id).to eq(358_486_183)
expect(direct_messages.first.direct_message.recipient.id).to eq(22_095_868)
end
end
describe '#direct_messages_sent' do
before do
stub_get('/1.1/direct_messages/sent.json').to_return(body: fixture('direct_messages.json'), headers: {content_type: 'application/json; charset=utf-8'})
Expand Down

0 comments on commit 38f6aaa

Please sign in to comment.