зеркало из
https://github.com/viginum-datalab/twscrape.git
synced 2025-10-29 21:16:25 +02:00
feat: relogin accounts
Этот коммит содержится в:
родитель
c35dcb902c
Коммит
3b116155aa
18
readme.md
18
readme.md
@ -133,11 +133,11 @@ First add accounts from file:
|
||||
```sh
|
||||
# twscrape add_accounts <file_path> <line_format>
|
||||
# line_format should have "username", "password", "email", "email_password" tokens
|
||||
# tokens delimeter should be same as an file
|
||||
# note: tokens delimeter should be same as an file
|
||||
twscrape add_accounts accounts.txt username:password:email:email_password
|
||||
```
|
||||
|
||||
The call login:
|
||||
Then call login:
|
||||
|
||||
```sh
|
||||
twscrape login_accounts
|
||||
@ -157,6 +157,20 @@ twscrape accounts
|
||||
# user3 False False None 120 Login error
|
||||
```
|
||||
|
||||
### Re-login accounts
|
||||
|
||||
It is possible to re-login specific accounts:
|
||||
|
||||
```sh
|
||||
twscrape relogin user1 user2
|
||||
```
|
||||
|
||||
Or retry login for all failed logins:
|
||||
|
||||
```sh
|
||||
twscrape relogin_failed
|
||||
```
|
||||
|
||||
### Use different accounts file
|
||||
|
||||
Useful if using a different set of accounts for different actions
|
||||
|
||||
@ -129,6 +129,33 @@ class AccountsPool:
|
||||
logger.info(f"[{i}/{len(accounts)}] Logging in {x.username} - {x.email}")
|
||||
await self.login(x)
|
||||
|
||||
async def relogin(self, usernames: str | list[str]):
|
||||
usernames = usernames if isinstance(usernames, list) else [usernames]
|
||||
usernames = list(set(usernames))
|
||||
if not usernames:
|
||||
logger.warning("No usernames provided")
|
||||
return
|
||||
|
||||
qs = f"""
|
||||
UPDATE accounts SET
|
||||
active = false,
|
||||
locks = json_object(),
|
||||
last_used = NULL,
|
||||
error_msg = NULL,
|
||||
headers = json_object(),
|
||||
cookies = json_object(),
|
||||
user_agent = "{UserAgent().safari}"
|
||||
WHERE username IN ({','.join([f'"{x}"' for x in usernames])})
|
||||
"""
|
||||
|
||||
await execute(self._db_file, qs)
|
||||
await self.login_all()
|
||||
|
||||
async def relogin_failed(self):
|
||||
qs = "SELECT username FROM accounts WHERE active = false AND error_msg IS NOT NULL"
|
||||
rs = await fetchall(self._db_file, qs)
|
||||
await self.relogin([x["username"] for x in rs])
|
||||
|
||||
async def set_active(self, username: str, active: bool):
|
||||
qs = "UPDATE accounts SET active = :active WHERE username = :username"
|
||||
await execute(self._db_file, qs, {"username": username, "active": active})
|
||||
@ -244,6 +271,10 @@ class AccountsPool:
|
||||
old_time = datetime(1970, 1, 1).replace(tzinfo=timezone.utc)
|
||||
items = sorted(items, key=lambda x: x["username"].lower())
|
||||
items = sorted(items, key=lambda x: x["active"], reverse=True)
|
||||
items = sorted(items, key=lambda x: x["last_used"] or old_time, reverse=True)
|
||||
items = sorted(
|
||||
items,
|
||||
key=lambda x: x["last_used"] or old_time if x["total_req"] > 0 else old_time,
|
||||
reverse=True,
|
||||
)
|
||||
# items = sorted(items, key=lambda x: x["total_req"], reverse=True)
|
||||
return items
|
||||
|
||||
@ -69,6 +69,14 @@ async def main(args):
|
||||
await pool.login_all()
|
||||
return
|
||||
|
||||
if args.command == "relogin_failed":
|
||||
await pool.relogin_failed()
|
||||
return
|
||||
|
||||
if args.command == "relogin":
|
||||
await pool.relogin(args.usernames)
|
||||
return
|
||||
|
||||
fn = args.command + "_raw" if args.raw else args.command
|
||||
fn = getattr(api, fn, None)
|
||||
if fn is None:
|
||||
@ -130,6 +138,9 @@ def run():
|
||||
add_accounts.add_argument("file_path", help="File with accounts")
|
||||
add_accounts.add_argument("line_format", help="args of Pool.add_account splited by same delim")
|
||||
subparsers.add_parser("login_accounts", help="Login accounts")
|
||||
relogin = subparsers.add_parser("relogin", help="Re-login selected accounts")
|
||||
relogin.add_argument("usernames", nargs="+", default=[], help="Usernames to re-login")
|
||||
subparsers.add_parser("relogin_failed", help="Retry login for failed accounts")
|
||||
|
||||
c_lim("search", "Search for tweets", "query", "Search query")
|
||||
c_one("tweet_details", "Get tweet details", "tweet_id", "Tweet ID", int)
|
||||
|
||||
@ -154,7 +154,7 @@ async def next_login_task(client: AsyncClient, acc: Account, rep: Response):
|
||||
|
||||
prev = rep.json()
|
||||
assert "flow_token" in prev, f"flow_token not in {rep.text}"
|
||||
# logger.debug(f"login tasks: {[x['subtask_id'] for x in data['subtasks']]}")
|
||||
logger.debug(f"login tasks: {[x['subtask_id'] for x in prev['subtasks']]}")
|
||||
|
||||
for x in prev["subtasks"]:
|
||||
task_id = x["subtask_id"]
|
||||
|
||||
Загрузка…
x
Ссылка в новой задаче
Block a user