Created
April 6, 2015 12:02
-
-
Save tomsmeding/eaaa91cd927c7bcae1d7 to your computer and use it in GitHub Desktop.
MagisterCLI by tomsmeding
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
var mjs=require("magister.js"), | |
persist=require("node-persist"), | |
readline=require("readline"), | |
util=require("util"); | |
require("datejs"); //modifies prototypes | |
function logRuler(maxwid,s){ | |
var i,j,len; | |
var isspace=function(c){return c!="\x1B"&&/\s/.test(c);}; | |
if(s.length<maxwid){ | |
console.log(s); | |
return; | |
} | |
for(i=0,len=0;i<s.length&&len<maxwid;i++){ | |
if(s[i]=="\x1B"){ | |
//ANSI escape sequences don't take up space, do they | |
while("ABCDEFGHJKSTfminsulh".indexOf(s[i])==-1)i++; | |
continue; | |
} | |
len++; | |
} | |
for(/*i set by loop above*/;i>0;i--){ | |
if(!isspace(s[i]))continue; | |
for(j=i+1;j<s.length;j++)if(!isspace(s[j]))break; | |
console.log(s.slice(0,i)); | |
logRuler(maxwid,s.slice(j)); | |
return; | |
} | |
//i==0 now, we couldn't find a splitting index :( | |
console.log(s.slice(0,maxwid)); | |
logRuler(maxwid,s.slice(maxwid)); | |
} | |
function clog(s){return logRuler(150,s);} | |
// http://stackoverflow.com/a/24037546/1608468 - edited | |
function hiddenRLquestion(rl, query, callback) { | |
var stdin = process.openStdin(); | |
function stdinDataHandler(char){ | |
char = char + ""; | |
switch (char) { | |
case "\n": | |
case "\r": | |
case "\u0004": | |
stdin.pause(); | |
break; | |
default: | |
process.stdout.write("\033[2K\033[200D" + query + Array(rl.line.length+1).join("*")); | |
break; | |
} | |
} | |
process.stdin.on("data", stdinDataHandler); | |
rl.question(query, function(value) { | |
rl.history = rl.history.slice(1); | |
process.stdin.removeListener("data", stdinDataHandler); | |
callback(value); | |
}); | |
} | |
function getCredentials(mschool){ | |
function useUserPassToLogin(u,p){ | |
var mag=new mjs.Magister(mschool,u,p,true); //ingelogdblijven - for keks | |
mag.ready(function(err){ | |
if(err){ | |
try{ | |
var parsed=JSON.parse(err); | |
clog("Login failed: "+(parsed.Message?parsed.Message:util.inspect(parsed))); | |
}catch(e){ | |
clog("Login failed: "+util.inspect(err)); | |
} | |
getCredentials(mschool); | |
} else { | |
persist.setItemSync("credentials",{username:u,password:p}); | |
startCLI(this); | |
} | |
}); | |
} | |
var credentials_persist=persist.getItem("credentials"); | |
if(credentials_persist){ | |
clog("Using account "+credentials_persist.username); | |
useUserPassToLogin(credentials_persist.username,credentials_persist.password); | |
return; | |
} | |
rlinter.resume(); | |
rlinter.question("username? ",function(username){ | |
hiddenRLquestion(rlinter,"password? ",function(password){ | |
rlinter.pause(); | |
useUserPassToLogin(username,password); | |
}); | |
}); | |
} | |
/*********************\ | |
|** **| | |
|** MAIN FUNCTION **| | |
|** **| | |
\*********************/ | |
function startCLI(mag){ | |
rlinter.close(); //we need our own completer now | |
var cmds=[ | |
[["help","?"],function(){ | |
//nsole.log("eighty-char ruler at the end of this string: 67890123456789012345678901234567890"); | |
clog("MagisterCLI by Tom Smeding -- using Magister.js by Lieuwe Rooijakkers"); | |
clog("- help, ? --> what you're looking at"); | |
clog("- appointments, calendar --> ~ \x1B[4mday\x1B[0m: shows appointments for the given day"); | |
clog("- grades --> ~ \x1B[4msubject\x1B[0m: shows grades for the given subject or subject abbreviation"); | |
clog("- exit, quit --> exit") | |
clog("Tab-completion is supported."); | |
rl.prompt(); | |
}], | |
[["appointments","calendar"],function(args){ | |
var arg=args.join(" "); | |
var date=Date.parse(arg); | |
if(date==null){ | |
clog("Could not parse '"+arg+"' to a date"); | |
return; | |
} | |
clog("Appointments for "+date.format("l d/m/Y")+":"); | |
var apts=mag.appointments(date,false,function(err,res){ | |
res.forEach(function(app){ | |
if(app.scrapped())return; | |
var l=""; | |
if(app.fullDay())l+="-"; | |
else if(app.beginBySchoolHour()){ | |
l+="["+app.beginBySchoolHour(); | |
if(app.endBySchoolHour()&&app.endBySchoolHour()!=app.beginBySchoolHour()) | |
l+="-"+app.endBySchoolHour(); | |
l+="]"; | |
} else l+="["+app.begin().format("H:m")+"-"+app.end().format("H:m")+"]"; | |
l+=" "+app.description(); | |
l+=" ("+app.location()+")"; | |
if(app.infoType())l+=" ["+app.infoType()+"]"; | |
clog(l); | |
}); | |
rl.prompt(); | |
}); | |
}], | |
[["grades"],function(args){ | |
var arg=args.join(" "); | |
mag.courses(function(err,courses){ | |
courses.forEach(function(course,ci){ | |
course.grades(false,true,false,function(err,grades){ | |
grades.forEach(function(grade,gi){ | |
clog(grade.class().abbreviation()+" - "+grade.description()+" - "+grade.grade()); | |
if(ci==courses.length-1&&gi==grades.length-1)rl.prompt(); | |
}); | |
}); | |
}); | |
}); | |
}], | |
[["exit","quit"],function(){process.exit();}] | |
]; | |
var profinfo=mag.profileInfo(); | |
var completer=function completer(ln){ | |
var poss=[],i; | |
for(i=0;i<cmds.length;i++)cmds[i][0].forEach(function(c){if(c.indexOf(ln)==0)poss.push(c);}); | |
if(poss.length)return [poss,ln]; | |
for(i=0;i<cmds.length;i++)cmds[i][0].forEach(function(c){poss.push(c);}); | |
return [poss,ln]; | |
}; | |
var rl=readline.createInterface({input:process.stdin,output:process.stdout,completer:completer,terminal:true}); | |
clog("Welcome, "+profinfo.fullName()+"!"); | |
rl.prompt(); | |
rl.on("line",function(line){ | |
var args=line.split(/\s+/g),cmd,func,i,j; | |
cmd=args[0]; args=args.slice(1); | |
func=null; | |
for(i=0;i<cmds.length&&func==null;i++){ | |
for(j=0;j<cmds[i][0].length;j++){ | |
if(cmds[i][0][j]==cmd){ | |
func=cmds[i][1]; | |
break; | |
} | |
} | |
} | |
if(func==null){ | |
clog("Unknown command "+cmd); | |
rl.prompt(); | |
return; | |
} | |
func(args); | |
//rl.prompt(); //called by the (async) functions | |
}); | |
} | |
persist.initSync({dir:"MagisterCLI"}); | |
var rlinter=readline.createInterface({input:process.stdin,output:process.stdout,terminal:true}); | |
rlinter.setPrompt("> "); | |
var mschool_persisted=persist.getItem("school"); | |
if(mschool_persisted){ | |
clog("Using school "+mschool_persisted.name); | |
getCredentials(mschool_persisted); | |
} else { | |
clog("What school are you on?"); | |
rlinter.prompt(); | |
var lineHandlerGetSchool=function lineHandlerGetSchool(err,res){ | |
if(res.length==0){ | |
clog("No schools found with a name like that."); | |
rlinter.prompt(); | |
} else if(res.length==1){ | |
clog("Taking school "+res[0].name); | |
persist.setItemSync("school",res[0]); | |
rlinter.removeListener(lineHandlerGetSchool); | |
getCredentials(res[0]); | |
} else { | |
res.forEach(function(o){ | |
clog("- "+o.name); | |
}); | |
rlinter.prompt(); | |
} | |
} | |
rlinter.on("line",function(line){ | |
rlinter.pause(); | |
mjs.MagisterSchool.getSchools(line,lineHandlerGetSchool); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment