├── book.json ├── robot1.jpg ├── robot2.jpg ├── robot3.jpg ├── robot4.jpg ├── 001Bulbasaur_Dream.png ├── 13709493_786878941780_84756877_o.png ├── 13663654_786684231980_2095554349_o.png ├── 5e50e7cf-4eb9-4a65-9e18-cfa5d4ee0e7c.png ├── Screen Shot 2015-09-29 at 10.46.40 PM.png ├── Screen Shot 2015-09-29 at 11.28.35 PM.png ├── Screen Shot 2015-09-29 at 11.41.44 PM.png ├── Screen Shot 2015-09-30 at 12.01.48 AM.png ├── Screen Shot 2015-10-01 at 9.34.10 PM.png ├── Screen Shot 2015-10-06 at 11.43.56 PM.png ├── Screen Shot 2015-10-06 at 11.46.29 PM.png ├── Screen Shot 2015-10-06 at 11.49.58 PM.png ├── Screen Shot 2015-10-06 at 9.11.34 PM.png ├── Screen Shot 2015-10-06 at 9.20.10 PM.png ├── Screen Shot 2015-10-07 at 10.24.26 AM.png ├── Screen Shot 2015-10-07 at 10.30.53 AM.png ├── Screen Shot 2015-10-11 at 5.56.57 PM.png ├── Screen Shot 2015-10-11 at 6.10.56 PM.png ├── Screen Shot 2015-10-11 at 6.18.10 PM.png ├── Screen Shot 2015-10-11 at 6.28.31 PM.png ├── Screen Shot 2015-10-11 at 6.30.54 PM.png ├── Screen Shot 2016-07-12 at 10.58.03 PM.png ├── Screen Shot 2016-07-12 at 11.46.02 PM.png ├── Screen Shot 2016-07-13 at 12.12.43 AM.png ├── Screen Shot 2016-07-13 at 12.31.44 AM.png ├── Screen Shot 2016-07-13 at 9.09.59 PM.png ├── chapter1.md ├── assets ├── Screen Shot 2017-04-05 at 8.28.21 PM.png ├── Screen Shot 2017-04-16 at 9.50.18 PM.png └── Screen Shot 2017-04-16 at 9.56.16 PM.png ├── .gitignore ├── cheatsheet.md ├── test_your_bot.md ├── tell_people_about_your_bot.md ├── how_well_build_one.md ├── forking.md ├── SUMMARY.md ├── copy_to_pythonanywhere.md ├── find_a_book.md ├── acknowledgements.md ├── set_up_pythonanywhere.md ├── set_up_scheduling.md ├── README.md ├── using_an_api.md ├── set_up_github.md ├── what_is_a_twitter_bot.md ├── set_up_twitter.md ├── write_unit_tests.md └── personalize_your_bot.md /book.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /robot1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/robot1.jpg -------------------------------------------------------------------------------- /robot2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/robot2.jpg -------------------------------------------------------------------------------- /robot3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/robot3.jpg -------------------------------------------------------------------------------- /robot4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/robot4.jpg -------------------------------------------------------------------------------- /001Bulbasaur_Dream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/001Bulbasaur_Dream.png -------------------------------------------------------------------------------- /13709493_786878941780_84756877_o.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/13709493_786878941780_84756877_o.png -------------------------------------------------------------------------------- /13663654_786684231980_2095554349_o.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/13663654_786684231980_2095554349_o.png -------------------------------------------------------------------------------- /5e50e7cf-4eb9-4a65-9e18-cfa5d4ee0e7c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/5e50e7cf-4eb9-4a65-9e18-cfa5d4ee0e7c.png -------------------------------------------------------------------------------- /Screen Shot 2015-09-29 at 10.46.40 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2015-09-29 at 10.46.40 PM.png -------------------------------------------------------------------------------- /Screen Shot 2015-09-29 at 11.28.35 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2015-09-29 at 11.28.35 PM.png -------------------------------------------------------------------------------- /Screen Shot 2015-09-29 at 11.41.44 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2015-09-29 at 11.41.44 PM.png -------------------------------------------------------------------------------- /Screen Shot 2015-09-30 at 12.01.48 AM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2015-09-30 at 12.01.48 AM.png -------------------------------------------------------------------------------- /Screen Shot 2015-10-01 at 9.34.10 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2015-10-01 at 9.34.10 PM.png -------------------------------------------------------------------------------- /Screen Shot 2015-10-06 at 11.43.56 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2015-10-06 at 11.43.56 PM.png -------------------------------------------------------------------------------- /Screen Shot 2015-10-06 at 11.46.29 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2015-10-06 at 11.46.29 PM.png -------------------------------------------------------------------------------- /Screen Shot 2015-10-06 at 11.49.58 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2015-10-06 at 11.49.58 PM.png -------------------------------------------------------------------------------- /Screen Shot 2015-10-06 at 9.11.34 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2015-10-06 at 9.11.34 PM.png -------------------------------------------------------------------------------- /Screen Shot 2015-10-06 at 9.20.10 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2015-10-06 at 9.20.10 PM.png -------------------------------------------------------------------------------- /Screen Shot 2015-10-07 at 10.24.26 AM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2015-10-07 at 10.24.26 AM.png -------------------------------------------------------------------------------- /Screen Shot 2015-10-07 at 10.30.53 AM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2015-10-07 at 10.30.53 AM.png -------------------------------------------------------------------------------- /Screen Shot 2015-10-11 at 5.56.57 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2015-10-11 at 5.56.57 PM.png -------------------------------------------------------------------------------- /Screen Shot 2015-10-11 at 6.10.56 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2015-10-11 at 6.10.56 PM.png -------------------------------------------------------------------------------- /Screen Shot 2015-10-11 at 6.18.10 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2015-10-11 at 6.18.10 PM.png -------------------------------------------------------------------------------- /Screen Shot 2015-10-11 at 6.28.31 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2015-10-11 at 6.28.31 PM.png -------------------------------------------------------------------------------- /Screen Shot 2015-10-11 at 6.30.54 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2015-10-11 at 6.30.54 PM.png -------------------------------------------------------------------------------- /Screen Shot 2016-07-12 at 10.58.03 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2016-07-12 at 10.58.03 PM.png -------------------------------------------------------------------------------- /Screen Shot 2016-07-12 at 11.46.02 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2016-07-12 at 11.46.02 PM.png -------------------------------------------------------------------------------- /Screen Shot 2016-07-13 at 12.12.43 AM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2016-07-13 at 12.12.43 AM.png -------------------------------------------------------------------------------- /Screen Shot 2016-07-13 at 12.31.44 AM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2016-07-13 at 12.31.44 AM.png -------------------------------------------------------------------------------- /Screen Shot 2016-07-13 at 9.09.59 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/Screen Shot 2016-07-13 at 9.09.59 PM.png -------------------------------------------------------------------------------- /chapter1.md: -------------------------------------------------------------------------------- 1 | # First Chapter 2 | 3 | GitBook allows you to organize your book into chapters, each chapter is stored in a separate file like this one. 4 | -------------------------------------------------------------------------------- /assets/Screen Shot 2017-04-05 at 8.28.21 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/assets/Screen Shot 2017-04-05 at 8.28.21 PM.png -------------------------------------------------------------------------------- /assets/Screen Shot 2017-04-16 at 9.50.18 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/assets/Screen Shot 2017-04-16 at 9.50.18 PM.png -------------------------------------------------------------------------------- /assets/Screen Shot 2017-04-16 at 9.56.16 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spinecone/build-a-bot-workshop/HEAD/assets/Screen Shot 2017-04-16 at 9.56.16 PM.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Node rules: 2 | ## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 3 | .grunt 4 | 5 | ## Dependency directory 6 | ## Commenting this out is preferred by some people, see 7 | ## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git 8 | node_modules 9 | 10 | # Book build output 11 | _book 12 | 13 | # eBook build output 14 | *.epub 15 | *.mobi 16 | *.pdf -------------------------------------------------------------------------------- /cheatsheet.md: -------------------------------------------------------------------------------- 1 | # Cheatsheet 2 | 3 | 4 | ## bash console commands 5 | 6 | * show contents of current directory: 7 | ``ls`` 8 | * change directory: ``cd [directory name]`` 9 | * set permissions: ``chmod [permission flag] [filename]`` 10 | 11 | ## Git commands 12 | * show changes that have been made: ``git diff`` 13 | * show current branch and files that have been changed: ``git status`` 14 | * clone a repository: ``git clone [clone url]`` -------------------------------------------------------------------------------- /test_your_bot.md: -------------------------------------------------------------------------------- 1 | # Test your bot 2 | The bot should be all ready to go. Go to the PythonAnywhere bash console, cd into hello-world-bot, and run ``python3 bot.py`` to test it. If everything has been set up correctly, the command will run without errors, a tweet will be posted to the bot's account, and the text of the tweet will be removed from book.txt. 3 |





17 |
18 | Now all you have to do is pass the text you've created to Tweepy. You can read data from pretty much any API just using requests.get() and json()!
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/set_up_github.md:
--------------------------------------------------------------------------------
1 |
2 | # Set up a GitHub account
3 | 
4 | ![]() |
5 | ![]() |
![]() | ![]() |
6 | ![]() | ![]() |
3 | *
4 | Create an account for the bot at https://twitter.com/signup. (don't worry about picking a perfect username, it can be changed later).
5 | * Note: if you've created a Twitter account before, you won't be allowed to use the same phone number to sign up for a new account. You can sign up for a free phone number at https://www.google.com/voice that will forward to your existing number.
6 | * If you would like, this is a good time to go to your account settings and turn off mobile and email notifications.
7 | *
8 | Visit https://apps.twitter.com/app/new to create a new Twitter application for this account. This will give us credentials that will allow our bot to tweet on this account's behalf.
9 |
10 | Note: The information you enter here won't be used for our bot, but make sure the (arbitrary) website you enter begins with http://
11 | *
12 | Once you have created an application for your account, visit the Keys and Access Tokens section.
13 | * Create a new access token.
14 |
15 | We will now take the credentials we just received and put them in a secrets.py file.
16 |
17 | *
18 | Go back to our PythonAnywhere bash console.
19 | *
20 | Add a secrets.py file to the hello-world-bot directory. You can add the file using the "Files" tab the same way we added book.txt, or you can use a text editor like vim on the bash console. It should resemble this:
21 | ```py
22 | consumer_key = "I'M A CONSUMER KEY"
23 | consumer_secret = "I'M A CONSUMER SECRET"
24 | access_token = "I'M AN ACCESS TOKEN"
25 | access_token_secret = "I'M AN ACCESS TOKEN SECRET"
26 | ```
27 | **It's very important that you do not commit your secrets file to GitHub! If you do, anyone in the world can use this information to post tweets on your behalf.**
28 |
29 | ##What did we just do?
30 |
31 | Twitter needs to give your bot permission to post tweets via its API. Like many services, Twitter uses OAuth to grant that permission. Instead of just authenticating with your username and password, which could compromise your account if stolen, OAuth allows you to generate tokens that you can turn off or set to "read only."
32 |
33 | OAuth can be a little complicated to set up, but most of that process is taken care of us by Tweepy, the library we're using to communicate with Twitter. You can read more about OAuth here.
--------------------------------------------------------------------------------
/write_unit_tests.md:
--------------------------------------------------------------------------------
1 | # Write unit tests for your bot
2 |
3 | Sweet! Your bot is tweeting on a schedule, and you're on your way to Twitter bot superstardom! But what if you want to add some changes to your bot down the line? How can we verify that your changes won't break any of the current behavior?
4 |
5 | We can safely make changes and additions to our bot through the magic of ✨unit tests✨!
6 |
7 | Unit tests check that every small part of a program works the way a programmer expects it to. For example, if you were programming a vending machine, you might write a unit test that checks that the machine gives you chips if you put a dollar into the machine, and another test that it won't give you the chips if you only put in 50 cents.
8 |
9 | In general, every unit test consists of some setup and one or more assertions. Here's how that might look with the vending machine from earlier.
10 |
11 |
12 |
13 | The setup for both of these tests is that we initialize a VendingMachine object, and put some money into it. In the first test, we assert that "chips" is what we get back after inserting 1 money, essentially a dollar. The second test asserts is that "NOT ENOUGH!" is what the machine returns for .5 money. We would prefer to receive proper edible chips from a real machine, but for the purposes of unit testing, the string "chips" will be just fine.
14 |
15 | Once these tests are in place, we can update the vending machine to accept different amounts of money and return different kinds of items knowing that we won't break our dollar chips behavior without realizing it.
16 |
17 | There are 3 unit tests that are included in the hello-world-bot template. The tests check that:
18 | 1. The bot will tweet sentences that are less than 140 characters.
19 | * If a sentence is longer than 140 characters, the bot will tweet up to 140 characters of it.
20 | * After tweeting, the bot will remove the text it just tweeted from the book file.
21 |
22 | You can run the tests with ```python3 tests.py```. However, depending on the changes you made to personalize your bot, these tests probably aren't valid anymore. Let's go over how these basic tests work(ed), and you can change them to fit your bot.
23 |
24 |
25 | Since we don't want to affect the book we're actually tweeting from, we use a temporary file ("test_file") that we create and destroy in each test. For this test, the test_file just has two short sentences, in order to assert that get_next_chunk() will return the entire first sentence if it's short enough.
26 |
27 | This test uses mocking to run the bot with test_file instead of book.txt, which has some pretty complicated syntax. If you're interested in learning more about mocks, you can read more about it here: https://docs.python.org/3/library/unittest.mock.html
28 |
--------------------------------------------------------------------------------
/personalize_your_bot.md:
--------------------------------------------------------------------------------
1 | # Personalize your Bot
2 |
3 | There are tons of free, easily accessible data sources you can use to create interesting bots. Some of my favorites are:
4 |
5 | *
6 | **Wikimedia** provides free, public APIs for all of their services including Wikipedia and Wikihow. Uses simple GET requests with no authentication required. There is [documentation](https://www.mediawiki.org/wiki/API:Main_page) as well as a [Python wrapper](https://pypi.python.org/pypi/wikipedia/). Cool bots that use the Wikimedia API include [@wikisext](https://twitter.com/wikisext) and [@how2butt](https://twitter.com/how2butt).
7 | * **Tweepy**, the library we used to send tweets from our sample bot, can also be used to search and reply to tweets. Tweepy is very [well documented](http://tweepy.readthedocs.org/en/v3.2.0/).
8 | * **Google** has a lot of different free, public APIs that have basic authentication and usage limit requirements. The whole list of Google APIs is [here](https://developers.google.com/apis-explorer/#p/). [@earthroverbot](https://twitter.com/EarthRoverBot) and [@youareherebot](https://twitter.com/youareherebot/with_replies) use the [Google Maps](https://developers.google.com/maps/?hl=en) API.
9 | * **ITunes** has a [search API](https://www.apple.com/itunes/affiliates/resources/documentation/itunes-store-web-service-search-api.html) that provides information on music, movies, and other media for free and with no authentication.
10 | * **Pokeapi** has a [wealth of pokemon data](http://pokeapi.co/) free and with no authentication steps.
11 |
12 |
13 | Here's a [mostly complete list of Python API wrappers](https://github.com/realpython/list-of-python-api-wrappers).
14 |
15 | It's also possible to make a unique bot without many changes or additions to the template. [@everyportland](https://twitter.com/everyportland) is a bot that has very minor differences from the original template. It tweets from a list of English nouns instead of a book, plus a Portland-specific modifier (i.e. "Natural abacuses").
16 |
17 | ****
18 | You can check out the source code for these Python Twitter bots for ideas or examples:
19 |
20 |
21 | * [@taco_helper](https://github.com/tpinecone/taco_helper) creates fantastical Taco Bell menu items and suggests them to people who are selected based on their recent tweets.
22 | *
23 | [@angryrichpeople](https://github.com/tpinecone/angry_rich_people) posts 1 star reviews of $$$$ Yelp reviews
24 | *
25 | [@crystalliser](https://github.com/Autophagy/crystalliser-bot) takes an image and "crystallizes" it.
26 | * [@emoji_haiku](https://github.com/williln/emojihaiku) creates haikus out of emoji.
27 | * [@gutendelight](https://github.com/hugovk/gutendelight) makes rhyming couplets out of hip hop lyrics and classic literature.
28 | *
29 | [@kaikkisanat](https://github.com/hugovk/everyfinnishword) is tweeting every word in Finnish.
30 | * [@permitbot](https://github.com/chagan/permitbot) reports on building permits filed in Chicago.
31 |
32 | BotWiki maintains a [list of Twitter bots](https://botwiki.org/bots/twitterbots) which are not all open source or written in Python.
33 |
34 | Pick out a couple APIs that look interesting to you, even if you're not sure how you'll turn it into a bot. We'll go over how to use an API in the next chapter.
35 |
36 |
--------------------------------------------------------------------------------