VRFS-986 recent history sidebar for landing pages
This commit is contained in:
commit
aa056d53fd
|
|
@ -8,7 +8,7 @@ ActiveAdmin.register_page "Dashboard" do
|
|||
span "JamKazam Data Administration Portal"
|
||||
small ul do
|
||||
li "Admin users are users with the admin boolean set to true"
|
||||
li "Create/Edit JamKazam users using the 'Jam User' menu in header"
|
||||
li "Invite JamKazam users using the 'Users > Invite' menu in header"
|
||||
li "Admin users are created/deleted when toggling the 'admin' flag for JamKazam users"
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
ActiveAdmin.register JamRuby::IcecastAdminAuthentication, :as => 'Admin Authentication' do
|
||||
menu :parent => 'Icecast'
|
||||
end
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
ActiveAdmin.register_page "Bootstrap" do
|
||||
menu :parent => 'Icecast'
|
||||
|
||||
page_action :create_server, :method => :post do
|
||||
|
||||
template = IcecastTemplate.find(params[:jam_ruby_icecast_server][:template_id])
|
||||
hostname = params[:jam_ruby_icecast_server][:hostname]
|
||||
|
||||
server = IcecastServer.new
|
||||
server.template = template
|
||||
server.hostname = hostname
|
||||
server.server_id = hostname
|
||||
server.save!
|
||||
|
||||
redirect_to admin_bootstrap_path, :notice => "Server created. If you start job worker (bundle exec rake all_jobs), it should update your icecast config."
|
||||
end
|
||||
|
||||
page_action :brew_template, :method => :post do
|
||||
# to make this template, I just did 'brew install icecast', and then based the rest of this code on what I saw in /usr/local/etc/icecast.xml
|
||||
|
||||
|
||||
IcecastServer.transaction do
|
||||
|
||||
|
||||
limit = IcecastLimit.new
|
||||
limit.clients = 100
|
||||
limit.sources = 2
|
||||
limit.queue_size = 524288
|
||||
limit.client_timeout = 30
|
||||
limit.header_timeout = 15
|
||||
limit.source_timeout = 10
|
||||
limit.burst_size = 65535
|
||||
limit.save!
|
||||
|
||||
admin_auth = IcecastAdminAuthentication.new
|
||||
admin_auth.source_pass = 'blueberryjam'
|
||||
admin_auth.relay_user = 'jamjam'
|
||||
admin_auth.relay_pass = 'blueberryjam'
|
||||
admin_auth.admin_user = 'jamjam'
|
||||
admin_auth.admin_pass = 'blueberryjam'
|
||||
admin_auth.save!
|
||||
|
||||
path = IcecastPath.new
|
||||
path.base_dir = '/usr/local/Cellar/icecast/2.3.3/share/icecast'
|
||||
path.log_dir = '/usr/local/Cellar/icecast/2.3.3/var/log/icecast'
|
||||
path.web_root = '/usr/local/Cellar/icecast/2.3.3/share/icecast/web'
|
||||
path.admin_root = '/usr/local/Cellar/icecast/2.3.3/share/icecast/admin'
|
||||
path.pid_file = nil
|
||||
path.save!
|
||||
|
||||
security = IcecastSecurity.new
|
||||
security.chroot = false
|
||||
security.save!
|
||||
|
||||
logging = IcecastLogging.new
|
||||
logging.access_log = 'access.log'
|
||||
logging.error_log = 'error.log'
|
||||
logging.log_level = 3 # you might want to change this after creating the template
|
||||
logging.log_size = 10000
|
||||
logging.save!
|
||||
|
||||
listen_socket1 = IcecastListenSocket.new
|
||||
listen_socket1.port = 8000
|
||||
listen_socket1.save!
|
||||
|
||||
listen_socket2 = IcecastListenSocket.new
|
||||
listen_socket2.port = 8001
|
||||
listen_socket2.save!
|
||||
|
||||
template = IcecastTemplate.new
|
||||
template.name = "Brew-#{IcecastTemplate.count + 1}"
|
||||
template.location = '@work'
|
||||
template.admin_email = 'nobody@jamkazam.com'
|
||||
template.fileserve = true
|
||||
template.limit = limit
|
||||
template.admin_auth = admin_auth
|
||||
template.path = path
|
||||
template.security = security
|
||||
template.logging = logging
|
||||
template.listen_sockets = [listen_socket1, listen_socket2]
|
||||
template.save!
|
||||
end
|
||||
|
||||
|
||||
redirect_to admin_bootstrap_path, :notice => "Brew template created. Create a server now with that template specified."
|
||||
end
|
||||
|
||||
action_item do
|
||||
link_to "Create Brew Template", admin_bootstrap_brew_template_path, :method => :post
|
||||
end
|
||||
|
||||
content do
|
||||
|
||||
if IcecastTemplate.count == 0
|
||||
para "You need to create at least one template for your environment"
|
||||
else
|
||||
semantic_form_for IcecastServer.new, :url => admin_bootstrap_create_server_path, :builder => ActiveAdmin::FormBuilder do |f|
|
||||
f.inputs "New Server" do
|
||||
f.input :hostname
|
||||
f.input :template
|
||||
end
|
||||
f.actions
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
ActiveAdmin.register JamRuby::IcecastDirectory, :as => 'Directory' do
|
||||
menu :parent => 'Icecast'
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
ActiveAdmin.register JamRuby::IcecastLimit, :as => 'Limit' do
|
||||
menu :parent => 'Icecast'
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
ActiveAdmin.register JamRuby::IcecastListenSocket, :as => 'Listener' do
|
||||
menu :parent => 'Icecast'
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
ActiveAdmin.register JamRuby::IcecastLogging, :as => 'Logging' do
|
||||
menu :parent => 'Icecast'
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
ActiveAdmin.register JamRuby::IcecastMasterServerRelay, :as => 'Master Server Relay' do
|
||||
menu :parent => 'Icecast'
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
ActiveAdmin.register JamRuby::IcecastMount, :as => 'Mount' do
|
||||
menu :parent => 'Icecast'
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
ActiveAdmin.register JamRuby::IcecastPath, :as => 'Path' do
|
||||
menu :parent => 'Icecast'
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
ActiveAdmin.register JamRuby::IcecastRelay, :as => 'Relay' do
|
||||
menu :parent => 'Icecast'
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
ActiveAdmin.register JamRuby::IcecastSecurity, :as => 'Security' do
|
||||
menu :parent => 'Icecast'
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
ActiveAdmin.register JamRuby::IcecastServer, :as => 'Server' do
|
||||
menu :parent => 'Icecast'
|
||||
end
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
ActiveAdmin.register JamRuby::IcecastServerMount, :as => 'ServerMounts' do
|
||||
menu :parent => 'Icecast'
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
ActiveAdmin.register JamRuby::IcecastServerRelay, :as => 'ServerRelays' do
|
||||
menu :parent => 'Icecast'
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
ActiveAdmin.register JamRuby::IcecastServerSocket, :as => 'ServerListenSockets' do
|
||||
menu :parent => 'Icecast'
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
ActiveAdmin.register JamRuby::IcecastTemplate, :as => 'Template' do
|
||||
menu :parent => 'Icecast'
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
ActiveAdmin.register JamRuby::IcecastTemplateSocket, :as => 'TemplateListenSockets' do
|
||||
menu :parent => 'Icecast'
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
ActiveAdmin.register JamRuby::IcecastUserAuthentication, :as => 'User Authentication' do
|
||||
menu :parent => 'Icecast'
|
||||
end
|
||||
|
|
@ -22,7 +22,7 @@ cp ../pb/target/ruby/jampb/jampb-${GEM_VERSION}.gem vendor/cache/ || { echo "una
|
|||
cp ../ruby/jam_ruby-${GEM_VERSION}.gem vendor/cache/ || { echo "unable to copy jam-ruby gem"; exit 1; }
|
||||
|
||||
# put all dependencies into vendor/bundle
|
||||
rm -rf vendor/bundle
|
||||
#rm -rf vendor/bundle -- let jenkins config 'wipe workspace' decide this
|
||||
rm Gemfile.lock # if we don't want versions to float, pin it in the Gemfile, not count on Gemfile.lock
|
||||
bundle install --path vendor/bundle
|
||||
bundle update
|
||||
|
|
|
|||
|
|
@ -91,5 +91,15 @@ module JamAdmin
|
|||
config.action_controller.allow_forgery_protection = false
|
||||
|
||||
config.redis_host = "localhost:6379"
|
||||
|
||||
config.email_alerts_alias = 'alerts@jamkazam.com' # should be used for 'oh no' server down/service down sorts of emails
|
||||
config.email_generic_from = 'nobody@jamkazam.com'
|
||||
config.email_smtp_address = 'smtp.sendgrid.net'
|
||||
config.email_smtp_port = 587
|
||||
config.email_smtp_domain = 'www.jamkazam.com'
|
||||
config.email_smtp_authentication = :plain
|
||||
config.email_smtp_user_name = 'jamkazam'
|
||||
config.email_smtp_password = 'jamjamblueberryjam'
|
||||
config.email_smtp_starttls_auto = true
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,6 +6,11 @@ class Footer < ActiveAdmin::Component
|
|||
end
|
||||
end
|
||||
|
||||
module ActiveAdmin
|
||||
class BaseController
|
||||
with_role :admin
|
||||
end
|
||||
end
|
||||
|
||||
ActiveAdmin.setup do |config|
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
ActionMailer::Base.raise_delivery_errors = true
|
||||
ActionMailer::Base.delivery_method = Rails.env == "test" ? :test : :smtp
|
||||
ActionMailer::Base.smtp_settings = {
|
||||
:address => "smtp.sendgrid.net",
|
||||
:port => 587,
|
||||
:domain => "www.jamkazam.com",
|
||||
:authentication => :plain,
|
||||
:user_name => "jamkazam",
|
||||
:password => "jamjamblueberryjam",
|
||||
:enable_starttls_auto => true
|
||||
:address => Rails.application.config.email_smtp_address,
|
||||
:port => Rails.application.config.email_smtp_port,
|
||||
:domain => Rails.application.config.email_smtp_domain,
|
||||
:authentication => Rails.application.config.email_smtp_authentication,
|
||||
:user_name => Rails.application.config.email_smtp_user_name,
|
||||
:password => Rails.application.config.email_smtp_password ,
|
||||
:enable_starttls_auto => Rails.application.config.email_smtp_starttls_auto
|
||||
}
|
||||
2
db/build
2
db/build
|
|
@ -19,7 +19,7 @@ rm -rf $TARGET
|
|||
mkdir -p $PG_BUILD_OUT
|
||||
mkdir -p $PG_RUBY_PACKAGE_OUT
|
||||
|
||||
bundle update
|
||||
#bundle update
|
||||
|
||||
echo "building migrations"
|
||||
bundle exec pg_migrate build --source . --out $PG_BUILD_OUT --test --verbose
|
||||
|
|
|
|||
|
|
@ -88,4 +88,5 @@ icecast.sql
|
|||
home_page_promos.sql
|
||||
mix_job_watch.sql
|
||||
music_session_constraints.sql
|
||||
ms_recording_anonymous_likes.sql
|
||||
ms_recording_anonymous_likes.sql
|
||||
ms_user_history_add_instruments.sql
|
||||
|
|
@ -13,7 +13,7 @@ CREATE TABLE icecast_limits (
|
|||
queue_size INTEGER NOT NULL DEFAULT 102400,
|
||||
|
||||
-- does not appear to be used
|
||||
client_timeout INTEGER DEFAULT 10,
|
||||
client_timeout INTEGER DEFAULT 30,
|
||||
|
||||
-- The maximum time (in seconds) to wait for a request to come in once
|
||||
-- the client has made a connection to the server.
|
||||
|
|
@ -35,23 +35,23 @@ CREATE TABLE icecast_limits (
|
|||
);
|
||||
|
||||
|
||||
create table icecast_admin_authentications (
|
||||
CREATE TABLE icecast_admin_authentications (
|
||||
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
|
||||
|
||||
-- The unencrypted password used by sources to connect to icecast2.
|
||||
-- The default username for all source connections is 'source' but
|
||||
-- this option allows to specify a default password. This and the username
|
||||
-- The DEFAULT username for all source connections is 'source' but
|
||||
-- this option allows to specify a DEFAULT password. This and the username
|
||||
-- can be changed in the individual mount sections.
|
||||
source_password VARCHAR(64) NOT NULL DEFAULT 'icejam321',
|
||||
source_pass VARCHAR(64) NOT NULL,
|
||||
|
||||
-- Used in the master server as part of the authentication when a slave requests
|
||||
-- the list of streams to relay. The default username is 'relay'
|
||||
relay_user VARCHAR(64) NOT NULL DEFAULT 'relay',
|
||||
relay_password VARCHAR(64) NOT NULL DEFAULT 'jkrelayhack',
|
||||
-- the list of streams to relay. The DEFAULT username is 'relay'
|
||||
relay_user VARCHAR(64) NOT NULL,
|
||||
relay_pass VARCHAR(64) NOT NULL,
|
||||
|
||||
--The username/password used for all administration functions.
|
||||
admin_user VARCHAR(64) NOT NULL DEFAULT 'jkadmin',
|
||||
admin_password VARCHAR(64) NOT NULL DEFAULT 'jKadmin123',
|
||||
admin_user VARCHAR(64) NOT NULL,
|
||||
admin_pass VARCHAR(64) NOT NULL,
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
|
|
@ -60,249 +60,322 @@ create table icecast_admin_authentications (
|
|||
|
||||
--contains all the settings for listing a stream on any of the Icecast2 YP Directory servers.
|
||||
-- Multiple occurances of this section can be specified in order to be listed on multiple directory servers.
|
||||
create table icecast_directories (
|
||||
CREATE TABLE icecast_directories (
|
||||
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
|
||||
yp_url_timeout INTEGER not null default 15,
|
||||
yp_url VARCHAR(1024) not null UNIQUE default 'http://dir.xiph.org/cgi-bin/yp-cgi',
|
||||
yp_url_timeout INTEGER NOT NULL DEFAULT 15,
|
||||
yp_url VARCHAR(1024) NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
create table icecast_servermiscs (
|
||||
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
|
||||
-- This is the DNS name or IP address that will be used for the stream directory lookups or possibily
|
||||
-- the playlist generation if a Host header is not provided. While localhost is shown as an example,
|
||||
-- in fact you will want something that your listeners can use.
|
||||
hostname VARCHAR(256) not null default 'concertsvr.jamkazam.com',
|
||||
--This sets the location string for this icecast instance. It will be shown e.g in the web interface.
|
||||
location VARCHAR(128) not null default 'earth',
|
||||
--This should contain contact details for getting in touch with the server administrator.
|
||||
admin VARCHAR(128) not null default 'icemaster@localhost',
|
||||
-- This flag turns on the icecast2 fileserver from which static files can be served.
|
||||
-- All files are served relative to the path specified in the <paths><webroot> configuration
|
||||
-- setting. By default the setting is enabled so that requests for the images
|
||||
-- on the status page are retrievable.
|
||||
fileserve INTEGER not null default 1,
|
||||
-- This optional setting allows for the administrator of the server to override the
|
||||
-- default server identification. The default is icecast followed by a version number
|
||||
-- and most will not care to change it however this setting will change that.
|
||||
server_id VARCHAR(128) not null default 'icecast 2.3',
|
||||
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
create table icecast_listen_sockets (
|
||||
CREATE TABLE icecast_listen_sockets (
|
||||
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
|
||||
|
||||
-- The TCP port that will be used to accept client connections.
|
||||
port INTEGER not null default 8001,
|
||||
port INTEGER NOT NULL DEFAULT 8001,
|
||||
|
||||
-- An optional IP address that can be used to bind to a specific network card.
|
||||
-- If not supplied, then it will bind to all interfaces.
|
||||
bind_address VARCHAR(128),
|
||||
bind_address VARCHAR(1024),
|
||||
|
||||
shoutcast_mount VARCHAR(128) default NULL,
|
||||
shoutcast_compat INTEGER not null default 0,
|
||||
shoutcast_mount VARCHAR(1024),
|
||||
shoutcast_compat INTEGER,
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
|
||||
create table icecast_mastersvr_relays (
|
||||
CREATE TABLE icecast_relays (
|
||||
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
|
||||
|
||||
-- ip address of server we are relaying from and port number
|
||||
server VARCHAR(1024) NOT NULL,
|
||||
port INTEGER NOT NULL DEFAULT 8001,
|
||||
|
||||
-- mount at server. eg /example.ogg
|
||||
mount VARCHAR(1024) NOT NULL,
|
||||
-- eg /different.ogg
|
||||
local_mount VARCHAR(1024),
|
||||
-- eg joe. could be null
|
||||
relay_username VARCHAR(64),
|
||||
-- user password
|
||||
relay_pass VARCHAR(64),
|
||||
relay_shoutcast_metadata INTEGER DEFAULT 0,
|
||||
--- relay only if we have someone wanting to listen
|
||||
on_demand INTEGER DEFAULT 1,
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE UNLOGGED TABLE icecast_user_authentications(
|
||||
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
|
||||
--"htpasswd or url"
|
||||
-- real name is type
|
||||
authentication_type VARCHAR(16) DEFAULT 'url',
|
||||
-- these are for httpasswd
|
||||
filename VARCHAR(1024),
|
||||
allow_duplicate_users INTEGER,
|
||||
|
||||
-- these options are for url
|
||||
-- eg value="http://myauthserver.com/stream_start.php"
|
||||
mount_add VARCHAR(1024),
|
||||
--value="http://myauthserver.com/stream_end.php"
|
||||
mount_remove VARCHAR(1024),
|
||||
--value="http://myauthserver.com/listener_joined.php"
|
||||
listener_add VARCHAR(1024),
|
||||
--value="http://myauthserver.com/listener_left.php"
|
||||
listener_remove VARCHAR(1024),
|
||||
-- value="user"
|
||||
unused_username VARCHAR(64),
|
||||
-- value="pass"
|
||||
unused_pass VARCHAR(64),
|
||||
-- value="icecast-auth-user: 1"
|
||||
auth_header VARCHAR(64) DEFAULT 'icecast-auth-user: 1',
|
||||
-- value="icecast-auth-timelimit:"
|
||||
timelimit_header VARCHAR(64) DEFAULT 'icecast-auth-timelimit:',
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
|
||||
CREATE UNLOGGED TABLE icecast_mounts (
|
||||
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
|
||||
-- eg/example-complex.ogg
|
||||
name VARCHAR(1024) UNIQUE NOT NULL,
|
||||
source_username VARCHAR(64),
|
||||
source_pass VARCHAR(64),
|
||||
max_listeners INTEGER DEFAULT 4,
|
||||
max_listener_duration INTEGER DEFAULT 3600,
|
||||
-- dump of the stream coming through on this mountpoint.
|
||||
-- eg /tmp/dump-example1.ogg
|
||||
dump_file VARCHAR(1024),
|
||||
-- intro music to play
|
||||
-- This optional value specifies a mountpoint that clients are automatically moved to
|
||||
-- if the source shuts down or is not streaming at the time a listener connects.
|
||||
intro VARCHAR(1024),
|
||||
fallback_mount VARCHAR(1024),
|
||||
-- When enabled, this allows a connecting source client or relay on this mountpoint
|
||||
-- to move listening clients back from the fallback mount.
|
||||
fallback_override INTEGER DEFAULT 1,
|
||||
|
||||
-- When set to 1, this will cause new listeners, when the max listener count for the mountpoint
|
||||
-- has been reached, to move to the fallback mount if there is one specified.
|
||||
fallback_when_full INTEGER DEFAULT 1,
|
||||
|
||||
--For non-Ogg streams like MP3, the metadata that is inserted into the stream often
|
||||
-- has no defined character set.
|
||||
charset VARCHAR(1024) DEFAULT 'ISO8859-1',
|
||||
-- possible values are -1, 0, 1
|
||||
-- real name is public but this is reserved word in ruby
|
||||
is_public INTEGER DEFAULT 0,
|
||||
|
||||
stream_name VARCHAR(1024),
|
||||
stream_description VARCHAR(10000),
|
||||
-- direct to user page
|
||||
stream_url VARCHAR(1024),
|
||||
-- get this from the session info
|
||||
genre VARCHAR(256),
|
||||
bitrate INTEGER,
|
||||
-- real name is type but this is reserved name in ruby
|
||||
mime_type VARCHAR(64) NOT NULL DEFAULT 'audio/ogg' ,
|
||||
subtype VARCHAR(64) NOT NULL DEFAULT 'vorbis',
|
||||
|
||||
-- This optional setting allows for providing a burst size which overrides the
|
||||
-- DEFAULT burst size as defined in limits. The value is in bytes.
|
||||
burst_size INTEGER,
|
||||
mp3_metadata_interval INTEGER,
|
||||
|
||||
-- Enable this to prevent this mount from being shown on the xsl pages.
|
||||
-- This is mainly for cases where a local relay is configured and you do
|
||||
-- not want the source of the local relay to be shown
|
||||
hidden INTEGER DEFAULT 1,
|
||||
|
||||
--called when the source connects or disconnects. The scripts are called with the name of the mount
|
||||
on_connect VARCHAR(1024),
|
||||
on_disconnect VARCHAR(1024),
|
||||
|
||||
-- references icecast_user_authentications(id)
|
||||
authentication_id varchar(64) DEFAULT NULL,
|
||||
|
||||
------stats------
|
||||
listeners INTEGER NOT NULL DEFAULT 0,
|
||||
sourced BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE icecast_paths (
|
||||
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
|
||||
base_dir VARCHAR(1024) NOT NULL DEFAULT './',
|
||||
log_dir VARCHAR(1024) NOT NULL DEFAULT './logs',
|
||||
pid_file VARCHAR(1024) DEFAULT './icecast.pid',
|
||||
web_root VARCHAR(1024) NOT NULL DEFAULT './web',
|
||||
admin_root VARCHAR(1024) NOT NULL DEFAULT './admin',
|
||||
allow_ip VARCHAR(1024),
|
||||
deny_ip VARCHAR(1024),
|
||||
alias_source VARCHAR(1024),
|
||||
alias_dest VARCHAR(1024),
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE icecast_loggings (
|
||||
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
|
||||
access_log VARCHAR(1024) NOT NULL DEFAULT 'access.log',
|
||||
error_log VARCHAR(1024) NOT NULL DEFAULT 'error.log',
|
||||
playlist_log VARCHAR(1024),
|
||||
-- 4 Debug, 3 Info, 2 Warn, 1 Error
|
||||
log_level INTEGER NOT NULL DEFAULT 3 ,
|
||||
log_archive INTEGER,
|
||||
-- 10 meg log file by default
|
||||
log_size INTEGER DEFAULT 10000,
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE icecast_securities (
|
||||
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
|
||||
chroot INTEGER NOT NULL DEFAULT 0,
|
||||
change_owner_user VARCHAR(64),
|
||||
change_owner_group VARCHAR(64),
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE icecast_master_server_relays(
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
|
||||
-- ip address of the master icecast server and port number
|
||||
master_server VARCHAR(128) not null,
|
||||
master_server_port INTEGER not null,
|
||||
master_server VARCHAR(1024) NOT NULL,
|
||||
master_server_port INTEGER NOT NULL DEFAULT 8001,
|
||||
--The interval (in seconds) that the Relay Server will poll the Master Server for any new mountpoints to relay.
|
||||
master_update_interval INTEGER not null default 120,
|
||||
|
||||
master_update_interval INTEGER NOT NULL DEFAULT 120,
|
||||
-- This is the relay username on the master server. It is used to query the server for a list of
|
||||
-- mountpoints to relay. If not specified then 'relay' is used
|
||||
master_username VARCHAR(64) not null default 'relay',
|
||||
master_password VARCHAR(64) not null,
|
||||
master_username VARCHAR(64) NOT NULL,
|
||||
master_pass VARCHAR(64) NOT NULL,
|
||||
|
||||
--Global on-demand setting for relays. Because you do not have individual relay options when
|
||||
-- using a master server relay, you still may want those relays to only pull the stream when
|
||||
-- there is at least one listener on the slave. The typical case here is to avoid surplus
|
||||
-- bandwidth costs when no one is listening.
|
||||
relays_on_demand INTEGER default 0,
|
||||
relays_on_demand INTEGER NOT NULL DEFAULT 1,
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
--make sure this combo is unique
|
||||
--CONSTRAINT serverID UNIQUE KEY (master_server,master_server_port)
|
||||
);
|
||||
|
||||
create table icecast_relays (
|
||||
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
|
||||
|
||||
-- ip address of server we are relaying from and port number
|
||||
server VARCHAR(128) not null,
|
||||
port INTEGER not null default 8001,
|
||||
|
||||
-- mount at server. eg /example.ogg
|
||||
mount VARCHAR(128) not null,
|
||||
-- eg /different.ogg
|
||||
local_mount VARCHAR(128) not null,
|
||||
-- eg joe. could be null
|
||||
username VARCHAR(64) default NULL ,
|
||||
-- user password
|
||||
password VARCHAR(64) default null ,
|
||||
relay_shoutcast_metadata INTEGER default 0,
|
||||
--- relay only if we have someone wanting to listen
|
||||
on_demand INTEGER default 0,
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
create TABLE icecast_user_authentications(
|
||||
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
|
||||
--"htpasswd or url"
|
||||
-- real name is type
|
||||
stype VARCHAR(16) DEFAULT NULL ,
|
||||
-- these are for httpasswd
|
||||
filename VARCHAR(256) default NULL,
|
||||
allow_duplicate_users INTEGER DEFAULT 0,
|
||||
|
||||
-- these options are for url
|
||||
-- eg value="http://myauthserver.com/stream_start.php"
|
||||
mount_add VARCHAR(256) default NULL,
|
||||
--value="http://myauthserver.com/stream_end.php"
|
||||
mount_remove VARCHAR(256) default NULL,
|
||||
--value="http://myauthserver.com/listener_joined.php"
|
||||
listener_add VARCHAR(256) default NULL,
|
||||
--value="http://myauthserver.com/listener_left.php"
|
||||
listener_remove VARCHAR(256) default NULL,
|
||||
-- value="user"
|
||||
username VARCHAR(64) default NULL,
|
||||
-- value="pass"
|
||||
password VARCHAR(64) default NULL,
|
||||
-- value="icecast-auth-user: 1"
|
||||
auth_header VARCHAR(64) default NULL,
|
||||
-- value="icecast-auth-timelimit:"
|
||||
timelimit_header VARCHAR(64) default NULL,
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
|
||||
create table icecast_mounts (
|
||||
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
|
||||
-- eg/example-complex.ogg
|
||||
mount_name VARCHAR(128) UNIQUE NOT NULL,
|
||||
username VARCHAR(64) NOT NULL DEFAULT 'jamsource',
|
||||
password VARCHAR(64) NOT NULL DEFAULT 'jamksource',
|
||||
max_listeners INTEGER NOT NULL DEFAULT 4,
|
||||
max_listener_duration INTEGER NOT NULL DEFAULT 3600,
|
||||
-- dump of the stream coming through on this mountpoint.
|
||||
-- eg /tmp/dump-example1.ogg
|
||||
dump_file VARCHAR(256) DEFAULT NULL,
|
||||
|
||||
-- intro music to play
|
||||
-- This optional value specifies a mountpoint that clients are automatically moved to
|
||||
-- if the source shuts down or is not streaming at the time a listener connects.
|
||||
intro VARCHAR(256) NOT NULL DEFAULT '/intro.ogg',
|
||||
fallback_mount VARCHAR(256) NOT NULL DEFAULT '/sourcedown.ogg',
|
||||
-- When enabled, this allows a connecting source client or relay on this mountpoint
|
||||
-- to move listening clients back from the fallback mount.
|
||||
fallback_override INTEGER DEFAULT 1,
|
||||
|
||||
-- When set to 1, this will cause new listeners, when the max listener count for the mountpoint
|
||||
-- has been reached, to move to the fallback mount if there is one specified.
|
||||
fallback_when_full INTEGER DEFAULT 1,
|
||||
|
||||
--For non-Ogg streams like MP3, the metadata that is inserted into the stream often
|
||||
-- has no defined character set.
|
||||
charset VARCHAR(256) NOT NULL DEFAULT 'ISO8859-1',
|
||||
-- possilble values are -1, 0, 1
|
||||
-- real name is public but this is reserved word in ruby
|
||||
publicc INTEGER DEFAULT 1,
|
||||
|
||||
stream_name VARCHAR(256) NOT NULL DEFAULT 'My Jamkazam Audio Stream',
|
||||
stream_description VARCHAR(256) NOT NULL DEFAULT 'My JK audio description',
|
||||
-- direct to user page
|
||||
stream_url VARCHAR(256) NOT NULL DEFAULT 'http://wwww.jamakazam.com#user_id',
|
||||
-- get this from the session info
|
||||
genre VARCHAR(64) NOT NULL DEFAULT 'Unknown',
|
||||
bitrate integer NOT NULL default 92,
|
||||
-- real name is type but this is reserved name in ruby
|
||||
mtype VARCHAR(64) NOT NULL DEFAULT 'application/ogg' ,
|
||||
subtype VARCHAR(64) NOT NULL DEFAULT 'vorbis',
|
||||
-- Enable this to prevent this mount from being shown on the xsl pages.
|
||||
-- This is mainly for cases where a local relay is configured and you do
|
||||
-- not want the source of the local relay to be shown
|
||||
hidden INTEGER DEFAULT 1,
|
||||
|
||||
-- This optional setting allows for providing a burst size which overrides the
|
||||
-- default burst size as defined in limits. The value is in bytes.
|
||||
burst_size INTEGER DEFAULT 65536,
|
||||
mp3_metadata_interval INTEGER DEFAULT 4096,
|
||||
|
||||
--called when the source connects or disconnects. The scripts are called with the name of the mount
|
||||
on_connect VARCHAR(256) DEFAULT '/home/icecast/bin/source-start',
|
||||
on_disconnect VARCHAR(256) DEFAULT '/home/icecast/bin/source-end',
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
|
||||
create table icecast_paths (
|
||||
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
|
||||
basedir VARCHAR(256) NOT NULL DEFAULT './',
|
||||
logdir VARCHAR(256) NOT NULL DEFAULT './logs',
|
||||
pidfile VARCHAR(256) NOT NULL DEFAULT './icecast.pid',
|
||||
webroot VARCHAR(256) NOT NULL DEFAULT './web',
|
||||
adminroot VARCHAR(256) NOT NULL DEFAULT './admin',
|
||||
allow_ip VARCHAR(256) NOT NULL DEFAULT '/path/to/ip_allowlist',
|
||||
deny_ip VARCHAR(256) NOT NULL DEFAULT '/path_to_ip_denylist',
|
||||
--real name is alias but alias is reserved in ruby
|
||||
aliass VARCHAR(256) DEFAULT 'source="/foo" dest="/bar"',
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
|
||||
create table icecast_loggings (
|
||||
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
|
||||
accesslog VARCHAR(256) NOT NULL DEFAULT 'access.log',
|
||||
errorlog VARCHAR(256) NOT NULL DEFAULT 'error.log',
|
||||
playlistlog VARCHAR(256) NOT NULL DEFAULT 'playlist.log',
|
||||
-- 4 Debug, 3 Info, 2 Warn, 1 Error
|
||||
loglevel INTEGER NOT NULL DEFAULT 4 ,
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
|
||||
create table icecast_securities (
|
||||
id VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT uuid_generate_v4(),
|
||||
|
||||
chroot INTEGER NOT NULL DEFAULT 0,
|
||||
changeowner_user VARCHAR(64) DEFAULT 'nobody',
|
||||
changeowner_group VARCHAR(64) DEFAULT 'nogroup',
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
create TABLE icecast_servers(
|
||||
CREATE TABLE icecast_templates (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
icecast_limit_id VARCHAR(64) REFERENCES icecast_limits(id)
|
||||
|
||||
limit_id VARCHAR(64) REFERENCES icecast_limits(id),
|
||||
admin_auth_id VARCHAR(64) REFERENCES icecast_admin_authentications(id),
|
||||
directory_id VARCHAR(64) REFERENCES icecast_directories(id),
|
||||
master_relay_id VARCHAR(64) REFERENCES icecast_master_server_relays(id),
|
||||
path_id VARCHAR(64) REFERENCES icecast_paths(id),
|
||||
logging_id VARCHAR(64) REFERENCES icecast_loggings(id),
|
||||
security_id VARCHAR(64) REFERENCES icecast_securities(id),
|
||||
|
||||
location VARCHAR(1024) NOT NULL,
|
||||
name VARCHAR(256) NOT NULL,
|
||||
admin_email VARCHAR(1024) NOT NULL DEFAULT 'admin@jamkazam.com',
|
||||
fileserve INTEGER NOT NULL DEFAULT 1,
|
||||
|
||||
-- configs
|
||||
-- mounts
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE icecast_servers (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
--use this to mark the server configuration as needing to be regenerated
|
||||
config_changed INTEGER DEFAULT 0,
|
||||
limit_id VARCHAR(64) REFERENCES icecast_limits(id),
|
||||
admin_auth_id VARCHAR(64) REFERENCES icecast_admin_authentications(id),
|
||||
directory_id VARCHAR(64) REFERENCES icecast_directories(id),
|
||||
master_relay_id VARCHAR(64) REFERENCES icecast_master_server_relays(id),
|
||||
path_id VARCHAR(64) REFERENCES icecast_paths(id),
|
||||
logging_id VARCHAR(64) REFERENCES icecast_loggings(id),
|
||||
security_id VARCHAR(64) REFERENCES icecast_securities(id),
|
||||
template_id VARCHAR(64) NOT NULL REFERENCES icecast_templates(id),
|
||||
|
||||
-- This is the DNS name or IP address that will be used for the stream directory lookups or possibily
|
||||
-- the playlist generation if a Host header is not provided. While localhost is shown as an example,
|
||||
-- in fact you will want something that your listeners can use.
|
||||
hostname VARCHAR(1024) NOT NULL,
|
||||
server_id VARCHAR(1024) UNIQUE NOT NULL,
|
||||
--This sets the location string for this icecast instance. It will be shown e.g in the web interface.
|
||||
location VARCHAR(1024),
|
||||
--This should contain contact details for getting in touch with the server administrator.
|
||||
admin_email VARCHAR(1024),
|
||||
-- This flag turns on the icecast2 fileserver from which static files can be served.
|
||||
-- All files are served relative to the path specified in the <paths><webroot> configuration
|
||||
-- setting. By DEFAULT the setting is enabled so that requests for the images
|
||||
-- on the status page are retrievable.
|
||||
fileserve INTEGER,
|
||||
-- This optional setting allows for the administrator of the server to override the
|
||||
-- DEFAULT server identification. The DEFAULT is icecast followed by a version number
|
||||
-- and most will not care to change it however this setting will change that.
|
||||
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
|
||||
);
|
||||
|
||||
CREATE TABLE icecast_server_mounts (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
--REFERENCES icecast_mounts(id) ON DELETE CASCADE,
|
||||
icecast_mount_id VARCHAR(64),
|
||||
icecast_server_id VARCHAR(64) REFERENCES icecast_servers(id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
ALTER TABLE icecast_server_mounts ADD CONSTRAINT server_mount_uniqkey UNIQUE (icecast_mount_id, icecast_server_id);
|
||||
|
||||
CREATE TABLE icecast_server_relays (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
icecast_relay_id VARCHAR(64) REFERENCES icecast_relays(id) ON DELETE CASCADE,
|
||||
icecast_server_id VARCHAR(64) REFERENCES icecast_servers(id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
ALTER TABLE icecast_server_relays ADD CONSTRAINT server_relay_uniqkey UNIQUE (icecast_relay_id, icecast_server_id);
|
||||
|
||||
CREATE TABLE icecast_server_sockets (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
icecast_listen_socket_id VARCHAR(64) REFERENCES icecast_listen_sockets(id) ON DELETE CASCADE,
|
||||
icecast_server_id VARCHAR(64) REFERENCES icecast_servers(id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
ALTER TABLE icecast_server_sockets ADD CONSTRAINT server_socket_uniqkey UNIQUE (icecast_listen_socket_id, icecast_server_id);
|
||||
|
||||
CREATE TABLE icecast_template_sockets (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
icecast_listen_socket_id VARCHAR(64) REFERENCES icecast_listen_sockets(id) ON DELETE CASCADE,
|
||||
icecast_template_id VARCHAR(64) REFERENCES icecast_templates(id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
ALTER TABLE icecast_template_sockets ADD CONSTRAINT template_socket_uniqkey UNIQUE (icecast_listen_socket_id, icecast_template_id);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,129 @@
|
|||
-- this manifest update makes every table associated with music_sessions UNLOGGED
|
||||
|
||||
-- tables to mark UNLOGGED
|
||||
-- connections, fan_invitations, invitations, genres_music_sessions, join_requests, tracks, music_sessions
|
||||
|
||||
-- tables to just get rid of
|
||||
-- session_plays
|
||||
|
||||
-- breaking foreign keys for tables
|
||||
-- connections: user_id
|
||||
-- fan_invitations: receiver_id, sender_id
|
||||
-- music_session: user_id, band_id, claimed_recording_id, claimed_recording_initiator_id
|
||||
-- genres_music_sessions: genre_id
|
||||
-- invitations: sender_id, receiver_id
|
||||
-- fan_invitations: user_id
|
||||
-- notifications: invitation_id, join_request_id, session_id
|
||||
|
||||
DROP TABLE sessions_plays;
|
||||
|
||||
-- divorce notifications from UNLOGGED tables
|
||||
|
||||
-- NOTIFICATIONS
|
||||
----------------
|
||||
-- "notifications_session_id_fkey" FOREIGN KEY (session_id) REFERENCES music_sessions(id) ON DELETE CASCADE
|
||||
ALTER TABLE notifications DROP CONSTRAINT notifications_session_id_fkey;
|
||||
-- "notifications_join_request_id_fkey" FOREIGN KEY (join_request_id) REFERENCES join_requests(id) ON DELETE CASCADE
|
||||
ALTER TABLE notifications DROP CONSTRAINT notifications_join_request_id_fkey;
|
||||
-- "notifications_invitation_id_fkey" FOREIGN KEY (invitation_id) REFERENCES invitations(id) ON DELETE CASCADE
|
||||
ALTER TABLE notifications DROP CONSTRAINT notifications_invitation_id_fkey;
|
||||
|
||||
-- FAN_INVITATIONS
|
||||
------------------
|
||||
DROP TABLE fan_invitations;
|
||||
DROP TABLE invitations;
|
||||
DROP TABLE join_requests;
|
||||
DROP TABLE genres_music_sessions;
|
||||
DROP TABLE tracks;
|
||||
DROP TABLE connections;
|
||||
DROP TABLE music_sessions;
|
||||
|
||||
-- MUSIC_SESSIONS
|
||||
-----------------
|
||||
CREATE UNLOGGED TABLE music_sessions (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
|
||||
description VARCHAR(8000),
|
||||
user_id VARCHAR(64) NOT NULL,
|
||||
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
musician_access BOOLEAN NOT NULL,
|
||||
band_id VARCHAR(64),
|
||||
approval_required BOOLEAN NOT NULL,
|
||||
fan_access BOOLEAN NOT NULL,
|
||||
fan_chat BOOLEAN NOT NULL,
|
||||
claimed_recording_id VARCHAR(64),
|
||||
claimed_recording_initiator_id VARCHAR(64)
|
||||
);
|
||||
|
||||
-- CONNECTIONS
|
||||
--------------
|
||||
CREATE UNLOGGED TABLE connections (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
|
||||
user_id VARCHAR(64),
|
||||
client_id VARCHAR(64) UNIQUE NOT NULL,
|
||||
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
music_session_id VARCHAR(64),
|
||||
ip_address VARCHAR(64),
|
||||
as_musician BOOLEAN,
|
||||
aasm_state VARCHAR(64) DEFAULT 'idle'::VARCHAR NOT NULL
|
||||
);
|
||||
ALTER TABLE ONLY connections ADD CONSTRAINT connections_music_session_id_fkey FOREIGN KEY (music_session_id) REFERENCES music_sessions(id) ON DELETE SET NULL;
|
||||
|
||||
-- GENRES_MUSIC_SESSIONS
|
||||
------------------------
|
||||
CREATE UNLOGGED TABLE genres_music_sessions (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
|
||||
genre_id VARCHAR(64),
|
||||
music_session_id VARCHAR(64)
|
||||
);
|
||||
ALTER TABLE ONLY genres_music_sessions ADD CONSTRAINT genres_music_sessions_music_session_id_fkey FOREIGN KEY (music_session_id) REFERENCES music_sessions(id) ON DELETE CASCADE;
|
||||
|
||||
CREATE UNLOGGED TABLE fan_invitations (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
|
||||
sender_id VARCHAR(64),
|
||||
receiver_id VARCHAR(64),
|
||||
music_session_id VARCHAR(64),
|
||||
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
|
||||
);
|
||||
ALTER TABLE ONLY fan_invitations ADD CONSTRAINT fan_invitations_music_session_id_fkey FOREIGN KEY (music_session_id) REFERENCES music_sessions(id) ON DELETE CASCADE;
|
||||
|
||||
CREATE UNLOGGED TABLE join_requests (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
|
||||
user_id VARCHAR(64),
|
||||
music_session_id VARCHAR(64),
|
||||
text VARCHAR(2000),
|
||||
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
|
||||
);
|
||||
ALTER TABLE ONLY join_requests ADD CONSTRAINT user_music_session_uniqkey UNIQUE (user_id, music_session_id);
|
||||
ALTER TABLE ONLY join_requests ADD CONSTRAINT join_requests_music_session_id_fkey FOREIGN KEY (music_session_id) REFERENCES music_sessions(id) ON DELETE CASCADE;
|
||||
|
||||
-- INVITATIONS
|
||||
--------------
|
||||
CREATE UNLOGGED TABLE invitations (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
|
||||
sender_id VARCHAR(64),
|
||||
receiver_id VARCHAR(64),
|
||||
music_session_id VARCHAR(64),
|
||||
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
join_request_id VARCHAR(64)
|
||||
);
|
||||
ALTER TABLE ONLY invitations ADD CONSTRAINT invitations_uniqkey UNIQUE (sender_id, receiver_id, music_session_id);
|
||||
ALTER TABLE ONLY invitations ADD CONSTRAINT invitations_join_request_id_fkey FOREIGN KEY (join_request_id) REFERENCES join_requests(id) ON DELETE CASCADE;
|
||||
ALTER TABLE ONLY invitations ADD CONSTRAINT invitations_music_session_id_fkey FOREIGN KEY (music_session_id) REFERENCES music_sessions(id) ON DELETE CASCADE;
|
||||
|
||||
-- TRACKS
|
||||
---------
|
||||
CREATE UNLOGGED TABLE tracks (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
|
||||
connection_id VARCHAR(64),
|
||||
instrument_id VARCHAR(64),
|
||||
sound VARCHAR(64) NOT NULL,
|
||||
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
|
||||
client_track_id VARCHAR(64) NOT NULL
|
||||
);
|
||||
ALTER TABLE ONLY tracks ADD CONSTRAINT connections_tracks_connection_id_fkey FOREIGN KEY (connection_id) REFERENCES connections(id) ON DELETE CASCADE;
|
||||
|
|
@ -0,0 +1 @@
|
|||
alter table music_sessions_user_history add column instruments varchar(255);
|
||||
|
|
@ -51,6 +51,11 @@ message ClientMessage {
|
|||
|
||||
MUSICIAN_SESSION_FRESH = 240;
|
||||
MUSICIAN_SESSION_STALE = 245;
|
||||
|
||||
|
||||
// icecast notifications
|
||||
SOURCE_UP_REQUESTED = 250;
|
||||
SOURCE_DOWN_REQUESTED = 255;
|
||||
|
||||
TEST_SESSION_MESSAGE = 295;
|
||||
|
||||
|
|
@ -114,11 +119,13 @@ message ClientMessage {
|
|||
// band notifications
|
||||
optional BandInvitation band_invitation = 225;
|
||||
optional BandInvitationAccepted band_invitation_accepted = 230;
|
||||
optional BandSessionJoin band_session_join = 235;
|
||||
|
||||
|
||||
optional MusicianSessionFresh musician_session_fresh = 240;
|
||||
optional MusicianSessionStale musician_session_stale = 245;
|
||||
|
||||
|
||||
// icecast notifications
|
||||
optional SourceUpRequested source_up_requested = 250;
|
||||
optional SourceDownRequested source_down_requested = 255;
|
||||
|
||||
// Client-Session messages (to/from)
|
||||
optional TestSessionMessage test_session_message = 295;
|
||||
|
|
@ -327,9 +334,10 @@ message RecordingEnded {
|
|||
|
||||
message RecordingMasterMixComplete {
|
||||
optional string recording_id = 1;
|
||||
optional string msg = 2;
|
||||
optional string notification_id = 3;
|
||||
optional string created_at = 4;
|
||||
optional string band_id = 2;
|
||||
optional string msg = 3;
|
||||
optional string notification_id = 4;
|
||||
optional string created_at = 5;
|
||||
}
|
||||
|
||||
message DownloadAvailable {
|
||||
|
|
@ -371,6 +379,18 @@ message MusicianSessionStale {
|
|||
optional string photo_url = 4;
|
||||
}
|
||||
|
||||
message SourceUpRequested {
|
||||
optional string host = 1; // icecast server host
|
||||
optional int32 port = 2; // icecast server port
|
||||
optional string mount = 3; // mount name
|
||||
optional string source_user = 4; // source user
|
||||
optional string source_pass = 5; // source pass
|
||||
}
|
||||
|
||||
message SourceDownRequested {
|
||||
optional string mount = 1; // mount name
|
||||
}
|
||||
|
||||
// route_to: session
|
||||
// a test message used by ruby-client currently. just gives way to send out to rest of session
|
||||
message TestSessionMessage {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ gem 'resque'
|
|||
gem 'resque-retry'
|
||||
gem 'resque-failed-job-mailer' #, :path => "/Users/seth/workspace/resque_failed_job_mailer"
|
||||
gem 'oj'
|
||||
gem 'builder'
|
||||
|
||||
if devenv
|
||||
gem 'jam_db', :path=> "../db/target/ruby_package"
|
||||
|
|
|
|||
|
|
@ -28,8 +28,11 @@ require "jam_ruby/lib/module_overrides"
|
|||
require "jam_ruby/lib/s3_util"
|
||||
require "jam_ruby/lib/s3_manager"
|
||||
require "jam_ruby/lib/profanity"
|
||||
require "jam_ruby/lib/em_helper.rb"
|
||||
require "jam_ruby/resque/audiomixer"
|
||||
require "jam_ruby/resque/icecast_config_writer"
|
||||
require "jam_ruby/resque/scheduled/audiomixer_retry"
|
||||
require "jam_ruby/resque/scheduled/icecast_config_retry"
|
||||
require "jam_ruby/mq_router"
|
||||
require "jam_ruby/base_manager"
|
||||
require "jam_ruby/connection_manager"
|
||||
|
|
@ -98,14 +101,18 @@ require "jam_ruby/models/icecast_directory"
|
|||
require "jam_ruby/models/icecast_limit"
|
||||
require "jam_ruby/models/icecast_listen_socket"
|
||||
require "jam_ruby/models/icecast_logging"
|
||||
require "jam_ruby/models/icecast_mastersvr_relay"
|
||||
require "jam_ruby/models/icecast_master_server_relay"
|
||||
require "jam_ruby/models/icecast_mount"
|
||||
require "jam_ruby/models/icecast_path"
|
||||
require "jam_ruby/models/icecast_relay"
|
||||
require "jam_ruby/models/icecast_sercurity"
|
||||
require "jam_ruby/models/icecast_security"
|
||||
require "jam_ruby/models/icecast_server"
|
||||
require "jam_ruby/models/icecast_servermisc"
|
||||
require "jam_ruby/models/icecast_template"
|
||||
require "jam_ruby/models/icecast_user_authentication"
|
||||
require "jam_ruby/models/icecast_server_mount"
|
||||
require "jam_ruby/models/icecast_server_relay"
|
||||
require "jam_ruby/models/icecast_server_socket"
|
||||
require "jam_ruby/models/icecast_template_socket"
|
||||
|
||||
include Jampb
|
||||
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ SQL
|
|||
else
|
||||
blk.call(db_conn, connection) unless blk.nil?
|
||||
user.update_progression_field(:first_music_session_at)
|
||||
MusicSessionUserHistory.save(music_session_id, user_id, client_id)
|
||||
MusicSessionUserHistory.save(music_session_id, user_id, client_id, tracks)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,95 @@
|
|||
require 'amqp'
|
||||
require 'jam_ruby'
|
||||
|
||||
# Creates a connection to RabbitMQ
|
||||
|
||||
# On that single connection, a channel is created (which is a way to multiplex multiple queues/topics over the same TCP connection with rabbitmq)
|
||||
# Then connections to the client_exchange and user_exchange are made, and put into the MQRouter static variables
|
||||
# If this code completes (which implies that Rails can start to begin with, because this is in an initializer),
|
||||
# then the Rails app itself is free to send messages over these exchanges
|
||||
|
||||
# Also starts websocket-gateway
|
||||
module JamWebEventMachine
|
||||
|
||||
@@log = Logging.logger[JamWebEventMachine]
|
||||
|
||||
# starts amqp & eventmachine up first.
|
||||
# and then calls your block.
|
||||
# After the supplied block is done,
|
||||
# waits until all EM tasks scheduled in the supplied block are done, or timeout
|
||||
def self.run_wait_stop(timeout = 30, &blk)
|
||||
JamWebEventMachine.start
|
||||
|
||||
thread = Thread.current
|
||||
|
||||
blk.call
|
||||
|
||||
# put our thread wake up event on the EM scheduler,
|
||||
# meaning we go last (assuming that all EM tasks needed were scheduled in the blk)
|
||||
EM.schedule do
|
||||
thread.wakeup
|
||||
end
|
||||
|
||||
sleep timeout
|
||||
|
||||
EM.stop
|
||||
end
|
||||
|
||||
|
||||
def self.run_em
|
||||
|
||||
EM.run do
|
||||
# this is global because we need to check elsewhere if we are currently connected to amqp before signalling success with some APIs, such as 'create session'
|
||||
$amqp_connection_manager = AmqpConnectionManager.new(true, 4, :host => APP_CONFIG.rabbitmq_host, :port => APP_CONFIG.rabbitmq_port)
|
||||
$amqp_connection_manager.connect do |channel|
|
||||
|
||||
AMQP::Exchange.new(channel, :topic, "clients") do |exchange|
|
||||
@@log.debug("#{exchange.name} is ready to go")
|
||||
MQRouter.client_exchange = exchange
|
||||
end
|
||||
|
||||
AMQP::Exchange.new(channel, :topic, "users") do |exchange|
|
||||
@@log.debug("#{exchange.name} is ready to go")
|
||||
MQRouter.user_exchange = exchange
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.die_gracefully_on_signal
|
||||
@@log.debug("*** die_gracefully_on_signal")
|
||||
Signal.trap("INT") { EM.stop }
|
||||
Signal.trap("TERM") { EM.stop }
|
||||
end
|
||||
|
||||
def self.start
|
||||
if defined?(PhusionPassenger)
|
||||
@@log.debug("PhusionPassenger detected")
|
||||
|
||||
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
||||
# for passenger, we need to avoid orphaned threads
|
||||
if forked && EM.reactor_running?
|
||||
@@log.debug("stopping EventMachine")
|
||||
EM.stop
|
||||
end
|
||||
@@log.debug("starting EventMachine")
|
||||
Thread.new do
|
||||
run_em
|
||||
end
|
||||
die_gracefully_on_signal
|
||||
end
|
||||
elsif defined?(Unicorn)
|
||||
@@log.debug("Unicorn detected--do nothing at initializer phase")
|
||||
else
|
||||
@@log.debug("Development environment detected")
|
||||
Thread.abort_on_exception = true
|
||||
|
||||
# create a new thread separate from the Rails main thread that EventMachine can run on
|
||||
Thread.new do
|
||||
run_em
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
|
@ -19,7 +19,7 @@ module JamRuby
|
|||
|
||||
# given a string (bytes) payload, return a client message
|
||||
def parse_client_msg(payload)
|
||||
return Jampb::ClientMessage.parse(payload)
|
||||
Jampb::ClientMessage.parse(payload)
|
||||
end
|
||||
|
||||
# create a login message using user/pass
|
||||
|
|
@ -30,7 +30,7 @@ module JamRuby
|
|||
:client_id => options[:client_id]
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::LOGIN,
|
||||
:route_to => SERVER_TARGET,
|
||||
:login => login
|
||||
|
|
@ -44,7 +44,7 @@ module JamRuby
|
|||
:client_id => options[:client_id]
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::LOGIN,
|
||||
:route_to => SERVER_TARGET,
|
||||
:login => login
|
||||
|
|
@ -63,7 +63,7 @@ module JamRuby
|
|||
:user_id => user_id
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::LOGIN_ACK,
|
||||
:route_to => CLIENT_TARGET,
|
||||
:login_ack => login_ack
|
||||
|
|
@ -73,7 +73,7 @@ module JamRuby
|
|||
def download_available
|
||||
download_available = Jampb::DownloadAvailable.new
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::DOWNLOAD_AVAILABLE,
|
||||
:route_to => CLIENT_TARGET,
|
||||
:download_available => download_available
|
||||
|
|
@ -84,7 +84,7 @@ module JamRuby
|
|||
def login_music_session(music_session)
|
||||
login_music_session = Jampb::LoginMusicSession.new(:music_session => music_session)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::LOGIN_MUSIC_SESSION,
|
||||
:route_to => SERVER_TARGET,
|
||||
:login_music_session => login_music_session
|
||||
|
|
@ -95,7 +95,7 @@ module JamRuby
|
|||
def login_music_session_ack(error, error_reason)
|
||||
login_music_session_ack = Jampb::LoginMusicSessionAck.new(:error => error, :error_reason => error_reason)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::LOGIN_MUSIC_SESSION_ACK,
|
||||
:route_to => CLIENT_TARGET,
|
||||
:login_music_session_ack => login_music_session_ack
|
||||
|
|
@ -106,7 +106,7 @@ module JamRuby
|
|||
def leave_music_session(music_session)
|
||||
leave_music_session = Jampb::LeaveMusicSession.new(:music_session => music_session)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::LEAVE_MUSIC_SESSION,
|
||||
:route_to => SERVER_TARGET,
|
||||
:leave_music_session => leave_music_session
|
||||
|
|
@ -117,7 +117,7 @@ module JamRuby
|
|||
def leave_music_session_ack(error, error_reason)
|
||||
leave_music_session_ack = Jampb::LeaveMusicSessionAck.new(:error => error, :error_reason => error_reason)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::LEAVE_MUSIC_SESSION_ACK,
|
||||
:route_to => CLIENT_TARGET,
|
||||
:leave_music_session_ack => leave_music_session_ack
|
||||
|
|
@ -128,7 +128,7 @@ module JamRuby
|
|||
def heartbeat()
|
||||
heartbeat = Jampb::Heartbeat.new
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::HEARTBEAT,
|
||||
:route_to => SERVER_TARGET,
|
||||
:heartbeat => heartbeat
|
||||
|
|
@ -139,7 +139,7 @@ module JamRuby
|
|||
def heartbeat_ack()
|
||||
heartbeat_ack = Jampb::HeartbeatAck.new
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::HEARTBEAT_ACK,
|
||||
:route_to => CLIENT_TARGET,
|
||||
:heartbeat_ack => heartbeat_ack
|
||||
|
|
@ -150,7 +150,7 @@ module JamRuby
|
|||
def server_bad_state_recovered(original_message_id)
|
||||
recovered = Jampb::ServerBadStateRecovered.new()
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::SERVER_BAD_STATE_RECOVERED,
|
||||
:route_to => CLIENT_TARGET,
|
||||
:server_bad_state_recovered => recovered,
|
||||
|
|
@ -162,7 +162,7 @@ module JamRuby
|
|||
def server_generic_error(error_msg)
|
||||
error = Jampb::ServerGenericError.new(:error_msg => error_msg)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::SERVER_GENERIC_ERROR,
|
||||
:route_to => CLIENT_TARGET,
|
||||
:server_generic_error => error
|
||||
|
|
@ -173,7 +173,7 @@ module JamRuby
|
|||
def server_rejection_error(error_msg)
|
||||
error = Jampb::ServerRejectionError.new(:error_msg => error_msg)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::SERVER_REJECTION_ERROR,
|
||||
:route_to => CLIENT_TARGET,
|
||||
:server_rejection_error => error
|
||||
|
|
@ -184,7 +184,7 @@ module JamRuby
|
|||
def server_permission_error(original_message_id, error_msg)
|
||||
error = Jampb::ServerPermissionError.new(:error_msg => error_msg)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::SERVER_PERMISSION_ERROR,
|
||||
:route_to => CLIENT_TARGET,
|
||||
:server_permission_error => error,
|
||||
|
|
@ -196,7 +196,7 @@ module JamRuby
|
|||
def server_bad_state_error(original_message_id, error_msg)
|
||||
error = Jampb::ServerBadStateError.new(:error_msg => error_msg)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::SERVER_BAD_STATE_ERROR,
|
||||
:route_to => CLIENT_TARGET,
|
||||
:server_bad_state_error => error,
|
||||
|
|
@ -215,7 +215,7 @@ module JamRuby
|
|||
:msg => msg
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::FRIEND_UPDATE,
|
||||
:route_to => USER_TARGET_PREFIX + user_id,
|
||||
:friend_update => friend
|
||||
|
|
@ -232,7 +232,7 @@ module JamRuby
|
|||
:created_at => created_at
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::FRIEND_REQUEST,
|
||||
:route_to => USER_TARGET_PREFIX + receiver_id,
|
||||
:friend_request => friend_request
|
||||
|
|
@ -248,7 +248,7 @@ module JamRuby
|
|||
:created_at => created_at
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::FRIEND_REQUEST_ACCEPTED,
|
||||
:route_to => USER_TARGET_PREFIX + receiver_id,
|
||||
:friend_request_accepted => friend_request_accepted
|
||||
|
|
@ -263,7 +263,7 @@ module JamRuby
|
|||
:created_at => created_at
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::NEW_USER_FOLLOWER,
|
||||
:route_to => USER_TARGET_PREFIX + receiver_id,
|
||||
:new_user_follower => new_user_follower
|
||||
|
|
@ -278,7 +278,7 @@ module JamRuby
|
|||
:created_at => created_at
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::NEW_BAND_FOLLOWER,
|
||||
:route_to => USER_TARGET_PREFIX + receiver_id,
|
||||
:new_band_follower => new_band_follower
|
||||
|
|
@ -293,7 +293,7 @@ module JamRuby
|
|||
:created_at => created_at
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::SESSION_INVITATION,
|
||||
:route_to => USER_TARGET_PREFIX + receiver_id,
|
||||
:session_invitation => session_invitation
|
||||
|
|
@ -311,7 +311,7 @@ module JamRuby
|
|||
:created_at => created_at
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::JOIN_REQUEST,
|
||||
:route_to => SESSION_TARGET_PREFIX + session_id,
|
||||
:join_request => req
|
||||
|
|
@ -329,7 +329,7 @@ module JamRuby
|
|||
:created_at => created_at
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::JOIN_REQUEST_APPROVED,
|
||||
:route_to => SESSION_TARGET_PREFIX + session_id,
|
||||
:join_request_approved => req_approved
|
||||
|
|
@ -347,7 +347,7 @@ module JamRuby
|
|||
:created_at => created_at
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::JOIN_REQUEST_REJECTED,
|
||||
:route_to => SESSION_TARGET_PREFIX + session_id,
|
||||
:join_request_rejected => req_rejected
|
||||
|
|
@ -361,7 +361,7 @@ module JamRuby
|
|||
:msg => msg
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::SESSION_JOIN,
|
||||
:route_to => CLIENT_TARGET,
|
||||
:session_join => join
|
||||
|
|
@ -376,7 +376,7 @@ module JamRuby
|
|||
:recording_id => recording_id
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::SESSION_DEPART,
|
||||
:route_to => CLIENT_TARGET,
|
||||
:session_depart => left
|
||||
|
|
@ -392,7 +392,7 @@ module JamRuby
|
|||
:created_at => created_at
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::MUSICIAN_SESSION_JOIN,
|
||||
:route_to => USER_TARGET_PREFIX + receiver_id,
|
||||
:musician_session_join => musician_session_join
|
||||
|
|
@ -408,7 +408,7 @@ module JamRuby
|
|||
:created_at => created_at
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::BAND_SESSION_JOIN,
|
||||
:route_to => USER_TARGET_PREFIX + receiver_id,
|
||||
:band_session_join => band_session_join
|
||||
|
|
@ -424,7 +424,7 @@ module JamRuby
|
|||
:created_at => created_at
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::MUSICIAN_RECORDING_SAVED,
|
||||
:route_to => USER_TARGET_PREFIX + receiver_id,
|
||||
:musician_recording_saved => musician_recording_saved
|
||||
|
|
@ -440,7 +440,7 @@ module JamRuby
|
|||
:created_at => created_at
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::BAND_RECORDING_SAVED,
|
||||
:route_to => USER_TARGET_PREFIX + receiver_id,
|
||||
:band_recording_saved => band_recording_saved
|
||||
|
|
@ -453,7 +453,7 @@ module JamRuby
|
|||
:msg => msg
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::RECORDING_STARTED,
|
||||
:route_to => USER_TARGET_PREFIX + receiver_id,
|
||||
:recording_started => recording_started
|
||||
|
|
@ -466,14 +466,27 @@ module JamRuby
|
|||
:msg => msg
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::RECORDING_ENDED,
|
||||
:route_to => USER_TARGET_PREFIX + receiver_id,
|
||||
:recording_ended => recording_ended
|
||||
)
|
||||
end
|
||||
|
||||
def recording_master_mix_complete
|
||||
def recording_master_mix_complete(receiver_id, recording_id, band_id, msg, notification_id, created_at)
|
||||
recording_master_mix_complete = Jampb::RecordingMasterMixComplete.new(
|
||||
:recording_id => recording_id,
|
||||
:band_id => band_id,
|
||||
:msg => msg,
|
||||
:notification_id => notification_id,
|
||||
:created_at => created_at
|
||||
)
|
||||
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::RECORDING_MASTER_MIX_COMPLETE,
|
||||
:route_to => USER_TARGET_PREFIX + receiver_id,
|
||||
:recording_master_mix_complete => recording_master_mix_complete
|
||||
)
|
||||
end
|
||||
|
||||
# create a band invitation message
|
||||
|
|
@ -487,7 +500,7 @@ module JamRuby
|
|||
:created_at => created_at
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::BAND_INVITATION,
|
||||
:route_to => USER_TARGET_PREFIX + receiver_id,
|
||||
:band_invitation => band_invitation
|
||||
|
|
@ -504,7 +517,7 @@ module JamRuby
|
|||
:created_at => created_at
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::BAND_INVITATION_ACCEPTED,
|
||||
:route_to => USER_TARGET_PREFIX + receiver_id,
|
||||
:band_invitation_accepted => band_invitation_accepted
|
||||
|
|
@ -520,7 +533,7 @@ module JamRuby
|
|||
:photo_url => photo_url
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::MUSICIAN_SESSION_FRESH,
|
||||
:route_to => CLIENT_TARGET,
|
||||
:musician_session_fresh => fresh
|
||||
|
|
@ -536,18 +549,45 @@ module JamRuby
|
|||
:photo_url => photo_url
|
||||
)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::MUSICIAN_SESSION_STALE,
|
||||
:route_to => CLIENT_TARGET,
|
||||
:musician_session_stale => stale
|
||||
)
|
||||
end
|
||||
|
||||
# create a source up requested message to send to clients in a session,
|
||||
# so that one of the clients will start sending source audio to icecast
|
||||
def source_up_requested (session_id, host, port, mount, source_user, source_pass)
|
||||
source_up_requested = Jampb::SourceUpRequested.new(
|
||||
host: host,
|
||||
port: port,
|
||||
mount: mount,
|
||||
source_user: source_user,
|
||||
source_pass: source_pass)
|
||||
|
||||
Jampb::ClientMessage.new(
|
||||
type: ClientMessage::Type::SOURCE_UP_REQUESTED,
|
||||
route_to: SESSION_TARGET_PREFIX + session_id,
|
||||
source_up_requested: source_up_requested)
|
||||
end
|
||||
|
||||
# create a source up requested message to send to clients in a session,
|
||||
# so that one of the clients will start sending source audio to icecast
|
||||
def source_down_requested (session_id, mount)
|
||||
source_down_requested = Jampb::SourceDownRequested.new(mount: mount)
|
||||
|
||||
Jampb::ClientMessage.new(
|
||||
type: ClientMessage::Type::SOURCE_DOWN_REQUESTED,
|
||||
route_to: SESSION_TARGET_PREFIX + session_id,
|
||||
source_down_requested: source_down_requested)
|
||||
end
|
||||
|
||||
# create a test message to send in session
|
||||
def test_session_message(session_id, msg)
|
||||
test = Jampb::TestSessionMessage.new(:msg => msg)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::TEST_SESSION_MESSAGE,
|
||||
:route_to => SESSION_TARGET_PREFIX + session_id,
|
||||
:test_session_message => test
|
||||
|
|
@ -560,7 +600,7 @@ module JamRuby
|
|||
def ping_request(client_id, from)
|
||||
ping_request = Jampb::PingRequest.new()
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::PING_REQUEST,
|
||||
:route_to => CLIENT_TARGET_PREFIX + client_id,
|
||||
:from => from,
|
||||
|
|
@ -572,7 +612,7 @@ module JamRuby
|
|||
def ping_ack(client_id, from)
|
||||
ping_ack = Jampb::PingAck.new
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::PING_ACK,
|
||||
:route_to => CLIENT_TARGET_PREFIX + client_id,
|
||||
:from => from,
|
||||
|
|
@ -584,7 +624,7 @@ module JamRuby
|
|||
def test_client_message(client_id, from, msg)
|
||||
test = Jampb::TestClientMessage.new(:msg => msg)
|
||||
|
||||
return Jampb::ClientMessage.new(
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::TEST_CLIENT_MESSAGE,
|
||||
:route_to => CLIENT_TARGET_PREFIX + client_id,
|
||||
:from => from,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ module JamRuby
|
|||
validates :biography, no_profanity: true
|
||||
|
||||
before_save :check_lat_lng
|
||||
before_save :check_website_url
|
||||
|
||||
# musicians
|
||||
has_many :band_musicians, :class_name => "JamRuby::BandMusician"
|
||||
|
|
@ -61,6 +62,13 @@ module JamRuby
|
|||
return self.music_sessions.size
|
||||
end
|
||||
|
||||
def recent_history
|
||||
recordings = ClaimedRecording.joins(:recordings).where(:recordings => {:band_id => "#{self.id}"}).limit(10)
|
||||
msh = MusicSessionHistory.where(:band_id => self.id).limit(10)
|
||||
recordings.concat(msh)
|
||||
recordings.sort! {|a,b| b.created_at <=> a.created_at}.first(5)
|
||||
end
|
||||
|
||||
def location
|
||||
loc = self.city.blank? ? '' : self.city
|
||||
loc = loc.blank? ? self.state : "#{loc}, #{self.state}" unless self.state.blank?
|
||||
|
|
@ -111,23 +119,6 @@ module JamRuby
|
|||
return recordings
|
||||
end
|
||||
|
||||
def self.search(query, options = { :limit => 10 })
|
||||
|
||||
# only issue search if at least 2 characters are specified
|
||||
if query.nil? || query.length < 2
|
||||
return []
|
||||
end
|
||||
|
||||
# create 'anded' statement
|
||||
query = Search.create_tsquery(query)
|
||||
|
||||
if query.nil? || query.length == 0
|
||||
return []
|
||||
end
|
||||
|
||||
return Band.where("name_tsv @@ to_tsquery('jamenglish', ?)", query).limit(options[:limit])
|
||||
end
|
||||
|
||||
# helper method for creating / updating a Band
|
||||
def self.save(id, name, website, biography, city, state, country, genres, user_id, photo_url, logo_url)
|
||||
user = User.find(user_id)
|
||||
|
|
@ -254,6 +245,14 @@ module JamRuby
|
|||
false
|
||||
end
|
||||
|
||||
def check_website_url
|
||||
if website_changed? && self.website.present?
|
||||
self.website.strip!
|
||||
self.website = "http://#{self.website}" unless self.website =~ /^http/
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
def self.validate_genres(genres, is_nil_ok)
|
||||
if is_nil_ok && genres.nil?
|
||||
|
|
|
|||
|
|
@ -1,73 +1,37 @@
|
|||
|
||||
module JSONable
|
||||
def jdumpXml (ovb, nm, ident=1, output=$stdout)
|
||||
|
||||
serialized = Hash.new
|
||||
ovb.myattr_accessor.each do |attribute|
|
||||
#serialized[attribute] = ovb[attribute]
|
||||
puts "attribute = #{attribute}"
|
||||
#serialized[attribute] = self.public_send attribute
|
||||
end
|
||||
|
||||
hash = serialized
|
||||
|
||||
tb = "\t"
|
||||
tbs = tb * ident
|
||||
tbse = tb * (ident-1)
|
||||
|
||||
output.puts "#{tbse}<#{nm}>"
|
||||
hash.each do |key, val|
|
||||
#puts "attrib: key=#{key} val=#{val}"
|
||||
|
||||
el = key
|
||||
if key.present?
|
||||
el = key.gsub(/_/, '-')
|
||||
end
|
||||
|
||||
|
||||
sv = val
|
||||
if val.to_s.empty?
|
||||
#skip ???
|
||||
else
|
||||
if val.instance_of? String
|
||||
#encode the string to be xml safe
|
||||
sv = CGI.escapeHTML(val)
|
||||
end
|
||||
end
|
||||
output.puts "#{tbs}<#{el}>#{sv}</#{el}>"
|
||||
end
|
||||
puts "#{tbse}</#{nm}>"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
module JamRuby
|
||||
class IcecastAdminAuthentication < ActiveRecord::Base
|
||||
include JSONable
|
||||
|
||||
attr_accessible :source_password, :relay_user, :relay_password, :admin_user, :admin_password
|
||||
#myattr_accessor = [:source_password, :relay_user, :relay_password, :admin_user, :admin_password ]
|
||||
attr_accessible :source_pass, :relay_user, :relay_pass, :admin_user, :admin_pass, as: :admin
|
||||
|
||||
after_initialize :init
|
||||
has_many :servers, :class_name => "JamRuby::IcecastServer", :inverse_of => :admin_auth, :foreign_key => "admin_auth_id"
|
||||
has_many :templates, :class_name => "JamRuby::IcecastTemplate", :inverse_of => :admin_auth, :foreign_key => "admin_auth_id"
|
||||
|
||||
protected
|
||||
def init
|
||||
#set only if nil
|
||||
self.source_password ||= "UndefinedSourcePassword"
|
||||
self.admin_password ||= "JKAminPw"
|
||||
validates :source_pass, presence: true, length: {minimum: 5}
|
||||
validates :admin_pass, presence: true, length: {minimum: 5}
|
||||
validates :relay_user, presence: true, length: {minimum: 5}
|
||||
validates :relay_pass, presence: true, length: {minimum: 5}
|
||||
validates :admin_user, presence: true, length: {minimum: 5}
|
||||
|
||||
after_save :poke_config
|
||||
|
||||
def poke_config
|
||||
IcecastServer.update(servers, config_changed: 1)
|
||||
templates.each { |template| IcecastServer.update(template.servers, config_changed: 1) }
|
||||
end
|
||||
|
||||
public
|
||||
self.primary_key = 'id'
|
||||
|
||||
validates :source_password, presence: true, length: {minimum: 5}
|
||||
validates :admin_password, presence: true, length: {minimum: 5}
|
||||
|
||||
def dumpXml (ident=1, output=$stdout)
|
||||
self.jdumpXml(self,"authentication", ident,output)
|
||||
def to_s
|
||||
"admin_user=#{admin_user} relay_user=#{relay_user}"
|
||||
end
|
||||
|
||||
def dumpXml (builder)
|
||||
|
||||
builder.tag! 'authentication' do |auth|
|
||||
auth.tag! 'source-password', source_pass
|
||||
auth.tag! 'admin-user', admin_user
|
||||
auth.tag! 'relay-user', relay_user
|
||||
auth.tag! 'relay-password', relay_pass
|
||||
auth.tag! 'admin-password', admin_pass
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,10 +1,31 @@
|
|||
module JamRuby
|
||||
class IcecastDirectory < ActiveRecord::Base
|
||||
|
||||
self.primary_key = 'id'
|
||||
attr_accessible :yp_url_timeout, :yp_url, as: :admin
|
||||
|
||||
attr_accessible :yp_url_timeout, :yp_url
|
||||
attr_accessor :yp_url_timeout, :yp_url
|
||||
has_many :servers, :class_name => "JamRuby::IcecastServer", :inverse_of => :directory, :foreign_key => "directory_id"
|
||||
has_many :templates, :class_name => "JamRuby::IcecastTemplate", :inverse_of => :directory, :foreign_key => "directory_id"
|
||||
|
||||
validates :yp_url_timeout, presence: true, numericality: {only_integer: true}, length: {in: 1..30}
|
||||
validates :yp_url, presence: true
|
||||
|
||||
after_save :poke_config
|
||||
|
||||
def poke_config
|
||||
IcecastServer.update(servers, config_changed: 1)
|
||||
templates.each { |template| IcecastServer.update(template.servers, config_changed: 1) }
|
||||
end
|
||||
|
||||
def to_s
|
||||
yp_url
|
||||
end
|
||||
|
||||
def dumpXml (builder)
|
||||
|
||||
builder.tag! 'directory' do |dir|
|
||||
dir.tag! 'yp-url-timeout', yp_url_timeout
|
||||
dir.tag! 'yp-url', yp_url
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,34 +1,44 @@
|
|||
module JamRuby
|
||||
class IcecastLimit < ActiveRecord::Base
|
||||
include JSONable
|
||||
|
||||
self.primary_key = 'id'
|
||||
attr_accessible :clients, :sources, :queue_size, :client_timeout, :header_timeout, :source_timeout, :burst_size,
|
||||
as: :admin
|
||||
|
||||
attr_accessible :clients, :sources, :queue_size, :client_timeout, :header_timeout, :source_timeout, :burst_size
|
||||
#attr_accessor :clients, :sources, :queue_size, :client_timeout, :header_timeout, :source_timeout, :burst_size
|
||||
has_many :servers, class_name: 'JamRuby::IcecastServer', inverse_of: :limit, foreign_key: 'limit_id'
|
||||
has_many :templates, class_name: 'JamRuby::IcecastTemplate', inverse_of: :limit, foreign_key: 'limit_id'
|
||||
|
||||
#validates :clients, numericality: {only_integer: true}, length: {in: 1..15000}
|
||||
validates :clients, numericality: {only_integer: true}
|
||||
validates :clients, presence: true, numericality: {only_integer: true}, length: {in: 1..15000}
|
||||
validates :sources, presence: true, numericality: {only_integer: true}, length: {in:1..10000}
|
||||
validates :queue_size, presence: true, numericality: {only_integer: true}
|
||||
validates :client_timeout, presence: true, numericality: {only_integer: true}
|
||||
validates :header_timeout, presence: true, numericality: {only_integer: true}
|
||||
validates :source_timeout, presence: true, numericality: {only_integer: true}
|
||||
validates :burst_size, presence: true, numericality: {only_integer: true}
|
||||
|
||||
after_initialize :init
|
||||
after_save :poke_config
|
||||
|
||||
|
||||
def init
|
||||
self.clients ||= 10000
|
||||
self.sources ||= 1000
|
||||
self.queue_size ||= 102400
|
||||
self.client_timeout ||= 30
|
||||
self.header_timeout ||= 15
|
||||
self.source_timeout ||= 10
|
||||
self.burst_size ||= 65536
|
||||
def poke_config
|
||||
IcecastServer.update(servers, config_changed: 1)
|
||||
templates.each { |template| IcecastServer.update(template.servers, config_changed: 1) }
|
||||
end
|
||||
|
||||
def setclients(val)
|
||||
@clients = val
|
||||
def to_s
|
||||
"clients=#{clients} sources=#{sources}"
|
||||
end
|
||||
def dumpXml (ident=1, output=$stdout)
|
||||
self.jdumpXml(self, "limits", ident, output)
|
||||
|
||||
def dumpXml (builder)
|
||||
|
||||
builder.tag! 'limits' do |limits|
|
||||
limits.tag! 'clients', clients
|
||||
limits.tag! 'sources', sources
|
||||
limits.tag! 'queue-size', queue_size
|
||||
limits.tag! 'client-timeout', client_timeout
|
||||
limits.tag! 'header-timeout', header_timeout
|
||||
limits.tag! 'source-timeout', source_timeout
|
||||
limits.tag! 'burst-on-connect', 1
|
||||
limits.tag! 'burst-size', burst_size
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,15 +1,35 @@
|
|||
module JamRuby
|
||||
class IcecastListenSocket < ActiveRecord::Base
|
||||
|
||||
self.primary_key = 'id'
|
||||
attr_accessible :port, :bind_address, :shoutcast_mount, :shoutcast_compat, as: :admin
|
||||
|
||||
attr_accessible :port, :bind_address, :shoutcast_mount, :shoutcast_compat
|
||||
attr_accessor :port, :bind_address, :shoutcast_mount, :shoutcast_compat
|
||||
has_many :server_sockets, :class_name => "JamRuby::IcecastServerSocket", :inverse_of => :socket, :foreign_key => 'icecast_listen_socket_id'
|
||||
has_many :servers, :class_name => "JamRuby::IcecastServer", :through => :server_sockets
|
||||
|
||||
def dumpXml()
|
||||
has_many :template_sockets, :class_name => "JamRuby::IcecastTemplateSocket", :inverse_of => :socket, :foreign_key => 'icecast_listen_socket_id'
|
||||
has_many :templates, :class_name => "JamRuby::IcecastTemplate", :through => :template_sockets
|
||||
|
||||
validates :port, presence: true, numericality: {only_integer: true}, length: {in: 1..65535}
|
||||
validates :shoutcast_compat, :inclusion => {:in => [nil, 0, 1]}
|
||||
|
||||
after_save :poke_config
|
||||
|
||||
def poke_config
|
||||
IcecastServer.update(servers, config_changed: 1)
|
||||
templates.each { |template| IcecastServer.update(template.servers, config_changed: 1) }
|
||||
end
|
||||
|
||||
def to_s
|
||||
"port=#{port} bind_address=#{bind_address}"
|
||||
end
|
||||
|
||||
def dumpXml (builder)
|
||||
builder.tag! 'listen-socket' do |listen|
|
||||
listen.tag! 'port', port
|
||||
listen.tag! 'bind-address', bind_address if !bind_address.nil? && !bind_address.empty?
|
||||
listen.tag! 'shoutcast-mount', shoutcast_mount if shoutcast_mount
|
||||
listen.tag! 'shoutcast-compat', shoutcast_compat if shoutcast_compat
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,14 +1,36 @@
|
|||
module JamRuby
|
||||
class IcecastLogging < ActiveRecord::Base
|
||||
|
||||
self.primary_key = 'id'
|
||||
attr_accessible :access_log, :error_log, :playlist_log, :log_level, :log_archive, :log_size, as: :admin
|
||||
|
||||
attr_accessible :accesslog, :errorlog, :playlistlog, :loglevel
|
||||
attr_accessor :accesslog, :errorlog, :playlistlog, :loglevel
|
||||
has_many :servers, :class_name => "JamRuby::IcecastServer", :inverse_of => :logging, :foreign_key => "logging_id"
|
||||
has_many :templates, :class_name => "JamRuby::IcecastTemplate", :inverse_of => :logging, :foreign_key => "logging_id"
|
||||
|
||||
def dumpXml()
|
||||
validates :access_log, presence: true
|
||||
validates :error_log, presence: true
|
||||
validates :log_level, :inclusion => {:in => [1, 2, 3, 4]}
|
||||
validates :log_archive, :inclusion => {:in => [nil, 0, 1]}
|
||||
validates :log_size, numericality: {only_integer: true}, if: lambda {|m| m.log_size.present?}
|
||||
|
||||
after_save :poke_config
|
||||
|
||||
def poke_config
|
||||
IcecastServer.update(servers, config_changed: 1)
|
||||
templates.each { |template| IcecastServer.update(template.servers, config_changed: 1) }
|
||||
end
|
||||
|
||||
def to_s
|
||||
"access_log=#{access_log} error_log=#{error_log} log_level=#{log_level}"
|
||||
end
|
||||
def dumpXml(builder)
|
||||
builder.tag! 'logging' do |log|
|
||||
log.tag! 'accesslog', access_log
|
||||
log.tag! 'errorlog', error_log
|
||||
log.tag! 'playlistlog', playlist_log if !playlist_log.nil? && !playlist_log.empty?
|
||||
log.tag! 'logsize', log_size if log_size
|
||||
log.tag! 'logarchive', log_archive if log_archive
|
||||
log.tag! 'loglevel', log_level
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
module JamRuby
|
||||
class IcecastMasterServerRelay < ActiveRecord::Base
|
||||
|
||||
attr_accessible :master_server, :master_server_port, :master_update_interval, :master_username, :master_pass,
|
||||
:relays_on_demand, as: :admin
|
||||
|
||||
has_many :servers, :class_name => "JamRuby::IcecastServer", :inverse_of => :master_relay, :foreign_key => "master_relay_id"
|
||||
has_many :templates, :class_name => "JamRuby::IcecastTemplate", :inverse_of => :master_relay, :foreign_key => "master_relay_id"
|
||||
|
||||
validates :master_server, presence: true, length: {minimum: 1}
|
||||
validates :master_server_port, presence: true, numericality: {only_integer: true}, length: {in: 1..65535}
|
||||
validates :master_update_interval, presence: true, numericality: {only_integer: true}, length: {in: 1..1200}
|
||||
validates :master_username, presence: true, length: {minimum: 5}
|
||||
validates :master_pass, presence: true, length: {minimum: 5}
|
||||
validates :relays_on_demand, :inclusion => {:in => [0, 1]}
|
||||
|
||||
after_save :poke_config
|
||||
|
||||
def poke_config
|
||||
IcecastServer.update(servers, config_changed: 1)
|
||||
templates.each { |template| IcecastServer.update(template.servers, config_changed: 1) }
|
||||
end
|
||||
|
||||
def to_s
|
||||
"master_server=#{master_server} master_server_port=#{master_server_port} master_username=#{master_username}"
|
||||
end
|
||||
|
||||
def dumpXml(builder)
|
||||
builder.tag! 'master-server', master_server
|
||||
builder.tag! 'master-server-port', master_server_port
|
||||
builder.tag! 'master-update-interval', master_update_interval
|
||||
builder.tag! 'master-username', master_username
|
||||
builder.tag! 'master-password', master_pass
|
||||
builder.tag! 'relays-on-demand', relays_on_demand
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
module JamRuby
|
||||
class IcecastMastersvrRelay < ActiveRecord::Base
|
||||
|
||||
self.primary_key = 'id'
|
||||
attr_accessible :master_server, :master_server_port, :master_username, :master_password, :relays_on_demand
|
||||
attr_accessible :master_server, :master_server_port, :master_username, :master_password, :relays_on_demand
|
||||
|
||||
def dumpXml()
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,24 +1,121 @@
|
|||
module JamRuby
|
||||
class IcecastMount < ActiveRecord::Base
|
||||
|
||||
self.primary_key = 'id'
|
||||
attr_accessible :authentication_id, :name, :source_username, :source_pass, :max_listeners, :max_listener_duration,
|
||||
:dump_file, :intro, :fallback_mount, :fallback_override, :fallback_when_full, :charset, :is_public,
|
||||
:stream_name, :stream_description, :stream_url, :genre, :bitrate, :mime_type, :subtype, :burst_size,
|
||||
:mp3_metadata_interval, :hidden, :on_connect, :on_disconnect, as: :admin
|
||||
|
||||
attr_accessible :mount_name, :username, :password, :max_listeners, :max_listener_duration, :dump_file
|
||||
attr_accessor :mount_name, :username, :password, :max_listeners, :max_listener_duration, :dump_file
|
||||
belongs_to :authentication, class_name: "JamRuby::IcecastUserAuthentication", inverse_of: :mount, :foreign_key => 'authentication_id'
|
||||
|
||||
attr_accessible :intro, :fallback_mount, :fallback_override, :fallback_when_full, :charset
|
||||
attr_accessor :intro, :fallback_mount, :fallback_override, :fallback_when_full, :charset
|
||||
has_many :server_mounts, :class_name => "JamRuby::IcecastServerMount", :inverse_of => :mount, :foreign_key => 'icecast_mount_id'
|
||||
has_many :servers, :class_name => "JamRuby::IcecastServer", :through => :server_mounts, :source => :server
|
||||
|
||||
attr_accessible :publicc, :stream_name, :stream_description, :stream_url, :genre, :bitrate
|
||||
attr_accessor :publicc, :stream_name, :stream_description, :stream_url, :genre, :bitrate
|
||||
validates :name, presence: true
|
||||
validates :source_username, length: {minimum: 5}, if: lambda {|m| m.source_username.present?}
|
||||
validates :source_pass, length: {minimum: 5}, if: lambda {|m| m.source_pass.present?}
|
||||
validates :max_listeners, length: {in: 1..15000}, if: lambda {|m| m.max_listeners.present?}
|
||||
validates :max_listener_duration, length: {in: 1..3600 * 48}, if: lambda {|m| m.max_listener_duration.present?}
|
||||
validates :fallback_override, :inclusion => {:in => [0, 1]} , if: lambda {|m| m.fallback_mount.present?}
|
||||
validates :fallback_when_full, :inclusion => {:in => [0, 1]} , if: lambda {|m| m.fallback_mount.present?}
|
||||
validates :is_public, presence: true, :inclusion => {:in => [-1, 0, 1]}
|
||||
validates :stream_name, presence: true
|
||||
validates :stream_description, presence: true
|
||||
validates :stream_url, presence: true
|
||||
validates :genre, presence: true
|
||||
validates :bitrate, numericality: {only_integer: true}, if: lambda {|m| m.bitrate.present?}
|
||||
validates :mime_type, presence: true
|
||||
validates :subtype, presence: true
|
||||
validates :burst_size, numericality: {only_integer: true}, if: lambda {|m| m.burst_size.present?}
|
||||
validates :mp3_metadata_interval, numericality: {only_integer: true}, if: lambda {|m| m.mp3_metadata_interval.present?}
|
||||
validates :hidden, :inclusion => {:in => [0, 1]}
|
||||
validate :name_has_correct_format
|
||||
|
||||
attr_accessible :mtype, :subtype, :hidden, :burst_size, :mp3_metadata_interval, :on_connect, :on_disconnect
|
||||
attr_accessor :mtype, :subtype, :hidden, :burst_size, :mp3_metadata_interval, :on_connect, :on_disconnect
|
||||
before_save :sanitize_active_admin
|
||||
after_save :after_save
|
||||
after_commit :after_commit
|
||||
|
||||
has_one :authentication, :class_name => "IcecastUserAuthentication"
|
||||
def name_has_correct_format
|
||||
errors.add(:name, "must start with /") unless name && name.start_with?('/')
|
||||
end
|
||||
|
||||
def dumpXml()
|
||||
def after_save
|
||||
IcecastServer.update(servers, config_changed: 1)
|
||||
|
||||
# transiting to sourced from not sourced
|
||||
if !sourced_was && sourced
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def sanitize_active_admin
|
||||
self.authentication_id = nil if self.authentication_id == ''
|
||||
end
|
||||
|
||||
def source_up
|
||||
with_lock do
|
||||
self.sourced = true
|
||||
self.save(:validate => false)
|
||||
end
|
||||
end
|
||||
|
||||
def source_down
|
||||
with_lock do
|
||||
sourced = false
|
||||
save(:validate => false)
|
||||
end
|
||||
end
|
||||
|
||||
def listener_add
|
||||
with_lock do
|
||||
increment!(:listeners)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def listener_remove
|
||||
with_lock do
|
||||
decrement!(:listeners)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def dumpXml(builder)
|
||||
builder.tag! 'mount' do |mount|
|
||||
mount.tag! 'mount-name', name
|
||||
mount.tag! 'username', source_username if !source_username.nil? && !source_username.empty?
|
||||
mount.tag! 'password', source_pass if !source_pass.nil? && !source_pass.empty?
|
||||
mount.tag! 'max-listeners', max_listeners unless max_listeners.nil?
|
||||
mount.tag! 'max-listener-duration', max_listener_duration unless max_listener_duration.nil?
|
||||
mount.tag! 'dump-file', dump_file if !dump_file.nil? && !dump_file.empty?
|
||||
mount.tag! 'intro', intro if !intro.nil? && !intro.empty?
|
||||
mount.tag! 'fallback-mount', fallback_mount if !fallback_mount.nil? && !fallback_mount.empty?
|
||||
mount.tag! 'fallback-override', fallback_override if fallback_override
|
||||
mount.tag! 'fallback-when-full', fallback_when_full if fallback_when_full
|
||||
mount.tag! 'charset', charset if charset
|
||||
mount.tag! 'public', is_public
|
||||
mount.tag! 'stream-name', stream_name if !stream_name.nil? && !stream_name.empty?
|
||||
mount.tag! 'stream-description', stream_description if !stream_description.nil? && !stream_description.empty?
|
||||
mount.tag! 'stream-url', stream_url if !stream_url.nil? && !stream_url.empty?
|
||||
mount.tag! 'genre', genre unless genre.empty?
|
||||
mount.tag! 'bitrate', bitrate if bitrate
|
||||
mount.tag! 'type', mime_type
|
||||
mount.tag! 'subtype', subtype
|
||||
mount.tag! 'burst-size', burst_size if burst_size
|
||||
mount.tag! 'mp3-metadata-interval', mp3_metadata_interval unless mp3_metadata_interval.nil?
|
||||
mount.tag! 'hidden', hidden
|
||||
mount.tag! 'on-connect', on_connect if on_connect
|
||||
mount.tag! 'on-disconnect', on_disconnect if on_disconnect
|
||||
|
||||
authentication.dumpXml(builder) if authentication
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def get_media_url
|
||||
raise "Unassociated server to mount" if self.server_mount.nil?
|
||||
|
||||
"http://" + server_mount.server.hostname + self.name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,14 +1,40 @@
|
|||
module JamRuby
|
||||
class IcecastPath < ActiveRecord::Base
|
||||
|
||||
self.primary_key = 'id'
|
||||
attr_accessible :base_dir, :log_dir, :pid_file, :web_root, :admin_root, :allow_ip, :deny_ip, :alias_source,
|
||||
:alias_dest, as: :admin
|
||||
|
||||
attr_accessible :basedir, :logdir, :pidfile, :webroot, :adminroot, :allow_ip, :deny_ip, :aliass
|
||||
attr_accessor :basedir, :logdir, :pidfile, :webroot, :adminroot, :allow_ip, :deny_ip, :aliass
|
||||
has_many :servers, :class_name => "JamRuby::IcecastServer", :inverse_of => :path, :foreign_key => "path_id"
|
||||
has_many :templates, :class_name => "JamRuby::IcecastTemplate", :inverse_of => :path, :foreign_key => "path_id"
|
||||
|
||||
def dumpXml()
|
||||
validates :base_dir, presence: true
|
||||
validates :log_dir, presence: true
|
||||
validates :web_root, presence: true
|
||||
validates :admin_root, presence: true
|
||||
|
||||
after_save :poke_config
|
||||
|
||||
def poke_config
|
||||
IcecastServer.update(servers, config_changed: 1)
|
||||
templates.each { |template| IcecastServer.update(template.servers, config_changed: 1) }
|
||||
end
|
||||
|
||||
def to_s
|
||||
"base_dir=#{base_dir}"
|
||||
end
|
||||
|
||||
def dumpXml (builder)
|
||||
|
||||
builder.tag! 'paths' do |paths|
|
||||
paths.tag! 'basedir', base_dir
|
||||
paths.tag! 'logdir', log_dir
|
||||
paths.tag! 'pidfile', pid_file if !pid_file.nil? && !pid_file.empty?
|
||||
paths.tag! 'webroot', web_root
|
||||
paths.tag! 'adminroot', admin_root
|
||||
paths.tag! 'allow-ip', allow_ip if allow_ip
|
||||
paths.tag! 'deny-ip', deny_ip if deny_ip
|
||||
paths.tag! 'alias', :source => alias_source, :dest => alias_dest if !alias_source.nil? && !alias_source.empty?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,14 +1,39 @@
|
|||
module JamRuby
|
||||
class IcecastRelay < ActiveRecord::Base
|
||||
|
||||
self.primary_key = 'id'
|
||||
attr_accessible :server, :port, :mount, :local_mount, :relay_username, :relay_pass, :relay_shoutcast_metadata, :on_demand,
|
||||
as: :admin
|
||||
|
||||
attr_accessible :server, :port, :mount, :local_mount, :username, :password, :relay_shoutcast_metadata, :on_demand
|
||||
attr_accessor :server, :port, :mount, :local_mount, :username, :password, :relay_shoutcast_metadata, :on_demand
|
||||
has_many :server_relays, :class_name => "JamRuby::IcecastServerRelay"
|
||||
has_many :servers, :class_name => "JamRuby::IcecastServer", :through => :server_relays, :source => :server
|
||||
|
||||
def dumpXml()
|
||||
validates :port, presence: true, numericality: {only_integer: true}, length: {in: 1..65535}
|
||||
validates :mount, presence: true
|
||||
validates :server, presence: true
|
||||
validates :relay_shoutcast_metadata, :inclusion => {:in => [0, 1]}
|
||||
validates :on_demand, presence: true, :inclusion => {:in => [0, 1]}
|
||||
|
||||
after_save :poke_config
|
||||
|
||||
def poke_config
|
||||
IcecastServer.update(servers, :config_changed => true)
|
||||
end
|
||||
|
||||
def to_s
|
||||
mount
|
||||
end
|
||||
|
||||
def dumpXml (builder)
|
||||
builder.tag! 'relay' do |listen|
|
||||
listen.tag! 'server', server
|
||||
listen.tag! 'port', port
|
||||
listen.tag! 'mount', mount
|
||||
listen.tag! 'local-mount', local_mount if !local_mount.nil? && !local_mount.empty?
|
||||
listen.tag! 'username', relay_username if !relay_username.nil? && !relay_username.empty?
|
||||
listen.tag! 'password', relay_pass if !relay_pass.nil? && !pasword.empty?
|
||||
listen.tag! 'relay-shoutcast-metadata', relay_shoutcast_metadata
|
||||
listen.tag! 'on-demand', on_demand
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
module JamRuby
|
||||
class IcecastSecurity < ActiveRecord::Base
|
||||
|
||||
attr_accessible :chroot, :change_owner_user, :change_owner_group, as: :admin
|
||||
|
||||
has_many :servers, :class_name => "JamRuby::IcecastServer", :inverse_of => :security, :foreign_key => "security_id"
|
||||
has_many :templates, :class_name => "JamRuby::IcecastTemplate", :inverse_of => :security, :foreign_key => "security_id"
|
||||
|
||||
validates :chroot, :inclusion => {:in => [0, 1]}
|
||||
|
||||
after_save :poke_config
|
||||
|
||||
def poke_config
|
||||
IcecastServer.update(servers, config_changed: 1)
|
||||
templates.each { |template| IcecastServer.update(template.servers, config_changed: 1) }
|
||||
end
|
||||
|
||||
def to_s
|
||||
"chroot=#{chroot} change_owner_user=#{change_owner_user} change_owner_group=#{change_owner_group}"
|
||||
end
|
||||
|
||||
def dumpXml(builder)
|
||||
builder.tag! 'security' do |security|
|
||||
security.tag! 'chroot', chroot
|
||||
if change_owner_user
|
||||
security.tag! 'changeowner' do
|
||||
security.tag! 'user', change_owner_user
|
||||
security.tag! 'group', change_owner_group
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
module JamRuby
|
||||
class IcecastSecurity < ActiveRecord::Base
|
||||
|
||||
self.primary_key = 'id'
|
||||
|
||||
attr_accessible :chroot, :changeowner_user, :changeowner_group
|
||||
attr_accessor :chroot, :changeowner_user, :changeowner_group
|
||||
|
||||
def dumpXml()
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -1,23 +1,124 @@
|
|||
module JamRuby
|
||||
class IcecastServer < ActiveRecord::Base
|
||||
|
||||
self.primary_key = 'id'
|
||||
attr_accessor :skip_config_changed_flag
|
||||
|
||||
has_one :limit, :class_name => "JamRuby::IcecastLimit"
|
||||
has_one :adminauth, :class_name => "JamRuby::IcecastAdminAuthentication"
|
||||
has_one :directory, :class_name => "JamRuby::IcecastDirectory"
|
||||
has_one :misc, :class_name => "JamRuby::IcecastServermisc"
|
||||
has_many :listen_sockets, :class_name => "JamRuby::IcecastListenSocket"
|
||||
has_one :master_relay, :class_name => "JamRuby::IcecastMastersvrRelay"
|
||||
has_one :relay, :class_name => "JamRuby::IcecastRelay"
|
||||
has_many :mounts, :class_name => "JamRuby::IcecastMount"
|
||||
has_one :path, :class_name => "JamRuby::IcecastPath"
|
||||
has_one :logging, :class_name => "JamRuby::IcecastLogging"
|
||||
has_one :security, :class_name => "JamRuby::IceCastSecurity"
|
||||
attr_accessible :template_id, :limit_id, :admin_auth_id, :directory_id, :master_relay_id, :path_id, :logging_id,
|
||||
:security_id, :config_changed, :hostname, :location, :admin_email, :fileserve, as: :admin
|
||||
|
||||
def dumpXml()
|
||||
belongs_to :template, :class_name => "JamRuby::IcecastTemplate", foreign_key: 'template_id', :inverse_of => :servers
|
||||
|
||||
# all are overrides, because the template defines all of these as well. When building the XML, we will prefer these if set
|
||||
belongs_to :limit, :class_name => "JamRuby::IcecastLimit", foreign_key: 'limit_id', :inverse_of => :servers
|
||||
belongs_to :admin_auth, :class_name => "JamRuby::IcecastAdminAuthentication", foreign_key: 'admin_auth_id', :inverse_of => :servers
|
||||
belongs_to :directory, :class_name => "JamRuby::IcecastDirectory", foreign_key: 'directory_id', :inverse_of => :servers
|
||||
belongs_to :master_relay, :class_name => "JamRuby::IcecastMasterServerRelay", foreign_key: 'master_relay_id', :inverse_of => :servers
|
||||
belongs_to :path, :class_name => "JamRuby::IcecastPath", foreign_key: 'path_id', :inverse_of => :servers
|
||||
belongs_to :logging, :class_name => "JamRuby::IcecastLogging", foreign_key: 'logging_id', :inverse_of => :servers
|
||||
belongs_to :security, :class_name => "JamRuby::IcecastSecurity", foreign_key: 'security_id', :inverse_of => :servers
|
||||
has_many :listen_socket_servers, :class_name => "JamRuby::IcecastServerSocket", :inverse_of => :server
|
||||
has_many :listen_sockets, :class_name => "JamRuby::IcecastListenSocket", :through => :listen_socket_servers, :source => :socket
|
||||
|
||||
# mounts and relays are naturally server-specific, though
|
||||
has_many :server_mounts, :class_name => "JamRuby::IcecastServerMount", :inverse_of => :server
|
||||
has_many :mounts, :class_name => "JamRuby::IcecastMount", :through => :server_mounts, :source => :mount
|
||||
|
||||
has_many :server_relays, :class_name => "JamRuby::IcecastServerRelay", :inverse_of => :relay
|
||||
has_many :relays, :class_name => "JamRuby::IcecastRelay", :through => :server_relays, :source => :relay
|
||||
|
||||
validates :config_changed, :inclusion => {:in => [0, 1]}
|
||||
validates :hostname, presence: true
|
||||
validates :fileserve, :inclusion => {:in => [0, 1]}, :if => lambda {|s| s.fileserve.present? }
|
||||
validates :server_id, presence: true
|
||||
|
||||
validates :template, presence: true
|
||||
|
||||
before_save :before_save, unless: lambda { skip_config_changed_flag }
|
||||
before_save :sanitize_active_admin
|
||||
after_save :after_save
|
||||
|
||||
def before_save
|
||||
self.config_changed = 1
|
||||
end
|
||||
|
||||
def sanitize_active_admin
|
||||
self.template_id = nil if self.template_id == ''
|
||||
self.limit_id = nil if self.limit_id == ''
|
||||
self.admin_auth_id = nil if self.admin_auth_id == ''
|
||||
self.directory_id = nil if self.directory_id == ''
|
||||
self.master_relay_id = nil if self.master_relay_id == ''
|
||||
self.path_id = nil if self.path_id == ''
|
||||
self.logging_id = nil if self.logging_id == ''
|
||||
self.security_id = nil if self.security_id == ''
|
||||
end
|
||||
|
||||
def after_save
|
||||
# if we set config_changed, then queue up a job
|
||||
if config_changed_was == 0 && config_changed == 1
|
||||
IcecastConfigWriter.enqueue(self.server_id)
|
||||
end
|
||||
end
|
||||
|
||||
# this method is the correct way to set config_changed to false
|
||||
# if you don't do it this way, then likely you'll get into a loop
|
||||
# config_changed = true, enqueued job, job executes, job accidentally flags config_changed by touching the model, and repeat
|
||||
def config_updated
|
||||
self.skip_config_changed_flag = true
|
||||
|
||||
self.config_changed = 0
|
||||
begin
|
||||
self.save!
|
||||
rescue
|
||||
raise
|
||||
ensure
|
||||
self.skip_config_changed_flag = false
|
||||
end
|
||||
end
|
||||
|
||||
def to_s
|
||||
return server_id
|
||||
end
|
||||
|
||||
def dumpXml (output=$stdout, indent=1)
|
||||
|
||||
builder = ::Builder::XmlMarkup.new(:target => output, :indent => indent)
|
||||
|
||||
builder.tag! 'icecast' do |root|
|
||||
root.tag! 'hostname', hostname
|
||||
root.tag! 'location', (location.nil? || location.empty?) ? template.location : location
|
||||
root.tag! 'server-id', server_id
|
||||
root.tag! 'admin', (admin_email.nil? || admin_email.empty?) ? template.admin_email : admin_email
|
||||
root.tag! 'fileserve', fileserve.nil? ? template.fileserve : fileserve
|
||||
|
||||
# do we have an override specified? or do we go with the template
|
||||
current_limit = limit ? limit : template.limit
|
||||
current_admin_auth = admin_auth ? admin_auth : template.admin_auth
|
||||
current_directory = directory ? directory : template.directory
|
||||
current_master_relay = master_relay ? master_relay : template.master_relay
|
||||
current_path = path ? path : template.path
|
||||
current_logging = logging ? logging : template.logging
|
||||
current_security = security ? security : template.security
|
||||
current_listen_sockets = listen_sockets.length > 0 ? listen_sockets : template.listen_sockets
|
||||
|
||||
current_limit.dumpXml(builder) unless current_limit.nil?
|
||||
current_admin_auth.dumpXml(builder) unless current_admin_auth.nil?
|
||||
current_directory.dumpXml(builder) unless current_directory.nil?
|
||||
current_master_relay.dumpXml(builder) unless current_master_relay.nil?
|
||||
current_path.dumpXml(builder) unless current_path.nil?
|
||||
current_logging.dumpXml(builder) unless current_logging.nil?
|
||||
current_security.dumpXml(builder) unless current_security.nil?
|
||||
current_listen_sockets.each do |listen_socket|
|
||||
listen_socket.dumpXml(builder)
|
||||
end
|
||||
|
||||
relays.each do |relay|
|
||||
relay.dumpXml(builder)
|
||||
end
|
||||
|
||||
mounts.each do |mount|
|
||||
mount.dumpXml(builder)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
module JamRuby
|
||||
class IcecastServerMount < ActiveRecord::Base
|
||||
self.table_name = 'icecast_server_mounts'
|
||||
|
||||
attr_accessible :icecast_mount_id, :icecast_server_id, as: :admin
|
||||
|
||||
belongs_to :mount, :class_name => "JamRuby::IcecastMount", :foreign_key => 'icecast_mount_id', :inverse_of => :server_mounts
|
||||
belongs_to :server, :class_name => "JamRuby::IcecastServer", :foreign_key => 'icecast_server_id', :inverse_of => :server_mounts
|
||||
|
||||
validates :server, :presence => true
|
||||
validates :mount, :presence => true
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
module JamRuby
|
||||
class IcecastServerRelay < ActiveRecord::Base
|
||||
|
||||
self.table_name = 'icecast_server_relays'
|
||||
|
||||
attr_accessible :icecast_relay_id, :icecast_server_id, as: :admin
|
||||
|
||||
belongs_to :relay, :class_name => "JamRuby::IcecastRelay", :foreign_key => 'icecast_relay_id', :inverse_of => :server_relays
|
||||
belongs_to :server, :class_name => "JamRuby::IcecastServer", :foreign_key => 'icecast_server_id', :inverse_of => :server_relays
|
||||
|
||||
validates :server, :presence => true
|
||||
validates :relay, :presence => true
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
module JamRuby
|
||||
class IcecastServerSocket < ActiveRecord::Base
|
||||
|
||||
self.table_name = 'icecast_server_sockets'
|
||||
|
||||
attr_accessible :icecast_listen_socket_id, :icecast_server_id, as: :admin
|
||||
|
||||
belongs_to :socket, :class_name => "JamRuby::IcecastListenSocket", :foreign_key => 'icecast_listen_socket_id', :inverse_of => :server_sockets
|
||||
belongs_to :server, :class_name => "JamRuby::IcecastServer", :foreign_key => 'icecast_server_id', :inverse_of => :listen_socket_servers
|
||||
|
||||
validates :socket, :presence => true
|
||||
validates :server, :presence => true
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
module JamRuby
|
||||
class IcecastServermisc < ActiveRecord::Base
|
||||
|
||||
self.primary_key = 'id'
|
||||
|
||||
attr_accessible :hostname, :location, :admin, :fileserve, :server_id
|
||||
attr_accessor :hostname, :location, :admin, :fileserve, :server_id
|
||||
|
||||
def dumpXml()
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
module JamRuby
|
||||
class IcecastTemplate < ActiveRecord::Base
|
||||
|
||||
attr_accessible :limit_id, :admin_auth_id, :directory_id, :master_relay_id, :path_id, :logging_id,
|
||||
:security_id, :name, :location, :admin_email, :fileserve, as: :admin
|
||||
|
||||
belongs_to :limit, :class_name => "JamRuby::IcecastLimit", foreign_key: 'limit_id', :inverse_of => :templates
|
||||
belongs_to :admin_auth, :class_name => "JamRuby::IcecastAdminAuthentication", foreign_key: 'admin_auth_id', :inverse_of => :templates
|
||||
belongs_to :directory, :class_name => "JamRuby::IcecastDirectory", foreign_key: 'directory_id', :inverse_of => :templates
|
||||
belongs_to :master_relay, :class_name => "JamRuby::IcecastMasterServerRelay", foreign_key: 'master_relay_id', :inverse_of => :templates
|
||||
belongs_to :path, :class_name => "JamRuby::IcecastPath", foreign_key: 'path_id', :inverse_of => :templates
|
||||
belongs_to :logging, :class_name => "JamRuby::IcecastLogging", foreign_key: 'logging_id', :inverse_of => :templates
|
||||
belongs_to :security, :class_name => "JamRuby::IcecastSecurity", foreign_key: 'security_id', :inverse_of => :templates
|
||||
|
||||
has_many :servers, :class_name => "JamRuby::IcecastServer", :inverse_of => :template, :foreign_key => "template_id"
|
||||
|
||||
#has_many :server_mounts, class_name: "JamRuby::IcecastServerMount", :inverse_of => :mount, :foreign_key
|
||||
#has_many :mounts, class_name: "JamRuby::IcecastMount", through: :server_mounts, :source => :template
|
||||
|
||||
has_many :listen_socket_templates, :class_name => "JamRuby::IcecastTemplateSocket", :inverse_of => :template, :foreign_key => 'icecast_template_id'
|
||||
has_many :listen_sockets, :class_name => "JamRuby::IcecastListenSocket", :through => :listen_socket_templates , :source => :socket
|
||||
|
||||
validates :name, presence: true
|
||||
validates :location, presence: true
|
||||
validates :admin_email, presence: true
|
||||
validates :fileserve, :inclusion => {:in => [0, 1]}
|
||||
|
||||
validates :limit, presence: true
|
||||
validates :admin_auth, presence: true
|
||||
validates :path, presence: true
|
||||
validates :logging, presence: true
|
||||
validates :security, presence: true
|
||||
validates :listen_sockets, length: {minimum: 1}
|
||||
|
||||
before_save :sanitize_active_admin
|
||||
after_save :poke_config
|
||||
|
||||
|
||||
def poke_config
|
||||
IcecastServer.update(servers, config_changed: 1)
|
||||
end
|
||||
|
||||
def sanitize_active_admin
|
||||
self.limit_id = nil if self.limit_id == ''
|
||||
self.admin_auth_id = nil if self.admin_auth_id == ''
|
||||
self.directory_id = nil if self.directory_id == ''
|
||||
self.master_relay_id = nil if self.master_relay_id == ''
|
||||
self.path_id = nil if self.path_id == ''
|
||||
self.logging_id = nil if self.logging_id == ''
|
||||
self.security_id = nil if self.security_id == ''
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
module JamRuby
|
||||
class IcecastTemplateSocket < ActiveRecord::Base
|
||||
|
||||
self.table_name = 'icecast_template_sockets'
|
||||
|
||||
attr_accessible :icecast_listen_socket_id, :icecast_template_id, as: :admin
|
||||
|
||||
belongs_to :socket, :class_name => "JamRuby::IcecastListenSocket", :foreign_key => 'icecast_listen_socket_id', :inverse_of => :template_sockets
|
||||
belongs_to :template, :class_name => "JamRuby::IcecastTemplate", :foreign_key => 'icecast_template_id', :inverse_of => :listen_socket_templates
|
||||
|
||||
validates :socket, :presence => true
|
||||
validates :template, :presence => true
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -1,17 +1,60 @@
|
|||
module JamRuby
|
||||
class IcecastUserAuthentication < ActiveRecord::Base
|
||||
|
||||
self.primary_key = 'id'
|
||||
attr_accessible :authentication_type, :filename, :allow_duplicate_users, :mount_add, :mount_remove, :listener_add,
|
||||
:listener_remove, :unused_username, :unused_pass, :auth_header, :timelimit_header, as: :admin
|
||||
|
||||
attr_accessible :stype, :filename, :allow_duplicate_users, :mount_add, :mount_remove,
|
||||
:listener_add, :listener_remove, :username, :password, :auth_header, :timelimit_header
|
||||
has_one :mount, class_name: 'JamRuby::IcecastMount', inverse_of: :authentication, :foreign_key => 'authentication_id'
|
||||
|
||||
attr_accessor :stype, :filename, :allow_duplicate_users, :mount_add, :mount_remove,
|
||||
:listener_add, :listener_remove, :username, :password, :auth_header, :timelimit_header
|
||||
validates :authentication_type, presence: true, :inclusion => {:in => ["url", "htpasswd"]}
|
||||
validates :allow_duplicate_users, :inclusion => {:in => [0, 1]}, if: :htpasswd_auth?
|
||||
validates :unused_username, length: {minimum: 5}, if: :url_auth_and_user_present?
|
||||
validates :unused_pass, length: {minimum: 5}, if: :url_auth_and_pass_present?
|
||||
validates :mount_add, presence: true, if: :url_auth?
|
||||
validates :mount_remove, presence: true, if: :url_auth?
|
||||
validates :listener_add, presence: true, if: :url_auth?
|
||||
validates :listener_remove, presence: true, if: :url_auth?
|
||||
validates :auth_header, presence: true, if: :url_auth?
|
||||
validates :timelimit_header, presence: true, if: :url_auth?
|
||||
|
||||
after_save :poke_config
|
||||
|
||||
def dumpXml()
|
||||
|
||||
def poke_config
|
||||
IcecastServer.update(mount.servers, config_changed: 1) if mount
|
||||
end
|
||||
|
||||
def to_s
|
||||
"mount=#{mount} username=#{unused_username} auth_header=#{auth_header} timelimit_header=#{timelimit_header}"
|
||||
end
|
||||
|
||||
def dumpXml (builder)
|
||||
builder.tag! 'authentication', type: authentication_type do |auth|
|
||||
auth.tag! 'option', name: 'mount_add', value: mount_add if !mount_add.nil? && !mount_remove.empty?
|
||||
auth.tag! 'option', name: 'mount_remove', value: mount_remove if !mount_remove.nil? && !mount_remove.empty?
|
||||
auth.tag! 'option', name: 'username', value: unused_username if !unused_username.nil? && !unused_username.empty?
|
||||
auth.tag! 'option', name: 'password', value: unused_pass if !unused_pass.nil? && !unused_pass.empty?
|
||||
auth.tag! 'option', name: 'listener_add', value: listener_add if !listener_add.nil? && !listener_add.empty?
|
||||
auth.tag! 'option', name: 'listener_remove', value: listener_remove if !listener_remove.nil? && !listener_remove.empty?
|
||||
auth.tag! 'option', name: 'auth_header', value: auth_header if !auth_header.nil? && !auth_header.empty?
|
||||
auth.tag! 'option', name: 'timelimit_header', value: timelimit_header if !timelimit_header.nil? && !timelimit_header.empty?
|
||||
end
|
||||
end
|
||||
|
||||
def htpasswd_auth?
|
||||
authentication_type == 'htpasswd'
|
||||
end
|
||||
|
||||
def url_auth?
|
||||
authentication_type == 'url'
|
||||
end
|
||||
|
||||
def url_auth_and_user_present?
|
||||
url_auth? && self.unused_username.present?
|
||||
end
|
||||
|
||||
def url_auth_and_pass_present?
|
||||
url_auth? && self.unused_pass.present?
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -33,6 +33,7 @@ module JamRuby
|
|||
false
|
||||
end
|
||||
|
||||
# avoid db validations
|
||||
Mix.where(:id => self.id).update_all(:started_at => Time.now)
|
||||
|
||||
true
|
||||
|
|
@ -56,9 +57,7 @@ module JamRuby
|
|||
self.md5 = md5
|
||||
self.completed = true
|
||||
if save
|
||||
recording.users.each do |user|
|
||||
Notification.send_download_available(user.id)
|
||||
end
|
||||
Notification.send_recording_master_mix_complete(recording)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -96,12 +95,6 @@ module JamRuby
|
|||
s3_manager.sign_url(self.url, {:expires => expiration_time, :content_type => 'audio/ogg', :secure => false}, :put)
|
||||
end
|
||||
|
||||
def self.queue_jobs_needing_retry
|
||||
Mix.find_each(:conditions => 'should_retry = TRUE or started_at is NULL', :batch_size => 100) do |mix|
|
||||
mix.enqueue
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def delete_s3_files
|
||||
|
|
|
|||
|
|
@ -15,11 +15,11 @@ module JamRuby
|
|||
:foreign_key => :band_id,
|
||||
:inverse_of => :music_session_history)
|
||||
|
||||
has_many :music_session_history_users, :class_name => "JamRuby::MusicSessionUserHistory", :foreign_key => "music_session_id"
|
||||
has_many :music_session_user_history, :class_name => "JamRuby::MusicSessionUserHistory", :foreign_key => "music_session_id"
|
||||
has_many :comments, :class_name => "JamRuby::MusicSessionComment", :foreign_key => "music_session_id"
|
||||
has_many :likes, :class_name => "JamRuby::MusicSessionLiker", :foreign_key => "music_session_id"
|
||||
|
||||
GENRE_SEPARATOR = '|'
|
||||
SEPARATOR = '|'
|
||||
|
||||
def comment_count
|
||||
self.comments.size
|
||||
|
|
@ -29,6 +29,21 @@ module JamRuby
|
|||
self.likes.size
|
||||
end
|
||||
|
||||
def tracks
|
||||
tracks = []
|
||||
self.music_session_user_history.each do |msuh|
|
||||
user = User.find(msuh.user_id)
|
||||
instruments = msuh.instruments.split(SEPARATOR)
|
||||
instruments.each do |instrument|
|
||||
t = Track.new
|
||||
t.user = user
|
||||
t.instrument_id = instrument
|
||||
tracks << t
|
||||
end
|
||||
end
|
||||
tracks
|
||||
end
|
||||
|
||||
def self.index(current_user, user_id, band_id = nil, genre = nil)
|
||||
hide_private = false
|
||||
if current_user.id != user_id
|
||||
|
|
@ -75,7 +90,7 @@ module JamRuby
|
|||
session_history.description = music_session.description unless music_session.description.nil?
|
||||
session_history.user_id = music_session.creator.id
|
||||
session_history.band_id = music_session.band.id unless music_session.band.nil?
|
||||
session_history.genres = music_session.genres.map { |g| g.id }.join GENRE_SEPARATOR
|
||||
session_history.genres = music_session.genres.map { |g| g.id }.join SEPARATOR
|
||||
session_history.save!
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ module JamRuby
|
|||
@perfdata ||= JamRuby::MusicSessionPerfData.find_by_client_id(self.client_id)
|
||||
end
|
||||
|
||||
def self.save(music_session_id, user_id, client_id)
|
||||
def self.save(music_session_id, user_id, client_id, tracks)
|
||||
return true if 0 < self.where(:music_session_id => music_session_id,
|
||||
:user_id => user_id,
|
||||
:client_id => client_id).count
|
||||
|
|
@ -35,6 +35,7 @@ module JamRuby
|
|||
session_user_history.music_session_id = music_session_id
|
||||
session_user_history.user_id = user_id
|
||||
session_user_history.client_id = client_id
|
||||
session_user_history.instruments = tracks.map {|t| t.instrument_id}.join("|")
|
||||
session_user_history.save
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ module JamRuby
|
|||
belongs_to :session, :class_name => "JamRuby::MusicSession", :foreign_key => "session_id"
|
||||
belongs_to :recording, :class_name => "JamRuby::Recording", :foreign_key => "recording_id"
|
||||
|
||||
validates :target_user, :presence => true
|
||||
|
||||
def index(user_id)
|
||||
Notification.where(:target_user_id => user_id).limit(50)
|
||||
end
|
||||
|
|
@ -658,6 +660,23 @@ module JamRuby
|
|||
end
|
||||
|
||||
def send_recording_master_mix_complete(recording)
|
||||
|
||||
# only people who get told about mixes are folks who claimed it... not everyone in the session
|
||||
recording.claimed_recordings.each do |claimed_recording|
|
||||
|
||||
notification = Notification.new
|
||||
notification.band_id = recording.band.id if recording.band
|
||||
notification.recording_id = recording.id
|
||||
notification.target_user_id = claimed_recording.user_id
|
||||
notification.description = NotificationTypes::RECORDING_MASTER_MIX_COMPLETE
|
||||
notification.save
|
||||
|
||||
notification_msg = format_msg(notification.description, nil, recording.band)
|
||||
|
||||
msg = @@message_factory.recording_master_mix_complete(claimed_recording.user_id, recording.id, notification.band_id, notification_msg, notification.id, notification.created_at.to_s)
|
||||
|
||||
@@mq_router.publish_to_user(claimed_recording.user_id, msg)
|
||||
end
|
||||
end
|
||||
|
||||
def send_band_invitation(band, band_invitation, sender, receiver)
|
||||
|
|
@ -741,12 +760,23 @@ module JamRuby
|
|||
@@mq_router.server_publish_to_session(music_session, msg, sender = {:client_id => client_id})
|
||||
end
|
||||
|
||||
|
||||
def send_download_available(user_id)
|
||||
msg = @@message_factory.download_available
|
||||
|
||||
@@mq_router.publish_to_user(user_id, msg)
|
||||
end
|
||||
|
||||
def send_source_up_requested(music_session, host, port, mount, source_user, source_pass)
|
||||
msg = @@message_factory.source_up_requested(music_session.id, host, port, mount, source_user, source_pass)
|
||||
|
||||
@@mg_router.server_publish_to_session(music_session, msg)
|
||||
end
|
||||
|
||||
def send_source_down_requested(music_session, mount)
|
||||
msg = @@message_factory.source_down_requested(music_session.id, mount)
|
||||
|
||||
@@mq_router.server_publish_to_session(music_session, msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,73 +1,64 @@
|
|||
module JamRuby
|
||||
# not a active_record model; just a search result
|
||||
|
||||
# not a active_record model; just a search result container
|
||||
class Search
|
||||
attr_accessor :bands, :musicians, :fans, :recordings, :friends, :search_type
|
||||
attr_accessor :bands_filter, :musicians_filter
|
||||
attr_accessor :results, :search_type
|
||||
attr_accessor :user_counters, :page_num, :page_count
|
||||
|
||||
LIMIT = 10
|
||||
|
||||
# performs a site-white search
|
||||
def self.search(query, user_id = nil)
|
||||
SEARCH_TEXT_TYPES = [:musicians, :bands, :fans]
|
||||
SEARCH_TEXT_TYPE_ID = :search_text_type
|
||||
|
||||
users = User.search(query, :limit => LIMIT)
|
||||
bands = Band.search(query, :limit => LIMIT)
|
||||
# NOTE: I removed recordings from search here. This is because we switched
|
||||
# to "claimed_recordings" so it's not clear what should be searched.
|
||||
|
||||
friends = Friendship.search(query, user_id, :limit => LIMIT)
|
||||
|
||||
return Search.new(users + bands + friends)
|
||||
def self.band_search(txt, user = nil)
|
||||
self.text_search({ SEARCH_TEXT_TYPE_ID => :bands, :query => txt }, user)
|
||||
end
|
||||
|
||||
# performs a friend search scoped to a specific user
|
||||
# def self.search_by_user(query, user_id)
|
||||
# friends = Friendship.search(query, user_id, :limit => LIMIT)
|
||||
# return Search.new(friends)
|
||||
# end
|
||||
def self.fan_search(txt, user = nil)
|
||||
self.text_search({ SEARCH_TEXT_TYPE_ID => :fans, :query => txt }, user)
|
||||
end
|
||||
|
||||
def self.musician_search(txt, user = nil)
|
||||
self.text_search({ SEARCH_TEXT_TYPE_ID => :musicians, :query => txt }, user)
|
||||
end
|
||||
|
||||
def self.text_search(params, user = nil)
|
||||
srch = Search.new
|
||||
unless (params.blank? || params[:query].blank? || 2 > params[:query].length)
|
||||
srch.text_search(params, user)
|
||||
end
|
||||
srch
|
||||
end
|
||||
|
||||
def text_search(params, user = nil)
|
||||
tsquery = Search.create_tsquery(params[:query])
|
||||
return [] if tsquery.blank?
|
||||
|
||||
rel = case params[SEARCH_TEXT_TYPE_ID].to_s
|
||||
when 'bands'
|
||||
@search_type = :bands
|
||||
Band.scoped
|
||||
when 'fans'
|
||||
@search_type = :fans
|
||||
User.fans
|
||||
else
|
||||
@search_type = :musicians
|
||||
User.musicians
|
||||
end
|
||||
@results = rel.where("(name_tsv @@ to_tsquery('jamenglish', ?))", tsquery).limit(10)
|
||||
@results
|
||||
end
|
||||
|
||||
# search_results - results from a Tire search across band/user/recording
|
||||
def initialize(search_results=nil)
|
||||
@bands = []
|
||||
@musicians = []
|
||||
@fans = []
|
||||
@recordings = []
|
||||
@friends = []
|
||||
@musicians_filter = []
|
||||
@bands_filter = []
|
||||
|
||||
if search_results.nil?
|
||||
return
|
||||
end
|
||||
|
||||
search_results.take(LIMIT).each do |result|
|
||||
if result.class == User
|
||||
if result.musician
|
||||
@musicians.push(result)
|
||||
else
|
||||
@fans.push(result)
|
||||
end
|
||||
elsif result.class == Band
|
||||
@bands.push(result)
|
||||
elsif result.class == Recording
|
||||
@recordings.push(result)
|
||||
elsif result.class == Friendship
|
||||
@friends.push(result.friend)
|
||||
else
|
||||
raise Exception, "unknown class #{result.class} returned in search results"
|
||||
end
|
||||
end
|
||||
@results = []
|
||||
self
|
||||
end
|
||||
|
||||
def self.create_tsquery(query)
|
||||
# empty queries don't hit back to elasticsearch
|
||||
if query.nil? || query.length == 0
|
||||
return nil
|
||||
end
|
||||
return nil if query.blank?
|
||||
|
||||
search_terms = query.split
|
||||
|
||||
if search_terms.length == 0
|
||||
return nil
|
||||
end
|
||||
return nil if search_terms.length == 0
|
||||
|
||||
args = nil
|
||||
search_terms.each do |search_term|
|
||||
|
|
@ -76,15 +67,11 @@ module JamRuby
|
|||
else
|
||||
args = args + " & " + search_term
|
||||
end
|
||||
|
||||
end
|
||||
args = args + ":*"
|
||||
|
||||
return args
|
||||
args
|
||||
end
|
||||
|
||||
attr_accessor :user_counters, :page_num, :page_count
|
||||
|
||||
PARAM_MUSICIAN = :srch_m
|
||||
PARAM_BAND = :srch_b
|
||||
|
||||
|
|
@ -105,7 +92,7 @@ module JamRuby
|
|||
ordering.blank? ? keys[0] : keys.detect { |oo| oo.to_s == ordering }
|
||||
end
|
||||
|
||||
def self.musician_search(params={}, current_user=nil)
|
||||
def self.musician_filter(params={}, current_user=nil)
|
||||
rel = User.musicians
|
||||
unless (instrument = params[:instrument]).blank?
|
||||
rel = rel.joins("RIGHT JOIN musicians_instruments AS minst ON minst.user_id = users.id")
|
||||
|
|
@ -140,6 +127,7 @@ module JamRuby
|
|||
|
||||
objs = rel.all
|
||||
srch = Search.new
|
||||
srch.search_type = :musicians_filter
|
||||
srch.page_num, srch.page_count = page, objs.total_pages
|
||||
srch.musician_results_for_user(objs, current_user)
|
||||
end
|
||||
|
|
@ -159,14 +147,14 @@ module JamRuby
|
|||
COUNT_SESSION = :count_session
|
||||
COUNTERS = [COUNT_FRIEND, COUNT_FOLLOW, COUNT_RECORD, COUNT_SESSION]
|
||||
|
||||
def musician_results_for_user(results, user)
|
||||
@search_type, @musicians_filter = PARAM_MUSICIAN, results
|
||||
def musician_results_for_user(_results, user)
|
||||
@results = _results
|
||||
if user
|
||||
@user_counters = results.inject({}) { |hh,val| hh[val.id] = []; hh }
|
||||
mids = "'#{@musicians_filter.map(&:id).join("','")}'"
|
||||
@user_counters = @results.inject({}) { |hh,val| hh[val.id] = []; hh }
|
||||
mids = "'#{@results.map(&:id).join("','")}'"
|
||||
|
||||
# this gets counts for each search result on friends/follows/records/sessions
|
||||
results.each do |uu|
|
||||
@results.each do |uu|
|
||||
counters = { }
|
||||
counters[COUNT_FRIEND] = Friendship.where(:user_id => uu.id).count
|
||||
counters[COUNT_FOLLOW] = UserFollowing.where(:user_id => uu.id).count
|
||||
|
|
@ -204,6 +192,26 @@ module JamRuby
|
|||
|
||||
public
|
||||
|
||||
def musicians_text_search?
|
||||
:musicians == @search_type
|
||||
end
|
||||
|
||||
def fans_text_search?
|
||||
:fans == @search_type
|
||||
end
|
||||
|
||||
def bands_text_search?
|
||||
:bands == @search_type
|
||||
end
|
||||
|
||||
def musicians_filter_search?
|
||||
:musicians_filter == @search_type
|
||||
end
|
||||
|
||||
def bands_filter_search?
|
||||
:band_filter == @search_type
|
||||
end
|
||||
|
||||
def follow_count(musician)
|
||||
_count(musician, COUNT_FOLLOW)
|
||||
end
|
||||
|
|
@ -247,7 +255,7 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def self.band_search(params={}, current_user=nil)
|
||||
def self.band_filter(params={}, current_user=nil)
|
||||
rel = Band.scoped
|
||||
|
||||
unless (genre = params[:genre]).blank?
|
||||
|
|
@ -282,18 +290,19 @@ module JamRuby
|
|||
|
||||
objs = rel.all
|
||||
srch = Search.new
|
||||
srch.search_type = :band_filter
|
||||
srch.page_num, srch.page_count = page, objs.total_pages
|
||||
srch.band_results_for_user(objs, current_user)
|
||||
end
|
||||
|
||||
def band_results_for_user(results, user)
|
||||
@search_type, @bands_filter = PARAM_BAND, results
|
||||
def band_results_for_user(_results, user)
|
||||
@results = _results
|
||||
if user
|
||||
@user_counters = results.inject({}) { |hh,val| hh[val.id] = []; hh }
|
||||
mids = "'#{@bands_filter.map(&:id).join("','")}'"
|
||||
@user_counters = @results.inject({}) { |hh,val| hh[val.id] = []; hh }
|
||||
mids = "'#{@results.map(&:id).join("','")}'"
|
||||
|
||||
# this gets counts for each search result
|
||||
results.each do |bb|
|
||||
@results.each do |bb|
|
||||
counters = { }
|
||||
counters[COUNT_FOLLOW] = BandFollowing.where(:band_id => bb.id).count
|
||||
counters[COUNT_RECORD] = Recording.where(:band_id => bb.id).count
|
||||
|
|
|
|||
|
|
@ -51,6 +51,10 @@ module JamRuby
|
|||
Track.transaction do
|
||||
connection = Connection.find_by_client_id!(clientId)
|
||||
|
||||
# each time tracks are synced we have to update the entry in music_sessions_user_history
|
||||
msh = MusicSessionUserHistory.find_by_client_id!(clientId)
|
||||
instruments = []
|
||||
|
||||
if tracks.length == 0
|
||||
connection.tracks.delete_all
|
||||
else
|
||||
|
|
@ -66,9 +70,11 @@ module JamRuby
|
|||
to_delete.delete(connection_track)
|
||||
to_add.delete(track)
|
||||
# don't update connection_id or client_id; it's unknown what would happen if these changed mid-session
|
||||
connection_track.instrument = Instrument.find(track[:instrument_id])
|
||||
connection_track.instrument_id = track[:instrument_id]
|
||||
connection_track.sound = track[:sound]
|
||||
connection_track.client_track_id = track[:client_track_id]
|
||||
|
||||
instruments << track[:instrument_id]
|
||||
if connection_track.save
|
||||
result.push(connection_track)
|
||||
next
|
||||
|
|
@ -80,10 +86,15 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
msh.instruments = instruments.join("|")
|
||||
if !msh.save
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
|
||||
to_add.each do |track|
|
||||
connection_track = Track.new
|
||||
connection_track.connection = connection
|
||||
connection_track.instrument = Instrument.find(track[:instrument_id])
|
||||
connection_track.instrument_id = track[:instrument_id]
|
||||
connection_track.sound = track[:sound]
|
||||
connection_track.client_track_id = track[:client_track_id]
|
||||
if connection_track.save
|
||||
|
|
@ -94,7 +105,7 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
to_delete.each do| delete_me |
|
||||
to_delete.each do |delete_me|
|
||||
delete_me.delete
|
||||
end
|
||||
end
|
||||
|
|
@ -105,7 +116,7 @@ module JamRuby
|
|||
|
||||
def self.save(id, connection_id, instrument_id, sound, client_track_id)
|
||||
if id.nil?
|
||||
track = Track.new()
|
||||
track = Track.new
|
||||
track.connection_id = connection_id
|
||||
else
|
||||
track = Track.find(id)
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ module JamRuby
|
|||
validate :update_email_case_insensitive_uniqueness, :if => :updating_email
|
||||
|
||||
scope :musicians, where(:musician => true)
|
||||
scope :fans, where(:musician => false)
|
||||
scope :geocoded_users, where(['lat IS NOT NULL AND lng IS NOT NULL'])
|
||||
scope :musicians_geocoded, musicians.geocoded_users
|
||||
|
||||
|
|
@ -285,6 +286,13 @@ module JamRuby
|
|||
def session_count
|
||||
return self.music_sessions.size
|
||||
end
|
||||
|
||||
def recent_history
|
||||
recordings = ClaimedRecording.joins(:recording).where(:recordings => {:owner_id => "#{self.id}"}).limit(10)
|
||||
msh = MusicSessionHistory.where(:user_id => self.id).limit(10)
|
||||
recordings.concat(msh)
|
||||
recordings.sort! {|a,b| b.created_at <=> a.created_at}.first(5)
|
||||
end
|
||||
|
||||
def confirm_email!
|
||||
self.email_confirmed = true
|
||||
|
|
@ -924,31 +932,6 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def self.search(query, options = { :limit => 10 })
|
||||
|
||||
# only issue search if at least 2 characters are specified
|
||||
if query.nil? || query.length < 2
|
||||
return []
|
||||
end
|
||||
|
||||
# save query for use in instrument search
|
||||
search_criteria = query
|
||||
|
||||
# create 'anded' statement
|
||||
query = Search.create_tsquery(query)
|
||||
|
||||
if query.nil? || query.length == 0
|
||||
return []
|
||||
end
|
||||
|
||||
# remove email_confirmed restriction due to VRFS-378
|
||||
# .where("email_confirmed = true AND (name_tsv @@ to_tsquery('jamenglish', ?) OR users.id in (select user_id from musicians_instruments where instrument_id like '%#{search_criteria.downcase}%'))", query)
|
||||
|
||||
return query = User
|
||||
.where("(name_tsv @@ to_tsquery('jamenglish', ?) OR users.id in (select user_id from musicians_instruments where instrument_id like '%#{search_criteria.downcase}%'))", query)
|
||||
.limit(options[:limit])
|
||||
end
|
||||
|
||||
def provides_location?
|
||||
!self.city.blank? && (!self.state.blank? || !self.country.blank?)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -77,6 +77,8 @@ class MQRouter
|
|||
# sends a message to a user with no checking of permissions (RAW USAGE)
|
||||
# this method deliberately has no database interactivity/active_record objects
|
||||
def publish_to_user(user_id, user_msg)
|
||||
@@log.warn "EM not running in publish_to_user" unless EM.reactor_running?
|
||||
|
||||
EM.schedule do
|
||||
@@log.debug "publishing to user:#{user_id} from server"
|
||||
# put it on the topic exchange for users
|
||||
|
|
|
|||
|
|
@ -17,10 +17,20 @@ module JamRuby
|
|||
:error_reason, :error_detail
|
||||
|
||||
def self.perform(mix_id, postback_output_url)
|
||||
audiomixer = AudioMixer.new()
|
||||
audiomixer.postback_output_url = postback_output_url
|
||||
audiomixer.mix_id = mix_id
|
||||
audiomixer.run
|
||||
|
||||
JamWebEventMachine.run_wait_stop do
|
||||
audiomixer = AudioMixer.new()
|
||||
audiomixer.postback_output_url = postback_output_url
|
||||
audiomixer.mix_id = mix_id
|
||||
audiomixer.run
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def self.queue_jobs_needing_retry
|
||||
Mix.find_each(:conditions => 'should_retry = TRUE or started_at is NULL', :batch_size => 100) do |mix|
|
||||
mix.enqueue
|
||||
end
|
||||
end
|
||||
|
||||
def initialize
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
require 'json'
|
||||
require 'resque'
|
||||
require 'resque-retry'
|
||||
require 'net/http'
|
||||
require 'digest/md5'
|
||||
|
||||
module JamRuby
|
||||
|
||||
# executes a mix of tracks, creating a final output mix
|
||||
class IcecastConfigWriter
|
||||
|
||||
@@log = Logging.logger[IcecastConfigWriter]
|
||||
|
||||
attr_accessor :icecast_server_id
|
||||
|
||||
def self.queue
|
||||
queue_name(::APP_CONFIG.icecast_server_id)
|
||||
end
|
||||
|
||||
def self.queue_jobs_needing_retry
|
||||
# if we haven't seen updated_at be tickled in 5 minutes, but config_changed is still set to TRUE, this record has gotten stale
|
||||
IcecastServer.find_each(:conditions => "config_changed = 1 AND updated_at < (NOW() - interval '#{APP_CONFIG.icecast_max_missing_check} second')", :batch_size => 100) do |server|
|
||||
IcecastConfigWriter.enqueue(server.server_id)
|
||||
end
|
||||
end
|
||||
|
||||
def self.queue_name(server_id)
|
||||
"icecast-#{server_id}"
|
||||
end
|
||||
|
||||
def self.perform(icecast_server_id)
|
||||
icecast = IcecastConfigWriter.new()
|
||||
icecast.icecast_server_id = icecast_server_id
|
||||
icecast.run
|
||||
end
|
||||
|
||||
def self.enqueue(server_id)
|
||||
begin
|
||||
Resque.enqueue_to(queue_name(server_id), IcecastConfigWriter, server_id)
|
||||
return true
|
||||
rescue
|
||||
@@log.error("unable to enqueue IceastConfigWriter(#{server_id}). #{$!}")
|
||||
# implies redis is down
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def initialize
|
||||
|
||||
end
|
||||
|
||||
def validate
|
||||
raise "icecast_server_id not spceified" unless icecast_server_id
|
||||
raise "queue routing mismatch error" unless icecast_server_id == APP_CONFIG.icecast_server_id
|
||||
end
|
||||
|
||||
def execute(cmd)
|
||||
system cmd
|
||||
$?.exitstatus
|
||||
end
|
||||
|
||||
def reload
|
||||
cmd = APP_CONFIG.icecast_reload_cmd
|
||||
result = execute(cmd)
|
||||
raise "unable to execute icecast reload cmd=#{cmd}. result=#{$?}" unless result == 0
|
||||
end
|
||||
|
||||
def run
|
||||
validate
|
||||
|
||||
config_file = APP_CONFIG.icecast_config_file
|
||||
|
||||
# check if the config file is there at all; if it's not, we need to generate it regardless if config has changed
|
||||
query = {server_id: icecast_server_id}
|
||||
|
||||
icecast_server = IcecastServer.where(server_id: icecast_server_id).first
|
||||
|
||||
raise "can not find icecast server with query #{query}" unless icecast_server
|
||||
|
||||
if File.exist?(config_file) && !icecast_server.config_changed
|
||||
@@log.info("config not changed. skipping run for server: #{icecast_server.server_id}")
|
||||
else
|
||||
icecast_server.with_lock do
|
||||
|
||||
# don't try to write to the file if for some reason the model isn't valid
|
||||
# this could happen if an admin mucks around in the db directly
|
||||
raise "icecast_server.id=#{icecast_server.server_id} not valid. errors=#{icecast_server.errors.inspect}" unless icecast_server.valid?
|
||||
|
||||
# write the new config to a temporary location
|
||||
tmp_config = Dir::Tmpname.make_tmpname(["#{Dir.tmpdir}/icecast", '.xml'], nil)
|
||||
|
||||
File.open(tmp_config, 'w') do |f|
|
||||
icecast_server.dumpXml(f)
|
||||
end
|
||||
|
||||
# if written successfully, overwrite the current file
|
||||
FileUtils.mv tmp_config, config_file
|
||||
|
||||
# reload server
|
||||
reload
|
||||
|
||||
icecast_server.config_updated
|
||||
end
|
||||
end
|
||||
|
||||
@@log.info("successful update of config for server: #{icecast_server.server_id}")
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -14,7 +14,7 @@ module JamRuby
|
|||
@@log = Logging.logger[AudioMixerRetry]
|
||||
|
||||
def self.perform
|
||||
Mix.queue_jobs_needing_retry
|
||||
AudioMixer.queue_jobs_needing_retry
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
require 'json'
|
||||
require 'resque'
|
||||
require 'resque-retry'
|
||||
require 'net/http'
|
||||
require 'digest/md5'
|
||||
|
||||
module JamRuby
|
||||
|
||||
# periodically scheduled to find jobs that need retrying
|
||||
class IcecastConfigRetry
|
||||
|
||||
@queue = :icecast_config_retry
|
||||
|
||||
@@log = Logging.logger[IcecastConfigRetry]
|
||||
|
||||
def self.perform
|
||||
IcecastConfigWriter.queue_jobs_needing_retry
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -136,8 +136,142 @@ FactoryGirl.define do
|
|||
end
|
||||
|
||||
factory :promo_buzz, :class => JamRuby::PromoBuzz do
|
||||
text_short Faker::Lorem.sentence
|
||||
text_short Faker::Lorem.characters(10)
|
||||
text_long Faker::Lorem.paragraphs(3).join("\n")
|
||||
end
|
||||
|
||||
factory :icecast_limit, :class => JamRuby::IcecastLimit do
|
||||
clients 5
|
||||
sources 1
|
||||
queue_size 102400
|
||||
client_timeout 30
|
||||
header_timeout 15
|
||||
source_timeout 10
|
||||
burst_size 65536
|
||||
end
|
||||
|
||||
factory :icecast_admin_authentication, :class => JamRuby::IcecastAdminAuthentication do
|
||||
source_pass Faker::Lorem.characters(10)
|
||||
admin_user Faker::Lorem.characters(10)
|
||||
admin_pass Faker::Lorem.characters(10)
|
||||
relay_user Faker::Lorem.characters(10)
|
||||
relay_pass Faker::Lorem.characters(10)
|
||||
end
|
||||
|
||||
factory :icecast_directory, :class => JamRuby::IcecastDirectory do
|
||||
yp_url_timeout 15
|
||||
yp_url Faker::Lorem.characters(10)
|
||||
end
|
||||
|
||||
factory :icecast_master_server_relay, :class => JamRuby::IcecastMasterServerRelay do
|
||||
master_server Faker::Lorem.characters(10)
|
||||
master_server_port 8000
|
||||
master_update_interval 120
|
||||
master_username Faker::Lorem.characters(10)
|
||||
master_pass Faker::Lorem.characters(10)
|
||||
relays_on_demand 1
|
||||
end
|
||||
|
||||
factory :icecast_path, :class => JamRuby::IcecastPath do
|
||||
base_dir Faker::Lorem.characters(10)
|
||||
log_dir Faker::Lorem.characters(10)
|
||||
pid_file Faker::Lorem.characters(10)
|
||||
web_root Faker::Lorem.characters(10)
|
||||
admin_root Faker::Lorem.characters(10)
|
||||
end
|
||||
|
||||
factory :icecast_logging, :class => JamRuby::IcecastLogging do
|
||||
access_log Faker::Lorem.characters(10)
|
||||
error_log Faker::Lorem.characters(10)
|
||||
log_level 3
|
||||
log_archive nil
|
||||
log_size 10000
|
||||
end
|
||||
|
||||
factory :icecast_security, :class => JamRuby::IcecastSecurity do
|
||||
chroot 0
|
||||
end
|
||||
|
||||
factory :icecast_mount, :class => JamRuby::IcecastMount do
|
||||
name "/" + Faker::Lorem.characters(10)
|
||||
source_username Faker::Lorem.characters(10)
|
||||
source_pass Faker::Lorem.characters(10)
|
||||
max_listeners 100
|
||||
max_listener_duration 3600
|
||||
fallback_mount Faker::Lorem.characters(10)
|
||||
fallback_override 1
|
||||
fallback_when_full 1
|
||||
is_public -1
|
||||
stream_name Faker::Lorem.characters(10)
|
||||
stream_description Faker::Lorem.characters(10)
|
||||
stream_url Faker::Lorem.characters(10)
|
||||
genre Faker::Lorem.characters(10)
|
||||
hidden 0
|
||||
|
||||
factory :icecast_mount_with_auth do
|
||||
association :authentication, :factory => :icecast_user_authentication
|
||||
end
|
||||
end
|
||||
|
||||
factory :icecast_listen_socket, :class => JamRuby::IcecastListenSocket do
|
||||
port 8000
|
||||
end
|
||||
|
||||
factory :icecast_relay, :class => JamRuby::IcecastRelay do
|
||||
port 8000
|
||||
mount Faker::Lorem.characters(10)
|
||||
server Faker::Lorem.characters(10)
|
||||
on_demand 1
|
||||
end
|
||||
|
||||
factory :icecast_user_authentication, :class => JamRuby::IcecastUserAuthentication do
|
||||
authentication_type 'url'
|
||||
unused_username Faker::Lorem.characters(10)
|
||||
unused_pass Faker::Lorem.characters(10)
|
||||
mount_add Faker::Lorem.characters(10)
|
||||
mount_remove Faker::Lorem.characters(10)
|
||||
listener_add Faker::Lorem.characters(10)
|
||||
listener_remove Faker::Lorem.characters(10)
|
||||
auth_header 'icecast-auth-user: 1'
|
||||
timelimit_header 'icecast-auth-timelimit:'
|
||||
end
|
||||
|
||||
factory :icecast_server, :class => JamRuby::IcecastServer do
|
||||
sequence(:hostname) { |n| "hostname-#{n}"}
|
||||
sequence(:server_id) { |n| "server-#{n}"}
|
||||
|
||||
factory :icecast_server_minimal do
|
||||
association :template, :factory => :icecast_template_minimal
|
||||
|
||||
factory :icecast_server_with_overrides do
|
||||
association :limit, :factory => :icecast_limit
|
||||
association :admin_auth, :factory => :icecast_admin_authentication
|
||||
association :path, :factory => :icecast_path
|
||||
association :logging, :factory => :icecast_logging
|
||||
association :security, :factory => :icecast_security
|
||||
|
||||
before(:create) do |server|
|
||||
server.listen_sockets << FactoryGirl.build(:icecast_listen_socket)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
factory :icecast_template, :class => JamRuby::IcecastTemplate do
|
||||
|
||||
sequence(:name) { |n| "name-#{n}"}
|
||||
sequence(:location) { |n| "location-#{n}"}
|
||||
|
||||
factory :icecast_template_minimal do
|
||||
association :limit, :factory => :icecast_limit
|
||||
association :admin_auth, :factory => :icecast_admin_authentication
|
||||
association :path, :factory => :icecast_path
|
||||
association :logging, :factory => :icecast_logging
|
||||
association :security, :factory => :icecast_security
|
||||
|
||||
before(:create) do |template|
|
||||
template.listen_sockets << FactoryGirl.build(:icecast_listen_socket)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -45,10 +45,6 @@ describe ConnectionManager do
|
|||
end
|
||||
end
|
||||
|
||||
it "can't create bogus user_id" do
|
||||
expect { @connman.create_connection("aeonuthaoentuh", "client_id", "1.1.1.1") }.to raise_error(PG::Error)
|
||||
end
|
||||
|
||||
it "can't create two client_ids of same value" do
|
||||
|
||||
client_id = "client_id1"
|
||||
|
|
@ -428,7 +424,6 @@ describe ConnectionManager do
|
|||
@connman.delete_connection(client_id)
|
||||
|
||||
assert_num_connections(client_id, 0)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -25,15 +25,15 @@ describe 'Band search' do
|
|||
it "finds all bands" do
|
||||
# expects all the bands
|
||||
num = Band.count
|
||||
results = Search.band_search({ :per_page => num })
|
||||
expect(results.bands_filter.count).to eq(num)
|
||||
results = Search.band_filter({ :per_page => num })
|
||||
expect(results.results.count).to eq(num)
|
||||
end
|
||||
|
||||
it "finds bands with proper ordering" do
|
||||
# the ordering should be create_at since no followers exist
|
||||
expect(BandFollower.count).to eq(0)
|
||||
results = Search.band_search({ :per_page => Band.count })
|
||||
results.bands_filter.each_with_index do |uu, idx|
|
||||
results = Search.band_filter({ :per_page => Band.count })
|
||||
results.results.each_with_index do |uu, idx|
|
||||
expect(uu.id).to eq(@bands.reverse[idx].id)
|
||||
end
|
||||
end
|
||||
|
|
@ -53,11 +53,11 @@ describe 'Band search' do
|
|||
|
||||
# refresh the order to ensure it works right
|
||||
@band2.followers.concat(users[1..-1])
|
||||
results = Search.band_search({ :per_page => @bands.size }, users[0])
|
||||
expect(results.bands_filter[0].id).to eq(@band2.id)
|
||||
results = Search.band_filter({ :per_page => @bands.size }, users[0])
|
||||
expect(results.results[0].id).to eq(@band2.id)
|
||||
|
||||
# check the follower count for given entry
|
||||
expect(results.bands_filter[0].search_follow_count.to_i).not_to eq(0)
|
||||
expect(results.results[0].search_follow_count.to_i).not_to eq(0)
|
||||
# check the follow relationship between current_user and result
|
||||
expect(results.is_follower?(@band2)).to be true
|
||||
end
|
||||
|
|
@ -65,8 +65,8 @@ describe 'Band search' do
|
|||
it 'paginates properly' do
|
||||
# make sure pagination works right
|
||||
params = { :per_page => 2, :page => 1 }
|
||||
results = Search.band_search(params)
|
||||
expect(results.bands_filter.count).to be 2
|
||||
results = Search.band_filter(params)
|
||||
expect(results.results.count).to be 2
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -87,8 +87,8 @@ describe 'Band search' do
|
|||
|
||||
# establish sorting order
|
||||
@band1.followers.concat(users)
|
||||
results = Search.band_search({},@band1)
|
||||
uu = results.bands_filter.detect { |mm| mm.id == @band1.id }
|
||||
results = Search.band_filter({},@band1)
|
||||
uu = results.results.detect { |mm| mm.id == @band1.id }
|
||||
expect(uu).to_not be_nil
|
||||
expect(results.follow_count(uu)).to eq(users.count)
|
||||
end
|
||||
|
|
@ -96,8 +96,8 @@ describe 'Band search' do
|
|||
it "session stat shows session count" do
|
||||
make_session(@band1)
|
||||
@band1.reload
|
||||
results = Search.band_search({},@band1)
|
||||
uu = results.bands_filter.detect { |mm| mm.id == @band1.id }
|
||||
results = Search.band_filter({},@band1)
|
||||
uu = results.results.detect { |mm| mm.id == @band1.id }
|
||||
expect(uu).to_not be_nil
|
||||
expect(results.session_count(uu)).to be 1
|
||||
end
|
||||
|
|
@ -112,9 +112,9 @@ describe 'Band search' do
|
|||
make_session(@band2)
|
||||
make_session(@band1)
|
||||
# order results by num recordings
|
||||
results = Search.band_search({ :orderby => 'plays' })
|
||||
expect(results.bands_filter[0].id).to eq(@band2.id)
|
||||
expect(results.bands_filter[1].id).to eq(@band1.id)
|
||||
results = Search.band_filter({ :orderby => 'plays' })
|
||||
expect(results.results[0].id).to eq(@band2.id)
|
||||
expect(results.results[1].id).to eq(@band1.id)
|
||||
end
|
||||
|
||||
it "by now playing" do
|
||||
|
|
@ -122,18 +122,18 @@ describe 'Band search' do
|
|||
session = make_session(@band3)
|
||||
FactoryGirl.create(:music_session_history, :music_session => session)
|
||||
|
||||
results = Search.band_search({ :orderby => 'playing' })
|
||||
expect(results.bands_filter.count).to be 1
|
||||
expect(results.bands_filter.first.id).to eq(@band3.id)
|
||||
results = Search.band_filter({ :orderby => 'playing' })
|
||||
expect(results.results.count).to be 1
|
||||
expect(results.results.first.id).to eq(@band3.id)
|
||||
|
||||
# should get 2 results with 2 active sessions
|
||||
# sort order should be created_at DESC
|
||||
session = make_session(@band4)
|
||||
FactoryGirl.create(:music_session_history, :music_session => session)
|
||||
results = Search.band_search({ :orderby => 'playing' })
|
||||
expect(results.bands_filter.count).to be 2
|
||||
expect(results.bands_filter[0].id).to eq(@band4.id)
|
||||
expect(results.bands_filter[1].id).to eq(@band3.id)
|
||||
results = Search.band_filter({ :orderby => 'playing' })
|
||||
expect(results.results.count).to be 2
|
||||
expect(results.results[0].id).to eq(@band4.id)
|
||||
expect(results.results[1].id).to eq(@band3.id)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -146,40 +146,40 @@ describe 'Band search' do
|
|||
@band1.reload
|
||||
ggg = @band1.genres.detect { |gg| gg.id == genre.id }
|
||||
expect(ggg).to_not be_nil
|
||||
results = Search.band_search({ :genre => ggg.id })
|
||||
results.bands_filter.each do |rr|
|
||||
results = Search.band_filter({ :genre => ggg.id })
|
||||
results.results.each do |rr|
|
||||
expect(rr.genres.detect { |gg| gg.id==ggg.id }.id).to eq(genre.id)
|
||||
end
|
||||
expect(results.bands_filter.count).to be 1
|
||||
expect(results.results.count).to be 1
|
||||
end
|
||||
|
||||
it "finds bands within a given distance of given location" do
|
||||
num = Band.count
|
||||
expect(@band1.lat).to_not be_nil
|
||||
# short distance
|
||||
results = Search.band_search({ :per_page => num,
|
||||
results = Search.band_filter({ :per_page => num,
|
||||
:distance => 10,
|
||||
:city => 'Apex' }, @band1)
|
||||
expect(results.bands_filter.count).to be num
|
||||
expect(results.results.count).to be num
|
||||
# long distance
|
||||
results = Search.band_search({ :per_page => num,
|
||||
results = Search.band_filter({ :per_page => num,
|
||||
:distance => 1000,
|
||||
:city => 'Miami',
|
||||
:state => 'FL' }, @band1)
|
||||
expect(results.bands_filter.count).to be num
|
||||
expect(results.results.count).to be num
|
||||
end
|
||||
|
||||
it "finds bands within a given distance of bands location" do
|
||||
expect(@band1.lat).to_not be_nil
|
||||
# uses the location of @band1
|
||||
results = Search.band_search({ :distance => 10, :per_page => Band.count }, @band1)
|
||||
expect(results.bands_filter.count).to be Band.count
|
||||
results = Search.band_filter({ :distance => 10, :per_page => Band.count }, @band1)
|
||||
expect(results.results.count).to be Band.count
|
||||
end
|
||||
|
||||
it "finds no bands within a given distance of location" do
|
||||
expect(@band1.lat).to_not be_nil
|
||||
results = Search.band_search({ :distance => 10, :city => 'San Francisco' }, @band1)
|
||||
expect(results.bands_filter.count).to be 0
|
||||
results = Search.band_filter({ :distance => 10, :city => 'San Francisco' }, @band1)
|
||||
expect(results.results.count).to be 0
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ describe User do
|
|||
end
|
||||
|
||||
it "should allow search of one band with an exact match" do
|
||||
ws = Band.search("Example Band")
|
||||
ws = Search.band_search("Example Band").results
|
||||
ws.length.should == 1
|
||||
band_result = ws[0]
|
||||
band_result.name.should == @band.name
|
||||
|
|
@ -22,61 +22,61 @@ describe User do
|
|||
end
|
||||
|
||||
it "should allow search of one band with partial matches" do
|
||||
ws = Band.search("Ex")
|
||||
ws = Search.band_search("Ex").results
|
||||
ws.length.should == 1
|
||||
ws[0].id.should == @band.id
|
||||
|
||||
ws = Band.search("Exa")
|
||||
ws = Search.band_search("Exa").results
|
||||
ws.length.should == 1
|
||||
ws[0].id.should == @band.id
|
||||
|
||||
ws = Band.search("Exam")
|
||||
ws = Search.band_search("Exam").results
|
||||
ws.length.should == 1
|
||||
ws[0].id.should == @band.id
|
||||
|
||||
ws = Band.search("Examp")
|
||||
ws = Search.band_search("Examp").results
|
||||
ws.length.should == 1
|
||||
ws[0].id.should == @band.id
|
||||
|
||||
ws = Band.search("Exampl")
|
||||
ws = Search.band_search("Exampl").results
|
||||
ws.length.should == 1
|
||||
ws[0].id.should == @band.id
|
||||
|
||||
ws = Band.search("Example")
|
||||
ws = Search.band_search("Example").results
|
||||
ws.length.should == 1
|
||||
ws[0].id.should == @band.id
|
||||
|
||||
ws = Band.search("Ba")
|
||||
ws = Search.band_search("Ba").results
|
||||
ws.length.should == 1
|
||||
ws[0].id.should == @band.id
|
||||
|
||||
ws = Band.search("Ban")
|
||||
ws = Search.band_search("Ban").results
|
||||
ws.length.should == 1
|
||||
ws[0].id.should == @band.id
|
||||
end
|
||||
|
||||
it "should not match mid-word searchs" do
|
||||
ws = Band.search("xa")
|
||||
ws = Search.band_search("xa").results
|
||||
ws.length.should == 0
|
||||
|
||||
ws = Band.search("le")
|
||||
ws = Search.band_search("le").results
|
||||
ws.length.should == 0
|
||||
end
|
||||
|
||||
it "should delete band" do
|
||||
ws = Band.search("Example Band")
|
||||
ws = Search.band_search("Example Band").results
|
||||
ws.length.should == 1
|
||||
band_result = ws[0]
|
||||
band_result.id.should == @band.id
|
||||
|
||||
@band.destroy # delete doesn't work; you have to use destroy.
|
||||
|
||||
ws = Band.search("Example Band")
|
||||
ws = Search.band_search("Example Band").results
|
||||
ws.length.should == 0
|
||||
end
|
||||
|
||||
it "should update band" do
|
||||
ws = Band.search("Example Band")
|
||||
ws = Search.band_search("Example Band").results
|
||||
ws.length.should == 1
|
||||
band_result = ws[0]
|
||||
band_result.id.should == @band.id
|
||||
|
|
@ -84,10 +84,10 @@ describe User do
|
|||
@band.name = "bonus-stuff"
|
||||
@band.save
|
||||
|
||||
ws = Band.search("Example Band")
|
||||
ws = Search.band_search("Example Band").results
|
||||
ws.length.should == 0
|
||||
|
||||
ws = Band.search("Bonus")
|
||||
ws = Search.band_search("Bonus").results
|
||||
ws.length.should == 1
|
||||
band_result = ws[0]
|
||||
band_result.id.should == @band.id
|
||||
|
|
@ -96,7 +96,7 @@ describe User do
|
|||
|
||||
it "should tokenize correctly" do
|
||||
@band2 = Band.save(nil, "Peach pit", "www.bands.com", "zomg we rock", "Apex", "NC", "US", ["hip hop"], user.id, nil, nil)
|
||||
ws = Band.search("pea")
|
||||
ws = Search.band_search("pea").results
|
||||
ws.length.should == 1
|
||||
user_result = ws[0]
|
||||
user_result.id.should == @band2.id
|
||||
|
|
@ -105,12 +105,12 @@ describe User do
|
|||
|
||||
it "should not return anything with a 1 character search" do
|
||||
@band2 = Band.save(nil, "Peach pit", "www.bands.com", "zomg we rock", "Apex", "NC", "US", ["hip hop"], user.id, nil, nil)
|
||||
ws = Band.search("pe")
|
||||
ws = Search.band_search("pe").results
|
||||
ws.length.should == 1
|
||||
user_result = ws[0]
|
||||
user_result.id.should == @band2.id
|
||||
|
||||
ws = Band.search("p")
|
||||
ws = Search.band_search("p").results
|
||||
ws.length.should == 0
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Band do
|
||||
|
||||
let(:band) { FactoryGirl.create(:band) }
|
||||
|
||||
describe 'website update' do
|
||||
it 'should have http prefix on website url' do
|
||||
band.website = 'example.com'
|
||||
band.save!
|
||||
expect(band.website).to match(/^http:\/\/example.com$/)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -3,23 +3,57 @@ require 'spec_helper'
|
|||
describe IcecastAdminAuthentication do
|
||||
|
||||
let(:admin) { IcecastAdminAuthentication.new }
|
||||
let(:output) { StringIO.new }
|
||||
let(:builder) { ::Builder::XmlMarkup.new(:target => output, :indent => 1) }
|
||||
|
||||
before(:all) do
|
||||
admin.source_password = "GoodJob@</>"
|
||||
it "save error" do
|
||||
admin.save.should be_false
|
||||
admin.errors[:source_pass].length.should == 2
|
||||
admin.errors[:admin_user].length.should == 2
|
||||
admin.errors[:admin_pass].length.should == 2
|
||||
admin.errors[:relay_user].length.should == 2
|
||||
admin.errors[:relay_pass].length.should == 2
|
||||
end
|
||||
|
||||
it "save" do
|
||||
admin.save!
|
||||
#puts "source password #{admin.source_password}"
|
||||
#puts "id #{admin.id}"
|
||||
#puts admin.errors
|
||||
#puts admin.inspect
|
||||
#puts admin.to_yaml
|
||||
#puts JSON.pretty_generate admin
|
||||
#puts admin.dumpXml (1)
|
||||
#puts admin.errors.inspect
|
||||
admin.errors.any?.should be_false
|
||||
admin.source_pass = Faker::Lorem.characters(10)
|
||||
admin.admin_user = Faker::Lorem.characters(10)
|
||||
admin.admin_pass = Faker::Lorem.characters(10)
|
||||
admin.relay_user = Faker::Lorem.characters(10)
|
||||
admin.relay_pass = Faker::Lorem.characters(10)
|
||||
|
||||
admin.save.should be_true
|
||||
|
||||
admin.dumpXml(builder)
|
||||
|
||||
output.rewind
|
||||
|
||||
xml = Nokogiri::XML(output)
|
||||
xml.css('authentication source-password').text.should == admin.source_pass
|
||||
xml.css('authentication source-password').length.should == 1
|
||||
xml.css('authentication admin-user').text.should == admin.admin_user
|
||||
xml.css('authentication admin-user').length.should == 1
|
||||
xml.css('authentication relay-user').text.should == admin.relay_user
|
||||
xml.css('authentication relay-user').length.should == 1
|
||||
xml.css('authentication relay-password').text.should == admin.relay_pass
|
||||
xml.css('authentication relay-password').length.should == 1
|
||||
xml.css('authentication admin-password').text.should == admin.admin_pass
|
||||
xml.css('authentication admin-password').length.should == 1
|
||||
end
|
||||
|
||||
describe "poke configs" do
|
||||
let(:server) { a = FactoryGirl.create(:icecast_server_with_overrides); a.config_updated; IcecastServer.find(a.id) }
|
||||
|
||||
it "success via template" do
|
||||
server.template.admin_auth.save!
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
|
||||
it "success via server" do
|
||||
server.admin_auth.save!
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,15 +1,67 @@
|
|||
require 'spec_helper'
|
||||
require 'stringio'
|
||||
|
||||
=begin
|
||||
example output:
|
||||
|
||||
<directory>
|
||||
<yp-url-timeout>15</yp-url-timeout>
|
||||
<yp-url>http://dir.xiph.org/cgi-bin/yp-cgi</yp-url>
|
||||
</directory>
|
||||
=end
|
||||
describe IcecastDirectory do
|
||||
|
||||
let(:idir) { IcecastDirectory.new }
|
||||
let(:dir) { IcecastDirectory.new }
|
||||
let(:output) { StringIO.new }
|
||||
let(:builder) { ::Builder::XmlMarkup.new(:target => output, :indent => 1) }
|
||||
|
||||
before(:all) do
|
||||
before(:each) do
|
||||
|
||||
end
|
||||
|
||||
it "save error" do
|
||||
dir.save.should be_false
|
||||
dir.errors[:yp_url].length.should == 1
|
||||
dir.errors[:yp_url_timeout].length.should == 0
|
||||
end
|
||||
|
||||
it "save" do
|
||||
idir.save.should be_true
|
||||
dir.yp_url = Faker::Lorem.characters(10)
|
||||
dir.yp_url_timeout = 20
|
||||
dir.save.should be_true
|
||||
dir.dumpXml(builder)
|
||||
|
||||
output.rewind
|
||||
xml = Nokogiri::XML(output)
|
||||
xml.css('directory yp-url-timeout').text.should == dir.yp_url_timeout.to_s
|
||||
xml.css('directory yp-url-timeout').length.should == 1
|
||||
xml.css('directory yp-url').text.should == dir.yp_url
|
||||
xml.css('directory yp-url').length.should == 1
|
||||
end
|
||||
|
||||
describe "poke configs" do
|
||||
let(:server) { a = FactoryGirl.create(:icecast_server_with_overrides); a.config_updated; IcecastServer.find(a.id) }
|
||||
|
||||
before(:each) do
|
||||
server.directory = FactoryGirl.create(:icecast_directory)
|
||||
server.template.directory = FactoryGirl.create(:icecast_directory)
|
||||
server.template.save!
|
||||
server.save!
|
||||
server.config_updated
|
||||
server.reload
|
||||
end
|
||||
|
||||
it "success via template" do
|
||||
server.template.directory.save!
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
|
||||
it "success via server" do
|
||||
server.directory.save!
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,26 +3,73 @@ require 'spec_helper'
|
|||
describe IcecastLimit do
|
||||
|
||||
let(:limit) { IcecastLimit.new }
|
||||
let(:output) { StringIO.new }
|
||||
let(:builder) { ::Builder::XmlMarkup.new(:target => output, :indent => 1) }
|
||||
|
||||
before(:all) do
|
||||
|
||||
it "save defaults" do
|
||||
limit.save.should be_true
|
||||
limit.dumpXml(builder)
|
||||
|
||||
output.rewind
|
||||
|
||||
xml = Nokogiri::XML(output)
|
||||
xml.css('limits clients').text.should == "1000"
|
||||
xml.css('limits clients').length.should == 1
|
||||
xml.css('limits sources').text.should == "50"
|
||||
xml.css('limits sources').length.should == 1
|
||||
xml.css('limits queue-size').text.should == "102400"
|
||||
xml.css('limits queue-size').length.should == 1
|
||||
xml.css('limits client-timeout').text.should == "30"
|
||||
xml.css('limits client-timeout').length.should == 1
|
||||
xml.css('limits header-timeout').text.should == "15"
|
||||
xml.css('limits header-timeout').length.should == 1
|
||||
xml.css('limits source-timeout').text.should == "10"
|
||||
xml.css('limits source-timeout').length.should == 1
|
||||
xml.css('limits burst-on-connect').text.should == "1"
|
||||
xml.css('limits burst-on-connect').length.should == 1
|
||||
xml.css('limits burst-size').text.should == "65536"
|
||||
xml.css('limits burst-size').length.should == 1
|
||||
end
|
||||
|
||||
it "save" do
|
||||
limit.clients = 9999
|
||||
limit.save
|
||||
#limit.dumpXml
|
||||
limit.errors.any?.should be_false
|
||||
v = IcecastLimit.find(limit.id)
|
||||
it "save specified" do
|
||||
limit.clients = 10000
|
||||
limit.sources = 2000
|
||||
limit.queue_size = 1000
|
||||
limit.client_timeout = 10
|
||||
limit.header_timeout = 20
|
||||
limit.source_timeout = 30
|
||||
limit.burst_size = 1000
|
||||
|
||||
limit.save.should be_true
|
||||
limit.dumpXml(builder)
|
||||
|
||||
output.rewind
|
||||
|
||||
xml = Nokogiri::XML(output)
|
||||
xml.css('limits clients').text.should == limit.clients.to_s
|
||||
xml.css('limits sources').text.should == limit.sources.to_s
|
||||
xml.css('limits queue-size').text.should == limit.queue_size.to_s
|
||||
xml.css('limits client-timeout').text.should == limit.client_timeout.to_s
|
||||
xml.css('limits header-timeout').text.should == limit.header_timeout.to_s
|
||||
xml.css('limits source-timeout').text.should == limit.source_timeout.to_s
|
||||
xml.css('limits burst-on-connect').text.should == "1"
|
||||
xml.css('limits burst-size').text.should == limit.burst_size.to_s
|
||||
end
|
||||
|
||||
=begin
|
||||
it "non-integer clients should be checked" do
|
||||
limit.setclients 'a'
|
||||
puts limit.clients
|
||||
puts limit.inspect
|
||||
limit.save.should be_false
|
||||
limit.errors[:clients].should == ['is not a number']
|
||||
describe "poke configs" do
|
||||
let(:server) { a = FactoryGirl.create(:icecast_server_with_overrides); a.config_updated; IcecastServer.find(a.id) }
|
||||
|
||||
it "success via template" do
|
||||
server.template.limit.save!
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
|
||||
it "success via server" do
|
||||
server.limit.save!
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
end
|
||||
=end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,14 +2,35 @@ require 'spec_helper'
|
|||
|
||||
describe IcecastListenSocket do
|
||||
|
||||
let(:iobj) { IcecastListenSocket.new }
|
||||
|
||||
before(:all) do
|
||||
|
||||
end
|
||||
let(:listen) { IcecastListenSocket.new }
|
||||
let(:output) { StringIO.new }
|
||||
let(:builder) { ::Builder::XmlMarkup.new(:target => output, :indent => 1) }
|
||||
|
||||
it "save" do
|
||||
iobj.save.should be_true
|
||||
listen.save!
|
||||
listen.dumpXml(builder)
|
||||
|
||||
output.rewind
|
||||
xml = Nokogiri::XML(output)
|
||||
xml.css('listen-socket port').text.should == "8001"
|
||||
xml.css('listen-socket shoutcast-compat').length.should == 0
|
||||
xml.css('listen-socket shoutcast-mount').length.should == 0
|
||||
xml.css('listen-socket bind-address').length.should == 0
|
||||
end
|
||||
|
||||
describe "poke configs" do
|
||||
let(:server) { a = FactoryGirl.create(:icecast_server_with_overrides); a.config_updated; IcecastServer.find(a.id) }
|
||||
|
||||
it "success via template" do
|
||||
server.template.listen_sockets.first.save!
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
|
||||
it "success via server" do
|
||||
server.listen_sockets.first.save!
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,14 +2,48 @@ require 'spec_helper'
|
|||
|
||||
describe IcecastLogging do
|
||||
|
||||
let(:iobj) { IcecastLogging.new }
|
||||
|
||||
before(:all) do
|
||||
let(:logging) { IcecastLogging.new }
|
||||
let(:output) { StringIO.new }
|
||||
let(:builder) { ::Builder::XmlMarkup.new(:target => output, :indent => 1) }
|
||||
|
||||
it "save works by default db values" do
|
||||
logging.save.should be_true
|
||||
logging.access_log.should == 'access.log'
|
||||
logging.error_log.should == 'error.log'
|
||||
end
|
||||
|
||||
|
||||
it "save" do
|
||||
iobj.save.should be_true
|
||||
logging.access_log = Faker::Lorem.characters(10)
|
||||
logging.error_log = Faker::Lorem.characters(10)
|
||||
logging.log_level = 4
|
||||
logging.log_size = 20000
|
||||
logging.save!
|
||||
|
||||
logging.dumpXml(builder)
|
||||
|
||||
output.rewind
|
||||
xml = Nokogiri::XML(output)
|
||||
xml.css('logging accesslog').text.should == logging.access_log
|
||||
xml.css('logging errorlog').text.should == logging.error_log
|
||||
xml.css('logging loglevel').text.should == logging.log_level.to_s
|
||||
xml.css('logging logsize').text.should == logging.log_size.to_s
|
||||
xml.css('logging playlistlog').length.should == 0
|
||||
xml.css('logging logarchive').length.should == 0
|
||||
end
|
||||
|
||||
describe "poke configs" do
|
||||
let(:server) { a = FactoryGirl.create(:icecast_server_with_overrides); a.config_updated; IcecastServer.find(a.id) }
|
||||
|
||||
it "success via template" do
|
||||
server.template.logging.save!
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
|
||||
it "success via server" do
|
||||
server.logging.save!
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe IcecastMasterServerRelay do
|
||||
|
||||
let(:relay) { IcecastMasterServerRelay.new }
|
||||
let(:output){ StringIO.new }
|
||||
let(:root) { ::Builder::XmlMarkup.new(:target => output, :indent => 1) }
|
||||
|
||||
|
||||
it "should not save" do
|
||||
relay.save.should be_false
|
||||
relay.errors[:master_pass].should == ["can't be blank", "is too short (minimum is 5 characters)"]
|
||||
relay.errors[:master_username].should == ["can't be blank", "is too short (minimum is 5 characters)"]
|
||||
relay.errors[:master_server].should == ["can't be blank", "is too short (minimum is 1 characters)"]
|
||||
end
|
||||
|
||||
it "should save" do
|
||||
relay.master_server = "test.www.com"
|
||||
relay.master_server_port = 7111
|
||||
relay.master_username = "hackme-user"
|
||||
relay.master_pass = "hackme-password"
|
||||
relay.save!
|
||||
|
||||
root.tag! 'root' do |builder|
|
||||
relay.dumpXml(builder)
|
||||
end
|
||||
|
||||
output.rewind
|
||||
xml = Nokogiri::XML(output)
|
||||
xml.css('root master-server').text.should == relay.master_server.to_s
|
||||
xml.css('root master-server-port').text.should == relay.master_server_port.to_s
|
||||
xml.css('root master-update-interval').text.should == relay.master_update_interval.to_s
|
||||
xml.css('root master-username').text.should == relay.master_username.to_s
|
||||
xml.css('root master-password').text.should == relay.master_pass.to_s
|
||||
xml.css('root relays-on-demand').text.should == relay.relays_on_demand.to_s
|
||||
end
|
||||
|
||||
describe "poke configs" do
|
||||
let(:server) { a = FactoryGirl.create(:icecast_server_with_overrides); a.config_updated; IcecastServer.find(a.id) }
|
||||
|
||||
before(:each) do
|
||||
server.master_relay = FactoryGirl.create(:icecast_master_server_relay)
|
||||
server.template.master_relay = FactoryGirl.create(:icecast_master_server_relay)
|
||||
server.template.save!
|
||||
server.save!
|
||||
server.config_updated
|
||||
server.reload
|
||||
end
|
||||
|
||||
it "success via template" do
|
||||
server.template.master_relay.save!
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
|
||||
it "success via server" do
|
||||
server.master_relay.save!
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe IcecastMastersvrRelay do
|
||||
|
||||
let(:iobj) { IcecastMastersvrRelay.new }
|
||||
|
||||
before(:all) do
|
||||
|
||||
end
|
||||
|
||||
|
||||
=begin
|
||||
it "should not save" do
|
||||
iobj.save.should be_false
|
||||
iobj.errors[:master_server].should_equal "is required"
|
||||
end
|
||||
=end
|
||||
|
||||
it "should save" do
|
||||
iobj.master_server = "test.www.com"
|
||||
iobj.master_server_port = 7111
|
||||
iobj.master_username = "hack"
|
||||
iobj.master_password = "hackme"
|
||||
iobj.save.should be_true
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -2,16 +2,95 @@ require 'spec_helper'
|
|||
|
||||
describe IcecastMount do
|
||||
|
||||
let(:iobj) { IcecastMount.new }
|
||||
|
||||
before(:all) do
|
||||
let(:icecast_mount) { FactoryGirl.create(:icecast_mount) }
|
||||
let(:output) { StringIO.new }
|
||||
let(:builder) { ::Builder::XmlMarkup.new(:target => output, :indent => 1) }
|
||||
|
||||
it "save error" do
|
||||
mount = IcecastMount.new
|
||||
mount.save.should be_false
|
||||
mount.errors[:name].should == ["can't be blank", "must start with /"]
|
||||
mount.errors[:stream_name].should == ["can't be blank"]
|
||||
mount.errors[:stream_description].should == ["can't be blank"]
|
||||
mount.errors[:stream_url].should == ["can't be blank"]
|
||||
mount.errors[:genre].should == ["can't be blank"]
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
it "save" do
|
||||
iobj.save.should be_true
|
||||
end
|
||||
=end
|
||||
mount = IcecastMount.new
|
||||
mount.name = "/" + Faker::Lorem.characters(10)
|
||||
mount.stream_name = Faker::Lorem.characters(10)
|
||||
mount.stream_description = Faker::Lorem.characters(10)
|
||||
mount.stream_url = Faker::Lorem.characters(10)
|
||||
mount.genre = Faker::Lorem.characters(10)
|
||||
mount.source_username = Faker::Lorem.characters(10)
|
||||
mount.source_pass = Faker::Lorem.characters(10)
|
||||
mount.intro = Faker::Lorem.characters(10)
|
||||
mount.fallback_mount = Faker::Lorem.characters(10)
|
||||
mount.on_connect = Faker::Lorem.characters(10)
|
||||
mount.on_disconnect = Faker::Lorem.characters(10)
|
||||
mount.fallback_override = true
|
||||
mount.fallback_when_full = true
|
||||
mount.max_listeners = 1000
|
||||
mount.max_listener_duration = 3600
|
||||
mount.authentication = FactoryGirl.create(:icecast_user_authentication)
|
||||
|
||||
mount.save!
|
||||
|
||||
mount.dumpXml(builder)
|
||||
|
||||
output.rewind
|
||||
|
||||
xml = Nokogiri::XML(output)
|
||||
xml.css('mount mount-name').text.should == mount.name
|
||||
xml.css('mount username').text.should == mount.source_username
|
||||
xml.css('mount password').text.should == mount.source_pass
|
||||
xml.css('mount max-listeners').text.should == mount.max_listeners.to_s
|
||||
xml.css('mount max-listener-duration').text.should == mount.max_listener_duration.to_s
|
||||
xml.css('mount intro').text.should == mount.intro
|
||||
xml.css('mount fallback-mount').text.should == mount.fallback_mount
|
||||
xml.css('mount fallback-override').text.should == mount.fallback_override.to_s
|
||||
xml.css('mount fallback-when-full').text.should == mount.fallback_when_full.to_s
|
||||
xml.css('mount stream-name').text.should == mount.stream_name
|
||||
xml.css('mount stream-description').text.should == mount.stream_description
|
||||
xml.css('mount stream-url').text.should == mount.stream_url
|
||||
xml.css('mount genre').text.should == mount.genre
|
||||
xml.css('mount bitrate').length.should == 0
|
||||
xml.css('mount charset').text == mount.charset
|
||||
xml.css('mount public').text == mount.is_public.to_s
|
||||
xml.css('mount type').text == mount.mime_type
|
||||
xml.css('mount subtype').text == mount.subtype
|
||||
xml.css('mount burst-size').length.should == 0
|
||||
xml.css('mount mp3-metadata-interval').length.should == 0
|
||||
xml.css('mount hidden').text.should == mount.hidden.to_s
|
||||
xml.css('mount on-connect').text.should == mount.on_connect
|
||||
xml.css('mount on-disconnect').text.should == mount.on_disconnect
|
||||
xml.css('mount dump-file').length.should == 0
|
||||
xml.css('mount authentication').length.should == 1 # no reason to test futher; it's tested in that model
|
||||
end
|
||||
|
||||
describe "poke configs" do
|
||||
let(:server) { a = FactoryGirl.create(:icecast_server_with_overrides); a.config_updated; IcecastServer.find(a.id) }
|
||||
|
||||
before(:each) do
|
||||
server.mounts << FactoryGirl.create(:icecast_mount)
|
||||
server.save!
|
||||
server.config_updated
|
||||
server.reload
|
||||
server.config_changed.should == 0
|
||||
end
|
||||
|
||||
it "success via server" do
|
||||
server.mounts.first.save!
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
end
|
||||
|
||||
describe "icecast server callbacks" do
|
||||
it "source up" do
|
||||
icecast_mount.source_up
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -2,14 +2,72 @@ require 'spec_helper'
|
|||
|
||||
describe IcecastPath do
|
||||
|
||||
let(:iobj) { IcecastPath.new }
|
||||
let(:path) { IcecastPath.new }
|
||||
let(:output) { StringIO.new }
|
||||
let(:builder) { ::Builder::XmlMarkup.new(:target => output, :indent => 1) }
|
||||
|
||||
before(:all) do
|
||||
it "save default" do
|
||||
path.save.should be_true
|
||||
path.dumpXml(builder)
|
||||
|
||||
output.rewind
|
||||
|
||||
xml = Nokogiri::XML(output)
|
||||
xml.css('paths basedir').text.should == "./"
|
||||
xml.css('paths basedir').length.should == 1
|
||||
xml.css('paths logdir').text.should == "./logs"
|
||||
xml.css('paths logdir').length.should == 1
|
||||
xml.css('paths pidfile').text.should == "./icecast.pid"
|
||||
xml.css('paths pidfile').length.should == 1
|
||||
xml.css('paths webroot').text.should == "./web"
|
||||
xml.css('paths webroot').length.should == 1
|
||||
xml.css('paths adminroot').text.should == "./admin"
|
||||
xml.css('paths adminroot').length.should == 1
|
||||
xml.css('paths allow-ip').length.should == 0
|
||||
xml.css('paths deny-ip').length.should == 0
|
||||
xml.css('paths alias').length.should == 0
|
||||
end
|
||||
|
||||
it "save" do
|
||||
iobj.save.should be_true
|
||||
it "save set values" do
|
||||
path.base_dir = Faker::Lorem.characters(10)
|
||||
path.log_dir = Faker::Lorem.characters(10)
|
||||
path.pid_file = Faker::Lorem.characters(10)
|
||||
path.web_root = Faker::Lorem.characters(10)
|
||||
path.admin_root = Faker::Lorem.characters(10)
|
||||
path.allow_ip = Faker::Lorem.characters(10)
|
||||
path.deny_ip = Faker::Lorem.characters(10)
|
||||
path.alias_source = Faker::Lorem.characters(10)
|
||||
path.alias_dest = Faker::Lorem.characters(10)
|
||||
path.save.should be_true
|
||||
path.dumpXml(builder)
|
||||
|
||||
output.rewind
|
||||
|
||||
xml = Nokogiri::XML(output)
|
||||
xml.css('paths basedir').text.should == path.base_dir
|
||||
xml.css('paths logdir').text.should == path.log_dir
|
||||
xml.css('paths pidfile').text.should == path.pid_file
|
||||
xml.css('paths webroot').text.should == path.web_root
|
||||
xml.css('paths adminroot').text.should == path.admin_root
|
||||
xml.css('paths allow-ip').text.should == path.allow_ip
|
||||
xml.css('paths deny-ip').text.should == path.deny_ip
|
||||
xml.css('paths alias').first['source'] == path.alias_source
|
||||
xml.css('paths alias').first['dest'] == path.alias_dest
|
||||
end
|
||||
|
||||
describe "poke configs" do
|
||||
let(:server) { a = FactoryGirl.create(:icecast_server_with_overrides); a.config_updated; IcecastServer.find(a.id) }
|
||||
|
||||
it "success via template" do
|
||||
server.template.path.save!
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
|
||||
it "success via server" do
|
||||
server.path.save!
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -2,16 +2,51 @@ require 'spec_helper'
|
|||
|
||||
describe IcecastRelay do
|
||||
|
||||
let(:iobj) { IcecastRelay.new }
|
||||
let(:relay) { IcecastRelay.new }
|
||||
let(:output){ StringIO.new }
|
||||
let(:builder) { ::Builder::XmlMarkup.new(:target => output, :indent => 1) }
|
||||
|
||||
before(:all) do
|
||||
|
||||
it "should not save" do
|
||||
relay.save.should be_false
|
||||
relay.errors[:mount].should == ["can't be blank"]
|
||||
relay.errors[:server].should == ["can't be blank"]
|
||||
end
|
||||
|
||||
=begin
|
||||
it "save" do
|
||||
:iobj.save.should be_true
|
||||
end
|
||||
=end
|
||||
relay.mount = Faker::Lorem.characters(10)
|
||||
relay.server = Faker::Lorem.characters(10)
|
||||
relay.relay_shoutcast_metadata = false
|
||||
relay.save!
|
||||
|
||||
relay.dumpXml(builder)
|
||||
|
||||
output.rewind
|
||||
xml = Nokogiri::XML(output)
|
||||
xml.css('relay port').text.should == relay.port.to_s
|
||||
xml.css('relay mount').text.should == relay.mount
|
||||
xml.css('relay server').text.should == relay.server
|
||||
xml.css('relay local-mount').length.should == 0
|
||||
xml.css('relay username').length.should == 0
|
||||
xml.css('relay password').length.should == 0
|
||||
xml.css('relay relay-shoutcast-metadata').text.should == "0"
|
||||
xml.css('relay on-demand').text.should == "1"
|
||||
end
|
||||
|
||||
describe "poke configs" do
|
||||
let(:server) { a = FactoryGirl.create(:icecast_server_with_overrides); a.config_updated; IcecastServer.find(a.id) }
|
||||
|
||||
before(:each) do
|
||||
server.relays << FactoryGirl.create(:icecast_relay)
|
||||
server.save!
|
||||
server.config_updated
|
||||
server.reload
|
||||
end
|
||||
|
||||
it "success via server" do
|
||||
server.relays.first.save!
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe IcecastSecurity do
|
||||
|
||||
let(:security) { IcecastSecurity.new }
|
||||
let(:output) { StringIO.new }
|
||||
let(:builder) { ::Builder::XmlMarkup.new(:target => output, :indent => 1) }
|
||||
|
||||
it "save with chroot" do
|
||||
security.change_owner_user ="hotdog"
|
||||
security.change_owner_group ="mongrel"
|
||||
security.chroot = 1
|
||||
security.save!
|
||||
security.dumpXml(builder)
|
||||
|
||||
output.rewind
|
||||
xml = Nokogiri::XML(output)
|
||||
xml.css('security chroot').text.should == '1'
|
||||
xml.css('security changeowner user').text.should == 'hotdog'
|
||||
xml.css('security changeowner group').text.should == 'mongrel'
|
||||
end
|
||||
|
||||
it "save without chroot" do
|
||||
security.save!
|
||||
security.dumpXml(builder)
|
||||
|
||||
output.rewind
|
||||
|
||||
xml = Nokogiri::XML(output)
|
||||
xml.css('security chroot').text.should == '0'
|
||||
xml.css('security changeowner').length.should == 0
|
||||
end
|
||||
|
||||
describe "poke configs" do
|
||||
let(:server) { a = FactoryGirl.create(:icecast_server_with_overrides); a.config_updated; IcecastServer.find(a.id) }
|
||||
|
||||
it "success via template" do
|
||||
server.template.security.save!
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
|
||||
it "success via server" do
|
||||
server.security.save!
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe IcecastServer do
|
||||
|
||||
let(:server) { IcecastServer.new }
|
||||
let(:output) { StringIO.new }
|
||||
let(:builder) { ::Builder::XmlMarkup.new(:target => output, :indent => 1) }
|
||||
|
||||
|
||||
it "save" do
|
||||
server = FactoryGirl.create(:icecast_server_minimal)
|
||||
server.save!
|
||||
server.reload
|
||||
server.dumpXml(output)
|
||||
|
||||
output.rewind
|
||||
|
||||
xml = Nokogiri::XML(output)
|
||||
xml.css('icecast hostname').text.should == server.hostname
|
||||
xml.css('icecast server-id').text.should == server.server_id
|
||||
xml.css('icecast location').text.should == server.template.location
|
||||
xml.css('icecast admin').text.should == server.template.admin_email
|
||||
xml.css('icecast fileserve').text.should == server.template.fileserve.to_s
|
||||
xml.css('icecast limits').length.should == 1
|
||||
xml.css('icecast authentication').length.should == 1
|
||||
xml.css('icecast directory').length.should == 0
|
||||
xml.css('icecast master-server').length.should == 0
|
||||
xml.css('icecast paths').length.should == 1
|
||||
xml.css('icecast logging').length.should == 1
|
||||
xml.css('icecast security').length.should == 1
|
||||
xml.css('icecast listen-socket').length.should == 1
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe IcecastListenSocket do
|
||||
|
||||
let(:template) { template = FactoryGirl.create(:icecast_template_minimal) }
|
||||
|
||||
it "save" do
|
||||
template.errors.any?.should be_false
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe IcecastUserAuthentication do
|
||||
|
||||
let(:auth) { IcecastUserAuthentication.new }
|
||||
let(:output) { StringIO.new }
|
||||
let(:builder) { ::Builder::XmlMarkup.new(:target => output, :indent => 1) }
|
||||
|
||||
it "save error" do
|
||||
auth.save.should be_false
|
||||
auth.errors[:mount_add].should == ["can't be blank"]
|
||||
auth.errors[:mount_remove].should == ["can't be blank"]
|
||||
auth.errors[:listener_add].should == ["can't be blank"]
|
||||
auth.errors[:listener_remove].should == ["can't be blank"]
|
||||
#auth.errors[:unused_username].should == ["is too short (minimum is 5 characters)"]
|
||||
#auth.errors[:unused_pass].should == ["is too short (minimum is 5 characters)"]
|
||||
end
|
||||
|
||||
it "save" do
|
||||
auth.mount_add = Faker::Lorem.characters(10)
|
||||
auth.mount_remove = Faker::Lorem.characters(10)
|
||||
auth.listener_add = Faker::Lorem.characters(10)
|
||||
auth.listener_remove = Faker::Lorem.characters(10)
|
||||
auth.unused_username = Faker::Lorem.characters(10)
|
||||
auth.unused_pass = Faker::Lorem.characters(10)
|
||||
|
||||
auth.save!
|
||||
|
||||
auth.dumpXml(builder)
|
||||
|
||||
output.rewind
|
||||
|
||||
xml = Nokogiri::XML(output)
|
||||
xml.css('authentication')[0]["type"].should == auth.authentication_type
|
||||
xml.css('authentication option[name="mount_add"]')[0]["value"].should == auth.mount_add
|
||||
xml.css('authentication option[name="mount_remove"]')[0]["value"].should == auth.mount_remove
|
||||
xml.css('authentication option[name="listener_add"]')[0]["value"].should == auth.listener_add
|
||||
xml.css('authentication option[name="listener_remove"]')[0]["value"].should == auth.listener_remove
|
||||
xml.css('authentication option[name="username"]')[0]["value"].should == auth.unused_username
|
||||
xml.css('authentication option[name="password"]')[0]["value"].should == auth.unused_pass
|
||||
xml.css('authentication option[name="auth_header"]')[0]["value"].should == auth.auth_header
|
||||
xml.css('authentication option[name="timelimit_header"]')[0]["value"].should == auth.timelimit_header
|
||||
end
|
||||
|
||||
describe "poke configs" do
|
||||
let(:server) { a = FactoryGirl.create(:icecast_server_with_overrides); a.config_updated; IcecastServer.find(a.id) }
|
||||
|
||||
before(:each) do
|
||||
server.mounts << FactoryGirl.create(:icecast_mount_with_auth)
|
||||
server.save!
|
||||
server.config_updated
|
||||
server.reload
|
||||
end
|
||||
|
||||
it "success via server" do
|
||||
server.mounts.first.authentication.save!
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -17,15 +17,16 @@ describe 'Musician search' do
|
|||
it "finds all musicians" do
|
||||
# expects all the users
|
||||
num = User.musicians.count
|
||||
results = Search.musician_search({ :per_page => num })
|
||||
expect(results.musicians_filter.count).to eq(num)
|
||||
results = Search.musician_filter({ :per_page => num })
|
||||
expect(results.results.count).to eq(num)
|
||||
expect(results.search_type).to be(:musicians_filter)
|
||||
end
|
||||
|
||||
it "finds musicians with proper ordering" do
|
||||
# the ordering should be create_at since no followers exist
|
||||
expect(UserFollower.count).to eq(0)
|
||||
results = Search.musician_search({ :per_page => User.musicians.count })
|
||||
results.musicians_filter.each_with_index do |uu, idx|
|
||||
results = Search.musician_filter({ :per_page => User.musicians.count })
|
||||
results.results.each_with_index do |uu, idx|
|
||||
expect(uu.id).to eq(@users.reverse[idx].id)
|
||||
end
|
||||
end
|
||||
|
|
@ -40,11 +41,11 @@ describe 'Musician search' do
|
|||
|
||||
# refresh the order to ensure it works right
|
||||
@user2.followers.concat([@user3, @user4, @user2])
|
||||
results = Search.musician_search({ :per_page => @users.size }, @user3)
|
||||
expect(results.musicians_filter[0].id).to eq(@user2.id)
|
||||
results = Search.musician_filter({ :per_page => @users.size }, @user3)
|
||||
expect(results.results[0].id).to eq(@user2.id)
|
||||
|
||||
# check the follower count for given entry
|
||||
expect(results.musicians_filter[0].search_follow_count.to_i).not_to eq(0)
|
||||
expect(results.results[0].search_follow_count.to_i).not_to eq(0)
|
||||
# check the follow relationship between current_user and result
|
||||
expect(results.is_follower?(@user2)).to be true
|
||||
end
|
||||
|
|
@ -52,8 +53,8 @@ describe 'Musician search' do
|
|||
it 'paginates properly' do
|
||||
# make sure pagination works right
|
||||
params = { :per_page => 2, :page => 1 }
|
||||
results = Search.musician_search(params)
|
||||
expect(results.musicians_filter.count).to be 2
|
||||
results = Search.musician_filter(params)
|
||||
expect(results.results.count).to be 2
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -95,8 +96,8 @@ describe 'Musician search' do
|
|||
# create friendship record
|
||||
Friendship.save(@user1.id, @user2.id)
|
||||
# search on user2
|
||||
results = Search.musician_search({}, @user2)
|
||||
friend = results.musicians_filter.detect { |mm| mm.id == @user1.id }
|
||||
results = Search.musician_filter({}, @user2)
|
||||
friend = results.results.detect { |mm| mm.id == @user1.id }
|
||||
expect(friend).to_not be_nil
|
||||
expect(results.friend_count(friend)).to be 1
|
||||
@user1.reload
|
||||
|
|
@ -114,8 +115,8 @@ describe 'Musician search' do
|
|||
expect(recording.claimed_recordings.length).to be 1
|
||||
expect(@user1.recordings.detect { |rr| rr == recording }).to_not be_nil
|
||||
|
||||
results = Search.musician_search({},@user1)
|
||||
uu = results.musicians_filter.detect { |mm| mm.id == @user1.id }
|
||||
results = Search.musician_filter({},@user1)
|
||||
uu = results.results.detect { |mm| mm.id == @user1.id }
|
||||
expect(uu).to_not be_nil
|
||||
|
||||
expect(results.record_count(uu)).to be 1
|
||||
|
|
@ -129,29 +130,29 @@ describe 'Musician search' do
|
|||
it "by plays" do
|
||||
make_recording(@user1)
|
||||
# order results by num recordings
|
||||
results = Search.musician_search({ :orderby => 'plays' }, @user2)
|
||||
expect(results.musicians_filter[0].id).to eq(@user1.id)
|
||||
results = Search.musician_filter({ :orderby => 'plays' }, @user2)
|
||||
expect(results.results[0].id).to eq(@user1.id)
|
||||
|
||||
# add more data and make sure order still correct
|
||||
make_recording(@user2); make_recording(@user2)
|
||||
results = Search.musician_search({ :orderby => 'plays' }, @user2)
|
||||
expect(results.musicians_filter[0].id).to eq(@user2.id)
|
||||
results = Search.musician_filter({ :orderby => 'plays' }, @user2)
|
||||
expect(results.results[0].id).to eq(@user2.id)
|
||||
end
|
||||
|
||||
it "by now playing" do
|
||||
# should get 1 result with 1 active session
|
||||
make_session(@user3)
|
||||
results = Search.musician_search({ :orderby => 'playing' }, @user2)
|
||||
expect(results.musicians_filter.count).to be 1
|
||||
expect(results.musicians_filter.first.id).to eq(@user3.id)
|
||||
results = Search.musician_filter({ :orderby => 'playing' }, @user2)
|
||||
expect(results.results.count).to be 1
|
||||
expect(results.results.first.id).to eq(@user3.id)
|
||||
|
||||
# should get 2 results with 2 active sessions
|
||||
# sort order should be created_at DESC
|
||||
make_session(@user4)
|
||||
results = Search.musician_search({ :orderby => 'playing' }, @user2)
|
||||
expect(results.musicians_filter.count).to be 2
|
||||
expect(results.musicians_filter[0].id).to eq(@user4.id)
|
||||
expect(results.musicians_filter[1].id).to eq(@user3.id)
|
||||
results = Search.musician_filter({ :orderby => 'playing' }, @user2)
|
||||
expect(results.results.count).to be 2
|
||||
expect(results.results[0].id).to eq(@user4.id)
|
||||
expect(results.results[1].id).to eq(@user3.id)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -165,40 +166,40 @@ describe 'Musician search' do
|
|||
@user1.reload
|
||||
ii = @user1.instruments.detect { |inst| inst.id == 'tuba' }
|
||||
expect(ii).to_not be_nil
|
||||
results = Search.musician_search({ :instrument => ii.id })
|
||||
results.musicians_filter.each do |rr|
|
||||
results = Search.musician_filter({ :instrument => ii.id })
|
||||
results.results.each do |rr|
|
||||
expect(rr.instruments.detect { |inst| inst.id=='tuba' }.id).to eq(ii.id)
|
||||
end
|
||||
expect(results.musicians_filter.count).to be 1
|
||||
expect(results.results.count).to be 1
|
||||
end
|
||||
|
||||
it "finds musicians within a given distance of given location" do
|
||||
num = User.musicians.count
|
||||
expect(@user1.lat).to_not be_nil
|
||||
# short distance
|
||||
results = Search.musician_search({ :per_page => num,
|
||||
results = Search.musician_filter({ :per_page => num,
|
||||
:distance => 10,
|
||||
:city => 'Apex' }, @user1)
|
||||
expect(results.musicians_filter.count).to be num
|
||||
expect(results.results.count).to be num
|
||||
# long distance
|
||||
results = Search.musician_search({ :per_page => num,
|
||||
results = Search.musician_filter({ :per_page => num,
|
||||
:distance => 1000,
|
||||
:city => 'Miami',
|
||||
:state => 'FL' }, @user1)
|
||||
expect(results.musicians_filter.count).to be num
|
||||
expect(results.results.count).to be num
|
||||
end
|
||||
|
||||
it "finds musicians within a given distance of users location" do
|
||||
expect(@user1.lat).to_not be_nil
|
||||
# uses the location of @user1
|
||||
results = Search.musician_search({ :distance => 10, :per_page => User.musicians.count }, @user1)
|
||||
expect(results.musicians_filter.count).to be User.musicians.count
|
||||
results = Search.musician_filter({ :distance => 10, :per_page => User.musicians.count }, @user1)
|
||||
expect(results.results.count).to be User.musicians.count
|
||||
end
|
||||
|
||||
it "finds no musicians within a given distance of location" do
|
||||
expect(@user1.lat).to_not be_nil
|
||||
results = Search.musician_search({ :distance => 10, :city => 'San Francisco' }, @user1)
|
||||
expect(results.musicians_filter.count).to be 0
|
||||
results = Search.musician_filter({ :distance => 10, :city => 'San Francisco' }, @user1)
|
||||
expect(results.results.count).to be 0
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -230,94 +230,6 @@ describe Recording do
|
|||
downloads["downloads"].length.should == 1
|
||||
end
|
||||
|
||||
|
||||
it "should return a file list for a user properly" do
|
||||
pending
|
||||
stub_const("APP_CONFIG", app_config)
|
||||
@recording = Recording.start(@music_session, @user)
|
||||
@recording.stop
|
||||
@recording.reload
|
||||
@genre = FactoryGirl.create(:genre)
|
||||
@recording.claim(@user, "Recording", "Recording Description", @genre, true, true)
|
||||
Recording.list_downloads(@user)["downloads"].length.should == 0
|
||||
Recording.list_uploads(@user)["uploads"].length.should == 1
|
||||
file = Recording.list_uploads(@user)["uploads"].first
|
||||
@recorded_track = @recording.recorded_tracks.first
|
||||
@recorded_track.upload_start(25000, "md5hash")
|
||||
@recorded_track.upload_complete
|
||||
Recording.list_downloads(@user)["downloads"].length.should == 1
|
||||
Recording.list_uploads(@user)["uploads"].length.should == 0
|
||||
file = Recording.list(@user)["downloads"].first
|
||||
file[:type].should == "recorded_track"
|
||||
file[:id].should == @recorded_track.id
|
||||
file[:length].should == 25000
|
||||
file[:md5].should == "md5hash"
|
||||
file[:url].should == S3Manager.url(S3Manager.hashed_filename('recorded_track', @recorded_track.id))
|
||||
|
||||
# Note that the recording should automatically schedule a mix when the upload completes
|
||||
@recording.mixes.length.should == 1
|
||||
@mix = Mix.next('server')
|
||||
@mix.should_not be_nil
|
||||
@mix.finish(50000, "md5hash")
|
||||
Recording.list_downloads(@user)["downloads"].length.should == 2
|
||||
Recording.list_uploads(@user)["uploads"].length.should == 0
|
||||
file = Recording.list_downloads(@user)["downloads"].last
|
||||
file[:type].should == "mix"
|
||||
file[:id].should == @mix.id
|
||||
file[:length].should == 50000
|
||||
file[:md5].should == "md5hash"
|
||||
file[:url].should == S3Manager.url(S3Manager.hashed_filename('mix', @mix.id))
|
||||
|
||||
end
|
||||
|
||||
it "should create a base mix manifest properly" do
|
||||
pending
|
||||
stub_const("APP_CONFIG", app_config)
|
||||
@user2 = FactoryGirl.create(:user)
|
||||
@connection2 = FactoryGirl.create(:connection, :user => @user)
|
||||
@instrument2 = FactoryGirl.create(:instrument, :description => 'a great instrument')
|
||||
@track2 = FactoryGirl.create(:track, :connection => @connection2, :instrument => @instrument2)
|
||||
@music_session.connections << @connection2
|
||||
@music_session.save
|
||||
@recording = Recording.start(@music_session, @user)
|
||||
#sleep 4
|
||||
@recording.stop
|
||||
@recording.recorded_tracks.length.should == 2
|
||||
@recorded_track = @recording.recorded_tracks.first
|
||||
@recorded_track.upload_start(25000, "md5hash")
|
||||
@recorded_track.upload_complete
|
||||
@recorded_track2 = @recording.recorded_tracks.last
|
||||
@recorded_track2.upload_start(50000, "md5hash2")
|
||||
@recorded_track2.upload_complete
|
||||
mix_manifest = @recording.base_mix_manifest
|
||||
mix_manifest.should_not be_nil
|
||||
files = mix_manifest["files"]
|
||||
files.should_not be_nil
|
||||
files.length.should == 2
|
||||
files.first["codec"].should == "vorbis"
|
||||
files.first["offset"].should == 0
|
||||
files.first["url"].should == @recording.recorded_tracks.first.url
|
||||
files.last["codec"].should == "vorbis"
|
||||
files.last["offset"].should == 0
|
||||
files.last["url"].should == @recording.recorded_tracks.last.url
|
||||
|
||||
timeline = mix_manifest["timeline"]
|
||||
timeline.should_not be_nil
|
||||
timeline.length.should == 2
|
||||
timeline.first["timestamp"].should == 0
|
||||
timeline.first["end"].should be_nil
|
||||
mix = timeline.first["mix"]
|
||||
mix.should_not be_nil
|
||||
mix.length.should == 2
|
||||
mix.first["balance"].should == 0
|
||||
mix.first["level"].should == 100
|
||||
mix.last["balance"].should == 0
|
||||
mix.last["level"].should == 100
|
||||
|
||||
timeline.last["timestamp"].should == @recording.duration
|
||||
timeline.last["end"].should == true
|
||||
end
|
||||
|
||||
describe "chance for everyone to keep or discard" do
|
||||
before(:each) do
|
||||
@user2 = FactoryGirl.create(:user)
|
||||
|
|
|
|||
|
|
@ -13,24 +13,24 @@ describe Search do
|
|||
end
|
||||
|
||||
def assert_peachy_data
|
||||
search = Search.search('peach')
|
||||
search = Search.musician_search('peach')
|
||||
search.results.length.should == 1
|
||||
obj = search.results[0]
|
||||
obj.should be_a_kind_of User
|
||||
obj.id.should == @user.id
|
||||
|
||||
search.recordings.length.should == 0
|
||||
search.bands.length.should == 1
|
||||
search.musicians.length.should == 1
|
||||
search.fans.length.should == 1
|
||||
search = Search.fan_search('peach')
|
||||
search.results.length.should == 1
|
||||
obj = search.results[0]
|
||||
obj.should be_a_kind_of User
|
||||
obj.id.should == @fan.id
|
||||
|
||||
musician = search.musicians[0]
|
||||
musician.should be_a_kind_of User
|
||||
musician.id.should == @user.id
|
||||
search = Search.band_search('peach')
|
||||
search.results.length.should == 1
|
||||
obj = search.results[0]
|
||||
obj.should be_a_kind_of Band
|
||||
obj.id.should == @band.id
|
||||
|
||||
band = search.bands[0]
|
||||
band.should be_a_kind_of Band
|
||||
band.id.should == @band.id
|
||||
|
||||
fan = search.fans[0]
|
||||
fan.should be_a_kind_of User
|
||||
fan.id.should == @fan.id
|
||||
end
|
||||
|
||||
it "search for band & musician " do
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ describe User do
|
|||
end
|
||||
|
||||
it "should allow search of one user" do
|
||||
ws = User.search("Example User")
|
||||
uu = FactoryGirl.create(:user, :musician => false)
|
||||
ws = Search.musician_search("Example User").results
|
||||
ws.length.should == 1
|
||||
user_result = ws[0]
|
||||
user_result.first_name.should == @user.first_name
|
||||
|
|
@ -19,20 +20,27 @@ describe User do
|
|||
user_result.musician.should == true
|
||||
end
|
||||
|
||||
it "should allow search of one fan" do
|
||||
uu = FactoryGirl.create(:user, :musician => false)
|
||||
ws = Search.fan_search(uu.name).results
|
||||
expect(ws.length).to be(1)
|
||||
expect(ws[0].id).to eq(uu.id)
|
||||
end
|
||||
|
||||
it "should delete user" do
|
||||
ws = User.search("Example User")
|
||||
ws = Search.musician_search("Example User").results
|
||||
ws.length.should == 1
|
||||
user_result = ws[0]
|
||||
user_result.id.should == @user.id
|
||||
|
||||
@user.destroy
|
||||
|
||||
ws = User.search("Example User")
|
||||
ws = Search.musician_search("Example User").results
|
||||
ws.length.should == 0
|
||||
end
|
||||
|
||||
it "should update user" do
|
||||
ws = User.search("Example User")
|
||||
ws = Search.musician_search("Example User").results
|
||||
ws.length.should == 1
|
||||
user_result = ws[0]
|
||||
user_result.id.should == @user.id
|
||||
|
|
@ -41,10 +49,10 @@ describe User do
|
|||
@user.last_name = "more-junk"
|
||||
@user.save
|
||||
|
||||
ws = User.search("Example User")
|
||||
ws = Search.musician_search("Example User").results
|
||||
ws.length.should == 0
|
||||
|
||||
ws = User.search("Bonus")
|
||||
ws = Search.musician_search("Bonus").results
|
||||
ws.length.should == 1
|
||||
user_result = ws[0]
|
||||
user_result.id.should == @user.id
|
||||
|
|
@ -55,7 +63,7 @@ describe User do
|
|||
@user2 = FactoryGirl.create(:user, first_name: "peaches", last_name: "test", email: "peach@example.com",
|
||||
password: "foobar", password_confirmation: "foobar", musician: true, email_confirmed: true,
|
||||
city: "Apex", state: "NC", country: "US")
|
||||
ws = User.search("pea")
|
||||
ws = Search.musician_search("pea").results
|
||||
ws.length.should == 1
|
||||
user_result = ws[0]
|
||||
user_result.id.should == @user2.id
|
||||
|
|
@ -65,14 +73,14 @@ describe User do
|
|||
@user3 = FactoryGirl.create(:user, first_name: "unconfirmed", last_name: "unconfirmed", email: "unconfirmed@example.com",
|
||||
password: "foobar", password_confirmation: "foobar", musician: true, email_confirmed: false,
|
||||
city: "Apex", state: "NC", country: "US")
|
||||
ws = User.search("unconfirmed")
|
||||
ws = Search.musician_search("unconfirmed").results
|
||||
ws.length.should == 1
|
||||
|
||||
# Ok, confirm the user, and see them show up
|
||||
@user3.email_confirmed = true
|
||||
@user3.save
|
||||
|
||||
ws = User.search("unconfirmed")
|
||||
ws = Search.musician_search("unconfirmed").results
|
||||
ws.length.should == 1
|
||||
user_result = ws[0]
|
||||
user_result.id.should == @user3.id
|
||||
|
|
|
|||
|
|
@ -21,39 +21,52 @@ describe MQRouter do
|
|||
@mq_router.user_publish_to_session(music_session, user1, "a message" ,:client_id => music_session_member1.client_id)
|
||||
end
|
||||
|
||||
it "user_publish_to_session works (checking exchange callbacks)" do
|
||||
|
||||
user1 = FactoryGirl.create(:user) # in the jam session
|
||||
user2 = FactoryGirl.create(:user) # in the jam session
|
||||
|
||||
music_session = FactoryGirl.create(:music_session, :creator => user1)
|
||||
|
||||
music_session_member1 = FactoryGirl.create(:connection, :user => user1, :music_session => music_session, :ip_address => "1.1.1.1", :client_id => "1")
|
||||
music_session_member2 = FactoryGirl.create(:connection, :user => user2, :music_session => music_session, :ip_address => "2.2.2.2", :client_id => "2")
|
||||
|
||||
|
||||
# this is necessary because other tests will call EM.schedule indirectly as they fiddle with AR models, since some of our
|
||||
# notifications are tied to model activity. So, the issue here is that you'll have an unknown known amount of
|
||||
# queued up messages ready to be sent to MQRouter (because EM.schedule will put deferred blocks onto @next_tick_queue),
|
||||
# resulting in messages from other tests being sent to client_exchange or user_exchange
|
||||
|
||||
# there is no API I can see to clear out the EM queue. so just open up the EM module and do it manually
|
||||
module EM
|
||||
@next_tick_queue = []
|
||||
describe "double MQRouter" do
|
||||
before(:all) do
|
||||
@original_client_exchange = MQRouter.client_exchange
|
||||
@original_user_exchange = MQRouter.user_exchange
|
||||
end
|
||||
|
||||
EM.run do
|
||||
after(:all) do
|
||||
MQRouter.client_exchange = @original_client_exchange
|
||||
MQRouter.user_exchange = @original_user_exchange
|
||||
end
|
||||
|
||||
# mock up exchange
|
||||
MQRouter.client_exchange = double("client_exchange")
|
||||
MQRouter.user_exchange = double("user_exchange")
|
||||
it "user_publish_to_session works (checking exchange callbacks)" do
|
||||
|
||||
MQRouter.client_exchange.should_receive(:publish).with("a message", :routing_key => "client.#{music_session_member2.client_id}")
|
||||
MQRouter.user_exchange.should_not_receive(:publish)
|
||||
user1 = FactoryGirl.create(:user) # in the jam session
|
||||
user2 = FactoryGirl.create(:user) # in the jam session
|
||||
|
||||
@mq_router.user_publish_to_session(music_session, user1, "a message", :client_id => music_session_member1.client_id)
|
||||
music_session = FactoryGirl.create(:music_session, :creator => user1)
|
||||
|
||||
EM.stop
|
||||
music_session_member1 = FactoryGirl.create(:connection, :user => user1, :music_session => music_session, :ip_address => "1.1.1.1", :client_id => "1")
|
||||
music_session_member2 = FactoryGirl.create(:connection, :user => user2, :music_session => music_session, :ip_address => "2.2.2.2", :client_id => "2")
|
||||
|
||||
|
||||
# this is necessary because other tests will call EM.schedule indirectly as they fiddle with AR models, since some of our
|
||||
# notifications are tied to model activity. So, the issue here is that you'll have an unknown known amount of
|
||||
# queued up messages ready to be sent to MQRouter (because EM.schedule will put deferred blocks onto @next_tick_queue),
|
||||
# resulting in messages from other tests being sent to client_exchange or user_exchange
|
||||
|
||||
# there is no API I can see to clear out the EM queue. so just open up the EM module and do it manually
|
||||
module EM
|
||||
@next_tick_queue = []
|
||||
end
|
||||
|
||||
# bad thing about a static singleton is that we have to 'repair' it by taking back off the double
|
||||
EM.run do
|
||||
|
||||
# mock up exchange
|
||||
MQRouter.client_exchange = double("client_exchange")
|
||||
MQRouter.user_exchange = double("user_exchange")
|
||||
|
||||
MQRouter.client_exchange.should_receive(:publish).with("a message", :routing_key => "client.#{music_session_member2.client_id}")
|
||||
MQRouter.user_exchange.should_not_receive(:publish)
|
||||
|
||||
@mq_router.user_publish_to_session(music_session, user1, "a message", :client_id => music_session_member1.client_id)
|
||||
|
||||
EM.stop
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ require 'fileutils'
|
|||
|
||||
# these tests avoid the use of ActiveRecord and FactoryGirl to do blackbox, non test-instrumented tests
|
||||
describe AudioMixer do
|
||||
pending "failing on build server"
|
||||
|
||||
include UsesTempFiles
|
||||
|
||||
|
|
@ -38,6 +39,14 @@ describe AudioMixer do
|
|||
|
||||
before(:each) do
|
||||
stub_const("APP_CONFIG", app_config)
|
||||
module EM
|
||||
@next_tick_queue = []
|
||||
end
|
||||
|
||||
MQRouter.client_exchange = double("client_exchange")
|
||||
MQRouter.user_exchange = double("user_exchange")
|
||||
MQRouter.client_exchange.should_receive(:publish).any_number_of_times
|
||||
MQRouter.user_exchange.should_receive(:publish).any_number_of_times
|
||||
end
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,159 @@
|
|||
require 'spec_helper'
|
||||
require 'fileutils'
|
||||
|
||||
# these tests avoid the use of ActiveRecord and FactoryGirl to do blackbox, non test-instrumented tests
|
||||
describe IcecastConfigWriter do
|
||||
|
||||
let(:worker) { IcecastConfigWriter.new }
|
||||
|
||||
describe "validate" do
|
||||
|
||||
it "no manifest" do
|
||||
expect { worker.validate }.to raise_error("icecast_server_id not spceified")
|
||||
end
|
||||
|
||||
it "no files specified" do
|
||||
worker.icecast_server_id = 'something'
|
||||
expect { worker.validate }.to raise_error("queue routing mismatch error")
|
||||
end
|
||||
|
||||
it "succeeds" do
|
||||
worker.icecast_server_id = APP_CONFIG.icecast_server_id
|
||||
worker.validate
|
||||
end
|
||||
end
|
||||
|
||||
describe "reload" do
|
||||
it "works with successful command" do
|
||||
IcecastConfigWriter.any_instance.stub(:execute).and_return(0)
|
||||
worker.reload
|
||||
end
|
||||
|
||||
it "raise exception when command fails" do
|
||||
IcecastConfigWriter.any_instance.stub(:execute).and_return(1)
|
||||
expect { worker.reload }.to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
describe "integration" do
|
||||
|
||||
let(:server) {FactoryGirl.create(:icecast_server_minimal, server_id: APP_CONFIG.icecast_server_id)}
|
||||
|
||||
describe "simulated" do
|
||||
|
||||
describe "perform" do
|
||||
# this case does not talk to redis, does not run a real reload command.
|
||||
# but it does talk to the database and verifies all the other logic
|
||||
it "success" do
|
||||
# return success code from reload command
|
||||
IcecastConfigWriter.any_instance.stub(:execute).and_return(0)
|
||||
|
||||
server.location = 'hello'
|
||||
server.save!
|
||||
server.config_changed.should == 1
|
||||
IcecastConfigWriter.perform(server.server_id)
|
||||
server.reload
|
||||
server.config_changed.should == 0
|
||||
end
|
||||
|
||||
it "errored" do
|
||||
# return error code from reload command, which will cause the job to blow up
|
||||
IcecastConfigWriter.any_instance.stub(:execute).and_return(1)
|
||||
|
||||
server.save!
|
||||
server.config_changed.should == 1
|
||||
expect { IcecastConfigWriter.perform(server.server_id) }.to raise_error
|
||||
server.reload
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
end
|
||||
|
||||
describe "with resque-spec" do
|
||||
|
||||
before(:each) do
|
||||
ResqueSpec.reset!
|
||||
end
|
||||
|
||||
it "should have been enqueued because the config changed" do
|
||||
server.save!
|
||||
# the act of just creating the IcecastServer puts a message on the queue
|
||||
IcecastConfigWriter.should have_queue_size_of(1)
|
||||
end
|
||||
|
||||
|
||||
it "should not have been enqueued if routed to a different server_id" do
|
||||
new_server = FactoryGirl.create(:icecast_server_minimal, server_id: APP_CONFIG.icecast_server_id)
|
||||
with_resque do
|
||||
new_server.save!
|
||||
end
|
||||
|
||||
# nobody was around to take it from the queue
|
||||
IcecastConfigWriter.should have_queue_size_of(1)
|
||||
end
|
||||
|
||||
it "should actually run the job" do
|
||||
IcecastConfigWriter.any_instance.stub(:execute).and_return(0)
|
||||
|
||||
with_resque do
|
||||
server.save!
|
||||
server.config_changed.should == 1
|
||||
end
|
||||
|
||||
IcecastConfigWriter.should have_queue_size_of(0)
|
||||
|
||||
server.reload
|
||||
server.config_changed.should == 0
|
||||
end
|
||||
|
||||
it "bails out with no error if no config change present" do
|
||||
IcecastConfigWriter.any_instance.stub(:execute).and_return(0)
|
||||
|
||||
with_resque do
|
||||
server.save!
|
||||
end
|
||||
|
||||
server.reload
|
||||
server.config_changed.should == 0
|
||||
|
||||
with_resque do
|
||||
IcecastConfigWriter.enqueue(server.server_id)
|
||||
end
|
||||
|
||||
server.reload
|
||||
server.config_changed.should == 0
|
||||
end
|
||||
|
||||
describe "queue_jobs_needing_retry" do
|
||||
|
||||
it "finds an unchecked server" do
|
||||
pending "failing on build server"
|
||||
|
||||
server.touch
|
||||
begin
|
||||
ActiveRecord::Base.record_timestamps = false
|
||||
server.updated_at = Time.now.ago(APP_CONFIG.icecast_max_missing_check + 1)
|
||||
server.save!
|
||||
ensure
|
||||
# very important to turn it back; it'll break all tests otherwise
|
||||
ActiveRecord::Base.record_timestamps = true
|
||||
end
|
||||
|
||||
# should enqueue 1 job
|
||||
IcecastConfigWriter.queue_jobs_needing_retry
|
||||
|
||||
IcecastConfigWriter.should have_queue_size_of(1)
|
||||
end
|
||||
|
||||
it "does not find a recently checked server" do
|
||||
pending "failing on build server"
|
||||
|
||||
# should enqueue 1 job
|
||||
IcecastConfigWriter.queue_jobs_needing_retry
|
||||
|
||||
IcecastConfigWriter.should have_queue_size_of(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -84,6 +84,7 @@ Spork.prefork do
|
|||
end
|
||||
|
||||
config.before(:each) do
|
||||
stub_const("APP_CONFIG", app_config)
|
||||
DatabaseCleaner.start
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,31 @@ def app_config
|
|||
ENV['AUDIOMIXER_PATH'] || audiomixer_workspace_path || "/var/lib/audiomixer/audiomixer/audiomixerapp"
|
||||
end
|
||||
|
||||
def icecast_reload_cmd
|
||||
'true' # as in, /bin/true
|
||||
end
|
||||
|
||||
def icecast_config_file
|
||||
Dir::Tmpname.make_tmpname(["#{Dir.tmpdir}/icecast", 'xml'], nil)
|
||||
end
|
||||
|
||||
def icecast_server_id
|
||||
'test'
|
||||
end
|
||||
|
||||
def icecast_max_missing_check
|
||||
2 * 60 # 2 minutes
|
||||
end
|
||||
|
||||
def rabbitmq_host
|
||||
"localhost"
|
||||
end
|
||||
|
||||
def rabbitmq_port
|
||||
5672
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def audiomixer_workspace_path
|
||||
|
|
|
|||
13
web/Gemfile
13
web/Gemfile
|
|
@ -61,9 +61,8 @@ gem 'haml-rails'
|
|||
gem 'resque'
|
||||
gem 'resque-retry'
|
||||
gem 'resque-failed-job-mailer'
|
||||
|
||||
gem 'resque-dynamic-queues'
|
||||
gem 'quiet_assets', :group => :development
|
||||
|
||||
gem "bugsnag"
|
||||
|
||||
group :development, :test do
|
||||
|
|
@ -90,12 +89,12 @@ end
|
|||
|
||||
group :test, :cucumber do
|
||||
gem 'capybara'
|
||||
if ENV['JAMWEB_QT5'] == '1'
|
||||
# necessary on platforms such as arch linux, where pacman -S qt5-webkit is your easiet option
|
||||
gem "capybara-webkit", :git => 'git://github.com/thoughtbot/capybara-webkit.git'
|
||||
else
|
||||
#if ENV['JAMWEB_QT5'] == '1'
|
||||
# # necessary on platforms such as arch linux, where pacman -S qt5-webkit is your easiet option
|
||||
# gem "capybara-webkit", :git => 'git://github.com/thoughtbot/capybara-webkit.git'
|
||||
#else
|
||||
gem "capybara-webkit"
|
||||
end
|
||||
#end
|
||||
gem 'capybara-screenshot'
|
||||
gem 'cucumber-rails', :require => false #, '1.3.0', :require => false
|
||||
gem 'guard-spork', '0.3.2'
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@
|
|||
players += context.JK.fillTemplate(pTemplate, playerVals);
|
||||
}
|
||||
var actionVals = {
|
||||
profile_url: "/#/profile/" + bb.id,
|
||||
profile_url: bb.website,
|
||||
button_follow: bb['is_following'] ? '' : 'button-orange',
|
||||
button_message: 'button-orange'
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,6 +8,20 @@
|
|||
|
||||
var instrument_logo_map = context.JK.getInstrumentIconMap24();
|
||||
|
||||
function initializeSearchNavLinks() {
|
||||
$('.search-nav').click(function() {
|
||||
$('.search-nav.active').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
setTimeout(search, 100);
|
||||
context.JK.Sidebar.searchTypeSelection($(this).data('search_text_type'));
|
||||
});
|
||||
}
|
||||
|
||||
context.JK.SearchResultScreen.searchTypeSelection = function(typeSelection) {
|
||||
$('.search-nav.active').removeClass('active');
|
||||
$('.search-result-header a[data-search_text_type='+typeSelection+']').addClass('active');
|
||||
}
|
||||
|
||||
function beforeShow(data) {
|
||||
var query = data.query;
|
||||
}
|
||||
|
|
@ -15,20 +29,31 @@
|
|||
function afterShow(data) {
|
||||
}
|
||||
|
||||
function search(evt) {
|
||||
evt.stopPropagation();
|
||||
function selectedSearchType() {
|
||||
var srchtype = $('.search-nav.active').data('search_text_type');
|
||||
if (srchtype === undefined) {
|
||||
srchtype = $('#search_text_type').val();
|
||||
}
|
||||
return srchtype;
|
||||
}
|
||||
|
||||
function search(evt) {
|
||||
if (evt) {
|
||||
evt.stopPropagation();
|
||||
}
|
||||
$('#search-results').empty();
|
||||
var query = $('#search-input').val();
|
||||
context.location = '#/searchResults/:' + query;
|
||||
if (query) {
|
||||
context.location = '#/searchResults/:' + query;
|
||||
} else {
|
||||
query = $('#query').html();
|
||||
}
|
||||
|
||||
logger.debug('query=' + query);
|
||||
if (query !== '') {
|
||||
$('#query').html(query + "\"");
|
||||
context.JK.search(query, app, onSearchSuccess);
|
||||
}
|
||||
|
||||
else {
|
||||
$('#query').html(query);
|
||||
query += '&search_text_type='+selectedSearchType();
|
||||
context.JK.search(query, app, context.JK.SearchResultScreen.onSearchSuccess);
|
||||
} else {
|
||||
$('#result-count').html('');
|
||||
$('#query').html('');
|
||||
}
|
||||
|
|
@ -36,68 +61,147 @@
|
|||
return false;
|
||||
}
|
||||
|
||||
function onSearchSuccess(response) {
|
||||
function resultDivVisibility(val, isSidebar) {
|
||||
if (isSidebar) {
|
||||
$('div[layout=sidebar user-id=' + val.id + '].sidebar-search-connected').hide();
|
||||
$('div[layout=sidebar user-id=' + val.id + '].sidebar-search-result').show();
|
||||
} else {
|
||||
$('div[user-id=' + val.id + '].search-connected').hide();
|
||||
$('div[user-id=' + val.id + '].search-result').show();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: generalize this for each search result type (band, musician, recordings, et. al.)
|
||||
$.each(response.musicians, function(index, val) {
|
||||
// fill in template for Connect pre-click
|
||||
var template = $('#template-search-result').html();
|
||||
var searchResultHtml = context.JK.fillTemplate(template, {
|
||||
userId: val.id,
|
||||
avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
|
||||
profile_url: "/#/profile/" + val.id,
|
||||
userName: val.name,
|
||||
location: val.location,
|
||||
instruments: getInstrumentHtml(val.instruments)
|
||||
});
|
||||
|
||||
$('#search-results').append(searchResultHtml);
|
||||
|
||||
// fill in template for Connect post-click
|
||||
template = $('#template-invitation-sent').html();
|
||||
var invitationSentHtml = context.JK.fillTemplate(template, {
|
||||
userId: val.id,
|
||||
first_name: val.first_name,
|
||||
profile_url: "/#/profile/" + val.id
|
||||
});
|
||||
|
||||
$('#search-results').append(invitationSentHtml);
|
||||
|
||||
// initialize visibility of the divs
|
||||
$('div[user-id=' + val.id + '].search-connected').hide();
|
||||
$('div[user-id=' + val.id + '].search-result').show();
|
||||
|
||||
// wire up button click handler if search result is not a friend or the current user
|
||||
if (!val.is_friend && val.id !== context.JK.currentUserId) {
|
||||
$('div[user-id=' + val.id + ']').find('.btn-connect-friend').click(sendFriendRequest);
|
||||
}
|
||||
else {
|
||||
$('div[user-id=' + val.id + ']').find('.btn-connect-friend').hide();
|
||||
}
|
||||
});
|
||||
|
||||
var resultCount = response.musicians.length;
|
||||
$('#result-count').html(resultCount);
|
||||
|
||||
if (resultCount === 1) {
|
||||
$('#result-count').append(" Result for \"");
|
||||
}
|
||||
else {
|
||||
$('#result-count').append(" Results for \"");
|
||||
}
|
||||
context.JK.SearchResultScreen.onSearchSuccess = function(response) {
|
||||
searchResults(response, true);
|
||||
searchResults(response, false);
|
||||
}
|
||||
|
||||
function friendRequestCallback(userId) {
|
||||
// toggle the pre-click and post-click divs
|
||||
$('div[user-id=' + userId + '].search-connected').show();
|
||||
$('div[user-id=' + userId + '].search-result').hide();
|
||||
}
|
||||
function searchResults(response, isSidebar) {
|
||||
var resultCount=0;
|
||||
var selector, template_name;
|
||||
selector = isSidebar ? '#sidebar-search-results' : '#search-results';
|
||||
$(selector).html('');
|
||||
|
||||
function sendFriendRequest(evt) {
|
||||
if (response.search_type === 'musicians') {
|
||||
resultCount = response.musicians.length;
|
||||
// TODO: generalize this for each search result type (band, musician, et. al.)
|
||||
template_name = isSidebar ? "#template-musicians-sidebar-search-result" : "#template-musicians-search-result";
|
||||
$.each(response.musicians, function(index, val) {
|
||||
// fill in template for Connect pre-click
|
||||
var args = {
|
||||
userId: val.id,
|
||||
avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
|
||||
profile_url: "/#/profile/" + val.id,
|
||||
userName: val.name,
|
||||
location: val.location,
|
||||
instruments: getInstrumentHtml(val.instruments)
|
||||
};
|
||||
selector = isSidebar ? '#sidebar-search-results' : '#search-results';
|
||||
$(selector).append(context.JK.fillTemplate($(template_name).html(), args));
|
||||
|
||||
// fill in template for Connect post-click
|
||||
selector = isSidebar ? '#template-sidebar-invitation-sent' : '#template-invitation-sent';
|
||||
var invitationSentHtml = context.JK.fillTemplate($(selector).html(), {
|
||||
userId: val.id,
|
||||
first_name: val.first_name,
|
||||
profile_url: "/#/profile/" + val.id
|
||||
});
|
||||
|
||||
selector = isSidebar ? '#sidebar-search-results' : '#search-results';
|
||||
$(selector).append(invitationSentHtml);
|
||||
|
||||
// wire up button click handler if search result is not a friend or the current use
|
||||
if (isSidebar) {
|
||||
var $sidebar = $('div[layout=sidebar] div[user-id=' + val.id + ']');
|
||||
if (!val.is_friend && val.id !== context.JK.currentUserId) {
|
||||
$sidebar.find('.btn-connect-friend').click(sendFriendRequest);
|
||||
} else {
|
||||
// hide the button if the search result is already a friend
|
||||
$sidebar.find('.btn-connect-friend').hide();
|
||||
}
|
||||
} else {
|
||||
if (!val.is_friend && val.id !== context.JK.currentUserId) {
|
||||
$('div[user-id=' + val.id + ']').find('.btn-connect-friend').click(sendFriendRequest);
|
||||
} else {
|
||||
$('div[user-id=' + val.id + ']').find('.btn-connect-friend').hide();
|
||||
}
|
||||
}
|
||||
resultDivVisibility(val, isSidebar);
|
||||
});
|
||||
|
||||
} else if (response.search_type === 'bands') {
|
||||
resultCount = response.bands.length;
|
||||
template_name = isSidebar ? "#template-bands-sidebar-search-result" : "#template-bands-search-result";
|
||||
$.each(response.bands, function(index, val) {
|
||||
// fill in template for Connect pre-click
|
||||
var searchResultHtml = context.JK.fillTemplate($(template_name).html(), {
|
||||
bandId: val.id,
|
||||
avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
|
||||
band_url: val.website,
|
||||
bandName: val.name,
|
||||
location: val.location
|
||||
});
|
||||
selector = isSidebar ? '#sidebar-search-results' : '#search-results';
|
||||
$(selector).append(searchResultHtml);
|
||||
resultDivVisibility(val, isSidebar);
|
||||
});
|
||||
|
||||
} else if (response.search_type === 'fans') {
|
||||
resultCount = response.fans.length;
|
||||
template_name = isSidebar ? "#template-fans-sidebar-search-result" : "#template-fans-search-result";
|
||||
$.each(response.fans, function(index, val) {
|
||||
// fill in template for Connect pre-click
|
||||
var searchResultHtml = context.JK.fillTemplate($(template_name).html(), {
|
||||
userId: val.id,
|
||||
avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
|
||||
profile_url: "/#/profile/" + val.id,
|
||||
userName: val.name,
|
||||
location: val.location
|
||||
});
|
||||
selector = isSidebar ? '#sidebar-search-results' : '#search-results';
|
||||
$(selector).append(searchResultHtml);
|
||||
resultDivVisibility(val, isSidebar);
|
||||
});
|
||||
}
|
||||
if (isSidebar) {
|
||||
// show header
|
||||
$('#sidebar-search-header').show();
|
||||
// hide panels
|
||||
$('[layout-panel="contents"]').hide();
|
||||
$('[layout-panel="contents"]').css({"height": "1px"});
|
||||
// resize search results area
|
||||
$('#sidebar-search-results').height(context.JK.Sidebar.getHeight() + 'px');
|
||||
} else {
|
||||
$('#result-count').html(resultCount);
|
||||
if (resultCount === 1) {
|
||||
$('#result-count').append(" Result for: ");
|
||||
} else {
|
||||
$('#result-count').append(" Results for: ");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function friendRequestCallbackSidebar(userId) {
|
||||
// toggle the pre-click and post-click divs
|
||||
$('div[layout=sidebar] div[user-id=' + userId + '].sidebar-search-connected').show();
|
||||
$('div[layout=sidebar] div[user-id=' + userId + '].sidebar-search-result').hide();
|
||||
}
|
||||
|
||||
function friendRequestCallbackSearchResults(userId) {
|
||||
// toggle the pre-click and post-click divs
|
||||
$('div[user-id=' + userId + '].search-connected').show();
|
||||
$('div[user-id=' + userId + '].search-result').hide();
|
||||
}
|
||||
|
||||
function sendFriendRequest(evt) {
|
||||
evt.stopPropagation();
|
||||
var userId = $(this).parent().attr('user-id');
|
||||
context.JK.sendFriendRequest(app, userId, friendRequestCallback);
|
||||
}
|
||||
if ($(this).closest('#sidebar-search-results')) {
|
||||
context.JK.sendFriendRequest(app, userId, friendRequestCallbackSidebar);
|
||||
} else {
|
||||
context.JK.sendFriendRequest(app, userId, friendRequestCallbackSearchResults);
|
||||
}
|
||||
}
|
||||
|
||||
function getInstrumentHtml(instruments) {
|
||||
var instrumentLogoHtml = '';
|
||||
|
|
@ -124,6 +228,7 @@
|
|||
};
|
||||
app.bindScreen('searchResults', screenBindings);
|
||||
events();
|
||||
initializeSearchNavLinks();
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,6 +9,18 @@
|
|||
var rest = context.JK.Rest();
|
||||
var invitationDialog = null;
|
||||
|
||||
function initializeSearchPanel() {
|
||||
$('#search_text_type').change(function() {
|
||||
searchForInput();
|
||||
context.JK.SearchResultScreen.searchTypeSelection($('#search_text_type').val());
|
||||
});
|
||||
}
|
||||
|
||||
context.JK.Sidebar.searchTypeSelection = function(typeSelection) {
|
||||
$('#search_text_type').val(typeSelection);
|
||||
emptySearchResults();
|
||||
}
|
||||
|
||||
function initializeFriendsPanel() {
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
|
@ -211,6 +223,7 @@
|
|||
|
||||
else if (type === context.JK.MessageType.RECORDING_MASTER_MIX_COMPLETE) {
|
||||
$notification.find('#div-actions').hide();
|
||||
context.jamClient.OnDownloadAvailable(); // poke backend, letting it know a download is available
|
||||
}
|
||||
|
||||
else if (type === context.JK.MessageType.BAND_INVITATION) {
|
||||
|
|
@ -252,66 +265,13 @@
|
|||
}
|
||||
|
||||
function search(query) {
|
||||
|
||||
logger.debug('query=' + query);
|
||||
if (query !== '') {
|
||||
context.JK.search(query, app, onSearchSuccess);
|
||||
context.JK.search(query, app, context.JK.SearchResultScreen.onSearchSuccess);
|
||||
}
|
||||
}
|
||||
|
||||
function onSearchSuccess(response) {
|
||||
|
||||
// TODO: generalize this for each search result type (band, musician, recordings, et. al.)
|
||||
$.each(response.musicians, function(index, val) {
|
||||
// fill in template for Connect pre-click
|
||||
var template = $('#template-sidebar-search-result').html();
|
||||
var searchResultHtml = context.JK.fillTemplate(template, {
|
||||
userId: val.id,
|
||||
avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
|
||||
profile_url: "/#/profile/" + val.id,
|
||||
userName: val.name,
|
||||
location: val.location
|
||||
});
|
||||
|
||||
$('#sidebar-search-results').append(searchResultHtml);
|
||||
|
||||
// fill in template for Connect post-click
|
||||
template = $('#template-sidebar-invitation-sent').html();
|
||||
var invitationSentHtml = context.JK.fillTemplate(template, {
|
||||
userId: val.id,
|
||||
first_name: val.first_name,
|
||||
profile_url: "/#/profile/" + val.id
|
||||
});
|
||||
|
||||
$('#sidebar-search-results').append(invitationSentHtml);
|
||||
|
||||
// initialize visibility of the divs
|
||||
$('div[layout=sidebar] div[user-id=' + val.id + '].sidebar-search-connected').hide();
|
||||
$('div[layout=sidebar] div[user-id=' + val.id + '].sidebar-search-result').show();
|
||||
|
||||
// wire up button click handler if search result is not a friend or the current user
|
||||
var $sidebar = $('div[layout=sidebar] div[user-id=' + val.id + ']');
|
||||
if (!val.is_friend && val.id !== context.JK.currentUserId) {
|
||||
$sidebar.find('.btn-connect-friend').click(sendFriendRequest);
|
||||
}
|
||||
// hide the button if the search result is already a friend
|
||||
else {
|
||||
$sidebar.find('.btn-connect-friend').hide();
|
||||
}
|
||||
});
|
||||
|
||||
// show header
|
||||
$('#sidebar-search-header').show();
|
||||
|
||||
// hide panels
|
||||
$('[layout-panel="contents"]').hide();
|
||||
$('[layout-panel="contents"]').css({"height": "1px"});
|
||||
|
||||
// resize search results area
|
||||
$('#sidebar-search-results').height(getHeight() + 'px');
|
||||
}
|
||||
|
||||
function getHeight() {
|
||||
context.JK.Sidebar.getHeight = function() {
|
||||
// TODO: refactor this - copied from layout.js
|
||||
var sidebarHeight = $(context).height() - 75 - 2 * 60 + $('[layout-sidebar-expander]').height();
|
||||
var combinedHeaderHeight = $('[layout-panel="contents"]').length * 36;
|
||||
|
|
@ -324,7 +284,7 @@
|
|||
function showFriendsPanel() {
|
||||
|
||||
var $expandedPanelContents = $('[layout-id="panelFriends"] [layout-panel="contents"]');
|
||||
var expandedPanelHeight = getHeight();
|
||||
var expandedPanelHeight = context.JK.Sidebar.getHeight();
|
||||
|
||||
// hide all other contents
|
||||
$('[layout-panel="contents"]').hide();
|
||||
|
|
@ -335,18 +295,6 @@
|
|||
$expandedPanelContents.animate({"height": expandedPanelHeight + "px"}, 400);
|
||||
}
|
||||
|
||||
function friendRequestCallback(userId) {
|
||||
// toggle the pre-click and post-click divs
|
||||
$('div[layout=sidebar] div[user-id=' + userId + '].sidebar-search-connected').show();
|
||||
$('div[layout=sidebar] div[user-id=' + userId + '].sidebar-search-result').hide();
|
||||
}
|
||||
|
||||
function sendFriendRequest(evt) {
|
||||
evt.stopPropagation();
|
||||
var userId = $(this).parent().attr('user-id');
|
||||
context.JK.sendFriendRequest(app, userId, friendRequestCallback);
|
||||
}
|
||||
|
||||
function hideSearchResults() {
|
||||
emptySearchResults();
|
||||
$('#search-input').val('');
|
||||
|
|
@ -412,6 +360,21 @@
|
|||
function inviteHoverOut() {
|
||||
$('.invitation-button-holder').slideUp();
|
||||
}
|
||||
|
||||
function searchForInput() {
|
||||
var query = $('#search-input').val();
|
||||
// logger.debug("query=" + query);
|
||||
if (query === '') {
|
||||
return hideSearchResults();
|
||||
}
|
||||
if (query.length > 2) {
|
||||
// FIXME: this is in searchResults
|
||||
$('#query').html(query);
|
||||
query += '&search_text_type='+$('#search_text_type').val();
|
||||
emptySearchResults();
|
||||
search(query);
|
||||
}
|
||||
}
|
||||
|
||||
function events() {
|
||||
$('#search-input').keyup(function(evt) {
|
||||
|
|
@ -420,24 +383,12 @@
|
|||
if (evt.which === 13) {
|
||||
return hideSearchResults();
|
||||
}
|
||||
|
||||
// ESCAPE KEY
|
||||
if (evt.which === 27) {
|
||||
return hideSearchResults();
|
||||
}
|
||||
|
||||
var query = $('#search-input').val();
|
||||
logger.debug("query=" + query);
|
||||
|
||||
if (query === '') {
|
||||
return hideSearchResults();
|
||||
}
|
||||
|
||||
if (query.length > 2) {
|
||||
emptySearchResults();
|
||||
search(query);
|
||||
}
|
||||
}, 1000);
|
||||
searchForInput();
|
||||
}, 500);
|
||||
});
|
||||
|
||||
$('#sidebar-search-expand').click(function(evt) {
|
||||
|
|
@ -923,6 +874,7 @@
|
|||
|
||||
this.initialize = function(invitationDialogInstance) {
|
||||
events();
|
||||
initializeSearchPanel();
|
||||
initializeFriendsPanel();
|
||||
initializeChatPanel();
|
||||
initializeNotificationsPanel();
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue