add login method to account_pool; update readme

Этот коммит содержится в:
Vlad Pronsky 2023-04-30 00:12:57 +03:00
родитель 410a1fb9a4
Коммит 01d59b50d6
4 изменённых файлов: 59 добавлений и 13 удалений

Просмотреть файл

@ -4,21 +4,51 @@ Twitter GraphQL and Search API implementation with [SNScrape](https://github.com
```python
import asyncio
from twapi.client import UserClient
from twapi.pool import AccountsPool
from twapi.search import Search
from twapi.account import Account
from twapi.accounts_pool import AccountsPool
from twapi.api import API
from twapi.utils import gather
async def main():
acc1 = UserClient("user1", "pass1", "user1@example.com", "email_pass1")
acc2 = UserClient("user2", "pass2", "user2@example.com", "email_pass2")
acc1 = Account("user1", "pass1", "user1@example.com", "email_pass1")
acc2 = Account("user2", "pass2", "user2@example.com", "email_pass2")
pool = AccountsPool()
pool.add_account(acc1)
pool.add_account(acc2)
search = Search(pool)
async for rep in search.query("elon musk"):
print(rep.status_code, rep.json())
# login all accounts if required (not account file found)
# session file will be saved to `accounts/{username}.json`
await pool.login()
api = API(pool)
# search api
await gather(api.search("elon musk", limit=20)) # list[Tweet]
# graphql api
tweet_id = 20
user_id, user_login = 2244994945, "twitterdev"
await api.tweet_details(tweet_id) # Tweet
await gather(api.retweeters(tweet_id, limit=20)) # list[User]
await gather(api.favoriters(tweet_id, limit=20)) # list[User]
await api.user_by_id(user_id) # User
await api.user_by_login(user_login) # User
await gather(api.followers(user_id, limit=20)) # list[User]
await gather(api.following(user_id, limit=20)) # list[User]
await gather(api.user_tweets(user_id, limit=20)) # list[Tweet]
await gather(api.user_tweets_and_replies(user_id, limit=20)) # list[Tweet]
# note 1: limit is optional, default is -1 (no limit)
# note 2: all methods have `raw` version e.g.:
async for tweet in api.search("elon musk"):
print(tweet.id, tweet.user.username, tweet.rawContent) # tweet is `Tweet` object
async for rep in api.search_raw("elon musk"):
print(rep.status_code, rep.json()) # rep is `httpx.Response` object
if __name__ == "__main__":
asyncio.run(main())

Просмотреть файл

@ -2,7 +2,7 @@ import asyncio
from loguru import logger
from .account import Account
from .account import Account, Status
class AccountsPool:
@ -12,7 +12,16 @@ class AccountsPool:
def add_account(self, account: Account):
self.accounts.append(account)
def get_login_by_token(self, auth_token: str) -> str:
async def login(self):
for x in self.accounts:
try:
if x.status == Status.NEW:
await x.login()
except Exception as e:
logger.error(f"Error logging in to {x.username}: {e}")
pass
def get_username_by_token(self, auth_token: str) -> str:
for x in self.accounts:
if x.client.cookies.get("auth_token") == auth_token:
return x.username

Просмотреть файл

@ -10,7 +10,7 @@ from .models import Tweet, User
from .utils import encode_params, find_item, to_old_obj, to_search_like
class Search:
class API:
def __init__(self, pool: AccountsPool):
self.pool = pool
@ -21,7 +21,7 @@ class Search:
ll = rep.headers.get("x-rate-limit-limit", -1)
auth_token = rep.request.headers["cookie"].split("auth_token=")[1].split(";")[0]
username = self.pool.get_login_by_token(auth_token)
username = self.pool.get_username_by_token(auth_token)
return f"{username} {lr}/{ll}"

Просмотреть файл

@ -1,6 +1,6 @@
import json
from collections import defaultdict
from typing import Any, TypeVar
from typing import Any, AsyncGenerator, TypeVar
from httpx import HTTPStatusError, Response
from loguru import logger
@ -8,6 +8,13 @@ from loguru import logger
T = TypeVar("T")
async def gather(gen: AsyncGenerator[T, None]) -> list[T]:
items = []
async for x in gen:
items.append(x)
return items
def raise_for_status(rep: Response, label: str):
try:
rep.raise_for_status()