--- /dev/null
+interactions:
+- request:
+ body: null
+ headers:
+ Accept:
+ - '*/*'
+ Accept-Encoding:
+ - gzip, deflate
+ Connection:
+ - keep-alive
+ User-Agent:
+ - Python/3.9.7 Requests/2.25.1 Tweepy/4.0.1
+ method: GET
+ uri: https://api.twitter.com/2/spaces/1YpKkzBgBlVxj
+ response:
+ body:
+ string: !!binary |
+ H4sIAAAAAAAAAKpWSkksSVSyqlbKTFGyUjKMLPDOrnJKd8oJq8hS0lEqLkksSQWKp+alpKYo1dYC
+ AAAA//8DANuEAIIvAAAA
+ headers:
+ api-version:
+ - '2.27'
+ cache-control:
+ - no-cache, no-store, max-age=0
+ content-disposition:
+ - attachment; filename=json.json
+ content-encoding:
+ - gzip
+ content-length:
+ - '72'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 04 Oct 2021 16:20:09 UTC
+ server:
+ - tsa_b
+ set-cookie:
+ - personalization_id="v1_8sltSYl5ot2fwTzCtHyhmg=="; Max-Age=63072000; Expires=Wed,
+ 04 Oct 2023 16:20:09 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+ - guest_id=v1%3A163336440956178191; Max-Age=63072000; Expires=Wed, 04 Oct 2023
+ 16:20:09 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+ strict-transport-security:
+ - max-age=631138519
+ x-access-level:
+ - read
+ x-connection-hash:
+ - fa3c76458eec0126e6a6b25810e44e72902ac0c3351b444f01b0531fb127b2ac
+ x-content-type-options:
+ - nosniff
+ x-frame-options:
+ - SAMEORIGIN
+ x-rate-limit-limit:
+ - '300'
+ x-rate-limit-remaining:
+ - '298'
+ x-rate-limit-reset:
+ - '1633364979'
+ x-xss-protection:
+ - '0'
+ status:
+ code: 200
+ message: OK
+version: 1
--- /dev/null
+interactions:
+- request:
+ body: null
+ headers:
+ Accept:
+ - '*/*'
+ Accept-Encoding:
+ - gzip, deflate
+ Connection:
+ - keep-alive
+ User-Agent:
+ - Python/3.9.7 Requests/2.25.1 Tweepy/4.0.1
+ method: GET
+ uri: https://api.twitter.com/2/spaces?ids=1YpKkzBgBlVxj%2C1OwGWzarWnNKQ
+ response:
+ body:
+ string: !!binary |
+ H4sIAAAAAAAAAKpWSkksSVSyiq5WykxRslIyjCzwzq5ySnfKCavIUtJRKi5JLEkFiqfmpaSmKNXq
+ wJT5l7uHVyUWhef5eQdiKoutBQAAAP//AwAJdS/qWAAAAA==
+ headers:
+ api-version:
+ - '2.27'
+ cache-control:
+ - no-cache, no-store, max-age=0
+ content-disposition:
+ - attachment; filename=json.json
+ content-encoding:
+ - gzip
+ content-length:
+ - '91'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 04 Oct 2021 16:20:10 UTC
+ server:
+ - tsa_b
+ set-cookie:
+ - personalization_id="v1_yfFprXL2G/FrJYvpbXwcUg=="; Max-Age=63072000; Expires=Wed,
+ 04 Oct 2023 16:20:10 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+ - guest_id=v1%3A163336440996144486; Max-Age=63072000; Expires=Wed, 04 Oct 2023
+ 16:20:10 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+ strict-transport-security:
+ - max-age=631138519
+ x-access-level:
+ - read
+ x-connection-hash:
+ - 611a98e7bbb653d89c38826150224a0fbc2f7ea1a18ac1b80da236f8a6e271b0
+ x-content-type-options:
+ - nosniff
+ x-frame-options:
+ - SAMEORIGIN
+ x-rate-limit-limit:
+ - '300'
+ x-rate-limit-remaining:
+ - '297'
+ x-rate-limit-reset:
+ - '1633364979'
+ x-xss-protection:
+ - '0'
+ status:
+ code: 200
+ message: OK
+- request:
+ body: null
+ headers:
+ Accept:
+ - '*/*'
+ Accept-Encoding:
+ - gzip, deflate
+ Connection:
+ - keep-alive
+ Cookie:
+ - guest_id=v1%3A163336440996144486; personalization_id="v1_yfFprXL2G/FrJYvpbXwcUg=="
+ User-Agent:
+ - Python/3.9.7 Requests/2.25.1 Tweepy/4.0.1
+ method: GET
+ uri: https://api.twitter.com/2/spaces/by/creator_ids?user_ids=1065249714214457345%2C2328002822
+ response:
+ body:
+ string: !!binary |
+ H4sIAAAAAAAAAKpWSkksSVSyiq5WykxRslIyLPOvKK/MCSpM9XF3UtJRKi5JLEkFihcnZ6SmlOak
+ pijVxuoo5aaC9FQrFaUWl+aUxCfnl+aVKFkZ1tYCAAAA//8DAErOjQNPAAAA
+ headers:
+ api-version:
+ - '2.27'
+ cache-control:
+ - no-cache, no-store, max-age=0
+ content-disposition:
+ - attachment; filename=json.json
+ content-encoding:
+ - gzip
+ content-length:
+ - '102'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 04 Oct 2021 16:20:10 UTC
+ server:
+ - tsa_b
+ strict-transport-security:
+ - max-age=631138519
+ x-access-level:
+ - read
+ x-connection-hash:
+ - 611a98e7bbb653d89c38826150224a0fbc2f7ea1a18ac1b80da236f8a6e271b0
+ x-content-type-options:
+ - nosniff
+ x-frame-options:
+ - SAMEORIGIN
+ x-rate-limit-limit:
+ - '300'
+ x-rate-limit-remaining:
+ - '296'
+ x-rate-limit-reset:
+ - '1633364979'
+ x-xss-protection:
+ - '0'
+ status:
+ code: 200
+ message: OK
+version: 1
--- /dev/null
+interactions:
+- request:
+ body: null
+ headers:
+ Accept:
+ - '*/*'
+ Accept-Encoding:
+ - gzip, deflate
+ Connection:
+ - keep-alive
+ User-Agent:
+ - Python/3.9.7 Requests/2.25.1 Tweepy/4.0.1
+ method: GET
+ uri: https://api.twitter.com/2/spaces/search?query=Twitter&state=live
+ response:
+ body:
+ string: !!binary |
+ H4sIAAAAAAAAAHzQTwuCMBzG8ffyO3vpmDdHYzD/5Q5RRsRsY6jTdE7RxPdeHTqFXh8+8MB3BsEt
+ B/c6Qy7AhZ1qx0GXE1INQeBAZ7mVn13ng4TF+SnJaRZlBiUnel5XsfANwugQtv6GKgfaeKZqmmTE
+ 66oIqZIq0JXnB+uqqokUE6sjvPU41TROMT+yF2EbKiL8wiMtBSnWlWB+qouwbQ3973VzoJLfvDMY
+ 2fXa3h/Pvrbg7pflDQAA//8DAO2i+Rp6AQAA
+ headers:
+ api-version:
+ - '2.27'
+ cache-control:
+ - no-cache, no-store, max-age=0
+ content-disposition:
+ - attachment; filename=json.json
+ content-encoding:
+ - gzip
+ content-length:
+ - '198'
+ content-type:
+ - application/json; charset=utf-8
+ date:
+ - Mon, 04 Oct 2021 16:23:43 UTC
+ server:
+ - tsa_b
+ set-cookie:
+ - personalization_id="v1_Q5Y420A90rTxiUPNvjznYg=="; Max-Age=63072000; Expires=Wed,
+ 04 Oct 2023 16:23:43 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+ - guest_id=v1%3A163336462208298649; Max-Age=63072000; Expires=Wed, 04 Oct 2023
+ 16:23:43 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
+ strict-transport-security:
+ - max-age=631138519
+ x-access-level:
+ - read
+ x-connection-hash:
+ - ba8571db95a98d39f2a2ddeac9236e3648f62c3a289efe13ccf35ea85b5de519
+ x-content-type-options:
+ - nosniff
+ x-frame-options:
+ - SAMEORIGIN
+ x-rate-limit-limit:
+ - '300'
+ x-rate-limit-remaining:
+ - '289'
+ x-rate-limit-reset:
+ - '1633364956'
+ x-xss-protection:
+ - '0'
+ status:
+ code: 200
+ message: OK
+version: 1
.. automethod:: Client.get_users
+Spaces
+======
+
+Search Spaces
+-------------
+
+.. automethod:: Client.search_spaces
+
+Spaces lookup
+-------------
+
+.. automethod:: Client.get_spaces
+
+.. automethod:: Client.get_space
+
Expansions and Fields Parameters
================================
``expansions``
--------------
-For methods that return Tweets, `Expansions`_ enable you to request additional
-data objects that relate to the originally returned Tweets. Submit a list of
-desired expansions in a comma-separated list without spaces. The ID that
-represents the expanded data object will be included directly in the Tweet data
-object, but the expanded object metadata will be returned within the
+`Expansions`_ enable you to request additional data objects that relate to the
+originally returned Space, Tweets, or users. Submit a list of desired
+expansions in a comma-separated list without spaces. The ID that represents the
+expanded data object will be included directly in the Space, Tweet, or user
+data object, but the expanded object metadata will be returned within the
``includes`` response object, and will also include the ID so that you can
-match this data object to the original Tweet object.
+match this data object to the original Space or Tweet object.
-The following data objects can be expanded using this parameter:
+For methods that return Spaces, the following data objects can be expanded
+using this parameter:
+
+* The Spaces creator's user object
+* The user objects of any Space co-host
+* Any mentioned users’ object
+* Any speaker's user object
+
+For methods that return Tweets, the following data objects can be expanded
+using this parameter:
* The Tweet author's user object
* The user object of the Tweet’s author that the
* Attached place’s object
* Any referenced Tweets’ object
-For methods that return users, `Expansions`_ enable you to request additional
-data objects that relate to the originally returned users. The ID that
-represents the expanded data object will be included directly in the user data
-object, but the expanded object metadata will be returned within the
-``includes`` response object, and will also include the ID so that you can
-match this data object to the original Tweet object. At this time, the only
-expansion available to endpoints that primarily return user objects is
-``expansions=pinned_tweet_id``. You will find the expanded Tweet data object
-living in the ``includes`` response object.
+At this time, the only expansion available to endpoints that primarily return
+user objects is ``expansions=pinned_tweet_id``. You will find the expanded
+Tweet data object living in the ``includes`` response object.
.. _media_fields_parameter:
request. While the poll ID will be located in the Tweet object, you will find
this ID and all additional poll fields in the ``includes`` data object.
+.. _space_fields_parameter:
+
+``space_fields``
+----------------
+
+This `fields`_ parameter enables you to select which specific `Space fields`_
+will deliver in each returned Space. Specify the desired fields in a
+comma-separated list.
+
.. _tweet_fields_parameter:
``tweet_fields``
``user_fields``
---------------
-For methods that return Tweets, this `fields`_ parameter enables you to select
-which specific `user fields`_ will deliver in each returned Tweet. Specify the
-desired fields in a comma-separated list without spaces between commas and
-fields. While the user ID will be located in the original Tweet object, you
-will find this ID and all additional user fields in the ``includes`` data
-object.
+For methods that return Spaces or Tweets, this `fields`_ parameter enables you
+to select which specific `user fields`_ will deliver in each returned Space or
+Tweet. Specify the desired fields in a comma-separated list without spaces
+between commas and fields. While the user ID will be located in the original
+Tweet object, you will find this ID and all additional user fields in the
+``includes`` data object.
You must also pass one of the user expansions to return the desired user
fields:
.. _media fields: https://developer.twitter.com/en/docs/twitter-api/data-dictionary/object-model/media
.. _place fields: https://developer.twitter.com/en/docs/twitter-api/data-dictionary/object-model/place
.. _poll fields: https://developer.twitter.com/en/docs/twitter-api/data-dictionary/object-model/poll
+.. _Space fields: https://developer.twitter.com/en/docs/twitter-api/data-dictionary/object-model/space
.. _Tweet fields: https://developer.twitter.com/en/docs/twitter-api/data-dictionary/object-model/tweet
.. _user fields: https://developer.twitter.com/en/docs/twitter-api/data-dictionary/object-model/user
:reference: https://developer.twitter.com/en/docs/twitter-api/data-dictionary/object-model/tweet
+ .. class:: tweepy.Space
+
+ :reference: https://developer.twitter.com/en/docs/twitter-api/data-dictionary/object-model/space
+
.. class:: tweepy.Tweet
:reference: https://developer.twitter.com/en/docs/twitter-api/data-dictionary/object-model/tweet
@tape.use_cassette("test_get_users.yaml", serializer="yaml")
def test_get_users(self):
self.client.get_users(usernames=["Twitter", "TwitterDev"])
+
+ @tape.use_cassette("test_search_spaces.yaml", serializer="yaml")
+ def test_search_spaces(self):
+ self.client.search_spaces("Twitter", "live")
+
+ @tape.use_cassette("test_get_spaces.yaml", serializer="yaml")
+ def test_get_spaces(self):
+ space_ids = ["1YpKkzBgBlVxj", "1OwGWzarWnNKQ"]
+ # Space ID for @TwitterSpaces Twitter Spaces community gathering + Q&A
+ # https://twitter.com/TwitterSpaces/status/1436382283347283969
+ # Space ID for @NASA #NASAWebb Space Telescope 101 and Q&A
+ # https://twitter.com/NASA/status/1442961745098653701
+ user_ids = [1065249714214457345, 2328002822]
+ # User IDs for @TwitterSpaces and @TwitterWomen
+ self.client.get_spaces(ids=space_ids)
+ self.client.get_spaces(user_ids=user_ids)
+
+ @tape.use_cassette("test_get_space.yaml", serializer="yaml")
+ def test_get_space(self):
+ space_id = "1YpKkzBgBlVxj"
+ # Space ID for @TwitterSpaces Twitter Spaces community gathering + Q&A
+ # https://twitter.com/TwitterSpaces/status/1436382283347283969
+ self.client.get_space(space_id)
from tweepy.pagination import Paginator
from tweepy.place import Place
from tweepy.poll import Poll
+from tweepy.space import Space
from tweepy.streaming import Stream
from tweepy.tweet import ReferencedTweet, Tweet
from tweepy.user import User
from tweepy.media import Media
from tweepy.place import Place
from tweepy.poll import Poll
+from tweepy.space import Space
from tweepy.tweet import Tweet
from tweepy.user import User
"ids", "usernames", "expansions", "tweet.fields", "user.fields"
), data_type=User, user_auth=user_auth
)
+
+ # Search Spaces
+
+ def search_spaces(self, query, state, **params):
+ """search_spaces(query, state, *, expansions, max_results, \
+ space_fields, user_fields)
+
+ Return live or scheduled Spaces matching your specified search terms
+
+ Parameters
+ ----------
+ query : str
+ Your search term. This can be any text (including mentions and
+ Hashtags) present in the title of the Space.
+ state : str
+ Determines the type of results to return. Use ``live`` to return
+ live Spaces or ``scheduled`` to return upcoming Spaces.
+ expansions : Union[List[str], str]
+ :ref:`expansions_parameter`
+ max_results : int
+ The maximum number of results to return in this request. Specify a
+ value between 1 and 100.
+ space_fields : Union[List[str], str]
+ :ref:`space_fields_parameter`
+ user_fields : Union[List[str], str]
+ :ref:`user_fields_parameter`
+
+ Returns
+ -------
+ Union[dict, requests.Response, Response]
+
+ References
+ ----------
+ https://developer.twitter.com/en/docs/twitter-api/spaces/search/api-reference/get-spaces-search
+ """
+ params["query"] = query
+ params["state"] = state
+ return self._make_request(
+ "GET", "/2/spaces/search", params=params,
+ endpoint_parameters=(
+ "query", "state", "expansions", "max_results", "space.fields",
+ "user.fields"
+ ), data_type=Space
+ )
+
+ # Spaces lookup
+
+ def get_spaces(self, *, ids=None, user_ids=None, **params):
+ """get_spaces(*, ids, user_ids, expansions, space_fields, user_fields)
+
+ Returns details about multiple live or scheduled Spaces (created by the
+ specified user IDs if specified). Up to 100 comma-separated Space or
+ user IDs can be looked up using this endpoint.
+
+ Parameters
+ ----------
+ ids : Union[List[str], str]
+ A comma separated list of Spaces (up to 100).
+ user_ids : Union[List[int, str], str]
+ A comma separated list of user IDs (up to 100).
+ expansions : Union[List[str], str]
+ :ref:`expansions_parameter`
+ space_fields : Union[List[str], str]
+ :ref:`space_fields_parameter`
+ user_fields : Union[List[str], str]
+ :ref:`user_fields_parameter`
+
+ Raises
+ ------
+ TypeError
+ If IDs and user IDs are not passed or both are passed
+
+ Returns
+ -------
+ Union[dict, requests.Response, Response]
+
+ References
+ ----------
+ https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces
+ https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-by-creator-ids
+ """
+ if ids is not None and user_ids is not None:
+ raise TypeError("Expected IDs or user IDs, not both")
+
+ route = "/2/spaces"
+
+ if ids is not None:
+ params["ids"] = ids
+ elif user_ids is not None:
+ route += "/by/creator_ids"
+ params["user_ids"] = user_ids
+ else:
+ raise TypeError("IDs or user IDs are required")
+
+ return self._make_request(
+ "GET", route, params=params,
+ endpoint_parameters=(
+ "ids", "user_ids", "expansions", "space.fields", "user.fields"
+ ), data_type=Space
+ )
+
+ def get_space(self, id, **params):
+ """get_space(id, *, expansions, space_fields, user_fields)
+
+ Returns a variety of information about a single Space specified by the
+ requested ID.
+
+ Parameters
+ ----------
+ id : Union[List[str], str]
+ Unique identifier of the Space to request.
+ expansions : Union[List[str], str]
+ :ref:`expansions_parameter`
+ space_fields : Union[List[str], str]
+ :ref:`space_fields_parameter`
+ user_fields : Union[List[str], str]
+ :ref:`user_fields_parameter`
+
+ Returns
+ -------
+ Union[dict, requests.Response, Response]
+
+ References
+ ----------
+ https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-id
+ """
+ return self._make_request(
+ "GET", f"/2/spaces/{id}", params=params,
+ endpoint_parameters=(
+ "expansions", "space.fields", "user.fields"
+ ), data_type=Space
+ )
--- /dev/null
+# Tweepy
+# Copyright 2009-2021 Joshua Roesslein
+# See LICENSE for details.
+
+import datetime
+
+from tweepy.mixins import DataMapping, HashableID
+
+
+class Space(HashableID, DataMapping):
+
+ __slots__ = (
+ "data", "id", "state", "created_at", "host_ids", "lang", "is_ticketed",
+ "invited_user_ids", "participant_count", "scheduled_start",
+ "speaker_ids", "started_at", "title", "updated_at"
+ )
+
+ def __init__(self, data):
+ self.data = data
+ self.id = data["id"]
+ self.state = data["state"]
+
+ self.created_at = data.get("created_at")
+ if self.created_at is not None:
+ self.created_at = datetime.datetime.strptime(
+ self.created_at, "%Y-%m-%dT%H:%M:%S.%f%z"
+ )
+
+ self.host_ids = data.get("host_ids", [])
+ self.lang = data.get("lang")
+ self.is_ticketed = data.get("is_ticketed")
+ self.invited_user_ids = data.get("invited_user_ids", [])
+ self.participant_count = data.get("participant_count")
+
+ self.scheduled_start = data.get("scheduled_start")
+ if self.scheduled_start is not None:
+ self.scheduled_start = datetime.datetime.strptime(
+ self.scheduled_start, "%Y-%m-%dT%H:%M:%S.%f%z"
+ )
+
+ self.speaker_ids = data.get("speaker_ids", [])
+
+ self.started_at = data.get("started_at")
+ if self.started_at is not None:
+ self.started_at = datetime.datetime.strptime(
+ self.started_at, "%Y-%m-%dT%H:%M:%S.%f%z"
+ )
+
+ self.title = data.get("title")
+
+ self.updated_at = data.get("updated_at")
+ if self.updated_at is not None:
+ self.updated_at = datetime.datetime.strptime(
+ self.updated_at, "%Y-%m-%dT%H:%M:%S.%f%z"
+ )
+
+ def __repr__(self):
+ return f"<Space id={self.id} state={self.state}>"
+
+ def __str__(self):
+ return self.full_name