Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam Parrish committed Nov 15, 2012
0 parents commit 11f5c15
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 0 deletions.
19 changes: 19 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Copyright (c) 2012 Adam Parrish

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
73 changes: 73 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
Everyword Bot
-------------

This is a small Python script that implements an [`@everyword`](http://twitter.com/everyword)-like Twitter bot. Here's what you'll need to run it:

* Python 2.6+
* [tweepy](http://tweepy.github.com/)
* a plain text file, with each of your desired tweets on one line

Instructions
------------

Run the script from the command-line like so:

$ python everywordbot.py --consumer_key=<ckey> --consumer_secret=<csecret> \
--access_token=<atoken> --token_secret=<tokensecret> \
--source_file=<source> --index_file=<index>

... where:

* `<ckey>` is your Twitter consumer key;
* `<csecret>` is your Twitter consumer secret;
* `<atoken>` is a valid Twitter access token;
* `<tokensecret>` is the access token secret for the token given above;
* `<source>` is the filename of a plain text file, with one tweet per line (defaults to `tweet_list.txt` in the current directory); and
* `<index>` is the name of a file where the script can store the current tweet index (i.e., which line in the file should be tweeted next). The script must be able to write to this file.

You'll need to arrange to have this script run at some interval, using a tool
like `cron`. For example, to post a tweet every half hour, you might put the
command line above in a bash script named `/home/aparrish/post_tweet.sh` and
then put the following in your crontab:

0,30 * * * * cd /home/aparrish; bash post_tweet.sh >>error.log 2>&1

Production Notes
----------------

Twitter may return one of a variety of error messages in response to an attempt to post
a status update (invalid authorization credentials, rate limits, fail whales,
etc.). This script does not attempt to catch or differentiate between these
errors; however, it will *only* increment the index if the post succeeds. (The idea is
that 100% coverage of the source file is more important than 100% uptime.)

As stated in the license, this software is provided under no warranty of any kind. However, if the operation of this script is critical to your business, grant application,
art school thesis, or innovative government program, you may want to monitor the results of the script by (e.g.) checking
the return value of the script and sending an e-mail message if it's non-zero.
Feel free to update the script to handle errors in whatever
method is appropriate for your specific application.

Obtaining Twitter authorization credentials
-------------------------------------------

The easiest way to obtain the appropriate credentials is as follows:

* Create a new Twitter account. This is the account on whose behalf the script will post tweets.
* Go to the [Twitter Developers Site](https://dev.twitter.com/) and sign in with the account you just created. (You'll need to verify your account's e-mail address before Twitter will let you log in with your new account.)
* After signing in, select "My Applications" from the drop-down in the upper-right corner of the page.
* Select "Create a new application."
* Fill in the form. The "Callback URL" field is not important.
* You'll be taken to the overview page for your new application. Activate the "Settings" tab and change the "Application Type" from "Read only" to "Read and Write."
* Return to the "Details" tab. Select "Create my access token" at the bottom of the page.
* Congratulations! All the information that you need (consumer key, consumer secret, access token, access token secret) is now displayed on the "Details" tab.

In my experience, Twitter may prevent newly created accounts from posting status updates, responding to such requests with invalid authorization errors. This is likely an anti-spam measure. Wait a few minutes and try again before freaking out.

(The above information above may become inaccurate if Twitter changes the
layout of the "My Applications" site.)

License
-------

Everyword Bot is provided under the MIT license. See `LICENSE.TXT` for more information.

65 changes: 65 additions & 0 deletions everywordbot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import tweepy
import sys
import os

class EverywordBot(object):

def __init__(self, consumer_key, consumer_secret, access_token, token_secret,
source_file_name, index_file_name):
self.source_file_name = source_file_name
self.index_file_name = index_file_name

auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, token_secret)
self.twitter = tweepy.API(auth)

def _get_current_index(self):
if not(os.path.isfile(self.index_file_name)):
return 0
with open(self.index_file_name) as index_fh:
return int(index_fh.read().strip())

def _increment_index(self, index):
with open(self.index_file_name, "w") as index_fh:
index_fh.truncate()
index_fh.write("%d" % (index + 1))
index_fh.close()

def _get_current_line(self, index):
with open(self.source_file_name) as source_fh:
# read up until the desired line
for i in range(index+1):
status_str = source_fh.readline().strip()
return status_str

def post(self):
index = self._get_current_index()
status_str = self._get_current_line(index)
self.twitter.update_status(status_str)
self._increment_index(index)

if __name__ == '__main__':
from optparse import OptionParser
parser = OptionParser()
parser.add_option('--consumer_key', dest='consumer_key',
help="twitter consumer key")
parser.add_option('--consumer_secret', dest='consumer_secret',
help="twitter consumer secret")
parser.add_option('--access_token', dest='access_token',
help="twitter token key")
parser.add_option('--token_secret', dest='token_secret',
help="twitter token secret")
parser.add_option('--source_file', dest='source_file',
default="tweet_list.txt",
help="source file (one line per tweet)")
parser.add_option('--index_file', dest='index_file',
default="index",
help="index file (must be able to write to this file)")
(options, args) = parser.parse_args()

bot = EverywordBot(options.consumer_key, options.consumer_secret,
options.access_token, options.token_secret, options.source_file,
options.index_file)

bot.post()

0 comments on commit 11f5c15

Please sign in to comment.