diff --git a/readme.md b/readme.md index 5931456..f888e89 100644 --- a/readme.md +++ b/readme.md @@ -19,6 +19,12 @@ from twitter.login import login usr, pwd = ..., ... session = login(usr, pwd) +# DM 1 user +dm('hello world', [123], session) + +# DM group of users +dm('foo bar', [123, 456, 789], session) + # create tweet with images, videos, gifs, and tagged users r = tweet('test 123', session, media=[{'file': 'image.jpeg', 'tagged_users': [123234345456], 'alt': 'some image'}]) r = tweet('test 123', session, media=['test.jpg', 'test.png']) diff --git a/setup.py b/setup.py index 7896f2e..f308551 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ import sys +from textwrap import dedent from setuptools import find_packages, setup -from textwrap import dedent install_requires = [ "ujson", @@ -14,7 +14,7 @@ if sys.platform != 'win32': setup( name="twitter-api-client", - version="0.2.0", + version="0.2.1", description="Twitter API", long_description=dedent(''' ## The Undocumented Twitter API diff --git a/twitter/config/operations.py b/twitter/config/operations.py index 2cf7ab2..dd785da 100644 --- a/twitter/config/operations.py +++ b/twitter/config/operations.py @@ -3170,9 +3170,7 @@ operations = { "tweet": None }, "requestId": None, - "target": { - "conversation_id": None - } + "target": None, }, } } diff --git a/twitter/config/settings.py b/twitter/config/settings.py index 0b30df5..6ed7884 100644 --- a/twitter/config/settings.py +++ b/twitter/config/settings.py @@ -15,7 +15,7 @@ content_settings = { 'include_ranked_timeline': True, 'include_alt_text_compose': True, 'display_sensitive_media': True, - 'protected': True, + 'protected': False, 'discoverable_by_email': False, 'discoverable_by_mobile_phone': False, 'allow_dms_from': 'following', ## {'all'} @@ -61,6 +61,6 @@ follow_settings = { } account_search_settings = { - "optInFiltering": False, - "optInBlocking": True, + "optInFiltering": True, # filter out nsfw content + "optInBlocking": True, # filter out blocked accounts } diff --git a/twitter/main.py b/twitter/main.py index 8806c96..0755163 100644 --- a/twitter/main.py +++ b/twitter/main.py @@ -22,12 +22,14 @@ from .utils import find_key try: if get_ipython().__class__.__name__ == 'ZMQInteractiveShell': import nest_asyncio + nest_asyncio.apply() except: ... if sys.platform != 'win32': import uvloop + asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) else: asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) @@ -303,6 +305,7 @@ def unretweet(tweet_id: int, session: Session) -> Response: return graphql_request(tweet_id, Operation.DeleteRetweet.name, 'source_tweet_id', session) +@log(level=logging.DEBUG, info=['json']) def get_tweets(user_id: int, session: Session) -> Response: operation = Operation.UserTweets.name qid = operations[operation]['queryId'] @@ -367,13 +370,10 @@ def unblock(user_id: int, session: Session) -> Response: @log(level=logging.DEBUG, info=['text']) -def update_search_settings(session: Session, **kwargs) -> Response: - if kwargs.get('incognito'): - kwargs.pop('incognito') - settings = account_search_settings.copy() - else: - settings = {} - settings |= kwargs +def update_search_settings(session: Session, hide_blocked=False, hide_nsfw=False) -> Response: + settings = account_search_settings.copy() + settings['optInFiltering'] = hide_nsfw + settings['optInBlocking'] = hide_blocked twid = int(session.cookies.get_dict()['twid'].split('=')[-1].strip('"')) headers = get_auth_headers(session=session) r = session.post( @@ -393,13 +393,8 @@ def update_content_settings(session: Session, **kwargs) -> Response: @param kwargs: settings to enable/disable @return: updated settings """ - if kwargs.get('incognito'): - kwargs.pop('incognito') - settings = content_settings.copy() - else: - settings = {} - settings |= kwargs - return api_request(settings, 'account/settings.json', session) + kwargs |= content_settings + return api_request(kwargs, 'account/settings.json', session) def build_query(params: dict) -> str: @@ -420,11 +415,17 @@ def stats(rest_id: int, session: Session) -> Response: @log(level=logging.DEBUG, info=['json']) -def dm(text: str, sender: int, receiver: int, session: Session, filename: str = '') -> Response: +def dm(text: str, receivers: list[int], session: Session, filename: str = '') -> Response: operation = Operation.useSendMessageMutation.name qid = operations[operation]['queryId'] params = operations[operation] - params['variables']['target']['conversation_id'] = '-'.join(map(str, sorted((sender, receiver)))) + + ## todo single DM request not needed, `participant_ids` field handles single DM request + # if len(receivers) == 1: + # params['variables']['target'] = {'conversation_id': '-'.join(map(str, sorted((sender, *receivers))))} + # else: + params['variables']['target'] = {"participant_ids": receivers} + params['variables']['requestId'] = str(uuid1(getnode())) # can be anything url = f"https://api.twitter.com/graphql/{qid}/{operation}" if filename: