Class: X::DirectMessage

Inherits:
Resource show all
Extended by:
DirectMessageConversations, Finders, Resources::DirectMessageConversations, Resources::Finders
Defined in:
x-resources/lib/x/resources/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



204
# File 'x-resources/lib/x/resources/direct_message.rb', line 204

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



161
# File 'x-resources/lib/x/resources/direct_message.rb', line 161

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:



179
# File 'x-resources/lib/x/resources/direct_message.rb', line 179

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&.dig("urls")

Returns:

  • (Hash, nil) —

    the entities



212
# File 'x-resources/lib/x/resources/direct_message.rb', line 212

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



153
# File 'x-resources/lib/x/resources/direct_message.rb', line 153

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



187
# File 'x-resources/lib/x/resources/direct_message.rb', line 187

attribute :participant_ids, :integers

#referenced_posts ⇒ Array<Hash> (readonly) Also known as: referenced_tweets

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



195
# File 'x-resources/lib/x/resources/direct_message.rb', line 195

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



169
# File 'x-resources/lib/x/resources/direct_message.rb', line 169

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



145
# File 'x-resources/lib/x/resources/direct_message.rb', line 145

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



78
79
80
# File 'x-resources/lib/x/resources/direct_message.rb', line 78

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



114
115
116
117
# File 'x-resources/lib/x/resources/direct_message.rb', line 114

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

.create_group(users, text = nil, client:, media_ids: nil, **params) ⇒ DirectMessage Originally defined in module Resources::DirectMessageConversations

Start a group conversation, sending its first message as the authenticated user

Examples:

Start a group conversation

X::DirectMessage.create_group([alice, bob], "Hello, both of you!", client: client)

Start a group conversation with an image

X::DirectMessage.create_group([alice, bob], client: client, media_ids: media)

Parameters:

  • users (Array<User, String, Integer>) —

    the other participants or their identifiers

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

    the text of the first 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 fields of the message, such as attachments

Returns:

  • (DirectMessage) —

    the sent message, holding only its identifiers, among them the new conversation's

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

.create_in(conversation, text = nil, client:, media_ids: nil, **params) ⇒ DirectMessage Originally defined in module Resources::DirectMessageConversations

Send a direct message to a conversation as the authenticated user

Examples:

Reply to the conversation of a message

X::DirectMessage.create_in(message, "Sounds good", client: client)

Reply with an image

X::DirectMessage.create_in(message, client: client, media_ids: media)

Parameters:

  • conversation (DirectMessage, String, Integer) —

    a message of the conversation, or the conversation's 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 conversation identifier is not one, the message has neither text nor any other field, or it has both media_ids and attachments

  • (MissingResource) —

    if the API answers without the message

.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



65
66
67
68
# File 'x-resources/lib/x/resources/direct_message.rb', line 65

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



127
128
129
130
# File 'x-resources/lib/x/resources/direct_message.rb', line 127

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

.find(id, client:, **params) {|problem| ... } ⇒ Resource? Originally defined in module Resources::Finders

Look up a resource by identifier

Examples:

Look up a post by identifier

X::Post.find(1234567890, client: client)

Parameters:

  • id (String, Integer, Resource) —

    the identifier, or a resource of this class

  • client (Object) —

    the client used to make the request

  • params (Hash) —

    query parameters merged over the default parameters; one that overrides a default field or expansion parameter to leave some out builds resources that are not hydrated, so hydrate fetches the rest

Yield Parameters:

  • problem (Problem) —

    each problem the API reported, such as a resource that was not found

Returns:

  • (Resource, nil) —

    the resource or nil if it was not found, whether the API answers 200 with no data or a 404 that reports the resource as not found

Raises:

  • (ArgumentError) —

    if the identifier is not one, or is a resource of another class, before a request

  • (X::NotFound) —

    if the API answers any other 404, such as one from a client pointed at the wrong host or API version

.find!(id, client:, **params) ⇒ Resource Originally defined in module Resources::Finders

Look up a resource by identifier, which must exist

The error it raises names the identifier looked up, whether the identifier or a resource was given. Its cause is the X::NotFound of a lookup the API answered with a 404 that reports the resource as not found.

Examples:

Look up a post by identifier

X::Post.find!(1234567890, client: client)

Parameters:

  • id (String, Integer, Resource) —

    the identifier, or a resource of this class

  • client (Object) —

    the client used to make the request

  • params (Hash) —

    query parameters merged over the default parameters; one that overrides a default field or expansion parameter to leave some out builds resources that are not hydrated, so hydrate fetches the rest

Returns:

Raises:

  • (ArgumentError) —

    if the identifier is not one, or is a resource of another class, before a request

  • (MissingResource) —

    if the resource was not found, whether the API answers 200 with no data or a 404 that reports the resource as not found

  • (X::NotFound) —

    if the API answers any other 404, such as one from a client pointed at the wrong host or API version

.in(conversation, client:, **params) ⇒ Cursor Originally defined in module Resources::DirectMessageConversations

The direct message events of a conversation, one-to-one or group

Examples:

Print the conversation a message belongs to

X::DirectMessage.in(message, client: client).each { |event| puts event.text }

Parameters:

  • conversation (DirectMessage, String, Integer) —

    a message of the conversation, or the conversation's identifier

  • client (Object) —

    the client used to make the requests

  • params (Hash) —

    query parameters merged over the default parameters, such as event_types

Returns:

  • (Cursor) —

    a cursor over the events

Raises:

  • (ArgumentError) —

    if the conversation identifier is not one

.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



91
92
93
94
# File 'x-resources/lib/x/resources/direct_message.rb', line 91

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



314
315
316
# File 'x-resources/lib/x/resources/direct_message.rb', line 314

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



264
# File 'x-resources/lib/x/resources/direct_message.rb', line 264

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



277
278
279
280
# File 'x-resources/lib/x/resources/direct_message.rb', line 277

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



236
# File 'x-resources/lib/x/resources/direct_message.rb', line 236

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



228
# File 'x-resources/lib/x/resources/direct_message.rb', line 228

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



299
300
301
302
303
304
305
306
# File 'x-resources/lib/x/resources/direct_message.rb', line 299

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



245
246
247
248
249
# File 'x-resources/lib/x/resources/direct_message.rb', line 245

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



220
# File 'x-resources/lib/x/resources/direct_message.rb', line 220

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