Class: X::Post

Inherits:
Resource show all
Extended by:
BatchFinders, PostCounts, PostSearch, PostWrites, Resources::BatchFinders, Resources::PostCounts, Resources::PostSearch, Resources::PostWrites
Includes:
PostCollections, References, Resources::PostCollections, Resources::References
Defined in:
x-resources/lib/x/resources/post.rb

Overview

A post, also known as a tweet

Constant Summary collapse

FIELDS =

Every public post field; the identifiers of referenced resources come with their expansions

The metrics that only the author, or an advertiser, may read, non_public_metrics, organic_metrics, and promoted_metrics, are left out, since a field that depends on who is authenticated would make every request fail for a client that cannot read it, as are the fields of Community Notes and of suggested sources, which the API gives to the programs they belong to. So is source, which the API has deprecated: a field it stops taking would make every request that asks for it fail. Nor does a post read it; a request that names it in its post.fields finds it in Resource#attrs.

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[article article_title attachments card_uri community_id context_annotations conversation_id
created_at display_text_range edit_controls entities geo id lang media_metadata note_post paid_partnership
possibly_sensitive public_metrics reply_settings scopes text withheld].freeze
EXPANSIONS =

The expansions of the resources a post refers to that the object layer resolves

The identifiers of a post's edit history come with every post, so the edit_history_post_ids expansion, which would include each version of the post again, including the post itself, is left out, as is entities.mentions.username, which would include each user the post mentions, since nothing reads them.

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 attachments.media_source_tweet attachments.poll_ids author_id geo.place_id
in_reply_to_user_id referenced_posts].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

#article ⇒ Hash? (readonly)

The article the post publishes, with its title

Examples:

Get the title of an article

post.article&.fetch("title")

Returns:

  • (Hash, nil) —

    the article



246
# File 'x-resources/lib/x/resources/post.rb', line 246

attribute :article, :object

#article_title ⇒ Hash? (readonly)

What the API describes of the title of the article the post publishes

Examples:

Get the metadata of the title of an article

post.article_title

Returns:

  • (Hash, nil) —

    the metadata of the article, or nil for a post that publishes none



254
# File 'x-resources/lib/x/resources/post.rb', line 254

attribute :article_title, :object

#attachments ⇒ Hash? (readonly)

The attachment keys and identifiers

Examples:

Get the attachments

post.attachments

Returns:

  • (Hash, nil) —

    the attachments



343
# File 'x-resources/lib/x/resources/post.rb', line 343

attribute :attachments, :object

#author_id ⇒ Integer? (readonly)

The identifier of the author

Examples:

Get the author identifier

post.author_id

Returns:

  • (Integer, nil) —

    the author identifier



143
# File 'x-resources/lib/x/resources/post.rb', line 143

attribute :author_id, :integer

#bookmark_count ⇒ Integer? (readonly)

The number of bookmarks

Examples:

Get the bookmark count

post.bookmark_count

Returns:

  • (Integer, nil) —

    the bookmark count



423
# File 'x-resources/lib/x/resources/post.rb', line 423

attribute :bookmark_count, :integer, key: %w[public_metrics bookmark_count]

#card_uri ⇒ String? (readonly)

The URI of the card the post shows

Examples:

Get the card URI

post.card_uri

Returns:

  • (String, nil) —

    the card URI



238
# File 'x-resources/lib/x/resources/post.rb', line 238

attribute :card_uri

#community_id ⇒ Integer? (readonly)

The identifier of the community the post was made in

Examples:

Get the community identifier

post.community_id

Returns:

  • (Integer, nil) —

    the community identifier



159
# File 'x-resources/lib/x/resources/post.rb', line 159

attribute :community_id, :integer

#context_annotations ⇒ Array<Hash> (readonly)

The context annotations

Examples:

Get the context annotations

post.context_annotations

Returns:

  • (Array<Hash>) —

    the context annotations, empty if there are none



326
# File 'x-resources/lib/x/resources/post.rb', line 326

attribute :context_annotations, :objects

#conversation_id ⇒ Integer? (readonly)

The identifier of the first post in the conversation

Examples:

Get the conversation identifier

post.conversation_id

Returns:

  • (Integer, nil) —

    the conversation identifier



151
# File 'x-resources/lib/x/resources/post.rb', line 151

attribute :conversation_id, :integer

#coordinates ⇒ Array<Numeric>? (readonly)

The longitude and latitude the post was tagged with

Examples:

Get the coordinates

post.coordinates # => [-122.4, 37.8]

Returns:

  • (Array<Numeric>, nil) —

    the longitude and latitude, each an Integer when the API gives a whole number



351
# File 'x-resources/lib/x/resources/post.rb', line 351

attribute :coordinates, key: %w[geo coordinates coordinates]

#created_at ⇒ Time? (readonly)

The time when the post was created

Examples:

Get the creation time

post.created_at

Returns:

  • (Time, nil) —

    the creation time



135
# File 'x-resources/lib/x/resources/post.rb', line 135

attribute :created_at, :time

#display_text_range ⇒ Range<Integer>? (readonly)

The range of characters of the text the API gives the post that is shown

It leaves out the mentions a reply begins with and the link to media it ends with. It is a range of the text the post holds itself, which for a long post is the text cut short, not the full text #text reads.

Examples:

Read the text that is shown

post.display_text_range&.then { |range| post.attrs["text"][range] }

Returns:

  • (Range<Integer>, nil) —

    the range, which leaves out its end, or nil if the response holds none

Raises:

  • (InvalidAttribute) —

    if the response holds something other than the start and end of a range



219
# File 'x-resources/lib/x/resources/post.rb', line 219

attribute :display_text_range, :range

#edit_controls ⇒ Hash? (readonly)

The edit controls

Examples:

Get the edit controls

post.edit_controls

Returns:

  • (Hash, nil) —

    the edit controls



206
# File 'x-resources/lib/x/resources/post.rb', line 206

attribute :edit_controls, :object

#edit_history_post_ids ⇒ Array<Integer> (readonly) Also known as: edit_history_tweet_ids

The identifiers of every version of the post

Examples:

Get the edit history identifiers

post.edit_history_post_ids

Returns:

  • (Array<Integer>) —

    the edit history identifiers, empty if there are none



198
# File 'x-resources/lib/x/resources/post.rb', line 198

attribute :edit_history_post_ids, :integers, tweet_key: %w[edit_history_tweet_ids]

#geo ⇒ Hash? (readonly)

The tagged place and coordinates

Examples:

Get the geo details

post.geo

Returns:

  • (Hash, nil) —

    the geo details



359
# File 'x-resources/lib/x/resources/post.rb', line 359

attribute :geo, :object

#impression_count ⇒ Integer? (readonly)

The number of impressions

Examples:

Get the impression count

post.impression_count

Returns:

  • (Integer, nil) —

    the impression count



431
# File 'x-resources/lib/x/resources/post.rb', line 431

attribute :impression_count, :integer, key: %w[public_metrics impression_count]

#in_reply_to_user_id ⇒ Integer? (readonly)

The identifier of the user being replied to

Examples:

Get the replied-to user identifier

post.in_reply_to_user_id

Returns:

  • (Integer, nil) —

    the replied-to user identifier



167
# File 'x-resources/lib/x/resources/post.rb', line 167

attribute :in_reply_to_user_id, :integer

#lang ⇒ String? (readonly)

The BCP 47 language tag

Examples:

Get the language

post.lang

Returns:

  • (String, nil) —

    the language tag



127
# File 'x-resources/lib/x/resources/post.rb', line 127

attribute :lang

#like_count ⇒ Integer? (readonly)

The number of likes

Examples:

Get the like count

post.like_count

Returns:

  • (Integer, nil) —

    the like count



407
# File 'x-resources/lib/x/resources/post.rb', line 407

attribute :like_count, :integer, key: %w[public_metrics like_count]

#media_metadata ⇒ Array<Hash> (readonly)

What the post describes of the media it attaches

Examples:

Get the metadata of the media

post.

Returns:

  • (Array<Hash>) —

    the metadata of each medium, empty if there is none



262
# File 'x-resources/lib/x/resources/post.rb', line 262

attribute :media_metadata, :objects

#note_post ⇒ Hash? (readonly) Also known as: note_tweet

The full text and entities of a long post

Examples:

Get the note details

post.note_post

Returns:

  • (Hash, nil) —

    the note details



375
# File 'x-resources/lib/x/resources/post.rb', line 375

attribute :note_post, :object, tweet_key: %w[note_tweet]

Whether the post is a paid partnership

Examples:

Check whether a post is a paid partnership

post.paid_partnership?

Returns:

  • (Boolean, nil) —

    true if the post is a paid partnership



270
# File 'x-resources/lib/x/resources/post.rb', line 270

attribute :paid_partnership, :boolean

#possibly_sensitive ⇒ Boolean? (readonly)

Whether the post may contain sensitive content

Examples:

Check whether a post may be sensitive

post.possibly_sensitive?

