Skip to content

Instantly share code, notes, and snippets.

@tomsmeding
Created April 6, 2015 12:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomsmeding/eaaa91cd927c7bcae1d7 to your computer and use it in GitHub Desktop.
Save tomsmeding/eaaa91cd927c7bcae1d7 to your computer and use it in GitHub Desktop.
MagisterCLI by tomsmeding
#!/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