HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Using tweet as command to shut down Ubuntu

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
tweetshutubuntudownusingcommand

Problem

I want to use Tweets sent out by a twitter account as a command to shut down Ubuntu. For this, I've written a Python script using tweepy, a Python library for Twitter. I scheduled the script to run half past the hour every hour (for eg at 5:30, 6:30, and so on) using crontab.

Here's the script:

import tweepy
import os
from datetime import datetime
p=None

api= tweepy.API()

for status in api.user_timeline('tweetneag4'):         
    while p==None:    #so that it checks only the first tweet
        if status.text.count(str((datetime.now().hour)+1))< 2 and str((datetime.time.now().hour)+1)==10:
            p=1
            pass
        elif str((datetime.now().hour)+1) in status.text:
            print "System shut down in 20 mins."
            os.system('shutdown -h +20')  
            p=1


Here is a sample tweet:

#loadshedding schedule in 10mins: 15:00-21:00 #group4 #nea


The twitter account (@tweetneag4) tweets an alert 30 mins and 10 mins before the power outage begins (here, the account tweets if and only if there's a power outage next hour). What I've tried to do is check at 5:30 whether it posts a tweet regarding 6 o'clock. I've done this by seeing if the tweet contains the string "6"(when checking at 5). When checking for ten o'clock, an additional complication arises because it may contain "10" in two scenarios- first as in 10 o'clock and second as in 10mins later. (I'm sure there's a better way of doing this)

If you see the twitter feed, things should be clearer. How could I improve so that the code become more elegant?

Solution

import tweepy
import os
from datetime import datetime
p=None


Use of single letter variable names is confusing, I have no idea what p is for.

api= tweepy.API()


Put spaces around your =

for status in api.user_timeline('tweetneag4'):         
    while p==None:    #so that it checks only the first tweet


What are you thinking here? If p doesn't get set to a true value, you'll loop over the next block repeatedly in an infinite loop. If you only want the first tweet pass count = 1 to user_timeline

if status.text.count(str((datetime.now().hour)+1))< 2 and str((datetime.time.now().hour)+1)==10:

            p=1


Setting flags is ugly. If you must set boolean flags use True and False not None and 1.

pass
        elif str((datetime.now().hour)+1) in status.text:
            print "System shut down in 20 mins."
            os.system('shutdown -h +20')  
            p=1


It seems to me that a much more straightforward way of doing this is to look at the time at which the status was posted. It seems to be available as status.created_at. Based on that you know that outage is either 30 or 10 minutes after that. So if it has been more then 30 minutes since that message, it must have already happened and we aren't concerned.

Something like this:

import tweepy
import os
from datetime import datetime, timedelta

api= tweepy.API()

status = api.user_timeline('tweetneag4', count=1)[0]
age = datetime.now() - status.created_at
if age < timedelta(minutes = 45):
    print "System shut down in 20 mins."
    os.system('shutdown -h +20')


NOTE: I get negative ages when I run this, I'm assuming that's time zones. Its also possible my logic is screwy.

If you really do need to get the actual time from the text, your current strategy of searching for numbers in the text is fragile. Instead you could do something like this:

# split the message up by whitespace, this makes it easy to grab the outage time
outage_time = status.split()[4]
# find everything up to the colon
hour_text, junk = outage_time.split(':')
# parse the actual hour
hour = int(hour_text)


Finally, for more complex examples using regular expressions to parse the text would be a good idea.

Code Snippets

import tweepy
import os
from datetime import datetime
p=None
api= tweepy.API()
for status in api.user_timeline('tweetneag4'):         
    while p==None:    #so that it checks only the first tweet
if status.text.count(str((datetime.now().hour)+1))< 2 and str((datetime.time.now().hour)+1)==10:

            p=1
pass
        elif str((datetime.now().hour)+1) in status.text:
            print "System shut down in 20 mins."
            os.system('shutdown -h +20')  
            p=1

Context

StackExchange Code Review Q#1525, answer score: 7

Revisions (0)

No revisions yet.