Returns:

  • (Boolean, nil) —

    true if the post may be sensitive



175
# File 'x-resources/lib/x/resources/post.rb', line 175

attribute :possibly_sensitive, :boolean

#public_metrics ⇒ Hash? (readonly)

The public metrics

Examples:

Get the public metrics

post.public_metrics

Returns:

  • (Hash, nil) —

    the public metrics



383
# File 'x-resources/lib/x/resources/post.rb', line 383

attribute :public_metrics, :object

#quote_count ⇒ Integer? (readonly)

The number of quotes

Examples:

Get the quote count

post.quote_count

Returns:

  • (Integer, nil) —

    the quote count



415
# File 'x-resources/lib/x/resources/post.rb', line 415

attribute :quote_count, :integer, key: %w[public_metrics quote_count]

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

The referenced posts with their types and identifiers

Examples:

Get the referenced posts

post.referenced_posts

Returns:

  • (Array<Hash>) —

    the referenced posts, empty if there are none



334
# File 'x-resources/lib/x/resources/post.rb', line 334

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

#reply_count ⇒ Integer? (readonly)

The number of replies

Examples:

Get the reply count

post.reply_count

Returns:

  • (Integer, nil) —

    the reply count



399
# File 'x-resources/lib/x/resources/post.rb', line 399

attribute :reply_count, :integer, key: %w[public_metrics reply_count]

#reply_settings ⇒ String? (readonly)

Who can reply: everyone, mentionedUsers, or following

Examples:

Get the reply settings

post.reply_settings

Returns:

  • (String, nil) —

    the reply settings



190
# File 'x-resources/lib/x/resources/post.rb', line 190

attribute :reply_settings

#repost_count ⇒ Integer? (readonly) Also known as: retweet_count

The number of reposts

Examples:

Get the repost count

post.repost_count

Returns:

  • (Integer, nil) —

    the repost count



391
# File 'x-resources/lib/x/resources/post.rb', line 391

attribute :repost_count, :integer, key: %w[public_metrics repost_count], tweet_key: %w[public_metrics retweet_count]

#scopes ⇒ Hash? (readonly)

Who may see the post

A post its author shared with followers alone holds {"followers" => true}.

Examples:

Check whether the post is shared with followers alone

post.scopes&.fetch("followers", false)

Returns:

  • (Hash, nil) —

    the scopes



230
# File 'x-resources/lib/x/resources/post.rb', line 230

attribute :scopes, :object

#withheld ⇒ Hash? (readonly)

The withholding details

Examples:

Get the withholding details

post.withheld

Returns:

  • (Hash, nil) —

    the withholding details



367
# File 'x-resources/lib/x/resources/post.rb', line 367

attribute :withheld, :object

Class Method Details

.count(query, client:, max_pages: nil, **params) ⇒ Integer Originally defined in module Resources::PostCounts

Count the recent posts that match a query, without reading them

The recent posts are counted a page of periods at a time, as the full archive is, which max_pages limits.

Examples:

Count the recent posts about Ruby

X::Post.count("ruby", client: client)

Parameters:

  • query (String) —

    the search query

  • client (Object) —

    the client used to make the requests

  • max_pages (Integer, nil) (defaults to: nil) —

    the most pages of counts to request, or nil for no limit

  • params (Hash) —

    query parameters, such as start_time and end_time

Returns:

  • (Integer) —

    the number of matching posts

Raises:

  • (ArgumentError) —

    if max_pages is neither an Integer of at least 1 nor nil, before a request

  • (InvalidAttribute) —

    if the response holds a total that is not a number

  • (UnreadableResponse) —

    if a page names the token of a page before it as the next

  • (PageLimitReached) —

    if the count requests max_pages pages, and the API names another

.count_all(query, client:, max_pages: nil, **params) ⇒ Integer Originally defined in module Resources::PostCounts

Count the posts from the full archive that match a query, without reading them

The archive is counted a page of periods at a time, and the API bills each page, so a count over many years can take many requests, which max_pages limits, raising PageLimitReached rather than read past them.

Examples:

Count every post about Ruby

X::Post.count_all("ruby", client: client)

Count the posts about Ruby in no more than three requests

X::Post.count_all("ruby", client: client, max_pages: 3)

Parameters:

  • query (String) —

    the search query

  • client (Object) —

    the client used to make the requests

  • max_pages (Integer, nil) (defaults to: nil) —

    the most pages of counts to request, or nil for no limit

  • params (Hash) —

    query parameters, such as start_time and end_time

Returns:

  • (Integer) —

    the number of matching posts

Raises:

  • (ArgumentError) —

    if max_pages is neither an Integer of at least 1 nor nil, before a request

  • (InvalidAttribute) —

    if the response holds a total that is not a number

  • (UnreadableResponse) —

    if a page names the token of a page before it as the next

  • (PageLimitReached) —

    if the count requests max_pages pages, and the API names another

.count_all_by_period(query, client:, max_pages: nil, **params) ⇒ Hash{Range<Time> => Integer} Originally defined in module Resources::PostCounts

Count the posts from the full archive that match a query, by period

The archive is counted a page of periods at a time, and the API bills each page, so a count over many years can take many requests, which max_pages limits, raising PageLimitReached rather than read past them.

Examples:

Count every post about Ruby by day

X::Post.count_all_by_period("ruby", client: client)

Parameters:

  • query (String) —

    the search query

  • client (Object) —

    the client used to make the requests

  • max_pages (Integer, nil) (defaults to: nil) —

    the most pages of counts to request, or nil for no limit

  • params (Hash) —

    query parameters, such as granularity, which is day by default

Returns:

  • (Hash{Range<Time> => Integer}) —

    the number of matching posts, keyed by the time each period spans, from its start up to, but not including, its end, oldest first

Raises:

  • (ArgumentError) —

    if max_pages is neither an Integer of at least 1 nor nil, before a request

  • (InvalidAttribute) —

    if the response holds a period without a start and an end in ISO 8601, or without a count

  • (UnreadableResponse) —

    if a page names the token of a page before it as the next

  • (PageLimitReached) —

    if the count requests max_pages pages, and the API names another

.count_by_period(query, client:, max_pages: nil, **params) ⇒ Hash{Range<Time> => Integer} Originally defined in module Resources::PostCounts

Count the posts from the last seven days that match a query, by period

The recent posts are counted a page of periods at a time, as the full archive is, which max_pages limits.

Examples:

Count the recent posts about Ruby by hour

X::Post.count_by_period("ruby", client: client, granularity: "hour")

Parameters:

  • query (String) —

    the search query

  • client (Object) —

    the client used to make the requests

  • max_pages (Integer, nil) (defaults to: nil) —

    the most pages of counts to request, or nil for no limit

  • params (Hash) —

    query parameters, such as granularity, which is day by default

Returns:

  • (Hash{Range<Time> => Integer}) —

    the number of matching posts, keyed by the time each period spans, from its start up to, but not including, its end, oldest first

Raises:

  • (ArgumentError) —

    if max_pages is neither an Integer of at least 1 nor nil, before a request

  • (InvalidAttribute) —

    if the response holds a period without a start and an end in ISO 8601, or without a count

  • (UnreadableResponse) —

    if a page names the token of a page before it as the next

  • (PageLimitReached) —

    if the count requests max_pages pages, and the API names another

.create(text = nil, client:, reply_to: nil, quote: nil, media_ids: nil, community: nil, **params) ⇒ Post Originally defined in module Resources::PostWrites

Create a post as the authenticated user

The API bills each post created, and bills a post whose text holds a URL more than ten times as much. A post needs no text when it has something else to show, such as media.

Examples:

Create a post

X::Post.create("Hello, World!", client: client)

Post an image without text

X::Post.create(client: client, media_ids: media)

Reply to a post with an image

X::Post.create("Hello!", client: client, reply_to: post, media_ids: [media["id"]])

Reply without the users a thread would otherwise mention

X::Post.create("Hello!", client: client, reply_to: post, reply: {exclude_reply_user_ids: ["7505382"]})

Post in a community

X::Post.create("Hello, Rubyists!", client: client, community: community)

Quote a post

X::Post.create("Worth reading", client: client, quote: post)

Parameters:

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

    the text of the post, or nil for a post without text, such as one of media alone

  • client (Object) —

    the client used to make the request

  • reply_to (Post, String, Integer, nil) (defaults to: nil) —

    the post to reply to or its identifier

  • quote (Post, String, Integer, nil) (defaults to: nil) —

    the post to quote or its identifier

  • 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; an empty list attaches nothing, as nil does

  • community (Community, String, Integer, nil) (defaults to: nil) —

    the community to post in or its identifier

  • params (Hash) —

    additional request body fields, such as poll or reply_settings, among them reply and media, whose other fields reply_to and media_ids are merged into, each named by a String or a Symbol

Returns:

  • (Post) —

    the created post, holding only its identifier and text

Raises:

  • (ArgumentError) —

    if the post has neither text nor any other field, which an empty media_ids is not

  • (MissingResource) —

    if the API answers without the post

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

