This commit is contained in:
Dominic Grimm 2023-02-28 12:16:33 +01:00
parent c9b11aa165
commit 288b6e9ec4
No known key found for this signature in database
GPG key ID: 6F294212DEAAC530
12 changed files with 119 additions and 101 deletions

View file

@ -4,12 +4,12 @@ POSTGRES_PASSWORD="bvplan"
RABBITMQ_USER="bvplan"
RABBITMQ_PASSWORD="bvplan"
BACKEND_UNTIS_API_URL="https://mese.webuntis.com/WebUntis/"
BACKEND_UNTIS_RPC_URL="https://mese.webuntis.com/WebUntis/jsonrpc.do"
BACKEND_UNTIS_CLIENT_NAME="bvplan"
BACKEND_UNTIS_SCHOOL=
BACKEND_UNTIS_USERNAME=
BACKEND_UNTIS_PASSWORD=
BACKEND_UNTIS_VPLAN_URL=
BACKEND_UNTIS_VPLAN_USERNAME=
BACKEND_UNTIS_VPLAN_PASSWORD=
BVPLAN_UNTIS_API_URL="https://mese.webuntis.com/WebUntis/"
BVPLAN_UNTIS_RPC_URL="https://mese.webuntis.com/WebUntis/jsonrpc.do"
BVPLAN_UNTIS_CLIENT_NAME="bvplan"
BVPLAN_UNTIS_SCHOOL=
BVPLAN_UNTIS_USERNAME=
BVPLAN_UNTIS_PASSWORD=
BVPLAN_UNTIS_VPLAN_URL=
BVPLAN_UNTIS_VPLAN_USERNAME=
BVPLAN_UNTIS_VPLAN_PASSWORD=

View file

@ -8,6 +8,7 @@ RUN find . -name "*.scss" -type f | xargs -I % sh -c 'sassc % > ../dist/$(basena
FROM tdewolff/minify:latest as static
WORKDIR /usr/src/static
COPY --from=css /usr/src/scss/dist ./css
COPY ./js ./js
RUN minify . -r -o .
FROM docker.io/lukemathwalker/cargo-chef:latest-rust-1.65.0 as chef
@ -24,13 +25,13 @@ RUN cargo chef prepare --recipe-path recipe.json
FROM chef as builder
WORKDIR /usr/src/backend
COPY --from=planner /usr/src/backend/recipe.json .
RUN cargo chef cook --recipe-path recipe.json
RUN cargo chef cook --release --recipe-path recipe.json
RUN rm -rf ./src
COPY ./build.rs .
COPY --from=static /usr/src/static ./static
COPY ./templates ./templates
COPY ./src ./src
RUN cargo build
RUN cargo build --release
FROM docker.io/debian:bullseye-slim as runner
LABEL maintainer="Dominic Grimm <dominic@dergrimm.net>" \
@ -51,6 +52,6 @@ WORKDIR /usr/src/backend
COPY ./run.sh .
RUN chmod +x ./run.sh
COPY ./migrations ./migrations
COPY --from=builder /usr/src/backend/target/debug/web /usr/src/backend/target/debug/worker ./bin/
COPY --from=builder /usr/src/backend/target/release/web /usr/src/backend/target/release/worker ./bin/
EXPOSE 80
ENTRYPOINT [ "./run.sh" ]

43
bvplan/js/bvplan.js Normal file
View file

@ -0,0 +1,43 @@
window.onerror = function () {
console.log("js error detected");
setTimeout(function () {
console.log("reloading page because of error");
window.location.reload();
}, 30_000);
};
const elementCount = JSON.parse($("#data-element-count").text());
const waitDelay = 10_000;
const scrollDuration = elementCount * 200;
function reload() {
window.location.reload();
}
function scrollUp() {
$("html, body").animate(
{
scrollTop: 0,
},
scrollDuration,
"linear"
);
setTimeout(reload, scrollDuration);
}
function scrollDown() {
$("html, body").animate(
{
scrollTop: $(document).height() - $(window).height(),
},
scrollDuration,
"linear"
);
setTimeout(scrollUp, scrollDuration + waitDelay);
}
window.scrollTo(0, 0);
setTimeout(
$(document).height() > $(window).height() ? scrollDown : reload,
waitDelay
);

View file

@ -98,5 +98,9 @@ body {
.element {
margin: 0.5rem 0;
&:last-of-type {
margin-bottom: 0;
}
}
}

View file

@ -11,7 +11,6 @@ use r2d2_redis::redis;
use std::ops::DerefMut;
use bvplan::*;
use templates::TemplateToResponseWithStatusCode;
pub mod static_dir {
include!(concat!(env!("OUT_DIR"), "/generated.rs"));
@ -22,14 +21,20 @@ async fn not_found() -> HttpResponse {
status_code: http::StatusCode::NOT_FOUND,
message: None,
}
.to_response_with_status_code(http::StatusCode::NOT_FOUND)
.to_response()
}
#[get("/")]
async fn index(redis_pool: web::Data<cache::RedisPool>) -> HttpResponse {
let redis_conn = &mut match redis_pool.get() {
Ok(x) => x,
Err(_) => return HttpResponse::InternalServerError().finish(),
Err(_) => {
return templates::StatusCode {
status_code: http::StatusCode::INTERNAL_SERVER_ERROR,
message: None,
}
.to_response()
}
};
if let Some(html) = match redis::cmd("GET")
@ -37,13 +42,23 @@ async fn index(redis_pool: web::Data<cache::RedisPool>) -> HttpResponse {
.query::<Option<String>>(redis_conn.deref_mut())
{
Ok(x) => x,
Err(_) => return HttpResponse::InternalServerError().finish(),
Err(_) => {
return templates::StatusCode {
status_code: http::StatusCode::INTERNAL_SERVER_ERROR,
message: None,
}
.to_response()
}
} {
HttpResponse::Accepted()
.content_type("text/html; charset=utf-8")
.body(html)
} else {
HttpResponse::InternalServerError().finish()
templates::StatusCode {
status_code: http::StatusCode::INTERNAL_SERVER_ERROR,
message: None,
}
.to_response()
}
}

View file

@ -17,19 +17,12 @@ async fn main() {
worker::init_blocking();
thread::spawn(|| {
tokio::runtime::Runtime::new().unwrap().block_on(async {
worker::beat()
.await
.unwrap()
.start()
.await
.unwrap();
worker::beat().await.unwrap().start().await.unwrap();
});
});
let app = worker::APP.lock().unwrap();
let app = app.as_ref().unwrap();
app.display_pretty().await;
app.consume_from(&[worker::QUEUE_NAME])
.await
.unwrap();
app.consume_from(&[worker::QUEUE_NAME]).await.unwrap();
}

View file

@ -5,40 +5,40 @@ use url::Url;
#[derive(Envconfig, Debug)]
pub struct Config {
#[envconfig(from = "BACKEND_DB_URL")]
#[envconfig(from = "BVPLAN_DB_URL")]
pub db_url: String,
#[envconfig(from = "BACKEND_AMQP_URL")]
#[envconfig(from = "BVPLAN_AMQP_URL")]
pub amqp_url: String,
#[envconfig(from = "BACKEND_REDIS_URL")]
#[envconfig(from = "BVPLAN_REDIS_URL")]
pub redis_url: String,
#[envconfig(from = "BACKEND_UNTIS_API_URL")]
#[envconfig(from = "BVPLAN_UNTIS_API_URL")]
pub untis_api_url: String,
#[envconfig(from = "BACKEND_UNTIS_RPC_URL")]
#[envconfig(from = "BVPLAN_UNTIS_RPC_URL")]
pub untis_rpc_url: String,
#[envconfig(from = "BACKEND_UNTIS_CLIENT_NAME")]
#[envconfig(from = "BVPLAN_UNTIS_CLIENT_NAME")]
pub untis_client_name: String,
#[envconfig(from = "BACKEND_UNTIS_SCHOOL")]
#[envconfig(from = "BVPLAN_UNTIS_SCHOOL")]
pub untis_school: String,
#[envconfig(from = "BACKEND_UNTIS_USERNAME")]
#[envconfig(from = "BVPLAN_UNTIS_USERNAME")]
pub untis_username: String,
#[envconfig(from = "BACKEND_UNTIS_PASSWORD")]
#[envconfig(from = "BVPLAN_UNTIS_PASSWORD")]
pub untis_password: String,
#[envconfig(from = "BACKEND_UNTIS_VPLAN_URL")]
#[envconfig(from = "BVPLAN_UNTIS_VPLAN_URL")]
pub untis_vplan_url: String,
#[envconfig(from = "BACKEND_UNTIS_VPLAN_USERNAME")]
#[envconfig(from = "BVPLAN_UNTIS_VPLAN_USERNAME")]
pub untis_vplan_username: String,
#[envconfig(from = "BACKEND_UNTIS_VPLAN_PASSWORD")]
#[envconfig(from = "BVPLAN_UNTIS_VPLAN_PASSWORD")]
pub untis_vplan_password: String,
}
@ -48,15 +48,13 @@ lazy_static! {
pub fn untis_from_env() -> Result<untis::Client> {
Ok(untis::Client {
// api_url: Url::parse(&CONFIG.untis_api_url)?,
webuntis_url: Url::parse(&CONFIG.untis_api_url)?,
rpc_url: untis::Client::gen_rpc_url(
&Url::parse(&CONFIG.untis_rpc_url)?,
&CONFIG.untis_school,
)?,
client_name: CONFIG.untis_client_name.to_owned(),
user_agent: "Mozilla/5.0 (Windows NT 10.0; rv:108.0) Gecko/20100101 Firefox/108.0"
.to_string(),
user_agent: "".to_string(),
username: CONFIG.untis_username.to_owned(),
password: CONFIG.untis_password.to_owned(),
session: None,

View file

@ -49,3 +49,9 @@ pub struct StatusCode {
pub status_code: http::StatusCode,
pub message: Option<String>,
}
impl StatusCode {
pub fn to_response(&self) -> HttpResponse<BoxBody> {
self.to_response_with_status_code(self.status_code)
}
}

View file

@ -240,7 +240,7 @@ async fn fetch_substitutions(
type StartEndTime = (NaiveTime, NaiveTime);
fn get_period(times: &Vec<StartEndTime>, start: bool, time: NaiveTime) -> Option<usize> {
fn get_period(times: &[StartEndTime], start: bool, time: NaiveTime) -> Option<usize> {
times
.iter()
.position(|x| (if start { x.0 } else { x.1 }) == time)
@ -417,14 +417,13 @@ fn cache_substitutions(
.collect::<Result<Vec<_>>>()
.unwrap()
.into_iter()
.filter_map(|s| s)
.flatten()
.collect::<Vec<_>>();
substitutions.sort_by_key(|x| {
(
x.classes.get(0).and_then(|x| {
x.split_once(' ')
.and_then(|y| y.0.parse::<u32>().map_or(None, |s| Some(s)))
}),
x.classes
.get(0)
.and_then(|x| x.split_once(' ').and_then(|y| y.0.parse::<u32>().ok())),
x.period,
)
});

View file

View file

@ -144,47 +144,6 @@
</p>
</footer>
<script>
window.onerror = function () {
console.log("js error detected");
setTimeout(function () {
console.log("reloading page because of error");
window.location.reload();
}, 30_000);
};
const elementCount = JSON.parse($("#data-element-count").text());
const waitDelay = 10_000;
const scrollDuration = elementCount * 200;
function reload() {
window.location.reload();
}
function scrollUp() {
$("html, body").animate(
{
scrollTop: 0,
},
scrollDuration,
"linear"
);
setTimeout(reload, scrollDuration);
}
function scrollDown() {
$("html, body").animate(
{
scrollTop: $(document).height() - $(window).height(),
},
scrollDuration,
"linear"
);
setTimeout(scrollUp, scrollDuration + waitDelay);
}
window.scrollTo(0, 0);
setTimeout($(document).height() > $(window).height() ? scrollDown : reload, waitDelay);
</script>
<script src="/static/js/bvplan.js"></script>
</body>
</html>

View file

@ -12,18 +12,18 @@ x-bvplan:
- rabbitmq
- redis
environment:
BACKEND_DB_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_USER}
BACKEND_AMQP_URL: amqp://${RABBITMQ_USER}:${RABBITMQ_PASSWORD}@rabbitmq:5672
BACKEND_REDIS_URL: redis://redis:6379
BACKEND_UNTIS_API_URL: ${BACKEND_UNTIS_API_URL}
BACKEND_UNTIS_RPC_URL: ${BACKEND_UNTIS_RPC_URL}
BACKEND_UNTIS_CLIENT_NAME: ${BACKEND_UNTIS_CLIENT_NAME}
BACKEND_UNTIS_SCHOOL: ${BACKEND_UNTIS_SCHOOL}
BACKEND_UNTIS_USERNAME: ${BACKEND_UNTIS_USERNAME}
BACKEND_UNTIS_PASSWORD: ${BACKEND_UNTIS_PASSWORD}
BACKEND_UNTIS_VPLAN_URL: ${BACKEND_UNTIS_VPLAN_URL}
BACKEND_UNTIS_VPLAN_USERNAME: ${BACKEND_UNTIS_VPLAN_USERNAME}
BACKEND_UNTIS_VPLAN_PASSWORD: ${BACKEND_UNTIS_VPLAN_PASSWORD}
BVPLAN_DB_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_USER}
BVPLAN_AMQP_URL: amqp://${RABBITMQ_USER}:${RABBITMQ_PASSWORD}@rabbitmq:5672
BVPLAN_REDIS_URL: redis://redis:6379
BVPLAN_UNTIS_API_URL: ${BVPLAN_UNTIS_API_URL}
BVPLAN_UNTIS_RPC_URL: ${BVPLAN_UNTIS_RPC_URL}
BVPLAN_UNTIS_CLIENT_NAME: ${BVPLAN_UNTIS_CLIENT_NAME}
BVPLAN_UNTIS_SCHOOL: ${BVPLAN_UNTIS_SCHOOL}
BVPLAN_UNTIS_USERNAME: ${BVPLAN_UNTIS_USERNAME}
BVPLAN_UNTIS_PASSWORD: ${BVPLAN_UNTIS_PASSWORD}
BVPLAN_UNTIS_VPLAN_URL: ${BVPLAN_UNTIS_VPLAN_URL}
BVPLAN_UNTIS_VPLAN_USERNAME: ${BVPLAN_UNTIS_VPLAN_USERNAME}
BVPLAN_UNTIS_VPLAN_PASSWORD: ${BVPLAN_UNTIS_VPLAN_PASSWORD}
services:
nginx: