aboutsummaryrefslogtreecommitdiff
path: root/server/src/ui/home.rs
blob: 17cac83867f26e19b0fab35484744b3a67556802 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/*
    This file is part of jellything (https://codeberg.org/metamuffin/jellything)
    which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
    Copyright (C) 2026 metamuffin <metamuffin.org>
*/

use super::error::MyResult;
use crate::request_info::RequestInfo;
use anyhow::{Context, Result};
use jellycommon::{Nku, jellyobject::EMPTY};
use jellydb::{Query, helper::DatabaseReturnExt};
use jellyui::components::home::{Home, HomeRow};
use rocket::{get, response::content::RawHtml};
use std::{borrow::Cow, str::FromStr};

#[get("/home")]
pub fn r_home(ri: RequestInfo<'_>) -> MyResult<RawHtml<String>> {
    ri.require_user()?;

    let mut rows = Vec::new();
    rows.push(home_row(
        &ri,
        "home.bin.latest_video",
        "FILTER (visi = visi AND kind = vide) SORT DESCENDING BY FIRST rldt",
    )?);
    rows.push(home_row(
        &ri,
        "home.bin.latest_music",
        "FILTER (visi = visi AND kind = musi) SORT DESCENDING BY FIRST rldt",
    )?);
    rows.extend(home_row_highlight(
        &ri,
        "home.bin.daily_random",
        "FILTER (visi = visi AND kind = movi) SORT RANDOM",
    )?);
    rows.push(home_row(
        &ri,
        "home.bin.max_rating",
        "SORT DESCENDING BY FIRST rtng.imdb",
    )?);
    rows.extend(home_row_highlight(
        &ri,
        "home.bin.daily_random",
        "FILTER (visi = visi AND kind = show) SORT RANDOM",
    )?);

    Ok(ri.respond_ui(&Home {
        ri: &ri.render_info(),
        rows: &rows,
    }))
}

fn home_row(
    ri: &RequestInfo<'_>,
    title: &'static str,
    query: &str,
) -> Result<(&'static str, HomeRow<'static>)> {
    let q = Query::from_str(query).context("parse query")?;
    ri.state.database.transaction_ret(|txn| {
        let rows = txn.query(q.clone())?.take(16).collect::<Result<Vec<_>>>()?;

        let mut nkus = Vec::new();
        for (row, _) in rows {
            let node = txn.get(row)?.unwrap();
            nkus.push(Nku {
                node: Cow::Owned(node),
                role: None,
                userdata: Cow::Borrowed(EMPTY),
            });
        }
        Ok((title, HomeRow::Inline(nkus)))
    })
}

fn home_row_highlight(
    ri: &RequestInfo<'_>,
    title: &'static str,
    query: &str,
) -> Result<Option<(&'static str, HomeRow<'static>)>> {
    let q = Query::from_str(query).context("parse query")?;
    ri.state.database.transaction_ret(|txn| {
        let Some(row) = txn.query(q.clone())?.next() else {
            return Ok(None);
        };
        let row = row?.0;
        let node = txn.get(row)?.unwrap();
        Ok(Some((
            title,
            HomeRow::Highlight(Nku {
                node: Cow::Owned(node),
                role: None,
                userdata: Cow::Borrowed(EMPTY),
            }),
        )))
    })
}