Commit 4f6c0fa2 authored by Marco Flowers's avatar Marco Flowers

Refined id pagination, reloadable config, error messages

Id pagination was changed to use listener count. Added a link
to reload the config file while the server is running. Errors
in the api now return error status codes and messages.
parent 1e19f887
......@@ -8,12 +8,12 @@ var express = require('express'),
conf = require('konphyg')(__dirname + '/config'),
validator = require('validator'),
xmlbuilder = require('xmlbuilder');
querystring = require('querystring');
var cache = cache_manager.caching({store: "memory", max: 100, ttl: 10});
var app = express();
var config = conf('config');
var config = conf.all().config;
/* Controllers */
var streamsFindBy = require('./controllers/stream-api.js')(query, cache);
......@@ -48,6 +48,20 @@ app.get('/by_genre/:genre', genres);
app.get('/by_format/:format', formats);
app.get('/listen/:streamId/:filename',listen);
// allows updated ban lists to be reloaded
app.get('/reloadconfig/:password',function(req, res) {
// so not everyone can reload the config file
if(req.params.password == config.bansreloadpassword) {
// clear config and reload it
conf.clear();
config = conf.all().config;
res.send("Config reloaded");
} else {
res.status(401);
res.send("Wrong password");
}
});
/* JSON API */
function respond(res, err, rows, result) {
if(err) {
......@@ -59,11 +73,45 @@ function respond(res, err, rows, result) {
app.get('/streams/', function(req,res){
res.set('Content-Type', 'application/json');
var params = req.query;
streamsFindBy(params.format, params.genre, params.q, params.order, params.limit, params.next, params.prev, 1, function(err, rows){
if(err || rows[0].streams == null) {
res.send([]);
var json = 1;
streamsFindBy(params.format, params.genre, params.q, params.order, params.limit, params.starting_after, params.ending_before, json, function(err, rows){
if(err) {
if(err.responsecode) {
res.status(err.responsecode);
} else {
res.status(400);
}
res.send({"error":err.message});
} else {
res.send(rows[0].streams);
var result = rows[0];
if(result.streams == null) {
result.streams = [];
}
result.data = {};
if(params.limit) {
var starting_after = params.starting_after;
var ending_before = params.ending_before;
var limit = params.limit;
var qstring;
if(result.streams.length == limit) {
// delete the previous values
delete params.starting_after;
delete params.ending_before;
// add in the new values
var last_id = rows[0].streams[result.streams.length-1].id;
params.starting_after = last_id;
qstring = querystring.stringify(params);
result.data.next_url = req.path+'?'+qstring;
delete params.starting_after;
params.ending_before = prev_id;
qstring = querystring.stringify(params);
result.data.prev_url = req.path+'?'+qstring;
}
}
res.send(result);
}
});
});
......@@ -71,6 +119,7 @@ app.get('/streams/:streamId', function(req,res){
res.set('Content-Type', 'application/json');
streamFindById(req.params.streamId, 1, function(err,rows,result){
if(err || rows[0].array_to_json == null) {
res.status(404);
res.send({});
} else {
res.send(rows[0].array_to_json[0]);
......@@ -84,6 +133,7 @@ app.get('/genres/', function(req, res) {
respond(res, err, rows, result);
});
});
app.get('/formats/', function(req, res) {
res.set('Content-Type', 'application/json');
var formats = 'SELECT DISTINCT val FROM (SELECT unnest(codec_sub_types) as val FROM streams) s;';
......
{
"db" : "postgres://marcof@localhost/marcof",
"bans": {
"illegalListen":{
"reason": "Not enough arguments",
......@@ -7,12 +6,40 @@
},
"abuse":{
"reason": "Your server has been banned for abuse, have a nice day!",
"listenIps": ["92.246.30.112"]
"listenIps": ["92.246.30.112","222","333"]
},
"misconfigured":{
"reason": "The network range in which your server resides has been suspended due to a high number of wrongly configured servers! Please contact webmaster@xiph.org urgently!",
"listenUrls": ["hostingcenter.com"],
"listenIps": ["192.240.97.","192.240.102.","50.7.."]
},
"illegalListen2":{
"reason":"Whatever",
"listenUrls":["lazaradio.hu","ice.mwsc.tmt.de","host504.com","bristol.railroadradio.net","www.kolombiaestereo.com","radiowanderbuehne.org","live.raincitystream.com","roubaix.fr.shinsen-radio.com",
"lepesradio.hu","laradiohd.com","s-radio.whyza.net","213.240.254.147","radio.adrenalin.fm","99.93.26.131",
"delux-streams.eu","radio.status.ks.ua","campus.longmusic.com","stream1.getradio.ru",
"servercristianonetwork.com","haiku.it.su.se","floodkik.no-ip.org","anytime-fm.i1234.me",
"108.46.109.251","laveteranacentro.com","prosoftnetwork.com","radioonce.mx","carter.sgc-univ.net",
"se-lkr2.stream.sevenbroadcasting.se","tv7n.com","ohmbrew.com","latinafm.com.ve","streamcenter.pro",
"radioutopia.ondametadona.net","www.sentimientosradio.com","magictodayradio.net","radiohd.com.ve",
"mfa05.mfa.go.th","www.radiompt.com.br","stream.pick-nik.ru","stream.ufostation.ru","salomefm.com",
"str0.zenon-media.com","livehost.com.br","radio.sfa.fathi.eu.org","belfast.fm","localhost.com","ix.clpw.ru",
"truecolorsradio.com","misionera.org.ve","thevibefmstlucia.net","www.radiounivo.com","66.135.42.116",
"laperladeltuy.com.ve","i-stereo.ru","topeslaradio.net","apollo21.cdnstream.com","educativa105.org",
"www.Meghedi.com","live.ultra-byte.ro","vps.ds106rad.io","streaming.rtz.rs","streaming.radioparacin.rs",
"netradiofm.com","195.24.224.77","vaststream.com","www.radio8.de","lafieraipiales.com","stream.martini-multimedia.net",
"sabambufm.com","midght-madness.is-a-rockstar.com","relay1.oxyradio.net","stream.ipv6.frequence3.net",
"janebarcelos.com.br","royal-host.net","live.radioanjangsanabogor.com","eclectica.mx","live.rtr.fm","player.morcegaofm.com.br",
"salyut.scenesat.com","nukmradio.com","osbleianos.com.br","radio2.promodeejay.net","stream1.letsgozik.org",
"tigerstream.k2d.com","novafmms.com.br","ondaradio.com.mx","mysuarafm.com","italodiscohits.com",
"reliastream.com","walsh.g-innova.com.ar","recitation.no-ip.org","services.lwbcast.org","305stream.com",
"www.clubkydz.com","marca.com","radioyan.com","radio.ya.dn.ua","radio.radiozlatousti.rs","radioprovinciafm.com",
"www.growradio.org","radiolatina.com.ar","radiocomunidadargentina.org","radiocfa.com.br","quibario.com",
"marketing.com.sv","larumbos.com","kdx.hobby-site.org","fmmonterrico.com","cooldradio.com",
"mai.com.es","manain.org","positiviemixcafe.com","7la.fm","live.unbandsoundz.org.uk","207.210.120.98",
"140.78.254.133","estudio100.com","frisby.com.co","217.144.56.128","ceomedia.cl",
"electronic-dream.com","radio.3rd.name","radiodurisima.com"]
}
}
}
......@@ -8,32 +8,65 @@ function init(q, c, s) {
}
function byFormat(req, res) {
var params = req.params;
var genre = undefined;
var q = undefined;
var order = 0; //descending
var limit = 2;
var json = 0;
var format = req.param("format");
var next = req.param("next");
var prev = req.param("prev");
streamsFindBy(format, undefined, undefined, 2, 10, next, prev, 0, function(err, rows) {
var starting_after = req.param("starting_after");
var ending_before = req.param("ending_before");
streamsFindBy(format, genre, q, order, limit, starting_after, ending_before, json, function(err, rows) {
if (err) {
res.send(503);
} else {
var error;
if (rows.length === 0) {
error = "No streams for this genre.";
error = "No streams for this format.";
} else {
error = false;
}
var next_url, prev_url;
if (rows.length == 10) {
var last_id = rows[9].id;
var next_url, prev_url, home_url;
var result = rows;
// if the full results don't appear show a start button
if((starting_after || ending_before) && result.length < limit) {
// clear pagination params
delete params.ending_before;
delete params.starting_after;
qstring = querystring.stringify(params);
home_url = req.path+'?'+qstring;
}
// on the fist page and any page with max results show the next button
if(!(starting_after || ending_before) || (result.length == limit)) {
var last_id = rows[result.length-1].id;
delete params.ending_before;
params.starting_after = last_id;
qstring = querystring.stringify(params);
next_url = req.path+'?'+qstring;
}
// any page with max results and any page with results with starting_after
// show the previous button
if((result.length == limit) || (result.length > 0 && starting_after)) {
var prev_id = rows[0].id;
next_url = req.path+'?next='+last_id;
prev_url = req.path+'?prev='+prev_id;
delete params.starting_after;
params.ending_before = prev_id;
qstring = querystring.stringify(params);
prev_url = req.path+'?'+qstring;
}
res.render("by_xx", {
title: format,
servers: rows,
error: error,
next: next_url,
prev: prev_url
prev: prev_url,
home: home_url
});
}
});
......
......@@ -8,11 +8,17 @@ function init(q, c, s) {
}
function byGenre(req, res) {
var params = req.params;
var format = undefined;
var q = undefined;
var order = 0; //descending
var limit = 2;
var json = 0;
var genre = req.param("genre");
var next = req.param("next");
var prev = req.param("prev");
streamsFindBy(undefined, genre, undefined, 2, 10, next, prev, 0, function(err, rows) {
console.log(req);
var starting_after = req.param("starting_after");
var ending_before = req.param("ending_before");
streamsFindBy(format, genre, q, order, limit, starting_after, ending_before, json, function(err, rows) {
if (err) {
res.send(503);
} else {
......@@ -22,19 +28,46 @@ function byGenre(req, res) {
} else {
error = false;
}
var next_url, prev_url;
if (rows.length == 10) {
var last_id = rows[9].id;
var next_url, prev_url, home_url;
var result = rows;
// if the full results don't appear show a start button
if((starting_after || ending_before) && result.length < limit) {
// clear pagination params
delete params.ending_before;
delete params.starting_after;
qstring = querystring.stringify(params);
home_url = req.path+'?'+qstring;
}
// on the fist page and any page with max results show the next button
if(!(starting_after || ending_before) || (result.length == limit)) {
var last_id = rows[result.length-1].id;
delete params.ending_before;
params.starting_after = last_id;
qstring = querystring.stringify(params);
next_url = req.path+'?'+qstring;
}
// any page with max results and any page with results with starting_after
// show the previous button
if((result.length == limit) || (result.length > 0 && starting_after)) {
var prev_id = rows[0].id;
next_url = req.path+'?next='+last_id;
prev_url = req.path+'?prev='+prev_id;
delete params.starting_after;
params.ending_before = prev_id;
qstring = querystring.stringify(params);
prev_url = req.path+'?'+qstring;
}
res.render("by_xx", {
title: genre,
servers: rows,
error: error,
next: next_url,
prev: prev_url
prev: prev_url,
home: home_url
});
}
});
......
......@@ -8,7 +8,15 @@ function init(q, c, s) {
}
function index(req, res) {
streamsFindBy(undefined, undefined, undefined, 0, 20, undefined, undefined, 0, function(err, rows) {
var format = undefined;
var genre = undefined;
var q = undefined;
var order = -1; //random
var limit = 10;
var starting_after = undefined;
var ending_before = undefined;
var json = 0;
streamsFindBy(format, genre, q, order, limit, starting_after, ending_before, json, function(err, rows) {
if (err) {
res.send(503);
} else {
......
......@@ -9,7 +9,6 @@ function init(q, c, x, s) {
}
function getListen(req, res) {
console.log(req.get('User-Agent'));
var userAgent = req.get('User-Agent');
filename = req.params.filename;
streamFindById(req.params.streamId, 0,function(err, rows) {
......
This diff is collapsed.
......@@ -20,15 +20,16 @@ function findById(id, json, resultCallback)
{
var queryStringJsonBeg = 'SELECT array_to_json(array_agg(row_to_json(t))) FROM (';
var queryStringJsonEnd = ' ) t';
var queryStringBeg = 'SELECT s.id, s.stream_name, s.stream_type, s.description \
,s.songname, s.url, s.avg_listening_time, s.codec_sub_types, s.bitrate, s.hits, \
s.cm, s.samplerate, s.channels, s.quality, s.genres, array_agg(sm.listenurl) AS listenurls, \
COUNT(sm.listeners) AS listeners, COUNT(sm.max_listeners) AS max_listeners \
FROM streams s \
INNER JOIN server_mounts AS sm ON s.id = sm.stream_id \
WHERE $1 = s.id \
GROUP BY s.id ';
var queryStringBeg = 'SELECT s.id, s.stream_name, s.stream_type, s.description ' +
',s.songname, s.url, s.avg_listening_time, s.codec_sub_types, s.bitrate, s.hits, ' +
's.cm, s.samplerate, s.channels, s.quality, s.genres, array_agg(sm.listenurl) AS listenurls, ' +
'SUM(sm.listeners) AS listeners, SUM(sm.max_listeners) AS max_listeners ' +
'FROM streams s ' +
'INNER JOIN server_mounts AS sm ON s.id = sm.stream_id ' +
'WHERE $1 = s.id ' +
'GROUP BY s.id ';
var queryString;
if(json) {
queryString = queryStringJsonBeg+queryStringBeg;
} else {
......
......@@ -13,12 +13,15 @@
{% for server in servers %}
{% include "./stream.html" %}
{% endfor %}
{% if prev %}
<a href="{{prev}}">Prev</a>
{% endif %}
{% if next %}
<a href="{{next}}">Next</a>
{% endif %}
{% endif %}
{% if home %}
<a href="{{home}}">Start</a>
{% endif %}
{% if prev %}
<a href="{{prev}}">Prev</a>
{% endif %}
{% if next %}
<a href="{{next}}">Next</a>
{% endif %}
</div>
{% endblock %}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment