Skip to content

Commit

Permalink
Merge pull request #165 from MerleLiuKun/feat-search-users
Browse files Browse the repository at this point in the history
Feat search users
  • Loading branch information
MerleLiuKun committed Mar 18, 2024
2 parents 326ae7c + e9bc313 commit 8f19b90
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 1 deletion.
12 changes: 12 additions & 0 deletions docs/docs/usage/users/search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
The Users Search endpoint provides a simple, relevance-based search interface to public user accounts on X. Try querying by topical interest, full name, company name, location, or other criteria.

You can get more information for this at [docs](https://developer.twitter.com/en/docs/twitter-api/users/search/introduction)

## Search Users

Get users that match a search query.

```python
my_api.search_users(query="developers")
# Response(data=[User(id='866707894389141505', name='Refinitiv Developers', username='Developers'), User(id='2244994945', name='Developers', username='XDevelopers')])
```
1 change: 1 addition & 0 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ nav:
- Follows: usage/users/follows.md
- Blocks: usage/users/blocks.md
- Mutes: usage/users/mutes.md
- Search: usage/users/search.md
- Spaces:
- Spaces Lookup: usage/spaces/spaces-lookup.md
- Search Spaces: usage/spaces/search.md
Expand Down
41 changes: 41 additions & 0 deletions pytwitter/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1786,6 +1786,47 @@ def get_me(
return_json=return_json,
)

def search_users(
self,
query: str,
*,
max_results: Optional[int] = None,
next_token: Optional[str] = None,
user_fields: Optional[Union[str, List, Tuple]] = None,
expansions: Optional[Union[str, List, Tuple]] = None,
tweet_fields: Optional[Union[str, List, Tuple]] = None,
return_json: bool = False,
) -> Union[dict, md.Response]:
"""
returns Users that match a search query.
:param query: One query for matching Users.
:param max_results: The maximum number of search results to be returned by a request. A number between 1 and 1000. By default, a request response will return 100 results.
:param next_token: Token for the pagination.
:param user_fields: Fields for the user object.
:param expansions: Fields for the expansions.
:param tweet_fields: Fields for the tweet object, Expansion required.
:param return_json: Type for returned data. If you set True JSON data will be returned.
:return: Response instance or json.
"""

args = {
"query": query,
"max_results": max_results,
"next_token": next_token,
"user.fields": enf_comma_separated(name="user_fields", value=user_fields),
"expansions": enf_comma_separated(name="expansions", value=expansions),
"tweet.fields": enf_comma_separated(
name="tweet_fields", value=tweet_fields
),
}
return self._get(
url="https://api.twitter.com/2/users/search",
params=args,
cls=md.User,
multi=True,
return_json=return_json,
)

def get_following(
self,
user_id: str,
Expand Down
13 changes: 13 additions & 0 deletions pytwitter/rate_limit.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,11 @@ def get_limit(self, auth_type, method="GET"):
LIMIT_APP_GET=300,
LIMIT_USER_GET=900,
)
USERS_SEARCH = Endpoint(
resource="/users/search",
regex=re.compile(r"/users/search"),
LIMIT_USER_GET=900,
)
USER_FOLLOWING = Endpoint(
resource="/users/:id/following",
regex=re.compile(r"/users/\d+/following"),
Expand Down Expand Up @@ -371,6 +376,12 @@ def get_limit(self, auth_type, method="GET"):
LIMIT_APP_GET=50,
)

TRENDS = Endpoint(
resource="/trends/by/woeid/:woeid",
regex=re.compile(r"/trends/by/woeid/\d+"),
LIMIT_APP_GET=75,
)

MEDIA_UPLOAD = Endpoint(
resource="/media/upload.json",
regex=re.compile(r"/media/upload.json"),
Expand Down Expand Up @@ -399,6 +410,7 @@ def get_limit(self, auth_type, method="GET"):
USERS_BY_ID,
USER_BY_USERNAME,
USERS_BY_USERNAME,
USERS_SEARCH,
USER_FOLLOWING,
USER_REMOVE_FOLLOWING,
USER_FOLLOWER,
Expand Down Expand Up @@ -433,6 +445,7 @@ def get_limit(self, auth_type, method="GET"):
DM_MESSAGE_TO_CONVERSATION,
DM_CONVERSATIONS,
USAGE_TWEETS,
TRENDS,
MEDIA_UPLOAD,
]

Expand Down
1 change: 1 addition & 0 deletions testdata/apis/user/search_users_resp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"data":[{"location":"127.0.0.1","name":"Developers","description":"The voice of the X Dev team and your official source for updates, news, and events, related to the X API.","username":"XDevelopers","id":"2244994945"},{"location":"Seattle, WA","name":"Suhem Parack","description":"Partner Engineering @XDevelopers","username":"suhemparack","id":"857699969263964161"},{"location":"New York, NY","name":"Chris Park","description":"𝕏 | @X @API @XDevelopers","username":"chrisparkX","id":"2533341854"},{"location":"Islington, London","name":"Haim Vaturi","description":"@XDevelopers","username":"haimvat","id":"853388192"},{"location":"Canada","name":"ROBLOX Devs","description":"Follow this account for a lot of cool ROBLOXdev from all kinds of different ROBLOX developers! Not an official @ROBLOX twitter account","username":"RBXdevelopers","id":"829457852125306890"},{"location":"東京都港区","name":"Twitter Dev Japan","description":"This account is no longer active. Follow @XDevelopers for updates.","username":"TwitterDevJP","id":"70915829"},{"name":"Rains®™☔️🧠 0xdevelopers.eth.eth","description":"","username":"0xdevelopersTm","id":"1619352801104039936"},{"name":"Project X Developers","description":"","username":"ProXDevelopers","id":"708786906058756096"},{"location":"Los Angeles, CA","name":"XDevelopersUS","description":"","username":"XDevelopersUS","id":"1315227013028904960"},{"location":"Rio de Janeiro & São Paulo","name":"XDevelopers","description":"Contato e Suporte Via Telefone (RJ): 21 980534086 e Via Email: contato@XDevelopers.com.br","username":"XDevBrasil","id":"3296066705"},{"location":"India","name":"ajX developers","description":"app developernweb designernentrepreneurnmachine learningnAI PIONEERnage just 16","username":"ajXdevelopers","id":"1234855897370910720"},{"name":"The X Developers","description":"","username":"TheXDevelopers","id":"1453775246"},{"name":"RBLXdevelopers","description":"","username":"XdevelopersRbl","id":"1513675812486193158"},{"location":"London, England","name":"XDevelopersUK","description":"","username":"XDevelopersUK","id":"1375178694520627204"},{"name":"xDevelopers","description":"","username":"xdevelopers_st","id":"1363113804842881024"},{"name":"xdevelopers","description":"","username":"itdenps","id":"2885219741"},{"name":"X","description":"","username":"xdevelopers_es","id":"1684769811539087362"},{"name":"XDevelopers","description":"","username":"XDeveloper_","id":"732232220803485696"},{"name":"xDevelopers","description":"","username":"developers_x","id":"831241935675326464"},{"location":"United States","name":"0xspark","description":"","username":"0xdevelopers","id":"1580611661169238016"},{"name":"XeXDevelopers","description":"","username":"XeXDevelopers","id":"2175184873"},{"name":"Izu","description":"","username":"XDevelopersJP","id":"1684141917129539585"},{"name":"SXDevelopers","description":"","username":"SonyXDevelopers","id":"1521381726"}],"meta":{"next_token":"5qym3iwm0f05lqu1ezcdkohsl2i4lyq"}}
16 changes: 15 additions & 1 deletion tests/apis/test_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def test_get_me(api_with_user, helpers):

responses.add(
responses.GET,
url=f"https://api.twitter.com/2/users/me",
url="https://api.twitter.com/2/users/me",
json=me_data,
)

Expand All @@ -116,6 +116,20 @@ def test_get_me(api_with_user, helpers):
assert me_resp.data.id == "2244994945"


@responses.activate
def test_search_users(api_with_user, helpers):
responses.add(
responses.GET,
url="https://api.twitter.com/2/users/search",
json=helpers.load_json_data("testdata/apis/user/search_users_resp.json"),
)
search_resp = api_with_user.search_users(
query="developers",
user_fields="id,name,username,description,location",
)
assert search_resp.data[0].name == "Developers"


@responses.activate
def test_block_and_unblock_user(api_with_user):
user_id, target_user_id = "123456", "78910"
Expand Down

0 comments on commit 8f19b90

Please sign in to comment.