Class: X::DirectMessage

Inherits:
Resource show all
Extended by:
DirectMessageConversations, Finders
Defined in:
x-objects/lib/x/objects/direct_message.rb

Overview

A direct message event

Constant Summary collapse

FIELDS =

The direct message event fields the object layer requests; the sender, the participants, and the posts a message refers to come with their expansions

A minor release may add to it the fields the API adds, so that a lookup asks for them too; see Resource#hydrated? for what that means for a resource looked up with a list of fields of its own.

%w[attachments created_at dm_conversation_id entities event_type id text].freeze
EXPANSIONS =

Every expansion available on direct message endpoints

A minor release may add to it the expansions the API adds, so that a lookup asks for them too; see Resource#hydrated? for what that means for a resource looked up with a list of expansions of its own.

%w[attachments.media_keys participant_ids referenced_posts sender_id].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

This class inherits a constructor from X::Resource

Instance Attribute Details

#attachments ⇒ Hash? (readonly)

The attachment keys

Examples:

Get the attachments

message.attachments

Returns:

  • (Hash, nil) —

    the attachments



197
# File 'x-objects/lib/x/objects/direct_message.rb', line 197

attribute :attachments, :object

#created_at ⇒ Time? (readonly)

The time when the event occurred

Examples:

Get the event time

message.created_at

Returns:

  • (Time, nil) —

    the event time



154
# File 'x-objects/lib/x/objects/direct_message.rb', line 154

attribute :created_at, :time

#dm_conversation_id ⇒ String? (readonly)

The identifier of the conversation

Examples:

Get the conversation identifier

message.dm_conversation_id

Returns:

  • (String, nil) —

    the conversation identifier: the identifiers of the two users of a one-to-one conversation joined with a hyphen, or the number of a group conversation

Raises:



172
# File 'x-objects/lib/x/objects/direct_message.rb', line 172

attribute :dm_conversation_id, :conversation_id

#entities ⇒ Hash? (readonly)

The entities found in the text: its URLs, hashtags, mentions, and cashtags

Examples:

Get the URLs of a message

message.entities&.fetch("urls")

Returns:

  • (Hash, nil) —

    the entities



205
# File 'x-objects/lib/x/objects/direct_message.rb', line 205

attribute :entities, :object

#event_type ⇒ String? (readonly)

The event type: MessageCreate, ParticipantsJoin, or ParticipantsLeave

Examples:

Get the event type

message.event_type

Returns:

  • (String, nil) —

    the event type



146
# File 'x-objects/lib/x/objects/direct_message.rb', line 146

attribute :event_type

#participant_ids ⇒ Array<Integer> (readonly)

The identifiers of the participants who joined or left

Examples:

Get the participant identifiers

message.participant_ids

Returns:

  • (Array<Integer>) —

    the participant identifiers, empty if there are none



180
# File 'x-objects/lib/x/objects/direct_message.rb', line 180

attribute :participant_ids, :integers

#referenced_posts ⇒ Array<Hash> (readonly)

The referenced posts with their identifiers

Examples:

Get the referenced posts

message.referenced_posts

Returns:

  • (Array<Hash>) —

    the referenced posts, empty if there are none



188
# File 'x-objects/lib/x/objects/direct_message.rb', line 188

attribute :referenced_posts, :objects, tweet_key: %w[referenced_tweets]

#sender_id ⇒ Integer? (readonly)

The identifier of the sender

Examples:

Get the sender identifier

message.sender_id

Returns:

  • (Integer, nil) —

    the sender identifier



162
# File 'x-objects/lib/x/objects/direct_message.rb', line 162

attribute :sender_id, :integer

#text ⇒ String? (readonly)

The text

It is the text as the API sends it, which escapes &, <, and > as &, <, and >, and it stays so throughout 1.x, so unescape it to display it.

Examples:

Get the text

message.text # => "Ruby &amp; Rails"

Display the text

CGI.unescapeHTML(message.text) # => "Ruby & Rails"

Returns:

  • (String, nil) —

    the text, HTML-escaped as the API sends it



138
# File 'x-objects/lib/x/objects/direct_message.rb', line 138

attribute :text

Class Method Details

.all(client:, **params) ⇒ Cursor

The most recent direct message events across every conversation

Examples:

Print the most recent direct messages

X::DirectMessage.all(client: client).first(10).each { |message| puts message.text }

Parameters:

  • client (Object) —

    the client used to make the requests

  • params (Hash) —

    query parameters merged over the default parameters

Returns:

  • (Cursor) —

    a cursor over the events



71
72
73
# File 'x-objects/lib/x/objects/direct_message.rb', line 71

def all(client:, **params)
  Cursor.__send__(:build, self, "dm_events", client:, params: {max_results: MAX_RESULTS}.merge(params))
end

.create(user, text = nil, client:, media_ids: nil, **params) ⇒ DirectMessage

Send a direct message to a user as the authenticated user

Examples:

Send a direct message

X::DirectMessage.create(user, "Hello!", client: client)

Send an image without text

X::DirectMessage.create(user, client: client, media_ids: media)

Parameters:

  • user (User, String, Integer) —

    the recipient or their identifier

  • text (String, nil) (defaults to: nil) —

    the text of the message, or nil for a message of attachments alone

  • client (Object) —

    the client used to make the request

  • media_ids (Array<String, Integer, #fetch, Media>, String, Integer, #fetch, Media, nil) (defaults to: nil) —

    the identifiers or media keys of uploaded media to attach, what the uploads returned, or media, such as that of a post, one or many

  • params (Hash) —

    additional request body fields, such as attachments

Returns:

  • (DirectMessage) —

    the sent message, holding only its identifiers

Raises:

  • (ArgumentError) —

    if the message has neither text nor any other field, or has both media_ids and attachments

  • (MissingResource) —

    if the API answers without the message



107
108
109
110
# File 'x-objects/lib/x/objects/direct_message.rb', line 107

def create(user, text = nil, client:, media_ids: nil, **params)
  path = "dm_conversations/with/#{Utils.id_of(user, User)}/messages"
  sent(client.post(path, message(text, params, media_ids), **Utils::JSON_CLASSES), path, client:)
end

.default_params ⇒ Hash{String => Array<String>}

The default query parameters requesting every direct message field and expansion

Examples:

Get the default parameters

X::DirectMessage.default_params["dm_event.fields"]

Returns:

  • (Hash{String => Array<String>}) —

    the default query parameters



58
59
60
61
# File 'x-objects/lib/x/objects/direct_message.rb', line 58

def default_params
  {"dm_event.fields" => FIELDS, "user.fields" => User::FIELDS, "post.fields" => Post::FIELDS,
   "media.fields" => Media::FIELDS, "expansions" => EXPANSIONS}
end

.delete(message, client:) ⇒ Boolean

Delete a direct message event as the authenticated user

Examples:

Delete a direct message

X::DirectMessage.delete("1234567890", client: client)

Parameters:

  • message (DirectMessage, String, Integer) —

    the event or its identifier

  • client (Object) —

    the client used to make the request

Returns:

  • (Boolean) —

    true if the event was deleted



120
121
122
123
# File 'x-objects/lib/x/objects/direct_message.rb', line 120

def delete(message, client:)
  body = client.delete("dm_events/#{Utils.id_of(message, self)}", **Utils::JSON_CLASSES)
  body.to_h.dig("data", "deleted").eql?(true)
end

.with(user, client:, **params) ⇒ Cursor

The direct message events in the one-to-one conversation with a user

Examples:

Print the conversation with a user

X::DirectMessage.with(user, client: client).each { |message| puts message.text }

Parameters:

  • user (User, String, Integer) —

    the other participant or their identifier

  • client (Object) —

    the client used to make the requests

  • params (Hash) —

    query parameters merged over the default parameters

Returns:

  • (Cursor) —

    a cursor over the events



84
85
86
87
# File 'x-objects/lib/x/objects/direct_message.rb', line 84

def with(user, client:, **params)
  path = "dm_conversations/with/#{Utils.id_of(user, User)}/dm_events"
  Cursor.__send__(:build, self, path, client:, params: {max_results: MAX_RESULTS}.merge(params))
end

Instance Method Details

#delete ⇒ Boolean

Delete this direct message event as the authenticated user

Examples:

Delete a direct message

message.delete

Returns:

  • (Boolean) —

    true if the event was deleted



307
308
309
# File 'x-objects/lib/x/objects/direct_message.rb', line 307

def delete
  self.class.delete(self, client: client!)
end

#from?(user) ⇒ Boolean

Check whether a user sent this message

A message that does not name its sender, as the message a new direct message returns does not, or one fetched with dm_event.fields that leave sender_id out, cannot say the user sent it, so it answers false; its sender_id is nil.

Examples:

Split messages into sent and received

me = client.current_user_id
messages.partition { |message| message.from?(me) }

Parameters:

  • user (User, String, Integer) —

    the user or their identifier

Returns:

  • (Boolean) —

    true if the user sent the message, false if another user did, or the message does not name its sender



257
# File 'x-objects/lib/x/objects/direct_message.rb', line 257

def from?(user) = sender_id.to_s.eql?(Utils.id_of(user, User))

#group? ⇒ Boolean

Check whether the message belongs to a group conversation

The identifier of a one-to-one conversation joins the identifiers of its two participants with a hyphen, and the identifier of a group conversation is a number of its own.

Examples:

Leave out the messages of group conversations

client.direct_messages.reject(&:group?)

Returns:

  • (Boolean) —

    true if the message belongs to a group conversation, false if to a one-to-one conversation or the message does not say

Raises:

  • (InvalidAttribute) —

    if the response holds a conversation identifier that is not one



270
271
272
273
# File 'x-objects/lib/x/objects/direct_message.rb', line 270

def group?
  conversation_id = dm_conversation_id
  !conversation_id.nil? && !conversation_id.include?("-")
end

#media ⇒ Array<Media>

The attached media, from the includes or as stubs holding only their keys

Examples:

Get the media URLs

message.media.map(&:url)

Returns:

  • (Array<Media>) —

    the media



229
# File 'x-objects/lib/x/objects/direct_message.rb', line 229

references :media, :Media, key: %w[attachments media_keys]

#participants ⇒ Array<User>

The participants who joined or left, from the includes or as stubs

Examples:

Get the participants

message.participants

Returns:

  • (Array<User>) —

    the participants



221
# File 'x-objects/lib/x/objects/direct_message.rb', line 221

references :participants, :User, key: %w[participant_ids]

#peer(user) ⇒ User?

The other participant of a one-to-one conversation, as seen by a user

The sender, when the user did not send the message, and otherwise the other member of the conversation, from the includes or as a stub holding only its identifier. A message that does not name its sender, as the message a new direct message returns does not, is read by its conversation alone, whose other member is the peer of a user who is one of its two. A message whose conversation the user is not one of the two members of has no peer for that user, even one another user sent, so neither has a message of a group conversation, whose identifier names none of its members.

Examples:

Print the identifier of the user each message was exchanged with

me = client.current_user_id
client.direct_messages.reject(&:group?).each { |message| puts message.peer(me)&.id }

Parameters:

  • user (User, String, Integer) —

    the user, usually the authenticated user, or their identifier

Returns:

  • (User, nil) —

    the other participant, or nil for a group conversation, one without another participant, or one the user is not a member of

Raises:

  • (InvalidAttribute) —

    if the response holds a conversation identifier that is not one



292
293
294
295
296
297
298
299
# File 'x-objects/lib/x/objects/direct_message.rb', line 292

def peer(user)
  user_id = Utils.id_of(user, User)
  members = dm_conversation_id.to_s.split("-")
  return unless members.empty? || members.include?(user_id)
  return sender unless sender_id.nil? || from?(user_id)

  resolve(User, members.find { |id| !id.eql?(user_id) }) #: User?
end

#references ⇒ Array<Post>

The referenced posts, resolved from the includes or built as stubs

Examples:

Get the referenced posts

message.references

Returns:

  • (Array<Post>) —

    the referenced posts

Raises:

  • (InvalidAttribute) —

    if the response holds a referenced post that is not an object



238
239
240
241
242
# File 'x-objects/lib/x/objects/direct_message.rb', line 238

def references
  referenced_posts.filter_map do |reference|
    resolve(Post, reference["id"]) #: Post?
  end.freeze
end

#sender ⇒ User?

The sender, resolved from the includes or as a stub holding only its identifier

Examples:

Get the sender's username

message.sender.username

Returns:

  • (User, nil) —

    the sender



213
# File 'x-objects/lib/x/objects/direct_message.rb', line 213

reference :sender, :User, key: %w[sender_id]