Add catfishing endpoint and UI
This commit is contained in:
parent
804000f681
commit
746d4b9fee
8 changed files with 353 additions and 0 deletions
|
|
@ -0,0 +1,49 @@
|
|||
<script setup lang="ts">
|
||||
import { useApiRequest } from "@/apiRequest";
|
||||
import { ref, useTemplateRef } from "vue";
|
||||
import CError from "./CError.vue";
|
||||
|
||||
const { disabled, error, makeRequest } = useApiRequest();
|
||||
const form = useTemplateRef<HTMLFormElement>("form");
|
||||
|
||||
const day = ref<number>(448);
|
||||
const feed = ref(true);
|
||||
|
||||
function submit() {
|
||||
const data = new URLSearchParams();
|
||||
if (typeof day.value === "number") data.append("day", day.value.toFixed());
|
||||
data.append("feed", String(feed.value));
|
||||
void makeRequest("api/catfishing", data);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form ref="form" @submit.prevent="submit">
|
||||
<h2>catfishing</h2>
|
||||
|
||||
<label class="wide">
|
||||
Day:
|
||||
<input v-model="day" type="number" min="1" :disabled />
|
||||
</label>
|
||||
|
||||
<div class="wide">
|
||||
<label><input v-model="feed" type="checkbox" :disabled /> Feed</label>
|
||||
</div>
|
||||
|
||||
<button :disabled>Print</button>
|
||||
<CError :message="error" />
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.wide {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
import { ref } from "vue";
|
||||
import CDocumentBanner from "./CDocumentBanner.vue";
|
||||
import CDocumentCalendar from "./CDocumentCalendar.vue";
|
||||
import CDocumentsCatfishing from "./CDocumentCatfishing.vue";
|
||||
import CDocumentCells from "./CDocumentCells.vue";
|
||||
import CDocumentChat from "./CDocumentChat.vue";
|
||||
import CDocumentEgg from "./CDocumentEgg.vue";
|
||||
|
|
@ -14,6 +15,7 @@ import CDocumentXkcd from "./CDocumentXkcd.vue";
|
|||
const mode = ref<
|
||||
| "banner"
|
||||
| "calendar"
|
||||
| "catfishing"
|
||||
| "cells"
|
||||
| "chat"
|
||||
| "egg"
|
||||
|
|
@ -30,6 +32,7 @@ const mode = ref<
|
|||
<button v-if="mode" class="close" @click="mode = undefined">X</button>
|
||||
<CDocumentBanner v-if="mode === 'banner'" />
|
||||
<CDocumentCalendar v-if="mode === 'calendar'" />
|
||||
<CDocumentsCatfishing v-if="mode === 'catfishing'" />
|
||||
<CDocumentCells v-if="mode === 'cells'" />
|
||||
<CDocumentChat v-if="mode === 'chat'" />
|
||||
<CDocumentEgg v-if="mode === 'egg'" />
|
||||
|
|
@ -44,6 +47,7 @@ const mode = ref<
|
|||
<div class="list">
|
||||
<button @click="mode = 'banner'">Banner</button>
|
||||
<button @click="mode = 'calendar'">Calendar</button>
|
||||
<button @click="mode = 'catfishing'">Catfishing</button>
|
||||
<button @click="mode = 'cells'">Cellular Automaton</button>
|
||||
<button @click="mode = 'chat'">Chat Message</button>
|
||||
<button @click="mode = 'egg'">Easter Egg</button>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ pub mod sunrise;
|
|||
pub mod text;
|
||||
pub mod tictactoe;
|
||||
pub mod xkcd;
|
||||
pub mod catfishing;
|
||||
|
||||
fn typst_with_lib() -> Typst {
|
||||
Typst::new().with_file("/lib/main.typ", include_str!("documents/lib/main.typ"))
|
||||
|
|
|
|||
223
showbits-thermal-printer/src/documents/catfishing/data.json
Normal file
223
showbits-thermal-printer/src/documents/catfishing/data.json
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
{
|
||||
"day": 448,
|
||||
"articles": [
|
||||
{
|
||||
"title": "Met Gala",
|
||||
"categories": [
|
||||
"1948 establishments in New York City",
|
||||
"Annual events in New York City",
|
||||
"Balls in the United States",
|
||||
"Fashion events in the United States",
|
||||
"Metropolitan Museum of Art",
|
||||
"Recurring events established in 1948",
|
||||
"Vogue (magazine)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Auto-Tune",
|
||||
"categories": [
|
||||
"1990s in music",
|
||||
"2000s in music",
|
||||
"2010s in music",
|
||||
"Audiovisual introductions in 1997",
|
||||
"Effects units",
|
||||
"Music controversies",
|
||||
"Pitch modification software"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Claus von Stauffenberg",
|
||||
"categories": [
|
||||
"1907 births",
|
||||
"1944 deaths",
|
||||
"Counts in Germany",
|
||||
"Executed failed assassins of Adolf Hitler",
|
||||
"Executed German assassins",
|
||||
"Executed members of the 20 July plot",
|
||||
"Executed military personnel",
|
||||
"Eyepatch wearers",
|
||||
"Failed assassins of Heinrich Himmler",
|
||||
"German amputees",
|
||||
"German anti-communists",
|
||||
"German Army officers of World War II",
|
||||
"German blind people",
|
||||
"German military personnel who were court-martialed",
|
||||
"German nationalist assassins",
|
||||
"German Roman Catholics",
|
||||
"Military personnel from the Kingdom of Bavaria",
|
||||
"People educated at Eberhard-Ludwigs-Gymnasium",
|
||||
"People executed by Nazi Germany by firing squad",
|
||||
"People from Bavaria executed by Nazi Germany",
|
||||
"People from Günzburg (district)",
|
||||
"Recipients of the Gold German Cross",
|
||||
"Reichswehr personnel",
|
||||
"Roman Catholics in the German Resistance"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Apollo Theater",
|
||||
"categories": [
|
||||
"1910s architecture in the United States",
|
||||
"1914 establishments in New York City",
|
||||
"African-American arts organizations",
|
||||
"African-American culture",
|
||||
"African-American theatre",
|
||||
"Black theatre",
|
||||
"Burlesque theatres",
|
||||
"George Keister buildings",
|
||||
"Historically African-American theaters and music venues",
|
||||
"Music venues in Manhattan",
|
||||
"Neoclassical architecture in New York City",
|
||||
"New York City Designated Landmarks in Manhattan",
|
||||
"New York City interior landmarks",
|
||||
"Theatres completed in 1914",
|
||||
"Theatres in Harlem",
|
||||
"Theatres on the National Register of Historic Places in Manhattan",
|
||||
"Tourist attractions in Manhattan"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Atomium",
|
||||
"categories": [
|
||||
"Buildings and structures completed in 1958",
|
||||
"Buildings and structures in Brussels",
|
||||
"Copyright infringement",
|
||||
"Expo 58",
|
||||
"Modernist architecture",
|
||||
"Modernist architecture in Belgium",
|
||||
"Symbols of Brussels",
|
||||
"Tourist attractions in Brussels",
|
||||
"World's fair architecture in Belgium"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Manufacturing Consent",
|
||||
"categories": [
|
||||
"1988 non-fiction books",
|
||||
"Books about media bias",
|
||||
"Books about politics of the United States",
|
||||
"Books about propaganda",
|
||||
"Books about public opinion",
|
||||
"Books by Edward S. Herman",
|
||||
"Books by Noam Chomsky",
|
||||
"Collaborative non-fiction books",
|
||||
"English-language non-fiction books",
|
||||
"Non-fiction books adapted into films",
|
||||
"Pantheon Books books",
|
||||
"Works about the information economy"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "The Shining (film)",
|
||||
"categories": [
|
||||
"1980 films",
|
||||
"1980 horror films",
|
||||
"1980s American films",
|
||||
"1980s British films",
|
||||
"1980s English-language films",
|
||||
"1980s ghost films",
|
||||
"American haunted house films",
|
||||
"American psychological horror films",
|
||||
"British haunted house films",
|
||||
"British psychological horror films",
|
||||
"English-language horror films",
|
||||
"Fiction about familicide",
|
||||
"Fiction about haunted houses",
|
||||
"Films about alcoholism",
|
||||
"Films about domestic violence",
|
||||
"Films about dysfunctional families",
|
||||
"Films about father-son relationships",
|
||||
"Films about mother-son relationships",
|
||||
"Films about telepathy",
|
||||
"Films about twin sisters",
|
||||
"Films about writers",
|
||||
"Films based on American horror novels",
|
||||
"Films based on works by Stephen King",
|
||||
"Films directed by Stanley Kubrick",
|
||||
"Films produced by Stanley Kubrick",
|
||||
"Films scored by Wendy Carlos",
|
||||
"Films set during snowstorms",
|
||||
"Films set in Colorado",
|
||||
"Films set in hotels",
|
||||
"Films set in mazes",
|
||||
"Films shot at EMI-Elstree Studios",
|
||||
"Films shot in chronological order",
|
||||
"Films shot in Hertfordshire",
|
||||
"Films shot in Montana",
|
||||
"Films shot in Oregon",
|
||||
"Films with screenplays by Diane Johnson",
|
||||
"Films with screenplays by Stanley Kubrick",
|
||||
"Saturn Award-winning films",
|
||||
"United States National Film Registry films",
|
||||
"Warner Bros. films"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Witch of Endor",
|
||||
"categories": [
|
||||
"11th-century BC women",
|
||||
"Ancient occultists",
|
||||
"Necromancy",
|
||||
"People from the Kingdom of Israel (united monarchy)",
|
||||
"Samuel",
|
||||
"Saul",
|
||||
"Spiritual mediums",
|
||||
"Unnamed people of the Bible",
|
||||
"Ventriloquists",
|
||||
"Women in the Hebrew Bible"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Nowruz",
|
||||
"categories": [
|
||||
"Ancient Iranian religion",
|
||||
"Culture of Iran",
|
||||
"Festivals in Albania",
|
||||
"Festivals in Azerbaijan",
|
||||
"Festivals in Georgia (country)",
|
||||
"Festivals in Iran",
|
||||
"Festivals in Iraq",
|
||||
"Festivals in Kazakhstan",
|
||||
"Festivals in Kosovo",
|
||||
"Festivals in Kyrgyzstan",
|
||||
"Festivals in Russia",
|
||||
"Festivals in Syria",
|
||||
"Festivals in Turkey",
|
||||
"Festivals in Uzbekistan",
|
||||
"Goldfish in culture",
|
||||
"Intangible Cultural Heritage of India",
|
||||
"March observances",
|
||||
"Masterpieces of the Oral and Intangible Heritage of Humanity",
|
||||
"National symbols of Iran",
|
||||
"New Year celebrations",
|
||||
"Observances on non-Gregorian calendars",
|
||||
"Observances set by the Solar Hijri calendar",
|
||||
"Persian culture",
|
||||
"Persian festivals",
|
||||
"Persian words and phrases",
|
||||
"Public holidays in Afghanistan",
|
||||
"Public holidays in Albania",
|
||||
"Public holidays in Azerbaijan",
|
||||
"Public holidays in Georgia (country)",
|
||||
"Public holidays in Iraq",
|
||||
"Public holidays in Kazakhstan",
|
||||
"Public holidays in Kyrgyzstan",
|
||||
"Public holidays in Uzbekistan",
|
||||
"Spring (season) in Iran",
|
||||
"Spring equinox",
|
||||
"Zoroastrian festivals"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Nagorno-Karabakh",
|
||||
"categories": [
|
||||
"Armenia-Azerbaijan relations",
|
||||
"Armenian irredentism",
|
||||
"Enclaves and exclaves",
|
||||
"Historical regions in Azerbaijan",
|
||||
"Subdivisions of Azerbaijan"
|
||||
]
|
||||
}
|
||||
],
|
||||
"feed": false
|
||||
}
|
||||
1
showbits-thermal-printer/src/documents/catfishing/lib
Symbolic link
1
showbits-thermal-printer/src/documents/catfishing/lib
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../lib
|
||||
19
showbits-thermal-printer/src/documents/catfishing/main.typ
Normal file
19
showbits-thermal-printer/src/documents/catfishing/main.typ
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#import "lib/main.typ" as lib;
|
||||
#show: it => lib.init(it)
|
||||
|
||||
#let data = json("data.json")
|
||||
|
||||
= Catfishing (day #data.day)
|
||||
|
||||
#for article in data.articles [
|
||||
#v(24pt)
|
||||
#for cat in article.categories [
|
||||
- #cat
|
||||
]
|
||||
#v(24pt)
|
||||
#line(length: 100%)
|
||||
]
|
||||
|
||||
#if data.feed {
|
||||
lib.feed
|
||||
}
|
||||
55
showbits-thermal-printer/src/documents/catfishing/mod.rs
Normal file
55
showbits-thermal-printer/src/documents/catfishing/mod.rs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
use axum::{
|
||||
Form,
|
||||
extract::State,
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::server::{Server, somehow};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct ArticleInfo {
|
||||
title: String,
|
||||
categories: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct Data {
|
||||
day: u32,
|
||||
articles: Vec<ArticleInfo>,
|
||||
feed: bool,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct FormData {
|
||||
pub day: u32,
|
||||
pub feed: bool,
|
||||
}
|
||||
|
||||
pub async fn post(server: State<Server>, Form(form): Form<FormData>) -> somehow::Result<Response> {
|
||||
let client = reqwest::Client::builder()
|
||||
.user_agent(crate::USER_AGENT)
|
||||
.build()?;
|
||||
|
||||
let url = format!("https://static.catfishing.net/daily/{}.json", form.day);
|
||||
|
||||
let articles = client
|
||||
.get(url)
|
||||
.send()
|
||||
.await?
|
||||
.json::<Vec<ArticleInfo>>()
|
||||
.await?;
|
||||
|
||||
let data = Data {
|
||||
day: form.day,
|
||||
articles,
|
||||
feed: form.feed,
|
||||
};
|
||||
|
||||
let typst = super::typst_with_lib()
|
||||
.with_json("/data.json", &data)
|
||||
.with_main_file(include_str!("main.typ"));
|
||||
|
||||
server.print_typst(typst).await?;
|
||||
Ok(().into_response())
|
||||
}
|
||||
|
|
@ -45,6 +45,7 @@ pub async fn run(
|
|||
// API
|
||||
.route("/api/banner", post(documents::banner::post))
|
||||
.route("/api/calendar", post(documents::calendar::post))
|
||||
.route("/api/catfishing", post(documents::catfishing::post))
|
||||
.route("/api/cells", post(documents::cells::post))
|
||||
.route("/api/chat", post(documents::chat::post))
|
||||
.route("/api/egg", post(documents::egg::post))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue