Skip to content

Commit

Permalink
loads of work
Browse files Browse the repository at this point in the history
  • Loading branch information
prehensile committed Mar 9, 2012
1 parent d2366a1 commit ad80ad7
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 73 deletions.
92 changes: 81 additions & 11 deletions brains.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,109 @@
import verbivorejr
import datetime
import config
import logging
import random
from google.appengine.api import taskqueue

# don't take any longer than this to process.
TIME_LIMIT = datetime.timedelta( minutes=9 )

def digest_user( api, vb, screen_name, deadline ):
def digest_user( api, worker, screen_name, deadline ):


user = twitter.get_user( screen_name )
statuses = api.user_timeline( screen_name=screen_name, since_id=user.last_id )
last_id = None
last_id = user.last_id
num_statuses = 20
if last_id is None:
# if we haven't seen this user before, get more statuses for better input
num_statuses = 100

statuses = api.user_timeline( count=num_statuses, screen_name=screen_name, since_id=last_id, include_rts=False )

statuses_digested = 0
for status in reversed(statuses): # reversed so we start at the oldest, in case we have to abort
last_id = status.id_str
vb.digest( status.text, deadline )
worker.digest( status.text, deadline )
statuses_digested = statuses_digested + 1
if datetime.datetime.now() >= deadline:
break

user.last_id = last_id
user.put()

return statuses_digested

def run():

then = datetime.datetime.now()
deadline = then + datetime.timedelta( minutes=5 )
logging.debug( "brains.run()" )

then = datetime.datetime.now()
settings = config.get_settings()
state = config.get_state()
lastrun = state.last_run

if lastrun is not None:
nextrun = lastrun + datetime.timedelta( hours=settings.tweet_frequency )
if nextrun > then:
logging.debug( "-> not due yet" )
return

deadline = then + TIME_LIMIT

learning_style = settings.learning_style
api = twitter.get_api()
vb = verbivorejr.VerbivoreWorker()

worker = verbivorejr.VerbivoreWorker()
statuses_digested = 0

if learning_style == constants.learning_style_oneuser:
# learn from one user
guru_name = settings.learning_guru
digest_user( api, vb, guru_name, deadline )
statuses_digested = digest_user( api, worker, guru_name, deadline )

logging.debug( "brains.run(): digested %d new statuses" % statuses_digested )

# store if we've learned anything new
if statuses_digested > 0:
worker.put( deadline )

# check deadline
if datetime.datetime.now() >= deadline:
logging.debug( "brains.run(): aborted after put()'ing worker, deadline is looming." )
taskqueue.add( url="/run" )
return

# only continue if chance is met
if settings.tweet_chance < random.random():
logging.debug( "brains.run(): didn't meet tweet_chance of %2.1f" % settings.tweet_chance )
return

queen = verbivorejr.VerbivoreQueen()
tweet = None

if settings.locquacity_onschedule:
logging.debug( "brains.run(): will tweet on schedule" )
tweet = queen.secrete( 130, deadline )
elif settings.locquacity_speakonnew and statuses_digested > 0 :
logging.debug( "brains.run(): locquacity_speakonnew, statuses_digested: %s" % statuses_digested )
tweet = queen.secrete( 130, deadline )


if tweet is not None:
try:
api.update_status( status=tweet )
except Exception as err:
logging.debug( "brains.run(): error from twitter api: %s" % err )

now = datetime.datetime.now()
elapsed = now - then
logging.debug( "brains.run(): completed in %d seconds" % elapsed.total_seconds() )

state.last_run = then
state.put()




deadline = then + TIME_LIMIT
vb.put( deadline )



Expand Down
22 changes: 17 additions & 5 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@
class MMSettings( db.Model ):
learning_style = db.StringProperty()
learning_guru = db.StringProperty()
locquacity = db.StringProperty()
tweet_frequency = db.FloatProperty()
frequency_unit = db.StringProperty()
locquacity_onschedule = db.BooleanProperty( required=True, default=False )
locquacity_reply = db.BooleanProperty( required=True, default=False )
locquacity_speakonnew = db.BooleanProperty( required=True, default=False )
tweet_frequency = db.FloatProperty( required=True, default=1.0 )
tweet_chance = db.FloatProperty( required=True, default=1.0 )

