#!/home/streamera/bin/php/bin/php
<?php

if (posix_getpwuid(posix_geteuid())['name'] == 'root') {
	set_time_limit(0);

	if ($argc) {
		$rReload = false;
		$rFirstRun = false;

		if (isset($argv[1])) {
			$rFirstRun = true;
		}

		require str_replace('\\', '/', dirname($argv[0])) . '/www/stream/init.php';
		ini_set('display_startup_errors', 1);
		ini_set('display_errors', 1);
		error_reporting(32767);

		if (!$rFirstRun) {
			echo "\n" . 'Status' . "\n" . '------------------------------' . "\n";

			if (isrunning()) {
				echo 'STREAMERA is running.' . "\n\n";
			} else {
				echo 'STREAMERA is not running.' . "\n\n";
			}
		} else {
			echo "\n";
		}

		echo 'Database' . "\n" . '------------------------------' . "\n";
		StreamingUtilities::connectDatabase();

		if (!StreamingUtilities::$db->connected) {
			echo "Couldn't connect to database. Please add them to config.ini." . "\n\n";

			exit();
		}

		echo 'Connected successfully.' . "\n\n";
		$rServers = abc6134f1458b898();

		if ($rServers[SERVER_ID]['is_main']) {
			// EXAMPLE OF A DB UPDATE
			// StreamingUtilities::$db->query("SHOW COLUMNS FROM `lines` LIKE 'allowed_outputs';");
			// if (StreamingUtilities::$db->num_rows() == 0) {
			// 	StreamingUtilities::$db->query('ALTER TABLE `lines` ADD COLUMN `allowed_outputs` MEDIUMTEXT NULL DEFAULT NULL AFTER `bouquet`;');
			// }

			StreamingUtilities::$db->query("SHOW COLUMNS FROM `watch_folders` LIKE 'plex_token';");
			if (StreamingUtilities::$db->num_rows() != 0) {
				StreamingUtilities::$db->query('ALTER TABLE `watch_folders` DROP COLUMN `plex_token`;');
			}

			StreamingUtilities::$db->query("SHOW COLUMNS FROM `panel_logs` LIKE 'file';");
			if (StreamingUtilities::$db->num_rows() == 0) {
				StreamingUtilities::$db->query('ALTER TABLE `panel_logs` ADD COLUMN `file` VARCHAR(255) NULL;');
			}

			StreamingUtilities::$db->query("SHOW COLUMNS FROM `panel_logs` LIKE 'env';");
			if (StreamingUtilities::$db->num_rows() == 0) {
				StreamingUtilities::$db->query("ALTER TABLE `panel_logs` ADD COLUMN `env` VARCHAR(32) NOT NULL DEFAULT 'cli';");
			}

			StreamingUtilities::$db->query("SHOW COLUMNS FROM `settings` LIKE 'segment_type';");
			if (StreamingUtilities::$db->num_rows() != 0) {
				StreamingUtilities::$db->query('ALTER TABLE `settings` DROP COLUMN IF EXISTS `segment_type`;');
			}

			StreamingUtilities::$db->query("INSERT INTO streams_arguments (argument_cat, argument_name, argument_description, argument_wprotocol, argument_key, argument_cmd, argument_type, argument_default_value) SELECT 'fetch', 'Force Input Audio Codec', 'Force FFmpeg to interpret the input audio stream as a specific codec (e.g., aac, ac3). Useful for streams with corrupted PMT metadata.', NULL, 'force_input_acodec', '-acodec %s', 'text', NULL FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM streams_arguments WHERE argument_key = 'force_input_acodec');");

			StreamingUtilities::$db->query("INSERT INTO streams_arguments (argument_cat, argument_name, argument_description, argument_wprotocol, argument_key, argument_cmd, argument_type, argument_default_value) SELECT 'fetch', 'Skip FFProbe', 'Skip codec detection via ffprobe. Assumes h264 video and aac audio. Use for streams with corrupted PMT where ffprobe misdetects codecs.', NULL, 'skip_ffprobe', '', 'radio', '0' FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM streams_arguments WHERE argument_key = 'skip_ffprobe');");

			StreamingUtilities::$db->query("SHOW COLUMNS FROM `settings` LIKE 'update_channel';");
			if (StreamingUtilities::$db->num_rows() == 0) {
				StreamingUtilities::$db->query("ALTER TABLE `settings` ADD COLUMN `update_channel` varchar(12) COLLATE utf8_unicode_ci DEFAULT 'stable';");
			}


			shell_exec('sudo chmod 0775 ' . MAIN_HOME . 'bin/install');
		}

		shell_exec('sudo chmod 0660 ' . MAIN_HOME . 'bin/php/sockets/*');
		shell_exec('sudo chmod 0771 ' . MAIN_HOME . 'bin/daemons.sh');
		shell_exec('sudo chmod 0775 ' . MAIN_HOME . 'bin/certbot');
		shell_exec('sudo chown -R streamera:streamera ' . MAIN_HOME . 'config');
		shell_exec("sudo echo 'net.ipv4.ip_unprivileged_port_start=0' > /etc/sysctl.d/50-allports-nonroot.conf && sudo sysctl --system 2> /dev/null");
		$rSSLConfig = file_get_contents(MAIN_HOME . 'bin/nginx/conf/ssl.conf');

		if (stripos($rSSLConfig, "\n" . 'ssl_stapling on;' . "\n" . 'ssl_stapling_verify on;') !== false || stripos($rSSLConfig, "\r\n" . 'ssl_stapling on;' . "\r\n" . 'ssl_stapling_verify on;') !== false) {
			file_put_contents(MAIN_HOME . 'bin/nginx/conf/ssl.conf', str_replace("\r\n" . 'ssl_stapling on;' . "\r\n" . 'ssl_stapling_verify on;', '', str_replace("\n" . 'ssl_stapling on;' . "\n" . 'ssl_stapling_verify on;', '', $rSSLConfig)));
			$rReload = true;
		}

		foreach (array('http', 'https') as $rType) {
			$rPortConfig = file_get_contents(MAIN_HOME . 'bin/nginx/ports/' . $rType . '.conf');

			if (stripos($rPortConfig, ' reuseport') === false) {
			} else {
				file_put_contents(MAIN_HOME . 'bin/nginx/ports/' . $rType . '.conf', str_replace(' reuseport', '', $rPortConfig));
				$rReload = true;
			}
		}

		if ($rReload) {
			exec('sudo -u streamera ' . MAIN_HOME . 'bin/nginx/sbin/nginx -s reload');
			exec('sudo service streamera restart');
		}

		$rCrons = array();

		if (file_exists(CRON_PATH . 'root_signals.php')) {
			$rCrons[] = '* * * * * ' . PHP_BIN . ' ' . CRON_PATH . 'root_signals.php # STREAMERA';
		}

		if (file_exists(CRON_PATH . 'root_mysql.php')) {
			$rCrons[] = '* * * * * ' . PHP_BIN . ' ' . CRON_PATH . 'root_mysql.php # STREAMERA';
		}

		$rWrite = false;
		exec('sudo crontab -l', $rOutput);

		foreach ($rCrons as $rCron) {
			if (!in_array($rCron, $rOutput)) {
				$rOutput[] = $rCron;
				$rWrite = true;
			}
		}

		if ($rWrite) {
			$rCronFile = tempnam(TMP_PATH, 'crontab');
			file_put_contents($rCronFile, implode("\n", $rOutput) . "\n");
			exec('sudo chattr -i /var/spool/cron/crontabs/root');
			exec('sudo crontab -r');
			exec('sudo crontab ' . $rCronFile);
			exec('sudo chattr +i /var/spool/cron/crontabs/root');
			echo 'Root crontab installed.' . "\n\n";
		}

		$rFile = file('/etc/systemd/system.conf');
		$db731ba4eed35cdc = false;
		$f4e6be426cb0f059 = false;

		for ($i = 0; $i < count($rFile); $i++) {
			if (substr($rFile[$i], 0, 19) != 'DefaultLimitNOFILE=') {
			} else {
				$db731ba4eed35cdc = true;
			}

			if (substr($rFile[$i], 0, 23) != 'DefaultLimitNOFILESoft=') {
			} else {
				$f4e6be426cb0f059 = true;
			}
		}

		if ($db731ba4eed35cdc && $f4e6be426cb0f059) {
		} else {
			echo 'Configuration' . "\n" . '------------------------------' . "\n";
			echo 'Increasing file limit... You need to reboot your system!' . "\n\n";

			if ($db731ba4eed35cdc) {
			} else {
				shell_exec('sudo echo "' . "\n" . 'DefaultLimitNOFILE=1048576" >> "/etc/systemd/system.conf"');
				shell_exec('sudo echo "' . "\n" . 'DefaultLimitNOFILE=1048576" >> "/etc/systemd/user.conf"');
			}

			if ($f4e6be426cb0f059) {
			} else {
				shell_exec('sudo echo "' . "\n" . 'DefaultLimitNOFILESoft=1048576" >> "/etc/systemd/system.conf"');
				shell_exec('sudo echo "' . "\n" . 'DefaultLimitNOFILESoft=1048576" >> "/etc/systemd/user.conf"');
			}
		}

		if (!file_exists('/etc/init.d/streamera')) {
		} else {
			unlink('/etc/init.d/streamera');
			shell_exec('sudo systemctl daemon-reload');
		}

		if ($rServers[SERVER_ID]['is_main']) {
			foreach ($rServers as $rServerID => $rServerArray) {
				StreamingUtilities::$db->query('DELETE FROM `signals` WHERE `custom_data` = ?;', json_encode(array('action' => 'update_binaries')));
				StreamingUtilities::$db->query('INSERT INTO `signals`(`server_id`, `time`, `custom_data`) VALUES(?, ?, ?);', $rServerID, time(), json_encode(array('action' => 'update_binaries')));
			}
			$rConfig = file_get_contents(MAIN_HOME . 'bin/redis/redis.conf');

			if (stripos($rConfig, "\n" . 'save 60 1000') !== false) {
			} else {
				$rWrite = true;
				$rConfig .= "\n" . 'save 60 1000';
				$rConfig = str_replace('stop-writes-on-bgsave-error yes', 'stop-writes-on-bgsave-error no', $rConfig);
				echo 'Turning Redis Snapshots On!' . "\n\n";
			}

			if (stripos($rConfig, "\n" . 'save 60 1000') !== false) {
			} else {
				$rWrite = true;
				$rConfig .= "\n" . 'save 60 1000';
				echo 'Turning Redis Snapshots On' . "\n\n";
			}

			if (stripos($rConfig, 'stop-writes-on-bgsave-error yes') === false) {
			} else {
				$rWrite = true;
				$rConfig = str_replace('stop-writes-on-bgsave-error yes', 'stop-writes-on-bgsave-error no', $rConfig);
				echo 'Disabling failed write lock on Redis' . "\n\n";
			}

			if (stripos($rConfig, "\n" . 'server-threads') !== false) {
			} else {
				$rWrite = true;
				$rConfig .= "\n" . 'server-threads 4' . "\n" . 'server-thread-affinity true';
				echo 'Enabling multithreading on Redis' . "\n\n";
			}

			$rPassword = trim(explode("\n", explode("\n" . 'requirepass ', $rConfig)[1])[0]);

			if ($rPassword == '#PASSWORD#') {
				$rWrite = true;
				$rPassword = generateString(512);
				$rConfig = str_replace('#PASSWORD#', $rPassword, $rConfig);
				echo 'Generating a new Redis password' . "\n\n";
			}

			if ($rWrite) {
				file_put_contents(MAIN_HOME . 'bin/redis/redis.conf', $rConfig);
			}

			StreamingUtilities::$db->query('SELECT `redis_password` FROM `settings`;');

			if (StreamingUtilities::$db->get_row()['redis_password'] == $rPassword) {
			} else {
				echo 'Updating Redis password in database' . "\n";
				StreamingUtilities::$db->query('UPDATE `settings` SET `redis_password` = ?;', $rPassword);
			}
		}

		if (!$rFirstRun && $rServers[SERVER_ID]['is_main']) {
			StreamingUtilities::$db->query('UPDATE `servers` SET `is_main` = 0 WHERE `id` <> ?;', SERVER_ID);
			StreamingUtilities::$db->query('UPDATE `servers` SET `is_main` = 1 WHERE `id` = ?;', SERVER_ID);
			StreamingUtilities::$db->query('UPDATE `settings` SET `status_uuid` = ?;', md5(streamera_VERSION));

			if (stripos(StreamingUtilities::$rSettings['server_name'], 'xtream') !== false || stripos(StreamingUtilities::$rSettings['server_name'], 'zapx') !== false || stripos(StreamingUtilities::$rSettings['server_name'], 'streamcreed') !== false) {
				StreamingUtilities::$db->query("UPDATE `settings` SET `server_name` = 'STREAMERA';");
			}

			StreamingUtilities::$db->query('SELECT * FROM `access_codes` WHERE `enabled` = 1 AND `type` = 0;');
			$Dc5a760abaff4c21 = 0;
			echo 'Access Codes' . "\n" . '------------------------------' . "\n";

			foreach (StreamingUtilities::$db->get_rows() as $rRow) {
				$rExists = file_exists(MAIN_HOME . 'bin/nginx/conf/codes/' . $rRow['code'] . '.conf');

				if ($rExists) {
					$Dc5a760abaff4c21++;
				}

				echo $rServers[SERVER_ID]['site_url'] . $rRow['code'] . '/' . "\n";
			}

			if ($Dc5a760abaff4c21 == 0) {
				echo 'No access codes available!' . "\n" . 'Generate a rescue code using tools' . "\n\n";
			} else {
				echo "\n";
			}

			StreamingUtilities::$db->query('SELECT COUNT(`id`) AS `count` FROM `users` LEFT JOIN `users_groups` ON `users_groups`.`group_id` = `users`.`member_group_id` WHERE `status` = 1 AND `users_groups`.`is_admin` = 1;');

			if (StreamingUtilities::$db->get_row()['count'] == 0) {
				echo 'No administrator users are available on the system.' . "\n" . 'Generate a rescue user with tools' . "\n\n";
			}

			echo 'Servers' . "\n" . '------------------------------' . "\n";
			$rOffline = 0;

			foreach ($rServers as $rServerID => $rServer) {
				if ($rServerID != SERVER_ID) {
					if (!(!$rServer['server_online'] && $rServer['enabled'] && $rServer['status'] != 3 && $rServer['status'] != 5)) {
					} else {
						echo 'Server #' . $rServerID . ' - ' . $rServer['server_ip'] . ' - Down since: ' . (($rServer['last_check_ago'] ? date('Y-m-d H:i:s', $rServer['last_check_ago']) : 'Always')) . "\n";
						$rOffline++;
					}
				}
			}

			if ($rOffline == 0) {
				echo 'All servers are Online and reporting back to STREAMERA!' . "\n\n";
			} else {
				echo "\n";
			}

			echo 'Installed Version: ' . $rServers[SERVER_ID]['streamera_version'] . "\n" . '------------------------------' . "\n";
			$Df0cfbe079756478 = 0;

			foreach ($rServers as $rServerID => $rServer) {
				if ($rServerID != SERVER_ID) {
					if (!($rServer['server_type'] == 0 && $rServer['streamera_version'] && $rServer['streamera_version'] != $rServers[SERVER_ID]['streamera_version'])) {
					} else {
						echo 'Server #' . $rServerID . ' - ' . $rServer['server_ip'] . ' - Running v' . $rServer['streamera_version'] . "\n";
						$Df0cfbe079756478++;
					}
				}
			}

			if ($Df0cfbe079756478 == 0) {
				echo 'All servers are up to date!' . "\n\n";
			} else {
				echo "\n";
			}
		}

		StreamingUtilities::$db->query('UPDATE `servers` SET `streamera_version` = ? WHERE `id` = ?;', streamera_VERSION, SERVER_ID);
	} else {
		exit(0);
	}
} else {
	exit('Please run as root!' . "\n");
}

function isrunning() {
	$rNginx = 0;
	exec('ps -fp $(pgrep -u streamera 2>/dev/null) 2>/dev/null', $rOutput, $rReturnVar);

	foreach ($rOutput as $rProcess) {
		$rSplit = explode(' ', preg_replace('!\\s+!', ' ', trim($rProcess)));

		if (!($rSplit[8] == 'nginx:' && $rSplit[9] == 'master')) {
		} else {
			$rNginx++;
		}
	}

	return 0 < $rNginx;
}

function ABc6134F1458b898() {
	StreamingUtilities::$db->query('SELECT * FROM `servers`');
	$rServers = array();
	$rOnlineStatus = array(1);

	foreach (StreamingUtilities::$db->get_rows() as $rRow) {
		if (empty($rRow['domain_name'])) {
			$rURL = escapeshellcmd($rRow['server_ip']);
		} else {
			$rURL = str_replace(array('http://', '/', 'https://'), '', escapeshellcmd(explode(',', $rRow['domain_name'])[0]));
		}

		if ($rRow['enable_https'] == 1) {
			$rProtocol = 'https';
		} else {
			$rProtocol = 'http';
		}

		$rPort = ($rProtocol == 'http' ? intval($rRow['http_broadcast_port']) : intval($rRow['https_broadcast_port']));
		$rRow['site_url'] = $rProtocol . '://' . $rURL . ':' . $rPort . '/';

		if ($rRow['server_type'] == 1) {
			$rLastCheckTime = 180;
		} else {
			$rLastCheckTime = 90;
		}

		$rRow['server_online'] = $rRow['enabled'] && in_array($rRow['status'], $rOnlineStatus) && time() - $rRow['last_check_ago'] <= $rLastCheckTime || SERVER_ID == $rRow['id'];
		$rServers[intval($rRow['id'])] = $rRow;
	}

	return $rServers;
}

function generateString($rLength = 10) {
	$rCharacters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789qwertyuiopasdfghjklzxcvbnm';
	$rString = '';
	$rMax = strlen($rCharacters) - 1;
	$i = 0;

	while ($i < $rLength) {
		$rString .= $rCharacters[rand(0, $rMax)];
		$i++;
	}

	return $rString;
}
