thatmattbone / twitiwt
A twitter bot for detecting palindromes.
Clone this repository (size: 16.8 KB): HTTPS / SSH
$ hg clone http://bitbucket.org/thatmattbone/twitiwt/
| commit 0: | 07898c3c08dc |
| branch: | default |
initial import of what I have
Changed (Δ7.3 KB):
raw changeset »
.hgignore (6 lines added, 0 lines removed)
README (11 lines added, 0 lines removed)
palindrome.py (41 lines added, 0 lines removed)
sax.py (78 lines added, 0 lines removed)
streaming.py (60 lines added, 0 lines removed)
tests.py (69 lines added, 0 lines removed)
1 |
This is my early attempt to create a twitter bot |
|
2 |
for detecting palindromes. Right now it's just my |
|
3 |
vehicle for playing around with event-oriented programming |
|
4 |
in Python. Please don't use it for some stupid fucking |
|
5 |
social media nonsense your boss cooked up. |
|
6 |
||
7 |
To run things you'll need a twitter account. |
|
8 |
Create a passwords.py file with two globals, for example: |
|
9 |
||
10 |
TWITTER_USERNAME = 'SARAHPalinUSA' |
|
11 |
TWITTER_PASSWORD = 'din0saurZrFake' |
Up to file-list palindrome.py:
1 |
import re |
|
2 |
||
3 |
STOP_LEN = 4 |
|
4 |
STOP_SET_SIZE = 3 |
|
5 |
PUNCTUATION_REGEX = re.compile('^[a-z]+$') |
|
6 |
STOP_WORDS = ['somos', 'esse', 'yehey', |
|
7 |
'kodok', 'neuen', 'malam', |
|
8 |
'nuhun'] |
|
9 |
||
10 |
def palindrome(word): |
|
11 |
if(len(word) < STOP_LEN): |
|
12 |
return False |
|
13 |
||
14 |
word = word.lower() |
|
15 |
||
16 |
||
17 |
if(word in STOP_WORDS): |
|
18 |
return False |
|
19 |
||
20 |
if(not PUNCTUATION_REGEX.match(word)): |
|
21 |
return False |
|
22 |
||
23 |
##I know how to spell 'forwards' but I think this is punny: |
|
24 |
forwords = list(word) |
|
25 |
forwords_set = set(forwords) |
|
26 |
if(len(forwords_set) < STOP_SET_SIZE): |
|
27 |
return False |
|
28 |
||
29 |
backwords = list(forwords) |
|
30 |
backwords.reverse() |
|
31 |
||
32 |
if(forwords == backwords): |
|
33 |
return word |
|
34 |
else: |
|
35 |
return False |
|
36 |
||
37 |
||
38 |
def palindrome_list(sentence): |
|
39 |
words = [word.strip() for word in sentence.split()] |
|
40 |
palindrome_list = [palindrome(word) for word in words] |
|
41 |
return [w for w in palindrome_list if w!=False] |
1 |
from xml.sax.handler import ContentHandler |
|
2 |
from xml.sax import parse |
|
3 |
||
4 |
from palindrome import palindrome_list |
|
5 |
||
6 |
from collections import defaultdict |
|
7 |
||
8 |
class TweetHandler(ContentHandler): |
|
9 |
||
10 |
screen_name = None |
|
11 |
record_screen_name = False |
|
12 |
||
13 |
tweet = None |
|
14 |
record_tweet = False |
|
15 |
||
16 |
def startElement(self, name, attrs): |
|
17 |
print(name) |
|
18 |
if(name == 'screen_name'): |
|
19 |
self.record_screen_name = True |
|
20 |
self.screen_name = '' |
|
21 |
elif(name == 'text'): |
|
22 |
self.record_tweet = True |
|
23 |
self.tweet = '' |
|
24 |
||
25 |
||
26 |
def characters(self, data): |
|
27 |
if(self.record_screen_name): |
|
28 |
self.screen_name += data |
|
29 |
elif(self.record_tweet): |
|
30 |
self.tweet += data |
|
31 |
||
32 |
def endElement(self, name): |
|
33 |
if(name == 'screen_name'): |
|
34 |
#emit tweet and restart |
|
35 |
self.tweeted(self.screen_name, self.tweet) |
|
36 |
||
37 |
self.reset() |
|
38 |
||
39 |
elif(name == 'text'): |
|
40 |
self.record_tweet = False |
|
41 |
||
42 |
def reset(self): |
|
43 |
self.screen_name = None |
|
44 |
self.record_screen_name = False |
|
45 |
||
46 |
self.tweet = None |
|
47 |
self.record_tweet = False |
|
48 |
||
49 |
||
50 |
||
51 |
if __name__ == '__main__': |
|
52 |
import random |
|
53 |
import time |
|
54 |
from xml.sax._exceptions import SAXParseException |
|
55 |
||
56 |
handle = open_streaming_handle() |
|
57 |
#for i in range(1, 2): |
|
58 |
#handle = open('public_timeline.xml') |
|
59 |
||
60 |
#try: |
|
61 |
handle = opener.open('http://stream.twitter.com/1/statuses/sample.json') |
|
62 |
sax_handler = TweetHandler() |
|
63 |
while(True): |
|
64 |
try: |
|
65 |
parse(handle, sax_handler) |
|
66 |
except SAXParseException as e: |
|
67 |
print("RESET") |
|
68 |
sax_handler.reset() |
|
69 |
continue |
|
70 |
except: |
|
71 |
break |
|
72 |
handle.close() |
|
73 |
||
74 |
||
75 |
#time.sleep(random.randint(5,15)) |
|
76 |
||
77 |
||
78 |
1 |
from passwords import TWITTER_USERNAME, TWITTER_PASSWORD |
|
2 |
||
3 |
from collections import defaultdict |
|
4 |
from urllib2 import urlopen, HTTPBasicAuthHandler, build_opener |
|
5 |
import urllib2 |
|
6 |
import json |
|
7 |
||
8 |
from palindrome import palindrome_list |
|
9 |
||
10 |
def open_streaming_handle(url): |
|
11 |
password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm() |
|
12 |
password_mgr.add_password(None, |
|
13 |
url, |
|
14 |
TWITTER_USERNAME, |
|
15 |
TWITTER_PASSWORD) |
|
16 |
handler = urllib2.HTTPBasicAuthHandler(password_mgr) |
|
17 |
opener = urllib2.build_opener(handler) |
|
18 |
||
19 |
return opener.open(url) |
|
20 |
||
21 |
||
22 |
#we create various |
|
23 |
class StreamingTweets(object): |
|
24 |
||
25 |
def __init__(self): |
|
26 |
self.stats = defaultdict(int) |
|
27 |
||
28 |
def tweeted(self, screen_name, tweet): |
|
29 |
"""Called with each screen name and tweet""" |
|
30 |
palindromes = palindrome_list(tweet) |
|
31 |
||
32 |
for palindrome in palindromes: |
|
33 |
print(palindrome) |
|
34 |
self.stats[palindrome] += 1 |
|
35 |
||
36 |
def print_stats(self): |
|
37 |
"""Print out the current palindrome stats""" |
|
38 |
reports = stats.items() |
|
39 |
reports.sort(key=lambda x: -1 * x[1]) |
|
40 |
for row in reports: |
|
41 |
print("%s: %s" % (row[0], row[1])) |
|
42 |
||
43 |
if __name__ == '__main__': |
|
44 |
tweet = StreamingTweets() |
|
45 |
||
46 |
handle = open_streaming_handle('http://stream.twitter.com/1/statuses/sample.json') |
|
47 |
i = 0 |
|
48 |
while(True): |
|
49 |
json_obj = json.loads(handle.readline()) |
|
50 |
try: |
|
51 |
tweet.tweeted(json_obj[u'text'], json_obj[u'user'][u'screen_name']) |
|
52 |
except KeyError as e: |
|
53 |
print("key error") |
|
54 |
continue |
|
55 |
i+=1 |
|
56 |
if(i%10==0): |
|
57 |
print(i) |
|
58 |
handle.close() |
|
59 |
||
60 |
1 |
# -*- coding: utf-8 -*- |
|
2 |
||
3 |
import unittest |
|
4 |
from palindrome import palindrome, palindrome_list |
|
5 |
||
6 |
class TestPalindrome(unittest.TestCase): |
|
7 |
||
8 |
def setUp(self): |
|
9 |
self.seq = range(10) |
|
10 |
||
11 |
def testPalindromeSentence(self): |
|
12 |
self.assertEqual(['racecar'], palindrome_list('the racecar went to the store')) |
|
13 |
self.assertEqual([], palindrome_list('the lady went to the store')) |
|
14 |
||
15 |
self.assertEqual(['racecar', 'level'], palindrome_list('the raCeCar is on leveL one')) |
|
16 |
||
17 |
def testPalindrome(self): |
|
18 |
false = (False, None) |
|
19 |
||
20 |
self.assertTrue(palindrome('racecar')) |
|
21 |
self.assertFalse(palindrome('racecare')) |
|
22 |
self.assertTrue(palindrome('racecaR')) |
|
23 |
||
24 |
self.assertFalse(palindrome('a')) |
|
25 |
self.assertFalse(palindrome('aa')) |
|
26 |
self.assertFalse(palindrome('aaa')) |
|
27 |
self.assertTrue(palindrome('woaow')) |
|
28 |
||
29 |
self.assertFalse(palindrome('EssE')) |
|
30 |
self.assertFalse(palindrome('esse')) |
|
31 |
self.assertFalse(palindrome('Somos')) |
|
32 |
self.assertFalse(palindrome('somos')) |
|
33 |
||
34 |
self.assertFalse(palindrome('lol')) |
|
35 |
self.assertFalse(palindrome('lolol')) |
|
36 |
self.assertFalse(palindrome('lool')) |
|
37 |
self.assertFalse(palindrome('hahah')) |
|
38 |
self.assertFalse(palindrome('hahahah')) |
|
39 |
||
40 |
self.assertFalse(palindrome('+----+')) |
|
41 |
||
42 |
self.assertFalse(palindrome('lool')) |
|
43 |
self.assertFalse(palindrome('xxxx')) |
|
44 |
self.assertFalse(palindrome('somos')) |
|
45 |
self.assertFalse(palindrome('*---------*')) |
|
46 |
self.assertFalse(palindrome('Xoxox')) |
|
47 |
self.assertFalse(palindrome('............')) |
|
48 |
self.assertFalse(palindrome('eeeee')) |
|
49 |
self.assertFalse(palindrome('!!!!')) |
|
50 |
self.assertFalse(palindrome('---')) |
|
51 |
self.assertFalse(palindrome('KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK')) |
|
52 |
self.assertFalse(palindrome('hahahahah')) |
|
53 |
self.assertFalse(palindrome('Maam')) |
|
54 |
self.assertFalse(palindrome('Hahahah')) |
|
55 |
self.assertFalse(palindrome('yehey')) |
|
56 |
self.assertFalse(palindrome('Ooooo')) |
|
57 |
self.assertFalse(palindrome('kkkkkkkkkk')) |
|
58 |
self.assertFalse(palindrome('Esse')) |
|
59 |
self.assertFalse(palindrome('*---*')) |
|
60 |
self.assertFalse(palindrome('hahahah')) |
|
61 |
self.assertFalse(palindrome('14441')) |
|
62 |
||
63 |
self.assertFalse(palindrome(u'今日から少し潜ります。\テスト爆発しろ/')) |
|
64 |
||
65 |
self.assertFalse(palindrome('waw,waw')) |
|
66 |
||
67 |
||
68 |
if __name__ == '__main__': |
|
69 |
unittest.main() |
