feat: notes wip part 2
This commit is contained in:
parent
067ebc3a36
commit
9f57b193ce
2
gazebot/.gitignore
vendored
Normal file
2
gazebot/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
target
|
||||||
|
.env
|
1662
gazebot/Cargo.lock
generated
Normal file
1662
gazebot/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
11
gazebot/Cargo.toml
Normal file
11
gazebot/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "gazebot"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tracing = "0.1"
|
||||||
|
tracing-subscriber = "0.3"
|
||||||
|
dotenvy = "0.15.7"
|
||||||
|
serenity = { version = "0.12", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] }
|
||||||
|
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
42
gazebot/src/main.rs
Normal file
42
gazebot/src/main.rs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
use std::env;
|
||||||
|
|
||||||
|
use serenity::async_trait;
|
||||||
|
use serenity::model::channel::Message;
|
||||||
|
use serenity::model::prelude::*;
|
||||||
|
use serenity::prelude::*;
|
||||||
|
|
||||||
|
struct Handler;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl EventHandler for Handler {
|
||||||
|
async fn message(&self, ctx: Context, msg: Message) {
|
||||||
|
if msg.content == "!ping" {
|
||||||
|
if let Err(why) = msg.channel_id.say(&ctx.http, "Pong!").await {
|
||||||
|
println!("Error sending message: {why:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn ready(&self, _: Context, ready: Ready) {
|
||||||
|
println!("{} is connected!", ready.user.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
let _ = dotenvy::dotenv();
|
||||||
|
|
||||||
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
|
let token = env::var("DISCORD_TOKEN").expect("Expected a token in the environment");
|
||||||
|
let intents = GatewayIntents::GUILD_MESSAGES
|
||||||
|
| GatewayIntents::DIRECT_MESSAGES
|
||||||
|
| GatewayIntents::MESSAGE_CONTENT;
|
||||||
|
|
||||||
|
let mut client =
|
||||||
|
Client::builder(&token, intents).event_handler(Handler).await.expect("Err creating client");
|
||||||
|
|
||||||
|
if let Err(why) = client.start().await {
|
||||||
|
println!("Client error: {why:?}");
|
||||||
|
}
|
||||||
|
}
|
19
src/components/token.svelte
Normal file
19
src/components/token.svelte
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export let punct: boolean = false;
|
||||||
|
export let keywd: boolean = false;
|
||||||
|
export let funct: boolean = false;
|
||||||
|
export let str: boolean = false;
|
||||||
|
|
||||||
|
export let small: boolean = false;
|
||||||
|
|
||||||
|
export let v: string;
|
||||||
|
|
||||||
|
const ty =
|
||||||
|
punct ? "punctuation"
|
||||||
|
: keywd ? "keyword"
|
||||||
|
: funct ? "function"
|
||||||
|
: str ? "string"
|
||||||
|
: ""
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<span class="align-middle token {ty} {small ? "text-sm" : ""}">{v}</span>
|
@ -1,9 +1,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export let title: string;
|
export let title: string | undefined = undefined;
|
||||||
export let iconUri: string = '';
|
export let iconUri: string = '';
|
||||||
export let id: string = '';
|
export let id: string = '';
|
||||||
export let sticky: boolean = false;
|
export let sticky: boolean = false;
|
||||||
export let entry: boolean = false;
|
export let entry: boolean = false;
|
||||||
|
export let removePadding: boolean = false;
|
||||||
|
export let center: boolean = false;
|
||||||
|
|
||||||
const scaleKeyframes = [
|
const scaleKeyframes = [
|
||||||
"window-open",
|
"window-open",
|
||||||
@ -21,38 +23,45 @@
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
flex flex-col {sticky ? 'md:sticky md:-top-9' : ''}
|
flex flex-col {sticky ? 'md:sticky md:-top-9' : ''} {center ? "mx-auto" : ""}
|
||||||
max-w-screen-md xl:max-w-screen-lg 2xl:max-w-screen-xl min-w-[30ch] lg:min-w-[40ch] w-full md:w-fit [height:fit-content]
|
max-w-screen-md xl:max-w-screen-lg 2xl:max-w-screen-xl min-w-[30ch] lg:min-w-[40ch] w-full md:w-fit [height:fit-content]
|
||||||
border-ralsei-white border-ridge border-8 border-t-[12px]
|
bg-ralsei-black border-ralsei-white border-ridge border-8 border-t-[12px]
|
||||||
bg-ralsei-black
|
|
||||||
animate-{chosenKeyframe}
|
animate-{chosenKeyframe}
|
||||||
"
|
"
|
||||||
{id}
|
{id}
|
||||||
>
|
>
|
||||||
<div
|
{#if title !== undefined}
|
||||||
class="
|
<div
|
||||||
p-1 border-ralsei-white border-8
|
class="
|
||||||
bg-gradient-to-l from-ralsei-pink-neon to-ralsei-black to-75%
|
p-1 border-ralsei-white border-8
|
||||||
"
|
bg-gradient-to-l from-ralsei-pink-neon to-ralsei-black to-75%
|
||||||
style="border-style: hidden hidden ridge hidden;"
|
"
|
||||||
>
|
style="border-style: hidden hidden ridge hidden;"
|
||||||
<div class="flex bg-opacity-100 pixelate-bg">
|
>
|
||||||
<h1
|
<div class="flex bg-opacity-100 pixelate-bg">
|
||||||
class="font-monospace text-xl text-ralsei-pink-regular grow justify-self-start self-center {entry ? 'p-name' : ''}"
|
<h1
|
||||||
>
|
class="
|
||||||
{title}
|
font-monospace text-xl text-ralsei-pink-regular
|
||||||
</h1>
|
grow justify-self-start self-center {entry ? 'p-name' : ''}
|
||||||
{#if iconUri !== ''}
|
"
|
||||||
<img
|
>
|
||||||
class="justify-self-end self-center max-h-7"
|
{title}
|
||||||
style="image-rendering: pixelated;"
|
</h1>
|
||||||
src={iconUri}
|
{#if iconUri !== ''}
|
||||||
alt={iconUri}
|
<img
|
||||||
/>
|
class="justify-self-end self-center max-h-7"
|
||||||
{/if}
|
style="image-rendering: pixelated;"
|
||||||
|
src={iconUri}
|
||||||
|
alt={iconUri}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{/if}
|
||||||
<div class="p-2 bg-gradient-to-tl to-ralsei-pink-neon/15 from-ralsei-pink-regular/20">
|
<div class="
|
||||||
|
{removePadding ? "" : "p-2"} bg-gradient-to-tl
|
||||||
|
to-ralsei-pink-neon/15 from-ralsei-pink-regular/20
|
||||||
|
">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,18 +4,19 @@ import { env } from '$env/dynamic/private'
|
|||||||
|
|
||||||
export interface Note {
|
export interface Note {
|
||||||
content: string,
|
content: string,
|
||||||
published: Date,
|
published: number,
|
||||||
}
|
}
|
||||||
type NoteId = string
|
type NoteId = string
|
||||||
|
|
||||||
export const notesFolder = `${env.WEBSITE_DATA_DIR}/note`
|
export const notesFolder = `${env.WEBSITE_DATA_DIR}/note`
|
||||||
export const notesListFile = `${env.WEBSITE_DATA_DIR}/notes`
|
export const notesListFile = `${env.WEBSITE_DATA_DIR}/notes`
|
||||||
|
export const noteIdLength = 8;
|
||||||
|
|
||||||
export const getNotePath = (id: NoteId) => { return `${notesFolder}/${id}` }
|
export const getNotePath = (id: NoteId) => { return `${notesFolder}/${id}` }
|
||||||
export const genNoteId = () => {
|
export const genNoteId = () => {
|
||||||
let id = nanoid(8)
|
let id = nanoid(noteIdLength)
|
||||||
while (existsSync(getNotePath(id))) {
|
while (existsSync(getNotePath(id))) {
|
||||||
id = nanoid(8)
|
id = nanoid(noteIdLength)
|
||||||
}
|
}
|
||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { noteExists, readNote, readNotesList } from '$lib/notes'
|
import { noteExists, readNote, readNotesList } from '$lib/notes'
|
||||||
|
|
||||||
const notesPerPage: number = 5
|
const notesPerPage: number = 8
|
||||||
|
|
||||||
export const load = ({url}) => {
|
export const load = ({ url }) => {
|
||||||
// get the note id to search for and display the page it is in
|
// get the note id to search for and display the page it is in
|
||||||
const noteId = url.searchParams.get("id")
|
const noteId = url.searchParams.get("id")
|
||||||
// get the page no if one is provided, otherwise default to 1
|
// get the page no if one is provided, otherwise default to 1
|
||||||
@ -26,9 +26,11 @@ export const load = ({url}) => {
|
|||||||
page = Math.max(page, 1)
|
page = Math.max(page, 1)
|
||||||
|
|
||||||
// get the notes from the chosen page
|
// get the notes from the chosen page
|
||||||
const notes = notesList.slice((page - 1) * notesPerPage, page * notesPerPage).map(
|
const notes =
|
||||||
(id) => {return {noteId: id, note: readNote(id)}}
|
notesList.slice((page - 1) * notesPerPage, page * notesPerPage)
|
||||||
)
|
.map(
|
||||||
|
(id) => { return { noteId: id, note: readNote(id) } }
|
||||||
|
)
|
||||||
|
|
||||||
return {notes, highlightedNote: noteId, page}
|
return { notes, highlightedNote: noteId, page }
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,44 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Window from '../../components/window.svelte';
|
import Window from '../../components/window.svelte';
|
||||||
|
import Token from '../../components/token.svelte';
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
|
|
||||||
|
const renderDate = (timestamp: number) => {
|
||||||
|
return (new Date(timestamp)).toLocaleString("en-GB", {
|
||||||
|
year: "2-digit",
|
||||||
|
month: "2-digit",
|
||||||
|
day: "2-digit",
|
||||||
|
hour: "numeric",
|
||||||
|
minute: "2-digit",
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex">
|
<div class="pl-16 pt-16">
|
||||||
<Window title="notes">
|
<Window title="terminal" removePadding>
|
||||||
<div class="prose prose-ralsei">
|
<div
|
||||||
<pre class="language-bash"><code class="language-bash"><span class="token punctuation">[</span>gazesystems <span class="token keyword">/notes/</span><span class="token punctuation">]$</span> <span class="token function">cat</span> *
|
class="
|
||||||
{#each data.notes as {noteId, note}}
|
prose prose-ralsei
|
||||||
|
prose-pre:rounded-none prose-pre:!m-0 prose-pre:!p-2
|
||||||
|
prose-pre:!bg-ralsei-black prose-code:!bg-ralsei-black
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<pre class="language-bash"><code class="language-bash"><nobr>
|
||||||
|
<Token v="[" punct/>gazesystems <Token v="/notes/" keywd/><Token v="]$" punct/> <Token v="source" funct/> note.nu
|
||||||
<br>
|
<br>
|
||||||
<span class="token keyword">{noteId}</span><span class="token punctuation">|> </span><span class="token string">{note.content}</span>
|
<Token v="[" punct/>gazesystems <Token v="/notes/" keywd/><Token v="]$" punct/> <Token v="ls" funct/> notes <Token v="|" punct/> <Token v="each" funct/> <Token v="{" punct/><Token v="|" punct/>file<Token v="|" punct/> <Token v="render" funct/> <Token v="(" punct/><Token v="open" funct/> $file.name<Token v=")" punct/><Token v="}" punct/>
|
||||||
{/each}
|
<br>
|
||||||
</code></pre>
|
<br>
|
||||||
</div>
|
{#each data.notes as { noteId, note }, index}
|
||||||
</Window>
|
<div class="text-wrap break-words max-w-[70ch] leading-none">
|
||||||
|
<Token v={renderDate(note.published)} small/> <Token v={noteId} keywd small/><Token v="#" punct/> <Token v={note.content} str/>
|
||||||
|
</div>
|
||||||
|
{#if index < data.notes.length - 1}
|
||||||
|
<div class="mt-3"/>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</nobr></code></pre>
|
||||||
|
</div>
|
||||||
|
</Window>
|
||||||
</div>
|
</div>
|
||||||
|
@ -28,8 +28,8 @@ export default {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
animation: {
|
animation: {
|
||||||
'bounce-slow' : 'bounce 3s infinite',
|
'bounce-slow': 'bounce 3s infinite',
|
||||||
'pulse-fast' : 'pulse 1s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
'pulse-fast': 'pulse 1s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
||||||
},
|
},
|
||||||
colors: {
|
colors: {
|
||||||
ralsei: {
|
ralsei: {
|
||||||
|
Loading…
Reference in New Issue
Block a user