1

Тема: Графическая география слушателей (icecast)

Сначала хотел описать настройку жидкого мыла, по шагам, чтоб он умел танцевать джигу, выводить ведущих и варить кофе, но в соответствующей теме все давным давно описано, так что пройдем по извращениям.

Итак дорогой дружок, сейчас я научу тебя делать модною динамическую картинку для своего сайта, с отображением географии ваших радиослушателей. Вот такого рода:
http://wasteland.su/radiotalk/geo.png
Внимание: текущая картинка статичная, что бы не афишировать радиостанцию.

Никакой практической ценности эта вещь не несет, только увеличивает длину вашего детородного органа и возможность гармонично вставить картинку в дизайн сайта.

Итак, у нас есть боевой сервер icecast2 который радостно вещает на ваши сотни слушателей (ну или на пару друзей), если зайти в админку его, в раздел List Mountpoints, в нем посмотреть любой ваш маунт, то там можно увидеть список слушателей поименно ip, клиент, время подключения.
Важно: у вас должен быть доступ к админке icecast
Но как вы поняли эту информацию уже можно обрабатывать как угодно (например бы генерить карту гугла с метками). Но мы же хитрые телом, поэтому будем сами генерить карту, для этого нам понадобиться старая, добрая php-шная библиотека GD, если вы не забыли мы с ней уже близко знакомились. Ну и одна из самых важных частей, это база Maxmind GeoIP

Ну обо всем по порядку.

Во первых нам понадобится карта, на которой мы будем рисовать всякие пошлости. Но любая карта не подойдет, нам понадобиться карта в определенных пропорциях.
Например эта подойдет:
http://wasteland.su/radiotalk/map.png

А эта уже нет:
http://wasteland.su/radiotalk/wrong.png

Разницу думаю увидите сами. Самый грамотный способ, это нарисовать (или кого заставить) нарисовать карту в нужном вам графическом оформлении в соответствующих пропорциях (смотри пример), либо найти в интернете, но первый способ лучше wink

база GeoIP, есть расширение для php, но он у меня вероломно отказался работать, так что воспользуемся "чистым" набором скриптов от maxmind'a, которые и будем подключать к нашему скрипту.
Качаем чистое, располагаем в удобном месте, и подключаем в начале скрипта

include ("geoipcity.inc");

Так же кроме собственно скриптов, которые работают с данными GeoIP нам собственно понадобиться бинарная база GeoIPCity, но так как она платная, а те что есть в свободном доступе малость уже устарели, то берем на офф сайте GeoLiteCity для наших нужд ее хватит, но а для большего шика можно использовать пару баз: полную, но старую (найденную в свободных источниках (линки не дам, ищите)), и легкую, но крайнюю версию.

Для особо продвинутых пользователей рекомендую закинуть в крон скрип, который будет рахз в месяц (числах в 5-х) скачивать крайнюю версию с офф сайта.
Типа такого:

#!/bin/sh
cd /tmp
fetch http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
gunzip GeoLiteCity.dat.gz
mv -f GeoLiteCity.dat /usr/local/share/GeoIP
chmod 644 /usr/local/share/GeoIP/GeoLiteCity.dat

команды для скачивания и разархивирования рекомендую использовать привычные вам.

Перед тем как переходить к финальной стадии написания кода поделюсь с вами скриптом, который будет нам устраивать общение с icecast, да, я ленивая скотина, и не стал писать данный кусок кода а нашел на офф форуме icecast.
Автор данного кода W. Herrmann, о чем моно и прочитать в этом коде.
Держи его

Итак мы подготовились, карта, база GeoIP, php модули GeoIP, скрипт icecast.class разархивированы и расположены в удобном вам месте, вы вспомнили/узнали пароль от админки то можно приступать к самому интересному и фкусному, делаем скрипт генерации карты.

Дальше следует поток кода с комментариями:

<?php 
error_reporting(1);
//сообщаем, что на выходе будет нет текст, а графика
header ("Content-type: image/png");
//подключаем внешнии скрипты
include("icecast.class.php"); 
include ("geoipcity.inc");
//создаем клас к которому будем обращатся
$icecast = new icecast();
//имя шрифта, надеюсь вы не забыли про него? 
$font="ft.ttf";
//список маунтов, которые чекаються
$mount[]="radio";
$mount[]="music";
$mount[]="autorj";
//размер карты по ширине, т.к. мы работаем с координатами, то пропорции карты должны быть 360х180
//остальные параметры, зависащии от размеров, расчитываються
$glob_x=900;
$glob_y=$glob_x/2;
$koeficent=$glob_x/360;
//начинаем опрашивать маунта, ничто не мешает крутить по циклу и список серверов
//думаю параметры (хост, логин и пароль админки вы уже увидели куда вбивать)
for ($nom_mount=0;$nom_mount<count($mount);$nom_mount++) {
    $icecast->host = "127.0.0.1";
    $icecast->port = 8000;
    $icecast->mount = $mount[$nom_mount];
    $icecast->user = "admin";
    $icecast->passwd = "hackme";
    //запрашиваем нужные нам параметры
    if ($icecast->openstats()) {
        if ($icecast->GetStreamStatus()) {
            $listeners = $icecast->GetListeners();
            //если массив списка слушателей получен, то сортируем его (сортировать не обязательно)
            if (is_array($listeners)) { 
                sort($listeners);
                //обходим и записываем в массив IP адреса
                for ($i=0;$i<sizeof($listeners);$i++) { 
                                    //массив $ip =)
                                    $ip[] = $listeners[$i]["ip"];
                }     
            }  
        }  
    } 
}
//подключаемся к БД GeoIP     
$gil = geoip_open("/usr/local/share/GeoIP/GeoLiteCity.dat", GEOIP_STANDARD); 
$gif = geoip_open("/usr/local/share/GeoIP/GeoIPCity.dat", GEOIP_STANDARD); 
//создаем первый "нулевой" элемент массивов координат
$array_coo[]="0,0";
$array_col[]=0;
//счетчик всего слушателей
$all=0;
//максимальное количество слушателей на координату
$maxal=0;
//опять сортруем и начинаем переберать результат
sort($ip);
for ($z=0;$z<count($ip);$z++) {
    //сначало запрос к лайту, получаем координаты
    $geoip = GeoIP_record_by_addr($gil,$ip[$z]);
    //операция с коэфицентом карты (по отношению к 360) делаем чтоб в масиве у нас хранились округленные значения
    $ipx=round(($geoip->latitude)*$koeficent)/$koeficent;
    $ipy=round(($geoip->longitude)*$koeficent)/$koeficent;
    //на всякий пожарный ^_^
    $ipx=$ipx*1;
    $ipy=$ipy*1;
    //если лайт база нам вернула не очень интересные данные, нулевые координаты, или же неизвестный кород, то координаты "фейковый" (с точности до страны)
    if ((($ipx==0) and ($ipy==0)) or (strlen($geoip->city)==0)) {
        //тогда делаем запрос к полной базе (не забыли ее найти?)
        $geoip = GeoIP_record_by_addr($gif,$ip[$z]);
        //к ней работаем так же как и с лайт
        $ipx=round(($geoip->latitude)*$koeficent)/$koeficent;
        $ipy=round(($geoip->longitude)*$koeficent)/$koeficent;
        $ipx=$ipx*1;
        $ipy=$ipy*1;
    }
    //причем в массиве храним строку с долготой и широтой сразу, через запятую
    $coord=$ipx.",".$ipy;
    //ищем полученную координату в массиве координат, зачем нам создавать новый элемент, если с такими координатами уже есть    
    $pnom=array_search($coord,$array_coo);
    if ($pnom==FALSE) {
        //не нашли, тогда создаем
        $array_coo[]=$coord;
        $array_col[]=1;
        if ($maxal<1) {$maxal=1;}
    } else {
        //нашли, тоже отлично, увеличиваем кол-во слушателей в этой точке
        $array_col[$pnom]++;
        //заодно проверяем это максимум тут или как
        if ($maxal<$array_col[$pnom]) {$maxal=$array_col[$pnom];}
    }
    $all++;
}
//закрываем базы GeoIP дабы они нам более не требуються
geoip_close($gil);
geoip_close($gif);
//создаем png для работы из нашей карты
$img=imagecreatefrompng("map.png");
//выбираем цвет чернил, которыми будем рисовать
$ink = imagecolorallocate($img, 0, 0, 0);
    
//и перебираем массив координат
for ($i=0;$i<count($array_coo);$i++) {
    //если в координате 0 слушателей, то не обрабатываем
    if ($array_col[$i]!=0) {
        //узнаем размер кружка
        //у меня тут по хитрому, все кружки пропорциональны относительно самого большого
        //кому не нравиться данная идея, используйте свой принцып
        //$kolb это диаметр кружка
        //для более гармоничного круга диаметр делайте кратным двум
        $kolb=round($array_col[$i]*10/$maxal)*2+1;
        //теперь нам больше не нужна запятая в координатах, разбираем на два элемента (широта и долгота)        
        $arc=split(",",$array_coo[$i]);
        //соотвественно полученные координаты умножаем на коофицент, для более гармоничного рамположения на карте    
        $arc[0]=$arc[0]*$koeficent;
        $arc[1]=$arc[1]*$koeficent;
        //т.к. 0 на графике в левов верхнем, то творим еще и такие подсчеты
        $smesh_x=$glob_x/2;
        $smesh_y=$glob_y/2;
        //рисуем таки кружок    IMG_ARC_PIE - значит, что будет заливка
        imagefilledarc($img,$smesh_x+$arc[1],$smesh_y-$arc[0],$kolb,$kolb,0,360,$ink,IMG_ARC_PIE);
    }
}

//рисуем всякие надписи
imagettftext($img,8,0,20,20,$ink,$font,"Special 4 radiotalk");
imagettftext($img,8,0,20,36,$ink,$font,"GeoIP");
imagettftext($img,8,0,20,52,$ink,$font,"listeners: ".$all);
//у меня сервер по гринвичу. А у вас?
$dat=date("n/j/24y g:ia",time()+14400);
$mr=imagettfbbox (8,0,  $font, $dat);
imagettftext($img,8,0,$glob_x-20-$mr[2],22,$ink,$font,$dat);
//черестрочный формат, не помешает
imageInterlace($img, 1);
//отдаем пользователю
imagepng($img);
//уничтожаем следы жизнидеятельности
imagedestroy($img);
?>

Результат работы кода:
http://wasteland.su/radiotalk/geo.php

Ну и традиционно: данный код лишь направление в котором следует изучать этот вопрос. Это базовый код. Много чего можно и нужно добавить. Так же каждый желающий может написать свой код, более оптимизирован, более красивый.

-------------------------------
R244390603111<- пиво лить сюда

2

Re: Графическая география слушателей (icecast)

Еще насчет GeoIP
Точность Lite версии следующая

-------------------------------
R244390603111<- пиво лить сюда

Re: Графическая география слушателей (icecast)

Klef пишет:

Еще насчет GeoIP
Точность Lite версии следующая

что-то я попыался сделать, хрен что получилось... вот http://gtiradio.ru/php/geo/

Re: Графическая география слушателей (icecast)

как лечить напасть?

5

Re: Графическая география слушателей (icecast)

у вас проблемы с генерированием изображения, точнее там вообще ничего не сгенерировалось, смотрите лог ошибок

Re: Графическая география слушателей (icecast)

tarasian666 пишет:

у вас проблемы с генерированием изображения, точнее там вообще ничего не сгенерировалось, смотрите лог ошибок

Судя по логу, ошибка в 46 строке.

И вот что это:

//подключаемся к БД GeoIP     
$gil = geoip_open("/usr/local/share/GeoIP/GeoLiteCity.dat", GEOIP_STANDARD);
$gif = geoip_open("/usr/local/share/GeoIP/GeoIPCity.dat", GEOIP_STANDARD);


Наверное у меня на хостинге другой путь к файлам

7

Re: Графическая география слушателей (icecast)

а конкретно что пишет ошибка?

Re: Графическая география слушателей (icecast)

tarasian666 пишет:

а конкретно что пишет ошибка?


[08-Oct-2012 12:14:19] PHP Fatal error:  Call to undefined function  geoip_open() in /php/geo/index.php on line 46

9

Re: Графическая география слушателей (icecast)

в php не включено или не установлено расширение geoip

Re: Графическая география слушателей (icecast)

tarasian666 пишет:

в php не включено или не установлено расширение geoip

да вот в том-то и дело, что сказали что поставили =/

11

Re: Графическая география слушателей (icecast)

значит или не активировали или не перезапустили сервер после этого, так всегда )

Re: Графическая география слушателей (icecast)

Вопрос есть: а эти GeoLiteCity.dat, GeoIPCity.dat устанавливаются вместе с расширением GeoIP???

13

Re: Графическая география слушателей (icecast)

вместе с geoip, но это не проблема, можно их самому скачать куда угодно

Re: Графическая география слушателей (icecast)

tarasian666 пишет:

вместе с geoip, но это не проблема, можно их самому скачать куда угодно

А можете подсказать где скачать? ссылка на одну есть, а вот на вторую что-то нету sad

15

Re: Графическая география слушателей (icecast)

Для особо продвинутых пользователей рекомендую закинуть в крон скрип, который будет рахз в месяц (числах в 5-х) скачивать крайнюю версию с офф сайта.

и ниже код и ссылка

Re: Графическая география слушателей (icecast)

tarasian666 пишет:

Для особо продвинутых пользователей рекомендую закинуть в крон скрип, который будет рахз в месяц (числах в 5-х) скачивать крайнюю версию с офф сайта.

и ниже код и ссылка

Блин что-то нихрена не выходит вообще sad

17

Re: Графическая география слушателей (icecast)

тогда учить мат часть )

Re: Графическая география слушателей (icecast)

tarasian666 пишет:

тогда учить мат часть )

Я тебя умоляю...

Странно почему не пашет... =/ ладно тогда как хостер появится попробую решить smile

19

Re: Графическая география слушателей (icecast)

если ошибка прежняя - мучить хостера, если что то типа syntax error или not fount тогда искать причину

Re: Графическая география слушателей (icecast)

tarasian666 пишет:

если ошибка прежняя - мучить хостера, если что то типа syntax error или not fount тогда искать причину


Это понятно. спс за помощь...

Re: Графическая география слушателей (icecast)

народ пардонте!

Вот это что такое?

//список маунтов, которые чекаються
$mount[]="radio";
$mount[]="music";
$mount[]="autorj";

что еще за маунты?

еще вопрос: Если ссылка не /usr/local/share/GeoIP/GeoLiteCity.dat, а /usr/share/GeoLiteCity.dat, то во всех файлах где эти ссылки есть менять?

Re: Графическая география слушателей (icecast)

Надоело ковыряться... не понятное описание. Строго по пунктам написать можно было, что делать... а то хер пойми че куда ставить...

23

Re: Графическая география слушателей (icecast)

что еще за маунты?

сразу видно ваш уровнь познаний в этом деле и автор мануала вам в этом не виноват

Re: Графическая география слушателей (icecast)

tarasian666 пишет:

что еще за маунты?

сразу видно ваш уровнь познаний в этом деле и автор мануала вам в этом не виноват

причем тут про мои познания, может быть не такие как у автора, но мне проще когда например:

1)
2)
3)

т.е. поэтапно...

25

Re: Графическая география слушателей (icecast)

а допустимы прямые пути в таких местах?

include("icecast.class.php"); 

Например

include("/var/www/******/data/www/*****/*****/icecast.class.php");
Fu** Pop, just Dance!