This repository has been archived by the owner on Jun 7, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Code refactoring, test case for QueryThread added
- Loading branch information
Showing
7 changed files
with
179 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# -*- coding: utf8 -*- | ||
|
||
|
||
class TwitterException(Exception): | ||
""" | ||
Generic Twitter exception class | ||
""" | ||
def __init__(self, msg): | ||
self.msg = msg | ||
Exception.__init__(self, '%s' % msg) | ||
|
||
|
||
class TwitterAuthenticationException(TwitterException): | ||
""" | ||
Twitter exception class for authentication failures. | ||
""" | ||
def __init__(self, reason): | ||
self.msg = 'Twitter authentication failure! Reason: %s' % (reason) | ||
TwitterException.__init__(self, self.msg) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,68 @@ | ||
# -*- coding: utf8 -*- | ||
from AvivoreXT import Avivore, Helper | ||
from AvivoreXT import Helper | ||
import threading | ||
import time | ||
|
||
|
||
class QueryThread(threading.Thread): | ||
""" | ||
Class implementing the thread that performs periodic twitter searches. | ||
""" | ||
def __init__(self, avivore): | ||
self.avivore = avivore | ||
self.stored = [] | ||
threading.Thread.__init__(self) | ||
|
||
def run(self): | ||
def init_run(self): | ||
""" | ||
Prints info message and performs application authentication with Twitter. | ||
:return: None | ||
""" | ||
Helper.output("Spawning query thread [Q].") | ||
self.twitter_query_main(self.avivore) | ||
self.avivore.twitter_auth() | ||
|
||
def run(self): | ||
""" | ||
Contains threads main loop that runs until the user kills the AvivoreXT process or some serious error occurs. | ||
# performs classic search queries with configured time interval | ||
def twitter_query_main(self, avivore): | ||
stored = [] | ||
avivore.twitter_auth() | ||
:return: None | ||
""" | ||
self.init_run() | ||
while 1: | ||
for x in avivore.avivore_config.twitter_search_terms: | ||
self.twitter_search(self.avivore) | ||
|
||
def extract_data_from_tweet(self, avivore, tweet): | ||
""" | ||
Scans data for extractable data sets (previously defined in the 'TypeDefs' section of the AvivoreXT | ||
configuration) and if found stores them in the result database. | ||
:param avivore: Previously initialized Avivore instance. | ||
:param tweet: The tweet to analyzed that was returned from Twitter as a JSON object. | ||
:return: None | ||
""" | ||
z = tweet['id'], tweet['created_at'], tweet['user']['screen_name'], tweet['text'], tweet['user']['id_str'] | ||
result = avivore.twitter_read_tweet(z[3]) | ||
if result[0] >= 0: # If something is found, then we'll process the tweet | ||
self.stored = self.stored, int(z[0]) | ||
# result value, time, result itself, tweet ID, tweet itself, userId | ||
string = result[0], z[2], result[1], z[0], z[3], z[4] | ||
message = avivore.process_tweet(string) | ||
if 0 != message: | ||
Helper.output("[Q] " + message) | ||
|
||
def twitter_search(self, avivore): | ||
""" | ||
Performs a Twitter search query for all keywords defined in 'csv_search_term' configuration option and returns | ||
all found tweets. | ||
:param avivore: Previously initialized Avivore instance. | ||
:return: None | ||
""" | ||
# performs classic search queries with configured time interval | ||
for x in avivore.avivore_config.twitter_search_terms: | ||
twit_data = avivore.twitter_search(x) | ||
if twit_data is not None: | ||
for y in avivore.twitter_search(x): | ||
z = y['id'], y['created_at'], y['user']['screen_name'], y['text'], y['user']['id_str'] | ||
result = avivore.twitter_read_tweet(z[3]) | ||
if result[0] < 0: | ||
pass | ||
else: # If something is found, then we'll process the tweet | ||
stored = stored, int(z[0]) | ||
# result value, time, result itself, tweet ID, tweet itself, userId | ||
string = result[0], z[2], result[1], z[0], z[3], z[4] | ||
message = avivore.process_tweet(string) | ||
if 0 != message: | ||
Helper.output("[Q] " + message) | ||
self.extract_data_from_tweet(avivore, y) | ||
time.sleep(avivore.avivore_config.twitter_search_interval) |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,59 @@ | ||
__author__ = 'rc0r' | ||
# -*- coding: utf-8 -*- | ||
|
||
import unittest | ||
from AvivoreXT import Avivore, QueryThread, AvivoreTwitterError | ||
import os | ||
|
||
|
||
class QueryThreadTestCase(unittest.TestCase): | ||
def setUp(self): | ||
# code to execute in preparation for tests | ||
os.symlink('../sample_conf.db', './testdata/test.db') | ||
|
||
self.avivore_conf = Avivore.AvivoreConfig.AvivoreConfig(1, './testdata/test.db') | ||
self.avivore_conf.read_config() | ||
self.avivore_conf.init_database() | ||
self.avivore_conf.twitter_search_interval = 0 | ||
self.avivore = Avivore.Avivore(self.avivore_conf) | ||
self.query_thread_instance = QueryThread.QueryThread(self.avivore) | ||
|
||
def tearDown(self): | ||
# code to execute to clean up after tests | ||
os.remove('./testdata/test.db') | ||
|
||
def test_run_init(self): | ||
# test for network failure or twitter authentication error (no valid twitter credentials in config file) | ||
with self.assertRaises(AvivoreTwitterError.TwitterAuthenticationException): | ||
self.assertIsNone(self.query_thread_instance.init_run()) | ||
|
||
@unittest.skip('This test assumes there are valid twitter credentials in sample_conf.db!') | ||
def test_run_init_working_creds(self): | ||
# test in case network is working | ||
self.assertIsNone(self.query_thread_instance.init_run()) | ||
|
||
def test_twitter_search(self): | ||
self.assertIsNone(self.query_thread_instance.twitter_search(self.avivore)) | ||
|
||
def test_extract_data_from_tweet(self): | ||
tweet = { | ||
'id': '0123456789', | ||
'created_at': '000000000', | ||
'user': { | ||
'id_str': '987654321', | ||
'screen_name': '_rc0r', | ||
}, | ||
'text': 'This is a test tweet! My server ip: 10.11.12.13!', | ||
} | ||
|
||
# process unseen tweet | ||
self.assertIsNone(self.query_thread_instance.extract_data_from_tweet(self.avivore, tweet)) | ||
# process dupe | ||
self.assertIsNone(self.query_thread_instance.extract_data_from_tweet(self.avivore, tweet)) | ||
|
||
|
||
def test_main(): | ||
unittest.main() | ||
|
||
|
||
if __name__ == '__main__': | ||
test_main() |
Binary file not shown.