protolink 0.2.7 → 0.2.8
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -0
- data/Gemfile.lock +12 -0
- data/README.markdown +15 -4
- data/example/chatbot.rb +24 -0
- data/example/create_and_subscribe.rb +5 -1
- data/example/linkbot/base_plugins.rb +71 -0
- data/example/linkbot/plugins/awwwyeah.rb +11 -0
- data/example/linkbot/plugins/blowhard.rb +40 -0
- data/example/linkbot/plugins/comic.rb +40 -0
- data/example/linkbot/plugins/dumb.rb +11 -0
- data/example/linkbot/plugins/dupe.rb.inactive +64 -0
- data/example/linkbot/plugins/face.rb +11 -0
- data/example/linkbot/plugins/fuuu.rb +12 -0
- data/example/linkbot/plugins/help.rb +26 -0
- data/example/linkbot/plugins/image.rb +30 -0
- data/example/linkbot/plugins/imgur.rb +31 -0
- data/example/linkbot/plugins/jason.rb +73 -0
- data/example/linkbot/plugins/karma.rb.inactive +75 -0
- data/example/linkbot/plugins/last.rb +40 -0
- data/example/linkbot/plugins/links.rb.inactive +41 -0
- data/example/linkbot/plugins/log.rb +17 -0
- data/example/linkbot/plugins/okay.rb +11 -0
- data/example/linkbot/plugins/onion.rb +19 -0
- data/example/linkbot/plugins/popcorn.rb +32 -0
- data/example/linkbot/plugins/qwantz.rb +29 -0
- data/example/linkbot/plugins/search.rb +32 -0
- data/example/linkbot/plugins/shutup.rb +11 -0
- data/example/linkbot/plugins/slap.rb +15 -0
- data/example/linkbot/plugins/snap.rb +18 -0
- data/example/linkbot/plugins/stab.rb +12 -0
- data/example/linkbot/plugins/store.rb +71 -0
- data/example/linkbot/plugins/store_help.rb +22 -0
- data/example/linkbot/plugins/swanson.rb +41 -0
- data/example/linkbot/plugins/titles.rb +34 -0
- data/example/linkbot/plugins/translate.rb +21 -0
- data/example/linkbot/plugins/tsa.rb +22 -0
- data/example/linkbot/plugins/twss.rb +20 -0
- data/example/linkbot/plugins/urban.rb +27 -0
- data/example/linkbot/util.rb +28 -0
- data/lib/protolink.rb +4 -0
- data/lib/protolink/channel.rb +4 -0
- data/lib/protolink/flash_connection.rb +47 -0
- data/lib/protolink/proto_socket.rb +33 -0
- data/lib/protolink/protonet.rb +18 -3
- data/lib/protolink/version.rb +1 -1
- data/test/all_tests.rb +2 -2
- metadata +41 -4
@@ -0,0 +1,22 @@
|
|
1
|
+
class StoreHelp < Linkbot::Plugin
|
2
|
+
def self.on_store(args)
|
3
|
+
mymsg = nil
|
4
|
+
|
5
|
+
if args.length > 0
|
6
|
+
Linkbot::Plugin.plugins.each {|k,v|
|
7
|
+
if v[:handlers][:"linkbot-store"] && v[:handlers][:"linkbot-store"][:help] && v[:handlers][:"linkbot-store"][:regex].match(args[0])
|
8
|
+
mymsg = v[:ptr].send(v[:handlers][:"linkbot-store"][:help])
|
9
|
+
end
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
mymsg
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
Linkbot::Plugin.register('store_help', self,
|
18
|
+
{
|
19
|
+
:"linkbot-store" => {:regex => /^help$/, :handler => :on_store},
|
20
|
+
}
|
21
|
+
)
|
22
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
class Swanson < Linkbot::Plugin
|
4
|
+
def self.on_message(message, matches)
|
5
|
+
quotes = [
|
6
|
+
"http://www.pajiba.com/image/ron-dancing-animated.gif",
|
7
|
+
"http://28.media.tumblr.com/tumblr_lgl0ieJ0Z01qzkiy8o1_400.jpg",
|
8
|
+
"http://www.randomblog.org/wp-content/uploads/2011/02/Ron-Swanson-Pyramid-e1297006038780.jpg",
|
9
|
+
"I have been developing the Swanson Pyramid of Greatness for years. It's a perfectly calibrated recipe for maximum personal achievement. Categories include: Capitalism, God's way of determining who is smart, and who is poor. Crying, acceptable at funerals and the Grand Canyon. Rage. Poise. Property rights. Fish, for sport only, not for meat. Fish meat is practically a vegetable.",
|
10
|
+
"The less I know about other people's affairs, the happier I am. I'm not interested in caring about people. I once worked with a guy for three years and never learned his name. Best friend I ever had. We still never talk sometimes.",
|
11
|
+
"Now, I know I'm not going to find somebody that's both aggressively mean and apathetic. April really is the whole package.",
|
12
|
+
"You had me at meat tornado.",
|
13
|
+
"I'm surrounded by a lot of women in this department. And that includes the men.",
|
14
|
+
"When I walked in this morning I saw that the flag was at half mast, I though, 'All right, another bureaucrat ate it!' And then I saw it was Lil' Sebastian. Half mast is too high. Show some damn respect.",
|
15
|
+
"I am submitting this menu from a Pawnee institution, J.J.'s Diner. Home of the world's best breakfast dish: The Four Horsemeals of the Eggporkalypse.",
|
16
|
+
"You may have thought you heard me say I wanted a lot of bacon and eggs, but what I said was: Give me all the bacon and eggs you have.",
|
17
|
+
"(On fishing) It's like yoga, except I still get to kill something.",
|
18
|
+
"Encapsulate the spirit of melancholy. Easy. Boom, a sad desk. Boom, sad wall. It's art. Anything is anything.",
|
19
|
+
"I am off to have a mid-morning pre-lunch with my lady friend, but I will be back in time for lunch.",
|
20
|
+
"The key to burning an ex-wife effigy is to dip it in paraffin wax and then toss the flaming bottle of isopropyl alcohol from a safe distance. Do not stand too close when you light an ex-wife effigy.",
|
21
|
+
"It's never too early to learn that the government is a greedy piglet that suckles on a taxpayer's teet until they have sore, chapped nipples. I'm gonna need a different metaphor to give this nine year old.",
|
22
|
+
"Leslie, you need to understand that we are headed to the most special place on earth. When I'm done eating a Mulligan's meal, for weeks afterwards there are flecks of meat in my mustache and I refuse to clean it because every now and then a piece of meat will fall into my mouth.",
|
23
|
+
"(His museum speech) Shut up. And look at me. Welcome to Visions of Nature. This room has several paintings in it. Some are big and some are small. People did them and they are here now. I believe after this is over they will be hung in government buildings. Why the government is involved in an art show is beyond me. I also think it's pointless for a human to paint scenes of nature when they can go outside and stand in it.",
|
24
|
+
"The whole thing is a scam. Birthdays were invented by Hallmark to sell cards.",
|
25
|
+
"I won't publicly endorse a product unless I use it exclusively. My only official recommendations are U.S. Army issued mustache trimmers, Morton's salt, and the C.R. Lawrence Fein two inch axe-style scraper oscillating knife blade."
|
26
|
+
]
|
27
|
+
quotes[rand(quotes.length)]
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.help
|
31
|
+
"!swanson - The one and only, Ron Swanson"
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
Linkbot::Plugin.register('swanson', self,
|
36
|
+
{
|
37
|
+
:message => {:regex => /!swanson/, :handler => :on_message, :help => :help},
|
38
|
+
:"direct-message" => {:regex => /!swanson/, :handler => :on_message, :help => :help}
|
39
|
+
}
|
40
|
+
)
|
41
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Titles < Linkbot::Plugin
|
2
|
+
def self.on_store(args)
|
3
|
+
mymsg = nil
|
4
|
+
|
5
|
+
if args.length > 1
|
6
|
+
target_user = args.shift
|
7
|
+
rows = Linkbot.db.execute("select username,showname from users where username='#{target_user}'")
|
8
|
+
if rows.length == 0
|
9
|
+
raise StoreError.new("Unknown user")
|
10
|
+
else
|
11
|
+
old_username = (rows[0][1].nil? || rows[0][1] == '') ? rows[0][0] : rows[0][1]
|
12
|
+
new_username = args.join(" ")
|
13
|
+
Linkbot.db.execute("update users set showname='#{new_username}' where username='#{target_user}'")
|
14
|
+
mymsg = "'#{old_username}' is now known as '#{new_username}'"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
mymsg
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.cost
|
22
|
+
50
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.advertisement
|
26
|
+
"name (username) (new name): Change how a user's name appears in any linkbot command."
|
27
|
+
end
|
28
|
+
|
29
|
+
Linkbot::Plugin.register('titles', self,
|
30
|
+
{
|
31
|
+
:"linkbot-store" => {:regex => /^name$/, :handler => :on_store},
|
32
|
+
}
|
33
|
+
)
|
34
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
require 'cgi'
|
4
|
+
|
5
|
+
class Translate < Linkbot::Plugin
|
6
|
+
def self.on_message(message, matches)
|
7
|
+
res = Net::HTTP.post_form(URI.parse('http://www.cs.utexas.edu/users/jbc/bork/bork.cgi'),
|
8
|
+
{'input'=> CGI.unescapeHTML(message_history[1]['body']), 'type'=>'chef'})
|
9
|
+
CGI::unescape(res.body.to_s.gsub("&epus;","'"))
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.help
|
13
|
+
"!translate - Trunslete-a zee lest messege-a"
|
14
|
+
end
|
15
|
+
|
16
|
+
Linkbot::Plugin.register('translate', self,
|
17
|
+
{
|
18
|
+
:message => {:regex => /!translate/, :handler => :on_message, :help => :help}
|
19
|
+
}
|
20
|
+
)
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Tsa < Linkbot::Plugin
|
2
|
+
Linkbot::Plugin.register('tsa', self,
|
3
|
+
{
|
4
|
+
:message => {:regex => Regexp.new('tsa', 'g'), :handler => :on_message}
|
5
|
+
}
|
6
|
+
)
|
7
|
+
|
8
|
+
def self.on_message(message, matches)
|
9
|
+
messages = [
|
10
|
+
"I'm going to touch your balls with the back of my hand",
|
11
|
+
"We have an opt-out!",
|
12
|
+
"TSA: the McDonalds workers of the government",
|
13
|
+
"Security Theater Professionals",
|
14
|
+
"Sir, you've been added to the \"domestic extremists\" list",
|
15
|
+
"Not all parts of the government are accountable to the public, especially the TSA",
|
16
|
+
"Your junk is safe in our hands",
|
17
|
+
"It's not a grope, it's a freedom pat",
|
18
|
+
"We handle more packages than UPS",
|
19
|
+
]
|
20
|
+
messages[rand(messages.length)]
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'twss'
|
2
|
+
|
3
|
+
class Twss < Linkbot::Plugin
|
4
|
+
def self.on_message(message, matches)
|
5
|
+
TWSS.threshold = 2.0 #lower = 'better'
|
6
|
+
if TWSS(message.body) and 1 < 0
|
7
|
+
"That's what she said"
|
8
|
+
else
|
9
|
+
""
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
Linkbot::Plugin.register('twss', self,
|
14
|
+
{
|
15
|
+
:message => {:handler => :on_message}
|
16
|
+
}
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class Define < Linkbot::Plugin
|
2
|
+
def self.on_message(message, match)
|
3
|
+
word = URI.escape(match[0])
|
4
|
+
doc = Hpricot(open("http://www.urbandictionary.com/define.php?term=#{word}").read)
|
5
|
+
definition = doc.search("#entries td div[@class=definition]")
|
6
|
+
if definition.empty?
|
7
|
+
message = "No definition for '#{match[0]}' found"
|
8
|
+
else
|
9
|
+
definition = definition[0].inner_html.gsub("<br />", "\n")
|
10
|
+
definition = Sanitize.clean(definition)
|
11
|
+
message = "#{match[0]}: #{definition}"
|
12
|
+
end
|
13
|
+
|
14
|
+
message
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.help
|
18
|
+
"!define (word) - use a dictionary, foo"
|
19
|
+
end
|
20
|
+
|
21
|
+
Linkbot::Plugin.register('urban', self,
|
22
|
+
{
|
23
|
+
:message => {:regex => /!define (.*)/, :handler => :on_message, :help => :help},
|
24
|
+
:"direct-message" => {:regex => /!define (.*)/, :handler => :on_message, :help => :help}
|
25
|
+
}
|
26
|
+
)
|
27
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Util
|
2
|
+
def self.ago_in_words(time1, time2)
|
3
|
+
diff = time1.to_i - time2.to_i
|
4
|
+
ago = ''
|
5
|
+
if diff == 1
|
6
|
+
ago = "#{diff} second ago"
|
7
|
+
elsif diff < 60
|
8
|
+
ago = "#{diff} seconds ago"
|
9
|
+
elsif diff < 120
|
10
|
+
ago = "a minute ago"
|
11
|
+
elsif diff < 3600
|
12
|
+
ago = "#{diff.to_i / 60} minutes ago"
|
13
|
+
elsif diff < 7200
|
14
|
+
ago = "an hour ago"
|
15
|
+
elsif diff < 86400
|
16
|
+
ago = "#{diff.to_i / 3600} hours ago"
|
17
|
+
elsif diff < 172800
|
18
|
+
ago = "yesterday"
|
19
|
+
elsif diff < 604800
|
20
|
+
ago = "#{diff.to_i / 86400} days ago"
|
21
|
+
elsif diff < 1209600
|
22
|
+
ago = "last week"
|
23
|
+
else
|
24
|
+
ago = "#{diff.to_i / 604800} weeks ago"
|
25
|
+
end
|
26
|
+
ago
|
27
|
+
end
|
28
|
+
end
|
data/lib/protolink.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'protolink/flash_connection'
|
3
|
+
require 'protolink/proto_socket'
|
1
4
|
require 'protolink/protonet'
|
2
5
|
require 'protolink/channel'
|
3
6
|
require 'protolink/user'
|
4
7
|
require 'protolink/listen'
|
5
8
|
require 'protolink/node'
|
6
9
|
|
10
|
+
|
7
11
|
module Protolink
|
8
12
|
class Error < StandardError; end
|
9
13
|
class SSLRequiredError < Error; end
|
data/lib/protolink/channel.rb
CHANGED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
class FlashConnection < EventMachine::Connection
|
4
|
+
def initialize
|
5
|
+
@buffer = ''
|
6
|
+
|
7
|
+
set_comm_inactivity_timeout 60
|
8
|
+
end
|
9
|
+
# JSON packets
|
10
|
+
def send_json json
|
11
|
+
send_data json.to_json + "\0"
|
12
|
+
end
|
13
|
+
|
14
|
+
# Null-terminated lines
|
15
|
+
def send_line line
|
16
|
+
send_data line + "\0"
|
17
|
+
end
|
18
|
+
|
19
|
+
def receive_line line
|
20
|
+
receive_json JSON.parse(line)
|
21
|
+
rescue JSON::ParserError
|
22
|
+
log "JSON parsing error"
|
23
|
+
end
|
24
|
+
|
25
|
+
# Raw bytes
|
26
|
+
def receive_data data
|
27
|
+
@buffer += data
|
28
|
+
|
29
|
+
while @buffer.include? "\0"
|
30
|
+
packet = @buffer[0, @buffer.index("\0")]
|
31
|
+
@buffer = @buffer[(@buffer.index("\0")+1)..-1]
|
32
|
+
|
33
|
+
receive_line packet
|
34
|
+
end
|
35
|
+
rescue => ex
|
36
|
+
p ex, ex.backtrace
|
37
|
+
end
|
38
|
+
|
39
|
+
# TODO: redundant code
|
40
|
+
def log text
|
41
|
+
puts "#{self}: #{text}" if Rails.env != "production" || $DEBUG
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_s
|
45
|
+
"connection #{inspect}"
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class ProtoSocket < FlashConnection
|
2
|
+
|
3
|
+
def initialize(connection, message_callback)
|
4
|
+
@connection = connection
|
5
|
+
@message_callback = message_callback
|
6
|
+
super()
|
7
|
+
end
|
8
|
+
|
9
|
+
def connection_completed
|
10
|
+
token = @connection.current_user.communication_token
|
11
|
+
|
12
|
+
send_json :operation => 'authenticate',
|
13
|
+
:payload => {:type => 'web', :user_id => @connection.current_user.id, :token => token}
|
14
|
+
|
15
|
+
periodic_ping
|
16
|
+
end
|
17
|
+
|
18
|
+
def receive_json(json)
|
19
|
+
@message_callback.call(json)
|
20
|
+
end
|
21
|
+
|
22
|
+
def periodic_ping
|
23
|
+
@ping ||= EventMachine.add_periodic_timer 30 do
|
24
|
+
# log "sending ping"
|
25
|
+
send_json :operation => 'ping'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def unbind
|
30
|
+
EventMachine::cancel_timer @ping
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
data/lib/protolink/protonet.rb
CHANGED
@@ -25,11 +25,20 @@ module Protolink
|
|
25
25
|
if proxy
|
26
26
|
clazz.http_proxy(proxy[:uri], proxy[:port])
|
27
27
|
end
|
28
|
-
clazz.new
|
28
|
+
clazz.new(username)
|
29
29
|
end
|
30
30
|
|
31
31
|
# CHANNELS
|
32
|
-
|
32
|
+
|
33
|
+
def initialize(username)
|
34
|
+
@current_user_name = username
|
35
|
+
super()
|
36
|
+
end
|
37
|
+
|
38
|
+
def current_user
|
39
|
+
@current_user ||= find_user_by_login(@current_user_name)
|
40
|
+
end
|
41
|
+
|
33
42
|
# Get an array of all the available channels
|
34
43
|
def channels
|
35
44
|
get('/api/v1/channels').map do |channel|
|
@@ -137,7 +146,7 @@ module Protolink
|
|
137
146
|
end
|
138
147
|
|
139
148
|
def destroy_listen(user_id, channel_id)
|
140
|
-
channel_query = channel_id.match("-") ? {:channel_uuid => channel_id} : {:channel_id => channel_id}
|
149
|
+
channel_query = channel_id.to_s.match("-") ? {:channel_uuid => channel_id} : {:channel_id => channel_id}
|
141
150
|
delete('/api/v1/listens', :body => {:user_id => user_id}.merge(channel_query) )
|
142
151
|
end
|
143
152
|
|
@@ -151,6 +160,12 @@ module Protolink
|
|
151
160
|
Node.new(self, response) if response
|
152
161
|
end
|
153
162
|
|
163
|
+
def socket(&blk)
|
164
|
+
EventMachine.run {
|
165
|
+
EventMachine.connect URI.parse(self.class.base_uri).host, 5000, ProtoSocket, self, blk
|
166
|
+
}
|
167
|
+
end
|
168
|
+
|
154
169
|
[:get, :post, :update, :delete].each do |method|
|
155
170
|
class_eval <<-EOS
|
156
171
|
def #{method}(uri, options = {})
|
data/lib/protolink/version.rb
CHANGED
data/test/all_tests.rb
CHANGED
@@ -8,8 +8,8 @@ require 'ruby-debug'
|
|
8
8
|
Debugger.start
|
9
9
|
# change this if you need to connect to another server
|
10
10
|
PTN_SERVER = "http://localhost:3000"
|
11
|
-
PTN_USER = "
|
12
|
-
PTN_PASS = "
|
11
|
+
PTN_USER = "admin"
|
12
|
+
PTN_PASS = "admin"
|
13
13
|
|
14
14
|
class TestAll < Test::Unit::TestCase
|
15
15
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: protolink
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 8
|
10
|
+
version: 0.2.8
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- "Bj\xC3\xB6rn B. Dorra"
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2011-10-
|
19
|
+
date: 2011-10-26 00:00:00 +02:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -64,11 +64,48 @@ files:
|
|
64
64
|
- Gemfile.lock
|
65
65
|
- README.markdown
|
66
66
|
- Rakefile
|
67
|
+
- example/chatbot.rb
|
67
68
|
- example/create_and_subscribe.rb
|
69
|
+
- example/linkbot/base_plugins.rb
|
70
|
+
- example/linkbot/plugins/awwwyeah.rb
|
71
|
+
- example/linkbot/plugins/blowhard.rb
|
72
|
+
- example/linkbot/plugins/comic.rb
|
73
|
+
- example/linkbot/plugins/dumb.rb
|
74
|
+
- example/linkbot/plugins/dupe.rb.inactive
|
75
|
+
- example/linkbot/plugins/face.rb
|
76
|
+
- example/linkbot/plugins/fuuu.rb
|
77
|
+
- example/linkbot/plugins/help.rb
|
78
|
+
- example/linkbot/plugins/image.rb
|
79
|
+
- example/linkbot/plugins/imgur.rb
|
80
|
+
- example/linkbot/plugins/jason.rb
|
81
|
+
- example/linkbot/plugins/karma.rb.inactive
|
82
|
+
- example/linkbot/plugins/last.rb
|
83
|
+
- example/linkbot/plugins/links.rb.inactive
|
84
|
+
- example/linkbot/plugins/log.rb
|
85
|
+
- example/linkbot/plugins/okay.rb
|
86
|
+
- example/linkbot/plugins/onion.rb
|
87
|
+
- example/linkbot/plugins/popcorn.rb
|
88
|
+
- example/linkbot/plugins/qwantz.rb
|
89
|
+
- example/linkbot/plugins/search.rb
|
90
|
+
- example/linkbot/plugins/shutup.rb
|
91
|
+
- example/linkbot/plugins/slap.rb
|
92
|
+
- example/linkbot/plugins/snap.rb
|
93
|
+
- example/linkbot/plugins/stab.rb
|
94
|
+
- example/linkbot/plugins/store.rb
|
95
|
+
- example/linkbot/plugins/store_help.rb
|
96
|
+
- example/linkbot/plugins/swanson.rb
|
97
|
+
- example/linkbot/plugins/titles.rb
|
98
|
+
- example/linkbot/plugins/translate.rb
|
99
|
+
- example/linkbot/plugins/tsa.rb
|
100
|
+
- example/linkbot/plugins/twss.rb
|
101
|
+
- example/linkbot/plugins/urban.rb
|
102
|
+
- example/linkbot/util.rb
|
68
103
|
- lib/protolink.rb
|
69
104
|
- lib/protolink/channel.rb
|
105
|
+
- lib/protolink/flash_connection.rb
|
70
106
|
- lib/protolink/listen.rb
|
71
107
|
- lib/protolink/node.rb
|
108
|
+
- lib/protolink/proto_socket.rb
|
72
109
|
- lib/protolink/protonet.rb
|
73
110
|
- lib/protolink/user.rb
|
74
111
|
- lib/protolink/version.rb
|