diff --git a/.travis.yml b/.travis.yml index 1ff3e2f56..be7aed736 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,6 +55,7 @@ install: fi - > if [[ "$PYTHON" == true ]]; then + pip install --user mkdocs pushd python_apps/airtime_analyzer python setup.py install --dry-run --no-init-script popd @@ -69,3 +70,17 @@ before_script: script: - ./travis/php.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 diff --git a/airtime_mvc/application/cloud_storage/Amazon_S3StorageBackend.php b/airtime_mvc/application/cloud_storage/Amazon_S3StorageBackend.php index 0145f00af..c91d9f442 100644 --- a/airtime_mvc/application/cloud_storage/Amazon_S3StorageBackend.php +++ b/airtime_mvc/application/cloud_storage/Amazon_S3StorageBackend.php @@ -118,8 +118,14 @@ class Amazon_S3StorageBackend extends StorageBackend public function getFilePrefix() { - $hostingId = Billing::getClientInstanceId(); - $filePrefix = substr($hostingId, -2)."/".$hostingId; + $filePrefix = ''; + // 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; } } diff --git a/airtime_mvc/application/common/UsabilityHints.php b/airtime_mvc/application/common/UsabilityHints.php index 04022a1a7..7acf92446 100644 --- a/airtime_mvc/application/common/UsabilityHints.php +++ b/airtime_mvc/application/common/UsabilityHints.php @@ -103,7 +103,7 @@ class Application_Common_UsabilityHints "", ""); } - } else if ($userIsOnShowbuilderPage && $userIsSuperAdmin) { + } else if (LIBRETIME_ENABLE_BILLING === true && $userIsOnShowbuilderPage && $userIsSuperAdmin) { $unpaidInvoice = Billing::checkForUnpaidInvoice(); if ($unpaidInvoice != null) { $invoiceUrl = "/billing/invoice?invoiceid=" . $unpaidInvoice['id']; diff --git a/airtime_mvc/application/configs/constants.php b/airtime_mvc/application/configs/constants.php index af84e69cb..f3ae0c97d 100644 --- a/airtime_mvc/application/configs/constants.php +++ b/airtime_mvc/application/configs/constants.php @@ -106,11 +106,15 @@ define('UI_PLAYLISTCONTROLLER_OBJ_SESSNAME', 'PLAYLISTCONTROLLER_OBJ'); define('UI_BLOCK_SESSNAME', 'BLOCK');*/ //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"); +//LiveChat integration +define('LIBRETIME_ENABLE_LIVECHAT', false); + //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 define('PROVISIONING_STATUS_SUSPENDED' , 'Suspended'); @@ -141,3 +145,6 @@ define('STATION_PODCAST_SERVICE_NAME', 'station_podcast'); //define('IMPORTED_PODCAST', 1); define('ITUNES_XML_NAMESPACE_URL', 'http://www.itunes.com/dtds/podcast-1.0.dtd'); + +// Billing configuration +define('LIBRETIME_ENABLE_BILLING', false); diff --git a/airtime_mvc/application/configs/navigation.php b/airtime_mvc/application/configs/navigation.php index 2a12003f7..0851b0cf6 100644 --- a/airtime_mvc/application/configs/navigation.php +++ b/airtime_mvc/application/configs/navigation.php @@ -7,122 +7,123 @@ * Zend_Navigation_Page::factory() when constructing * the navigation container below. */ -$pages = array( - array( - 'label' => ""._('My Podcast'), - 'module' => 'default', - 'controller' => 'podcast', - 'action' => 'station', - 'resource' => 'podcast' - ), - array( - 'label' => ""._('Radio Page'), - 'uri' => '/', - 'resource' => '', - 'pages' => array( +$pages = array(); +$pages[] = array( + 'label' => ""._('My Podcast'), + 'module' => 'default', + 'controller' => 'podcast', + 'action' => 'station', + 'resource' => 'podcast' +); +$pages[] = array( + 'label' => ""._('Radio Page'), + 'uri' => '/', + 'resource' => '', + 'pages' => array( + ) +); +$pages[] = array( + 'label' => ""._('Calendar'), + 'module' => 'default', + 'controller' => 'schedule', + 'action' => 'index', + 'resource' => 'schedule' +); +$pages[] = array( + 'label' => ""._('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' => ""._('Calendar'), - 'module' => 'default', - 'controller' => 'schedule', - 'action' => 'index', - 'resource' => 'schedule' - ), - array( - 'label' => ""._('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', - ) + ) +); +$pages[] = array( + 'label' => ""._("Settings"), + 'resource' => 'preference', + 'action' => 'index', + 'module' => 'default', + 'controller' => 'preference', + 'title' => 'Settings', + 'pages' => array( + array( + 'label' => _('General'), + 'module' => 'default', + 'controller' => 'preference' + ), + array( + 'label' => _('My Profile'), + 'controller' => 'user', + 'action' => 'edit-user', + 'resource' => 'user' + ), + array( + 'label' => _('Users'), + 'module' => 'default', + 'controller' => 'user', + 'action' => 'add-user', + 'resource' => 'user' + ), + array( + 'label' => _('Streams'), + 'module' => 'default', + 'controller' => 'preference', + 'action' => 'stream-setting' ) - ), - array( - 'label' => ""._("Settings"), - 'resource' => 'preference', - 'action' => 'index', - 'module' => 'default', - 'controller' => 'preference', - 'title' => 'Settings', - 'pages' => array( - array( - 'label' => _('General'), - 'module' => 'default', - 'controller' => 'preference' - ), - array( - 'label' => _('My Profile'), - 'controller' => 'user', - 'action' => 'edit-user', - 'resource' => 'user' - ), - array( - 'label' => _('Users'), - 'module' => 'default', - 'controller' => 'user', - 'action' => 'add-user', - 'resource' => 'user' - ), - array( - 'label' => _('Streams'), - 'module' => 'default', - 'controller' => 'preference', - 'action' => 'stream-setting' - ) - ) - ), - array( - 'label' => ""._("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( + ) +); +$pages[] = array( + 'label' => ""._("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' + ), + ) +); +if (LIBRETIME_ENABLE_BILLING === true) { + $pages[] = array( 'label' => (Application_Model_Preference::GetPlanLevel()=="trial") ? ""._('Upgrade')."" : ""._('Billing'), 'controller' => 'billing', 'action' => 'upgrade', @@ -151,48 +152,48 @@ $pages = array( 'resource' => 'billing' ) ) - ), - array( - 'label' => ""._('Help'), - 'controller' => 'dashboard', - 'action' => 'help', - 'resource' => 'dashboard', - 'title' => 'Help', - 'pages' => array( - array( - 'label' => _('Getting Started'), - 'module' => 'default', - 'controller' => 'dashboard', - 'action' => 'help', - 'resource' => 'dashboard' - ), - array( - 'label' => _('FAQ'), - 'uri' => FAQ_URL, - 'target' => "_blank" - ), - array( - 'label' => _('User Manual'), - 'uri' => USER_MANUAL_URL, - 'target' => "_blank" - ), - array( - 'label' => _('File a Support Ticket'), - 'uri' => SUPPORT_TICKET_URL, - 'target' => "_blank" - ), - array( - 'label' => _(sprintf("Help Translate %s", PRODUCT_NAME)), - 'uri' => AIRTIME_TRANSIFEX_URL, - 'target' => "_blank" - ), - array( - 'label' => _('What\'s New?'), - 'uri' => UI_REVAMP_YOUTUBE_URL, - 'target' => "_blank" - ) + ); +} +$pages[] = array( + 'label' => ""._('Help'), + 'controller' => 'dashboard', + 'action' => 'help', + 'resource' => 'dashboard', + 'title' => 'Help', + 'pages' => array( + array( + 'label' => _('Getting Started'), + 'module' => 'default', + 'controller' => 'dashboard', + 'action' => 'help', + 'resource' => 'dashboard' + ), + array( + 'label' => _('FAQ'), + 'uri' => FAQ_URL, + 'target' => "_blank" + ), + array( + 'label' => _('User Manual'), + 'uri' => USER_MANUAL_URL, + 'target' => "_blank" + ), + array( + 'label' => _('File a Support Ticket'), + 'uri' => SUPPORT_TICKET_URL, + 'target' => "_blank" + ), + array( + 'label' => _(sprintf("Help Translate %s", PRODUCT_NAME)), + 'uri' => AIRTIME_TRANSIFEX_URL, + 'target' => "_blank" + ), + array( + 'label' => _('What\'s New?'), + 'uri' => UI_REVAMP_YOUTUBE_URL, + 'target' => "_blank" ) - ), + ) ); diff --git a/airtime_mvc/application/controllers/LibraryController.php b/airtime_mvc/application/controllers/LibraryController.php index d1f4c9604..e063ea263 100644 --- a/airtime_mvc/application/controllers/LibraryController.php +++ b/airtime_mvc/application/controllers/LibraryController.php @@ -443,7 +443,7 @@ class LibraryController extends Zend_Controller_Action $this->_helper->layout->disableLayout(); - if (!Billing::isStationPodcastAllowed()) { + if (LIBRETIME_ENABLE_BILLING === true && !Billing::isStationPodcastAllowed()) { $this->renderScript("podcast/featureupgrade-pane.phtml"); } diff --git a/airtime_mvc/application/controllers/LoginController.php b/airtime_mvc/application/controllers/LoginController.php index bd3869919..6912f07c6 100644 --- a/airtime_mvc/application/controllers/LoginController.php +++ b/airtime_mvc/application/controllers/LoginController.php @@ -45,7 +45,7 @@ class LoginController extends Zend_Controller_Action //uses separate layout without a navigation. $this->_helper->layout->setLayout('login'); - $error = false; + $this->view->error = false; $baseUrl = Application_Common_OsPath::getBaseDir(); @@ -92,7 +92,7 @@ class LoginController extends Zend_Controller_Action Application_Model_Preference::SetUserLocale($locale); $this->_redirect('showbuilder'); - } else { + } elseif (LIBRETIME_ENABLE_WHMCS) { $email = $form->getValue('username'); $authAdapter = new WHMCS_Auth_Adapter("admin", $email, $password); $auth = Zend_Auth::getInstance(); @@ -105,23 +105,14 @@ class LoginController extends Zend_Controller_Action $this->_redirect('showbuilder'); } else { - $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(); - $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(); - } + $form = $this->loginError($username); } + } else { + $form = $this->loginError($username); } } } - $this->view->message = $message; - $this->view->error = $error; $this->view->form = $form; $this->view->airtimeVersion = Application_Model_Preference::GetAirtimeVersion(); $this->view->airtimeCopyright = AIRTIME_COPYRIGHT_DATE; @@ -260,4 +251,24 @@ class LoginController extends Zend_Controller_Action $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; + } } diff --git a/airtime_mvc/application/controllers/PlaylistController.php b/airtime_mvc/application/controllers/PlaylistController.php index 543b2870b..84848d301 100644 --- a/airtime_mvc/application/controllers/PlaylistController.php +++ b/airtime_mvc/application/controllers/PlaylistController.php @@ -226,7 +226,7 @@ class PlaylistController extends Zend_Controller_Action $obj = new $objInfo['className']($id); $this->createFullResponse($obj); } catch (PlaylistNotFoundException $e) { - $this->playlistNotFound(); + $this->playlistNotFound($type); } catch (Exception $e) { $this->playlistUnknownError($e); } diff --git a/airtime_mvc/application/controllers/PodcastController.php b/airtime_mvc/application/controllers/PodcastController.php index 6c1fd05c3..d826f666b 100644 --- a/airtime_mvc/application/controllers/PodcastController.php +++ b/airtime_mvc/application/controllers/PodcastController.php @@ -27,7 +27,7 @@ class PodcastController extends Zend_Controller_Action { */ public function stationAction() { - if (!Billing::isStationPodcastAllowed()) { + if (LIBRETIME_ENABLE_BILLING === true && !Billing::isStationPodcastAllowed()) { $this->render("featureupgrade-page"); return; } diff --git a/airtime_mvc/application/controllers/plugins/PageLayoutInitPlugin.php b/airtime_mvc/application/controllers/plugins/PageLayoutInitPlugin.php index cf39af00a..f0239e413 100644 --- a/airtime_mvc/application/controllers/plugins/PageLayoutInitPlugin.php +++ b/airtime_mvc/application/controllers/plugins/PageLayoutInitPlugin.php @@ -224,7 +224,8 @@ class PageLayoutInitPlugin extends Zend_Controller_Plugin_Abstract } $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'], 'audiopreview') === false && $_SERVER['REQUEST_URI'] != "/") { diff --git a/airtime_mvc/application/forms/EditUser.php b/airtime_mvc/application/forms/EditUser.php index e35a9ce5d..cfe6ca790 100644 --- a/airtime_mvc/application/forms/EditUser.php +++ b/airtime_mvc/application/forms/EditUser.php @@ -131,7 +131,7 @@ class Application_Form_EditUser extends Zend_Form $timezone->setDecorators(array('ViewHelper')); $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, $cellPhone, $skype, $jabber); foreach ($elemsToDisable as $element) { diff --git a/airtime_mvc/application/models/Preference.php b/airtime_mvc/application/models/Preference.php index 3109e0b21..cdbab0500 100644 --- a/airtime_mvc/application/models/Preference.php +++ b/airtime_mvc/application/models/Preference.php @@ -1573,7 +1573,7 @@ class Application_Model_Preference * @return int either 0 (public) or 1 (private) */ public static function getStationPodcastPrivacy() { - if (!Billing::isStationPodcastAllowed()) { + if (LIBRETIME_ENABLE_BILLING === true && !Billing::isStationPodcastAllowed()) { // return private setting return 1; } diff --git a/airtime_mvc/application/models/RabbitMq.php b/airtime_mvc/application/models/RabbitMq.php index 16efc2674..0269971e6 100644 --- a/airtime_mvc/application/models/RabbitMq.php +++ b/airtime_mvc/application/models/RabbitMq.php @@ -81,16 +81,18 @@ class Application_Model_RabbitMq public static function getRmqConfigPath() { //Hack for Airtime Pro. The RabbitMQ settings for communicating with airtime_analyzer are global //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(); $devEnv = "production"; //Default if (array_key_exists("dev_env", $CC_CONFIG)) { $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 the dev env specific rabbitmq-analyzer.ini doesn't exist default // 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; } diff --git a/airtime_mvc/application/views/scripts/form/edit-user.phtml b/airtime_mvc/application/views/scripts/form/edit-user.phtml index 1d4e1587e..cff096136 100644 --- a/airtime_mvc/application/views/scripts/form/edit-user.phtml +++ b/airtime_mvc/application/views/scripts/form/edit-user.phtml @@ -1,7 +1,7 @@

- isSuperAdmin()) : ?> + isSuperAdmin()) : ?>

