From 75d3d5f1aa3e6db9c067ef3c85415a3d2e3933d7 Mon Sep 17 00:00:00 2001 From: Hellow <74311245+HeIIow2@users.noreply.github.com> Date: Mon, 12 Feb 2024 22:17:48 +0100 Subject: [PATCH] feat: implemented twitter feed --- publish_meetups/__init__.py | 19 +++++-- publish_meetups/feeds/__init__.py | 12 +++-- publish_meetups/feeds/mastodon_feed.py | 7 ++- publish_meetups/feeds/twitter_feed.py | 68 ++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 11 deletions(-) create mode 100644 publish_meetups/feeds/twitter_feed.py diff --git a/publish_meetups/__init__.py b/publish_meetups/__init__.py index b4bbcff..0462fcc 100644 --- a/publish_meetups/__init__.py +++ b/publish_meetups/__init__.py @@ -6,11 +6,13 @@ import toml from .utils import Paths, PROGRAM_NAME from .feeds.mastodon_feed import MastodonFeed +from .feeds.twitter_feed import TwitterFeed NAME_TO_FEED = { "mastodon": MastodonFeed, + "twitter": TwitterFeed, } @@ -23,15 +25,17 @@ class PublishMeetups: self.config = { "active_feeds": [ "mastodon", + "twitter", ], "mastodon": {}, + "twitter": {}, } self.logger = logging.getLogger(__name__) def __enter__(self): if self.config_file.exists(): - with self.config_file.open("r") as f: + with self.config_file.open("r", encoding="utf-8") as f: self.config.update(toml.load(f)) return self @@ -53,15 +57,20 @@ class PublishMeetups: feed_config.update(feed_class.prompt_auth(feed_config)) self.config[feed] = feed_config - with self.config_file.open("w") as f: + with self.config_file.open("w", encoding="utf-8") as f: toml.dump(self.config, f) - with feed_class(**feed_config) as f: - f.run() + with feed_class(**feed_config, config=feed_config) as feed_instance: + self.config[feed].update(feed_instance.config) + + with self.config_file.open("w", encoding="utf-8") as f: + toml.dump(self.config, f) + + feed_instance.run() def __exit__(self, exc_type, exc_val, exc_tb): print("Exiting") - with self.config_file.open("w") as f: + with self.config_file.open("w", encoding="utf-8") as f: toml.dump(self.config, f) diff --git a/publish_meetups/feeds/__init__.py b/publish_meetups/feeds/__init__.py index b272755..a5c9c74 100644 --- a/publish_meetups/feeds/__init__.py +++ b/publish_meetups/feeds/__init__.py @@ -1,16 +1,20 @@ +import logging + + class Feed: @classmethod def prompt_auth(cls, existing_config: dict) -> dict: return existing_config - def __init__(self): - pass + def __init__(self, config: dict = None, **kwargs): + self.logger = logging.getLogger(self.__class__.__name__) + self.config = config or {} def __enter__(self): return self - def post(self, message: str): - pass + def post(self, message: str, **kwargs): + print(f"Posting {message}") def run(self): self.post("Hello, World!") diff --git a/publish_meetups/feeds/mastodon_feed.py b/publish_meetups/feeds/mastodon_feed.py index 42e386c..0ac044e 100644 --- a/publish_meetups/feeds/mastodon_feed.py +++ b/publish_meetups/feeds/mastodon_feed.py @@ -30,8 +30,11 @@ class MastodonFeed(Feed): access_token=access_token, ) - super().__init__() + super().__init__(**kwargs) def post(self, message: str): - print(f"Posting to Mastodon: {message}") + kwargs = locals().copy() + self.mastodon.toot(message) + + Feed.post(**kwargs) diff --git a/publish_meetups/feeds/twitter_feed.py b/publish_meetups/feeds/twitter_feed.py new file mode 100644 index 0000000..0189aea --- /dev/null +++ b/publish_meetups/feeds/twitter_feed.py @@ -0,0 +1,68 @@ +from pathlib import Path + +from twikit import Client +from twikit.errors import Forbidden, Unauthorized + +from . import Feed +from ..utils import Paths, PROGRAM_NAME, prompt + + +class TwitterFeed(Feed): + CLIENTCRED_PATH: Path = Paths.CONFIG_PATH.joinpath("mastodon_clientcred.secret") + + @classmethod + def prompt_auth(cls, existing_config: dict) -> dict: + """ + client.login( + auth_info_1=USERNAME , + auth_info_2=EMAIL, + password=PASSWORD + ) + """ + + return { + "auth_info_1": prompt.for_string("Username"), + "auth_info_2": prompt.for_string("Email"), + "password": prompt.for_password("Password"), + } + + # https://github.com/d60/twikit + def __init__(self, auth_info_1: str, auth_info_2: str, password: str, cookies: dict = None, **kwargs): + super().__init__(**kwargs) + + self.client = Client('en-US') + + logged_in = False + + cookies = cookies or {} + if cookies is not None: + self.client.http.client.cookies = cookies + try: + self.client.user_id() + logged_in = True + except (Forbidden, Unauthorized): + self.logger.warning("Cookies are expired.") + self.client.http.client.cookies.clear() + + if not logged_in: + self.logger.info("Logging in with username and email.") + self.client.login( + auth_info_1=auth_info_1, + auth_info_2=auth_info_2, + password=password, + ) + logged_in = True + + self.config['cookies'] = dict(self.client.http.client.cookies) + print(self.client.user_id()) + print(self.client._base_headers) + + + def post(self, message: str): + kwargs = locals().copy() + + self.client.create_tweet( + text=message, + ) + + Feed.post(**kwargs)