Merge branch 'master' into hebe

This commit is contained in:
Mikołaj Pich 2023-04-15 20:50:43 +02:00
commit ae322f4966
435 changed files with 9334 additions and 13423 deletions

View file

@ -1,62 +0,0 @@
version: 2
references:
workspace_root: &workspace_root
~/sdk
container_config: &container_config
docker:
- image: circleci/openjdk:8-jdk-stretch
working_directory: *workspace_root
attach_workspace: &attach_workspace
attach_workspace:
at: *workspace_root
general_cache_key: &general_cache_key
key: cache-{{ checksum "build.gradle" }}
paths:
- ~/.gradle
jobs:
test:
<<: *container_config
steps:
- *attach_workspace
- checkout
- restore_cache:
<<: *general_cache_key
- run: ./.circleci/host-hotfix.sh
- run: ./gradlew build -x check --no-daemon --stacktrace --console=plain -PdisablePreDex
- run: ./gradlew check jacocoTestReport --no-daemon --stacktrace --console=plain -PdisablePreDex
- save_cache:
<<: *general_cache_key
- run: bash <(curl -s https://codecov.io/bash)
- store_test_results:
path: ./build/test-results
- store_artifacts:
path: ./build/reports/jacoco/test
- store_artifacts:
path: ./build/reports/tests/test
- store_artifacts:
path: ./build/libs/sdk-0.16.0.jar
deploy:
<<: *container_config
steps:
- *attach_workspace
- checkout
- restore_cache:
<<: *general_cache_key
- run: ./gradlew bintrayUpload --no-daemon --stacktrace --console=plain -PdisablePreDex
workflows:
version: 2
test:
jobs:
- test

View file

@ -1,9 +0,0 @@
#!/usr/bin/env bash
echo "127.0.0.1 fakelog.localhost" | sudo tee -a /etc/hosts
echo "127.0.0.1 adfs.fakelog.localhost" | sudo tee -a /etc/hosts
echo "127.0.0.1 adfslight.fakelog.localhost" | sudo tee -a /etc/hosts
echo "127.0.0.1 cufs.fakelog.localhost" | sudo tee -a /etc/hosts
echo "127.0.0.1 uonetplus.fakelog.localhost" | sudo tee -a /etc/hosts
echo "127.0.0.1 uonetplus-opiekun.fakelog.localhost" | sudo tee -a /etc/hosts
echo "127.0.0.1 uonetplus-uczen.fakelog.localhost" | sudo tee -a /etc/hosts

View file

@ -11,3 +11,5 @@ indent_size=2
[*.{kt,kts}]
disabled_rules=import-ordering,no-wildcard-imports
max_line_length=177
ij_kotlin_allow_trailing_comma_on_call_site=true
ij_kotlin_allow_trailing_comma=true

17
.github/dependabot.yml vendored Normal file
View file

@ -0,0 +1,17 @@
version: 2
updates:
- package-ecosystem: gradle
directory: "/"
schedule:
interval: monthly
open-pull-requests-limit: 10
ignore:
- dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-core
versions:
- 1.4.3-native-mt
- dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-test
versions:
- 1.4.3-native-mt
- dependency-name: org.jlleitschuh.gradle.ktlint
versions:
- 9.4.1

31
.github/workflows/deploy.yml vendored Normal file
View file

@ -0,0 +1,31 @@
name: Deploy
on:
push:
branches: [ master ]
jobs:
deploy-sonatype:
name: Deploy to sonatype
runs-on: ubuntu-latest
timeout-minutes: 10
environment: ossrh
steps:
- uses: actions/checkout@v2
- uses: gradle/wrapper-validation-action@v1
- uses: actions/setup-java@v1
with:
java-version: 11
- uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
- name: Build and publish
env:
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
MAVEN_SIGNING_KEY: ${{ secrets.MAVEN_SIGNING_KEY }}
MAVEN_SIGNING_PASSWORD: ${{ secrets.MAVEN_SIGNING_PASSWORD }}
MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
run: ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository --stacktrace

54
.github/workflows/test.yml vendored Normal file
View file

@ -0,0 +1,54 @@
name: Tests
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:
jobs:
unit-tests:
name: Unit tests
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: fkirc/skip-duplicate-actions@master
- uses: actions/checkout@v2
- uses: gradle/wrapper-validation-action@v1
- uses: actions/setup-java@v1
with:
java-version: 11
- uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
- name: Unit tests
run: |
./gradlew test --stacktrace
./gradlew jacocoTestReport --stacktrace
- uses: codecov/codecov-action@v1
lint:
name: Lint check
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: fkirc/skip-duplicate-actions@master
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: 11
- uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}
- name: Lint
run: |
./gradlew ktlintCheck --stacktrace
- uses: codecov/codecov-action@v1

37
.gitignore vendored
View file

@ -22,8 +22,36 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
.idea/
!.idea/codeStyles/
# IntelliJ configurations
*.iml
.idea/workspace.xml
.idea/tasks.xml
#.idea/gradle.xml
.idea/assetWizardSettings.xml
.idea/dictionaries
.idea/libraries
.idea/caches
.idea/modules.xml
.idea/navEditor.xml
.idea/caches/
.idea/libraries/
.idea/shelf/
.idea/.name
.idea/compiler.xml
.idea/copyright/profiles_settings.xml
.idea/encodings.xml
.idea/misc.xml
.idea/scopes/scope_settings.xml
.idea/vcs.xml
.idea/jsLibraryMappings.xml
.idea/datasources.xml
.idea/dataSources.ids
.idea/sqlDataSources.xml
.idea/dynamic.xml
.idea/uiDesigner.xml
.idea/runConfigurations.xml
.idea/discord.xml
.idea/jarRepositories.xml
.gradle
build/
out/
@ -42,3 +70,8 @@ gradle-app.setting
*iml
classes
.DS_Store
.idea/libraries-with-intellij-classes.xml
.idea/kotlinc.xml
.idea/jpa-buddy.xml
.idea/kotlinScripting.xml

View file

@ -4,7 +4,7 @@
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value>
<package name="kotlinx.android.synthetic" withSubpackages="true" static="false" />
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
</value>
</option>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
@ -25,8 +25,6 @@
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="0" />
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
<option name="CALL_PARAMETERS_LPAREN_ON_NEXT_LINE" value="false" />
<option name="CALL_PARAMETERS_RPAREN_ON_NEXT_LINE" value="false" />
<option name="WRAP_ON_TYPING" value="0" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />

20
.idea/gradle.xml Normal file
View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="corretto-11" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/sdk" />
<option value="$PROJECT_DIR$/sdk-hebe" />
<option value="$PROJECT_DIR$/sdk-scrapper" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

View file

@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2019 Wulkanowy
Copyright 2023 Wulkanowy
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View file

@ -1,8 +1,9 @@
# VULCAN UONET+ SDK
[![GitHub Workflow status](https://img.shields.io/github/actions/workflow/status/wulkanowy/sdk/test.yml?branch=master&style=flat-square)](https://github.com/wulkanowy/sdk/actions)
[![Codecov branch](https://img.shields.io/codecov/c/github/wulkanowy/sdk/master.svg?style=flat-square)](https://codecov.io/gh/wulkanowy/sdk)
[![CircleCI branch](https://img.shields.io/circleci/project/github/wulkanowy/sdk/master.svg?style=flat-square)](https://circleci.com/gh/wulkanowy/sdk)
[![Bintray](https://img.shields.io/bintray/v/wulkanowy/wulkanowy/sdk.svg?style=flat-square)](https://bintray.com/wulkanowy/wulkanowy/sdk)
[![Maven Central](https://img.shields.io/maven-central/v/io.github.wulkanowy/sdk?style=flat-square)](https://search.maven.org/artifact/io.github.wulkanowy/sdk)
![Sonatype Nexus (Snapshots)](https://img.shields.io/nexus/s/io.github.wulkanowy/sdk?server=https%3A%2F%2Fs01.oss.sonatype.org&style=flat-square)
[![JitPack](https://img.shields.io/jitpack/v/wulkanowy/sdk.svg?style=flat-square)](https://jitpack.io/#wulkanowy/sdk)
[![License](https://img.shields.io/github/license/wulkanowy/sdk.svg?style=flat-square)](https://github.com/wulkanowy/sdk)
[![Discord](https://img.shields.io/discord/390889354199040011.svg?style=flat-square)](https://discord.gg/vccAQBr)
@ -14,7 +15,6 @@
Check it out [full public api](https://github.com/wulkanowy/sdk/blob/master/sdk/src/main/kotlin/io/github/wulkanowy/sdk/Sdk.kt)
and [test examples](https://github.com/wulkanowy/sdk/blob/master/sdk/src/test/kotlin/io/github/wulkanowy/sdk/SdkRemoteTest.kt).
## Documentation
Check [wiki page](https://github.com/wulkanowy/sdk/wiki).
@ -24,11 +24,17 @@ Check [wiki page](https://github.com/wulkanowy/sdk/wiki).
```gradle
allprojects {
repositories {
...
// for stable releases
mavenCentral()
// for snapshots
maven { url "https://s01.oss.sonatype.org/content/repositories/snapshots/" }
// for everything
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'io.github.wulkanowy:sdk:0.16.0'
implementation 'io.github.wulkanowy:sdk:<version>'
}
```

View file

@ -1,60 +1,106 @@
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.3.61' apply false
id "org.jlleitschuh.gradle.ktlint" version "9.2.1"
id 'com.jfrog.bintray' version '1.8.4'
alias(libs.plugins.kotlin) apply false
alias(libs.plugins.ksp) apply false
alias(libs.plugins.serialization)
id "org.jlleitschuh.gradle.ktlint" version "11.3.1"
id "io.github.gradle-nexus.publish-plugin" version "1.3.0"
}
ext {
PUBLISH_VERSION = '0.16.0'
PUBLISH_VERSION = '1.9.2'
SITE_URL = 'https://github.com/wulkanowy/sdk'
GIT_URL = 'https://github.com/wulkanowy/sdk.git'
jspoon = "1.3.2"
okhttp3 = "3.12.10"
retrofit = "2.6.4"
threetenbp = "1.4.1"
slf4j = "1.7.30"
jsoup = "1.15.4"
slf4j = "2.0.7"
moshi = "1.13.0"
}
version = PUBLISH_VERSION
group = "io.github.wulkanowy"
nexusPublishing {
repositories {
sonatype {
nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/"))
snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/"))
username = System.getenv("MAVEN_USERNAME")
password = System.getenv("MAVEN_PASSWORD")
}
}
}
allprojects {
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'kotlin'
apply plugin: 'maven-publish'
apply plugin: 'signing'
apply plugin: "org.jlleitschuh.gradle.ktlint"
apply plugin: 'com.jfrog.bintray'
apply plugin: 'kotlinx-serialization'
repositories {
mavenCentral()
jcenter()
maven { url "https://jitpack.io" }
}
version = PUBLISH_VERSION
group = "io.github.wulkanowy"
dependencies {
implementation "org.slf4j:slf4j-api:$slf4j"
testImplementation "org.slf4j:slf4j-simple:$slf4j"
bintray {
user = System.getenv('BINTRAY_USER')
key = System.getenv('BINTRAY_KEY')
configurations = ['archives']
implementation platform(libs.okhttp.bom)
}
pkg {
repo = 'wulkanowy'
name = 'sdk'
desc = 'Unified way of retrieving data from the UONET+ register through mobile api and scraping api'
java {
withJavadocJar()
withSourcesJar()
}
websiteUrl = 'https://github.com/wulkanowy/sdk'
issueTrackerUrl = 'https://github.com/wulkanowy/sdk/issues'
vcsUrl = 'https://github.com/wulkanowy/sdk.git'
licenses = ['Apache-2.0']
userOrg = 'wulkanowy'
labels = ['wulkanowy', 'sdk']
publicDownloadNumbers = true
publish = true
publishing {
publications {
sdk(MavenPublication) {
from components.java
version = rootProject.version
version {
name = PUBLISH_VERSION
vcsTag = PUBLISH_VERSION
released = new Date()
pom {
name = 'VULCAN UONET+ SDK'
description = 'Unified way of retrieving data from the UONET+ register through mobile api and scraping api'
url = 'https://github.com/wulkanowy/sdk'
licenses {
license {
name = 'The Apache License, Version 2.0'
url = 'https://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
developers {
developer {
id = 'mklkj'
name = 'Mikołaj Pich'
email = 'm.pich@outlook.com'
}
}
scm {
connection = 'https://github.com/wulkanowy/sdk.git'
developerConnection = 'git@github.com:wulkanowy/sdk.git'
url = 'https://github.com/wulkanowy/sdk'
}
}
}
}
if (System.getenv("MAVEN_SIGNING_KEY")) {
signing {
def signingKey = System.getenv("MAVEN_SIGNING_KEY") ?: ""
def signingPassword = System.getenv("MAVEN_SIGNING_PASSWORD")
useInMemoryPgpKeys(new String(signingKey.decodeBase64()), signingPassword)
sign publishing.publications.sdk
}
}
javadoc {
if (JavaVersion.current().isJava9Compatible()) {
options.addBooleanOption('html5', true)
}
}
}
@ -68,30 +114,30 @@ subprojects {
disabledRules = [
"no-wildcard-imports",
"import-ordering",
"max-line-length"
"max-line-length",
"multiline-if-else"
]
filter {
exclude { element -> element.file.path.contains("generated/") }
}
}
sourceCompatibility = 1.8
compileKotlin {
kotlinOptions {
jvmTarget = "1.6"
javaParameters = true
kotlin {
jvmToolchain {
languageVersion.set(JavaLanguageVersion.of("11"))
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation libs.coroutines.core
implementation "io.reactivex.rxjava2:rxjava:2.2.18"
implementation "com.squareup.okhttp3:logging-interceptor:$okhttp3"
implementation "com.squareup.okhttp3:logging-interceptor"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0"
compileOnly "org.threeten:threetenbp:$threetenbp:no-tzdb"
testImplementation "org.threeten:threetenbp:$threetenbp"
testImplementation "com.squareup.okhttp3:mockwebserver:$okhttp3"
testImplementation "junit:junit:4.13"
testImplementation "junit:junit:4.13.2"
testImplementation "com.squareup.okhttp3:mockwebserver"
testImplementation libs.retrofit.mock
testImplementation libs.coroutines.test
}
jacocoTestReport {
@ -99,36 +145,21 @@ subprojects {
xml.enabled true
}
}
jacoco {
toolVersion "0.8.8"
}
test {
testLogging.showStandardStreams = false
}
group = "io.github.wulkanowy.sdk"
if (project.plugins.hasPlugin('java')) {
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
artifacts {
archives sourcesJar
archives javadocJar
}
}
}
dependencies {
compile project(":sdk")
compile project(":sdk-hebe")
compile project(":sdk-mobile")
compile project(":sdk-scrapper")
api project(":sdk")
api project(":sdk-hebe")
api project(":sdk-scrapper")
compile "com.squareup.okhttp3:okhttp:$okhttp3"
api "com.squareup.okhttp3:okhttp"
}

Binary file not shown.

View file

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

286
gradlew vendored
View file

@ -1,78 +1,129 @@
#!/usr/bin/env sh
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m"'
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
MAX_FD=maximum
warn () {
echo "$*"
}
} >&2
die () {
echo
echo "$*"
echo
exit 1
}
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
@ -89,84 +140,95 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

43
gradlew.bat vendored
View file

@ -1,3 +1,19 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m"
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -35,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@ -45,28 +64,14 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell

2
jitpack.yml Normal file
View file

@ -0,0 +1,2 @@
jdk:
- openjdk11

View file

@ -7,12 +7,9 @@ plugins {
dependencies {
implementation "io.github.wulkanowy:uonet-request-signer:991de26"
implementation 'com.google.code.gson:gson:2.8.6'
implementation "com.brsanthu:migbase64:2.2"
implementation "com.squareup.retrofit2:retrofit:$retrofit"
implementation "com.squareup.retrofit2:converter-gson:$retrofit"
implementation "com.squareup.retrofit2:converter-scalars:$retrofit"
implementation "com.squareup.retrofit2:retrofit:$retrofit"
implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofit"
implementation libs.retrofit.core
implementation libs.retrofit.scalars
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0"
}

View file

@ -1,36 +1,39 @@
package io.github.wulkanowy.sdk.hebe
import com.google.gson.annotations.SerializedName
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
class ApiResponse<T> {
@SerializedName("Envelope")
@SerialName("Envelope")
var envelope: T? = null
@SerializedName("EnvelopeType")
@SerialName("EnvelopeType")
lateinit var envelopeType: String
@SerializedName("InResponseTo")
@SerialName("InResponseTo")
var inResponseTo: String? = null
@SerializedName("RequestId")
@SerialName("RequestId")
lateinit var requestId: String
@SerializedName("Status")
@SerialName("Status")
lateinit var status: Status
@SerializedName("Timestamp")
@SerialName("Timestamp")
var timestamp: Long = 0
@SerializedName("TimestampFormatted")
@SerialName("TimestampFormatted")
lateinit var timestampFormatted: String
@Serializable
data class Status(
@SerializedName("Code")
@SerialName("Code")
val code: Int,
@SerializedName("Message")
val message: String
@SerialName("Message")
val message: String,
)
}

View file

@ -3,7 +3,6 @@ package io.github.wulkanowy.sdk.hebe
import io.github.wulkanowy.sdk.hebe.register.RegisterResponse
import io.github.wulkanowy.sdk.hebe.register.StudentInfo
import io.github.wulkanowy.sdk.hebe.repository.RepositoryManager
import io.reactivex.Single
import okhttp3.Interceptor
import okhttp3.logging.HttpLoggingInterceptor
@ -47,15 +46,13 @@ class Hebe {
private val routes by resettableLazy(resettableManager) { serviceManager.getRoutesRepository() }
fun register(privateKey: String, certificateId: String, token: String, pin: String, symbol: String): Single<ApiResponse<RegisterResponse>> {
return routes.getRouteByToken(token).flatMap { baseUrl ->
serviceManager
.getRegisterRepository(baseUrl, symbol)
.registerDevice(privateKey, certificateId, deviceModel, pin, token)
}
suspend fun register(privateKey: String, certificateId: String, token: String, pin: String, symbol: String): ApiResponse<RegisterResponse> {
return serviceManager
.getRegisterRepository(routes.getRouteByToken(token), symbol)
.registerDevice(privateKey, certificateId, deviceModel, pin, token)
}
fun getStudents(url: String, symbol: String): Single<List<StudentInfo>> {
suspend fun getStudents(url: String, symbol: String): List<StudentInfo> {
return serviceManager
.getRegisterRepository(url, symbol)
.getStudentInfo()

View file

@ -6,25 +6,26 @@ import io.github.wulkanowy.sdk.hebe.register.RegisterRequest
import io.github.wulkanowy.sdk.hebe.register.RegisterResponse
import io.github.wulkanowy.sdk.hebe.register.StudentInfo
import io.github.wulkanowy.sdk.hebe.service.RegisterService
import io.reactivex.Single
class RegisterRepository(private val service: RegisterService) {
fun registerDevice(privateKey: String, certificateId: String, deviceModel: String, pin: String, token: String): Single<ApiResponse<RegisterResponse>> {
return service.registerDevice(ApiRequest(
certificateId = certificateId,
firebaseToken = "",
envelope = RegisterRequest(
certificate = privateKey,
certificateThumbprint = certificateId,
deviceModel = deviceModel,
pin = pin,
securityToken = token
)
))
suspend fun registerDevice(privateKey: String, certificateId: String, deviceModel: String, pin: String, token: String): ApiResponse<RegisterResponse> {
return service.registerDevice(
ApiRequest(
certificateId = certificateId,
firebaseToken = "",
envelope = RegisterRequest(
certificate = privateKey,
certificateThumbprint = certificateId,
deviceModel = deviceModel,
pin = pin,
securityToken = token,
),
),
)
}
fun getStudentInfo(): Single<List<StudentInfo>> {
return service.getStudentsInfo().map { requireNotNull(it.envelope) }
suspend fun getStudentInfo(): List<StudentInfo> {
return service.getStudentsInfo().envelope!!
}
}

View file

@ -1,13 +1,15 @@
package io.github.wulkanowy.sdk.hebe.repository
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import io.github.wulkanowy.sdk.hebe.interceptor.ErrorInterceptor
import io.github.wulkanowy.sdk.hebe.interceptor.SignInterceptor
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import okhttp3.Interceptor
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory
import retrofit2.create
@ -16,9 +18,19 @@ class RepositoryManager(
private val privateKey: String,
private val interceptors: MutableList<Pair<Interceptor, Boolean>>,
private val baseUrl: String,
private val schoolSymbol: String
private val schoolSymbol: String,
) {
@OptIn(ExperimentalSerializationApi::class)
private val json by lazy {
Json {
explicitNulls = false
ignoreUnknownKeys = true
coerceInputValues = true
isLenient = true
}
}
fun getRoutesRepository(): RoutingRulesRepository {
return RoutingRulesRepository(getRetrofitBuilder(interceptors).baseUrl("http://komponenty.vulcan.net.pl").build().create())
}
@ -29,22 +41,23 @@ class RepositoryManager(
return RegisterRepository(getRetrofitBuilder(interceptors).baseUrl("${baseUrl.removeSuffix("/")}/api/mobile/register/").build().create())
}
@OptIn(ExperimentalSerializationApi::class)
private fun getRetrofitBuilder(interceptors: MutableList<Pair<Interceptor, Boolean>>): Retrofit.Builder {
return Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(OkHttpClient().newBuilder()
.addInterceptor(HttpLoggingInterceptor().setLevel(logLevel))
.addInterceptor(ErrorInterceptor())
.addInterceptor(SignInterceptor(privateKey))
.apply {
interceptors.forEach {
if (it.second) addNetworkInterceptor(it.first)
else addInterceptor(it.first)
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
.client(
OkHttpClient().newBuilder()
.addInterceptor(HttpLoggingInterceptor().setLevel(logLevel))
.addInterceptor(ErrorInterceptor())
.addInterceptor(SignInterceptor(privateKey))
.apply {
interceptors.forEach {
if (it.second) addNetworkInterceptor(it.first)
else addInterceptor(it.first)
}
}
}
.build()
.build(),
)
}
}

View file

@ -5,15 +5,14 @@ import io.github.wulkanowy.sdk.hebe.ApiResponse
import io.github.wulkanowy.sdk.hebe.register.RegisterRequest
import io.github.wulkanowy.sdk.hebe.register.RegisterResponse
import io.github.wulkanowy.sdk.hebe.register.StudentInfo
import io.reactivex.Single
import retrofit2.http.GET
import retrofit2.http.POST
interface RegisterService {
@POST("new")
fun registerDevice(request: ApiRequest<RegisterRequest>): Single<ApiResponse<RegisterResponse>>
suspend fun registerDevice(request: ApiRequest<RegisterRequest>): ApiResponse<RegisterResponse>
@GET("hebe")
fun getStudentsInfo(): Single<ApiResponse<List<StudentInfo>>>
suspend fun getStudentsInfo(): ApiResponse<List<StudentInfo>>
}

View file

@ -1,18 +0,0 @@
plugins {
id 'java'
id 'org.jetbrains.kotlin.jvm'
id 'jacoco'
}
dependencies {
implementation "io.github.wulkanowy:uonet-request-signer:991de26"
implementation 'com.google.code.gson:gson:2.8.6'
implementation "com.brsanthu:migbase64:2.2"
implementation "com.squareup.retrofit2:retrofit:$retrofit"
implementation "com.squareup.retrofit2:converter-gson:$retrofit"
implementation "com.squareup.retrofit2:converter-scalars:$retrofit"
implementation "com.squareup.retrofit2:retrofit:$retrofit"
implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofit"
}

View file

@ -1,29 +0,0 @@
package io.github.wulkanowy.sdk.mobile
import com.google.gson.annotations.SerializedName
import org.threeten.bp.LocalDateTime.now
import org.threeten.bp.ZoneOffset
import java.util.UUID
@Suppress("unused")
abstract class ApiRequest(
@SerializedName("RemoteMobileTimeKey")
val remoteMobileTimeKey: Long = now().toEpochSecond(ZoneOffset.UTC),
@SerializedName("TimeKey")
val timeKey: Long = now().toEpochSecond(ZoneOffset.UTC) - 1,
@SerializedName("RequestId")
val requestId: String = UUID.randomUUID().toString(),
@SerializedName("RemoteMobileAppVersion")
val remoteMobileAppVersion: String = MOBILE_APP_VERSION,
@SerializedName("RemoteMobileAppName")
val remoteMobileAppName: String = "VULCAN-Android-ModulUcznia"
) {
companion object {
const val MOBILE_APP_VERSION = "20.1.1.447"
}
}

View file

@ -1,27 +0,0 @@
package io.github.wulkanowy.sdk.mobile
import com.google.gson.annotations.SerializedName
data class ApiResponse<out T>(
@SerializedName("Status")
val status: String,
@SerializedName("TimeKey")
val timeKey: String,
@SerializedName("TimeValue")
val timeValue: String,
@SerializedName("RequestId")
val requestId: String,
@SerializedName("DayOfWeek")
val dayOfWeek: String,
@SerializedName("AppVersion")
val appVersion: String,
@SerializedName("Data")
val data: T?
)

View file

@ -1,190 +0,0 @@
package io.github.wulkanowy.sdk.mobile
import com.migcomponents.migbase64.Base64
import io.github.wulkanowy.sdk.mobile.attendance.Attendance
import io.github.wulkanowy.sdk.mobile.dictionaries.Dictionaries
import io.github.wulkanowy.sdk.mobile.exams.Exam
import io.github.wulkanowy.sdk.mobile.exception.InvalidPinException
import io.github.wulkanowy.sdk.mobile.exception.NoStudentsException
import io.github.wulkanowy.sdk.mobile.exception.TokenDeadException
import io.github.wulkanowy.sdk.mobile.exception.TokenNotFoundException
import io.github.wulkanowy.sdk.mobile.exception.UnknownTokenException
import io.github.wulkanowy.sdk.mobile.exception.UnsupportedTokenException
import io.github.wulkanowy.sdk.mobile.grades.Grade
import io.github.wulkanowy.sdk.mobile.grades.GradesSummaryResponse
import io.github.wulkanowy.sdk.mobile.homework.Homework
import io.github.wulkanowy.sdk.mobile.messages.Message
import io.github.wulkanowy.sdk.mobile.messages.Recipient
import io.github.wulkanowy.sdk.mobile.notes.Note
import io.github.wulkanowy.sdk.mobile.register.CertificateResponse
import io.github.wulkanowy.sdk.mobile.register.Student
import io.github.wulkanowy.sdk.mobile.repository.RepositoryManager
import io.github.wulkanowy.sdk.mobile.school.Teacher
import io.github.wulkanowy.sdk.mobile.timetable.Lesson
import io.github.wulkanowy.signer.getPrivateKeyFromCert
import io.reactivex.Single
import okhttp3.Interceptor
import okhttp3.logging.HttpLoggingInterceptor
import org.threeten.bp.LocalDate
import org.threeten.bp.LocalDateTime
import java.nio.charset.Charset
class Mobile {
var classId = 0
var studentId = 0
var loginId = 0
private val resettableManager = resettableManager()
var logLevel = HttpLoggingInterceptor.Level.BASIC
set(value) {
field = value
resettableManager.reset()
}
var privateKey = ""
set(value) {
field = value
resettableManager.reset()
}
var certKey = ""
set(value) {
field = value
resettableManager.reset()
}
var baseUrl = ""
set(value) {
field = value
resettableManager.reset()
}
var schoolSymbol = ""
set(value) {
field = value
resettableManager.reset()
}
private val serviceManager by resettableLazy(resettableManager) { RepositoryManager(logLevel, privateKey, certKey, interceptors, baseUrl, schoolSymbol) }
private val routes by resettableLazy(resettableManager) { serviceManager.getRoutesRepository() }
private val mobile by resettableLazy(resettableManager) { serviceManager.getMobileRepository() }
private val interceptors: MutableList<Pair<Interceptor, Boolean>> = mutableListOf()
fun setInterceptor(interceptor: Interceptor, network: Boolean = false) {
interceptors.add(interceptor to network)
}
private lateinit var dictionaries: Dictionaries
fun getDictionaries(): Single<Dictionaries> {
if (::dictionaries.isInitialized) return Single.just(dictionaries)
return mobile.getDictionaries(0, 0, classId).map {
it.apply { dictionaries = this }
}
}
fun getCertificate(token: String, pin: String, symbol: String, deviceName: String, androidVersion: String): Single<CertificateResponse> {
return routes.getRouteByToken(token).flatMap { baseUrl ->
serviceManager.getRegisterRepository(baseUrl, symbol).getCertificate(token, pin, deviceName, androidVersion)
}
}
fun getStudents(certRes: CertificateResponse, apiKey: String = ""): Single<List<Student>> {
if (certRes.isError) when {
certRes.message == "TokenDead" -> throw TokenDeadException(certRes.message)
certRes.message == "TokenNotFound" -> throw TokenNotFoundException(certRes.message)
certRes.message?.startsWith("Podany numer PIN jest niepoprawny") == true -> throw InvalidPinException(certRes.message.orEmpty())
certRes.message?.startsWith("Trzykrotnie wpisano niepoprawny kod PIN") == true -> throw InvalidPinException(certRes.message.orEmpty())
certRes.message == "NoPupils" -> throw NoStudentsException(certRes.message.orEmpty())
certRes.message == "OnlyKindergarten" -> throw UnsupportedTokenException(certRes.message)
else -> throw UnknownTokenException(certRes.message.orEmpty())
}
val cert = certRes.tokenCert!!
certKey = cert.certificateKey
baseUrl = cert.baseUrl.removeSuffix("/")
privateKey = getPrivateKeyFromCert(apiKey.ifEmpty {
Base64.decode(if (cert.baseUrl.contains("fakelog")) "KDAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OUFCKQ==" else "KENFNzVFQTU5OEM3NzQzQUQ5QjBCNzMyOERFRDg1QjA2KQ==")
.toString(Charset.defaultCharset())
.removeSurrounding("(", ")")
}, cert.certificatePfx)
return serviceManager.getRegisterRepository(cert.baseUrl).getStudents().map { students ->
students.map {
it.copy().apply {
certificateKey = this@Mobile.certKey
privateKey = this@Mobile.privateKey
mobileBaseUrl = this@Mobile.baseUrl
}
}
}
}
fun getStudents(): Single<List<Student>> {
return serviceManager.getRegisterRepository(baseUrl).getStudents()
}
fun getAttendance(start: LocalDate, end: LocalDate, classificationPeriodId: Int): Single<List<Attendance>> {
return mobile.getAttendance(start, end, classId, classificationPeriodId, studentId)
}
fun getExams(start: LocalDate, end: LocalDate, classificationPeriodId: Int): Single<List<Exam>> {
return mobile.getExams(start, end, classId, classificationPeriodId, studentId)
}
fun getGrades(classificationPeriodId: Int): Single<List<Grade>> {
return mobile.getGrades(classId, classificationPeriodId, studentId)
}
fun getGradesSummary(classificationPeriodId: Int): Single<GradesSummaryResponse> {
return mobile.getGradesSummary(classId, classificationPeriodId, studentId)
}
fun getHomework(start: LocalDate, end: LocalDate, classificationPeriodId: Int): Single<List<Homework>> {
return mobile.getHomework(start, end, classId, classificationPeriodId, studentId)
}
fun getNotes(classificationPeriodId: Int): Single<List<Note>> {
return mobile.getNotes(classificationPeriodId, studentId)
}
fun getTeachers(studentId: Int, semesterId: Int): Single<List<Teacher>> {
return mobile.getTeachers(studentId, semesterId)
}
fun getMessages(start: LocalDateTime, end: LocalDateTime): Single<List<Message>> {
return mobile.getMessages(start, end, loginId, studentId)
}
fun getMessagesSent(start: LocalDateTime, end: LocalDateTime): Single<List<Message>> {
return mobile.getMessagesSent(start, end, loginId, studentId)
}
fun getMessagesDeleted(start: LocalDateTime, end: LocalDateTime): Single<List<Message>> {
return mobile.getMessagesDeleted(start, end, loginId, studentId)
}
fun changeMessageStatus(messageId: Int, folder: String, status: String): Single<String> {
return mobile.changeMessageStatus(messageId, folder, status, loginId, studentId)
}
fun sendMessage(subject: String, content: String, recipients: List<Recipient>): Single<Message> {
return getStudents().map { students ->
students.singleOrNull { it.loginId == loginId }?.name.orEmpty()
}.flatMap { sender ->
mobile.sendMessage(sender, subject, content, recipients, loginId, studentId)
}
}
fun getTimetable(start: LocalDate, end: LocalDate, classificationPeriodId: Int): Single<List<Lesson>> {
return mobile.getTimetable(start, end, classId, classificationPeriodId, studentId)
}
}

View file

@ -1,55 +0,0 @@
package io.github.wulkanowy.sdk.mobile
import java.util.LinkedList
import kotlin.reflect.KProperty
/**
* see https://stackoverflow.com/a/35757638/6695449
*/
class ResettableLazyManager {
// we synchronize to make sure the timing of a reset() call and new inits do not collide
val managedDelegates = LinkedList<Resettable>()
fun register(managed: Resettable) {
synchronized(managedDelegates) {
managedDelegates.add(managed)
}
}
fun reset() {
synchronized(managedDelegates) {
managedDelegates.forEach { it.reset() }
managedDelegates.clear()
}
}
}
interface Resettable {
fun reset()
}
class ResettableLazy<PROPTYPE>(val manager: ResettableLazyManager, val init: () -> PROPTYPE) : Resettable {
@Volatile
var lazyHolder = makeInitBlock()
operator fun getValue(thisRef: Any?, property: KProperty<*>): PROPTYPE {
return lazyHolder.value
}
override fun reset() {
lazyHolder = makeInitBlock()
}
fun makeInitBlock(): Lazy<PROPTYPE> {
return lazy {
manager.register(this)
init()
}
}
}
fun <PROPTYPE> resettableLazy(manager: ResettableLazyManager, init: () -> PROPTYPE): ResettableLazy<PROPTYPE> {
return ResettableLazy(manager, init)
}
fun resettableManager(): ResettableLazyManager = ResettableLazyManager()

View file

@ -1,9 +0,0 @@
package io.github.wulkanowy.sdk.mobile
import org.threeten.bp.LocalDate
import org.threeten.bp.LocalDateTime
import org.threeten.bp.format.DateTimeFormatter.ofPattern
fun LocalDate.toFormat(): String = format(ofPattern("yyyy-MM-dd"))
fun LocalDateTime.toFormat(): String = format(ofPattern("yyyy-MM-dd"))

View file

@ -1,27 +0,0 @@
package io.github.wulkanowy.sdk.mobile.attendance
import com.google.gson.annotations.SerializedName
data class Attendance(
@SerializedName("IdKategoria")
val categoryId: Int,
@SerializedName("Numer")
val number: Int,
@SerializedName("IdPoraLekcji")
val lessonTimeId: Int,
@SerializedName("Dzien")
val date: Long,
@SerializedName("DzienTekst")
val dateText: String,
@SerializedName("IdPrzedmiot")
val subjectId: Int,
@SerializedName("PrzedmiotNazwa")
val subjectName: String
)

View file

@ -1,22 +0,0 @@
package io.github.wulkanowy.sdk.mobile.attendance
import com.google.gson.annotations.SerializedName
import io.github.wulkanowy.sdk.mobile.ApiRequest
data class AttendanceRequest(
@SerializedName("DataPoczatkowa")
val startDate: String,
@SerializedName("DataKoncowa")
val endDate: String,
@SerializedName("IdOddzial")
val classId: Int,
@SerializedName("IdOkresKlasyfikacyjny")
val classificationPeriodId: Int,
@SerializedName("IdUczen")
val studentId: Int
) : ApiRequest()

View file

@ -1,21 +0,0 @@
package io.github.wulkanowy.sdk.mobile.attendance
import com.google.gson.annotations.SerializedName
data class AttendanceResponse(
@SerializedName("DataPoczatkowa")
val dateStart: Long,
@SerializedName("DataPoczatkowaTekst")
val dateStartText: String,
@SerializedName("DataKoncowa")
val dateEnd: Long,
@SerializedName("DataKoncowaTekst")
val dateEndText: String,
@SerializedName("Frekwencje")
val data: List<Attendance>
)

View file

@ -1,33 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.google.gson.annotations.SerializedName
data class AttendanceCategory(
@SerializedName("Id")
val id: Int,
@SerializedName("Nazwa")
val name: String,
@SerializedName("Pozycja")
val position: Int,
@SerializedName("Obecnosc")
val presence: Boolean,
@SerializedName("Nieobecnosc")
val absence: Boolean,
@SerializedName("Zwolnienie")
val exemption: Boolean,
@SerializedName("Spoznienie")
val lateness: Boolean,
@SerializedName("Usprawiedliwione")
val excused: Boolean,
@SerializedName("Usuniete")
val deleted: Boolean
)

View file

@ -1,24 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.google.gson.annotations.SerializedName
data class AttendanceType(
@SerializedName("Id")
val id: Int,
@SerializedName("Symbol")
val symbol: String,
@SerializedName("Nazwa")
val name: String,
@SerializedName("Aktywny")
val active: Boolean,
@SerializedName("WpisDomyslny")
val defaultEntry: Boolean,
@SerializedName("IdKategoriaFrek")
val categoryId: Int
)

View file

@ -1,33 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.google.gson.annotations.SerializedName
data class Dictionaries(
@SerializedName("TimeKey")
val timeKey: Long,
@SerializedName("Nauczyciele")
val teachers: List<Teacher>,
@SerializedName("Pracownicy")
val employees: List<Employee>,
@SerializedName("Przedmioty")
val subjects: List<Subject>,
@SerializedName("PoryLekcji")
val lessonTimes: List<LessonTime>,
@SerializedName("KategorieOcen")
val gradeCategories: List<GradeCategory>,
@SerializedName("KategorieUwag")
val noteCategories: List<NoteCategory>,
@SerializedName("KategorieFrekwencji")
val attendanceCategories: List<AttendanceCategory>,
@SerializedName("TypyFrekwencji")
val attendanceTypes: List<AttendanceType>
)

View file

@ -1,17 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.google.gson.annotations.SerializedName
import io.github.wulkanowy.sdk.mobile.ApiRequest
data class DictionariesRequest(
@SerializedName("IdUczen")
val userId: Int,
@SerializedName("IdOkresKlasyfikacyjny")
val classificationPeriodId: Int,
@SerializedName("IdOddzial")
val classId: Int
) : ApiRequest()

View file

@ -1,27 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.google.gson.annotations.SerializedName
data class Employee(
@SerializedName("Id")
val id: Int,
@SerializedName("Imie")
val name: String,
@SerializedName("Nazwisko")
val surname: String,
@SerializedName("Kod")
val code: String,
@SerializedName("Aktywny")
val active: Boolean,
@SerializedName("Nauczyciel")
val teacher: Boolean,
@SerializedName("LoginId")
val loginId: Int
)

View file

@ -1,15 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.google.gson.annotations.SerializedName
data class GradeCategory(
@SerializedName("Id")
val id: Int,
@SerializedName("Kod")
val code: String,
@SerializedName("Nazwa")
val name: String
)

View file

@ -1,24 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.google.gson.annotations.SerializedName
data class LessonTime(
@SerializedName("Id")
val id: Int,
@SerializedName("Numer")
val number: Int,
@SerializedName("Poczatek")
val start: Long,
@SerializedName("PoczatekTekst")
val startText: String,
@SerializedName("Koniec")
val end: Long,
@SerializedName("KoniecTekst")
val endText: String
)

View file

@ -1,15 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.google.gson.annotations.SerializedName
data class NoteCategory(
@SerializedName("Id")
val id: Int,
@SerializedName("Kod")
val code: String,
@SerializedName("Nazwa")
val name: String
)

View file

@ -1,21 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.google.gson.annotations.SerializedName
data class Subject(
@SerializedName("Id")
val id: Int,
@SerializedName("Nazwa")
val name: String,
@SerializedName("Kod")
val code: String,
@SerializedName("Aktywny")
val active: Boolean,
@SerializedName("Pozycja")
val position: Int
)

View file

@ -1,27 +0,0 @@
package io.github.wulkanowy.sdk.mobile.dictionaries
import com.google.gson.annotations.SerializedName
data class Teacher(
@SerializedName("Id")
val id: Int,
@SerializedName("Imie")
val name: String,
@SerializedName("Nazwisko")
val surname: String,
@SerializedName("Kod")
val code: String,
@SerializedName("Aktywny")
val active: Boolean,
@SerializedName("Nauczyciel")
val teacher: Boolean,
@SerializedName("LoginId")
val loginId: Int
)

View file

@ -1,39 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exams
import com.google.gson.annotations.SerializedName
data class Exam(
@SerializedName("Id")
val id: Int,
@SerializedName("IdPrzedmiot")
val subjectId: Int,
@SerializedName("IdPracownik")
val employeeId: Int,
@SerializedName("IdOddzial")
val classId: Int?,
@SerializedName("IdPodzial")
val divideId: Int?,
@SerializedName("PodzialNazwa")
val divideName: String?,
@SerializedName("Rodzaj")
val type: Boolean, // false - quiz, true - test
@SerializedName("RodzajNumer")
val typeNumber: Int,
@SerializedName("Opis")
val description: String,
@SerializedName("Data")
val date: Long,
@SerializedName("DataTekst")
val dateText: String
)

View file

@ -1,22 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exams
import com.google.gson.annotations.SerializedName
import io.github.wulkanowy.sdk.mobile.ApiRequest
data class ExamsRequest(
@SerializedName("DataPoczatkowa")
val startDate: String,
@SerializedName("DataKoncowa")
val endDate: String,
@SerializedName("IdOddzial")
val classId: Int,
@SerializedName("IdOkresKlasyfikacyjny")
val classificationPeriodId: Int,
@SerializedName("IdUczen")
val studentId: Int
) : ApiRequest()

View file

@ -1,5 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exception
import java.io.IOException
class InvalidPinException(message: String) : IOException(message)

View file

@ -1,5 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exception
import java.io.IOException
class InvalidSymbolException : IOException()

View file

@ -1,5 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exception
import java.io.IOException
open class InvalidTokenException internal constructor(message: String) : IOException(message)

View file

@ -1,5 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exception
import java.io.IOException
class NoStudentsException(message: String) : IOException(message)

View file

@ -1,3 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exception
class TokenDeadException(message: String) : InvalidTokenException(message)

View file

@ -1,3 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exception
class TokenNotFoundException(message: String) : InvalidTokenException(message)

View file

@ -1,3 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exception
class UnknownTokenException(message: String) : InvalidTokenException(message)

View file

@ -1,5 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exception
import java.io.IOException
class UnsupportedTokenException(message: String) : IOException(message)

View file

@ -1,66 +0,0 @@
package io.github.wulkanowy.sdk.mobile.grades
import com.google.gson.annotations.SerializedName
data class Grade(
@SerializedName("id")
val id: Int,
@SerializedName("Pozycja")
val position: Int,
@SerializedName("PrzedmiotPozycja")
val subjectPosition: Int,
@SerializedName("IdPrzedmiot")
val subjectId: Int,
@SerializedName("IdKategoria")
val categoryId: Int,
@SerializedName("Wpis")
val entry: String,
@SerializedName("Wartosc")
val value: Double,
@SerializedName("WagaModyfikatora")
val modificationWeight: Double?,
@SerializedName("WagaOceny")
val gradeWeight: Double,
@SerializedName("Licznik")
val counter: Double?,
@SerializedName("Mianownik")
val denominator: Int?,
@SerializedName("Komentarz")
val comment: String?,
@SerializedName("Waga")
val weight: String,
@SerializedName("Opis")
val description: String,
@SerializedName("DataUtworzenia")
val creationDate: Long,
@SerializedName("DataUtworzeniaTekst")
val creationDateText: String,
@SerializedName("DataModyfikacji")
val modificationDate: Long,
@SerializedName("DataModyfikacjiTekst")
val modificationDateText: String,
@SerializedName("IdPracownikD")
val employeeIdD: Int,
@SerializedName("IdPracownikM")
val employeeIdM: Int
)

View file

@ -1,18 +0,0 @@
package io.github.wulkanowy.sdk.mobile.grades
import com.google.gson.annotations.SerializedName
data class GradeSummary(
@SerializedName("IdPrzedmiot")
val subjectId: Int = 0,
@SerializedName("Wpis")
val entry: String = "",
@SerializedName("SredniaOcen")
val average: String = "0",
@SerializedName("SumaPunktow")
val pointsSum: String = ""
)

View file

@ -1,16 +0,0 @@
package io.github.wulkanowy.sdk.mobile.grades
import com.google.gson.annotations.SerializedName
import io.github.wulkanowy.sdk.mobile.ApiRequest
data class GradesRequest(
@SerializedName("IdOddzial")
val classId: Int,
@SerializedName("IdOkresKlasyfikacyjny")
val classificationPeriodId: Int,
@SerializedName("IdUczen")
val studentId: Int
) : ApiRequest()

View file

@ -1,15 +0,0 @@
package io.github.wulkanowy.sdk.mobile.grades
import com.google.gson.annotations.SerializedName
data class GradesSummaryResponse(
@SerializedName("OcenyPrzewidywane")
val predicted: List<GradeSummary>,
@SerializedName("OcenyKlasyfikacyjne")
val evaluative: List<GradeSummary>,
@SerializedName("SrednieOcen")
val average: List<GradeSummary>
)

View file

@ -1,27 +0,0 @@
package io.github.wulkanowy.sdk.mobile.homework
import com.google.gson.annotations.SerializedName
data class Homework(
@SerializedName("Id")
val id: Int,
@SerializedName("IdUczen")
val studentId: Int,
@SerializedName("Data")
val date: Long,
@SerializedName("DataTekst")
val dateText: String,
@SerializedName("IdPracownik")
val employeeId: Int,
@SerializedName("IdPrzedmiot")
val subjectId: Int,
@SerializedName("Opis")
val content: String
)

View file

@ -1,22 +0,0 @@
package io.github.wulkanowy.sdk.mobile.homework
import com.google.gson.annotations.SerializedName
import io.github.wulkanowy.sdk.mobile.ApiRequest
data class HomeworkRequest(
@SerializedName("DataPoczatkowa")
val startDate: String,
@SerializedName("DataKoncowa")
val endDate: String,
@SerializedName("IdOddzial")
val classId: Int,
@SerializedName("IdOkresKlasyfikacyjny")
val classificationPeriodId: Int,
@SerializedName("IdUczen")
val studentId: Int
) : ApiRequest()

View file

@ -1,20 +0,0 @@
package io.github.wulkanowy.sdk.mobile.interceptor
import io.github.wulkanowy.sdk.mobile.exception.InvalidSymbolException
import okhttp3.Interceptor
import okhttp3.Response
class ErrorInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val response = chain.proceed(chain.request())
val body = response.peekBody(Long.MAX_VALUE).string()
when {
body == "Bad Request" -> throw InvalidSymbolException()
body.contains("Podany symbol grupujący jest nieprawidłowy") -> throw InvalidSymbolException()
}
return response
}
}

View file

@ -1,32 +0,0 @@
package io.github.wulkanowy.sdk.mobile.interceptor
import io.github.wulkanowy.signer.signContent
import okhttp3.Interceptor
import okhttp3.Response
import okio.Buffer
import java.nio.charset.Charset
class SignInterceptor(
private val privateKey: String,
private val certKey: String
) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val original = chain.request()
val request = original.newBuilder()
request.header("User-Agent", "MobileUserAgent")
if (privateKey.isNotBlank()) {
val signature = Buffer().run {
original.body()?.writeTo(this)
signContent(privateKey, readString(Charset.defaultCharset()))
}
request.header("RequestCertificateKey", certKey)
request.header("RequestSignatureValue", signature)
}
return chain.proceed(request.method(original.method(), original.body()).build())
}
}

View file

@ -1,54 +0,0 @@
package io.github.wulkanowy.sdk.mobile.messages
import com.google.gson.annotations.SerializedName
data class Message(
@SerializedName("WiadomoscId")
val messageId: Int,
@SerializedName("Nadawca")
val senderName: String?,
@SerializedName("NadawcaId")
val senderId: Int,
@SerializedName("Adresaci")
val recipients: List<Recipient>?,
@SerializedName("Tytul")
val subject: String,
@SerializedName("Tresc")
val content: String,
@SerializedName("DataWyslania")
val sentDate: String,
@SerializedName("DataWyslaniaUnixEpoch")
val sentDateTime: Long,
@SerializedName("GodzinaWyslania")
val sentHour: String,
@SerializedName("DataPrzeczytania")
val readDate: String?,
@SerializedName("DataPrzeczytaniaUnixEpoch")
val readDateTime: Long?,
@SerializedName("GodzinaPrzeczytania")
val readHour: String?,
@SerializedName("StatusWiadomosci")
val status: String,
@SerializedName("FolderWiadomosci")
val folder: String,
@SerializedName("Nieprzeczytane")
val unread: String?,
@SerializedName("Przeczytane")
val read: String?
)

View file

@ -1,22 +0,0 @@
package io.github.wulkanowy.sdk.mobile.messages
import com.google.gson.annotations.SerializedName
import io.github.wulkanowy.sdk.mobile.ApiRequest
data class MessageStatusChangeRequest(
@SerializedName("WiadomoscId")
val messageId: Int,
@SerializedName("FolderWiadomosci")
val folder: String,
@SerializedName("Status")
val status: String,
@SerializedName("LoginId")
val loginId: Int,
@SerializedName("IdUczen")
val studentId: Int
) : ApiRequest()

View file

@ -1,19 +0,0 @@
package io.github.wulkanowy.sdk.mobile.messages
import com.google.gson.annotations.SerializedName
import io.github.wulkanowy.sdk.mobile.ApiRequest
data class MessagesRequest(
@SerializedName("DataPoczatkowa")
val startDate: String,
@SerializedName("DataKoncowa")
val endDate: String,
@SerializedName("LoginId")
val loginId: Int,
@SerializedName("IdUczen")
val studentId: Int
) : ApiRequest()

View file

@ -1,12 +0,0 @@
package io.github.wulkanowy.sdk.mobile.messages
import com.google.gson.annotations.SerializedName
data class Recipient(
@SerializedName("LoginId")
val loginId: Int,
@SerializedName("Nazwa")
val name: String
)

View file

@ -1,24 +0,0 @@
package io.github.wulkanowy.sdk.mobile.messages
import com.google.gson.annotations.SerializedName
data class SendMessageRequest(
@SerializedName("NadawcaWiadomosci")
val sender: String,
@SerializedName("Tytul")
val subject: String,
@SerializedName("Tresc")
val content: String,
@SerializedName("Adresaci")
val recipients: List<Recipient>,
@SerializedName("LoginId")
val loginId: Int,
@SerializedName("IdUczen")
val studentId: Int
)

View file

@ -1,48 +0,0 @@
package io.github.wulkanowy.sdk.mobile.notes
import com.google.gson.annotations.SerializedName
data class Note(
@SerializedName("Id")
val id: Int,
@SerializedName("IdKategoriaUwag")
val noteCategoryId: Int,
@SerializedName("IdUczen")
val studentId: Int,
@SerializedName("UczenImie")
val studentName: String,
@SerializedName("UczenNazwisko")
val studentSurname: String,
@SerializedName("IdPracownik")
val employeeId: Int,
@SerializedName("PracownikImie")
val employeeName: String,
@SerializedName("PracownikNazwisko")
val employeeSurname: String,
@SerializedName("DataWpisu")
val entryDate: Long,
@SerializedName("DataWpisuTekst")
val entryDateText: String,
@SerializedName("DataModyfikacji")
val modificationDate: Long?,
@SerializedName("DataModyfikacjiTekst")
val modificationDateText: String?,
@SerializedName("UwagaKey")
val noteKey: String,
@SerializedName("TrescUwagi")
val content: String
)

View file

@ -1,13 +0,0 @@
package io.github.wulkanowy.sdk.mobile.notes
import com.google.gson.annotations.SerializedName
import io.github.wulkanowy.sdk.mobile.ApiRequest
data class NotesRequest(
@SerializedName("IdOkresKlasyfikacyjny")
val classificationPeriodId: Int,
@SerializedName("IdUczen")
val studentId: Int
) : ApiRequest()

View file

@ -1,36 +0,0 @@
package io.github.wulkanowy.sdk.mobile.register
import com.google.gson.annotations.SerializedName
import io.github.wulkanowy.sdk.mobile.ApiRequest
import java.util.UUID
data class CertificateRequest(
@SerializedName("PIN")
val pin: String,
@SerializedName("TokenKey")
val tokenKey: String,
@SerializedName("AppVersion")
val appVersion: String = MOBILE_APP_VERSION,
@SerializedName("DeviceId")
val deviceId: String = UUID.randomUUID().toString(),
@SerializedName("DeviceName")
val deviceName: String,
@SerializedName("DeviceNameUser")
val deviceNameUser: String = "",
@SerializedName("DeviceDescription")
val deviceDescription: String = "",
@SerializedName("DeviceSystemType")
val deviceSystemType: String = "Android",
@SerializedName("DeviceSystemVersion")
val deviceSystemVersion: String = "8.1.0"
) : ApiRequest()

View file

@ -1,24 +0,0 @@
package io.github.wulkanowy.sdk.mobile.register
import com.google.gson.annotations.SerializedName
data class CertificateResponse(
@SerializedName("IsError")
val isError: Boolean,
@SerializedName("IsMessageForUser")
val isMessageForUser: Boolean,
@SerializedName("Message")
val message: String?,
@SerializedName("TokenKey")
val tokenKey: String?,
@SerializedName("TokenStatus")
val tokenStatus: String?,
@SerializedName("TokenCert")
val tokenCert: TokenCert?
)

View file

@ -1,100 +0,0 @@
package io.github.wulkanowy.sdk.mobile.register
import com.google.gson.annotations.SerializedName
data class Student(
@SerializedName("IdOkresKlasyfikacyjny")
val classificationPeriodId: Int,
@SerializedName("OkresPoziom")
val periodLevel: Int,
@SerializedName("OkresNumer")
val periodNumber: Int,
@SerializedName("OkresDataOd")
val periodDateFrom: Long,
@SerializedName("OkresDataDo")
val periodDateTo: Long,
@SerializedName("OkresDataOdTekst")
val periodDateFromText: String,
@SerializedName("OkresDataDoTekst")
val periodDateToText: String,
@SerializedName("IdJednostkaSprawozdawcza")
val reportingUnitId: Int,
@SerializedName("JednostkaSprawozdawczaSkrot")
val reportingUnitShortcut: String,
@SerializedName("JednostkaSprawozdawczaNazwa")
val reportingUnitName: String,
@SerializedName("JednostkaSprawozdawczaSymbol")
val reportingUnitSymbol: String,
@SerializedName("IdJednostka")
val unitId: Int,
@SerializedName("JednostkaNazwa")
val unitName: String,
@SerializedName("JednostkaSkrot")
val unitShortcut: String,
@SerializedName("OddzialSymbol")
val classSymbol: String,
@SerializedName("OddzialKod")
val classCode: String?,
@SerializedName("UzytkownikRola")
val userRole: String,
@SerializedName("UzytkownikLogin")
val userLogin: String,
@SerializedName("UzytkownikLoginId")
val userLoginId: Int,
@SerializedName("UzytkownikNazwa")
val userName: String,
@SerializedName("Id")
val id: Int,
@SerializedName("IdOddzial")
val classId: Int,
@SerializedName("Imie")
val name: String,
@SerializedName("Imie2")
val nameSecond: String?,
@SerializedName("Nazwisko")
val surname: String,
@SerializedName("Pseudonim")
val nick: String?,
@SerializedName("UczenPlec")
val pupilGender: Int,
@SerializedName("Pozycja")
val position: Int,
@SerializedName("LoginId")
val loginId: Int?
) {
var privateKey = ""
var certificateKey = ""
var mobileBaseUrl = ""
}

View file

@ -1,36 +0,0 @@
package io.github.wulkanowy.sdk.mobile.register
import com.google.gson.annotations.SerializedName
data class TokenCert(
@SerializedName("CertyfikatKlucz")
val certificateKey: String,
@SerializedName("CertyfikatKluczSformatowanyTekst")
val certificateKeyFormatted: String,
@SerializedName("CertyfikatDataUtworzenia")
val certificateCreatedDate: Int,
@SerializedName("CertyfikatDataUtworzeniaSformatowanyTekst")
val certificateCreatedDateText: String,
@SerializedName("CertyfikatPfx")
val certificatePfx: String,
@SerializedName("GrupaKlientow")
val symbol: String,
@SerializedName("AdresBazowyRestApi")
val baseUrl: String,
@SerializedName("UzytkownikLogin")
val userLogin: String,
@SerializedName("UzytkownikNazwa")
val userName: String,
@SerializedName("TypKonta")
val accountType: String?
)

View file

@ -1,101 +0,0 @@
package io.github.wulkanowy.sdk.mobile.repository
import io.github.wulkanowy.sdk.mobile.ApiRequest
import io.github.wulkanowy.sdk.mobile.ApiResponse
import io.github.wulkanowy.sdk.mobile.attendance.Attendance
import io.github.wulkanowy.sdk.mobile.attendance.AttendanceRequest
import io.github.wulkanowy.sdk.mobile.dictionaries.Dictionaries
import io.github.wulkanowy.sdk.mobile.dictionaries.DictionariesRequest
import io.github.wulkanowy.sdk.mobile.exams.Exam
import io.github.wulkanowy.sdk.mobile.exams.ExamsRequest
import io.github.wulkanowy.sdk.mobile.grades.Grade
import io.github.wulkanowy.sdk.mobile.grades.GradesRequest
import io.github.wulkanowy.sdk.mobile.grades.GradesSummaryResponse
import io.github.wulkanowy.sdk.mobile.homework.Homework
import io.github.wulkanowy.sdk.mobile.homework.HomeworkRequest
import io.github.wulkanowy.sdk.mobile.messages.Message
import io.github.wulkanowy.sdk.mobile.messages.MessageStatusChangeRequest
import io.github.wulkanowy.sdk.mobile.messages.MessagesRequest
import io.github.wulkanowy.sdk.mobile.messages.Recipient
import io.github.wulkanowy.sdk.mobile.messages.SendMessageRequest
import io.github.wulkanowy.sdk.mobile.notes.Note
import io.github.wulkanowy.sdk.mobile.notes.NotesRequest
import io.github.wulkanowy.sdk.mobile.school.Teacher
import io.github.wulkanowy.sdk.mobile.school.TeachersRequest
import io.github.wulkanowy.sdk.mobile.service.MobileService
import io.github.wulkanowy.sdk.mobile.timetable.Lesson
import io.github.wulkanowy.sdk.mobile.timetable.TimetableRequest
import io.github.wulkanowy.sdk.mobile.toFormat
import io.reactivex.Single
import org.threeten.bp.LocalDate
import org.threeten.bp.LocalDateTime
class MobileRepository(private val api: MobileService) {
fun logStart(): Single<ApiResponse<String>> = api.logAppStart(object : ApiRequest() {})
fun getDictionaries(userId: Int, classificationPeriodId: Int, classId: Int): Single<Dictionaries> {
return api.getDictionaries(DictionariesRequest(userId, classificationPeriodId, classId)).map { requireNotNull(it.data) }
}
fun getTeachers(studentId: Int, semesterId: Int): Single<List<Teacher>> {
return api.getTeachers(TeachersRequest(studentId, semesterId)).map { requireNotNull(it.data) }.map {
it.schoolTeachers.union(it.teachersSubjects).toList()
}
}
fun getTimetable(start: LocalDate, end: LocalDate, classId: Int, classificationPeriodId: Int, studentId: Int): Single<List<Lesson>> {
return api.getTimetable(TimetableRequest(start.toFormat(), end.toFormat(), classId, classificationPeriodId, studentId)).map { requireNotNull(it.data) }
}
fun getGrades(classId: Int, classificationPeriodId: Int, studentId: Int): Single<List<Grade>> {
return api.getGrades(GradesRequest(classId, classificationPeriodId, studentId)).map { requireNotNull(it.data) }
}
fun getGradesSummary(classId: Int, classificationPeriodId: Int, studentId: Int): Single<GradesSummaryResponse> {
return api.getGradesSummary(GradesRequest(classId, classificationPeriodId, studentId)).map { requireNotNull(it.data) }
}
fun getExams(start: LocalDate, end: LocalDate, classId: Int, classificationPeriodId: Int, studentId: Int): Single<List<Exam>> {
return api.getExams(ExamsRequest(start.toFormat(), end.toFormat(), classId, classificationPeriodId, studentId)).map { requireNotNull(it.data) }
}
fun getNotes(classificationPeriodId: Int, studentId: Int): Single<List<Note>> {
return api.getNotes(NotesRequest(classificationPeriodId, studentId)).map { requireNotNull(it.data) }
}
fun getAttendance(start: LocalDate, end: LocalDate, classId: Int, classificationPeriodId: Int, studentId: Int): Single<List<Attendance>> {
return api.getAttendance(AttendanceRequest(start.toFormat(), end.toFormat(), classId, classificationPeriodId, studentId)).map { requireNotNull(it.data?.data) }
}
fun getHomework(start: LocalDate, end: LocalDate, classId: Int, classificationPeriodId: Int, studentId: Int): Single<List<Homework>> {
return api.getHomework(HomeworkRequest(start.toFormat(), end.toFormat(), classId, classificationPeriodId, studentId)).map { requireNotNull(it.data) }
}
fun getMessages(start: LocalDateTime, end: LocalDateTime, loginId: Int, studentId: Int): Single<List<Message>> {
return api.getMessages(MessagesRequest(start.toFormat(), end.toFormat(), loginId, studentId)).map { requireNotNull(it.data) }
}
fun getMessagesDeleted(start: LocalDateTime, end: LocalDateTime, loginId: Int, studentId: Int): Single<List<Message>> {
return api.getMessagesDeleted(MessagesRequest(start.toFormat(), end.toFormat(), loginId, studentId)).map { requireNotNull(it.data) }
}
fun getMessagesSent(start: LocalDateTime, end: LocalDateTime, loginId: Int, studentId: Int): Single<List<Message>> {
return api.getMessagesSent(MessagesRequest(start.toFormat(), end.toFormat(), loginId, studentId)).map { requireNotNull(it.data) }
}
fun changeMessageStatus(messageId: Int, folder: String, status: String, loginId: Int, studentId: Int): Single<String> {
return api.changeMessageStatus(MessageStatusChangeRequest(messageId, folder, status, loginId, studentId)).map { requireNotNull(it.data) }
}
fun sendMessage(sender: String, subject: String, content: String, recipients: List<Recipient>, loginId: Int, studentId: Int): Single<Message> {
return api.sendMessage(SendMessageRequest(
sender = sender,
subject = subject,
content = content,
recipients = recipients,
loginId = loginId,
studentId = studentId
))
}
}

View file

@ -1,17 +0,0 @@
package io.github.wulkanowy.sdk.mobile.repository
import io.github.wulkanowy.sdk.mobile.ApiRequest
import io.github.wulkanowy.sdk.mobile.register.CertificateRequest
import io.github.wulkanowy.sdk.mobile.register.CertificateResponse
import io.github.wulkanowy.sdk.mobile.register.Student
import io.github.wulkanowy.sdk.mobile.service.RegisterService
import io.reactivex.Single
class RegisterRepository(private val api: RegisterService) {
fun getCertificate(token: String, pin: String, deviceName: String, androidVersion: String): Single<CertificateResponse> {
return api.getCertificate(CertificateRequest(tokenKey = token, pin = pin, deviceName = "$deviceName (Wulkanowy)", deviceSystemVersion = androidVersion))
}
fun getStudents(): Single<List<Student>> = api.getPupils(object : ApiRequest() {}).map { requireNotNull(it.data) }
}

View file

@ -1,55 +0,0 @@
package io.github.wulkanowy.sdk.mobile.repository
import io.github.wulkanowy.sdk.mobile.interceptor.ErrorInterceptor
import io.github.wulkanowy.sdk.mobile.interceptor.SignInterceptor
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory
import retrofit2.create
class RepositoryManager(
private val logLevel: HttpLoggingInterceptor.Level,
private val privateKey: String,
private val certKey: String,
private val interceptors: MutableList<Pair<Interceptor, Boolean>>,
private val baseUrl: String,
private val schoolSymbol: String
) {
fun getRoutesRepository(): RoutingRulesRepository {
return RoutingRulesRepository(getRetrofitBuilder(interceptors).baseUrl("http://komponenty.vulcan.net.pl").build().create())
}
fun getMobileRepository(): MobileRepository {
return MobileRepository(getRetrofitBuilder(interceptors).baseUrl("$baseUrl/$schoolSymbol/mobile-api/Uczen.v3.Uczen/").build().create())
}
fun getRegisterRepository(baseUrl: String, symbol: String) = getRegisterRepository("${baseUrl.removeSuffix("/")}/$symbol")
fun getRegisterRepository(baseUrl: String): RegisterRepository {
return RegisterRepository(getRetrofitBuilder(interceptors).baseUrl("${baseUrl.removeSuffix("/")}/mobile-api/Uczen.v3.UczenStart/").build().create())
}
private fun getRetrofitBuilder(interceptors: MutableList<Pair<Interceptor, Boolean>>): Retrofit.Builder {
return Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(OkHttpClient().newBuilder()
.addInterceptor(HttpLoggingInterceptor().setLevel(logLevel))
.addInterceptor(ErrorInterceptor())
.addInterceptor(SignInterceptor(privateKey, certKey))
.apply {
interceptors.forEach {
if (it.second) addNetworkInterceptor(it.first)
else addInterceptor(it.first)
}
}
.build()
)
}
}

View file

@ -1,24 +0,0 @@
package io.github.wulkanowy.sdk.mobile.repository
import io.github.wulkanowy.sdk.mobile.exception.InvalidTokenException
import io.github.wulkanowy.sdk.mobile.exception.UnknownTokenException
import io.github.wulkanowy.sdk.mobile.service.RoutingRulesService
import io.reactivex.Single
class RoutingRulesRepository(private val api: RoutingRulesService) {
fun getRouteByToken(token: String): Single<String> {
if (token.length < 4) return Single.error<String>(InvalidTokenException("Token '$token' is too short"))
val tokenSymbol = token.substring(0..2)
if ("FK1" == tokenSymbol) return Single.just("https://api.fakelog.cf")
return api.getRoutingRules().map { routes ->
routes.split("\r?\n".toRegex())
.singleOrNull { tokenSymbol == it.substringBefore(",") }
?.substringAfter(",")
?: throw UnknownTokenException("This token: '$token' is unsupported")
}
}
}

View file

@ -1,15 +0,0 @@
package io.github.wulkanowy.sdk.mobile.school
import com.google.gson.annotations.SerializedName
data class Teacher(
@SerializedName("IdPracownik")
val employeeId: Int,
@SerializedName("IdPrzedmiot")
val subjectId: Int,
@SerializedName("Rola")
val role: String
)

View file

@ -1,13 +0,0 @@
package io.github.wulkanowy.sdk.mobile.school
import com.google.gson.annotations.SerializedName
import io.github.wulkanowy.sdk.mobile.ApiRequest
class TeachersRequest(
@SerializedName("IdUczen")
val studentId: Int,
@SerializedName("IdOkresKlasyfikacyjny")
val semesterId: Int
) : ApiRequest()

View file

@ -1,12 +0,0 @@
package io.github.wulkanowy.sdk.mobile.school
import com.google.gson.annotations.SerializedName
data class TeachersResponse(
@SerializedName("NauczycieleSzkola")
val schoolTeachers: List<Teacher>,
@SerializedName("NauczycielePrzedmioty")
val teachersSubjects: List<Teacher>
)

View file

@ -1,76 +0,0 @@
package io.github.wulkanowy.sdk.mobile.service
import io.github.wulkanowy.sdk.mobile.ApiRequest
import io.github.wulkanowy.sdk.mobile.ApiResponse
import io.github.wulkanowy.sdk.mobile.attendance.AttendanceRequest
import io.github.wulkanowy.sdk.mobile.attendance.AttendanceResponse
import io.github.wulkanowy.sdk.mobile.dictionaries.Dictionaries
import io.github.wulkanowy.sdk.mobile.dictionaries.DictionariesRequest
import io.github.wulkanowy.sdk.mobile.exams.Exam
import io.github.wulkanowy.sdk.mobile.exams.ExamsRequest
import io.github.wulkanowy.sdk.mobile.grades.Grade
import io.github.wulkanowy.sdk.mobile.grades.GradesRequest
import io.github.wulkanowy.sdk.mobile.grades.GradesSummaryResponse
import io.github.wulkanowy.sdk.mobile.homework.Homework
import io.github.wulkanowy.sdk.mobile.homework.HomeworkRequest
import io.github.wulkanowy.sdk.mobile.messages.Message
import io.github.wulkanowy.sdk.mobile.messages.MessageStatusChangeRequest
import io.github.wulkanowy.sdk.mobile.messages.MessagesRequest
import io.github.wulkanowy.sdk.mobile.messages.SendMessageRequest
import io.github.wulkanowy.sdk.mobile.notes.Note
import io.github.wulkanowy.sdk.mobile.notes.NotesRequest
import io.github.wulkanowy.sdk.mobile.school.TeachersRequest
import io.github.wulkanowy.sdk.mobile.school.TeachersResponse
import io.github.wulkanowy.sdk.mobile.timetable.Lesson
import io.github.wulkanowy.sdk.mobile.timetable.TimetableRequest
import io.reactivex.Single
import retrofit2.http.Body
import retrofit2.http.POST
interface MobileService {
@POST("LogAppStart")
fun logAppStart(@Body logAppStartRequest: ApiRequest): Single<ApiResponse<String>>
@POST("Slowniki")
fun getDictionaries(@Body dictionariesRequest: DictionariesRequest): Single<ApiResponse<Dictionaries>>
@POST("Nauczyciele")
fun getTeachers(@Body teachersRequest: TeachersRequest): Single<ApiResponse<TeachersResponse>>
@POST("PlanLekcjiZeZmianami")
fun getTimetable(@Body timetableRequest: TimetableRequest): Single<ApiResponse<List<Lesson>>>
@POST("Oceny")
fun getGrades(@Body gradesRequest: GradesRequest): Single<ApiResponse<List<Grade>>>
@POST("OcenyPodsumowanie")
fun getGradesSummary(@Body gradesRequest: GradesRequest): Single<ApiResponse<GradesSummaryResponse>>
@POST("Sprawdziany")
fun getExams(@Body examsRequest: ExamsRequest): Single<ApiResponse<List<Exam>>>
@POST("UwagiUcznia")
fun getNotes(@Body notesRequest: NotesRequest): Single<ApiResponse<List<Note>>>
@POST("Frekwencje")
fun getAttendance(@Body attendanceRequest: AttendanceRequest): Single<ApiResponse<AttendanceResponse>>
@POST("ZadaniaDomowe")
fun getHomework(@Body homeworkRequest: HomeworkRequest): Single<ApiResponse<List<Homework>>>
@POST("WiadomosciOdebrane")
fun getMessages(@Body messagesRequest: MessagesRequest): Single<ApiResponse<List<Message>>>
@POST("WiadomosciWyslane")
fun getMessagesSent(@Body messagesRequest: MessagesRequest): Single<ApiResponse<List<Message>>>
@POST("WiadomosciUsuniete")
fun getMessagesDeleted(@Body messagesRequest: MessagesRequest): Single<ApiResponse<List<Message>>>
@POST("ZmienStatusWiadomosci")
fun changeMessageStatus(@Body messageStatusChangeRequest: MessageStatusChangeRequest): Single<ApiResponse<String>>
@POST("DodajWiadomosc")
fun sendMessage(@Body sendMessageRequest: SendMessageRequest): Single<Message>
}

View file

@ -1,21 +0,0 @@
package io.github.wulkanowy.sdk.mobile.service
import io.github.wulkanowy.sdk.mobile.ApiRequest
import io.github.wulkanowy.sdk.mobile.ApiResponse
import io.github.wulkanowy.sdk.mobile.register.CertificateRequest
import io.github.wulkanowy.sdk.mobile.register.CertificateResponse
import io.github.wulkanowy.sdk.mobile.register.Student
import io.reactivex.Single
import retrofit2.http.Body
import retrofit2.http.Headers
import retrofit2.http.POST
interface RegisterService {
@POST("Certyfikat")
@Headers("RequestMobileType: RegisterDevice")
fun getCertificate(@Body certificateRequest: CertificateRequest): Single<CertificateResponse>
@POST("ListaUczniow")
fun getPupils(@Body pupilsListRequest: ApiRequest): Single<ApiResponse<List<Student>>>
}

View file

@ -1,10 +0,0 @@
package io.github.wulkanowy.sdk.mobile.service
import io.reactivex.Single
import retrofit2.http.GET
interface RoutingRulesService {
@GET("/UonetPlusMobile/RoutingRules.txt")
fun getRoutingRules(): Single<String>
}

View file

@ -1,57 +0,0 @@
package io.github.wulkanowy.sdk.mobile.timetable
import com.google.gson.annotations.SerializedName
data class Lesson(
@SerializedName("Dzien")
val day: Long,
@SerializedName("DzienTekst")
val dayText: String,
@SerializedName("NumerLekcji")
val lessonNumber: Int,
@SerializedName("IdPoraLekcji")
val lessonTimeId: Int,
@SerializedName("IdPrzedmiot")
val subjectId: Int,
@SerializedName("PrzedmiotNazwa")
val subjectName: String,
@SerializedName("PodzialSkrot")
val divisionShort: String?,
@SerializedName("Sala")
val room: String?,
@SerializedName("IdPracownik")
val employeeId: Int,
@SerializedName("IdPracownikWspomagajacy")
val employeeSupporterId: Int?,
@SerializedName("IdPracownikOld")
val employeeOldId: Int?,
@SerializedName("IdPracownikWspomagajacyOld")
val employeeSupporterOldId: Int?,
@SerializedName("IdPlanLekcji")
val timetableId: Int,
@SerializedName("AdnotacjaOZmianie")
val annotationAboutChange: String?,
@SerializedName("PrzekreslonaNazwa")
val overriddenName: Boolean,
@SerializedName("PogrubionaNazwa")
val boldName: Boolean,
@SerializedName("PlanUcznia")
val studentPlan: Boolean
)

View file

@ -1,22 +0,0 @@
package io.github.wulkanowy.sdk.mobile.timetable
import com.google.gson.annotations.SerializedName
import io.github.wulkanowy.sdk.mobile.ApiRequest
data class TimetableRequest(
@SerializedName("DataPoczatkowa")
val startDate: String,
@SerializedName("DataKoncowa")
val endDate: String,
@SerializedName("IdOddzial")
val classId: Int,
@SerializedName("IdOkresKlasyfikacyjny")
val classificationPeriodId: Int,
@SerializedName("IdUczen")
val studentId: Int
) : ApiRequest()

View file

@ -1,43 +0,0 @@
package io.github.wulkanowy.sdk.mobile
import io.github.wulkanowy.sdk.mobile.interceptor.ErrorInterceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory
open class BaseLocalTest {
val server = MockWebServer()
fun MockWebServer.enqueue(fileName: String, clazz: Class<*>) {
enqueue(MockResponse().setBody(clazz.getResource(fileName).readText()))
}
fun MockWebServer.enqueueAndStart(fileName: String, clazz: Class<*> = this@BaseLocalTest.javaClass, port: Int = 3030) {
enqueue(fileName, clazz)
start(port)
}
@After
fun tearDown() {
server.shutdown()
}
fun getRetrofit(baseUrl: String = server.url("/").toString()): Retrofit = getRetrofitBuilder().baseUrl(baseUrl).build()
fun getRetrofitBuilder(): Retrofit.Builder = Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(OkHttpClient().newBuilder()
.addInterceptor(ErrorInterceptor())
.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BASIC))
.build()
)
}

View file

@ -1,171 +0,0 @@
package io.github.wulkanowy.sdk.mobile
import io.github.wulkanowy.sdk.mobile.attendance.Attendance
import io.github.wulkanowy.sdk.mobile.dictionaries.Dictionaries
import io.github.wulkanowy.sdk.mobile.exams.Exam
import io.github.wulkanowy.sdk.mobile.grades.Grade
import io.github.wulkanowy.sdk.mobile.homework.Homework
import io.github.wulkanowy.sdk.mobile.interceptor.SignInterceptor
import io.github.wulkanowy.sdk.mobile.notes.Note
import io.github.wulkanowy.sdk.mobile.register.CertificateResponse
import io.github.wulkanowy.sdk.mobile.register.Student
import io.github.wulkanowy.sdk.mobile.repository.MobileRepository
import io.github.wulkanowy.sdk.mobile.repository.RegisterRepository
import io.github.wulkanowy.sdk.mobile.timetable.Lesson
import io.github.wulkanowy.signer.getPrivateKeyFromCert
import io.reactivex.observers.TestObserver
import junit.framework.TestCase.assertEquals
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import org.junit.BeforeClass
import org.junit.Ignore
import org.junit.Test
import org.threeten.bp.LocalDate.of
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory
import retrofit2.create
const val PASSWORD = "012345678901234567890123456789AB"
const val DEVICE_NAME = "Wulkanowy#client"
const val HOST = "https://api.fakelog.cf"
const val SYMBOL = "powiatwulkanowy"
const val TOKEN = "FK100000"
const val PIN = "999999"
@Ignore
class UonetTest {
companion object {
private lateinit var mobile: MobileRepository
private lateinit var student: Student
private fun getRetrofitBuilder(privateKey: String, certKey: String): Retrofit.Builder {
return Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(OkHttpClient().newBuilder()
.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BASIC))
.addInterceptor(SignInterceptor(privateKey, certKey))
.build()
)
}
@JvmStatic
@BeforeClass
fun setUp() {
// RegisterRepository
val register = RegisterRepository(getRetrofitBuilder("", "")
.baseUrl("$HOST/$SYMBOL/mobile-api/Uczen.v3.UczenStart/")
.build().create()
)
val certificate = register.getCertificate(TOKEN, PIN, DEVICE_NAME, "8.1.0")
val certSubscriber = TestObserver<CertificateResponse>()
certificate.subscribe(certSubscriber)
certSubscriber.assertComplete()
certSubscriber.assertNoErrors()
assertEquals(false, certSubscriber.values()[0].isError)
val tokenCrt = certSubscriber.values()[0].tokenCert
val certKey = tokenCrt!!.certificateKey
val cert = tokenCrt.certificatePfx
val privateKey = getPrivateKeyFromCert(PASSWORD, cert)
val pupils = register.getStudents()
val pupilSubscriber = TestObserver<List<Student>>()
pupils.subscribe(pupilSubscriber)
pupilSubscriber.assertComplete()
pupilSubscriber.assertNoErrors()
assertEquals(2, pupilSubscriber.values()[0].size)
student = pupilSubscriber.values()[0][0]
// MobileRepository
mobile = MobileRepository(getRetrofitBuilder(privateKey, certKey)
.baseUrl("$HOST/powiatwulkanowy/${student.reportingUnitSymbol}/mobile-api/Uczen.v3.Uczen/")
.build().create()
)
}
}
@Test
fun logStartTest() {
val start = mobile.logStart()
val startSubscriber = TestObserver<ApiResponse<String>>()
start.subscribe(startSubscriber)
startSubscriber.assertComplete()
startSubscriber.assertNoErrors()
assertEquals("Ok", startSubscriber.values()[0].status)
}
@Test
fun dictionariesTest() {
val dictionaries = mobile.getDictionaries(student.userLoginId, student.classificationPeriodId, student.classId)
val dictionariesSubscriber = TestObserver<Dictionaries>()
dictionaries.subscribe(dictionariesSubscriber)
dictionariesSubscriber.assertComplete()
dictionariesSubscriber.assertNoErrors()
}
@Test
fun timetableTest() {
val lessons = mobile.getTimetable(of(2018, 4, 23), of(2018, 4, 24), student.classId, student.classificationPeriodId, student.id)
val lessonsSubscriber = TestObserver<List<Lesson>>()
lessons.subscribe(lessonsSubscriber)
lessonsSubscriber.assertComplete()
lessonsSubscriber.assertNoErrors()
}
@Test
fun gradesTest() {
val grades = mobile.getGrades(student.classId, student.classificationPeriodId, student.id)
val gradesSubscriber = TestObserver<List<Grade>>()
grades.subscribe(gradesSubscriber)
gradesSubscriber.assertComplete()
gradesSubscriber.assertNoErrors()
}
@Test
fun examsTest() {
val exams = mobile.getExams(of(2018, 5, 28), of(2018, 6, 3), student.classId, student.classificationPeriodId, student.id)
val examsSubscriber = TestObserver<List<Exam>>()
exams.subscribe(examsSubscriber)
examsSubscriber.assertComplete()
examsSubscriber.assertNoErrors()
}
@Test
fun notesTest() {
val notes = mobile.getNotes(student.classificationPeriodId, student.id)
val notesSubscriber = TestObserver<List<Note>>()
notes.subscribe(notesSubscriber)
notesSubscriber.assertComplete()
notesSubscriber.assertNoErrors()
}
@Test
fun attendanceTest() {
val attendance = mobile.getAttendance(of(2018, 4, 23), of(2018, 4, 24), student.classId, student.classificationPeriodId, student.id)
val attendanceSubscriber = TestObserver<List<Attendance>>()
attendance.subscribe(attendanceSubscriber)
attendanceSubscriber.assertComplete()
attendanceSubscriber.assertNoErrors()
}
@Test
fun homeworkTest() {
val homework = mobile.getHomework(of(2017, 10, 23), of(2017, 10, 27), student.classId, student.classificationPeriodId, student.id)
val homeworkSubscriber = TestObserver<List<Homework>>()
homework.subscribe(homeworkSubscriber)
homeworkSubscriber.assertComplete()
homeworkSubscriber.assertNoErrors()
}
}

View file

@ -1,22 +0,0 @@
package io.github.wulkanowy.sdk.mobile.exams
import io.github.wulkanowy.sdk.mobile.BaseLocalTest
import io.github.wulkanowy.sdk.mobile.repository.MobileRepository
import org.junit.Assert.assertEquals
import org.junit.Test
import org.threeten.bp.LocalDate.of
import retrofit2.create
class ExamsTest : BaseLocalTest() {
private val exams by lazy { MobileRepository(getRetrofit().create()) }
@Test
fun getExams() {
server.enqueueAndStart("Sprawdziany.json")
val items = exams.getExams(of(2020, 1, 16), of(2020, 1, 17), 1, 2, 3).blockingGet()
assertEquals(3, items.size)
}
}

View file

@ -1,21 +0,0 @@
package io.github.wulkanowy.sdk.mobile.grades
import io.github.wulkanowy.sdk.mobile.BaseLocalTest
import io.github.wulkanowy.sdk.mobile.repository.MobileRepository
import org.junit.Assert.assertEquals
import org.junit.Test
import retrofit2.create
class GradesTest : BaseLocalTest() {
private val grades by lazy { MobileRepository(getRetrofit().create()) }
@Test
fun getGrades() {
server.enqueueAndStart("Oceny.json")
val items = grades.getGrades(0, 0, 0).blockingGet()
assertEquals(2, items.size)
}
}

View file

@ -1,36 +0,0 @@
package io.github.wulkanowy.sdk.mobile.interceptor
import io.github.wulkanowy.sdk.mobile.BaseLocalTest
import io.github.wulkanowy.sdk.mobile.exception.InvalidSymbolException
import io.github.wulkanowy.sdk.mobile.register.Student
import io.github.wulkanowy.sdk.mobile.repository.RegisterRepository
import io.reactivex.observers.TestObserver
import org.junit.Test
import retrofit2.create
class ErrorInterceptorTest : BaseLocalTest() {
@Test
fun invalidSymbol() {
server.enqueueAndStart("invalid-symbol.txt")
val repo = RegisterRepository(getRetrofitBuilder().baseUrl("http://localhost:3030/").build().create())
val students = repo.getStudents()
val studentsObserver = TestObserver<List<Student>>()
students.subscribe(studentsObserver)
studentsObserver.assertNotComplete()
studentsObserver.assertError(InvalidSymbolException::class.java)
}
@Test
fun invalidSymbol_diacritics() {
server.enqueueAndStart("invalid-symbol.html")
val repo = RegisterRepository(getRetrofitBuilder().baseUrl("http://localhost:3030/").build().create())
val students = repo.getStudents()
val studentsObserver = TestObserver<List<Student>>()
students.subscribe(studentsObserver)
studentsObserver.assertNotComplete()
studentsObserver.assertError(InvalidSymbolException::class.java)
}
}

View file

@ -1,20 +0,0 @@
package io.github.wulkanowy.sdk.mobile.register
import io.github.wulkanowy.sdk.mobile.BaseLocalTest
import io.github.wulkanowy.sdk.mobile.repository.RegisterRepository
import org.junit.Assert.assertEquals
import org.junit.Test
import retrofit2.create
class RegisterTest : BaseLocalTest() {
private val repo by lazy { RegisterRepository(getRetrofit().create()) }
@Test
fun getStudents() {
server.enqueueAndStart("ListaUczniow.json")
val students = repo.getStudents().blockingGet()
assertEquals(2, students.size)
}
}

View file

@ -1,45 +0,0 @@
package io.github.wulkanowy.sdk.mobile.repository
import io.github.wulkanowy.sdk.mobile.BaseLocalTest
import io.github.wulkanowy.sdk.mobile.exception.InvalidTokenException
import io.reactivex.observers.TestObserver
import org.junit.Assert.assertEquals
import org.junit.Test
import retrofit2.create
class RoutingRulesRepositoryTest : BaseLocalTest() {
@Test
fun getRouteByToken() {
server.enqueueAndStart("RoutingRules.txt")
val repo = RoutingRulesRepository(getRetrofit().create())
val route = repo.getRouteByToken("KA2000").blockingGet()
assertEquals("https://uonetplus-komunikacja-test.mcuw.katowice.eu", route)
}
@Test
fun getRouteByToken_invalid() {
server.enqueueAndStart("RoutingRules.txt")
val repo = RoutingRulesRepository(getRetrofit().create())
val route = repo.getRouteByToken("ERR00000")
val routeObserver = TestObserver<String>()
route.subscribe(routeObserver)
routeObserver.assertNotComplete()
routeObserver.assertError(InvalidTokenException::class.java)
}
@Test
fun getRouteByToken_tooShort() {
server.enqueueAndStart("RoutingRules.txt")
val repo = RoutingRulesRepository(getRetrofit().create())
val route = repo.getRouteByToken("ER")
val routeObserver = TestObserver<String>()
route.subscribe(routeObserver)
routeObserver.assertNotComplete()
routeObserver.assertError(InvalidTokenException::class.java)
}
}

View file

@ -1,22 +0,0 @@
package io.github.wulkanowy.sdk.mobile.timetable
import io.github.wulkanowy.sdk.mobile.BaseLocalTest
import io.github.wulkanowy.sdk.mobile.repository.MobileRepository
import org.junit.Assert.assertEquals
import org.junit.Test
import org.threeten.bp.LocalDate.of
import retrofit2.create
class TimetableTest : BaseLocalTest() {
private val timetable by lazy { MobileRepository(getRetrofit().create()) }
@Test
fun getTimetable() {
server.enqueueAndStart("PlanLekcji.json")
val items = timetable.getTimetable(of(2020, 1, 10), of(2020, 2, 11), 1, 2, 3).blockingGet()
assertEquals(5, items.size)
}
}

View file

@ -1,911 +0,0 @@
{
"Status": "Ok",
"TimeKey": 1579118032,
"TimeValue": "Wed, 15 Jan 2020 19:53:51 GMT",
"RequestId": "38af6dfe-cd51-4b74-b7d3-52f764b48d85",
"DayOfWeek": 3,
"AppVersion": "17.09.0009.26859",
"Data": {
"TimeKey": 1579118032,
"Nauczyciele": [
{
"Id": 1,
"Imie": "Karolina",
"Nazwisko": "Kowalska",
"Kod": "AN",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 100
},
{
"Id": 2,
"Imie": "Zofia",
"Nazwisko": "Czerwińska",
"Kod": "NA",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 101
},
{
"Id": 3,
"Imie": "Aleksandra",
"Nazwisko": "Krajewska",
"Kod": "AK",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 102
},
{
"Id": 4,
"Imie": "Stanisław",
"Nazwisko": "Krupa",
"Kod": "BS",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 103
},
{
"Id": 5,
"Imie": "Aleksandra",
"Nazwisko": "Wójtowicz",
"Kod": "AW",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 104
},
{
"Id": 6,
"Imie": "Sara",
"Nazwisko": "Wierzbicka",
"Kod": "KB",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 105
},
{
"Id": 7,
"Imie": "Mateusz",
"Nazwisko": "Kowal",
"Kod": "MK",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 106
},
{
"Id": 8,
"Imie": "Amelia",
"Nazwisko": "Mazur",
"Kod": "AM",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 107
},
{
"Id": 9,
"Imie": "Barbara",
"Nazwisko": "Markowska",
"Kod": "BM",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 108
},
{
"Id": 10,
"Imie": "Michał",
"Nazwisko": "Mazur",
"Kod": "MM",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 109
}
],
"Pracownicy": [
{
"Id": 1,
"Imie": "Karolina",
"Nazwisko": "Kowalska",
"Kod": "AN",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 100
},
{
"Id": 2,
"Imie": "Zofia",
"Nazwisko": "Czerwińska",
"Kod": "NA",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 101
},
{
"Id": 3,
"Imie": "Aleksandra",
"Nazwisko": "Krajewska",
"Kod": "AK",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 102
},
{
"Id": 4,
"Imie": "Stanisław",
"Nazwisko": "Krupa",
"Kod": "BS",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 103
},
{
"Id": 5,
"Imie": "Aleksandra",
"Nazwisko": "Wójtowicz",
"Kod": "AW",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 104
},
{
"Id": 6,
"Imie": "Sara",
"Nazwisko": "Wierzbicka",
"Kod": "KB",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 105
},
{
"Id": 7,
"Imie": "Mateusz",
"Nazwisko": "Kowal",
"Kod": "MK",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 106
},
{
"Id": 8,
"Imie": "Amelia",
"Nazwisko": "Mazur",
"Kod": "AM",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 107
},
{
"Id": 9,
"Imie": "Barbara",
"Nazwisko": "Markowska",
"Kod": "BM",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 108
},
{
"Id": 10,
"Imie": "Michał",
"Nazwisko": "Mazur",
"Kod": "MM",
"Aktywny": true,
"Nauczyciel": true,
"LoginId": 109
}
],
"Przedmioty": [
{
"Id": 300,
"Nazwa": "Zajęcia z wychowawcą",
"Kod": "godz.wych",
"Aktywny": true,
"Pozycja": 0
},
{
"Id": 301,
"Nazwa": "Język polski",
"Kod": "j. polski",
"Aktywny": true,
"Pozycja": 3
},
{
"Id": 302,
"Nazwa": "Historia",
"Kod": "historia",
"Aktywny": true,
"Pozycja": 1
},
{
"Id": 303,
"Nazwa": "Etyka",
"Kod": "etyka",
"Aktywny": true,
"Pozycja": 2
},
{
"Id": 304,
"Nazwa": "Język angielski",
"Kod": "j. angielski",
"Aktywny": true,
"Pozycja": 4
},
{
"Id": 305,
"Nazwa": "Język niemiecki",
"Kod": "j. niemiecki",
"Aktywny": true,
"Pozycja": 5
},
{
"Id": 306,
"Nazwa": "Metodologia programowania",
"Kod": "metod.programowania",
"Aktywny": true,
"Pozycja": 6
},
{
"Id": 307,
"Nazwa": "Matematyka",
"Kod": "matematyka",
"Aktywny": true,
"Pozycja": 7
},
{
"Id": 308,
"Nazwa": "Fizyka",
"Kod": "fizyka",
"Aktywny": true,
"Pozycja": 8
},
{
"Id": 309,
"Nazwa": "Chemia",
"Kod": "chemia",
"Aktywny": true,
"Pozycja": 9
},
{
"Id": 310,
"Nazwa": "Biologia",
"Kod": "biologia",
"Aktywny": true,
"Pozycja": 10
},
{
"Id": 311,
"Nazwa": "Geografia",
"Kod": "geografia",
"Aktywny": true,
"Pozycja": 11
},
{
"Id": 312,
"Nazwa": "Informatyka",
"Kod": "informatyka",
"Aktywny": true,
"Pozycja": 12
},
{
"Id": 313,
"Nazwa": "Religia",
"Kod": "religia",
"Aktywny": true,
"Pozycja": 13
}
],
"PoryLekcji": [
{
"Id": 76,
"Numer": 1,
"Poczatek": 25200,
"PoczatekTekst": "08:00",
"Koniec": 27900,
"KoniecTekst": "08:45"
},
{
"Id": 77,
"Numer": 2,
"Poczatek": 28500,
"PoczatekTekst": "08:55",
"Koniec": 31200,
"KoniecTekst": "09:40"
},
{
"Id": 78,
"Numer": 3,
"Poczatek": 31800,
"PoczatekTekst": "09:50",
"Koniec": 34500,
"KoniecTekst": "10:35"
},
{
"Id": 79,
"Numer": 4,
"Poczatek": 35100,
"PoczatekTekst": "10:45",
"Koniec": 37800,
"KoniecTekst": "11:30"
},
{
"Id": 80,
"Numer": 5,
"Poczatek": 38400,
"PoczatekTekst": "11:40",
"Koniec": 41100,
"KoniecTekst": "12:25"
},
{
"Id": 81,
"Numer": 6,
"Poczatek": 42300,
"PoczatekTekst": "12:45",
"Koniec": 45000,
"KoniecTekst": "13:30"
},
{
"Id": 82,
"Numer": 7,
"Poczatek": 45600,
"PoczatekTekst": "13:40",
"Koniec": 48300,
"KoniecTekst": "14:25"
},
{
"Id": 83,
"Numer": 8,
"Poczatek": 48600,
"PoczatekTekst": "14:30",
"Koniec": 51300,
"KoniecTekst": "15:15"
},
{
"Id": 84,
"Numer": 9,
"Poczatek": 51600,
"PoczatekTekst": "15:20",
"Koniec": 54300,
"KoniecTekst": "16:05"
},
{
"Id": 85,
"Numer": 10,
"Poczatek": 54600,
"PoczatekTekst": "16:10",
"Koniec": 57300,
"KoniecTekst": "16:55"
},
{
"Id": 86,
"Numer": 11,
"Poczatek": 57600,
"PoczatekTekst": "17:00",
"Koniec": 60300,
"KoniecTekst": "17:45"
},
{
"Id": 87,
"Numer": 12,
"Poczatek": 60600,
"PoczatekTekst": "17:50",
"Koniec": 63300,
"KoniecTekst": "18:35"
}
],
"KategorieOcen": [
{
"Id": 26,
"Kod": "Akt",
"Nazwa": "A - aktywność (czarny)"
},
{
"Id": 27,
"Kod": "Bież",
"Nazwa": "B - bieżące (fiol)"
},
{
"Id": 28,
"Kod": "Kart",
"Nazwa": "K - kartkówka (zielony)"
},
{
"Id": 29,
"Kod": "Spr",
"Nazwa": "S - sprawdzian (czerwony)"
},
{
"Id": 30,
"Kod": "Z.dom",
"Nazwa": "Zd - zadanie domowe (czarny)"
},
{
"Id": 65,
"Kod": "odp",
"Nazwa": "OD - odpowiedź ustna (nieb)"
},
{
"Id": 67,
"Kod": "ref",
"Nazwa": "Referat"
},
{
"Id": 68,
"Kod": "zewn",
"Nazwa": "Sprawdzian zewnętrzny"
},
{
"Id": 69,
"Kod": "tsm",
"Nazwa": "Test sprawności motorycznej"
},
{
"Id": 70,
"Kod": "tu",
"Nazwa": "Test umiejętności"
},
{
"Id": 71,
"Kod": "zs",
"Nazwa": "Zawody sportowe"
},
{
"Id": 72,
"Kod": "bs",
"Nazwa": "Brak stroju"
},
{
"Id": 73,
"Kod": "r",
"Nazwa": "Rozgrzewka"
},
{
"Id": 74,
"Kod": "pr_dł",
"Nazwa": "Praca długoterminowa"
},
{
"Id": 75,
"Kod": "ze_ćwi",
"Nazwa": "Zeszyt ćwiczeń"
},
{
"Id": 76,
"Kod": "Inne",
"Nazwa": "Inne"
},
{
"Id": 77,
"Kod": "popspr",
"Nazwa": "Poprawa sprawdzianu"
},
{
"Id": 78,
"Kod": "PK",
"Nazwa": "Praca klasowa"
},
{
"Id": 79,
"Kod": "Re",
"Nazwa": "Recytacja"
},
{
"Id": 80,
"Kod": "dyk",
"Nazwa": "Dyktando"
},
{
"Id": 81,
"Kod": "lek",
"Nazwa": "Lektura"
},
{
"Id": 82,
"Kod": "sp_wiedzy",
"Nazwa": "Sprawdzian wiedzy"
},
{
"Id": 83,
"Kod": "egz_próbny",
"Nazwa": "Egzamin próbny"
}
],
"KategorieUwag": [
{
"Id": 46,
"Nazwa": "Wypełnianie obowiązków ucznia",
"Aktywny": false
},
{
"Id": 47,
"Nazwa": "Zaangażowanie społeczne",
"Aktywny": false
},
{
"Id": 48,
"Nazwa": "Kultura języka",
"Aktywny": false
},
{
"Id": 49,
"Nazwa": "Kultura osobista",
"Aktywny": false
},
{
"Id": 50,
"Nazwa": "Dbałość o bezpieczeństwo i zdrowie",
"Aktywny": false
},
{
"Id": 51,
"Nazwa": "Szacunek dla innych osób",
"Aktywny": false
},
{
"Id": 52,
"Nazwa": "Zachowanie norm etycznych",
"Aktywny": false
},
{
"Id": 53,
"Nazwa": "Reprezentowanie szkoły",
"Aktywny": false
},
{
"Id": 54,
"Nazwa": "Zachowanie na lekcji",
"Aktywny": false
},
{
"Id": 58,
"Nazwa": "Inne (informacja bez punktów)",
"Aktywny": true
},
{
"Id": 59,
"Nazwa": "Udział w konkursie szkolnym +20 pkt",
"Aktywny": false
},
{
"Id": 61,
"Nazwa": "Przeszkadzanie na lekcjach -5 pkt",
"Aktywny": false
},
{
"Id": 66,
"Nazwa": "+ Udział w olimpiadzie przedmiotowej i konkursach pozaszk. (rza w sem. 20-30-50)",
"Aktywny": true
},
{
"Id": 67,
"Nazwa": "+ Udział w konkursie szkolnym (0-20)",
"Aktywny": true
},
{
"Id": 68,
"Nazwa": "+ Funkcja w szkole (0-20)",
"Aktywny": true
},
{
"Id": 69,
"Nazwa": "+ Funkcja w klasie (0-30)",
"Aktywny": true
},
{
"Id": 70,
"Nazwa": "+ Reprezentowanie szkoły w rozgrywkach sport.( raz w sem. 0-100)",
"Aktywny": true
},
{
"Id": 71,
"Nazwa": "+ Pomoc podczas imprezy szkolnej (0-10)",
"Aktywny": false
},
{
"Id": 72,
"Nazwa": "+ Praca na rzecz klasy (0-20)",
"Aktywny": true
},
{
"Id": 73,
"Nazwa": "+ Praca na rzecz szkoły (0-20)",
"Aktywny": true
},
{
"Id": 74,
"Nazwa": "+ Punktualność (0-20)",
"Aktywny": true
},
{
"Id": 75,
"Nazwa": "+ Pomoc kolegom (0-10)",
"Aktywny": true
},
{
"Id": 76,
"Nazwa": "+ Kulturalne zachowanie się w szkole i poza nią (0-50)",
"Aktywny": false
},
{
"Id": 77,
"Nazwa": "+ Przeciwstawianie się przejawom agresji i wulgarności (0-20)",
"Aktywny": false
},
{
"Id": 79,
"Nazwa": "+ Do dyspozycji wychowawcy (0-50)",
"Aktywny": true
},
{
"Id": 80,
"Nazwa": "+ Realizacja projektu edukacyjnego (0-50)",
"Aktywny": true
},
{
"Id": 81,
"Nazwa": "- Przeszkadzanie na lekcjach -5p.",
"Aktywny": true
},
{
"Id": 82,
"Nazwa": "- Okłamywanie i oszukiwanie nauczyciela 20p.",
"Aktywny": true
},
{
"Id": 83,
"Nazwa": "- Niewykonywanie poleceń nauczyciela (10-20)",
"Aktywny": true
},
{
"Id": 84,
"Nazwa": "- Aroganckie zachowanie wobec nauczyciela lub pracownika szkoły -50p.",
"Aktywny": true
},
{
"Id": 85,
"Nazwa": "- Ubliżanie kolegom/koleżankom (10-30)",
"Aktywny": true
},
{
"Id": 86,
"Nazwa": "- Przemoc fizyczna (10-30)",
"Aktywny": true
},
{
"Id": 87,
"Nazwa": "- Wulgarne słownictwo (10-30)",
"Aktywny": true
},
{
"Id": 88,
"Nazwa": "- Opuszczanie terenu szkoły w czasie zajęć -10p.",
"Aktywny": true
},
{
"Id": 89,
"Nazwa": "- Niszczenie mienia (10-30)",
"Aktywny": true
},
{
"Id": 90,
"Nazwa": "- Zaśmiecanie otoczenia (5-10)",
"Aktywny": true
},
{
"Id": 91,
"Nazwa": "- Strój i wygląd niezgodny z regulaminem ucznia (2-20)",
"Aktywny": true
},
{
"Id": 92,
"Nazwa": "- Spóźnienia się na lekcję do 10 min. (3p.)",
"Aktywny": true
},
{
"Id": 93,
"Nazwa": "- Niewykonywanie zobowiązania (10-20)",
"Aktywny": true
},
{
"Id": 94,
"Nazwa": "- Nieusprawiedliwiona nieobecność (5p.)",
"Aktywny": true
},
{
"Id": 95,
"Nazwa": "- Wyłudzanie pieniędzy (50p.)",
"Aktywny": true
},
{
"Id": 96,
"Nazwa": "- Kradzież (50p.)",
"Aktywny": true
},
{
"Id": 97,
"Nazwa": "- Palenie papierosów (50p.)",
"Aktywny": true
},
{
"Id": 98,
"Nazwa": "- Picie alkoholu (50p.)",
"Aktywny": true
},
{
"Id": 99,
"Nazwa": "- Stosowanie środków odurzających (50p.)",
"Aktywny": true
},
{
"Id": 100,
"Nazwa": "- Korzystanie z tel. kom. i urz. elek. niezgodnie z regulaminem (5-20)",
"Aktywny": true
},
{
"Id": 101,
"Nazwa": "- Drastyczne naruszenie ogólnie przyjętych norm społ. (100-250)",
"Aktywny": true
}
],
"KategorieFrekwencji": [
{
"Id": 1,
"Nazwa": "obecność",
"Pozycja": 1000,
"Obecnosc": true,
"Nieobecnosc": false,
"Zwolnienie": false,
"Spoznienie": false,
"Usprawiedliwione": false,
"Usuniete": false
},
{
"Id": 2,
"Nazwa": "nieobecność nieusprawiedliwiona",
"Pozycja": 1000,
"Obecnosc": false,
"Nieobecnosc": true,
"Zwolnienie": false,
"Spoznienie": false,
"Usprawiedliwione": false,
"Usuniete": false
},
{
"Id": 3,
"Nazwa": "nieobecność usprawiedliwiona",
"Pozycja": 1000,
"Obecnosc": false,
"Nieobecnosc": true,
"Zwolnienie": false,
"Spoznienie": false,
"Usprawiedliwione": true,
"Usuniete": false
},
{
"Id": 4,
"Nazwa": "spóźnienie nieusprawiedliwione",
"Pozycja": 1000,
"Obecnosc": true,
"Nieobecnosc": false,
"Zwolnienie": false,
"Spoznienie": true,
"Usprawiedliwione": false,
"Usuniete": false
},
{
"Id": 5,
"Nazwa": "spóźnienie usprawiedliwione",
"Pozycja": 1000,
"Obecnosc": true,
"Nieobecnosc": false,
"Zwolnienie": false,
"Spoznienie": true,
"Usprawiedliwione": true,
"Usuniete": false
},
{
"Id": 6,
"Nazwa": "nieobecny z przyczyn szkolnych",
"Pozycja": 1000,
"Obecnosc": true,
"Nieobecnosc": false,
"Zwolnienie": false,
"Spoznienie": false,
"Usprawiedliwione": false,
"Usuniete": false
},
{
"Id": 7,
"Nazwa": "zwolniony",
"Pozycja": 1000,
"Obecnosc": false,
"Nieobecnosc": false,
"Zwolnienie": true,
"Spoznienie": false,
"Usprawiedliwione": false,
"Usuniete": false
},
{
"Id": 8,
"Nazwa": "usunięty wpis",
"Pozycja": 1000,
"Obecnosc": false,
"Nieobecnosc": false,
"Zwolnienie": false,
"Spoznienie": false,
"Usprawiedliwione": false,
"Usuniete": true
}
],
"TypyFrekwencji": [
{
"Id": 40,
"Symbol": "●",
"Nazwa": "obecność",
"Aktywny": true,
"WpisDomyslny": true,
"IdKategoriaFrek": 1
},
{
"Id": 41,
"Symbol": "—",
"Nazwa": "nieobecność",
"Aktywny": true,
"WpisDomyslny": false,
"IdKategoriaFrek": 2
},
{
"Id": 42,
"Symbol": "u",
"Nazwa": "nieob. uspraw.",
"Aktywny": true,
"WpisDomyslny": false,
"IdKategoriaFrek": 3
},
{
"Id": 43,
"Symbol": "s",
"Nazwa": "spóźnienie",
"Aktywny": true,
"WpisDomyslny": false,
"IdKategoriaFrek": 4
},
{
"Id": 44,
"Symbol": "su",
"Nazwa": "spóźn. uspr.",
"Aktywny": true,
"WpisDomyslny": false,
"IdKategoriaFrek": 5
},
{
"Id": 45,
"Symbol": "ns",
"Nazwa": "nieob. uspr. p.s.",
"Aktywny": true,
"WpisDomyslny": false,
"IdKategoriaFrek": 6
},
{
"Id": 46,
"Symbol": "z",
"Nazwa": "zwolniony",
"Aktywny": true,
"WpisDomyslny": false,
"IdKategoriaFrek": 7
},
{
"Id": 47,
"Symbol": "",
"Nazwa": "usunięty wpis",
"Aktywny": true,
"WpisDomyslny": false,
"IdKategoriaFrek": 8
},
{
"Id": 55,
"Symbol": "zr",
"Nazwa": "zwolniony przez rodzica",
"Aktywny": false,
"WpisDomyslny": false,
"IdKategoriaFrek": 3
}
]
}
}

View file

@ -1,52 +0,0 @@
{
"Status": "Ok",
"TimeKey": 1579113877,
"TimeValue": "Wed, 15 Jan 2020 18:44:36 GMT",
"RequestId": "79ff96b3-5c63-4b03-9922-b5e22ed3ba6f",
"DayOfWeek": 3,
"AppVersion": "17.09.0009.26859",
"Data": [
{
"Id": 2740,
"IdPrzedmiot": 118,
"IdPracownik": 94,
"IdOddzial": 52,
"IdPodzial": null,
"PodzialNazwa": null,
"PodzialSkrot": null,
"Rodzaj": true,
"RodzajNumer": 1,
"Opis": "Bajki - Ignacy Krasicki",
"Data": 1579215600,
"DataTekst": "2020-01-17"
},
{
"Id": 2741,
"IdPrzedmiot": 118,
"IdPracownik": 94,
"IdOddzial": 52,
"IdPodzial": null,
"PodzialNazwa": null,
"PodzialSkrot": null,
"Rodzaj": false,
"RodzajNumer": 2,
"Opis": "Epopeja - Pan Tadeusz",
"Data": 1579215600,
"DataTekst": "2020-01-17"
},
{
"Id": 2742,
"IdPrzedmiot": 118,
"IdPracownik": 94,
"IdOddzial": 52,
"IdPodzial": null,
"PodzialNazwa": null,
"PodzialSkrot": null,
"Rodzaj": false,
"RodzajNumer": 3,
"Opis": "Wielki Poeta - Słowacki",
"Data": 1579215600,
"DataTekst": "2020-01-17"
}
]
}

View file

@ -1,54 +0,0 @@
{
"Status": "Ok",
"TimeKey": 1580410527,
"TimeValue": "Thu, 30 Jan 2020 18:55:27 GMT",
"RequestId": "090cdefc-64a7-4a06-908c-d12703a5f465",
"DayOfWeek": 4,
"AppVersion": "17.09.0009.26859",
"Data": [
{
"Id": 1000,
"Pozycja": 1,
"PrzedmiotPozycja": 1,
"IdPrzedmiot": 300,
"IdKategoria": 26,
"Wpis": "3",
"Wartosc": 3,
"WagaModyfikatora": null,
"WagaOceny": 5,
"Licznik": null,
"Mianownik": null,
"Komentarz": null,
"Waga": "5,00",
"Opis": "Aktywność",
"DataUtworzenia": 1536883200,
"DataUtworzeniaTekst": "2018-09-14",
"DataModyfikacji": 1536883200,
"DataModyfikacjiTekst": "2018-09-14",
"IdPracownikD": 1,
"IdPracownikM": 1
},
{
"Id": 1001,
"Pozycja": 3,
"PrzedmiotPozycja": 8,
"IdPrzedmiot": 300,
"IdKategoria": 26,
"Wpis": "4",
"Wartosc": 4,
"WagaModyfikatora": null,
"WagaOceny": 5,
"Licznik": null,
"Mianownik": null,
"Komentarz": null,
"Waga": "5,00",
"Opis": "Aktywność",
"DataUtworzenia": 1538179200,
"DataUtworzeniaTekst": "2018-09-29",
"DataModyfikacji": 1538179200,
"DataModyfikacjiTekst": "2018-09-29",
"IdPracownikD": 1,
"IdPracownikM": 1
}
]
}

View file

@ -1,32 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>UONET+ dla urządzeń mobilnych</title>
<link href="https://lekcjaplus.vulcan.net.pl/Content/mobile.css?v=5" rel="stylesheet" type="text/css" />
</head>
<body>
<a href="http://lekcjaplus.vulcan.net.pl/mobile/mobile/" class="pageHeader">
<div>Witamy w systemie UONET+ dla urządzeń mobilnych</div>
</a>
<div class="pageBlock">
<script type="text/mobile-api-data" id="AppVersion">19.11.0002.35804</script>
<div class="block">
<div class="blockInner">
<div style="font-weight: bold;">Podany symbol grupujący jest nieprawidłowy</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -1,41 +0,0 @@
{
"Status": "Ok",
"TimeKey": 1579185018,
"TimeValue": "Thu, 16 Jan 2020 14:30:18 GMT",
"RequestId": "1799be6b-7a60-4665-b75c-1bca504e8ebd",
"DayOfWeek": 4,
"AppVersion": "17.09.0009.26859",
"Data": [
{
"IdOkresKlasyfikacyjny": 12,
"OkresPoziom": 4,
"OkresNumer": 1,
"OkresDataOd": 1567296000,
"OkresDataDo": 1580256000,
"OkresDataOdTekst": "2019-09-01",
"OkresDataDoTekst": "2020-01-29",
"IdJednostkaSprawozdawcza": 6,
"JednostkaSprawozdawczaSkrot": "Fake123456",
"JednostkaSprawozdawczaNazwa": "Fakelog public diary nr 1",
"JednostkaSprawozdawczaSymbol": "123456",
"IdJednostka": 0,
"JednostkaNazwa": "Publiczna szkoła Wulkanowego nr 1 w fakelog.cf",
"JednostkaSkrot": "Fake123456",
"OddzialSymbol": "A",
"OddzialKod": "4A",
"UzytkownikRola": "uczeń",
"UzytkownikLogin": "jan@fakelog.cf",
"UzytkownikLoginId": 1,
"UzytkownikNazwa": "Jan Kowalski",
"Id": 1,
"IdOddzial": 1,
"Imie": "Jan",
"Imie2": "Marek",
"Nazwisko": "Kowalski",
"Pseudonim": "",
"UczenPlec": 1,
"Pozycja": 0,
"LoginId": null
}
]
}

View file

@ -1,72 +0,0 @@
{
"Status": "Ok",
"TimeKey": 1579185018,
"TimeValue": "Thu, 16 Jan 2020 14:30:18 GMT",
"RequestId": "1799be6b-7a60-4665-b75c-1bca504e8ebd",
"DayOfWeek": 4,
"AppVersion": "17.09.0009.26859",
"Data": [
{
"IdOkresKlasyfikacyjny": 12,
"OkresPoziom": 4,
"OkresNumer": 2,
"OkresDataOd": 1580342400,
"OkresDataDo": 1598832000,
"OkresDataOdTekst": "2020-01-30",
"OkresDataDoTekst": "2020-08-31",
"IdJednostkaSprawozdawcza": 6,
"JednostkaSprawozdawczaSkrot": "Fake123456",
"JednostkaSprawozdawczaNazwa": "Fakelog public diary nr 1",
"JednostkaSprawozdawczaSymbol": "123456",
"IdJednostka": 0,
"JednostkaNazwa": "Publiczna szkoła Wulkanowego nr 1 w fakelog.cf",
"JednostkaSkrot": "Fake123456",
"OddzialSymbol": "A",
"OddzialKod": "4A",
"UzytkownikRola": "uczeń",
"UzytkownikLogin": "jan@fakelog.cf",
"UzytkownikLoginId": 2,
"UzytkownikNazwa": "Joanna Czerwińska",
"Id": 2,
"IdOddzial": 2,
"Imie": "Joanna",
"Imie2": "Maria",
"Nazwisko": "Czerwińska",
"Pseudonim": "",
"UczenPlec": 0,
"Pozycja": 0,
"LoginId": null
},
{
"IdOkresKlasyfikacyjny": 12,
"OkresPoziom": 4,
"OkresNumer": 2,
"OkresDataOd": 1580342400,
"OkresDataDo": 1598832000,
"OkresDataOdTekst": "2020-01-30",
"OkresDataDoTekst": "2020-08-31",
"IdJednostkaSprawozdawcza": 6,
"JednostkaSprawozdawczaSkrot": "Fake123456",
"JednostkaSprawozdawczaNazwa": "Fakelog public diary nr 1",
"JednostkaSprawozdawczaSymbol": "123456",
"IdJednostka": 0,
"JednostkaNazwa": "Publiczna szkoła Wulkanowego nr 1 w fakelog.cf",
"JednostkaSkrot": "Fake123456",
"OddzialSymbol": "A",
"OddzialKod": "4A",
"UzytkownikRola": "uczeń",
"UzytkownikLogin": "jan@fakelog.cf",
"UzytkownikLoginId": 1,
"UzytkownikNazwa": "Jan Kowalski",
"Id": 1,
"IdOddzial": 1,
"Imie": "Jan",
"Imie2": "Marek",
"Nazwisko": "Kowalski",
"Pseudonim": "",
"UczenPlec": 1,
"Pozycja": 0,
"LoginId": null
}
]
}

View file

@ -1,11 +0,0 @@
3S1,https://lekcjaplus.vulcan.net.pl
TA1,https://uonetplus-komunikacja.umt.tarnow.pl
OP1,https://uonetplus-komunikacja.eszkola.opolskie.pl
RZ1,https://uonetplus-komunikacja.resman.pl
GD1,https://uonetplus-komunikacja.edu.gdansk.pl
KA1,https://uonetplus-komunikacja.mcuw.katowice.eu
KA2,https://uonetplus-komunikacja-test.mcuw.katowice.eu
P03,https://efeb-komunikacja-pro-efebmobile.pro.vulcan.pl
P01,http://efeb-komunikacja.pro-hudson.win.vulcan.pl
P02,http://efeb-komunikacja.pro-hudsonrc.win.vulcan.pl
P90,http://efeb-komunikacja-pro-mwujakowska.neo.win.vulcan.pl

View file

@ -1,105 +0,0 @@
{
"Status": "Ok",
"TimeKey": 1581205518,
"TimeValue": "Sat, 08 Feb 2020 23:45:17 GMT",
"RequestId": "8f8b7d7f-cd4b-4fa5-b662-c5be2a82af54",
"DayOfWeek": 6,
"AppVersion": "17.09.0009.26859",
"Data": [
{
"Dzien": 1580688000,
"DzienTekst": "2020-02-03",
"NumerLekcji": 1,
"IdPoraLekcji": 76,
"IdPrzedmiot": 308,
"PrzedmiotNazwa": "Fizyka",
"PodzialSkrot": null,
"Sala": "213",
"IdPracownik": 1,
"IdPracownikWspomagajacy": null,
"IdPracownikOld": null,
"IdPracownikWspomagajacyOld": null,
"IdPlanLekcji": 23,
"AdnotacjaOZmianie": "",
"PrzekreslonaNazwa": false,
"PogrubionaNazwa": false,
"PlanUcznia": true
},
{
"Dzien": 1580688000,
"DzienTekst": "2020-02-03",
"NumerLekcji": 2,
"IdPoraLekcji": 77,
"IdPrzedmiot": 300,
"PrzedmiotNazwa": "Sieci komputerowe",
"PodzialSkrot": "t.infor",
"Sala": "G1",
"IdPracownik": 4,
"IdPracownikWspomagajacy": null,
"IdPracownikOld": null,
"IdPracownikWspomagajacyOld": null,
"IdPlanLekcji": 4,
"AdnotacjaOZmianie": "(przeniesiona z lekcji 1, 10.02.2020)",
"PrzekreslonaNazwa": false,
"PogrubionaNazwa": true,
"PlanUcznia": true
},
{
"Dzien": 1580688000,
"DzienTekst": "2020-02-03",
"NumerLekcji": 2,
"IdPoraLekcji": 77,
"IdPrzedmiot": 499,
"PrzedmiotNazwa": "Wychowanie fizyczne",
"PodzialSkrot": "wf_grupa_2",
"Sala": "S4",
"IdPracownik": 7,
"IdPracownikWspomagajacy": null,
"IdPracownikOld": 5,
"IdPracownikWspomagajacyOld": null,
"IdPlanLekcji": 46,
"AdnotacjaOZmianie": "(zastępstwo: Anon Gałecki, sala S4)",
"PrzekreslonaNazwa": true,
"PogrubionaNazwa": false,
"PlanUcznia": true
},
{
"Dzien": 1580688000,
"DzienTekst": "2020-02-03",
"NumerLekcji": 3,
"IdPoraLekcji": 78,
"IdPrzedmiot": 499,
"PrzedmiotNazwa": "Wychowanie fizyczne",
"PodzialSkrot": "wf_grupa_2",
"Sala": "S4",
"IdPracownik": 7,
"IdPracownikWspomagajacy": null,
"IdPracownikOld": 5,
"IdPracownikWspomagajacyOld": null,
"IdPlanLekcji": 47,
"AdnotacjaOZmianie": "(zastępstwo: Anon Gałecki, sala S4)",
"PrzekreslonaNazwa": false,
"PogrubionaNazwa": false,
"PlanUcznia": true
},
{
"Dzien": 1582239600,
"DzienTekst": "2020-02-03",
"NumerLekcji": 4,
"IdPoraLekcji": 79,
"IdPrzedmiot": 311,
"PrzedmiotNazwa": "Geografia",
"PodzialSkrot": null,
"Sala": "A215",
"IdPracownik": 10,
"IdPracownikWspomagajacy": null,
"IdPracownikOld": 5,
"IdPracownikWspomagajacyOld": null,
"IdPlanLekcji": 42,
"AdnotacjaOZmianie": "(nieobecny oddział - Zwiedzanie Muzeum II Wojny Światowej w Gdańsku.)",
"PrzekreslonaNazwa": true,
"PogrubionaNazwa": false,
"PlanUcznia": true
}
]
}

Some files were not shown because too many files have changed in this diff Show more