1
votes

I wrote a bot that fetches posts from Reddit and posts them on a Twitter Account. But sometimes - i dont know why - it posts twice in a row, and not once every 3 hours. I am suspecting that it is because i did something like this:

do stuff:
    if stuff doesnt already exist:
        do other stuff
    else:
        do stuff

And i really think its bad practice, but i cant figure out how else i can let it run in an infinite loop, but still try to get a post that hasnt been posted before.

I have two points in my code where i "re-run" the entire code upon a check. One is when the post that is fetched from reddit is not an image, the other when the post that was fetched was already posted before (and stored in a json file for this exact check).

I hope someone understands what i mean, thanks in advance.

import time
import tweepy
import datetime
import praw
import urllib.request
import os
import json


def Mainbot():
    reddit = praw.Reddit(client_id='X',
                          client_secret='X',
                          user_agent='RedditFetchBot by FlyingThunder')

    def Tweet(postinfo):
        auth = tweepy.OAuthHandler("X", "X")
        auth.set_access_token("X", "X")
        api = tweepy.API(auth)
        try:
            api.update_with_media("local-filename.jpg", postinfo)
        except:
            print("not a file post")
            Mainbot()            #check 1


    post = reddit.subreddit('okbrudimongo').random()
    x = post.id

    with open('data.json', 'r') as e:
        eread = e.read()
        if x not in eread:
            with open('data.json', 'a') as f:
                json.dump(x, f)
                f.close()
                e.close()
        else:
            e.close()
            print("already posted")
            Mainbot()      #check 2

    print(post.url + " " + post.title)
    urllib.request.urlretrieve(post.url, "local-filename.jpg")
    Tweet(postinfo=post.title+" (https://www.reddit.com" + post.permalink+")")
    try:
        time.sleep(5)
        os.remove("local-filename.jpg")
    except:
        print("Datei nicht vorhanden")

def loop():
    time.sleep(1800)
    print("still running")
    print(datetime.datetime.now())

while True:
    Mainbot()
    loop()
    loop()
    loop()
    loop()
    loop()
    loop()

By the way, here is what it gives back - i made print checks to see what goes wrong, here you can see what it says when it posts twice

still running
2019-09-24 13:27:23.437152
still running
2019-09-24 13:57:23.437595
already posted
https://i.redd.it/xw38s1qrmlh31.jpg Führ Samstag bai ihm
https://i.redd.it/nnaxll9gjwf31.jpg Sorri Mamer
still running
2019-09-24 14:27:39.913651
still running
2019-09-24 14:57:39.913949
still running
2019-09-24 15:27:39.914013
2

2 Answers

1
votes

There's quite a bit to unpack here.

if x not in eread:
    ...
else:
    ...
    Mainbot()    # <--- this line

in the above snippet, you check if the post.id is already in your file. and if it is, you call the function Mainbot() again which means it has another chance to post a tweet.

However, this line

Tweet(postinfo=post.title+" (https://www.reddit.com" + post.permalink+")")

Occurs outside if your if-else check, which means it will post a tweet regardless of whether or not the post.id was in your file.

I also want to address your method of looping the bot. Your use of recursion is causing your double-posting issue and could technically recursively loop a post many tweets at once if multiple posts in a row end up in the "else" branch listed above.

Also, if you are using python with open(...) as f: you don't need to call python f.close()

Here is a solution I came up with that should solve your problem and doesn't use recursion:

import time
import tweepy
import datetime
import praw
import urllib.request
import os
import json

def initBot():
# this function logs into your reddit and twitter accounts
# and returns their instances

    reddit = praw.Reddit(client_id='XXXX',
                          client_secret='XXXX',
                          user_agent='RedditFetchBot by FlyingThunder')
    auth = tweepy.OAuthHandler("XXXX", "XXXX")
    auth.set_access_token("XXXX",
                          "XXXX")
    twitter = tweepy.API(auth)

    return reddit, twitter

def Tweet(post):
# this function simply tries to post a tweet
    postinfo = post.title + " (https://www.reddit.com" + post.permalink + ")"
    try:
        twitter.update_with_media("local-filename.jpg", postinfo)
    except:
        print("not a file post"+post.permalink)

def Mainbot():
    while True:
        with open('data.json', 'r+') as e:  # 'r+' let's you read and write to a file
            eread = e.read()

            # This section loops until it finds a reddit submission
            # that's not in your file
            post = reddit.subreddit('okbrudimongo').random()
            x = post.id
            while x in eread:
                post = reddit.subreddit('okbrudimongo').random()
                x = post.id

            # add the post.id to the file
            json.dump(x, e)
            print(post.url + " " + post.title)

            # Get and tweet image
            urllib.request.urlretrieve(post.url, "local-filename.jpg")
            Tweet(post)

            # Remove image file
            try:
                time.sleep(5)
                os.remove("local-filename.jpg")
            except:
                print("Datei nicht vorhanden")

        # sleep for a total of three hours, but report status every 30 minutes
        for i in range(6):
            time.sleep(1800)
            print("still running")
            print(datetime.datetime.now())

if __name__ == "__main__":

    reddit, twitter = initBot()
    Mainbot()

I haven't tested this because I don't have twitter keys.

0
votes

Solution i found (i still dont fully understand what mechanic caused the bug):

import time
import tweepy
import datetime
import praw
import urllib.request
import os
import json


def Mainbot():
    reddit = praw.Reddit(client_id='XXXX',
                          client_secret='XXXX',
                          user_agent='RedditFetchBot by FlyingThunder')

    def Tweet(postinfo):
        auth = tweepy.OAuthHandler("XXXX", "XXXX")
        auth.set_access_token("XXXX",
                              "XXXX")
        api = tweepy.API(auth)
        try:
            api.update_with_media("local-filename.jpg", postinfo)
        except:
            print("not a file post"+post.permalink)
            Mainbot()


    post = reddit.subreddit('okbrudimongo').random()
    x = post.id

    with open('data.json', 'r') as e:
        eread = e.read()
        if x not in eread:
            with open('data.json', 'a') as f:
                json.dump(x, f)
                f.close()
                e.close()
                print(post.url + " " + post.title)
                urllib.request.urlretrieve(post.url, "local-filename.jpg")
                Tweet(postinfo=post.title + " (https://www.reddit.com" + post.permalink + ")")
                try:
                    time.sleep(5)
                    os.remove("local-filename.jpg")
                except:
                    print("Datei nicht vorhanden")
        else:
            e.close()
            print("already posted")
            Mainbot()
def loop():
    time.sleep(1800)
    print("still running")
    print(datetime.datetime.now())

while True:
    Mainbot()
    loop()
    loop()
    loop()
    loop()
    loop()
    loop()