nyoibo 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "shoulda-matchers", :git => "https://github.com/thoughtbot/shoulda-matchers.git"
4
+ gem "shoulda-context", :git => "https://github.com/thoughtbot/shoulda-context.git"
5
+ gem "turn", :git => "https://github.com/yalab/turn.git"
6
+ gemspec
@@ -0,0 +1,20 @@
1
+ Copyright 2011 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,11 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+ require 'rake/testtask'
4
+ desc "Default Task"
5
+ Rake::TestTask.new do |t|
6
+ files = FileList['test/test_helper.rb', 'test/**/*test.rb']
7
+ t.test_files = files
8
+ t.libs << "test"
9
+ # t.warning = true
10
+ end
11
+ task :default => :test
@@ -0,0 +1,15 @@
1
+ module NyoiboHelper
2
+ def ws_form_for(model, options={}, &block)
3
+ options[:html] ||= {}
4
+ options[:html][:id] ||= 'ws-form'
5
+ output = ''
6
+ output << javascript_tag(<<EOS)
7
+ WEB_SOCKET_DEBUG = true;
8
+ WEB_SOCKET_SWF_LOCATION = '/WebSocketMain.swf';
9
+ var nyoibo = #{I18n.t('nyoibo').to_json};
10
+ EOS
11
+ output << form_for(model, options, &block)
12
+ output << content_tag(:div, '', :id => 'ws-progress')
13
+ output.html_safe
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ require 'rails'
2
+ require 'rails/generators'
3
+ module Nyoibo
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path("../templates", __FILE__)
7
+
8
+ desc "Creates a Nyoibo initializer and copy javascript and locale files to your application."
9
+ def copy_initializer
10
+ template "nyoibo.rb.erb", "config/initializers/nyoibo.rb"
11
+ template "nyoibo_en.yml", "config/locales/nyoibo_en.yml"
12
+ template "nyoibo.js.coffee", "app/assets/javascripts/nyoibo.js.coffee"
13
+ template "../../../../vendor/html5jp/progress.js", "app/assets/javascripts/progress.js"
14
+ template "../../../../vendor/web-socket-js/web_socket.js", "app/assets/javascripts/web_socket.js"
15
+ template "../../../../vendor/web-socket-js/swfobject.js", "app/assets/javascripts/swfobject.js"
16
+ template "../../../../vendor/web-socket-js/WebSocketMain.swf", "public/WebSocketMain.swf"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,65 @@
1
+ jQuery ($)->
2
+ progress = new html5jp.progress("ws-progress")
3
+ progress.draw()
4
+
5
+ form = $('#ws-form')
6
+ progress_bar = $("#ws-progress")
7
+
8
+ fire = (obj, name, data) ->
9
+ event = $.Event(name)
10
+ obj.trigger(event, data)
11
+ return event.result != false
12
+
13
+ form.bind 'ws:upload', (event) ->
14
+ file = form.find('input[type=file]').get(0).files[0]
15
+ try
16
+ max_length = file.size
17
+ catch e
18
+ alert nyoibo.file_not_found
19
+ return
20
+ if max_length == 0
21
+ alert nyoibo.file_not_found
22
+ return
23
+ chunk = 102400
24
+ start = 0
25
+ ws = new WebSocket("ws://localhost:3030/")
26
+
27
+ fire(form, 'ws:before_upload')
28
+ ws.onclose = ->
29
+ progress.set_val(100)
30
+ fire(form, 'ws:after_upload')
31
+ progress.reset()
32
+ ws = null
33
+
34
+ ws.onmessage = (evt) ->
35
+ switch evt.data
36
+ when 'OK Ready'
37
+ params = {filename: file.name, comment: $('#post_comment').val(), size: max_length, session_string: $('#session_string').val()}
38
+ ws.send("JSON: " + JSON.stringify(params))
39
+ when 'OK Bye'
40
+ ws.close()
41
+ when 'EMPTY'
42
+ ws.send("QUIT")
43
+ when 'NEXT'
44
+ val = Math.floor(start / max_length * 100)
45
+ progress.set_val(val)
46
+ stop = start + chunk - 1
47
+ if stop >= max_length
48
+ stop = max_length
49
+
50
+ blob = if typeof(file.mozSlice) == "function"
51
+ file.mozSlice(start, stop)
52
+ else if typeof(file.webkitSlice) == "function"
53
+ file.webkitSlice(start, stop)
54
+ start = stop
55
+ reader = new FileReader()
56
+ reader.onloadend = (e) ->
57
+ ws.send(e.target.result)
58
+
59
+ setTimeout ->
60
+ reader.readAsBinaryString(blob)
61
+ , 300
62
+
63
+ $('#ws-form input[type=submit]').click ->
64
+ fire(form, 'ws:upload') if fire(form, 'ws:prepare_upload')
65
+ return false
@@ -0,0 +1,4 @@
1
+ Nyoibo.configure do
2
+ host "localhost"
3
+ port 3030
4
+ end
@@ -0,0 +1,3 @@
1
+ en:
2
+ nyoibo:
3
+ file_not_found: `File is not exists`
@@ -0,0 +1,17 @@
1
+ require 'em-websocket'
2
+ require 'json'
3
+ require 'nyoibo/configure'
4
+ require 'nyoibo/daemon'
5
+ require 'nyoibo/callback'
6
+
7
+ module Nyoibo
8
+ extend Configure
9
+ extend Daemon
10
+ extend Callback::Runner
11
+ end
12
+
13
+ if defined?(Rails)
14
+ require 'rails'
15
+ require 'nyoibo/rails'
16
+ require 'nyoibo/railtie'
17
+ end
@@ -0,0 +1,28 @@
1
+ module Nyoibo
2
+ module Callback
3
+ def self.callbacks
4
+ @callbacks ||= {}
5
+ end
6
+ def self.included(base)
7
+ base.extend ClassMethod
8
+ end
9
+
10
+ module ClassMethod
11
+ def uploaded(path, &block)
12
+ if ENV["NYOIBO_ENV"] == "production" && Nyoibo::Callback.callbacks[path]
13
+ raise "Already defined '#{path}' updated callback."
14
+ end
15
+ Nyoibo::Callback.callbacks[path] = block
16
+
17
+ Process.kill(:TERM, Nyoibo.pid) && Nyoibo.run if ENV["NYOIBO_ENV"] == "development"
18
+ end
19
+ end
20
+
21
+ module Runner
22
+ def run_callback(path="/", *args)
23
+ block = Nyoibo::Callback.callbacks[path]
24
+ block.call(*args)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,19 @@
1
+ module Nyoibo
2
+ module Configure
3
+ attr_accessor :config
4
+ def configure(&block)
5
+ @config = Config.new
6
+ @config.instance_exec(&block)
7
+ end
8
+ end
9
+
10
+ class Config
11
+ [:host, :port].each do |method|
12
+ module_eval <<-EOS, __FILE__, __LINE__
13
+ def #{method}(value = nil)
14
+ (value) ? (@#{method} = value) : @#{method}
15
+ end
16
+ EOS
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,58 @@
1
+ module Nyoibo
2
+ module Daemon
3
+ attr_reader :pid
4
+ CMD_QUIT = /^QUIT$/
5
+ CMD_JSON = /^JSON: /
6
+ TYPE_BASE64 = %r|^data:application/octet-stream;base64,|
7
+ def run
8
+ return if defined?(IRB)
9
+ daemon = lambda{
10
+ EventMachine::WebSocket.start(:host => config.host, :port => config.port) do |ws|
11
+ ws.onopen{
12
+ ws.send "OK Ready"
13
+ }
14
+ ws.onclose{
15
+ ws.send "OK Bye"
16
+ }
17
+ ws.onmessage{|msg|
18
+ @binary ||= ""
19
+ @binary_type ||= 'binary'
20
+ case msg
21
+ when CMD_QUIT
22
+ if @binary_type == 'base64'
23
+ @binary = Base64.decode64(@binary)
24
+ elsif @binary.encoding == Encoding::UTF_8
25
+ @binary = @binary.unpack('U*').pack('c*')
26
+ end
27
+ Nyoibo.run_callback(ws.request["path"], @json, @binary)
28
+ ws.close_connection
29
+ when CMD_JSON
30
+ msg.gsub!(CMD_JSON, '')
31
+ @json = JSON.parse(msg)
32
+ @json['size'] = @json['size'].to_i
33
+ ws.send("NEXT")
34
+ else
35
+
36
+ if msg =~ TYPE_BASE64
37
+ msg.gsub!(TYPE_BASE64, '')
38
+ @binary_type = 'base64'
39
+ end
40
+
41
+ if msg.length > 0
42
+ @binary << msg
43
+ ws.send("NEXT")
44
+ else
45
+ ws.send("EMPTY")
46
+ end
47
+ end
48
+ }
49
+ end
50
+ }
51
+ if ENV["NYOIBO_ENV"] == "test"
52
+ daemon.call
53
+ else
54
+ @pid = Process.fork &daemon
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,4 @@
1
+ module Nyoibo
2
+ class Rails < Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,8 @@
1
+ require "nyoibo"
2
+
3
+ class Nyoibo::Railtie < Rails::Railtie
4
+ config.after_initialize do
5
+ ENV["NYOIBO_ENV"] = Rails.env
6
+ Nyoibo.run
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ module Nyoibo
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "nyoibo/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "nyoibo"
7
+ s.version = Nyoibo::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["yalab"]
10
+ s.email = ["rudeboyjet@gmail.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{Websocket uploader with progressbar.}
13
+ s.description = %q{}
14
+ s.license = 'MIT'
15
+
16
+ s.rubyforge_project = "nyoibo"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+ s.add_dependency("em-websocket", "~>0.3.0")
23
+ s.add_dependency("json", "~>1.5.3")
24
+ s.add_development_dependency('em-http-request', '~> 0.2.6')
25
+ s.add_development_dependency('railties')
26
+ end
Binary file
@@ -0,0 +1,19 @@
1
+ require 'test/unit'
2
+ require 'socket'
3
+ require 'bundler'
4
+ ENV['BUNDLE_GEMFILE'] = File.expand_path("../../Gemfile", __FILE__)
5
+ require 'bundler/setup'
6
+ require 'shoulda/context'
7
+ require 'em-http'
8
+ require 'turn'
9
+
10
+ Dir.glob(File.expand_path("../../lib/**/*.rb", __FILE__)).each {|f| require f }
11
+
12
+ ENV["NYOIBO_ENV"] = "test"
13
+
14
+ Test::Unit::TestCase.module_eval do
15
+ def failed
16
+ EventMachine.stop
17
+ fail
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ require 'test_helper'
2
+ class Nyoibo::CallbackTest < Test::Unit::TestCase
3
+ class TestApp
4
+ include Nyoibo::Callback
5
+ uploaded "/" do
6
+ "uploaded!"
7
+ end
8
+ end
9
+ context "Run callback" do
10
+ setup do
11
+ @response = Nyoibo.run_callback("/")
12
+ end
13
+ should "fetch response" do
14
+ assert_equal "uploaded!", @response
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ require 'test_helper'
2
+ class Nyoibo::ConfigureTest < Test::Unit::TestCase
3
+ context ".configure" do
4
+ setup do
5
+ Nyoibo.configure do
6
+ host 'localhost'
7
+ port 3030
8
+ end
9
+ end
10
+ should "reflect config" do
11
+ assert_equal 'localhost', Nyoibo.config.host
12
+ assert_equal 3030, Nyoibo.config.port
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,60 @@
1
+ require 'test_helper'
2
+ class Nyoibo::DaemonTest < Test::Unit::TestCase
3
+ class TestApp < Test::Unit::TestCase
4
+ include Nyoibo::Callback
5
+ uploaded "/" do |json, binary|
6
+ File.open("/tmp/test.jpg", "w:binary"){|f|
7
+ f.write(binary)
8
+ }
9
+ raise "finame is not 'test.jpg'" if json["filename"] != "test.jpg"
10
+ raise "Binary size is not '3137' byte" if binary.length != 3137
11
+ end
12
+ end
13
+
14
+ context "run" do
15
+ setup do
16
+ @file = File.new(File.expand_path("../../fixtures/test.jpg", __FILE__), "rb")
17
+ Nyoibo.configure do
18
+ host "localhost"
19
+ port 3030
20
+ end
21
+ end
22
+
23
+ should "listen port" do
24
+ EM.run do
25
+ EventMachine.add_timer(0.1) do
26
+ http = EventMachine::HttpRequest.new('ws://localhost:3030/').get(:timeout => 0)
27
+ http.errback { failed }
28
+ @start = 0
29
+ @sendsize = 1024
30
+ http.stream{|msg|
31
+ case msg
32
+ when "OK Ready"
33
+ http.send("JSON: " + {:filename => File.basename(@file.path), :size => @file.size}.to_json)
34
+ when "NEXT"
35
+ @end = @start + @sendsize
36
+ @encoded ||= Base64.encode64(@file.read)
37
+
38
+ @end = @encoded.size - 1 if @end >= @encoded.size
39
+ if @start == @encoded.size
40
+ http.send("QUIT")
41
+ else
42
+ chunk = @encoded.slice(@start..@end)
43
+ if @start == 0
44
+ chunk = "data:application/octet-stream;base64," + chunk
45
+ end
46
+
47
+ http.send(chunk)
48
+ end
49
+ @start = @end + 1
50
+ end
51
+ }
52
+ http.disconnect{
53
+ EventMachine.stop
54
+ }
55
+ end
56
+ Nyoibo.run
57
+ end
58
+ end
59
+ end
60
+ end