PHP - Icecast info being updated on page - php

I'm using a script from this site. This script works fine for me and it does what its need to do but I have one problem. When a track finishes on my Icecast server it doesn't get updates on the site. So if my song is 'Stole the show' than it says 'Stole the show' the page but when the song finished and e.g. 'Thinking out loud' starts the page still says 'Stole the show' on a refresh it will update. But how to make it so the page auto updates itself so the users doesn't have to refresh manually?
PHP
<?php
// include the class file
include( 'icecast.php' );
// instantiate class
$stream = new IceCast();
// set server and mount
$server = 'http://radio.finioxfm.com:8000';
$file = '/status.xsl';
// set the url
$stream->setUrl($server,$file);
// get status info
$radio = $stream->getStatus();
// assign array to variables
extract($radio);
// echo the status
echo $status.'<br/>';
// display more stats if ON AIR
if ($status=='ON AIR') :
echo $listeners.' listeners<br/>';
echo $title.'<br/>';
echo $genre.'<br/>';
for ($i=0; $i < 1; $i++) {
echo $now_playing['artist'].'<br/>';
echo $now_playing['track'].'<br/>';
}
endif;
?>
icecast.php script
<?php
class IceCast {
var $server = "http://radio.finioxfm.com:8000";
var $stats_file = "/status.xsl";
var $radio_info=array();
function __construct() {
// build array to store our Icecast stats
$this->radio_info['server'] = $this->server;
$this->radio_info['title'] = '';
$this->radio_info['description'] = '';
$this->radio_info['content_type'] = '';
$this->radio_info['mount_start'] = '';
$this->radio_info['bit_rate'] = '';
$this->radio_info['listeners'] = '';
$this->radio_info['most_listeners'] = '';
$this->radio_info['genre'] = '';
$this->radio_info['url'] = '';
$this->radio_info['now_playing'] = array();
$this->radio_info['now_playing']['artist'] = 'Unknown';
$this->radio_info['now_playing']['track'] = 'Unknown';
$this->radio_info['status'] = 'OFF AIR';
}
function setUrl($url,$file) {
$this->server=$url;
$this->stats_file=$file;
$this->radio_info['server'] = $this->server;
}
private function fetch() {
// create a new curl resource
$ch = curl_init();
// set the url
curl_setopt($ch,CURLOPT_URL,$this->server.$this->stats_file);
// return as a string
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
// $output = the status.xsl file
$output = curl_exec($ch);
// close curl resource to free up system resources
curl_close($ch);
return $output;
}
function getStatus() {
$output=$this->fetch();
// loop through $output and sort arrays
$temp_array = array();
$search_for = "<td\s[^>]*class=\"streamdata\">(.*)<\/td>";
$search_td = array('<td class="streamdata">','</td>');
if(preg_match_all("/$search_for/siU",$output,$matches)) {
foreach($matches[0] as $match) {
$to_push = str_replace($search_td,'',$match);
$to_push = trim($to_push);
array_push($temp_array,$to_push);
}
}
if(count($temp_array)) {
//sort our temp array into our ral array
$this->radio_info['title'] = $temp_array[0];
$this->radio_info['description'] = $temp_array[1];
$this->radio_info['content_type'] = $temp_array[2];
$this->radio_info['mount_start'] = $temp_array[3];
$this->radio_info['bit_rate'] = $temp_array[4];
$this->radio_info['listeners'] = $temp_array[5];
$this->radio_info['most_listeners'] = $temp_array[6];
$this->radio_info['genre'] = $temp_array[7];
$this->radio_info['url'] = $temp_array[8];
if(isset($temp_array[9])) {
$x = explode(" - ",$temp_array[9]);
$this->radio_info['now_playing']['artist'] = $x[0];
$this->radio_info['now_playing']['track'] = $x[1];
}
$this->radio_info['status'] = 'ON AIR';
}
return $this->radio_info;
}
}
?>

First of all, I have to point out that you shouldn't use this script. It works by parsing the Icecast Status page, which we highly discourage, as it may change. For example in Icecast 2.4 we re-made the complete web interface, so chances are that this script breaks.
You should actually parse the XML Icecast provides at http://icecast.tld:8000/admin/stats. It contains everything you need. If you can't access Icecast's Admin page for some reason, you can use the JSON at http://icecast.tld:8000/status-json.xsl, which is there since Icecast 2.4 exactly for the purpose you describe.
To get the site display new metadata information without refreshing, you need to use an AJAX call which either loads directly the status-json.xsl and extracts the metadata and updates it on the page, or if you use the admin XML you need to write a PHP script which returns json, that you can fetch via AJAX and update accordingly.

A lot of people in the past have spoken about setting up node.js (if you have a server doing your streaming).
Personally I have gone with a jquery solution; which just compares the last fetched data with the live data every 10 seconds. That way it loads in almost 'real time'.
You can find my solution here broken down here http://www.radiodj.ro/community/index.php?topic=7471.0

Related

How to download and save arrays of files to my local PC in php

I am currently using a simple html dom to scrape a website, part of the contents I scrape are : images, links, and text. Now what I need to accomplish is to save the scraped data to my local PC or database. Is there a way I can accomplish this using php?
To force download those contents at once to my PC or database.
Will upload my codes if you feel it's necessary.
Thank you in advance...
Edited: Here is my code...
include("../dom/simple_html_dom.php");
if (isset($_POST['submit']))
{
if ($_POST['word1'] != ""){
//posts of the search query
$word1 = $_POST['word1'];
$items = array('url'=>'https://www.example.com/mobile-phones/?q='.str_replace(' ','+',$word1)."/",'img'=>'.image-wrapper img','brand'=>'h2.title span.brand','name'=>'h2.title span.name','price'=>'span.price-box','link'=>'section.products a.link');
$site = new simple_html_dom();
$currentImg = '';
$currentItemBrand = '';
$currentItemName = '';
$currentLink = '';
$currentPrice = '';
$counter = 0;
$number = -1;
$site->load_file($items['url']);
$currentImg = array();
$currentItemBrand = $site->find($items["brand"]);
$currentItemName = $site->find($items["name"]);
$currentLink = $site->find($items["link"]);
$currentPrice = $site->find($items["price"]);
foreach($site->find($items["img"]) as $element) {
$counter2++;
//initializing array objects
if($counter2 % 2 == 0 && $counter2 < 42)
{
$number++;
$currentImg = $element[$number]->src;
$currentItemName[$number]->plaintext;
$currentItemBrand2[$number]->plaintext;
$currentLink[$number]->href;
$currentPrice[$number]->plaintext;
}
}
// My Database Code
$insertSQL = "INSERT INTO items (img, name, link, price, brand) VALUES ('$currentImg', '$currentItemName', '$currentItemLink','$currentPrice','$currentItemBrand')";
mysqli_select_db($elecom_connect,$database_elecom_connect);
$Result1 = mysqli_query($elecom_connect,$insertSQL) or die(mysqli_error($elecom_connect));
exit();
}
}
}
?>
The issue I have with this code is that it only save a reference of the images, to the database...What I want is to download all the arrays of files and then store them in my database....I am a bit confused on how to do that....Will appreciate your suggestions or codes block.

PHP+Apache2+Ubuntu Server: How to get all threads to work in parallel?