class MMState( db.Model ):
last_run = db.DateTimeProperty()

def get_settings():
settings = MMSettings.all()
Expand All @@ -14,5 +19,12 @@ def get_settings():
settings = MMSettings()
return settings

CONSUMER_KEY = "replace me"
CONSUMER_SECRET = "replace me"
def get_state():
state = MMState.all()
state = state.get()
if state is None:
settings = MMState()
return state

CONSUMER_KEY = "change me"
CONSUMER_SECRET = "change me too"
5 changes: 3 additions & 2 deletions constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
learning_style_list = "list"

key_locquacity = "locquacity"
locquacity_scheduled = "onschedule"
locquacity_replyonly = "replyonly"
locquacity_onschedule = "onschedule"
locquacity_replyonly = "replyonly"
locquacity_newonly = "newonly"
5 changes: 5 additions & 0 deletions cron.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
cron:

- description: daily session cleanup
url: /session_cleanup
schedule: every 24 hours

- description: run cycle
url: /run
schedule: every 15 minutes
26 changes: 17 additions & 9 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ def render_template( self, values=None, settings=None ):
template_values[ 'twitter_username' ] = creds.screen_name

template_values[ 'guru_name' ] = settings.learning_guru
template_values[ "tweet_frequency" ] = settings.tweet_frequency
template_values[ "tweet_chance" ] = settings.tweet_chance

if settings.learning_style == constants.learning_style_oneuser:
template_values[ 'learnfrom_oneuser_checked' ] = "checked"
elif settings.learning_style == constants.learning_style_followers:
Expand All @@ -118,10 +121,12 @@ def render_template( self, values=None, settings=None ):
elif settings.learning_style == constants.learning_style_list:
template_values[ 'learnfrom_list_checked' ] = "checked"

if( settings.locquacity == constants.locquacity_scheduled ):
if settings.locquacity_onschedule:
template_values[ 'locquacity_onschedule_checked' ] = "checked"
elif( settings.locquacity == constants.locquacity_replyonly ):
template_values[ 'locquacity_replyonly_checked' ] = "checked"
if settings.locquacity_reply:
template_values[ 'locquacity_reply_checked' ] = "checked"
if settings.locquacity_speakonnew:
template_values[ 'locquacity_speakonnew_checked' ] = "checked"

path = path_for_template( "settings.html" )
self.response.out.write( template.render( path, template_values ) )
Expand All @@ -136,12 +141,15 @@ def post(self):
settings = config.get_settings()
settings.learning_style = self.request.get( 'learnfrom' )
settings.learning_guru = self.request.get( 'guru_name' )
settings.locquacity = self.request.get( 'locquacity' )
try:
settings.tweet_frequency = float( self.request.get( 'frequency' ) )
except Exception:
pass
settings.frequency_unit = self.request.get( 'frequency_unit' )
settings.locquacity_onschedule = self.request.get( 'locquacity_onschedule' ) == "true"
settings.locquacity_reply = self.request.get( 'locquacity_reply' ) == "true"
settings.locquacity_speakonnew = self.request.get( 'locquacity_speakonnew' ) == "true"
tweet_frequency = self.request.get( 'tweet_frequency' )
if tweet_frequency is not None and len(tweet_frequency) > 0:
settings.tweet_frequency = float( tweet_frequency )
tweet_chance = self.request.get( 'tweet_chance' )
if tweet_chance is not None and len(tweet_chance) > 0:
settings.tweet_chance = float( tweet_chance )
self.render_template( { "saved" : True }, settings )
settings.put()

Expand Down
39 changes: 21 additions & 18 deletions templates/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@
{
element.style.display = visible ? "inline" : "none";
}
function onGuruRadioClicked(radio)
function onLearnRadioClicked(radio)
{
namebox = document.getElementById("guru_name");
setElementVisibility( namebox, radio.value == "oneuser" );
}