The default query parameters requesting every post field and expansion

Examples:

Get the default parameters

X::Post.default_params["post.fields"]

Returns:

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

    the default query parameters



98
99
100
101
# File 'x-resources/lib/x/resources/post.rb', line 98

def default_params
  {"post.fields" => FIELDS, "user.fields" => User::FIELDS, "media.fields" => Media::FIELDS,
   "poll.fields" => Poll::FIELDS, "place.fields" => Place::FIELDS, "expansions" => EXPANSIONS}
end

.delete(post, client:) ⇒ Boolean Originally defined in module Resources::PostWrites

Delete a post as the authenticated user

Examples:

Delete a post

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

Parameters:

  • post (Post, String, Integer) —

    the post or its identifier

  • client (Object) —

    the client used to make the request

Returns:

  • (Boolean) —

    true if the post was deleted

.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

.find_all(ids, client:, concurrency: DEFAULT_CONCURRENCY, **params) {|problem| ... } ⇒ Array<Resource> Originally defined in module Resources::BatchFinders

Look up many resources by identifier, in parallel batches

The resources come back in the order of the identifiers they were asked for by, whatever order the batches were answered in, one for each identifier that was found, so an identifier asked for twice comes back twice, as hydrate_all keeps a resource it is given twice. Each identifier is asked for once, however often it is given.

Examples:

Look up many posts by identifier, reporting the ones that were not found

X::Post.find_all([1234567890, 1234567891], client: client) { |problem| warn problem.detail }

Look up many posts one batch at a time, to spend a rate limit more slowly

X::Post.find_all(ids, client: client, concurrency: 1)

Parameters:

  • ids (Array<String, Integer, Resource>) —

    the identifiers, or resources of this class

  • client (Object) —

    the client used to make the requests

  • concurrency (Integer) (defaults to: DEFAULT_CONCURRENCY) —

    the number of batches looked up at once, four by default, which must be at least one; each is a request of up to 100 identifiers, so a lower number spends a rate limit more slowly

  • 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 an identifier that was not found

Returns:

  • (Array<Resource>) —

    the resources that were found, one for each identifier that names one, frozen

Raises:

  • (ArgumentError) —

    if the concurrency is less than one

  • (ArgumentError) —

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

.hide_reply(post, client:) ⇒ Boolean Originally defined in module Resources::PostWrites

Hide a reply to a post of the authenticated user

X still shows a hidden reply, behind a notice that its author was hidden.

Examples:

Hide a reply

X::Post.hide_reply("1234567890", client: client)

Parameters:

  • post (Post, String, Integer) —

    the reply or its identifier

  • client (Object) —

    the client used to make the request

Returns:

  • (Boolean) —

    true if the reply is now hidden

.hydrate_all(resources, client:, concurrency: DEFAULT_CONCURRENCY, **params) {|problem| ... } ⇒ Array<Resource> Originally defined in module Resources::BatchFinders

Replace the resources that are not hydrated with the full resources

A resource that hydrate would look up is looked up, which is a stub and also a resource a response included without every field, so what comes back is hydrated throughout. A resource that was not found is dropped, as is nil, which a reference to no resource reads as, such as the author of a post whose response named none, and a hydrated resource is kept as it is, so resources that are all hydrated need no lookup. What was found is stored in each original, so hydrating one of them afterwards costs no request, unless params override a default field or expansion parameter: what such a lookup found is not the full resource, so it is returned without being stored, and hydrating an original fetches the full resource. A resource that holds what hydrate returns, because hydrate or an earlier hydrate_all stored it, is replaced with that, and looked up again by no request, since the API bills each resource a lookup returns.

Examples:

Look up every field of the authors of posts, the ones a search included among them

X::User.hydrate_all(posts.map(&:author), client: client)

Expand only the authors a search did not include, which the API bills for alone

X::User.hydrate_all(posts.filter_map(&:author).select(&:stub?), client: client)

Parameters:

  • resources (Array<Resource, nil>) —

    the resources, some of which may not be hydrated, and some nil

  • client (Object) —

    the client used to make the requests

  • concurrency (Integer) (defaults to: DEFAULT_CONCURRENCY) —

    the number of batch lookups made at once, four by default, which must be at least one

  • 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:

  • (Array<Resource>) —

    the resources, in order, with the ones that were not hydrated replaced, frozen

Raises:

  • (ArgumentError) —

    if the concurrency is less than one

  • (ArgumentError) —

    if a resource is not of this class, which a lookup of its identifier would find another resource for, before a request

