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 ```python
import asyncio import asyncio
from twapi.client import UserClient from twapi.account import Account
from twapi.pool import AccountsPool from twapi.accounts_pool import AccountsPool
from twapi.search import Search from twapi.api import API
from twapi.utils import gather
async def main(): async def main():
acc1 = UserClient("user1", "pass1", "user1@example.com", "email_pass1") acc1 = Account("user1", "pass1", "user1@example.com", "email_pass1")
acc2 = UserClient("user2", "pass2", "user2@example.com", "email_pass2") acc2 = Account("user2", "pass2", "user2@example.com", "email_pass2")
pool = AccountsPool() pool = AccountsPool()
pool.add_account(acc1) pool.add_account(acc1)
pool.add_account(acc2) pool.add_account(acc2)
search = Search(pool) # login all accounts if required (not account file found)
async for rep in search.query("elon musk"): # session file will be saved to `accounts/{username}.json`
print(rep.status_code, rep.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__": if __name__ == "__main__":
asyncio.run(main()) asyncio.run(main())

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

@ -2,7 +2,7 @@ import asyncio
from loguru import logger from loguru import logger
from .account import Account from .account import Account, Status
class AccountsPool: class AccountsPool:
@ -12,7 +12,16 @@ class AccountsPool:
def add_account(self, account: Account): def add_account(self, account: Account):
self.accounts.append(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: for x in self.accounts:
if x.client.cookies.get("auth_token") == auth_token: if x.client.cookies.get("auth_token") == auth_token:
return x.username 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 from .utils import encode_params, find_item, to_old_obj, to_search_like
class Search: class API:
def __init__(self, pool: AccountsPool): def __init__(self, pool: AccountsPool):
self.pool = pool self.pool = pool
@ -21,7 +21,7 @@ class Search:
ll = rep.headers.get("x-rate-limit-limit", -1) ll = rep.headers.get("x-rate-limit-limit", -1)
auth_token = rep.request.headers["cookie"].split("auth_token=")[1].split(";")[0] 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}" return f"{username} {lr}/{ll}"

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

@ -1,6 +1,6 @@
import json import json
from collections import defaultdict from collections import defaultdict
from typing import Any, TypeVar from typing import Any, AsyncGenerator, TypeVar
from httpx import HTTPStatusError, Response from httpx import HTTPStatusError, Response
from loguru import logger from loguru import logger
@ -8,6 +8,13 @@ from loguru import logger
T = TypeVar("T") 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): def raise_for_status(rep: Response, label: str):
try: try:
rep.raise_for_status() rep.raise_for_status()