2
\$\begingroup\$

I wrote a script that will eventually go onto a Raspberry Pi. It takes a picture then uploads it to Twitter every 15 minutes from 5:30-9:00pm.

It works fine as is, but I feel I need to organize this as a class. I was wondering if someone could point me in the right direction on how to take my functions and make it into a class.

Just to be clear, I have basic knowledge on how classes work. I'm just confused about how I could get all of my functions to work within a class.

#Take care of imports
import pyimgur
import json
import requests
from requests_oauthlib import OAuth1
from twython import Twython
from apscheduler.scheduler import Scheduler
import logging
logging.basicConfig()

#Imgur credentials
CLIENT_ID = "----"

#Twitter credentials
consumer_key = '----'
consumer_secret = '----'
access_token = '-----'
access_token_secret = '----'
user_id = "----"


################################
##### FUNCTIONS ################
################################


#Optional: Upload an image to imgur and grab the link to tweet it. Bypassing twitpic
def upload_to_imgur():      
    #path to image
    path = "/pathtopicture" 

    #upload to imgur
    im = pyimgur.Imgur(CLIENT_ID)
    uploaded_image = im.upload_image(PATH, title="Uploaded with PyImgur")

    #print various test things
    #print(uploaded_image.title)
    #print(uploaded_image.datetime)
    #print(uploaded_image.link)
    imgur_link = uploaded_image.link


#Upload a tweet or a media tweet to twitter
def upload_to_twitter():    
    # #upload simple tweet
    twitter = Twython(consumer_key, consumer_secret, access_token, access_token_secret)
    twitter.update_status(status="tweet text goes here")
    #
    # OR upload a media tweet
    #
    # photo = open('/pathtopicture', 'rb')
    # twitter.update_status_with_media(status='tweetText', media=photo)
    #
    # OR upload to imgur then tweet link
    #
    # upload_to_imgur()
    # twitter.update_status(status=imgur_link)
    #

#Destroy a tweet from twitter
def destroy_tweet():    
    #URL for the destroy request
    destroy_url = 'https://api.twitter.com/1.1/statuses/user_timeline.json?user_id=---&count=1'

    #authentication
    auth = OAuth1(consumer_key, consumer_secret, access_token, access_token_secret)

    #Request twitter for JSON response
    r =requests.get(destroy_url, auth=auth)

    #Grab most recent tweet ID from JSON response
    tweet_id=r.json()[0]['id_str']

    #Set what twitter means
    twitter = Twython(consumer_key, consumer_secret, access_token, access_token_secret)

    #Destroy the latest tweet
    twitter.destroy_status(id=tweet_id)


#Every 15 minutes from 5:30-9:00pm tweet a picture and upload to twitter.
def start_scheduler():
    #initialize
    sched = Scheduler()

    #All fo the schedulers
    #Scheduler at 5:30
    @sched.cron_schedule(day_of_week='mon-sat', hour=17, minute=30)
    def scheduled_job():
        destroy_tweet()
        upload_to_twitter()

    #Scheduler at 5:45
    @sched.cron_schedule(day_of_week='mon-sat', hour=17, minute=45)
    def scheduled_job():
        destroy_tweet()
        upload_to_twitter()

    #Scheduler at 6:00
    @sched.cron_schedule(day_of_week='mon-sat', hour=18)
    def scheduled_job():
        destroy_tweet()
        upload_to_twitter()

    #Scheduler at 6:15
    @sched.cron_schedule(day_of_week='mon-sat', hour=18, minute=15)
    def scheduled_job():
        destroy_tweet()
        upload_to_twitter()

    #Scheduler at 6:30
    @sched.cron_schedule(day_of_week='mon-sat', hour=18, minute=30)
    def scheduled_job():
        destroy_tweet()
        upload_to_twitter()

    #Scheduler at 6:45
    @sched.cron_schedule(day_of_week='mon-sat', hour=18, minute=45)
    def scheduled_job():
        destroy_tweet()
        upload_to_twitter()

    #Scheduler at 7:00
    @sched.cron_schedule(day_of_week='mon-sat', hour=19)
    def scheduled_job():
        destroy_tweet()
        upload_to_twitter()

    #Scheduler at 7:15
    @sched.cron_schedule(day_of_week='mon-sat', hour=19, minute=15)
    def scheduled_job():
        destroy_tweet()
        upload_to_twitter()

    #Scheduler at 7:30
    @sched.cron_schedule(day_of_week='mon-sat', hour=19, minute=30)
    def scheduled_job():
        destroy_tweet()
        upload_to_twitter()

    #Scheduler at 7:45
    @sched.cron_schedule(day_of_week='mon-sat', hour=19, minute=45)
    def scheduled_job():
        destroy_tweet()
        upload_to_twitter()

    #Scheduler at 8:00
    @sched.cron_schedule(day_of_week='mon-sat', hour=20)
    def scheduled_job():
        destroy_tweet()
        upload_to_twitter()

    #Scheduler at 8:15
    @sched.cron_schedule(day_of_week='mon-sat', hour=20, minute=15)
    def scheduled_job():
        destroy_tweet()
        upload_to_twitter()

    #Scheduler at 8:30
    @sched.cron_schedule(day_of_week='mon-sat', hour=20, minute=30)
    def scheduled_job():
        destroy_tweet()
        upload_to_twitter()

    #Scheduler at 8:45
    @sched.cron_schedule(day_of_week='mon-sat', hour=20, minute=45)
    def scheduled_job():
        destroy_tweet()
        upload_to_twitter()

    #Scheduler at 9:00
    @sched.cron_schedule(day_of_week='mon-sat', hour=21)
    def scheduled_job():
        destroy_tweet()
        upload_to_twitter()


    #start scheduler
    sched.start()
    #loop
    while True:
        pass


#Start the script
start_scheduler()
\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

Repeating the scheduled jobs is not necessary. A sufficiently complex cron-style expression should do:

@sched.cron_schedule(hour='17-20', minute='0-45/15')
def scheduled_job():
    destroy_tweet()
    upload_to_twitter()

The downside of this is that it, unlike your original code, will not be triggered at 9:00.

Even if that's not acceptable, your original code need not repeat itself so much. After defining scheduled_job without the sched.cron_schedule decorator, you can still schedule that as a job within a for loop, which would be much cleaner, e.g.:

for hour in range(17, 21):
    for minute in [0, 15, 30, 45]:
        sched.add_cron_job(scheduled_job, hour=hour, minute=minute)

This would also allow for adding the special 9:00 case.

\$\endgroup\$
1
\$\begingroup\$

I think that defining a function inside of a function definition body is bad practice. For example you can have a class called Scheduler and define each function inside that class.

I will leave the rest for the more expirienced people.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.