diff --git a/Dockerfile b/Dockerfile index e5af681..3994cd9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,4 +2,4 @@ FROM python:latest COPY . /etc/botyam WORKDIR /etc/botyam RUN pip install -r requirements.txt -CMD ["python3", "./main.py"] \ No newline at end of file +CMD ["python3", "./src/main.py"] \ No newline at end of file diff --git a/main.py b/main.py deleted file mode 100644 index c60949c..0000000 --- a/main.py +++ /dev/null @@ -1,114 +0,0 @@ -import tweepy -import os -import syslog -import random - -def init_api(): - # Syslog report - syslog.syslog(syslog.LOG_INFO, "Loading API...") - - # Secrets - consumer_key = os.getenv("CONSUMER_KEY") - consumer_secret = os.getenv("CONSUMER_SECRET") - access_token = os.getenv("ACCESS_TOKEN") - access_token_secret = os.getenv("ACCESS_TOKEN_SECRET") - bearer = os.getenv("BEARER") - - return tweepy.Client( - bearer_token=bearer, - consumer_key=consumer_key, - consumer_secret=consumer_secret, - access_token=access_token, - access_token_secret=access_token_secret) - -def init_streamobject(): - syslog.syslog(syslog.LOG_INFO, "Loading Stream object...") - bearer = os.getenv("BEARER") - return BotYamPoster(bearer) - -def post_reply(api, tweet, words, reply_text): - # Search for word in word bank - if any(word in tweet.data['text'] for word in words): - # Post reply - res = api.create_tweet( - text=reply_text, - in_reply_to_tweet_id=tweet["id"] - ) - response_data = f"RESPONDING: {res.data['text']}" - syslog.syslog(syslog.LOG_INFO, response_data) - -# Poster class -class BotYamPoster(tweepy.StreamingClient): - - # Define a callback function to handle tweets - def on_tweet(self, tweet): - # Make it easy on Yashar - if (tweet.data['author_id'] == "1533213104" and random.randint(0,3) != 0): - return - - # Don't use bot for own replies - if tweet.data['author_id'] == "1604848395805401092": - return - - api = init_api() - # Debug - tweet_data = f"NEW TWEET from @{api.get_user(id=tweet.data['author_id']).data['username']}: {tweet.data['text']}" - syslog.syslog(syslog.LOG_INFO, tweet_data) - - # Spare me if starts with RT - if tweet.data['text'][:2] == "RT": - syslog.syslog(syslog.LOG_INFO, "Skipping retweet...") - return - - # Words bank - bat_yam_words = ['בת ים', 'בת ימ', 'בת-ים', 'בת-ימ', 'https://t.co/PZqQaUVGAM'] - gebels_words = ['גבלס', 'נאצי', 'היטלר', 'קורונה', 'מסמכים', 'ההסמכה'] - police_words = ['שוטר', 'מלשין', 'מלשינ', 'נלשן', 'מלשנ', 'להלשין', 'משטרה', 'משטרות', 'סירנה', 'שיטור', 'בוגדים', 'בוגד', 'בגידה', '👮‍♀️', '🚨', '🚔', '🚓', '👮‍♂️', 'קטטה', 'מתקוטט', 'משטרע', 'מאפיה', 'טרור', 'סירנות', '1312', '13.12', '1 3 1 2', '13 12', '1 312', '131 2', '13-12', '1-312', '131-2', '1-3-1-2', '1 3 12', '1 3 12', '13 1 2', '1-3-12', '1-3-12', '13-1-2', 'acab', 'ac ab', 'ACAB', 'AC AB', 'אגאב', 'קצין', 'קצינ', 'קצונה', 'צהוב', 'כחול'] - misadot_words = ['העיקר מסעדות', 'מסעדה', 'מסעדות'] - smol_words = ['שמאל', '0מול', 'סמול'] - reply_words = ['@FromBotYam'] - - # Reply bank - reply_text_batyam = "https://twitter.com/FromBotYam/status/1611546128524185601/video/1" - reply_text_police = "https://twitter.com/FromBotYam/status/1611542331781529601/video/1" - reply_text_gebels = "https://twitter.com/FromBotYam/status/1611548817853227009/video/1" - reply_text_misadot = [reply_text_gebels, "https://twitter.com/FromBotYam/status/1612853363066175490/video/1", "https://twitter.com/FromBotYam/status/1616828733314170881/video/1"] - reply_text_smol = "https://twitter.com/FromBotYam/status/1613249771275182089/video/1" - reply_videons_reply = ["https://twitter.com/FromBotYam/status/1611495568148238336/video/1", "https://twitter.com/FromBotYam/status/1612852295980683264/video/1"] - reply_text_reply = f"מה עכשיו לערב אותי פה חבורה של קקות {reply_videons_reply[random.randint(0,1)]}" - - # Users bank - batyam_folks = ['134339937', '1533213104'] - - # Replies - post_reply(api, tweet, reply_words, reply_text_reply) - post_reply(api, tweet, gebels_words, reply_text_gebels) - post_reply(api, tweet, police_words, reply_text_police) - if any(botyam_og in tweet.data['author_id'] for botyam_og in batyam_folks): - post_reply(api, tweet, bat_yam_words, reply_text_batyam) - # Misadot (will be sectioned off later) - if tweet.data['text'] == misadot_words[0]: - post_reply(api, tweet, misadot_words[0], reply_text_misadot[-1]) - if not any(gebels_word in tweet.data['text'] for gebels_word in gebels_words): - post_reply(api, tweet, misadot_words, reply_text_misadot[random.randint(0,2)]) - else: - post_reply(api, tweet, misadot_words, reply_text_misadot[random.randint(1,2)]) - post_reply(api, tweet, smol_words, reply_text_smol) - - # Define a callback function to handle errors - def on_error(self, status_code): - # Print the error code - syslog.syslog(syslog.LOG_ERR, status_code) - -def main(): - syslog.syslog(syslog.LOG_INFO, "BOT-YAM - VERSION 2.1.2 >>>>") - stream = init_streamobject() - syslog.syslog(syslog.LOG_INFO, "Adding stream rules...") - stream.add_rules(tweepy.StreamRule("from:LucyBscalE OR from:aviv_yashar OR from:shaulig OR from:DvirAviam OR from:YoavFried1 OR from:StevenRaz5 OR from:nir_hau")) - stream.add_rules(tweepy.StreamRule("@FromBotYam")) - # Start listening for tweets - syslog.syslog(syslog.LOG_INFO, "Starting Twitter stream!") - stream.filter(expansions="author_id") - -if __name__ == "__main__": - main() diff --git a/requirements.txt b/requirements.txt index 3907e3b..38d05a9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,4 +7,8 @@ PyYAML==5.3.1 requests==2.28.1 requests-oauthlib==1.3.1 tweepy==4.12.1 -urllib3==1.26.13 \ No newline at end of file +urllib3==1.26.13 +jsonschema==3.2.0 +six==1.16.0 +crc16=0.1.1 +python-redis=0.3.0 \ No newline at end of file diff --git a/src/BotYamPoster.py b/src/BotYamPoster.py new file mode 100644 index 0000000..7e1b1f4 --- /dev/null +++ b/src/BotYamPoster.py @@ -0,0 +1,87 @@ +import tweepy +import os +import syslog +import random +import json +from main import Connector + +def init_streamobject(conn): + syslog.syslog(syslog.LOG_INFO, "Loading Stream object...") + return BotYamPoster(conn.get_bearer()) + +def post_reply(conn, victim_bank, tweet, words, reply_text_bank, postcounter): + # Search for word in word bank + if any(word in tweet.data['text'] for word in words): + reply_text = reply_text_bank[random.randint(0, (reply_text_bank.len()-1))] + # Post reply + if tweet.data['author_id'] in victim_bank.author_id: + reply_text = victim_bank.text[random.randint(0,2)] + "\n" + reply_text + res = conn.api.create_tweet( + text=reply_text, + in_reply_to_tweet_id=tweet["id"] + ) + response_data = f"RESPONDING: {res.data['text']}" + syslog.syslog(syslog.LOG_INFO, response_data) + return (postcounter + 1) + +class BotYamPoster(tweepy.StreamingClient): + + # Define a callback function to handle tweets + def on_tweet(self, tweet): + # Make it easy on Yashar + + postcounter = 0 + + if (not "@FromBotYam" in tweet.data['text'] and random.randint(0,3) != 0): + return + + # Don't use bot for own replies + if tweet.data['author_id'] == "1604848395805401092": + return + + conn = Connector() + reply_bank = json.loads(conn.dbconn.get_reply_bank()) + + # Debug + tweet_data = f"NEW TWEET from @{conn.api.get_user(id=tweet.data['author_id']).data['username']}: {tweet.data['text']}" + syslog.syslog(syslog.LOG_INFO, tweet_data) + + # Spare me if starts with RT + if tweet.data['text'][:2] == "RT": + syslog.syslog(syslog.LOG_INFO, "Skipping retweet...") + return + + # Run on all gags + for gag in reply_bank.gags: + postcounter = post_reply(conn, reply_bank.victims, tweet, gag.keywords, gag.reply, postcounter) + + # Special gags + if reply_bank.special_gags['haikar_misadot'].keywords[0] in tweet.data["text"]: + postcounter = post_reply( + conn, + reply_bank.victims, + tweet, + reply_bank.special_gags['haikar_misadot'].keywords, + reply_bank.special_gags['haikar_misadot'].reply, + postcounter) + elif not any(gebol in tweet.data['text'] for gebol in reply_bank.gags[1].keywords) and any(misada in tweet.data['text'] for misada in reply_bank.special_gags['misadot'].keywords): + postcounter = post_reply( + conn, + reply_bank.victims, + tweet, + reply_bank.special_gags['misadot'].keywords, + reply_bank.special_gags['misadot'].reply, + postcounter) + + if any(tilter in tweet.data['text'] for tilter in reply_bank.special_gags['tilt'].keywords) or (postcounter == 0 and "@FromBotYam" in tweet.data['text']): + postcounter = post_reply( + conn, + reply_bank.victims, + tweet, reply_bank.special_gags['tilt'].keywords, + reply_bank.special_gags['tilt'].reply, + postcounter) + + # Define a callback function to handle errors + def on_error(self, status_code): + # Print the error code + syslog.syslog(syslog.LOG_ERR, status_code) diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..02c7402 --- /dev/null +++ b/src/main.py @@ -0,0 +1,55 @@ +import tweepy +import os +import syslog +import json +import redis +from BotYamPoster import BotYamPoster +from BotYamPoster import init_streamobject + + +class Connector(): + def __init__(self): + syslog.syslog(syslog.LOG_INFO, "Loading Consul connector...") + # TODO: Add token + self.dbconn = redis.Redis( + host=os.getenv("REDIS_HOST"), + port=os.getenv("REDIS_PORT"), + password=os.getenv("REDIS_CREDENTIALS") + ) + + self.api = Connector.init_api(self.dbconn) + + def init_api(dbconn): + # Syslog report + syslog.syslog(syslog.LOG_INFO, "Loading Twitter API connector...") + + return tweepy.Client( + bearer_token=str(dbconn.hget("api", "bearer")), + consumer_key=str(dbconn.hget("api", "consumer_key")), + consumer_secret=str(dbconn.hget("api", "consumer_secret")) + access_token=str(dbconn.hget("api", "access_token")), + access_token_secret=str(dbconn.hget("api","access_token_secret")) + ) + + def get_reply_bank(self): + return json.loads(self.dbconn.get('reply_bank')) + + def get_victims(self): + return json.loads(self.dbconn.get('reply_bank')).victims + + def get_bearer(self): + return str(self.dbconn.hget("api", "bearer")) + +def main(): + syslog.syslog(syslog.LOG_INFO, "BOT-YAM - VERSION 2.1.2 >>>>") + conn = Connector() + stream = init_streamobject(conn) + syslog.syslog(syslog.LOG_INFO, "Adding stream rules...") + stream.add_rules(tweepy.StreamRule(conn.get_victims().stream_filter)) + stream.add_rules(tweepy.StreamRule("@FromBotYam")) + # Start listening for tweets + syslog.syslog(syslog.LOG_INFO, "Starting Twitter stream!") + stream.filter(expansions="author_id") + +if __name__ == "__main__": + main()