summaryrefslogblamecommitdiffstats
path: root/assets/js/lopolisc.js
blob: dfd9ff62a38b27571389e233a47f167c2d25c7f5 (plain) (tree)
1
2
3
4
5
6
7
8
9





                                                               

                                                                               
                                                  





                                                                                




                       
                                                                                  










                                                                                    
                                        





                                                                                                                  





                                                                                                   

















                                                                                                                     
                                              





















                                                                                                            
                                                                     

                                                                       





                                                                                                                      







                                                                                         








































                                                                                                                                                           
                                                 










                                                                    

                                                             

                                                                                                      
                          
                                                                                                                                                               









                                                                                                




                                                         
                                          
                                                                                     


                                                                                     
                                                                                                                 




                                                                                                                                                     

                                                                                                      
                                                                                                                 


                                                                                                            
                                                                                                               









                                                                                                                    
                                                                                                                 
                                         





                                                                                                            





                                                   




























                                                                                                     
                                      
















                                                                                                 
                                                         
                                                              
                                                                                                  


                                                                                                
                                                                                             

                                                                                                 
                                                                                             


                                                                                                


                                                                                                                                                         






                                              
                                                                                     



                                                         


                                           

                                                                                     

                                                                                    
                                                                                         




                                                                                                                                                     
                                                             
                                                                    

                                                                                                                 
                                                                          


                                                                                      

                                                           
                                                                   










                                                                                                                    

                                                                                                                  






                                                                                                                    
                                                                                                               









                                                                                                                    
                                                                                                                 
                                                 





                                                                                                                           

                                               





                                                                                                  




                                

















                                                                                                  
                                                         
                                                              

                                                                                              



                                                                                     

                                                                                                   






                                                                                                 








                                                                                                                                                                               





                                              








                                                                     
 


                                                                                
function getStringBetween(string, start, end) {
	return string.split(start).pop().split(end)[0];
}

const LOPOLIS_URL = "https://lopolis.gimb.tk/";
const LOPOLISC_ERR_NET = "LOPOLSIC NETWORK ERROR (ajax error)";
const	LOPOLISC_ERR_NET_POSTBACK_GET = "LOPOLISC NETWORK ERROR (ajax error) "+
	"in postback GET";
const LOPOLISC_ERR_LOGIN = "LOPOLISC LOGIN ERROR";
const LOPOLISC_ERR_NET_POSTBACK_POST = "LOPOLISC NETWORK ERROR (ajax error) "+
	"in postback POST";
const LOPOLISC_ERR_NET_POSTBACK_POST_IN_POSTBACK = "LOPOLISC NETWORK ERROR $$$";
const LOPOLISC_ERR_NOTAPPLIED = "LOPOLISC DATA NOT APPLIED ERROR";
const LOPOLISC_SIGNATURE = "lopolisc.js neuradni API - anton<at>sijanec.eu";
const LOPOLISC_ERR_OUT_OF_RETRIES = "LOPOLISC ERROR NI VEČ POSKUSOV!";
class lopolisc {

	constructor() {
	}

	parseAndPost(inputHTML, userParams, formId = null, useDiffAction = null) {
		return new Promise((resolve, reject) => {
			let parser = new DOMParser();
			let parsed = parser.parseFromString(inputHTML, "text/html");

			var form;
			if (formId == null) {
				form = parsed.getElementsByTagName("form")[0];
			} else {
				form = parsed.getElementById(formId);
			}

			var params = {};
			var otherParams = $(form).serializeArray();
			for (const input of otherParams) {
				if (!(input.name in params)) {
					params[input.name] = input.value; // so we don't overwrite existing values
				}
			}

			for (const [key, value] of Object.entries(userParams)) { // neki me je
				params[key] = value; // zajebaval, pa sem tkole naredu - še enkrat
			} // prepišemo vse, kar je v params, z uporabniškimi parametri
			// POPRAVEK PO 2 min debugganja: ne, nič ni bilo narobe, pozabil sem
			// passat dataToSend v postback(), passal sem {} :facepalm: </notetoself>
			var action;
			if (useDiffAction == null || useDiffAction == false) {
				action = new URL($(form).attr("action"), LOPOLIS_URL); // absolute == relative + base
			} else {
				action = useDiffAction;
			}

			params["programska-oprema"] = LOPOLISC_SIGNATURE;
			$.ajax({
				xhrFields: {
					withCredentials: true
				},
				crossDomain: true,
				url: action,
				cache: false,
				type: "POST",
				data: params,
				dataType: "text",
				maxRetries: 3,
				success: (postData, textStatus, xhr) => {
					resolve({data: postData, textStatus: textStatus, code: xhr.status});
				},
				error: () => {
					reject(new Error(LOPOLISC_ERR_NET_POSTBACK_POST));
				}
			});
		});
	}

	postback(getUrl, params = {}, formId = null, useDiffAction = null) {
		return new Promise( (resolve, reject) => {
			$.ajax({
				xhrFields: {
					withCredentials: true
				},
				crossDomain: true,
				url: getUrl,
				cache: false,
				type: "GET",
				dataType: "html",
				success: (data) => {
					if (useDiffAction === true) {
						useDiffAction = getUrl;
					}
						this.parseAndPost(data, params, formId, useDiffAction)
						.then((value) => {
							resolve(value);
						}).catch((e)=>{
							reject(new Error(LOPOLISC_ERR_NET_POSTBACK_POST_IN_POSTBACK));
						});
				},
				error: () => {
					reject(new Error(LOPOLISC_ERR_NET_POSTBACK_GET));
				}
			});
		});
	}

	getUserData() {
		return new Promise((resolve, reject)=>{
			$.ajax({
				xhrFields: {
					withCredentials: true
				},
				crossDomain: true,
				url: LOPOLIS_URL+"?MeniID=2",
				cache: false,
				type: "GET",
				dataType: "html",
				success: (data) => {
					if (data.includes("Dostop ni dovoljen")) {
						// console.log(data);
						resolve(false);
						return;
					}
					let parser = new DOMParser();
					let p = parser.parseFromString(data, "text/html");
					let uporabnik = {
						u: p.getElementsByClassName("obrazecPovdarjen")[0].innerText.trim(),
						n: p.getElementsByClassName("obrazecPovdarjen")[1].innerText.trim(),
						e: p.getElementById("Email").value
					}
					resolve(uporabnik);
				},
				error: () => {
					reject(new Error(LOPOLISC_ERR_NET));
				}
			});
		});
	}

	logout() { // you can get pretty race conditiony if you use this wrong! // nah
		return new Promise((resolve, reject)=>{
			this.postback(LOPOLIS_URL + "Uporab/Prijava", {}, null, false).then((response) => { // če je true, bo URL, če je false, bo action
				resolve(true); // don't bother checking cookies...
			});
		});
	}

	login(usernameToLogin, passwordToLogin) {
		return new Promise(async function(resolve, reject) {
			let l = new lopolisc();
			var uporabnik = await l.getUserData();
			if (uporabnik != false) {
				if (uporabnik.u = usernameToLogin) {
					resolve(true);
					return;
				} else {
					await this.logout();
				}
			}
			var dataToSend = {
				"Uporabnik": usernameToLogin,
				"Geslo": passwordToLogin,
				"OsveziURL": "https://pornhub.com/\"; lopolis=\"boljsi od easistenta",
			};
			l.postback(LOPOLIS_URL + "Uporab/Prijava", dataToSend, null, true).then((response) => { // če je true, bo URL, če je false, bo action
				let parser = new DOMParser();
				let parsed = parser.parseFromString(response.data, "text/html");
				if (parsed.getElementById("divPrijavaOsvezi") != null) {
					resolve(true);
				}
				reject(new Error(LOPOLISC_ERR_LOGIN));
			});
		});
	}

