Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

Commit 6ec3fcbf authored by deuce's avatar deuce

Add contests command that lists upcoming contests.

parent c878f37c
......@@ -13,6 +13,9 @@ var update_interval=2;
var last_wflength=-1;
var last_solar_update=0;
var solar_x;
var contests={};
var last_contest_update=0;
function main(srv,target)
{
if((time() - last_update) < update_interval) return;
......@@ -67,6 +70,103 @@ Bot_Commands["Z"].command = function (target, onick, ouh, srv, lbl, cmd) {
return true;
}
function update_contests()
{
// Only update once per day.
if((time() - last_contest_update) < 60*60*24) return;
contests={};
contest_order=[];
function parse_contest(cont) {
var m;
var c;
function parse_time(t) {
var se = t.split(/ to /);
var ret={};
if(se.length==1) {
se=t.match(/([0-9]{4})([^-]*?)-([0-9]{4})([^-]*?), ([A-Za-z]{3}) ([0-9]+)/)
if(se == null) {
log("Error parsing range "+t+"!");
return;
}
ret.startTime=se[1];
ret.zone=se[2].replace(/^\s*(.*?)\s*$/, "$1");
ret.endTime=se[3];
ret.startMonth=se[5];
ret.endMonth=se[5];
ret.startDay=se[6];
ret.endDay=se[6];
}
else {
var s=se[0].match(/([0-9]{4})([^-]*?), ([A-Za-z]{3}) ([0-9]+)/);
if(s == null) {
log("Error parsing start "+se[0]+"!");
return;
}
ret.startTime=s[1];
ret.zone=s[2].replace(/^\s*(.*?)\s*$/, "$1");
ret.startMonth=s[3];
ret.startDay=s[4];
s=se[1].match(/([0-9]{4})([^-]*?), ([A-Za-z]{3}) ([0-9]+)/);
if(s == null) {
log("Error parsing end "+se[1]+"!");
return;
}
ret.endTime=s[1];
ret.endMonth=s[3];
ret.endDay=s[4];
}
return ret;
}
m=cont.match(/<tr><td colspan="3" class="bgray"><strong><a[^>]*>(.[^<]*)<\/a>([^<]*)<\/strong>/)
if(m != null) {
c=m[1];
var times=m[2].split(/ and /);
contest_order.push(c);
contests[c]={};
contests[c].timeStr=m[2];
contests[c].times=[];
for(timeidx in times) {
contests[c].times.push(parse_time(times[timeidx]));
}
var re=/<tr><td [^>]*>&nbsp;<\/td><td class="blightblue twhite">(.*?):<\/td><td>(.*?)<\/td><\/tr>/g;
var prop;
while((prop=re.exec(cont))!=null) {
if(prop[1]=='Bands') {
prop[2] = prop[2].replace(/ Only$/i,'').replace(/([0-9])m$/,'$1').replace(/VHF\/UHF/,'VHF, UHF');
contests[c][prop[1]]=prop[2].split(/,\s*/);
}
else if(prop[1]=='Mode') {
contests[c][prop[1]]=prop[2].split(/,\s*/);
}
else if(prop[1]=='Find rules at') {
contests[c][prop[1]]=prop[2].replace(/^.*href="(.*?)">.*$/,"$1");
}
else {
contests[c][prop[1]]=prop[2].split(/<br>/);
}
}
}
}
// Fetch current contest cal (next 8 days)
var req=new HTTPRequest();
var currcal=req.Get('http://www.hornucopia.com/contestcal/weeklycont.php');
var matches=currcal.match(/<tr><td colspan="3" class="bgray"><strong>[\x00-\xff]*?<tr><td>&nbsp;<\/td><td class="blightblue">&nbsp;<\/td><td>&nbsp;<\/td><\/tr>/g);
for(match in matches) {
parse_contest(matches[match]);
}
var currcal=req.Get('http://www.hornucopia.com/contestcal/weeklycont.php?mode=custom&week=next');
var matches=currcal.match(/<tr><td colspan="3" class="bgray"><strong>[\x00-\xff]*?<tr><td>&nbsp;<\/td><td class="blightblue">&nbsp;<\/td><td>&nbsp;<\/td><\/tr>/g);
for(match in matches) {
parse_contest(matches[match]);
}
}
function update_solar()
{
// MUST NOT request more than every hour or you will get banned!
......@@ -200,6 +300,108 @@ Bot_Commands["CALLSIGN"].command = function (target,onick,ouh,srv,lvl,cmd) {
return true;
}
Bot_Commands["CONTESTS"] = new Bot_Command(0,false,false);
Bot_Commands["CONTESTS"].command = function (target, onick, ouh, srv, lvl, cmd) {
// Remove empty cmd args
for(i=1; i<cmd.length; i++) {
if(cmd[i].search(/^\s*$/)==0) {
cmd.splice(i,1);
i--;
}
}
update_contests();
function match_contests(rules)
{
var ret=[];
var c;
var rules;
var matches;
for(contest in contest_order) {
c=contests[contest_order[contest]];
matches=0;
for(rule in rules) {
var r=rules[rule].toLowerCase();
if(r == 'hf' || r.search(/^[0-9]+$/)!= -1 || r == 'vhf'
|| r == 'uhf') {
for(band in c.Bands) {
var b=c.Bands[band].toLowerCase();
var bn=parseFloat(b);
if(b==r) {
matches++;
break;
}
else if(b=='all' || b=='any') {
matches++;
break;
}
else if(r=='hf' && bn >= 10 && bn <= 160) {
matches++;
break;
}
else if(r=='vhf' && ((bn <=6 && bn >= 1.25) || (bn >= 219 && bn <= 225))) {
matches++;
break;
}
else if(r=='UHF' && ((bn > 1.25 && bn < 10) || (bn >= 420))) {
matches++;
break;
}
}
}
else if(r == 'ssb' || r == 'cw' || r == 'phone' || r == 'sstv'
|| r == 'rtty' || r == 'psk' || r == 'digital'
|| r == 'data' || r == 'feld hell' || r == 'am' || r=='fm') {
for(mode in c.Mode) {
var m=c.Mode[mode].toLowerCase();
if(m==r) {
matches++;
break;
}
else if(r=='phone' && (m=='ssb' || m=='am' || m=='fm')) {
matches++;
break;
}
else if((r=='data' || r=='digital') && (m=='cw' || m=='rtty' || m=='psk' || m == 'feld hell')) {
matches++;
break;
}
}
}
else {
matches++;
}
}
if(matches==rules.length) {
ret.push(contest_order[contest]);
}
}
return ret;
}
var cl=match_contests(cmd.slice(1));
var displayed=0;
for(c in cl) {
var t=contests[cl[c]];
srv.o(target, cl[c]+': '+t.timeStr+' '+t['Find rules at']);
displayed++;
if(displayed > 8) {
srv.o(target, "--- Aboring after 8 entries");
break;
}
}
if(displayed) {
srv.o(target,'Provided by WA7BNM Contest Calendar');
}
else {
srv.o(target,'No contests found');
}
}
//var dumb={o:function(x,y) {log(y);}};
//Bot_Commands["GEO"].command(undefined, undefined, undefined,dumb,undefined,['GEO']);
//Bot_Commands["HF"].command(undefined, undefined, undefined,dumb,undefined,['GEO']);
......
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