turntable_api 0.0.2

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.
@@ -0,0 +1,2 @@
1
+ require "turntable_api/version"
2
+ require "turntable_api/bot"
@@ -0,0 +1,162 @@
1
+ require 'rubygems'
2
+ require 'websocker'
3
+ require 'json'
4
+ require 'digest/sha1'
5
+ require 'httparty'
6
+
7
+ module TurntableAPI
8
+ class Bot
9
+ attr_reader :connected, :roomid
10
+
11
+ def initialize(opts = {})
12
+ @userid = opts[:userid]
13
+ @clientid = opts[:clientid] || "#{Time.now.to_i}-#{rand}"
14
+ @auth = opts[:auth]
15
+ @logger = opts[:logger] || Logger.new(STDOUT)
16
+ @msgId = 0
17
+ @command_handlers ||= {}
18
+ @response_handler ||= {}
19
+ @received_heartbeat = false
20
+ end
21
+
22
+ def start
23
+ connect
24
+ end
25
+
26
+ def room_register(roomid)
27
+ @ws.close unless @ws.nil?
28
+ if roomid.instance_of?(Hash) then roomid = roomid[:roomid] end
29
+ connect(roomid)
30
+ call_api 'room.register', :roomid => roomid
31
+ @roomid = roomid
32
+ end
33
+
34
+ def room_vote(opts)
35
+ dir = opts[:val]
36
+ songid = opts[:songid]
37
+ raise ArgumentError, "dir and songid are required" if songid.nil? or dir.nil?
38
+ opts[:vh] ||= hash("#{@roomid}#{dir}#{songid}")
39
+ opts[:th] ||= hash(rand.to_s)
40
+ opts[:ph] ||= hash(rand.to_s)
41
+ send_command('room_vote', opts)
42
+ end
43
+ alias_method :vote, :room_vote
44
+
45
+ # sends a command and sets up a callback that triggers
46
+ # when the reply is received
47
+ def on_response(cmd, opts={}, &blk)
48
+ msg_id = send_command cmd, opts
49
+ @response_handler[msg_id] = blk
50
+ end
51
+
52
+ def method_missing(meth, *args)
53
+ @logger.debug "method_missing #{meth}: #{args}"
54
+ hash = args[0] unless args.empty?
55
+ hash ||= {}
56
+ send_command(meth, hash)
57
+ end
58
+
59
+ # send a command to Turntable.FM
60
+ def send_command(command, opts={})
61
+ command = command.to_s.sub('_', '.')
62
+ call_api(command, opts)
63
+ end
64
+
65
+ # triggered when we receive a command from Turntable.FM
66
+ def on_command(command, &blk)
67
+ @command_handlers[command.to_sym] = blk
68
+ end
69
+
70
+ def on_ready(&blk)
71
+ @ready_handler = blk
72
+ end
73
+
74
+ def on_error(&blk)
75
+ @error_handler = blk
76
+ end
77
+
78
+ def on_message(msg)
79
+ if msg == "~m~10~m~no_session"
80
+ authenticate
81
+ elsif msg =~ /~m~[0-9]+~m~(~h~[0-9]+)/
82
+ hb = $1
83
+ @ready_handler.call unless @received_heartbeat or @ready_handler.nil?
84
+ @received_heartbeat = true
85
+ send_text(hb)
86
+ else
87
+ msg =~ /~m~\d*~m~(\{.*\})/
88
+ json = JSON.parse($1)
89
+ command = json["command"]
90
+ err = json["err"]
91
+ msgid = json["msgid"]
92
+ @error_handler.call(err) unless @error_handler.nil? or err.nil?
93
+ unless command.nil?
94
+ blk = @command_handlers[command.to_sym]
95
+ blk.call(json) unless blk.nil?
96
+ end
97
+ unless @response_handler[msgid].nil?()
98
+ blk = @response_handler[msgid]
99
+ blk.call(json) unless blk.nil?
100
+ @response_handler.delete(msgid)
101
+ end
102
+ end
103
+ end
104
+
105
+ private
106
+
107
+ def connect(roomid='unknown')
108
+ @ws = Websocker::Client.new(:host => chatserver(roomid), :path => "/socket.io/websocket")
109
+ @ws.connect
110
+ @ws.on_message do |msg|
111
+ on_message msg
112
+ end
113
+ @ws.on_closed do
114
+ on_closed
115
+ end
116
+ @listener_thread = @ws.listen
117
+ @connected = true
118
+ end
119
+
120
+ def on_closed
121
+ @connected = false
122
+ Thread.kill(@listener_thread) unless @listener_thread.nil?
123
+ end
124
+
125
+ def authenticate
126
+ call_api "user.authenticate"
127
+ end
128
+
129
+ def call_api(api, addl_params={})
130
+ messageId = next_message_id
131
+ params = { 'api' => api, 'userid' => @userid, 'clientid' => @clientid, 'userauth' => @auth, 'msgid' => messageId }
132
+ params['roomid'] = @roomid if @roomid
133
+ params.merge!(addl_params)
134
+ send_text(params.to_json)
135
+ return messageId
136
+ end
137
+
138
+ def send_text(txt)
139
+ msg = "~m~#{txt.length}~m~#{txt}"
140
+ send_raw(msg)
141
+ end
142
+
143
+ def send_raw(msg)
144
+ @logger.debug "Sent: #{msg}"
145
+ @ws.send(msg)
146
+ end
147
+
148
+ def next_message_id
149
+ @msgId += 1
150
+ end
151
+
152
+ def hash(msg)
153
+ Digest::SHA1.hexdigest(msg)
154
+ end
155
+
156
+ def chatserver(roomid)
157
+ resp = HTTParty.get("http://turntable.fm/api/room.which_chatserver?roomid=#{roomid}").body
158
+ JSON.parse(resp)[1]["chatserver"][0]
159
+ end
160
+ end
161
+
162
+ end
@@ -0,0 +1,3 @@
1
+ module TurntableAPI
2
+ VERSION = "0.0.2"
3
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: turntable_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Lawrence Mcalpin
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: websocker
16
+ requirement: &24047748 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *24047748
25
+ - !ruby/object:Gem::Dependency
26
+ name: json
27
+ requirement: &24046992 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *24046992
36
+ - !ruby/object:Gem::Dependency
37
+ name: httparty
38
+ requirement: &24046212 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *24046212
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: &24060960 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *24060960
58
+ - !ruby/object:Gem::Dependency
59
+ name: rake
60
+ requirement: &24059892 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *24059892
69
+ description: A simple API for making Turntable.fm bots.
70
+ email:
71
+ - lmcalpin+turntable_api@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - lib/turntable_api/bot.rb
77
+ - lib/turntable_api/version.rb
78
+ - lib/turntable_api.rb
79
+ homepage: ''
80
+ licenses: []
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubyforge_project: turntable_api
99
+ rubygems_version: 1.8.16
100
+ signing_key:
101
+ specification_version: 3
102
+ summary: API for creating Turntable bots.
103
+ test_files: []