I usually work with web hosting companies but I decided to start learning working with servers to expand my knowledge.
I'll better give a real example to explain my question the best:
I have a web application that gathers data from a slow API that returns JSON data of products.
I have a function running every 1AM running a lot of queries on "id"s in my database.
Crontab:
0 1 * * * cd /var/www/html/tools; php index.php aso Cli_kas kas_alert
So this creates a process for the app (please correct me here if I'm wrong) and each process creates threads, and just to be more accurate, they are multi-threads since they do more than one thing: like pulling data from the DB to get the right variables and string them to the API queries, getting the data from the API, organizing it, searching the relevant data, and then inserting new data to the database.
The main PHP functions:
// MAIN: Cron Job Function
public function kas_alert() {
// 0. Deletes all the saved data from the `data` table 1 month+ ago.
// $this->kas_model->clean_old_rows();
// 1. Get 'prod' table
$data['table'] = $this->kas_model->prod_table();
// 2. Go through each row -
foreach ( $data['table'] as $row ) {
// 2.2. Gets all vars from the first query.
$last_row_query = $this->kas_model->get_last_row_of_tag($row->tag_id);
$last_row = $last_row_query[0];
$l_aaa_id = $last_row->prod_aaa_id;
$l_and_id = $last_row->prod_bbb_id;
$l_r_aaa = $last_row->dat_data1_aaa;
$l_r_and = $last_row->dat_data1_bbb;
$l_t_aaa = $last_row->dat_data2_aaa;
$l_t_and = $last_row->dat_data2_bbb;
$tagword = $last_row->tag_word;
$tag_id = $last_row->tag_id;
$country = $last_row->kay_country;
$email = $last_row->u_email;
$prod_name = $last_row->prod_name;
// For the Weekly report:
$prod_id = $last_row->prod_id;
$today = date('Y-m-d');
// 2.3. Run the tagword query again for today on each one of the tags and insert to DB.
if ( ($l_aaa_id != 0) || ( !empty($l_aaa_id) ) ) {
$aaa_data_today = $this->get_data1_aaa_by_id_and_kw($l_aaa_id, $tagword, $country);
} else{
$aaa_data_today['data1'] = 0;
$aaa_data_today['data2'] = 0;
$aaa_data_today['data3'] = 0;
}
if ( ($l_and_id != 0) || ( !empty($l_and_id) ) ) {
$bbb_data_today = $this->get_data1_bbb_by_id_and_kw($l_and_id, $tagword, $country);
} else {
$bbb_data_today['data1'] = 0;
$bbb_data_today['data2'] = 0;
$bbb_data_today['data3'] = 0;
}
// 2.4. Insert the new variables to the "data" table.
if ($this->kas_model->insert_new_tag_to_db( $tag_id, $aaa_data_today['data1'], $bbb_data_today['data1'], $aaa_data_today['data2'], $bbb_data_today['data2'], $aaa_data_today['data3'], $bbb_data_today['data3']) ){
}
// Kas Alert Outputs ($SEND is echoed in it's original function)
echo "<h1>prod Name: $prod_id</h1>";
echo "<h2>tag id: $tag_id</h2>";
var_dump($aaa_data_today);
echo "aaa old: ";
echo $l_r_aaa;
echo "<br> aaa new: ";
echo $aaa_data_today['data1'];
var_dump($bbb_data_today);
echo "<br> bbb old: ";
echo $l_r_and;
echo "<br> bbb new: ";
echo $bbb_data_today['data1'];
// 2.5. Check if there is a need to send something
$send = $this->check_if_send($l_aaa_id, $l_and_id, $l_r_aaa, $aaa_data_today['data1'], $l_r_and, $bbb_data_today['data1']);
// 2.6. If there is a trigger, send the email!
if ($send) {
$this->send_mail($l_aaa_id, $l_and_id, $aaa_data_today['data1'], $bbb_data_today['data1'], $l_r_aaa, $l_r_and, $tagword, $email, $prod_name);
}
}
}
For #Raptor, this is the function that get's the API data:
// aaa tag Query
// Gets aaa prod dataing by ID.
public function get_data_aaa_by_id_and_tg($id, $tag, $query_country){
$tag_for_url = rawurlencode($tag);
$found = FALSE;
$i = 0;
$data = array();
// Create a stream for Json. That's how the code knows what to expect to get.
$context_opts = array(
'http' => array(
'method' => "GET",
'header' => "Accepts: application/json\r\n"
));
$context = stream_context_create($context_opts);
while ($found == FALSE) {
// aaa Query
$json_query_aaa = "https://api.example.com:443/aaa/ajax/research_tag?app_id=$id&term=$tag_for_url&page_index=$i&country=$query_country&auth_token=666";
// Get the Json
$json_query_aaa = file_get_contents($json_query_aaa, false, $context);
// Turn Json to a PHP array
$json_query_aaa = json_decode($json_query_aaa, true);
// Get the data2
$data2 = $json_query_aaa['tag']['data2'];
if (is_null($data2)){ $data2 = 0; }
// Get data3
$data3 = $json_query_aaa['tag']['phone_prod']['data3'];
if (is_null($data3)){ $data3 = 0; }
// Finally, the main prod array.
$json_query_aaa = $json_query_aaa['tag']['phone_prod']['app_list'];
if ( count($json_query_aaa) > 2 ) {
for ( $j=0; $j<count($json_query_aaa); $j++ ) {
if ( $json_query_aaa[$j]['id'] == $id ) {
$found = TRUE;
$data = $json_query_aaa[$j]['data'] + 1;
break;
}
if ($found == TRUE){
break;
}
}
$i++;
} else {
$data = 0;
break;
}
}
$data['data1'] = $data;
$data['data2'] = $data2;
$data['data3'] = $data3;
return $data;
}
All threads are stacked one after an other, and when one thread is done, only then - the second thread can proceed, ect'.
And in technical view on this, all threads wait in the RAM until the one before them is done working "inside" the CPU. (correct me if I'm wrong again :] )
This doesn't even "tickle" the servers RAM or CPU when looking at it in the process manager (I use "htop"). RAM is at 400M/4.25G and CPU at ONLY 0.7%-1.3%.
Making me feel this isn't the best I can get from my current server, and getting slow results from my web app.
How do I get things done in a way that all threads work in parallel, but not to a point that my app crashes due to lacks of CPU or RAM?

Forecast.io service unavailable

I am using forecast.io API to deliver weather data to my website. Sometimes the forecast.io API is down, which causes every single page on my website which uses the forecast.io API to return "Service Unavailable, unable to get file content errors"
This is what I'm using to gather the weather data from the API
<?php
include("assets/php/forecast.php");
$api_key = '123123123';
$latitude = $data->getLatitude();
$longitude = $data->getLongitude();
$forecast = new ForecastIO($api_key);
/*
* GET CURRENT CONDITIONS
*/
$condition = $forecast->getCurrentConditions($latitude, $longitude);
$temp = $condition->getTemperature();
$temp = $temp + 2;
$summ = $condition->getSummary();
$icon = $condition->getIcon();
$icon2 = $condition->getIcon();
$icon = str_replace('-', '_', $icon);
$icon2 = str_replace('-', ' ', $icon2);
$icon = strtoupper($icon);
$icon2 = ucfirst($icon2);
?>
I would like to include some sort of error handler where if the forecast.io API is unavailable, then this code doesn't get called.
This is the site where I had the problem
https://seek.estate/
https://seek.estate/buy/422-melbournes-most-liveable-home-sea-views-elevator-designer-masterpiece
This is what I changed
$forecast = new ForecastIO($api_key);
$request_url = 'https://api.forecast.io/forecast/';
$content = file_get_contents($request_url);
if (!empty($content)) {
return condition = $forecast->getCurrentConditions($latitude, $longitude);
} else {
return false;
}

Exporting Invoices from Magento

I have been trying to export all of our invoices in a specific format for importing into Sage accounting. I have been unable to export via Dataflow as I need to export the customer ID (which strangely is unavailable) and also a couple of static fields to denote tax codes etc…
This has left me with the option of using the API to export the data and write it to a CSV. I have taken an example script I found (sorry can’t remember where in order to credit it...) and made some amendments and have come up with the following:
<?php
$website = 'www.example.com';
$api_login = 'user';
$api_key ='password';
function magento_soap_array($website,$api_login,$api_key,$list_type,$extra_info){
$proxy = new SoapClient('http://'.$website.'/api/soap/?wsdl');
$sessionId = $proxy->login($api_login, $api_key);
$results = $proxy->call($sessionId,$list_type,1);
if($list_type == 'order_invoice.list'){
/*** INVOICES CSV EXPORT START ***/
$filename = "invoices.csv";
$data = "Type,Account Reference,Nominal A/C Ref,Date,Invoice No,Net Amount,Tax Code,Tax Amount\n";
foreach($results as $invoice){
foreach($invoice as $entry => $value){
if ($entry == "order_id"){
$orders = $proxy->call($sessionId,'sales_order.list',$value);
}
}
$type = "SI";
$nominal = "4600";
$format = 'Y-m-d H:i:s';
$date = DateTime::createFromFormat($format, $invoice['created_at']);
$invoicedOn = $date->format('d/m/Y');
$invoiceNo = $invoice['increment_id'];
$subtotal = $invoice['base_subtotal'];
$shipping = $invoice['base_shipping_amount'];
$net = $subtotal+$shipping;
$taxCode = "T1";
$taxAmount = $invoice['tax_amount'];
$orderNumber = $invoice['order_id'];
foreach($orders as $order){
if ($order['order_id'] == $orderNumber){
$accRef = $order['customer_id'];
}
}
$data .= "$type,$accRef,$nominal,$invoicedOn,$invoiceNo,$net,$taxCode,$taxAmount\n";
}
file_put_contents($_SERVER['DOCUMENT_ROOT']."/var/export/" . $filename, "$header\n$data");
/*** INVOICES CSV EXPORT END ***/
}else{
echo "nothing to see here";
}/*** GENERIC PAGES END ***/
}/*** END function magento_soap_array ***/
if($_GET['p']=="1")
{
magento_soap_array($website,$api_login,$api_key,'customer.list','Customer List');
}
else if($_GET['p']=="2")
{
magento_soap_array($website,$api_login,$api_key,'order_creditmemo.list','Credit Note List');
}
else if($_GET['p']=="3")
{
magento_soap_array($website,$api_login,$api_key,'sales_order.list','Orders List');
}
else if($_GET['p']=="4")
{
magento_soap_array($website,$api_login,$api_key,'order_invoice.list','Invoice List');
}
?>
This seems to be working fine, however it is VERY slow and I can’t help but think there must be a better, more efficient way of doing it…
Has anybody got any ideas?
Thanks
Marc
i think on put break; would be okey. because only one key with order_id, no need to looping after found order_id key.
if ($entry == "order_id"){
$orders = $proxy->call($sessionId,'sales_order.list',$value);
break;
}
and you can gather all call(s) and call it with multicall as example:
$client = new SoapClient('http://magentohost/soap/api/?wsdl');
// If somestuff requires api authentification,
// then get a session token
$session = $client->login('apiUser', 'apiKey');
$result = $client->call($session, 'somestuff.method');
$result = $client->call($session, 'somestuff.method', 'arg1');
$result = $client->call($session, 'somestuff.method', array('arg1', 'arg2', 'arg3'));
$result = $client->multiCall($session, array(
array('somestuff.method'),
array('somestuff.method', 'arg1'),
array('somestuff.method', array('arg1', 'arg2'))
));
// If you don't need the session anymore
$client->endSession($session);
source

Accessing YouTube yt:rating (like/dislike) system in PHP

I'm using PHP to access YouTube video attributes e.g. title, url, thumbnail, duration etc.
Not that gd:rating (5 star ratings) has been replaced by yt:rating (like/dislike system), I'm trying to modify my PHP.
gd:rating (old)
$gd = $entry->children('http://schemas.google.com/g/2005');
if ($gd->rating) {
$attrs = $gd->rating->attributes();
$rating = $attrs['average'];
} else {
$rating = 0;
}
yt:rating (new)
$yt = $entry->children('http://gdata.youtube.com/schemas/2007');
if ($yt->rating && $yt->rating[0]->attributes()) {
$attrs = $yt->rating[0]->attributes();
$videoobj[$loopCounter]['dislikes'] = strval($attrs['numDislikes']);
$videoobj[$loopCounter]['likes'] = strval($attrs['numLikes']);
} else {
$videoobj[$loopCounter]['dislikes'] = 0;
$videoobj[$loopCounter]['likes'] = 0;
}
Using the yt:rating code didn't work. Even if I do a print_r($yt->rating);, there is nothing in the array.
Where am I going wrong?
Correction. You can.
The URL you access needs this appended to the end:
$url = 'http://gdata.youtube.com/feeds/api/videos/' . $vid . '?v=2';
That made all the difference - so the last bit of my code:
// get <yt:rating> node for like/dislikes
$yt = $entry->children('http://gdata.youtube.com/schemas/2007');
$attrs = $yt->rating->attributes();
$obj->dislikes = $attrs['numDislikes'];
$obj->likes = $attrs['numLikes'];
echo $obj->dislikes;
echo ' ';
echo $obj->likes;

Categories