Merge branch 'master' into feature/analyzer-on-travis
# Conflicts: # .travis.yml
This commit is contained in:
commit
188c127057
15
.travis.yml
15
.travis.yml
|
@ -55,6 +55,7 @@ install:
|
||||||
fi
|
fi
|
||||||
- >
|
- >
|
||||||
if [[ "$PYTHON" == true ]]; then
|
if [[ "$PYTHON" == true ]]; then
|
||||||
|
pip install --user mkdocs
|
||||||
pushd python_apps/airtime_analyzer
|
pushd python_apps/airtime_analyzer
|
||||||
python setup.py install --dry-run --no-init-script
|
python setup.py install --dry-run --no-init-script
|
||||||
popd
|
popd
|
||||||
|
@ -69,3 +70,17 @@ before_script:
|
||||||
script:
|
script:
|
||||||
- ./travis/php.sh
|
- ./travis/php.sh
|
||||||
- ./travis/python.sh
|
- ./travis/python.sh
|
||||||
|
- mkdocs build --clean -q > /dev/null
|
||||||
|
deploy:
|
||||||
|
provider: pages
|
||||||
|
skip_cleanup: true
|
||||||
|
local_dir: build/docs
|
||||||
|
github_token: $GITHUB_TOKEN # Set in travis-ci.org dashboard
|
||||||
|
target_branch: master
|
||||||
|
repo: LibreTime/LibreTime.github.io
|
||||||
|
project_name: LibreTime
|
||||||
|
fqdn: libretime.org
|
||||||
|
name: R. LibreTime DocBot
|
||||||
|
on:
|
||||||
|
branch: master
|
||||||
|
env: PYTHON=true
|
||||||
|
|
|
@ -118,8 +118,14 @@ class Amazon_S3StorageBackend extends StorageBackend
|
||||||
|
|
||||||
public function getFilePrefix()
|
public function getFilePrefix()
|
||||||
{
|
{
|
||||||
$hostingId = Billing::getClientInstanceId();
|
$filePrefix = '';
|
||||||
$filePrefix = substr($hostingId, -2)."/".$hostingId;
|
// only prefix files on S3 when billing is active since saas customers share a s3 bucket
|
||||||
|
// I'm not sure why the choice was made to put everything into one bucket
|
||||||
|
// We might refactor this to use a bucket per customer if we revisit S3
|
||||||
|
if (LIBRETIME_ENABLE_BILLING === true) {
|
||||||
|
$hostingId = Billing::getClientInstanceId();
|
||||||
|
$filePrefix = substr($hostingId, -2)."/".$hostingId;
|
||||||
|
}
|
||||||
return $filePrefix;
|
return $filePrefix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ class Application_Common_UsabilityHints
|
||||||
"<a href=\"/schedule\">",
|
"<a href=\"/schedule\">",
|
||||||
"</a>");
|
"</a>");
|
||||||
}
|
}
|
||||||
} else if ($userIsOnShowbuilderPage && $userIsSuperAdmin) {
|
} else if (LIBRETIME_ENABLE_BILLING === true && $userIsOnShowbuilderPage && $userIsSuperAdmin) {
|
||||||
$unpaidInvoice = Billing::checkForUnpaidInvoice();
|
$unpaidInvoice = Billing::checkForUnpaidInvoice();
|
||||||
if ($unpaidInvoice != null) {
|
if ($unpaidInvoice != null) {
|
||||||
$invoiceUrl = "/billing/invoice?invoiceid=" . $unpaidInvoice['id'];
|
$invoiceUrl = "/billing/invoice?invoiceid=" . $unpaidInvoice['id'];
|
||||||
|
|
|
@ -106,11 +106,15 @@ define('UI_PLAYLISTCONTROLLER_OBJ_SESSNAME', 'PLAYLISTCONTROLLER_OBJ');
|
||||||
define('UI_BLOCK_SESSNAME', 'BLOCK');*/
|
define('UI_BLOCK_SESSNAME', 'BLOCK');*/
|
||||||
|
|
||||||
//WHMCS integration
|
//WHMCS integration
|
||||||
define("WHMCS_API_URL", "https://account.sourcefabric.com/includes/api.php");
|
define("LIBRETIME_ENABLE_WHMCS", false);
|
||||||
|
define("WHMCS_API_URL", "https://account.example.org/includes/api.php");
|
||||||
define("SUBDOMAIN_WHMCS_CUSTOM_FIELD_NAME", "Choose your domain");
|
define("SUBDOMAIN_WHMCS_CUSTOM_FIELD_NAME", "Choose your domain");
|
||||||
|
|
||||||
|
//LiveChat integration
|
||||||
|
define('LIBRETIME_ENABLE_LIVECHAT', false);
|
||||||
|
|
||||||
//Sentry error logging
|
//Sentry error logging
|
||||||
define('SENTRY_CONFIG_PATH', '/etc/airtime-saas/sentry.airtime_web.ini');
|
define('SENTRY_CONFIG_PATH', LIBRETIME_CONF_DIR . '/sentry.airtime_web.ini');
|
||||||
|
|
||||||
//Provisioning status
|
//Provisioning status
|
||||||
define('PROVISIONING_STATUS_SUSPENDED' , 'Suspended');
|
define('PROVISIONING_STATUS_SUSPENDED' , 'Suspended');
|
||||||
|
@ -141,3 +145,6 @@ define('STATION_PODCAST_SERVICE_NAME', 'station_podcast');
|
||||||
//define('IMPORTED_PODCAST', 1);
|
//define('IMPORTED_PODCAST', 1);
|
||||||
|
|
||||||
define('ITUNES_XML_NAMESPACE_URL', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
|
define('ITUNES_XML_NAMESPACE_URL', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
|
||||||
|
|
||||||
|
// Billing configuration
|
||||||
|
define('LIBRETIME_ENABLE_BILLING', false);
|
||||||
|
|
|
@ -7,122 +7,123 @@
|
||||||
* Zend_Navigation_Page::factory() when constructing
|
* Zend_Navigation_Page::factory() when constructing
|
||||||
* the navigation container below.
|
* the navigation container below.
|
||||||
*/
|
*/
|
||||||
$pages = array(
|
$pages = array();
|
||||||
array(
|
$pages[] = array(
|
||||||
'label' => "<i class='icon-music icon-white'></i>"._('My Podcast'),
|
'label' => "<i class='icon-music icon-white'></i>"._('My Podcast'),
|
||||||
'module' => 'default',
|
'module' => 'default',
|
||||||
'controller' => 'podcast',
|
'controller' => 'podcast',
|
||||||
'action' => 'station',
|
'action' => 'station',
|
||||||
'resource' => 'podcast'
|
'resource' => 'podcast'
|
||||||
),
|
);
|
||||||
array(
|
$pages[] = array(
|
||||||
'label' => "<i class='icon-globe icon-white'></i>"._('Radio Page'),
|
'label' => "<i class='icon-globe icon-white'></i>"._('Radio Page'),
|
||||||
'uri' => '/',
|
'uri' => '/',
|
||||||
'resource' => '',
|
'resource' => '',
|
||||||
'pages' => array(
|
'pages' => array(
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$pages[] = array(
|
||||||
|
'label' => "<i class='icon-calendar icon-white'></i>"._('Calendar'),
|
||||||
|
'module' => 'default',
|
||||||
|
'controller' => 'schedule',
|
||||||
|
'action' => 'index',
|
||||||
|
'resource' => 'schedule'
|
||||||
|
);
|
||||||
|
$pages[] = array(
|
||||||
|
'label' => "<i class='icon-wrench icon-white'></i>"._('Widgets'),
|
||||||
|
'module' => 'default',
|
||||||
|
'controller' => 'embeddablewidgets',
|
||||||
|
'action' => 'player',
|
||||||
|
'resource' => 'embeddablewidgets',
|
||||||
|
'title' => 'Widgets',
|
||||||
|
'pages' => array(
|
||||||
|
array(
|
||||||
|
'label' => _('Player'),
|
||||||
|
'module' => 'default',
|
||||||
|
'controller' => 'embeddablewidgets',
|
||||||
|
'action' => 'player',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'label' => _('Weekly Schedule'),
|
||||||
|
'module' => 'default',
|
||||||
|
'controller' => 'embeddablewidgets',
|
||||||
|
'action' => 'schedule',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'label' => _('Facebook'),
|
||||||
|
'module' => 'default',
|
||||||
|
'controller' => 'embeddablewidgets',
|
||||||
|
'action' => 'facebook',
|
||||||
)
|
)
|
||||||
),
|
)
|
||||||
array(
|
);
|
||||||
'label' => "<i class='icon-calendar icon-white'></i>"._('Calendar'),
|
$pages[] = array(
|
||||||
'module' => 'default',
|
'label' => "<i class='icon-cog icon-white'></i>"._("Settings"),
|
||||||
'controller' => 'schedule',
|
'resource' => 'preference',
|
||||||
'action' => 'index',
|
'action' => 'index',
|
||||||
'resource' => 'schedule'
|
'module' => 'default',
|
||||||
),
|
'controller' => 'preference',
|
||||||
array(
|
'title' => 'Settings',
|
||||||
'label' => "<i class='icon-wrench icon-white'></i>"._('Widgets'),
|
'pages' => array(
|
||||||
'module' => 'default',
|
array(
|
||||||
'controller' => 'embeddablewidgets',
|
'label' => _('General'),
|
||||||
'action' => 'player',
|
'module' => 'default',
|
||||||
'resource' => 'embeddablewidgets',
|
'controller' => 'preference'
|
||||||
'title' => 'Widgets',
|
),
|
||||||
'pages' => array(
|
array(
|
||||||
array(
|
'label' => _('My Profile'),
|
||||||
'label' => _('Player'),
|
'controller' => 'user',
|
||||||
'module' => 'default',
|
'action' => 'edit-user',
|
||||||
'controller' => 'embeddablewidgets',
|
'resource' => 'user'
|
||||||
'action' => 'player',
|
),
|
||||||
),
|
array(
|
||||||
array(
|
'label' => _('Users'),
|
||||||
'label' => _('Weekly Schedule'),
|
'module' => 'default',
|
||||||
'module' => 'default',
|
'controller' => 'user',
|
||||||
'controller' => 'embeddablewidgets',
|
'action' => 'add-user',
|
||||||
'action' => 'schedule',
|
'resource' => 'user'
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'label' => _('Facebook'),
|
'label' => _('Streams'),
|
||||||
'module' => 'default',
|
'module' => 'default',
|
||||||
'controller' => 'embeddablewidgets',
|
'controller' => 'preference',
|
||||||
'action' => 'facebook',
|
'action' => 'stream-setting'
|
||||||
)
|
|
||||||
)
|
)
|
||||||
),
|
)
|
||||||
array(
|
);
|
||||||
'label' => "<i class='icon-cog icon-white'></i>"._("Settings"),
|
$pages[] = array(
|
||||||
'resource' => 'preference',
|
'label' => "<i class='icon-signal icon-white'></i>"._("Analytics"),
|
||||||
'action' => 'index',
|
'module' => 'default',
|
||||||
'module' => 'default',
|
'controller' => 'playouthistory',
|
||||||
'controller' => 'preference',
|
'action' => 'index',
|
||||||
'title' => 'Settings',
|
'resource' => 'playouthistory',
|
||||||
'pages' => array(
|
'title' => 'Analytics',
|
||||||
array(
|
'pages' => array(
|
||||||
'label' => _('General'),
|
array(
|
||||||
'module' => 'default',
|
'label' => _('Playout History'),
|
||||||
'controller' => 'preference'
|
'module' => 'default',
|
||||||
),
|
'controller' => 'playouthistory',
|
||||||
array(
|
'action' => 'index',
|
||||||
'label' => _('My Profile'),
|
'resource' => 'playouthistory'
|
||||||
'controller' => 'user',
|
),
|
||||||
'action' => 'edit-user',
|
array(
|
||||||
'resource' => 'user'
|
'label' => _('History Templates'),
|
||||||
),
|
'module' => 'default',
|
||||||
array(
|
'controller' => 'playouthistorytemplate',
|
||||||
'label' => _('Users'),
|
'action' => 'index',
|
||||||
'module' => 'default',
|
'resource' => 'playouthistorytemplate'
|
||||||
'controller' => 'user',
|
),
|
||||||
'action' => 'add-user',
|
array(
|
||||||
'resource' => 'user'
|
'label' => _('Listener Stats'),
|
||||||
),
|
'module' => 'default',
|
||||||
array(
|
'controller' => 'listenerstat',
|
||||||
'label' => _('Streams'),
|
'action' => 'index',
|
||||||
'module' => 'default',
|
'resource' => 'listenerstat'
|
||||||
'controller' => 'preference',
|
),
|
||||||
'action' => 'stream-setting'
|
)
|
||||||
)
|
);
|
||||||
)
|
if (LIBRETIME_ENABLE_BILLING === true) {
|
||||||
),
|
$pages[] = array(
|
||||||
array(
|
|
||||||
'label' => "<i class='icon-signal icon-white'></i>"._("Analytics"),
|
|
||||||
'module' => 'default',
|
|
||||||
'controller' => 'playouthistory',
|
|
||||||
'action' => 'index',
|
|
||||||
'resource' => 'playouthistory',
|
|
||||||
'title' => 'Analytics',
|
|
||||||
'pages' => array(
|
|
||||||
array(
|
|
||||||
'label' => _('Playout History'),
|
|
||||||
'module' => 'default',
|
|
||||||
'controller' => 'playouthistory',
|
|
||||||
'action' => 'index',
|
|
||||||
'resource' => 'playouthistory'
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'label' => _('History Templates'),
|
|
||||||
'module' => 'default',
|
|
||||||
'controller' => 'playouthistorytemplate',
|
|
||||||
'action' => 'index',
|
|
||||||
'resource' => 'playouthistorytemplate'
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'label' => _('Listener Stats'),
|
|
||||||
'module' => 'default',
|
|
||||||
'controller' => 'listenerstat',
|
|
||||||
'action' => 'index',
|
|
||||||
'resource' => 'listenerstat'
|
|
||||||
),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'label' => (Application_Model_Preference::GetPlanLevel()=="trial") ? "<i class='icon-star icon-orange'></i><span style='color: #ff5d1a'>"._('Upgrade')."</span>" : "<i class='icon-briefcase icon-white'></i>"._('Billing'),
|
'label' => (Application_Model_Preference::GetPlanLevel()=="trial") ? "<i class='icon-star icon-orange'></i><span style='color: #ff5d1a'>"._('Upgrade')."</span>" : "<i class='icon-briefcase icon-white'></i>"._('Billing'),
|
||||||
'controller' => 'billing',
|
'controller' => 'billing',
|
||||||
'action' => 'upgrade',
|
'action' => 'upgrade',
|
||||||
|
@ -151,48 +152,48 @@ $pages = array(
|
||||||
'resource' => 'billing'
|
'resource' => 'billing'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
);
|
||||||
array(
|
}
|
||||||
'label' => "<i class='icon-question-sign icon-white'></i>"._('Help'),
|
$pages[] = array(
|
||||||
'controller' => 'dashboard',
|
'label' => "<i class='icon-question-sign icon-white'></i>"._('Help'),
|
||||||
'action' => 'help',
|
'controller' => 'dashboard',
|
||||||
'resource' => 'dashboard',
|
'action' => 'help',
|
||||||
'title' => 'Help',
|
'resource' => 'dashboard',
|
||||||
'pages' => array(
|
'title' => 'Help',
|
||||||
array(
|
'pages' => array(
|
||||||
'label' => _('Getting Started'),
|
array(
|
||||||
'module' => 'default',
|
'label' => _('Getting Started'),
|
||||||
'controller' => 'dashboard',
|
'module' => 'default',
|
||||||
'action' => 'help',
|
'controller' => 'dashboard',
|
||||||
'resource' => 'dashboard'
|
'action' => 'help',
|
||||||
),
|
'resource' => 'dashboard'
|
||||||
array(
|
),
|
||||||
'label' => _('FAQ'),
|
array(
|
||||||
'uri' => FAQ_URL,
|
'label' => _('FAQ'),
|
||||||
'target' => "_blank"
|
'uri' => FAQ_URL,
|
||||||
),
|
'target' => "_blank"
|
||||||
array(
|
),
|
||||||
'label' => _('User Manual'),
|
array(
|
||||||
'uri' => USER_MANUAL_URL,
|
'label' => _('User Manual'),
|
||||||
'target' => "_blank"
|
'uri' => USER_MANUAL_URL,
|
||||||
),
|
'target' => "_blank"
|
||||||
array(
|
),
|
||||||
'label' => _('File a Support Ticket'),
|
array(
|
||||||
'uri' => SUPPORT_TICKET_URL,
|
'label' => _('File a Support Ticket'),
|
||||||
'target' => "_blank"
|
'uri' => SUPPORT_TICKET_URL,
|
||||||
),
|
'target' => "_blank"
|
||||||
array(
|
),
|
||||||
'label' => _(sprintf("Help Translate %s", PRODUCT_NAME)),
|
array(
|
||||||
'uri' => AIRTIME_TRANSIFEX_URL,
|
'label' => _(sprintf("Help Translate %s", PRODUCT_NAME)),
|
||||||
'target' => "_blank"
|
'uri' => AIRTIME_TRANSIFEX_URL,
|
||||||
),
|
'target' => "_blank"
|
||||||
array(
|
),
|
||||||
'label' => _('What\'s New?'),
|
array(
|
||||||
'uri' => UI_REVAMP_YOUTUBE_URL,
|
'label' => _('What\'s New?'),
|
||||||
'target' => "_blank"
|
'uri' => UI_REVAMP_YOUTUBE_URL,
|
||||||
)
|
'target' => "_blank"
|
||||||
)
|
)
|
||||||
),
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -443,7 +443,7 @@ class LibraryController extends Zend_Controller_Action
|
||||||
$this->_helper->layout->disableLayout();
|
$this->_helper->layout->disableLayout();
|
||||||
|
|
||||||
|
|
||||||
if (!Billing::isStationPodcastAllowed()) {
|
if (LIBRETIME_ENABLE_BILLING === true && !Billing::isStationPodcastAllowed()) {
|
||||||
$this->renderScript("podcast/featureupgrade-pane.phtml");
|
$this->renderScript("podcast/featureupgrade-pane.phtml");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ class LoginController extends Zend_Controller_Action
|
||||||
//uses separate layout without a navigation.
|
//uses separate layout without a navigation.
|
||||||
$this->_helper->layout->setLayout('login');
|
$this->_helper->layout->setLayout('login');
|
||||||
|
|
||||||
$error = false;
|
$this->view->error = false;
|
||||||
|
|
||||||
$baseUrl = Application_Common_OsPath::getBaseDir();
|
$baseUrl = Application_Common_OsPath::getBaseDir();
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ class LoginController extends Zend_Controller_Action
|
||||||
Application_Model_Preference::SetUserLocale($locale);
|
Application_Model_Preference::SetUserLocale($locale);
|
||||||
|
|
||||||
$this->_redirect('showbuilder');
|
$this->_redirect('showbuilder');
|
||||||
} else {
|
} elseif (LIBRETIME_ENABLE_WHMCS) {
|
||||||
$email = $form->getValue('username');
|
$email = $form->getValue('username');
|
||||||
$authAdapter = new WHMCS_Auth_Adapter("admin", $email, $password);
|
$authAdapter = new WHMCS_Auth_Adapter("admin", $email, $password);
|
||||||
$auth = Zend_Auth::getInstance();
|
$auth = Zend_Auth::getInstance();
|
||||||
|
@ -105,23 +105,14 @@ class LoginController extends Zend_Controller_Action
|
||||||
$this->_redirect('showbuilder');
|
$this->_redirect('showbuilder');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$message = _("Wrong username or password provided. Please try again.");
|
$form = $this->loginError($username);
|
||||||
Application_Model_Subjects::increaseLoginAttempts($username);
|
|
||||||
Application_Model_LoginAttempts::increaseAttempts($_SERVER['REMOTE_ADDR']);
|
|
||||||
$form = new Application_Form_Login();
|
|
||||||
$error = true;
|
|
||||||
//Only show the captcha if you get your login wrong 4 times in a row.
|
|
||||||
if (Application_Model_Subjects::getLoginAttempts($username) > 3)
|
|
||||||
{
|
|
||||||
$form->addRecaptcha();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$form = $this->loginError($username);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->view->message = $message;
|
|
||||||
$this->view->error = $error;
|
|
||||||
$this->view->form = $form;
|
$this->view->form = $form;
|
||||||
$this->view->airtimeVersion = Application_Model_Preference::GetAirtimeVersion();
|
$this->view->airtimeVersion = Application_Model_Preference::GetAirtimeVersion();
|
||||||
$this->view->airtimeCopyright = AIRTIME_COPYRIGHT_DATE;
|
$this->view->airtimeCopyright = AIRTIME_COPYRIGHT_DATE;
|
||||||
|
@ -260,4 +251,24 @@ class LoginController extends Zend_Controller_Action
|
||||||
|
|
||||||
$this->view->form = $form;
|
$this->view->form = $form;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* populates view with results from a login error and adds a new form
|
||||||
|
*
|
||||||
|
* @param String $username user that failed to login
|
||||||
|
* @return new form
|
||||||
|
*/
|
||||||
|
private function loginError($username)
|
||||||
|
{
|
||||||
|
$this->view->message = _("Wrong username or password provided. Please try again.");
|
||||||
|
Application_Model_Subjects::increaseLoginAttempts($username);
|
||||||
|
Application_Model_LoginAttempts::increaseAttempts($_SERVER['REMOTE_ADDR']);
|
||||||
|
$form = new Application_Form_Login();
|
||||||
|
$this->view->error = true;
|
||||||
|
//Only show the captcha if you get your login wrong 4 times in a row.
|
||||||
|
if (Application_Model_Subjects::getLoginAttempts($username) > 3) {
|
||||||
|
$form->addRecaptcha();
|
||||||
|
}
|
||||||
|
return $form;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,7 +226,7 @@ class PlaylistController extends Zend_Controller_Action
|
||||||
$obj = new $objInfo['className']($id);
|
$obj = new $objInfo['className']($id);
|
||||||
$this->createFullResponse($obj);
|
$this->createFullResponse($obj);
|
||||||
} catch (PlaylistNotFoundException $e) {
|
} catch (PlaylistNotFoundException $e) {
|
||||||
$this->playlistNotFound();
|
$this->playlistNotFound($type);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$this->playlistUnknownError($e);
|
$this->playlistUnknownError($e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ class PodcastController extends Zend_Controller_Action {
|
||||||
*/
|
*/
|
||||||
public function stationAction() {
|
public function stationAction() {
|
||||||
|
|
||||||
if (!Billing::isStationPodcastAllowed()) {
|
if (LIBRETIME_ENABLE_BILLING === true && !Billing::isStationPodcastAllowed()) {
|
||||||
$this->render("featureupgrade-page");
|
$this->render("featureupgrade-page");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,7 +224,8 @@ class PageLayoutInitPlugin extends Zend_Controller_Plugin_Abstract
|
||||||
}
|
}
|
||||||
|
|
||||||
$view->headScript()->appendScript("var userType = '$userType';");
|
$view->headScript()->appendScript("var userType = '$userType';");
|
||||||
if (array_key_exists('REQUEST_URI', $_SERVER) //Doesn't exist for unit tests
|
if (LIBRETIME_ENABLE_LIVECHAT === true
|
||||||
|
&& array_key_exists('REQUEST_URI', $_SERVER) //Doesn't exist for unit tests
|
||||||
&& strpos($_SERVER['REQUEST_URI'], 'Dashboard/stream-player') === false
|
&& strpos($_SERVER['REQUEST_URI'], 'Dashboard/stream-player') === false
|
||||||
&& strpos($_SERVER['REQUEST_URI'], 'audiopreview') === false
|
&& strpos($_SERVER['REQUEST_URI'], 'audiopreview') === false
|
||||||
&& $_SERVER['REQUEST_URI'] != "/") {
|
&& $_SERVER['REQUEST_URI'] != "/") {
|
||||||
|
|
|
@ -131,7 +131,7 @@ class Application_Form_EditUser extends Zend_Form
|
||||||
$timezone->setDecorators(array('ViewHelper'));
|
$timezone->setDecorators(array('ViewHelper'));
|
||||||
$this->addElement($timezone);
|
$this->addElement($timezone);
|
||||||
|
|
||||||
if (Application_Model_User::getCurrentUser()->isSuperAdmin()) {
|
if (LIBRETIME_ENABLE_BILLING === true && Application_Model_User::getCurrentUser()->isSuperAdmin()) {
|
||||||
$elemsToDisable = array($password, $passwordVerify, $email, $firstName, $lastName,
|
$elemsToDisable = array($password, $passwordVerify, $email, $firstName, $lastName,
|
||||||
$cellPhone, $skype, $jabber);
|
$cellPhone, $skype, $jabber);
|
||||||
foreach ($elemsToDisable as $element) {
|
foreach ($elemsToDisable as $element) {
|
||||||
|
|
|
@ -1573,7 +1573,7 @@ class Application_Model_Preference
|
||||||
* @return int either 0 (public) or 1 (private)
|
* @return int either 0 (public) or 1 (private)
|
||||||
*/
|
*/
|
||||||
public static function getStationPodcastPrivacy() {
|
public static function getStationPodcastPrivacy() {
|
||||||
if (!Billing::isStationPodcastAllowed()) {
|
if (LIBRETIME_ENABLE_BILLING === true && !Billing::isStationPodcastAllowed()) {
|
||||||
// return private setting
|
// return private setting
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,16 +81,18 @@ class Application_Model_RabbitMq
|
||||||
public static function getRmqConfigPath() {
|
public static function getRmqConfigPath() {
|
||||||
//Hack for Airtime Pro. The RabbitMQ settings for communicating with airtime_analyzer are global
|
//Hack for Airtime Pro. The RabbitMQ settings for communicating with airtime_analyzer are global
|
||||||
//and shared between all instances on Airtime Pro.
|
//and shared between all instances on Airtime Pro.
|
||||||
|
//
|
||||||
|
// todo: rewrite me to only use the config class and not access /etc/airtime directly
|
||||||
$CC_CONFIG = Config::getConfig();
|
$CC_CONFIG = Config::getConfig();
|
||||||
$devEnv = "production"; //Default
|
$devEnv = "production"; //Default
|
||||||
if (array_key_exists("dev_env", $CC_CONFIG)) {
|
if (array_key_exists("dev_env", $CC_CONFIG)) {
|
||||||
$devEnv = $CC_CONFIG["dev_env"];
|
$devEnv = $CC_CONFIG["dev_env"];
|
||||||
}
|
}
|
||||||
$rmq_config_path = "/etc/airtime-saas/".$devEnv."/rabbitmq-analyzer.ini";
|
$rmq_config_path = LIBRETIME_CONF_DIR . '/' . $devEnv."/rabbitmq-analyzer.ini";
|
||||||
if (!file_exists($rmq_config_path)) {
|
if (!file_exists($rmq_config_path)) {
|
||||||
// If the dev env specific rabbitmq-analyzer.ini doesn't exist default
|
// If the dev env specific rabbitmq-analyzer.ini doesn't exist default
|
||||||
// to the production rabbitmq-analyzer.ini
|
// to the production rabbitmq-analyzer.ini
|
||||||
$rmq_config_path = "/etc/airtime-saas/production/rabbitmq-analyzer.ini";
|
$rmq_config_path = LIBRETIME_CONF_PATH . "/production/rabbitmq-analyzer.ini";
|
||||||
}
|
}
|
||||||
return $rmq_config_path;
|
return $rmq_config_path;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<h2><?php echo _("My Profile") ?></h2>
|
<h2><?php echo _("My Profile") ?></h2>
|
||||||
<div id="current-user-container">
|
<div id="current-user-container">
|
||||||
|
|
||||||
<?php if(Application_Model_User::getCurrentUser()->isSuperAdmin()) : ?>
|
<?php if(LIBRETIME_ENABLE_BILLING === true && Application_Model_User::getCurrentUser()->isSuperAdmin()) : ?>
|
||||||
<div id="user_details_superadmin_message">
|
<div id="user_details_superadmin_message">
|
||||||
<p class="alert alert-error">
|
<p class="alert alert-error">
|
||||||
<?=sprintf(_("<b>Note:</b> Since you're the station owner, your account information can be edited in <a href=\"%s\">Billing Settings</a> instead."), "/billing/client");?>
|
<?=sprintf(_("<b>Note:</b> Since you're the station owner, your account information can be edited in <a href=\"%s\">Billing Settings</a> instead."), "/billing/client");?>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
if (Billing::isStationPodcastAllowed()) { ?>
|
if (LIBRETIME_ENABLE_BILLING === true && Billing::isStationPodcastAllowed()) { ?>
|
||||||
<h3 class="collapsible-header" id="soundcloud-heading"><span class="arrow-icon"></span><?php echo _("SoundCloud Settings") ?></h3>
|
<h3 class="collapsible-header" id="soundcloud-heading"><span class="arrow-icon"></span><?php echo _("SoundCloud Settings") ?></h3>
|
||||||
<div class="collapsible-content" id="soundcloud-settings">
|
<div class="collapsible-content" id="soundcloud-settings">
|
||||||
<?php echo $this->element->getSubform('preferences_soundcloud') ?>
|
<?php echo $this->element->getSubform('preferences_soundcloud') ?>
|
||||||
|
|
|
@ -26,9 +26,11 @@
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<?php if (LIBRETIME_ENABLE_BILLING === true) { ?>
|
||||||
<div class="user-data" id="user_details_superadmin_message" style="display: none; margin-top: 105px; text-align: center;">
|
<div class="user-data" id="user_details_superadmin_message" style="display: none; margin-top: 105px; text-align: center;">
|
||||||
<?=sprintf(_("Super Admin details can be changed in your <a href=\"%s\">Billing Settings</a>."), "/billing/client");?>
|
<?=sprintf(_("Super Admin details can be changed in your <a href=\"%s\">Billing Settings</a>."), "/billing/client");?>
|
||||||
</div>
|
</div>
|
||||||
|
<?php } ?>
|
||||||
<div class="user-data simple-formblock" id="user_details">
|
<div class="user-data simple-formblock" id="user_details">
|
||||||
<?php echo $this->successMessage ?>
|
<?php echo $this->successMessage ?>
|
||||||
<fieldset class="padded">
|
<fieldset class="padded">
|
||||||
|
|
|
@ -25,8 +25,7 @@ require_once(dirname(dirname( __DIR__)) . "/application/models/airtime/CcMusicDi
|
||||||
class MediaSetup extends Setup {
|
class MediaSetup extends Setup {
|
||||||
|
|
||||||
const MEDIA_FOLDER = "mediaFolder";
|
const MEDIA_FOLDER = "mediaFolder";
|
||||||
const AIRTIME_CONF_PATH = "/etc/airtime/airtime.conf";
|
const LIBRETIME_CONF_FILE_NAME = "airtime.conf";
|
||||||
const RMQ_INI_BASE_PATH = "/etc/airtime-saas/";
|
|
||||||
const RMQ_INI_FILE_NAME = "rabbitmq-analyzer.ini";
|
const RMQ_INI_FILE_NAME = "rabbitmq-analyzer.ini";
|
||||||
|
|
||||||
static $path;
|
static $path;
|
||||||
|
@ -77,8 +76,11 @@ class MediaSetup extends Setup {
|
||||||
* airtime.conf to airtime.conf.tmp during the setup process. Now that we're done,
|
* airtime.conf to airtime.conf.tmp during the setup process. Now that we're done,
|
||||||
* we can rename it to airtime.conf.bak to avoid confusion.
|
* we can rename it to airtime.conf.bak to avoid confusion.
|
||||||
*/
|
*/
|
||||||
if (file_exists(self::AIRTIME_CONF_PATH . ".tmp")) {
|
$fileName = LIBRETIME_CONF_DIR . '/' . self::LIBRETIME_CONF_FILE_NAME;
|
||||||
rename(self::AIRTIME_CONF_PATH . ".tmp", self::AIRTIME_CONF_PATH . ".bak");
|
$tmpFile = $fileName . '.tmp';
|
||||||
|
$bakFile = $fileName . '.bak';
|
||||||
|
if (file_exists($tmpFile)) {
|
||||||
|
rename($tmpFile, $bakFile);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self::$message = "Failed to move airtime.conf; /etc/airtime doesn't exist!";
|
self::$message = "Failed to move airtime.conf; /etc/airtime doesn't exist!";
|
||||||
|
@ -96,7 +98,7 @@ class MediaSetup extends Setup {
|
||||||
* @return boolean false if either of the copy or removal operations fail
|
* @return boolean false if either of the copy or removal operations fail
|
||||||
*/
|
*/
|
||||||
function moveAirtimeConfig() {
|
function moveAirtimeConfig() {
|
||||||
return copy(AIRTIME_CONF_TEMP_PATH, self::AIRTIME_CONF_PATH)
|
return copy(AIRTIME_CONF_TEMP_PATH, LIBRETIME_CONF_DIR . '/' . self::LIBRETIME_CONF_FILE_NAME)
|
||||||
&& unlink(AIRTIME_CONF_TEMP_PATH);
|
&& unlink(AIRTIME_CONF_TEMP_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,8 +107,8 @@ class MediaSetup extends Setup {
|
||||||
* @return boolean false if either of the copy or removal operations fail
|
* @return boolean false if either of the copy or removal operations fail
|
||||||
*/
|
*/
|
||||||
function moveRmqConfig() {
|
function moveRmqConfig() {
|
||||||
return copy(RMQ_INI_TEMP_PATH, self::RMQ_INI_BASE_PATH . self::RMQ_INI_FILE_NAME)
|
return copy(RMQ_INI_TEMP_PATH, LIBRETIME_CONF_DIR . '/' . self::RMQ_INI_FILE_NAME)
|
||||||
&& copy(RMQ_INI_TEMP_PATH, self::RMQ_INI_BASE_PATH . "production/" . self::RMQ_INI_FILE_NAME)
|
&& copy(RMQ_INI_TEMP_PATH, LIBRETIME_CONF_DIR . '/production/' . self::RMQ_INI_FILE_NAME)
|
||||||
&& unlink(RMQ_INI_TEMP_PATH);
|
&& unlink(RMQ_INI_TEMP_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
pre.codehilite > code,
|
||||||
|
div.codehilite > pre {
|
||||||
|
color: #808080;
|
||||||
|
padding: 1em;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 110%;
|
||||||
|
font-weight: bold;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.codehilite > code.language-console > span,
|
||||||
|
div.codehilite > pre > span[style*="color: #AA22FF"] {
|
||||||
|
color: #808080 !important;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
Documentation
|
||||||
|
=============
|
||||||
|
|
||||||
|
The LibreTime documentation site is generated with [mkdocs](http://www.mkdocs.org/). To get started contributing to this project, fork it on Github. Then install mkdocs and clone this repo locally:
|
||||||
|
|
||||||
|
:::bash
|
||||||
|
sudo brew install python # For OSX users
|
||||||
|
sudo aptitude install python-pip # For Debian/Ubuntu users
|
||||||
|
sudo pip install mkdocs
|
||||||
|
git clone https://github.com/libretime/libretime
|
||||||
|
cd libretime
|
||||||
|
git remote add sandbox https://github.com/<username>/libretime # URL for your fork
|
||||||
|
mkdocs build --clean
|
||||||
|
mkdocs serve
|
||||||
|
|
||||||
|
Your local LibreTime docs site should now be available for browsing: [http://localhost:8888/](http://localhost:8888/).
|
||||||
|
|
||||||
|
When you find a typo, an error, unclear or missing explanations or instructions, open a new terminal and start editing. Your changes should be reflected automatically on the local server. Find the page you’d like to edit; everything is in the docs/ directory. Make your changes, commit and push them, and start a pull request:
|
||||||
|
|
||||||
|
:::bash
|
||||||
|
git checkout -b fix_typo
|
||||||
|
vi docs/index.md # Add/edit/remove whatever you see fit. Be bold!
|
||||||
|
mkdocs build --clean; mkdocs serve # Go check your changes. We’ll wait...
|
||||||
|
git diff # Make sure there aren’t any unintended changes.
|
||||||
|
git commit -am”Fixed typo.” # Useful commit message are a good habit.
|
||||||
|
git push sandbox fix_typo
|
||||||
|
|
||||||
|
Visit your fork on Github and start a PR.
|
|
@ -0,0 +1,9 @@
|
||||||
|
Features
|
||||||
|
========
|
||||||
|
|
||||||
|
TBD
|
||||||
|
|
||||||
|
Screenshots
|
||||||
|
-----------
|
||||||
|
|
||||||
|
TBD
|
|
@ -0,0 +1,25 @@
|
||||||
|
Welcome to LibreTime
|
||||||
|
====================
|
||||||
|
|
||||||
|
LibreTime makes it easy to run your own online radio station. Check out some [features](features.md) and [screenshots](features.md#screenshots), then [install it](install.md) and start broadcasting!
|
||||||
|
|
||||||
|
LibreTime is Free/Libre and Open Source Software (FLOSS). Among other things, this means that you have the freedom to:
|
||||||
|
|
||||||
|
* Run it royalty-free for as long as you like.
|
||||||
|
* Read and alter the code that makes it work (or hire someone to do this for you!)
|
||||||
|
* Contribute documentation, bug-fixes, etc. so that everyone in the community benefits.
|
||||||
|
|
||||||
|
LibreTime is a fork of AirTime due to stalled development of the FLOSS version. For background on this, see this [open letter to the Airtime community](https://gist.github.com/hairmare/8c03b69c9accc90cfe31fd7e77c3b07d).
|
||||||
|
|
||||||
|
|
||||||
|
Getting Started
|
||||||
|
---------------
|
||||||
|
|
||||||
|
The easiest way to check out LibreTime for yourself is to run a local instance in a virtual machine. Assuming you already have Git, Vagrant and Virtualbox installed, just run:
|
||||||
|
|
||||||
|
:::bash
|
||||||
|
git clone https://github.com/libretime/libretime.git
|
||||||
|
cd libretime
|
||||||
|
vagrant up
|
||||||
|
|
||||||
|
Of course, this setup isn't appropriate for production use. For that, check out our [installation instructions](install.md).
|
|
@ -0,0 +1,9 @@
|
||||||
|
Installing LibreTime
|
||||||
|
====================
|
||||||
|
|
||||||
|
LibreTime should generally be installed on a dedicated host. By default, its installer will install and configure all its dependencies. At the moment, the installer works best on Ubuntu Trusty.
|
||||||
|
|
||||||
|
:::bash
|
||||||
|
./install
|
||||||
|
|
||||||
|
Plans are in the works for ```.deb``` and ```.rpm``` packages, as well as Docker and AWS images.
|
|
@ -0,0 +1,10 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
echo "Updating Apt."
|
||||||
|
apt-get update > /dev/null
|
||||||
|
echo "Ensuring Pip is installed."
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq python-pip > /dev/null
|
||||||
|
echo "Updating Pip."
|
||||||
|
pip install pip -q -q --upgrade > /dev/null
|
||||||
|
echo "Ensuring Mkdocs is installed."
|
||||||
|
pip install -q mkdocs > /dev/null
|
|
@ -0,0 +1,10 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
cd /vagrant
|
||||||
|
echo "Stopping any running Mkdocs servers."
|
||||||
|
pkill mkdocs
|
||||||
|
echo "Building Mkdocs documentation."
|
||||||
|
mkdocs build --clean -q > /dev/null
|
||||||
|
echo "Launching Mkdocs server."
|
||||||
|
mkdocs serve > /dev/null 2>&1 &
|
||||||
|
echo "Visit http://localhost:8888 to see the LibreTime documentation."
|
|
@ -0,0 +1,20 @@
|
||||||
|
site_name: LibreTime
|
||||||
|
theme: readthedocs
|
||||||
|
|
||||||
|
dev_addr: '0.0.0.0:8888'
|
||||||
|
site_dir: 'build/docs'
|
||||||
|
markdown_extensions:
|
||||||
|
- codehilite:
|
||||||
|
noclasses: True
|
||||||
|
pygments_style: emacs
|
||||||
|
|
||||||
|
extra_css:
|
||||||
|
- '_css/term.css'
|
||||||
|
|
||||||
|
pages:
|
||||||
|
- 'Home': index.md
|
||||||
|
- 'Features': features.md
|
||||||
|
- 'Install': install.md
|
||||||
|
- 'Development':
|
||||||
|
- 'Testing': testing.md
|
||||||
|
- 'Documentation': documentation.md
|
|
@ -28,7 +28,7 @@ Developers
|
||||||
To debug, you can run celery directly from the command line:
|
To debug, you can run celery directly from the command line:
|
||||||
|
|
||||||
$ cd /my/airtime/root/python_apps/airtime-celery
|
$ cd /my/airtime/root/python_apps/airtime-celery
|
||||||
$ RMQ_CONFIG_FILE=/etc/airtime/airtime.conf celery -A airtime-celery.tasks worker --loglevel=info
|
$ RMQ_CONFIG_FILE=${LIBRETIME_CONF_DIR}/airtime.conf celery -A airtime-celery.tasks worker --loglevel=info
|
||||||
|
|
||||||
This worker can be run alongside the service without issue.
|
This worker can be run alongside the service without issue.
|
||||||
|
|
||||||
|
@ -57,8 +57,8 @@ If you run into issues getting Celery to accept tasks from Airtime:
|
||||||
|
|
||||||
2) Check the log file (/var/log/airtime/airtime-celery[-DEV_ENV].log) to make sure Celery started correctly.
|
2) Check the log file (/var/log/airtime/airtime-celery[-DEV_ENV].log) to make sure Celery started correctly.
|
||||||
|
|
||||||
3) Check your /etc/airtime/airtime.conf rabbitmq settings. Make sure the settings here align with
|
3) Check your $LIBRETIME_CONF_DIR/airtime.conf rabbitmq settings. Make sure the settings here align with
|
||||||
/etc/airtime-saas/production/rabbitmq.ini.
|
$LIBRETIME_CONF_DIR/$ENVIRONMENT/rabbitmq.ini.
|
||||||
|
|
||||||
4) Check RabbitMQ to make sure the celeryresults and task queues were created in the correct vhost.
|
4) Check RabbitMQ to make sure the celeryresults and task queues were created in the correct vhost.
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ from boto.s3.key import Key
|
||||||
# https://github.com/docker/docker-registry/issues/400
|
# https://github.com/docker/docker-registry/issues/400
|
||||||
u'fix getaddrinfo deadlock'.encode('idna')
|
u'fix getaddrinfo deadlock'.encode('idna')
|
||||||
|
|
||||||
CLOUD_CONFIG_PATH = '/etc/airtime-saas/cloud_storage.conf'
|
CLOUD_CONFIG_PATH = os.path.join(os.getenv('LIBRETIME_CONF_DIR', '/etc/airtime'), 'cloud_storage.conf')
|
||||||
STORAGE_BACKEND_FILE = "file"
|
STORAGE_BACKEND_FILE = "file"
|
||||||
SOCKET_TIMEOUT = 240
|
SOCKET_TIMEOUT = 240
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ from libcloud.storage.providers import get_driver
|
||||||
from libcloud.storage.types import Provider, ContainerDoesNotExistError, ObjectDoesNotExistError
|
from libcloud.storage.types import Provider, ContainerDoesNotExistError, ObjectDoesNotExistError
|
||||||
|
|
||||||
|
|
||||||
CLOUD_CONFIG_PATH = '/etc/airtime-saas/cloud_storage.conf'
|
CLOUD_CONFIG_PATH = os.path.join(os.getenv('LIBRETIME_CONF_DIR', '/etc/airtime'), 'cloud_storage.conf')
|
||||||
STORAGE_BACKEND_FILE = "file"
|
STORAGE_BACKEND_FILE = "file"
|
||||||
|
|
||||||
class CloudStorageUploader:
|
class CloudStorageUploader:
|
||||||
|
|
|
@ -8,8 +8,9 @@ import os
|
||||||
import airtime_analyzer.airtime_analyzer as aa
|
import airtime_analyzer.airtime_analyzer as aa
|
||||||
|
|
||||||
VERSION = "1.0"
|
VERSION = "1.0"
|
||||||
DEFAULT_RMQ_CONFIG_PATH = '/etc/airtime/airtime.conf'
|
LIBRETIME_CONF_DIR = os.getenv('LIBRETIME_CONF_DIR', '/etc/airtime')
|
||||||
DEFAULT_CLOUD_STORAGE_CONFIG_PATH = '/etc/airtime-saas/production/cloud_storage.conf'
|
DEFAULT_RMQ_CONFIG_PATH = os.path.join(LIBRETIME_CONF_DIR, 'airtime.conf')
|
||||||
|
DEFAULT_CLOUD_STORAGE_CONFIG_PATH = os.path.join(LIBRETIME_CONF_DIR, os.getenv('ENVIRONMENT', 'production'), 'airtime.conf')
|
||||||
DEFAULT_HTTP_RETRY_PATH = '/tmp/airtime_analyzer_http_retries'
|
DEFAULT_HTTP_RETRY_PATH = '/tmp/airtime_analyzer_http_retries'
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
|
|
|
@ -22,7 +22,7 @@ def teardown():
|
||||||
def test_basic():
|
def test_basic():
|
||||||
filename = os.path.basename(DEFAULT_AUDIO_FILE)
|
filename = os.path.basename(DEFAULT_AUDIO_FILE)
|
||||||
q = Queue.Queue()
|
q = Queue.Queue()
|
||||||
#cloud_storage_config_path = '/etc/airtime-saas/production/cloud_storage.conf'
|
#cloud_storage_config_path = os.path.join(os.getenv('LIBRETIME_CONF_DIR', '/etc/airtime'), '/production/cloud_storage.conf')
|
||||||
#cloud_storage_config = config_file.read_config_file(cloud_storage_config_path)
|
#cloud_storage_config = config_file.read_config_file(cloud_storage_config_path)
|
||||||
cloud_storage_config = SafeConfigParser()
|
cloud_storage_config = SafeConfigParser()
|
||||||
cloud_storage_config.add_section("current_backend")
|
cloud_storage_config.add_section("current_backend")
|
||||||
|
|
Loading…
Reference in New Issue