Note: Since you're the station owner, your account information can be edited in Billing Settings instead."), "/billing/client");?> diff --git a/airtime_mvc/application/views/scripts/form/preferences.phtml b/airtime_mvc/application/views/scripts/form/preferences.phtml index d2fa6494f..ad3aa1d6b 100644 --- a/airtime_mvc/application/views/scripts/form/preferences.phtml +++ b/airtime_mvc/application/views/scripts/form/preferences.phtml @@ -9,7 +9,7 @@

+ if (LIBRETIME_ENABLE_BILLING === true && Billing::isStationPodcastAllowed()) { ?>

element->getSubform('preferences_soundcloud') ?> diff --git a/airtime_mvc/application/views/scripts/user/add-user.phtml b/airtime_mvc/application/views/scripts/user/add-user.phtml index 573eb476e..b58294cb5 100644 --- a/airtime_mvc/application/views/scripts/user/add-user.phtml +++ b/airtime_mvc/application/views/scripts/user/add-user.phtml @@ -26,9 +26,11 @@
+ +
successMessage ?>
diff --git a/airtime_mvc/public/setup/media-setup.php b/airtime_mvc/public/setup/media-setup.php index 701ba0749..3816330ab 100644 --- a/airtime_mvc/public/setup/media-setup.php +++ b/airtime_mvc/public/setup/media-setup.php @@ -25,8 +25,7 @@ require_once(dirname(dirname( __DIR__)) . "/application/models/airtime/CcMusicDi class MediaSetup extends Setup { const MEDIA_FOLDER = "mediaFolder"; - const AIRTIME_CONF_PATH = "/etc/airtime/airtime.conf"; - const RMQ_INI_BASE_PATH = "/etc/airtime-saas/"; + const LIBRETIME_CONF_FILE_NAME = "airtime.conf"; const RMQ_INI_FILE_NAME = "rabbitmq-analyzer.ini"; 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, * we can rename it to airtime.conf.bak to avoid confusion. */ - if (file_exists(self::AIRTIME_CONF_PATH . ".tmp")) { - rename(self::AIRTIME_CONF_PATH . ".tmp", self::AIRTIME_CONF_PATH . ".bak"); + $fileName = LIBRETIME_CONF_DIR . '/' . self::LIBRETIME_CONF_FILE_NAME; + $tmpFile = $fileName . '.tmp'; + $bakFile = $fileName . '.bak'; + if (file_exists($tmpFile)) { + rename($tmpFile, $bakFile); } } else { 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 */ 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); } @@ -105,8 +107,8 @@ class MediaSetup extends Setup { * @return boolean false if either of the copy or removal operations fail */ function moveRmqConfig() { - return copy(RMQ_INI_TEMP_PATH, self::RMQ_INI_BASE_PATH . self::RMQ_INI_FILE_NAME) - && copy(RMQ_INI_TEMP_PATH, self::RMQ_INI_BASE_PATH . "production/" . self::RMQ_INI_FILE_NAME) + return copy(RMQ_INI_TEMP_PATH, LIBRETIME_CONF_DIR . '/' . self::RMQ_INI_FILE_NAME) + && copy(RMQ_INI_TEMP_PATH, LIBRETIME_CONF_DIR . '/production/' . self::RMQ_INI_FILE_NAME) && unlink(RMQ_INI_TEMP_PATH); } diff --git a/docs/_css/term.css b/docs/_css/term.css new file mode 100644 index 000000000..3510c5ff7 --- /dev/null +++ b/docs/_css/term.css @@ -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; +} diff --git a/docs/documentation.md b/docs/documentation.md new file mode 100644 index 000000000..a588dfdd2 --- /dev/null +++ b/docs/documentation.md @@ -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//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. diff --git a/docs/features.md b/docs/features.md new file mode 100644 index 000000000..3df32286b --- /dev/null +++ b/docs/features.md @@ -0,0 +1,9 @@ +Features +======== + +TBD + +Screenshots +----------- + +TBD diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 000000000..6dfb154c2 --- /dev/null +++ b/docs/index.md @@ -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). diff --git a/docs/install.md b/docs/install.md new file mode 100644 index 000000000..385237ff5 --- /dev/null +++ b/docs/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. diff --git a/docs/scripts/install.sh b/docs/scripts/install.sh new file mode 100755 index 000000000..d7fb756f3 --- /dev/null +++ b/docs/scripts/install.sh @@ -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 diff --git a/docs/scripts/serve.sh b/docs/scripts/serve.sh new file mode 100755 index 000000000..2596ef316 --- /dev/null +++ b/docs/scripts/serve.sh @@ -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." diff --git a/docs/TESTING.md b/docs/testing.md similarity index 100% rename from docs/TESTING.md rename to docs/testing.md diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 000000000..85554ac3f --- /dev/null +++ b/mkdocs.yml @@ -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 diff --git a/python_apps/airtime-celery/README.rst b/python_apps/airtime-celery/README.rst index 78df52a42..b5cf464c5 100644 --- a/python_apps/airtime-celery/README.rst +++ b/python_apps/airtime-celery/README.rst @@ -28,7 +28,7 @@ Developers To debug, you can run celery directly from the command line: $ 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. @@ -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. - 3) Check your /etc/airtime/airtime.conf rabbitmq settings. Make sure the settings here align with - /etc/airtime-saas/production/rabbitmq.ini. + 3) Check your $LIBRETIME_CONF_DIR/airtime.conf rabbitmq settings. Make sure the settings here align with + $LIBRETIME_CONF_DIR/$ENVIRONMENT/rabbitmq.ini. 4) Check RabbitMQ to make sure the celeryresults and task queues were created in the correct vhost. diff --git a/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader.py b/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader.py index 1b25d7d35..ed80ee1c5 100644 --- a/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader.py +++ b/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader.py @@ -10,7 +10,7 @@ from boto.s3.key import Key # https://github.com/docker/docker-registry/issues/400 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" SOCKET_TIMEOUT = 240 diff --git a/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader_libcloud.py b/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader_libcloud.py index c0950dc15..e98dfe0b2 100644 --- a/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader_libcloud.py +++ b/python_apps/airtime_analyzer/airtime_analyzer/cloud_storage_uploader_libcloud.py @@ -6,7 +6,7 @@ from libcloud.storage.providers import get_driver 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" class CloudStorageUploader: diff --git a/python_apps/airtime_analyzer/bin/airtime_analyzer b/python_apps/airtime_analyzer/bin/airtime_analyzer index 98ac8a5b6..18142a0f4 100755 --- a/python_apps/airtime_analyzer/bin/airtime_analyzer +++ b/python_apps/airtime_analyzer/bin/airtime_analyzer @@ -8,8 +8,9 @@ import os import airtime_analyzer.airtime_analyzer as aa VERSION = "1.0" -DEFAULT_RMQ_CONFIG_PATH = '/etc/airtime/airtime.conf' -DEFAULT_CLOUD_STORAGE_CONFIG_PATH = '/etc/airtime-saas/production/cloud_storage.conf' +LIBRETIME_CONF_DIR = os.getenv('LIBRETIME_CONF_DIR', '/etc/airtime') +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' def run(): diff --git a/python_apps/airtime_analyzer/tests/analyzer_pipeline_tests.py b/python_apps/airtime_analyzer/tests/analyzer_pipeline_tests.py index 8ea079847..e7f2b66e0 100644 --- a/python_apps/airtime_analyzer/tests/analyzer_pipeline_tests.py +++ b/python_apps/airtime_analyzer/tests/analyzer_pipeline_tests.py @@ -22,7 +22,7 @@ def teardown(): def test_basic(): filename = os.path.basename(DEFAULT_AUDIO_FILE) 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 = SafeConfigParser() cloud_storage_config.add_section("current_backend")