Initial commit

This commit is contained in:
Thastertyn 2023-02-22 21:53:10 +01:00
commit a66d67676f
33 changed files with 793 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/src/main/java/xyz/thastertyn/Jecna/Credentials.java
/target/classes/xyz/thastertyn/Jecna/Credentials.class

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"java.configuration.updateBuildConfiguration": "interactive"
}

96
pom.xml Normal file
View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>xyz.thastertyn</groupId>
<artifactId>jecnak-tui</artifactId>
<version>1.0-SNAPSHOT</version>
<name>jecnak-tui</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.15.3</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>com.googlecode.lanterna</groupId>
<artifactId>lanterna</artifactId>
<version>3.2.0-alpha1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@ -0,0 +1,88 @@
package xyz.thastertyn;
import xyz.thastertyn.Jecna.*;
import xyz.thastertyn.Window.MainWindow;
/**
* Hello world!
*
*/
public class App {
public static void main(String[] args) {
//System.out.println("Hello World!");
//Login l = new Login();
//l.login(Credentials.user, Credentials.pass);
MainWindow window = new MainWindow();
window.run();
/*
try {
//#region Jidelna
//#region JSESSIONID
Connection.Response jidelna = Jsoup.connect("https://objednavky.jidelnasokolska.cz/")
.header("Connection", "keep-alive")
.method(Method.HEAD)
.execute();
String jidelnaJSESSIONID = jidelna.cookie("JSESSIONID");
String XSRF_TOKEN = jidelna.cookie("XSRF-TOKEN");
//#endregion
//#region CSRF
String csrf = Jsoup.connect("https://objednavky.jidelnasokolska.cz/faces/login.jsp")
.header("Connection", "keep-alive")
.cookie("XSRF-TOKEN", XSRF_TOKEN)
.cookie("JSESSIONID", jidelnaJSESSIONID)
.get()
.select("input[name=_csrf]")
.attr("value");
if(!XSRF_TOKEN.equals(csrf))
{
throw new SecurityException("CSRF tokens do not match, something is up");
}
//#endregion
//#region Login
Connection.Response jidelnaLogin = Jsoup.connect("https://objednavky.jidelnasokolska.cz/j_spring_security_check")
.header("Connection", "keep-alive")
.header("Content-Type", "application/x-www-form-urlencoded")
.cookie("XSRF-TOKEN", XSRF_TOKEN)
.cookie("JSESSIONID", jidelnaJSESSIONID)
.data("j_username", Credentials.user)
.data("j_password", Credentials.pass)
.data("terminal", "false")
.data("type", "web")
.data("_csrf", XSRF_TOKEN)
.data("targetUrl", "/faces/secured/main.jsp?terminal=false&status=true&printer=false&keyboard=false")
.method(Method.POST)
.execute();
//#endregion
Document obedy = Jsoup.connect("https://objednavky.jidelnasokolska.cz/faces/secured/month.jsp?terminal=false&keyboard=&printer=")
.header("Connection", "keep-alive")
.cookie("XSRF-TOKEN", XSRF_TOKEN)
.cookie("JSESSIONID", jidelnaJSESSIONID)
.get();
System.out.println(obedy.toString());
//#endregion
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e)
{
e.printStackTrace();
}*/
}
}

View File

@ -0,0 +1,15 @@
package xyz.thastertyn;
import org.jsoup.Jsoup;
public class Connection {
private static final org.jsoup.Connection CONNECTION = Jsoup.connect("")
.header("Connection", "keep-alive")
.cookie("role", "student");
public static org.jsoup.Connection getConnection()
{
return CONNECTION;
}
}

View File

@ -0,0 +1,5 @@
package xyz.thastertyn;
public class Download {
}

View File

@ -0,0 +1,31 @@
package xyz.thastertyn.Jecna;
import java.io.IOException;
import java.util.HashMap;
import org.jsoup.nodes.Document;
import xyz.thastertyn.Connection;
import xyz.thastertyn.Tuple.Pair;
public class Dochazka {
private HashMap<String, Pair<String, String>> absence = new HashMap<>();
public byte downloadAbsence(String JSESSIOND)
{
Document absenceDoc;
try {
// absence-list
absenceDoc = Connection.getConnection()
.cookie("JSESSIOND", JSESSIOND)
.url("https://www.spsejecna.cz" + "/absence/passing-student")
.get();
} catch (IOException e) {
e.printStackTrace();
}
return 0;
}
}

View File

@ -0,0 +1,15 @@
package xyz.thastertyn.Jecna;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
public class Downloader {
public static Connection download(String url, String Jsessionid)
{
return Jsoup.connect(url)
.header("Connection", "keep-alive")
.cookie("role", "student")
.cookie("JSESSIONID", Jsessionid);
}
}

View File

@ -0,0 +1,102 @@
package xyz.thastertyn.Jecna;
import java.io.File;
import java.io.IOException;
import java.net.UnknownHostException;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.Connection.Method;
public class Login {
private String Jsessionid = null;
// Check for session expiration
private long start;
private long lastCheck;
/**
* Zkontroluje zda jiz neexistuji ulozene udaje na systemu
* @return <ul>
* <li> {@code true} soubor existuje a neni prazdny </li>
* <li> {@code false} neexistuje, nebo jsou prazdne </li>
* </ul>
*/
public boolean getCredentials()
{
File credentials = null;
if(System.getProperty("os.name").equals("Linux"))
{
credentials = new File("~/.local/share/jecnak/credentials.json");
}else if(System.getProperty("os.name").contains("Windows"))
{
credentials = new File(System.getenv("APPDATA\\jecnak\\"));
}
if(!credentials.exists() || credentials.length() == 0)
{
return false;
}
return true;
}
public String getJSESSIONID()
{
return Jsessionid;
}
public byte login(String user, String pass)
{
try {
//#region JSESSIONID
Connection.Response response = Jsoup.connect("https://www.spsejecna.cz")
.header("Connection", "keep-alive")
.method(Method.HEAD)
.execute();
Jsessionid = response.cookie("JSESSIONID");
//#endregion
//#region Token3
String token3 = Jsoup.connect("https://www.spsejecna.cz/user/role?role=student")
.header("Connection", "keep-alive")
.cookie("JSESSIONID", Jsessionid)
.get()
.select("input[name=token3]")
.attr("value");
//#endregion
//#region Login
Connection.Response login = Jsoup.connect("https://www.spsejecna.cz/user/login")
.method(Connection.Method.POST)
.header("Content-Type", "application/x-www-form-urlencoded")
//.header("Content-Length", "71") Adds 10 seconds to total request time
.header("Origin", "https://www.spsejecna.cz")
.header("Connection", "keep-alive")
.cookie("JSESSIONID", Jsessionid)
.cookie("role", "student")
.data("token3", token3)
.data("user", user)
.data("pass", pass)
.data("submit", "P%C5%99ihl%C3%A1sit+se")
.followRedirects(true)
.execute();
//#endregion
start = System.currentTimeMillis() / 1000L;
lastCheck = start;
return 0;
} catch(UnknownHostException e)
{
// Not connected to internet
return 127;
} catch(IOException e)
{
return 126;
}
}
}

View File

@ -0,0 +1,103 @@
package xyz.thastertyn.Jecna;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.HashSet;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
/**
* Jeden radek v rozvrhu
*/
public class Rozvrh {
private String[][] rozvrh = new String[5][10];
int pos = 0;
public void setPredmet(String pr, int d, int i)
{
rozvrh[d][i] = pr;
}
public String[][] getRozvrh()
{
return rozvrh;
}
@Override
public String toString()
{
String s = "";
for(String[] st : rozvrh)
{
s += ("| ");
for(String str : st)
{
s += String.format("%-5s", str) + " | ";
}
s += "\n";
}
return s;
}
/**
* Stahne rozvrh z www.spsejecna.cz a dale ho zpracuje do formy
* se kterou da pracovat
* @param Jsessionid ze stranek
* @return Status code
* <newline>
* <ul>
* <li> 0 - Operace probehla bez problemu</li>
* </ul>
* @throws UnknownHostException kdyz neni pripojeni k internetu
* @throws IOException ostatni exceptiony nejsou dulezite, tak jsou zahrnuty v jednom
*/
public void downloadRozvrh(final String Jsessionid) throws UnknownHostException, IOException
{
Document rozvrhDoc = Downloader.download("https://www.spsejecna.cz" + "/timetable/class", Jsessionid).get();
Elements rozvrhTable = rozvrhDoc.select("table.timetable").select("tr");
Elements[] rozvrhDny = new Elements[rozvrhTable.size()];
for(int i = 0; i < rozvrhTable.size(); i++)
{
rozvrhDny[i] = rozvrhTable.get(i).children();
}
for(int i = 1; i < 6; i++)
{
for(int j = 1; j < 11; j++)
{
String predmet = rozvrhDny[i].get(j).select("span.subject").text().replaceAll(" ", "/");
// Predmety jako CEL jsou trikrat, staci ale jen jednou
// V hashsetu se neopakuji prvky
HashSet<String> set = new HashSet<>();
String[] split = predmet.split("/");
for(String s : split)
{
set.add(s);
}
String pr = "";
if(set.size() > 1)
{
for(String s : set)
{
pr += s + "/";
}
pr = pr.substring(0, pr.length() - 1);
}else{
for(String s : set) { pr = s; break; }
}
rozvrh[i-1][j-1] = pr;
}
}
}
}

View File

@ -0,0 +1,111 @@
package xyz.thastertyn.Jecna;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import xyz.thastertyn.Tuple.Pair;
public class Znamky {
private boolean wasDownloaded;
// key (String) reprezentuje predmet, value (arraylist) znamky a pair znamku s jeji vahou
private HashMap<String, ArrayList<Pair<Integer, Double>>> grades = new HashMap<>();
public void addGrade(String subject, int grade, double weight)
{
grades.get(subject).add(new Pair<Integer,Double>(grade, weight));
}
public void addSubject(String subject)
{
grades.put(subject, new ArrayList<Pair<Integer, Double>>());
}
private double getAverage(ArrayList<Pair<Integer, Double>> a)
{
try{
int divident = 0;
int divisor = 0;
for(Pair<Integer, Double> p : a)
{
divident += p.getValue0() * p.getValue1();
divisor += p.getValue1();
}
return (double) divident / divisor;
}catch(ArithmeticException e)
{
return 0;
}
}
public byte downloadZnamky(final String Jsessionid)
{
wasDownloaded = true;
Document znamkyDoc = null;
try {
znamkyDoc = Downloader.download("https://www.spsejecna.cz" + "/score/student", Jsessionid).get();
} catch (IOException e) {
e.printStackTrace();
return 127;
}
Elements rows = znamkyDoc.select("table.score").select("tr");
Elements[] rows_split = new Elements[rows.size()];
for (int i = 0; i < rows.size(); i++)
{
rows_split[i] = rows.get(i).children();
}
for(int i = 1; i < rows_split.length; i++)
{
String predmet = rows_split[i].get(0).text();
addSubject(predmet);
for(Element e : rows_split[i].get(1).select("a.score"))
{
int znamka = Integer.parseInt(e.select("span.value").text());
// Mala znamka se bude pocitat jako polovicni vaha
if(e.hasClass("scoreSmall"))
{
addGrade(predmet, znamka, 0.5);
}else{
addGrade(predmet, znamka, 1);
}
}
}
return 0;
}
@Override
public String toString()
{
if(wasDownloaded)
{
String s = "";
for(Map.Entry<String, ArrayList<Pair<Integer, Double>>> entry : grades.entrySet())
{
double prumer = getAverage(entry.getValue());
double p = (double) Math.round(prumer * 100) / 100;
s += entry.getKey() + " | " + entry.getValue().toString() + " { " + p + " }\n";
}
return s;
}else{
return "Nothing was downloaded";
}
}
}

View File

@ -0,0 +1,8 @@
package xyz.thastertyn;
import java.util.ArrayList;
public class Predmet {
}

View File

@ -0,0 +1,5 @@
package xyz.thastertyn;
public class RozvrhDownload {
}

View File

@ -0,0 +1,53 @@
package xyz.thastertyn.Tuple;
/**
* Ekvitalent Tuplu, ktery neni zabudovan v jave
*/
public class Pair<T1, T2> {
private T1 value0;
private T2 value1;
public Pair(T1 value0, T2 value1)
{
this.value0 = value0;
this.value1 = value1;
}
public Pair()
{
}
public void put(T1 value0, T2 value1)
{
this.value0 = value0;
this.value1 = value1;
}
public T1 getValue0()
{
return value0;
}
public T2 getValue1()
{
return value1;
}
public void setValue0(T1 value0)
{
this.value0 = value0;
}
public void setValue1(T2 value1)
{
this.value1 = value1;
}
@Override
public String toString()
{
return "[" + value0 + ", " + value1 + "]";
}
}

View File

@ -0,0 +1,74 @@
package xyz.thastertyn.Window;
import java.io.IOException;
import java.util.Arrays;
import com.googlecode.lanterna.TextColor;
import com.googlecode.lanterna.gui2.BasicWindow;
import com.googlecode.lanterna.gui2.DefaultWindowManager;
import com.googlecode.lanterna.gui2.Direction;
import com.googlecode.lanterna.gui2.EmptySpace;
import com.googlecode.lanterna.gui2.LinearLayout;
import com.googlecode.lanterna.gui2.MultiWindowTextGUI;
import com.googlecode.lanterna.gui2.Panel;
import com.googlecode.lanterna.gui2.Separator;
import com.googlecode.lanterna.gui2.Window;
import com.googlecode.lanterna.screen.Screen;
import com.googlecode.lanterna.screen.TerminalScreen;
import com.googlecode.lanterna.terminal.DefaultTerminalFactory;
import com.googlecode.lanterna.terminal.Terminal;
import xyz.thastertyn.Jecna.Credentials;
import xyz.thastertyn.Jecna.Login;
public class MainWindow {
Login l = new Login();
public void run()
{
Terminal terminal = null;
try {
// Setup terminal and screen layers
terminal = new DefaultTerminalFactory().createTerminal();
Screen screen = new TerminalScreen(terminal);
screen.startScreen();
// Create panel to hold components
final Panel mainPanel = new Panel();
mainPanel.setLayoutManager(new LinearLayout(Direction.HORIZONTAL));
// Create window to hold the panel
BasicWindow window = new BasicWindow();
window.setComponent(mainPanel);
window.setHints(Arrays.asList(Window.Hint.CENTERED));
mainPanel.addComponent(new Separator(Direction.VERTICAL).setLayoutData(LinearLayout.createLayoutData(LinearLayout.Alignment.Fill)));
final Panel content = new Panel();
mainPanel.addComponent(content);
Login l = new Login();
l.login(Credentials.user, Credentials.pass);
Rozvrh r = new Rozvrh();
r.download(l.getJSESSIONID());
content.addComponent(r.getPanel());
// Create gui and start gui
final MultiWindowTextGUI gui = new MultiWindowTextGUI(screen, new DefaultWindowManager(), new EmptySpace(TextColor.ANSI.BLACK_BRIGHT));
/*KeyStroke k = terminal.readInput();
if(k.equals(KeyStroke.fromString("<up>")))
{
window.close();
}*/
gui.addWindowAndWait(window);
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,62 @@
package xyz.thastertyn.Window;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.List;
import com.googlecode.lanterna.TerminalSize;
import com.googlecode.lanterna.TextColor;
import com.googlecode.lanterna.graphics.SimpleTheme;
import com.googlecode.lanterna.gui2.Direction;
import com.googlecode.lanterna.gui2.Panel;
import com.googlecode.lanterna.gui2.Separator;
import com.googlecode.lanterna.gui2.TextGUIGraphics;
import com.googlecode.lanterna.gui2.table.Table;
import com.googlecode.lanterna.gui2.table.TableCellRenderer;
public class Rozvrh {
private Panel rozvrhPanel = new Panel();
private xyz.thastertyn.Jecna.Rozvrh rozvrh = new xyz.thastertyn.Jecna.Rozvrh();
private String[] labels = {"Den", "7:30-8:15", "8:25-9:10", "9:20-10:05", "10:20-11:05", "11:15-12:00", "12:10-12:55", "13:05-13:50", "14:00-14:45", "14:55-15:40", "15:50-16:35"};
String[] days = {"PO", "UT", "ST", "CT", "PA"};
Table<String> t = new Table<>(labels);
public byte download(String Jsessionid)
{
try
{
rozvrh.downloadRozvrh(Jsessionid);
String[][] r = rozvrh.getRozvrh();
String[] s = new String[labels.length];
for(int i = 0; i < r.length; i++)
{
s[0] = days[i];
for(int j = 1; j < r[i].length; j++) { s[j] = r[i][j]; }
t.getTableModel().addRow(s);
}
t.addTo(rozvrhPanel);
return 0;
}catch(UnknownHostException e)
{
return 127;
}catch(IOException e)
{
return 126;
}
}
public Panel getPanel()
{
return rozvrhPanel;
}
}

View File

@ -0,0 +1,20 @@
package xyz.thastertyn;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
/**
* Unit test for simple App.
*/
public class AppTest
{
/**
* Rigorous Test :-)
*/
@Test
public void shouldAnswerWithTrue()
{
assertTrue( true );
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.