function onAlwaysTweetClicked(checkbox)
{
fieldset = document.getElementById("fieldset_speakonnew");
setElementVisibility( fieldset, !checkbox.checked );
}
</script>
</head>
<body>
Expand All @@ -34,29 +38,28 @@ <h1>Saved</h1>
</fieldset>
<fieldset id="fieldset_2">
<legend>Absorption rate</legend>
<input type="radio" name="learnfrom" value="oneuser" onclick="onGuruRadioClicked(this);" {{learnfrom_oneuser_checked}}/>
<input type="radio" name="learnfrom" value="oneuser" onclick="onLearnRadioClicked(this);" {{learnfrom_oneuser_checked}}/>
Learn from one user
<input id="guru_name" {% if not learnfrom_oneuser_checked %} style="display:none"{% endif %} type="text" name="guru_name" maxlength="20" value="{{guru_name}}"/>
<input type="radio" name="learnfrom" value="followers" onclick="onGuruRadioClicked(this);" {{learnfrom_followers_checked}}/>
Learn from my followers
<input type="radio" name="learnfrom" value="followed" onclick="onGuruRadioClicked(this);" {{learnfrom_followed_checked}}/>
Learn from everyone I follow
<input type="radio" name="learnfrom" value="list" onclick="onGuruRadioClicked(this);" {{learnfrom_list_checked}}/>
<input type="radio" name="learnfrom" value="list" onclick="onLearnRadioClicked(this);" {{learnfrom_list_checked}}/>
Learn from a list
<input type="radio" name="learnfrom" value="followed" onclick="onLearnRadioClicked(this);" {{learnfrom_followed_checked}}/>
Learn from everyone I follow
<input type="radio" name="learnfrom" value="followers" onclick="onLearnRadioClicked(this);" {{learnfrom_followers_checked}}/>
Learn from my followers
</fieldset>
<fieldset id="fieldset_2">
<legend>Locquacity</legend>
<input type="radio" name="locquacity" value="onschedule" {{locquacity_onschedule_checked}}/>
Tweet on schedule
<fieldset id="schedule_settings" style="display:none">
<input type="text" name="frequency" size="2" value="{{tweet_frequency}}"/>
<select name="frequency_unit">
<option value="hrs" {{frequency_hrs_selected}}>hours</option>
<option value="mins" {{frequency_mins_selected}}>minutes</option>
</select>
Wake up every <input type="text" name="tweet_frequency" size="5" value="{{tweet_frequency}}"/> hours with a <input type="text" name="tweet_chance" size="3" value="{{tweet_chance}}" /> chance of tweeting
<br/>
<input onclick="onAlwaysTweetClicked(this);" type="checkbox" name="locquacity_onschedule" value="true" {{locquacity_onschedule_checked}}/>
Always tweet
<fieldset id="fieldset_speakonnew" {% if locquacity_onschedule_checked %} style="display:none"{% else %} style="display:inline" {% endif %} >
<input type="checkbox" name="locquacity_speakonnew" value="true" {{locquacity_speakonnew_checked}}/>
Speak when I've learned something new
</fieldset>
<input type="radio" name="locquacity" value="replyonly" {{locquacity_replyonly_checked}}/>
Speak only when spoken to
<input type="checkbox" name="locquacity_reply" value="true" {{locquacity_reply_checked}}/>
Reply to @mentions and direct messages
</fieldset>
<input type="submit" value="Save" />
</form>
Expand Down
1 change: 0 additions & 1 deletion twitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ def put_twitter_creds( key, secret, screen_name ):

def get_user( screen_name ):
user = MMTwitterUser.all()
user.filter( 'screen_name = ', screen_name )
user = user.get()
if user is None:
user = MMTwitterUser( screen_name=screen_name )
Expand Down
Loading

0 comments on commit ad80ad7

Please sign in to comment.