	fetchCheckouts(date_object = null) {
		if (date_object == null) {
			date_object = new Date();
		}
		return new Promise((resolve, reject) => {
			var dataToSend = {
				"MesecModel.Mesec": String(date_object.getMonth()+1),
				"MesecModel.Leto": String(date_object.getFullYear()),
				"Ukaz": ""
			};
			this.postback(LOPOLIS_URL+"Prehrana/Odjava", dataToSend, null, true).then((response) => {
				let parser = new DOMParser();
				let parsed = parser.parseFromString(response.data, "text/html");
				let checkouts = {};
				for (const element of parsed.getElementsByTagName("tbody")[0].
															getElementsByTagName("tr")) {
					let date_idx = element.getElementsByTagName("input")[2].value;
					checkouts[date_idx] = {
						checked/*out*/: element.getElementsByTagName("input")[0].checked,
						readonly: element.getElementsByTagName("input")[0].disabled,
						// spodaj spremenljivke, ki so potrebne za submit (ne-API)
						index: Number(getStringBetween( // string, start, end
							element.getElementsByTagName("input")[0].name, "[", "]"
						)),
						"OsebaModel.ddlOseba":
							parsed.getElementsByTagName("option")[0].value,
						"OsebaModel.OsebaID":
							parsed.getElementById("OsebaModel_OsebaID").value,
						"OsebaModel.OsebaTipID":
							parsed.getElementById("OsebaModel_OsebaTipID").value,
						"OsebaModel.UstanovaID":
							parsed.getElementById("OsebaModel_UstanovaID").value,
						"MesecModel.Mesec": parsed.getElementById("MesecModel_Mesec").value,
						"MesecModel.Leto": parsed.getElementById("MesecModel_Leto").value
					}
					checkouts[date_idx][element.getElementsByTagName("input")[2].name] =
						String(element.getElementsByTagName("input")[2].value);
					checkouts[date_idx][element.getElementsByTagName("input")[3].name] =
						String(element.getElementsByTagName("input")[3].value);
					checkouts[date_idx][element.getElementsByTagName("input")[4].name] =
						String(element.getElementsByTagName("input")[4].value);
				}
				resolve(checkouts);
			});
		});
	}

	fetchAllMeals(koliko = 3) { // "vsi" pomeni nas. n mes. (vklj. s tem me.)
		return new Promise (async function(resolve, reject) {
			let date = new Date();
			let podatki = {};
			while (koliko-- > 0) {
				let l = new lopolisc(); // this zajebava, sorry; seja je itak na
				let resp = await l.fetchMeals(date); // browserju, ne na objectu.
				podatki = {...podatki, ...resp};
				date.setMonth(date.getMonth()+1); // ja, popravi se letnica!
			}
			resolve(podatki);
		});
	}


	fetchAllCheckouts(koliko = 3) { // "vsi" pomeni nas. n mes. (vklj. s tem me.)
		return new Promise (async function(resolve, reject) {
			let date = new Date();
			let podatki = {};
			while (koliko-- > 0) {
				let l = new lopolisc(); // this zajebava, sorry; seja je itak na
				let resp = await l.fetchCheckouts(date); // browserju, ne na objectu.
				podatki = {...podatki, ...resp};
				date.setMonth(date.getMonth()+1); // ja, popravi se letnica!
			}
			resolve(podatki);
		});
	}

	setCheckouts(odjava_objects) {
		let odjava_objects_sorted = {};
		for (const [odjava_da, odjava_ob] of Object.entries(odjava_objects)) {
			let yearmonth_combo = odjava_da.substring(0,7);
			if (odjava_objects_sorted[yearmonth_combo] == undefined) {
				odjava_objects_sorted[yearmonth_combo] = {};
			}
			odjava_objects_sorted[yearmonth_combo][odjava_da] = odjava_ob;
		}
		if (Object.entries(odjava_objects_sorted).length < 1) {
			return false;
		} else if (Object.entries(odjava_objects_sorted).length > 1) {
			var response;
			for (const [ym_combo, odj_ob] of Object.entries(odjava_objects_sorted)) {
				response = this.setCheckouts(odj_ob);
			}
			return response; // napake so itak exceptioni, promisov ne potrebujemo!
		} // else: samo en mesec podatkov imamo, let's go!
		return new Promise((resolve, reject) => {
			var dataToSend = { "Ukaz": "Shrani" };
			for (const [odjava_da, odjava_object] of Object.entries(odjava_objects)) {
				for (const [index, property] of Object.entries(odjava_object)) {
					dataToSend[index] = property;
				}
				dataToSend["OdjavaItems["+odjava_object.index+"].CheckOut"] =
					String(odjava_object.checked);
			} // now we have some excess values, who cares (index, readonly, checked)
			this.postback(LOPOLIS_URL+"Prehrana/Odjava", dataToSend, null, true).
				then( (response) => {
				let parser = new DOMParser();
				let parsed = parser.parseFromString(response.data, "text/html");
				for (const [od_date, odjava_object] of Object.entries(odjava_objects)) {
					if (!(parsed.getElementById("OdjavaItems_"+odjava_object.index+"__CheckOut").checked == odjava_object.checked)) {
						reject(LOPOLISC_ERR_NOTAPPLIED);
					}
				}
				resolve(true);
			});
		});
	}

	fetchMeals(date_object = null, retried = 3) { // retried je interni parameter
		if (date_object == null) {
			date_object = new Date();
		}
		return new Promise((resolve, reject) => {
			var meals = {};
			var dataToSend = {
				"Ukaz": "",
				"MesecModel.Mesec": String(date_object.getMonth()+1),
				"API-METODA": "fetchMeals",
				"MesecModel.Leto": String(date_object.getFullYear())
			}
			this.postback(LOPOLIS_URL+"?MeniID=78",dataToSend,"form1",false).
				then((response) => {
				let parser = new DOMParser();
				let parsed = parser.parseFromString(response.data, "text/html");
				for (const element of parsed.getElementsByTagName("tbody")[0].
															getElementsByTagName("tr")) {
					let menuoptions = [];
					let is_any_selected = false;
					for (const opt of element.getElementsByTagName("select")[0].options) {
						if (opt.value.length > 0 || 1==1) { // tudi prazno opcijo pustimo
							menuoptions.push({
								value: opt.value,
								text: opt.innerText,
								selected: opt.selected
							});
						}
						if (opt.selected) {
							is_any_selected = true;
						}
					}
					if (!is_any_selected) {
						menuoptions[0].selected = true; // !!! KAJ GRE LAHKO NAROBE:
						// * če je readonly je itak en izbran
						// * če je en izbran je itak en izbran
						// * če noben ni izbran in je readonly se izbere prazna - okej
						// * če noben ni izbran in je readonly se izbere prazna - okej
						// prazna (index 0) defaulta na meni 1 (index 1) ampak ne bom tvegal
					}
					let date_idx = element.getElementsByTagName("input")[0].value;
					meals[date_idx] = {	// trying to keep same api as rstular's lopolisapi
						meal: element.getElementsByTagName("td")[1].innerText.trim(),
						"menu-type": element.getElementsByTagName("td")[2].innerText.trim(),
						location: element.getElementsByTagName("td")[3].innerText.trim(),
						readonly: element.getElementsByTagName("select")[0].disabled,
						menu_options: menuoptions,
						// properties below are "private" and non-API (undocumented even)
						index: Number(getStringBetween( // string, start, end
							element.getElementsByTagName("input")[0].name, "[", "]"
						)),
						"OsebaModel.ddlOseba":
							parsed.getElementsByTagName("option")[0].value,
						"OsebaModel.OsebaID":
							parsed.getElementById("OsebaModel_OsebaID").value,
						"OsebaModel.OsebaTipID":
							parsed.getElementById("OsebaModel_OsebaTipID").value,
						"OsebaModel.UstanovaID":
							parsed.getElementById("OsebaModel_UstanovaID").value,
						"MesecModel.Mesec": parsed.getElementById("MesecModel_Mesec").value,
						"MesecModel.Leto": parsed.getElementById("MesecModel_Leto").value
						}
						meals[date_idx][element.getElementsByTagName("input")[0].name] =
							String(element.getElementsByTagName("input")[0].value); // date
						meals[date_idx][element.getElementsByTagName("input")[1].name] =
							String(element.getElementsByTagName("input")[1].value); // prijOID?
						meals[date_idx][element.getElementsByTagName("input")[2].name] =
							String(element.getElementsByTagName("input")[2].value); // readonly
				}
				resolve(meals);
			}).catch((err)=>{
				if (retried <= 0) {
					reject(new Error(LOPOLISC_ERR_OUT_OF_RETRIES));
				} else {
					resolve(this.fetchMeals(date_object, retried-1)); // retry
				}
			});
		});
	}

	setMeals(meal_objects) {
		let meal_objects_sorted = {};
		for (const [meal_da, meal_ob] of Object.entries(meal_objects)) {
			let yearmonth_combo = meal_da.substring(0,7);
			if (meal_objects_sorted[yearmonth_combo] == undefined) {
				meal_objects_sorted[yearmonth_combo] = {};
			}
			meal_objects_sorted[yearmonth_combo][meal_da] = meal_ob;
		}
		if (Object.entries(meal_objects_sorted).length < 1) { // ni podatkov sploh
			return false;
		} else if (Object.entries(meal_objects_sorted).length > 1) {
			var response;
			for (const [ym_combo, meal_ob] of Object.entries(meal_objects_sorted)) {
				response = this.setMeals(meal_ob);
			}
			return response; // itak ne uporabljamo response ampak try{}catch{} except
		} // else: samo en mesec podatkov imamo, let's go!
	
		return new Promise((resolve, reject) => {
			var dataToSend = { "Ukaz": "Shrani" };
			for (const [meal_date, meal_object] of Object.entries(meal_objects)) {
				for (const [index, property] of Object.entries(meal_object)) {
					dataToSend[index] = String(property);
				}
				for (const menu_option of meal_object.menu_options) {
					if (menu_option.selected) {
						dataToSend["PrednarocanjeItems["+meal_object.index+
							"].MeniIDSkupinaID"] = menu_option.value;
					}
				}
			} // excess values: meal, menu-type, location, readonly, menu_options
			this.postback(LOPOLIS_URL+"Prehrana/Prednarocanje",dataToSend,null,true).
					then( (response) => {
				let parser = new DOMParser();
				let parsed = parser.parseFromString(response.data, "text/html");
				for (const [meal_date, meal_object] of Object.entries(meal_objects)) {
					let selected_value;
					for (const menu_option of meal_object.menu_options) {
						if (menu_option.selected) {
							selected_value = menu_option.value;
						}
					}
					if (!(parsed.getElementById("PrednarocanjeItems_"+meal_object.index+"__MeniIDSkupinaID").selectedOptions[0].value == selected_value)) {
						reject(LOPOLISC_ERR_NOTAPPLIED);
					}
				}
				resolve(true);
			});
		});
	}
	
	chooseMenu(meal_object, meal_index) {
		for (const menu_option of meal_object.menu_options) {
			menu_option.selected = false;
		}
		meal_object.menu_options[meal_index].selected = true;
		return;
	}

}

//   Edited with    \  / o  _ _    this script is     I         /\/\        2020
//   Improved & free \/  I I I I   vim-powered        my editor \__/  -- sijanec