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
thatmattbone
3 months ago

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)

Up to file-list .hgignore:

1
# use glob syntax.
2
syntax: glob
3
4
passwords.py
5
*.pyc
6
*~

Up to file-list README:

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]

Up to file-list sax.py:

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

Up to file-list streaming.py:

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

Up to file-list tests.py:

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()