updated AGENTS.md and pps site works again.

This commit is contained in:
Sebastian Moser
2026-10-14 01:50:08 +02:00
parent a7db7da9d2
commit 0b316ad54f
20 changed files with 1053 additions and 264 deletions

View File

@@ -47,6 +47,7 @@ axum-oidc = { version = "=1.0.0-dev-1", optional = true }
tower = { version = "0.5.3", optional = true }
tower-sessions = { version = "0.15.0", optional = true }
tower-http = { version = "0.7.1", optional = true, features = [ "cors", "trace" ] }
cmd_lib = "2.0.1"

View File

@@ -291,8 +291,7 @@ fn export_timetrack(ctx: &mut ProcedureContext, username: String, date: String)
info!("end_of_day: {}", end_timestamp);
let mut export = String::new();
export.push_str(&format!("# export for {}\n\n", date));
export.push_str(&format!("## actions\n"));
//export.push_str(&format!("### actions\n"));
let profile = ctx.with_tx(|tx| tx.db.profiles().username().find(&username)).ok_or(format!("Profile with username {} not found", username))?;
@@ -306,17 +305,19 @@ fn export_timetrack(ctx: &mut ProcedureContext, username: String, date: String)
.to_chrono_date_time()
.map_err(|err| err.to_string())?
.with_timezone(&Europe::Vienna)
.format("%H:%M:%S");
.format("%H:%M");
let end = event.end
.to_chrono_date_time()
.map_err(|err| err.to_string())?
.with_timezone(&Europe::Vienna)
.format("%H:%M:%S");
.format("%H:%M");
let line = format!("{} to {} ... {}\n", start, end, event.action.name);
export.push_str(line.as_str());
}
return Ok(export); // don't do thoughts right now
export.push_str("\n");
export.push_str("## thoughts\n");
let thoughts = ctx.with_tx(|tx| {
@@ -355,8 +356,8 @@ pub fn migrate(ctx: &mut ProcedureContext) -> String {
#[procedure]
pub fn test(ctx: &mut ProcedureContext) -> String {
let mut s = String::from("hoooooooooooooooooooooo\n");
let a: String = ctx.with_tx(|tx| {
let mut s = String::new();
let a: String = ctx.with_tx(|_tx| {
let s = String::new();

View File

@@ -265,7 +265,7 @@ pub fn part_client_auth(mize: &mut Mize) -> MizeResult<()> {
mize: mize.clone(),
};
let mut secrets = match load_secrets(mize) {
let secrets = match load_secrets(mize) {
Ok(secrets) => Some(secrets),
Err(err) => {
tracing::warn!("err reading secrets: {:?}", err);

View File

@@ -6,6 +6,8 @@ use clap::{Arg, Command};
use mize::item::ItemData;
use rusqlite::{params, Connection};
use serde_json::{json, Value};
use clap::ArgMatches;
use cmd_lib::run_cmd as sh;
use dioxus::prelude::*;
use mize::{mize_err, mize_part, Mize, MizeError, MizePart, MizePartCreate, MizeResult};
@@ -18,13 +20,13 @@ use generated::spacetime::{
Action, ActivitiesTableAccess, Activity, DbConnection, LogEventsTableAccess, TaskPart, TaskPartTableAccess, activitiesQueryTableAccess, next_action, remove_activity, task_partQueryTableAccess, update_activity, update_upcoming
};
use spacetimedb_sdk::{
credentials, DbContext, Error, Event, Identity, Status, SubscriptionHandle, Table,
credentials, DbContext, Error, Event, Identity, Status,
TableWithPrimaryKey,
};
static MIZE_SRC: &str = "/home/me/work/config/mize";
static SRC: &str = "/home/me/work/config";
static RSYNC_EXCLUDES: &str = "--exclude=node_modules --exclude=target --exclude=mize_config.toml --exclude=rust_dist --exclude=deno_dist --exclude=dist --exclude=result --exclude=pkg";
static RSYNC_EXCLUDES: &str = "--exclude=node_modules --exclude=target --exclude=mize_config.toml --exclude=rust_dist --exclude=deno_dist --exclude=dist --exclude=result --exclude=pkg --exclude /src --exclude obsidian-brat --exclude forked-zed";
#[mize_part]
#[derive(Default)]
@@ -78,7 +80,7 @@ pub fn part_c2vi(mize: &mut Mize) -> MizeResult<()> {
name: "SC2 Publish Daily Journal".to_string(),
callback: Box::new(|mut mize| {
let matrix = mize.get_part_native::<crate::matrix::MatrixPart>("matrix")?;
matrix.send_message(room_id);
//matrix.send_message(room_id);
Ok(())
}),
@@ -92,9 +94,11 @@ fn c2vi_deploy_things(mize: &mut Mize) -> MizeResult<()> {
let mut cli = mize.get_part_native::<CliPart>("cli")?;
cli.set_command("dev");
let bin_arg = Arg::new("bin").short('b');
cli.subcommand(
Command::new("deploy-lush").alias("dlu").arg(&bin_arg),
Box::new(move |matches: &ArgMatches, mize| remote_deploy(matches, mize, "lush")),
Box::new(move |matches: &ArgMatches, mize| remote_deploy(matches, mize, "te")),
)?;
cli.subcommand(
Command::new("deploy-mac").alias("dmc").arg(&bin_arg),
@@ -124,10 +128,6 @@ fn c2vi_deploy_things(mize: &mut Mize) -> MizeResult<()> {
Command::new("deploy-spacetime").alias("dsp").arg(&bin_arg),
Box::new(deploy_spacetime),
)?;
cli.subcommand(
Command::new("generate").alias("gen").arg(&bin_arg),
Box::new(md_generate),
)?;
Ok(())
}
@@ -168,33 +168,61 @@ pub fn use_spacetime<T: Fn(QueryBuilder)>(query: T) {
//pub fn use_by_pk(identity: Identity)
//pub fn use_one<T>
pub fn c2vi_dash_main() -> Element {
let mut current = use_signal_sync(|| "".to_string());
let mut next = use_signal_sync(|| "".to_string());
//TaskPart::
//use_one()
use_effect(move || {
let mut mize = use_context::<Mize>();
let mut spacetime = mize.get_part_native::<SpacetimePart>("spacetime").unwrap();
let spacetime = match mize.get_part_native::<SpacetimePart>("spacetime") {
Ok(val) => val,
Err(e) => {
e.log();
return;
},
};
let con = spacetime.con();
con.subscription_builder()
.on_applied(move |ctx| {
let data = ctx.db.task_part().identity().find(&ctx.identity()).unwrap();
let data = match ctx.db.task_part().identity().find(&ctx.identity()) {
Some(val) => val,
None => {
debug!("can't find task part for user");
return;
},
};
current.set(data.current.name.clone());
if let Some(first_upcoming) = data.upcoming.first() {
next.set(first_upcoming.name.clone());
} else {
next.set("".to_string());
}
})
.add_query(|q| q.from.task_part().r#where(|t| t.identity.eq(con.identity())))
.subscribe();
con.db
.task_part()
.on_update(move |_, old: &TaskPart, new: &TaskPart| {
.on_update(move |_, _old: &TaskPart, new: &TaskPart| {
current.set(new.current.name.clone());
if let Some(first_upcoming) = new.upcoming.first() {
next.set(first_upcoming.name.clone());
} else {
next.set("".to_string());
}
});
});
rsx! {
div {
style: "text-align: center; padding: 2rem; font-size: 50px;",
style: "text-align: center; padding: 2rem; font-size: 120px;",
p {
"{current}"
}
p {
style: "font-size: 50px; color: grey; opacity: 0.7;",
"{next}"
}
}
}
}
@@ -774,8 +802,7 @@ pub fn remote_deploy(matches: &ArgMatches, _: Mize, hostname: &str) -> MizeResul
let bin = match matches.get_one::<String>("bin") {
Some(val) => val.to_owned(),
None => {
do_mize_restart = true;
format!("{}-os", hostname)
"mize".to_owned()
}
};
@@ -785,7 +812,7 @@ pub fn remote_deploy(matches: &ArgMatches, _: Mize, hostname: &str) -> MizeResul
"files" => "/home/files/here/config",
"nico" => "/root/work/config-c2vi",
"ppc-hosting" => "/root/host/c2vi-config",
_ => "main-idk",
_ => "/home/me/here/config",
};
let mize_store_dir = match hostname {
"lush" => "/home/me/host/mize",
@@ -793,13 +820,15 @@ pub fn remote_deploy(matches: &ArgMatches, _: Mize, hostname: &str) -> MizeResul
"files" => "/home/files/storage/files/mize",
"nico" => "/root/work/app-data/mize",
"ppc-hosting" => "/root/host/mize",
_ => "/tmp/idk",
_ => "/home/me/host/mize",
};
let rclone_flag = match hostname {
"nico" => "--chown=root:root",
"ppc-hosting" => "--chown=root:root",
_ => "",
};
sh!(echo cmd: rsync -r -u -v -a --delete --perms $rclone_flag --include=".git/" --include=".git/**" --exclude="target" --mkpath $RSYNC_EXCLUDES $SRC/ $hostname:$remote_src_dir)?;
sh!(rsync -r -u -v -a --delete --perms $rclone_flag --include=".git/" --include=".git/**" --exclude="target" --mkpath $RSYNC_EXCLUDES $SRC/ $hostname:$remote_src_dir)?;
let ssh_cmd = format!(
@@ -812,7 +841,7 @@ pub fn remote_deploy(matches: &ArgMatches, _: Mize, hostname: &str) -> MizeResul
fi
tmux send-keys -t mize-deploy "DO_MIZE_RESTART={do_mize_restart}" Enter
tmux send-keys -t mize-deploy "cargo build --manifest-path {remote_src_dir}/Cargo.toml --bin {bin}" Enter
tmux send-keys -t mize-deploy "cargo build --manifest-path {remote_src_dir}/mize/Cargo.toml --bin {bin}" Enter
tmux send-keys -t mize-deploy 'BUILD_SUCCESS=$?' Enter
tmux send-keys -t mize-deploy '[[ "$BUILD_SUCCESS" == "0" ]] && echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" > {mize_store_dir}/daemon.env' Enter
tmux send-keys -t mize-deploy '[[ "$BUILD_SUCCESS" == "0" ]] && echo "MIZE_CONFIG_FILES={mize_store_dir}/config.toml" >> {mize_store_dir}/daemon.env' Enter
@@ -888,7 +917,7 @@ pub fn main_deploy(_: &ArgMatches, _: Mize) -> MizeResult<()> {
);
std::env::set_var("SRC", SRC);
}
let cmd = str!(
let cmd =
r#"
if ! tmux has-session -t mize-deploy 2>/dev/null; then
systemd-run --user --scope --description="mize deploy tmux session" tmux new-session -d -s mize-deploy "nix develop git+file://$SRC/mize#buildShell"
@@ -898,8 +927,7 @@ pub fn main_deploy(_: &ArgMatches, _: Mize) -> MizeResult<()> {
tmux send-keys -t mize-deploy "cargo build --manifest-path $SRC/mize/Cargo.toml --bin mize" Enter
tmux send-keys -t mize-deploy 'echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" > /home/me/work/app-data/mize/daemon.env' Enter
tmux send-keys -t mize-deploy "systemctl --user restart mize" Enter
"#
);
"#;
sh!(/bin/sh -c "$cmd")?;
Ok(())
}

View File

@@ -84,7 +84,7 @@ pub fn cli(mize: &mut Mize) -> MizeResult<()> {
)?;
mize.add_listener(
"cli.spawn_done",
Box::new(move |mut msg, mize| {
Box::new(move |_msg, _mize| {
log::info!("before send");
spawn_wait_tx.send(());
log::info!("after send");
@@ -256,7 +256,7 @@ impl CliPart {
action: T,
) -> MizeResult<()> {
let name = subcmd.get_name().to_string();
let mut cmd = self
let cmd = self
.cmds
.remove(&self.current_cmd_name)
.unwrap()
@@ -299,6 +299,7 @@ impl CliPart {
}
// impl smth like this to run cli commands in the daemon.
/*
pub fn mize_thin_cli_client(bin_name: Option<&str>) -> MizeResult<()> {
use std::io::Write;
use std::os::unix::net::UnixStream;
@@ -353,3 +354,4 @@ pub fn mize_thin_cli_client(bin_name: Option<&str>) -> MizeResult<()> {
Ok(())
}
*/

View File

@@ -2,13 +2,13 @@
use mize::{Mize, MizeResult, MizeError, mize_err};
use crate::CliPart;
use clap::Arg;
// spacetime gen command: sh!(RUST_LOG=error RUST_BACKTRACE=0 spacetime generate --build-options="--lint-dir=" -p $SRC/mize/marts/spacetime -o $SRC/mize/marts/generated/src/spacetime --lang rust)?;
pub fn part_dev(mize: &mut Mize) -> MizeResult<()> {
let mut cli = mize.get_part_native::<CliPart>("cli")?;
cli.set_command("dev");
let bin_arg = Arg::new("bin").short('b');

View File

@@ -38,7 +38,6 @@ pub use auth::*;
pub mod ppc;
pub mod timetrack;
#[cfg(feature = "target-obsidian")]
pub mod matrix;

View File

@@ -1,194 +0,0 @@
use dioxus::prelude::*;
use axum::response::Html;
pub fn main_page() -> Html<String> {
let html_output = dioxus_ssr::render_element(rsx! {
div {
h1 { "Hello from Dioxus SSR!" }
p { "This was rendered on the server and sent via Axum." }
}
});
Html(html_output)
}
pub fn main_page_element() -> Element {
rsx! {
"hello world"
div {
class: "min-h-screen bg-gray-100 items-center flex h-screen items-center justify-center",
// Header
header {
class: "bg-blue-600 text-white py-4",
div {
class: "container mx-auto px-4",
h1 {
class: "text-2xl font-bold",
"People Corner (PPC)"
}
}
}
// Main content
main {
class: "container mx-auto px-4 py-8",
// Hero section
section {
class: "bg-white rounded-lg shadow-md p-6 mb-8",
h2 {
class: "text-xl font-semibold mb-4 text-blue-600",
"Welcome to People Corner"
}
p {
class: "text-gray-700 mb-4",
"PPC is a social platform for intentional people who want to get more out of life together."
}
p {
class: "text-gray-700",
"We're building a community-driven social media network that brings people together to do cool things, share resources, and support each other."
}
}
// Mission section
section {
class: "bg-white rounded-lg shadow-md p-6 mb-8",
h2 {
class: "text-xl font-semibold mb-4 text-blue-600",
"Our Mission"
}
ul {
class: "list-disc pl-6 space-y-2",
li { "Bring people together to get more out of life" }
li { "Create meaningful connections beyond superficial social media" }
li { "Support intentional living and personal growth" }
li { "Build a platform by people, for people" }
li { "Foster real-world meetups and collaborations" }
li { "Create a social media for diligent, intentional people" }
}
}
// Key concepts section
section {
class: "bg-white rounded-lg shadow-md p-6",
h2 {
class: "text-xl font-semibold mb-4 text-blue-600",
"Key Concepts"
}
ul {
class: "list-disc pl-6 space-y-2",
li {
strong { "Trust Network: " }
"A system for building and maintaining trust between members"
}
li {
strong { "Intentional Communities: " }
"Both online and physical spaces for like-minded people"
}
li {
strong { "Resource Sharing: " }
"Platform for sharing skills, knowledge, and physical resources"
}
li {
strong { "Real Connections: " }
"Focus on meaningful relationships over superficial interactions"
}
li {
strong { "Personal Growth: " }
"Support for individuals to achieve their life goals"
}
}
}
}
// Footer
footer {
class: "bg-blue-600 text-white py-4 mt-8",
div {
class: "container mx-auto px-4 text-center",
p { "© 2024 People Corner. All rights reserved." }
}
}
}
}
}
/// About page component
pub fn about_page() -> Element {
rsx! {
div {
class: "container mx-auto px-4 py-8",
h1 {
class: "text-2xl font-bold mb-4 text-blue-600",
"About PPC"
}
p {
class: "text-gray-700 mb-4",
"People Corner (PPC) is more than just a social platform - it's a movement to bring intentional people together to create meaningful connections and achieve more in life."
}
p {
class: "text-gray-700",
"Our vision is to build a world where people support each other, share resources, and grow together through real-world interactions and digital connections."
}
}
}
}
/// Contact page component
pub fn contact_page() -> Element {
rsx! {
div {
class: "container mx-auto px-4 py-8",
h1 {
class: "text-2xl font-bold mb-4 text-blue-600",
"Contact Us"
}
p {
class: "text-gray-700 mb-4",
"We'd love to hear from you! Whether you have questions, feedback, or want to get involved, please reach out."
}
form {
class: "max-w-md space-y-4",
div {
label {
class: "block text-gray-700 mb-2",
"Name"
}
input {
class: "w-full px-3 py-2 border rounded-lg",
r#type: "text",
placeholder: "Your name"
}
}
div {
label {
class: "block text-gray-700 mb-2",
"Email"
}
input {
class: "w-full px-3 py-2 border rounded-lg",
r#type: "email",
placeholder: "Your email"
}
}
div {
label {
class: "block text-gray-700 mb-2",
"Message"
}
textarea {
class: "w-full px-3 py-2 border rounded-lg h-32",
placeholder: "Your message"
}
}
button {
class: "bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700",
r#type: "submit",
"Send Message"
}
}
}
}
}

View File

@@ -1,9 +1,199 @@
use std::str::FromStr;
use axum::response::Html;
use clap::Command;
use dioxus::prelude::*;
use mize::Mize;
use mize::MizeResult;
pub mod server;
pub mod main_page;
pub fn mc_page() -> Html<String> {
Html(r#"
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="style.css">
<title>PPC Minecraft Server</title>
<script defer data-domain="ppc.social" src="https://plausible.c2vi.dev/js/script.file-downloads.hash.outbound-links.pageview-props.revenue.tagged-events.js"></script>
<script>window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }</script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #f0efeb;
height: 100vh;
width: 100vw;
font-family: 'Montserrat', sans-serif;
padding: 100px;
font-size: 16px;
font-weight: 800;
color: #8e8e8e;
}
.strong { color: black; }
.semi { color: #484847; }
.link { color: #588fff; display: inline; }
.code { font-family: monospace; }
.mt { margin-top: 20px; }
.ml { margin-left: 20px; }
.mr { margin-right: 20px; }
.mb { margin-bottom: 20px; }
.flex {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: flex-start;
}
.main {
width: 100%;
row-gap: 150px;
}
.card {
padding: 20px;
flex: 1 0 400px;
& > * {
display: block;
margin-top: 5px;
.card-heading { font-size: 24px; }
.card-body {
text-align: justify;
}
}
}
.title {
font-size: 48px;
flex: 1 0 40%;
}
.info { flex: 1 0 60%; }
.sub-card {
flex: 1 1 50%;
height: min-content;
padding: 20px 20px 20px 0;
* {
display: block;
margin-top: 5px;
}
.card-heading { font-size: 18px; }
.card-footer { font-size: 12px; }
.card-body {
font-size: 23px;
color: #588fff;
}
}
@media screen and (max-width: 650px) {
* { word-wrap: normal; }
body { padding: 20px; }
.title { font-size: 24px; }
.card { padding: 0; flex: 0 0 100%; }
.card:not(:last-child):after {
display: block;
content: "";
border-bottom: 5px solid currentColor;
margin: 20px 0 20px 0;
border-radius: 5px;
}
.card:last-child { margin-bottom: 100px; }
.sub-card:after { display: block; content: ""; border-bottom: 1px solid currentColor; margin-top: 20px; }
.main { row-gap: 0; }
.sub-card .card-body { font-size: 18px; }
}
@media screen and (max-width: 360px) {
body { font-size: 12px !important; }
.sub-card .card-body { font-size: 16px; }
}
</style>
</head>
<body>
<div class="main flex">
<div class="card title">
<div>Welcome to the</div>
<div class="strong">PPC</div>
<div>Minecraft Cluster</div>
</div>
<div class="card info flex">
<div class="sub-card">
<span class="card-heading">Address</span>
<span class="card-body">first.ppc.social</span>
<span class="card-footer">Java 1.21.11 and Bedrock (bedrock not working rn)</span>
</div>
<div class="sub-card">
<span class="card-heading">Discord</span>
<a class="card-body" href="https://discord.gg/cMKQNJMkRe" target="_blank">https://discord.gg/cMKQNJMkRe</a>
<span class="card-footer">come and say hi!</span>
</div>
<div class="semi mt">
See you ingame and invite all your friends to play as well!!
</div>
</div>
<div class="card">
<span class="card-heading strong">SimpleVoicechat</span>
<span class="card-body">
This is <span class="semi">not required</span>, but makes playing soooo much more fun, so it's
<span class="semi">highly encouraged</span>.
<br/><br/>
<span class="semi">Instructions can be found here</span>:<br/>
<a href="https://fabricmc.net/use/installer/" class="link ml">Fabric</a>
<br/>
<a class="link ml" href="https://modrepo.de/minecraft/voicechat/wiki/installation#fabric">SimpleVoiceChat</a>
<br/><br/>
</span>
</div>
</div>
</body>
</html>
"#.to_owned())
}
pub fn main_page() -> Html<String> {
Html(r#"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>People Corner</title>
<link rel="stylesheet" href="/app/static/styles.css">
<link rel="icon" type="image/png" href="/app/static/logo.png">
<script defer data-domain="ppc.social" src="https://plausible.c2vi.dev/js/script.file-downloads.hash.outbound-links.pageview-props.revenue.tagged-events.js"></script>
<script>window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }</script>
</head>
<body style="text-align: center" >
<div class="highlighted">
<h2>"Cool People doing Cool things together"</h2>
<p>Read what this is all about: <a href="https://wiki.ppc.social/u/c2vi/The-Idea-of-PPC">About</a></p>
<br>
<p>There is a Discord Server: <a href="https://discord.gg/cMKQNJMkRe">https://discord.gg/cMKQNJMkRe</a></p>
<p>There is a <a href="https://ppc.social/mc">Minecraft server</a>.</p>
<p>There is <a href="https://wiki.ppc.social">The PPC Wiki Projekt</a>.</p>
<p>There is an <a href="https://www.instagram.com/ppc.social/">Instagram</a> and a <a href="https://www.youtube.com/@ppc.social">Youtube Channel</a></p>
<p>and that's about all for now...</p>
</body>
</html>
"#.to_owned())
}

View File

@@ -29,7 +29,7 @@ use tower_sessions::{
pub fn part_ppc_server(mize: &mut Mize) -> MizeResult<()> {
mize.add_name_only_part("ppc.server");
let mut mize_clone = mize.clone();
let mize_clone = mize.clone();
mize.spawn_async("ppc.server_runner", start_server(mize_clone));
Ok(())
@@ -38,9 +38,9 @@ pub fn part_ppc_server(mize: &mut Mize) -> MizeResult<()> {
pub async fn start_server(mut mize: Mize) -> MizeResult<()> {
dioxus::logger::initialize_default();
let issuer = mize.get_config("auth.issuer")?.value_string()?;
let client_id = mize.get_config("auth.client_id")?.value_string()?;
let client_secret = mize.get_config("auth.client_secret")?.value_string()?;
let issuer = mize.get_config("auth.server.issuer")?.value_string()?;
let client_id = mize.get_config("auth.server.client_id")?.value_string()?;
let client_secret = mize.get_config("auth.server.client_secret")?.value_string()?;
let url = mize.get_config("web.url")?.value_string()?;
let redirect_url = format!("{url}/oidc");
@@ -88,7 +88,8 @@ pub async fn start_server(mut mize: Mize) -> MizeResult<()> {
.layer(session_layer)
.layer(tower_http::trace::TraceLayer::new_for_http())
// not authenticated routes
.route("/", get(crate::ppc::main_page::main_page()))
.route("/", get(crate::ppc::main_page()))
.route("/mc", get(crate::ppc::mc_page()))
// matrix .well-known
.route(
"/.well-known/matrix/client",
@@ -101,7 +102,7 @@ pub async fn start_server(mut mize: Mize) -> MizeResult<()> {
tracing::info!("Running on http://localhost:3000");
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
let listener = tokio::net::TcpListener::bind("0.0.0.0:8010").await.unwrap();
axum::serve(listener, app.into_make_service())
.await
.unwrap();
@@ -140,6 +141,6 @@ async fn handle_matrix_client() -> Json<Value> {
async fn handle_matrix_server() -> Json<Value> {
Json(json!({
"m.server": "://ppc.social"
"m.server": "matrix.ppc.social:443"
}))
}

View File

@@ -0,0 +1,8 @@
pub use mize::{Mize, MizeResult, MizeError};
pub fn part_sci_inbox(mize: &mut Mize) -> MizeResult<()> {
mize.add_name_only_part("sci.inbox");
Ok(())
}

View File

@@ -1,6 +1,7 @@
use mize::*;
pub mod timetrack;
use clap::Command;
pub fn part_sci(mize: &mut Mize) -> MizeResult<()> {
part_add_thought(mize)?;
@@ -9,20 +10,20 @@ pub fn part_sci(mize: &mut Mize) -> MizeResult<()> {
}
pub fn part_add_thought(mize: &mut Mize) -> MizeResult<()> {
use marts::generated::spacetime::add_thought;
let mut cli = mize.get_part_native::<marts::CliPart>("cli")?;
use crate::generated::spacetime::add_thought;
let mut cli = mize.get_part_native::<crate::CliPart>("cli")?;
cli.set_command("sci");
cli.subcommand(Command::new("inputThought").alias("ti"), |matches, mut mize| {
cli.subcommand(Command::new("inputThought").alias("ti"), |_matches, mut mize| {
let tmp_file = std::env::temp_dir().join(format!(
"sc2-input-thought-{}.txt",
chrono::Utc::now().timestamp()
));
marts::cli_spawn(format!("nvim {}", tmp_file.display()))?;
crate::cli_spawn(&mut mize, format!("nvim {}", tmp_file.display()))?;
let new_file_content = std::fs::read_to_string(&tmp_file)
.map_err(|e| mize_err!("Failed to read temp file: {}", e))?;
let _ = std::fs::remove_file(&tmp_file);
let spacetime = mize.get_part_native::<marts::SpacetimePart>("spacetime")?;
let spacetime = mize.get_part_native::<crate::SpacetimePart>("spacetime")?;
spacetime.con().reducers.add_thought(new_file_content)?;
Ok(())
})?;

View File

@@ -7,6 +7,15 @@ use mize::out;
use mize::proto::MizeMessage;
use mize::{Mize, MizeError, MizePart, MizePartCreate, MizeResult, mize_err, mize_part};
use spacetimedb_sdk::{DbContext, Table};
use generated::spacetime::export_timetrack;
use generated::spacetime::first_timetrack_date;
use std::fs::OpenOptions;
use chrono::Local;
use chrono::TimeDelta;
use std::io::Write;
use std::path::Path;
use std::fs;
use std::io;
use generated::spacetime::{
Action, ActivitiesTableAccess, Activity, DbConnection, TaskPartTableAccess,
@@ -149,7 +158,7 @@ impl MizePart for TimeTrack {
#[cfg(feature = "target-os")]
fn command_next_action(matches: &ArgMatches, mut mize: Mize) -> MizeResult<()> {
let mut spacetime = mize.get_part_native::<SpacetimePart>("spacetime")?;
let spacetime = mize.get_part_native::<SpacetimePart>("spacetime")?;
let con = spacetime.con();
let break_flag = matches.get_flag("break");
@@ -183,7 +192,7 @@ fn command_next_action(matches: &ArgMatches, mut mize: Mize) -> MizeResult<()> {
#[cfg(feature = "target-os")]
fn command_current_action(_: &ArgMatches, mut mize: Mize) -> MizeResult<()> {
let mut spacetime = mize.get_part_native::<SpacetimePart>("spacetime")?;
let spacetime = mize.get_part_native::<SpacetimePart>("spacetime")?;
let action = get_current_action(&mut mize, spacetime.con())?;
out!("{}", action.name);
Ok(())
@@ -220,7 +229,7 @@ fn get_current_action(_mize: &mut Mize, con: &DbConnection) -> MizeResult<Action
#[cfg(feature = "target-os")]
fn command_list_activities(_: &ArgMatches, mut mize: Mize) -> MizeResult<()> {
let mut spacetime = mize.get_part_native::<SpacetimePart>("spacetime")?;
let spacetime = mize.get_part_native::<SpacetimePart>("spacetime")?;
let activities = get_activities(&mut mize, spacetime.con())?;
for ac in activities.clone() {
@@ -239,7 +248,7 @@ fn command_list_activities(_: &ArgMatches, mut mize: Mize) -> MizeResult<()> {
#[cfg(feature = "target-os")]
fn command_list_actions(_: &ArgMatches, mut mize: Mize) -> MizeResult<()> {
let mut spacetime = mize.get_part_native::<SpacetimePart>("spacetime")?;
let spacetime = mize.get_part_native::<SpacetimePart>("spacetime")?;
let actions = get_actions(spacetime.con())?;
@@ -252,7 +261,7 @@ fn command_list_actions(_: &ArgMatches, mut mize: Mize) -> MizeResult<()> {
#[cfg(feature = "target-os")]
fn command_edit_action_list(matches: &ArgMatches, mut mize: Mize) -> MizeResult<()> {
let mut spacetime = mize.get_part_native::<SpacetimePart>("spacetime")?;
let spacetime = mize.get_part_native::<SpacetimePart>("spacetime")?;
// maybe append a template to the action list
if matches.get_flag("defaultTemplate") {
@@ -353,7 +362,7 @@ fn parse_action(action: &mut Action) {
#[cfg(feature = "target-os")]
fn command_edit_activities(_: &ArgMatches, mut mize: Mize) -> MizeResult<()> {
let mut spacetime = mize.get_part_native::<SpacetimePart>("spacetime")?;
let spacetime = mize.get_part_native::<SpacetimePart>("spacetime")?;
// get list of activities
let activities = get_activities(&mut mize, spacetime.con())?;
@@ -546,18 +555,16 @@ fn parse_activities_from_text(
}
pub fn part_timetrack_export(mize: &mut Mize) -> MizeResult<()> {
use std::path::Path;
let mut cli = mize.get_part_native::<marts::CliPart>("cli")?;
let mut cli = mize.get_part_native::<crate::CliPart>("cli")?;
cli.set_command("ppc");
cli.subcommand(Command::new("exportTimetrack").alias("et").arg(Arg::new("date").short('d')).arg(Arg::new("all").short('a').action(ArgAction::SetTrue)), |matches , mut mize| {
let spacetime = mize.get_part_native::<marts::SpacetimePart>("spacetime")?;
let notes_dir = mize.get_config("sc2.userNotesDir").unwrap_or_default().value_string()?;
cli.set_command("sci");
cli.subcommand(Command::new("timetrackExport").alias("te").arg(Arg::new("date").short('d')).arg(Arg::new("all").short('a').action(ArgAction::SetTrue)), |matches , mut mize| {
let spacetime = mize.get_part_native::<crate::SpacetimePart>("spacetime")?;
let today = Local::now().format("%Y-%m-%d").to_string();
let mut date = matches.get_one::<String>("date").unwrap_or(&today);
std::fs::create_dir_all(Path::new(&notes_dir).join("timetrack_exports"))?;
let all = matches.get_flag("all");
if all {
out!("exporting all not implemented rn");
let (tx, rx) = oneshot::channel();
spacetime.con().procedures.first_timetrack_date_then("c2vi".to_string(), |_, res| {tx.send(res);});
let res = rx.recv()???;
@@ -567,23 +574,56 @@ pub fn part_timetrack_export(mize: &mut Mize) -> MizeResult<()> {
let (tx, rx) = oneshot::channel();
spacetime.con().procedures.export_timetrack_then("c2vi".to_string(), date.to_owned(), |_, res| {tx.send(res);});
let res = rx.recv()???;
let mut file = OpenOptions::new().create(true).write(true).open(Path::new(&notes_dir).join("timetrack_exports").join(format!("timetrack_export_{}.md", date)))?;
file.write_all(res.as_bytes())?;
//let mut file = OpenOptions::new().create(true).write(true).open(Path::new(&notes_dir).join("timetrack_exports").join(format!("timetrack_export_{}.md", date)))?;
//file.write_all(res.as_bytes())?;
}
return Ok(());
}
out!("date: {}", date);
let (tx, rx) = oneshot::channel();
spacetime.con().procedures.export_timetrack_then("c2vi".to_string(), date.to_owned(), |_, res| {tx.send(res);});
spacetime.con().procedures.export_timetrack_then("c2vi".to_string(), date.to_owned(), |_, res| {let _ = tx.send(res);});
let res = rx.recv()???;
let mut file = OpenOptions::new().create(true).write(true).open(Path::new(&notes_dir).join("timetrack_exports").join(format!("timetrack_export_{}.md", date)))?;
file.write_all(res.as_bytes())?;
let daily_notes_path = mize.get_config("timetrack.dailyNotesPath")?.value_string()?;
let note_path = format!("{}/{}.md", daily_notes_path, date);
out!("writing to file: {}", note_path);
write_under_heading(note_path, "## timetrack export", res.as_ref())?;
Ok(())
})?;
Ok(())
}
fn write_under_heading(
file_path: impl AsRef<Path>,
heading: &str,
content: &str,
) -> io::Result<()> {
let file_path = file_path.as_ref();
let markdown = fs::read_to_string(file_path)?;
let heading_line = format!("{}", heading);
let mut lines: Vec<&str> = markdown.lines().collect();
let index = lines
.iter()
.position(|line: &&str| line.trim() == heading_line)
.ok_or_else(|| {
io::Error::new(
io::ErrorKind::NotFound,
format!("Heading '{}' not found", heading),
)
})?;
lines.insert(index + 1, content);
let mut updated = lines.join("\n");
updated.push('\n');
fs::write(file_path, updated)
}
fn dates_until_today(start: &str) -> Result<Vec<String>, chrono::ParseError> {
use chrono::NaiveDate;
let mut current = NaiveDate::parse_from_str(start, "%Y-%m-%d")?;