Skip to content

Commit 33be84f

Browse files
committed
Added totp_secret parameter to the login method for handling two-factor authentication
1 parent 0404e25 commit 33be84f

File tree

5 files changed

+31
-11
lines changed

5 files changed

+31
-11
lines changed

requirements.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
httpx
22
filetype
3-
beautifulsoup4
3+
beautifulsoup4
4+
pyotp

setup.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
install_requires=[
1515
'httpx',
1616
'filetype',
17-
'beautifulsoup4'
17+
'beautifulsoup4',
18+
'pyotp'
1819
],
19-
python_requires='>=3.10',
20+
python_requires='>=3.8',
2021
description='Twitter API wrapper for python with **no API key required**.',
2122
long_description=long_description,
2223
long_description_content_type='text/markdown',

twikit/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
A Python library for interacting with the Twitter API.
88
"""
99

10-
__version__ = '1.7.0'
10+
__version__ = '1.7.1'
1111

1212
from ._captcha import Capsolver
1313
from .bookmark import BookmarkFolder

twikit/client.py

+13-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import filetype
1111
import httpx
12+
import pyotp
1213
from httpx import Response
1314

1415
from .bookmark import BookmarkFolder
@@ -114,7 +115,7 @@ def request(
114115
if isinstance(response_data, dict) and 'errors' in response_data:
115116
error_code = response_data['errors'][0]['code']
116117
error_message = response_data['errors'][0].get('message')
117-
if error_code == 37:
118+
if error_code in (37, 64):
118119
# Account suspended
119120
raise AccountSuspended(error_message)
120121

@@ -298,7 +299,8 @@ def login(
298299
*,
299300
auth_info_1: str,
300301
auth_info_2: str | None = None,
301-
password: str
302+
password: str,
303+
totp_secret: str | None = None
302304
) -> dict:
303305
"""
304306
Logs into the account using the specified login information.
@@ -319,6 +321,9 @@ def login(
319321
It can be a username, email address, or phone number.
320322
password : :class:`str`
321323
The password associated with the account.
324+
totp_secret : :class:`str`
325+
The TOTP (Time-Based One-Time Password) secret key used for
326+
two-factor authentication (2FA).
322327
323328
Examples
324329
--------
@@ -385,12 +390,16 @@ def login(
385390
self._user_id = find_dict(flow.response, 'id_str')[0]
386391

387392
if flow.task_id == 'LoginTwoFactorAuthChallenge':
388-
print(find_dict(flow.response, 'secondary_text')[0]['text'])
393+
if totp_secret is None:
394+
print(find_dict(flow.response, 'secondary_text')[0]['text'])
395+
totp_code = input('>>>')
396+
else:
397+
totp_code = pyotp.TOTP(totp_secret).now()
389398

390399
flow.execute_task({
391400
'subtask_id': 'LoginTwoFactorAuthChallenge',
392401
'enter_text': {
393-
'text': input('>>> '),
402+
'text': totp_code,
394403
'link': 'next_link'
395404
}
396405
})

twikit/twikit_async/client.py

+12-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import filetype
1111
import httpx
12+
import pyotp
1213
from httpx import Response
1314

1415
from ..errors import (
@@ -116,7 +117,7 @@ async def request(
116117
if isinstance(response_data, dict) and 'errors' in response_data:
117118
error_code = response_data['errors'][0]['code']
118119
error_message = response_data['errors'][0].get('message')
119-
if error_code == 37:
120+
if error_code in (37, 64):
120121
# Account suspended
121122
raise AccountSuspended(error_message)
122123

@@ -314,6 +315,7 @@ async def login(
314315
auth_info_1: str,
315316
auth_info_2: str | None = None,
316317
password: str,
318+
totp_secret: str | None = None
317319
) -> dict:
318320
"""
319321
Logs into the account using the specified login information.
@@ -334,6 +336,9 @@ async def login(
334336
It can be a username, email address, or phone number.
335337
password : :class:`str`
336338
The password associated with the account.
339+
totp_secret : :class:`str`
340+
The TOTP (Time-Based One-Time Password) secret key used for
341+
two-factor authentication (2FA).
337342
338343
Examples
339344
--------
@@ -400,12 +405,16 @@ async def login(
400405
self._user_id = find_dict(flow.response, 'id_str')[0]
401406

402407
if flow.task_id == 'LoginTwoFactorAuthChallenge':
403-
print(find_dict(flow.response, 'secondary_text')[0]['text'])
408+
if totp_secret is None:
409+
print(find_dict(flow.response, 'secondary_text')[0]['text'])
410+
totp_code = input('>>>')
411+
else:
412+
totp_code = pyotp.TOTP(totp_secret).now()
404413

405414
await flow.execute_task({
406415
'subtask_id': 'LoginTwoFactorAuthChallenge',
407416
'enter_text': {
408-
'text': input('>>> '),
417+
'text': totp_code,
409418
'link': 'next_link'
410419
}
411420
})

0 commit comments

Comments
 (0)