.reposts_of_me(client:, **params) ⇒ Cursor Also known as: retweets_of_me Originally defined in module Resources::PostSearch

The posts of the authenticated user that other users have reposted

The endpoint names no user, so these are always the posts of the user the client authenticates as.

Examples:

Print the reposted posts

X::Post.reposts_of_me(client: client).each { |post| puts post.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 reposted posts

.search(query, client:, **params) ⇒ Cursor Originally defined in module Resources::PostSearch

Search recent posts

Examples:

Print posts about Ruby

X::Post.search("ruby -is:retweet", client: client).each { |post| puts post.text }

Parameters:

  • query (String) —

    the search query

  • client (Object) —

    the client used to make the requests

  • params (Hash) —

    query parameters merged over the default parameters

Returns:

  • (Cursor) —

    a cursor over the matching posts

.search_all(query, client:, **params) ⇒ Cursor Originally defined in module Resources::PostSearch

Search the full archive of posts

A page holds up to 500 posts, or 100 when the request asks for context annotations, as the default fields do.

Examples:

Print every post about Ruby

X::Post.search_all("ruby -is:retweet", client: client).each { |post| puts post.text }

Page through every post about Ruby 500 at a time, without context annotations

X::Post.search_all("ruby", client: client, "post.fields": %w[created_at text])

Parameters:

  • query (String) —

    the search query

  • client (Object) —

    the client used to make the requests

  • params (Hash) —

    query parameters merged over the default parameters

Returns:

  • (Cursor) —

    a cursor over the matching posts

.unhide_reply(post, client:) ⇒ Boolean Originally defined in module Resources::PostWrites

Show a reply that was hidden, as the author of the post it replies to

Examples:

Show a hidden reply

X::Post.unhide_reply("1234567890", client: client)

Parameters:

  • post (Post, String, Integer) —

    the reply or its identifier

  • client (Object) —

    the client used to make the request

Returns:

  • (Boolean) —

    true if the reply is no longer hidden

Instance Method Details

#author ⇒ User?

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

Examples:

Get the author's username

post.author.username

Returns:

  • (User, nil) —

    the author



439
# File 'x-resources/lib/x/resources/post.rb', line 439

reference :author, :User, key: %w[author_id]

#community ⇒ Community?

The community the post was made in, as a stub holding only its identifier

Examples:

Get the community's name

post.community.hydrate.name

Returns:



455
# File 'x-resources/lib/x/resources/post.rb', line 455

reference :community, :Community, key: %w[community_id]

#delete ⇒ Boolean

Delete this post as the authenticated user

Examples:

Delete a post

post.delete

Returns:

  • (Boolean) —

    true if the post was deleted



553
554
555
# File 'x-resources/lib/x/resources/post.rb', line 553

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

#entities ⇒ Hash?

The entities found in the full text

The entities, such as links, mentions, and hashtags, come from note_post for a long post, whose note the API gives entities when the full text has any, and from the post itself for a short one, so that each lies where #text holds it. A long post whose note holds none has none: the entities the post holds itself, such as its annotations, lie in the text cut short, which attrs holds.

Examples:

Get the entities

post.entities

Returns:

  • (Hash, nil) —

    the entities

Raises:

  • (InvalidAttribute) —

    if the response holds a note_post, or entities, that is not an object



291
# File 'x-resources/lib/x/resources/post.rb', line 291

def entities = Shape.read_object("#{self.class}#entities", full["entities"])

#expanded_text ⇒ String?

The text with every shortened link replaced by the URL it stands for

A link the API expanded to no URL is left as it is, and a link without a url, which the API documents as one that may hold none, is passed over, as it holds nothing to replace.

Every link is replaced in one pass over the text, so a URL a link stands for is never read for the links after it, and holds what it holds, even the shortened url of another link of the post. A url that begins another, longer one is not read in it.

The rest of the text is as #text reads it, HTML-escaped as the API sends it, and each URL is HTML-escaped as it is put in, since the API sends a URL as it is, so the whole text is escaped alike: unescape it to display it.

Examples:

Display a post with its links in full

CGI.unescapeHTML(post.expanded_text)

Returns:

  • (String, nil) —

    the text with expanded links

Raises:

  • (InvalidAttribute) —

    if the response holds a link whose url, or whose expanded_url beside a url, is neither a String nor null, or text that is not a String



542
543
544
545
# File 'x-resources/lib/x/resources/post.rb', line 542

def expanded_text
  replacements = expansions
  Shape.read_string("#{self.class}#expanded_text", text)&.gsub(Regexp.union(replacements.keys.sort_by { |url| -url.length }), replacements)
end

#hide_reply ⇒ Boolean

Hide this reply, as the author of the post it replies to

Examples:

Hide a reply

reply.hide_reply

Returns:

  • (Boolean) —

    true if the reply is now hidden



563
564
565
# File 'x-resources/lib/x/resources/post.rb', line 563

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

#in_reply_to_user ⇒ User?

The user being replied to, resolved from the includes or built as a stub

Examples:

Get the replied-to user

post.in_reply_to_user

Returns:

  • (User, nil) —

    the replied-to user



447
# File 'x-resources/lib/x/resources/post.rb', line 447

reference :in_reply_to_user, :User, key: %w[in_reply_to_user_id]

#liked_by(**params) ⇒ Cursor Originally defined in module Resources::PostCollections

The users who liked this post

Examples:

Print the users who liked a post

post.liked_by.each { |user| puts user.username }

Parameters:

  • params (Hash) —

    query parameters merged over the default parameters

Returns:

  • (Cursor) —

    a cursor over the users who liked the post

#matching_rules ⇒ Array<MatchingRule>

The rules of the filtered stream this post matched

A post the filtered stream delivers names the rules it matched, and any other post names none. The streaming client of x-streams builds the posts of a stream given X::Post as its object_class.

Examples:

Print the tags of the rules each post of the filtered stream matched

streaming_client.stream("tweets/search/stream", object_class: X::Post) { |post| p post.matching_rules.map(&:tag) }

Returns:

  • (Array<MatchingRule>) —

    the rules, empty for a post that did not come from the filtered stream

Raises:

  • (InvalidAttribute) —

    if the response holds the rules as something other than a list of objects, or a rule without an identifier that is a number, or with a tag that is not a String



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

def matching_rules
  reader = "#{self.class}#matching_rules"
  Shape.objects(reader, attrs["matching_rules"]).map { |rule| Utils.read(reader, rule) { MatchingRule.new(rule) } }.freeze
end

#media ⇒ Array<Media>

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

Examples:

Get the media URLs

post.media.map(&:url)

Returns:

  • (Array<Media>) —

    the media



471
# File 'x-resources/lib/x/resources/post.rb', line 471

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

#media_source_posts ⇒ Array<Post> Also known as: media_source_tweets

The posts the attached media was first posted with

A post that attaches media another post was made with, as one that shares a video does, names that post as the source of the media. Each is read from the includes, or built as a stub holding only its identifier.

Examples:

Credit the author of shared media

post.media_source_posts.map { |source| source.author&.username }

Returns:

  • (Array<Post>) —

    the posts, empty if the media was first posted with this post, or it has none



491
# File 'x-resources/lib/x/resources/post.rb', line 491

references :media_source_posts, :Post, key: %w[attachments media_source_tweet_id]

Check whether the post is a paid partnership

Examples:

Check whether the post is a paid partnership

post.paid_partnership?

Returns:

  • (Boolean) —

    true if the post is a paid partnership



# File 'x-resources/lib/x/resources/post.rb', line 272

The permalink of the post, by the author's username when known

Examples:

Get the permalink

post.permalink # => "https://x.com/sferik/status/1234567890"

Returns:

  • (String) —

    the x.com address of the post

Raises:

  • (InvalidAttribute) —

    if the response holds the username of the author as something other than a String



513
# File 'x-resources/lib/x/resources/post.rb', line 513

def permalink = "https://x.com/#{Shape.read_string("#{self.class}#permalink", author&.username) || "i"}/status/#{id}"

#place ⇒ Place?

The tagged place, from the includes or as a stub holding only its identifier

Examples:

Get the place

post.place

Returns:

  • (Place, nil) —

    the place



463
# File 'x-resources/lib/x/resources/post.rb', line 463

reference :place, :Place, key: %w[geo place_id]

#polls ⇒ Array<Poll>

The attached polls, from the includes or as stubs holding only their identifiers

Examples:

Get the poll options

post.polls.first.options

Returns:

  • (Array<Poll>) —

    the polls



479
# File 'x-resources/lib/x/resources/post.rb', line 479

references :polls, :Poll, key: %w[attachments poll_ids]

#possibly_sensitive? ⇒ Boolean

Check whether the post may contain sensitive content

Examples:

Check whether the post may contain sensitive content

post.possibly_sensitive?

Returns:

  • (Boolean) —

    true if the post may be sensitive



# File 'x-resources/lib/x/resources/post.rb', line 177

#quote? ⇒ Boolean Originally defined in module Resources::References

Check whether this post is a quote

Examples:

Check whether a post is a quote

post.quote?

Returns:

  • (Boolean) —

    true if the post quotes another post

#quoted ⇒ Post? Originally defined in module Resources::References

The post this post quotes

Examples:

Get the quoted post

post.quoted

Returns:

  • (Post, nil) —

    the quoted post

Raises:

  • (InvalidAttribute) —

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

#quotes(**params) ⇒ Cursor Also known as: quote_tweets Originally defined in module Resources::PostCollections

The posts quoting this post

Examples:

Print the quotes

post.quotes.each { |quote| puts quote.text }

Parameters:

  • params (Hash) —

    query parameters merged over the default parameters

Returns:

  • (Cursor) —

    a cursor over the quotes

#references ⇒ Array<Post> Originally defined in module Resources::References

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

Examples:

Get the referenced posts

post.references

Returns:

  • (Array<Post>) —

    the referenced posts

Raises:

  • (InvalidAttribute) —

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

#replied_to ⇒ Post? Originally defined in module Resources::References

The post this post replies to

Examples:

Get the replied-to post

post.replied_to

Returns:

  • (Post, nil) —

    the replied-to post

Raises:

  • (InvalidAttribute) —

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

#reply? ⇒ Boolean Originally defined in module Resources::References

Check whether this post is a reply

Examples:

Check whether a post is a reply

post.reply?

Returns:

  • (Boolean) —

    true if the post replies to another post

#repost? ⇒ Boolean Also known as: retweet? Originally defined in module Resources::References

Check whether this post is a repost

Examples:

Check whether a post is a repost

post.repost?

Returns:

  • (Boolean) —

    true if the post reposts another post

#reposted ⇒ Post? Also known as: retweeted Originally defined in module Resources::References

The post this post reposts

Examples:

Get the reposted post

post.reposted

Returns:

  • (Post, nil) —

    the reposted post

Raises:

  • (InvalidAttribute) —

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

#reposted_by(**params) ⇒ Cursor Also known as: retweeted_by Originally defined in module Resources::PostCollections

The users who reposted this post

Examples:

Print the reposting users

post.reposted_by.each { |user| puts user.username }

Parameters:

  • params (Hash) —

    query parameters merged over the default parameters

Returns:

  • (Cursor) —

    a cursor over the reposting users

#reposts(**params) ⇒ Cursor Also known as: retweets Originally defined in module Resources::PostCollections

The reposts of this post, each a post of its own by the user who reposted it

Examples:

Print when and by whom a post was reposted

post.reposts.each { |repost| puts "#{repost.author.username} at #{repost.created_at}" }

Parameters:

  • params (Hash) —

    query parameters merged over the default parameters

Returns:

  • (Cursor) —

    a cursor over the reposts

#text ⇒ String?

The full text

A long post, of more than 280 characters, holds its full text in note_post, and a text cut short with an ellipsis and a link to the post; this reads the full 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

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

Display the text

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

Returns:

  • (String, nil) —

    the text, HTML-escaped as the API sends it

Raises:

  • (InvalidAttribute) —

    if the response holds a note_post that is not an object



119
# File 'x-resources/lib/x/resources/post.rb', line 119

def text = full["text"]

#unhide_reply ⇒ Boolean

Show this reply after hiding it, as the author of the post it replies to

Examples:

Show a hidden reply

reply.unhide_reply

Returns:

  • (Boolean) —

    true if the reply is no longer hidden



573
574
575
# File 'x-resources/lib/x/resources/post.rb', line 573

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

#uri ⇒ URI::Generic

The permalink of the post as a URI

Examples:

Get the address as a URI

post.uri # => #<URI::HTTPS https://x.com/sferik/status/1234567890>

Returns:

  • (URI::Generic) —

    the x.com address of the post

Raises:

  • (InvalidAttribute) —

    if the response holds the username of the author as something other than a String



522
# File 'x-resources/lib/x/resources/post.rb', line 522

def uri = URI(permalink)

#urls ⇒ Array<Hash>

The links in the full text, each with its shortened url and its expanded_url

Examples:

Get the links

post.urls # => [{"url" => "https://t.co/...", "expanded_url" => "https://github.com/sferik/x-ruby", ...}]

Returns:

  • (Array<Hash>) —

    the links, empty if there are none

Raises:

  • (InvalidAttribute) —

    if the response holds entities, or links, that are not what the API documents



300
# File 'x-resources/lib/x/resources/post.rb', line 300

def urls = Shape.objects("#{self.class}#urls", entities&.[]("urls"))