kermit 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. data/Gemfile +18 -0
  2. data/LICENSE.txt +20 -0
  3. data/README.md +54 -0
  4. data/Rakefile +31 -0
  5. data/VERSION +1 -0
  6. data/bin/kermit +24 -0
  7. data/config/config.example.yml +24 -0
  8. data/doc/Adapter.html +533 -0
  9. data/doc/Converter.html +348 -0
  10. data/doc/DAO.html +1047 -0
  11. data/doc/KermitPFC.html +927 -0
  12. data/doc/Link.html +667 -0
  13. data/doc/Logging.html +401 -0
  14. data/doc/Logging/Settings.html +170 -0
  15. data/doc/RandomAdapter.html +501 -0
  16. data/doc/RandomConverter.html +359 -0
  17. data/doc/RandomPhraseGenerator.html +317 -0
  18. data/doc/ToUser.html +815 -0
  19. data/doc/TwitterAdapter.html +550 -0
  20. data/doc/TwitterConverter.html +598 -0
  21. data/doc/USMF.html +2188 -0
  22. data/doc/User.html +1407 -0
  23. data/doc/WebSocketClient.html +316 -0
  24. data/doc/WebSocketServer.html +427 -0
  25. data/doc/_index.html +270 -0
  26. data/doc/class_list.html +53 -0
  27. data/doc/css/common.css +1 -0
  28. data/doc/css/full_list.css +57 -0
  29. data/doc/css/style.css +328 -0
  30. data/doc/file.LICENSE.html +73 -0
  31. data/doc/file.README.html +123 -0
  32. data/doc/file_list.html +58 -0
  33. data/doc/frames.html +28 -0
  34. data/doc/index.html +123 -0
  35. data/doc/js/app.js +214 -0
  36. data/doc/js/full_list.js +173 -0
  37. data/doc/js/jquery.js +4 -0
  38. data/doc/method_list.html +764 -0
  39. data/doc/top-level-namespace.html +138 -0
  40. data/lib/business/adapter/adapter.rb +39 -0
  41. data/lib/business/adapter/random_adapter.rb +50 -0
  42. data/lib/business/adapter/twitter_adapter.rb +75 -0
  43. data/lib/business/converter/converter.rb +24 -0
  44. data/lib/business/converter/random_converter.rb +42 -0
  45. data/lib/business/converter/twitter_converter.rb +164 -0
  46. data/lib/business/random_phrase_generator.rb +39 -0
  47. data/lib/helper/DAO.rb +94 -0
  48. data/lib/helper/settings.rb +11 -0
  49. data/lib/helper/websocket_client.rb +37 -0
  50. data/lib/helper/websocket_server.rb +65 -0
  51. data/lib/kermitpfc.rb +164 -0
  52. data/lib/logging.rb +31 -0
  53. data/lib/model/USMF/USMF.rb +98 -0
  54. data/lib/model/USMF/link.rb +30 -0
  55. data/lib/model/USMF/to_user.rb +32 -0
  56. data/lib/model/USMF/user.rb +41 -0
  57. data/lib/model/templates/USMF +56 -0
  58. data/lib/model/templates/atom.xml +74 -0
  59. data/lib/model/templates/example +59 -0
  60. data/lib/model/templates/rss.xml +68 -0
  61. data/lib/model/templates/template +49 -0
  62. data/lib/model/templates/tweet +116 -0
  63. data/spec/DAO_spec.rb +64 -0
  64. data/spec/random_adapter_spec.rb +24 -0
  65. data/spec/random_converter_spec.rb +115 -0
  66. data/spec/random_phrase_generator_spec.rb +15 -0
  67. data/spec/twitter_adapter_spec.rb +24 -0
  68. data/spec/twitter_converter_spec.rb +132 -0
  69. data/websocket_client.html +20 -0
  70. metadata +253 -0
@@ -0,0 +1,138 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6
+ <title>
7
+ Top Level Namespace
8
+
9
+ &mdash; Documentation by YARD 0.8.2.1
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" media="screen" charset="utf-8" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
16
+
17
+ <script type="text/javascript" charset="utf-8">
18
+ hasFrames = window.top.frames.main ? true : false;
19
+ relpath = '';
20
+ framesUrl = "frames.html#!" + escape(window.location.href);
21
+ </script>
22
+
23
+
24
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
25
+
26
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
27
+
28
+
29
+ </head>
30
+ <body>
31
+ <div id="header">
32
+ <div id="menu">
33
+
34
+ <a href="_index.html">Index</a> &raquo;
35
+
36
+
37
+ <span class="title">Top Level Namespace</span>
38
+
39
+
40
+ <div class="noframes"><span class="title">(</span><a href="." target="_top">no frames</a><span class="title">)</span></div>
41
+ </div>
42
+
43
+ <div id="search">
44
+
45
+ <a class="full_list_link" id="class_list_link"
46
+ href="class_list.html">
47
+ Class List
48
+ </a>
49
+
50
+ <a class="full_list_link" id="method_list_link"
51
+ href="method_list.html">
52
+ Method List
53
+ </a>
54
+
55
+ <a class="full_list_link" id="file_list_link"
56
+ href="file_list.html">
57
+ File List
58
+ </a>
59
+
60
+ </div>
61
+ <div class="clear"></div>
62
+ </div>
63
+
64
+ <iframe id="search_frame"></iframe>
65
+
66
+ <div id="content"><h1>Top Level Namespace
67
+
68
+
69
+
70
+ </h1>
71
+
72
+ <dl class="box">
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+ </dl>
82
+ <div class="clear"></div>
83
+
84
+ <h2>Defined Under Namespace</h2>
85
+ <p class="children">
86
+
87
+
88
+ <strong class="modules">Modules:</strong> <span class='object_link'><a href="Logging.html" title="Logging (module)">Logging</a></span>
89
+
90
+
91
+
92
+ <strong class="classes">Classes:</strong> <span class='object_link'><a href="Adapter.html" title="Adapter (class)">Adapter</a></span>, <span class='object_link'><a href="Converter.html" title="Converter (class)">Converter</a></span>, <span class='object_link'><a href="DAO.html" title="DAO (class)">DAO</a></span>, <span class='object_link'><a href="KermitPFC.html" title="KermitPFC (class)">KermitPFC</a></span>, <span class='object_link'><a href="Link.html" title="Link (class)">Link</a></span>, <span class='object_link'><a href="RandomAdapter.html" title="RandomAdapter (class)">RandomAdapter</a></span>, <span class='object_link'><a href="RandomConverter.html" title="RandomConverter (class)">RandomConverter</a></span>, <span class='object_link'><a href="RandomPhraseGenerator.html" title="RandomPhraseGenerator (class)">RandomPhraseGenerator</a></span>, <span class='object_link'><a href="ToUser.html" title="ToUser (class)">ToUser</a></span>, <span class='object_link'><a href="TwitterAdapter.html" title="TwitterAdapter (class)">TwitterAdapter</a></span>, <span class='object_link'><a href="TwitterConverter.html" title="TwitterConverter (class)">TwitterConverter</a></span>, <span class='object_link'><a href="USMF.html" title="USMF (class)">USMF</a></span>, <span class='object_link'><a href="User.html" title="User (class)">User</a></span>, <span class='object_link'><a href="WebSocketClient.html" title="WebSocketClient (class)">WebSocketClient</a></span>, <span class='object_link'><a href="WebSocketServer.html" title="WebSocketServer (class)">WebSocketServer</a></span>
93
+
94
+
95
+ </p>
96
+
97
+ <h2>Constant Summary</h2>
98
+
99
+ <dl class="constants">
100
+
101
+ <dt id="SOCKETS-constant" class="">SOCKETS =
102
+ <div class="docstring">
103
+ <div class="discussion">
104
+ <p>
105
+ WebSocket clients array
106
+ </p>
107
+
108
+
109
+ </div>
110
+ </div>
111
+ <div class="tags">
112
+
113
+
114
+ </div>
115
+ </dt>
116
+ <dd><pre class="code"><span class='lbracket'>[</span><span class='rbracket'>]</span></pre></dd>
117
+
118
+ </dl>
119
+
120
+
121
+
122
+
123
+
124
+
125
+
126
+
127
+
128
+
129
+ </div>
130
+
131
+ <div id="footer">
132
+ Generated on Sat Aug 18 16:24:07 2012 by
133
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
134
+ 0.8.2.1 (ruby-1.9.2).
135
+ </div>
136
+
137
+ </body>
138
+ </html>
@@ -0,0 +1,39 @@
1
+ require_relative '../../logging'
2
+ # @author Daniel Machado Fernandez
3
+ # @version 1.0
4
+ # @abstract
5
+ #
6
+ # You must implement this class to adapt your data stream in our framework
7
+ class Adapter
8
+
9
+ include Logging
10
+
11
+ # Initializes the Adapter to run the logger
12
+ #
13
+ # @raise [Exception] if the method hasn't been implemented yet
14
+ def initialize
15
+
16
+ logger.fatal('The method initialize in Adapter must be implemented')
17
+ raise 'This method must be implemented'
18
+
19
+ end
20
+
21
+ # Connects to a particular data stream
22
+ #
23
+ # @raise [Exception] if the method hasn't been implemented yet
24
+ # @param stream [Integer] the number of the stream to identify it
25
+ def connect_stream (stream=1)
26
+ logger.fatal('The method connect_stream in Adapter must be implemented')
27
+ raise 'This method must be implemented'
28
+ end
29
+
30
+ # Persist the status retrieved from the data stream
31
+ #
32
+ # @raise [Exception] if the method hasn't been implemented yet
33
+ # @param status [String] the status retrieved from the data stream
34
+ def persist status
35
+ logger.fatal('The method persist in Adapter must be implemented')
36
+ raise 'This method must be implemented'
37
+ end
38
+
39
+ end
@@ -0,0 +1,50 @@
1
+ require_relative "../random_phrase_generator"
2
+ require_relative "./adapter"
3
+ require_relative "../../helper/DAO"
4
+ require_relative "../../logging"
5
+
6
+ # @author Daniel Machado Fernandez
7
+ # @version 1.0
8
+ #
9
+ # Self implementation from Adapter class to make it works with a Random Phrase Generator
10
+ class RandomAdapter < Adapter
11
+
12
+ include Logging
13
+
14
+ # Initializes the Random Adapter class with the dao parameters
15
+ def initialize
16
+
17
+ @dao = DAO.new 'rpg'
18
+ logger.debug('Starting RandomAdapter...')
19
+
20
+ end
21
+
22
+
23
+ # Connects to a Random Phrase Generator and retrieves phrases
24
+ #
25
+ # @param stream [Integer] number of the stream
26
+ def connect_stream (stream=1)
27
+
28
+ random = RandomPhraseGenerator.new
29
+ i=0
30
+ while true
31
+
32
+ persist random.generate
33
+ logger.debug('retrieving...')
34
+ i = i+1
35
+ if i%10 == 0
36
+ sleep 10
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+
43
+ # Save the status in a database to release the execution charge of threat that info in real time
44
+ #
45
+ # @param status [String] the status to persist
46
+ def persist status
47
+ @dao.save_status status
48
+ end
49
+
50
+ end
@@ -0,0 +1,75 @@
1
+ require 'json'
2
+ require 'twitter/json_stream'
3
+
4
+ require_relative "./adapter"
5
+ require_relative "../../helper/DAO"
6
+ require_relative "../../logging"
7
+
8
+ # @author Daniel Machado Fernandez
9
+ # @version 1.0
10
+ #
11
+ # Self implementation from Adapter class to make it works with Twitter Streaming API
12
+ class TwitterAdapter < Adapter
13
+
14
+ include Logging
15
+
16
+ # Configures the dao with the apropiates params
17
+ def initialize
18
+
19
+ logger.info('Starting TwitterAdapter...')
20
+ @dao = DAO.new 'twitter'
21
+
22
+ end
23
+
24
+ # Connects to the Twitter Streaming API and retrieves statuses with a track word previously defined
25
+ #
26
+ # @param stream [Integer] the number of the stream to identify it (use it when you have got more than one)
27
+ def connect_stream (stream=1)
28
+
29
+ logger.debug('retrieving...')
30
+ puts 'retrieving... '
31
+ track = Settings.twitter.track.send("track#{stream}")
32
+
33
+ EventMachine::run {
34
+
35
+ stream = Twitter::JSONStream.connect(
36
+ :path => "/1/statuses/filter.json?track=#{track}",
37
+ :auth => "#{Settings.twitter.login}:#{Settings.twitter.pass}",
38
+ :ssl => true,
39
+ :port => Settings.twitter.port
40
+ )
41
+
42
+ stream.each_item do |status|
43
+
44
+ persist status
45
+
46
+ end
47
+
48
+ stream.on_error do |message|
49
+ logger.error("#{message}")
50
+ end
51
+
52
+ stream.on_reconnect do |timeout, retries|
53
+ logger.warn("reconnecting in: #{timeout} seconds\n")
54
+ end
55
+
56
+ stream.on_max_reconnects do |timeout, retries|
57
+ logger.fatal("Failed after #{retries} failed reconnects\n")
58
+ end
59
+
60
+ trap('TERM') {
61
+ stream.stop
62
+ }
63
+ }
64
+ end
65
+
66
+ # Saves the tweet into the database
67
+ #
68
+ # @param status [String] tweet retrieved previously
69
+ def persist status
70
+
71
+ @dao.save_status status
72
+
73
+ end
74
+
75
+ end
@@ -0,0 +1,24 @@
1
+ require_relative '../../logging'
2
+
3
+ # @author Daniel Machado Fernandez
4
+ # @version 1.0
5
+ # @abstract
6
+ #
7
+ # Abstract class that must be implemented to transform a specifical status from a Stream into a USMF standard message
8
+ class Converter
9
+
10
+ include Logging
11
+
12
+ # Parses a status into a USMF message
13
+ #
14
+ # @raise [Exception] if the method hasn't been implemented yet
15
+ # @param status [String] status retrieved and saved previously in the Adapter
16
+ # @return [USMF] the resultant USMF message
17
+ def to_usmf status
18
+
19
+ logger.fatal('The method to_usmf in Converter must be implemented')
20
+ raise 'This method must be implemented'
21
+
22
+ end
23
+
24
+ end
@@ -0,0 +1,42 @@
1
+ require_relative './converter'
2
+ require_relative '../../model/USMF/USMF'
3
+ require_relative '../../model/USMF/link'
4
+ require_relative '../../model/USMF/to_user'
5
+ require_relative '../../model/USMF/user'
6
+ require_relative '../../logging'
7
+
8
+ # @author Daniel Machado Fernandez
9
+ # @version 1.0
10
+ #
11
+ # Self implementation from the Converter to work it with the Random Phrase Generator
12
+ class RandomConverter < Converter
13
+
14
+ include Logging
15
+
16
+ # Field to field parsing from status to a USMF message
17
+ #
18
+ # @param status [String] the phrase from the Random Phrase Generator
19
+ # @return [USMF] the resultant message
20
+ def to_usmf status
21
+
22
+ logger.debug("Start the random parse")
23
+ usmf = USMF.new
24
+ user = User.new
25
+
26
+ x = status.split('@')
27
+
28
+ usmf.service = 'Random'
29
+ usmf.id = x[0]
30
+ usmf.text = x[2]
31
+ user.name = x[1]
32
+
33
+ usmf.user = user
34
+
35
+ usmf.links = []
36
+ usmf.to_users = []
37
+ logger.debug("Finish the random parse")
38
+ usmf
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,164 @@
1
+ require 'json'
2
+
3
+ require_relative './converter'
4
+ require_relative '../../model/USMF/USMF'
5
+ require_relative '../../model/USMF/link'
6
+ require_relative '../../model/USMF/to_user'
7
+ require_relative '../../model/USMF/user'
8
+ require_relative '../../logging'
9
+
10
+ # @author Daniel Machado Fernandez
11
+ # @version 1.0
12
+ #
13
+ # Twitter Specification from Converter
14
+ class TwitterConverter < Converter
15
+
16
+ include Logging
17
+
18
+ # Field to field parsing to become a tweet into a USMF message
19
+ #
20
+ # @param status [String] the tweet previously retrieved
21
+ # @return [USMF] the resultant message
22
+ def to_usmf status
23
+
24
+ logger.debug("Starting tweet parse")
25
+
26
+ usmf = USMF.new
27
+ user = User.new
28
+
29
+ status = JSON.parse(status)
30
+ if status.has_key? 'Error'
31
+ logger.error("tweet malformed")
32
+ raise "status malformed"
33
+ end
34
+
35
+ #Retrieving a status from Twitter
36
+ usmf.service = "Twitter"
37
+ usmf.id = status["id_str"]
38
+
39
+
40
+ x = status["coordinates"]
41
+ unless x==nil
42
+ usmf.geo = x["coordinates"]
43
+ end
44
+
45
+ usmf.application = status["source"]
46
+
47
+
48
+ x = status["place"]
49
+ unless x == nil
50
+ usmf.location = x["full_name"] + " , " + x["country"]
51
+ end
52
+
53
+ usmf.date = status["created_at"]
54
+ usmf.text = status["text"]
55
+ usmf.description = status["in_reply_to_status_id_str"]
56
+ usmf.likes = status["retweet_count"]
57
+
58
+ #Retrieving user
59
+ x = status["user"]
60
+ unless x == nil
61
+ user.name = x["screen_name"]
62
+ user.real_name = x["name"]
63
+ user.id = x["id_str"]
64
+ user.language = x["lang"]
65
+
66
+ unless x["time_zone"] == nil and x["utc_offset"] == nil
67
+ user.utc = x["time_zone"].to_s + " + " + x["utc_offset"].to_s
68
+ end
69
+
70
+ user.description = x["description"]
71
+ user.avatar = x["profile_image_url_https"]
72
+ user.location = x["location"]
73
+ user.subscribers = x["followers_count"]
74
+ user.subscriptions = x["friends_count"]
75
+ user.postings = x["statuses_count"]
76
+ user.profile = "https://twitter.com/#!/#{user.name}"
77
+ user.website = x["url"]
78
+
79
+ usmf.user = user
80
+ usmf.source = "https://twitter.com/#{usmf.user.name}/status/#{usmf.id}"
81
+ end
82
+
83
+
84
+ usmf.to_users = []
85
+ usmf.links = []
86
+
87
+ #Retrieving entities
88
+
89
+ entities = status["entities"]
90
+ unless entities == nil
91
+
92
+ #Retrieving URLs
93
+
94
+ x = entities["urls"]
95
+ unless x == nil
96
+ x.each do |item|
97
+ l = Link.new
98
+ l.href = item["url"]
99
+
100
+ usmf.links << l
101
+ end
102
+ end
103
+
104
+ #Retrieving all media content
105
+
106
+ x = entities["media"]
107
+ unless x == nil
108
+ x.each do |item|
109
+ l = Link.new
110
+ l.title = item["type"]
111
+ l.thumbnail = item["media_url"]
112
+ l.href = item["url"]
113
+
114
+ usmf.links << l
115
+ end
116
+ end
117
+
118
+ #Retrieving hashtags
119
+
120
+ x = entities["hashtags"]
121
+ unless x == nil
122
+
123
+ usmf.keywords = ""
124
+ x.each do |h|
125
+
126
+ usmf.keywords += h["text"] + ", "
127
+
128
+ end
129
+
130
+ end
131
+
132
+ #Retrieving mentions
133
+
134
+ x = entities["user_mentions"]
135
+ unless x == nil
136
+ x.each do |item|
137
+ tu = ToUser.new
138
+
139
+ tu.name = item["screen_name"]
140
+ tu.id = item["id_str"]
141
+
142
+ if item["id_str"] == status["in_reply_to_user_id_str"]
143
+ tu.service = "reply"
144
+ else
145
+ tu.service = "mention"
146
+ end
147
+ unless status["in_reply_to_status_id_str"] == nil
148
+ tu.title = status["in_reply_to_status_id_str"]
149
+ tu.href = "https://twitter.com/#{tu.name}/status/#{tu.title}"
150
+ end
151
+
152
+ usmf.to_users << tu
153
+ end
154
+ end
155
+
156
+ end
157
+
158
+ logger.debug("Finished tweet parse")
159
+
160
+ usmf
161
+
162
+ end
163
+
164
+ end