mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 20:01:09 +02:00
✨ feat(zitare): add @zitare/content package for shared quotes
- Create new @zitare/content package with 50 German quotes - Include 10 categories: motivation, weisheit, liebe, leben, erfolg, glueck, freundschaft, mut, hoffnung, natur - Add utility functions: getRandomQuote, getDailyQuote, searchQuotes, getQuotesByCategory, formatQuote, etc. - Migrate matrix-zitare-bot to use the shared package - Remove hardcoded quotes from bot configuration
This commit is contained in:
parent
9924eb545a
commit
74c1cfed4f
13 changed files with 1069 additions and 660 deletions
24
apps/zitare/packages/content/package.json
Normal file
24
apps/zitare/packages/content/package.json
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "@zitare/content",
|
||||
"version": "1.0.0",
|
||||
"description": "Static quote content for Zitare",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.cjs"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsup",
|
||||
"type-check": "tsc --noEmit"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tsup": "^8.0.0",
|
||||
"typescript": "^5.3.0"
|
||||
}
|
||||
}
|
||||
47
apps/zitare/packages/content/src/categories.ts
Normal file
47
apps/zitare/packages/content/src/categories.ts
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* Quote categories
|
||||
*/
|
||||
export const CATEGORIES = [
|
||||
'motivation',
|
||||
'weisheit',
|
||||
'liebe',
|
||||
'leben',
|
||||
'erfolg',
|
||||
'glueck',
|
||||
'freundschaft',
|
||||
'mut',
|
||||
'hoffnung',
|
||||
'natur',
|
||||
] as const;
|
||||
|
||||
export type Category = (typeof CATEGORIES)[number];
|
||||
|
||||
/**
|
||||
* German labels for categories
|
||||
*/
|
||||
export const CATEGORY_LABELS: Record<Category, string> = {
|
||||
motivation: 'Motivation',
|
||||
weisheit: 'Weisheit',
|
||||
liebe: 'Liebe',
|
||||
leben: 'Leben',
|
||||
erfolg: 'Erfolg',
|
||||
glueck: 'Glueck',
|
||||
freundschaft: 'Freundschaft',
|
||||
mut: 'Mut',
|
||||
hoffnung: 'Hoffnung',
|
||||
natur: 'Natur',
|
||||
};
|
||||
|
||||
/**
|
||||
* Get label for a category
|
||||
*/
|
||||
export function getCategoryLabel(category: Category): string {
|
||||
return CATEGORY_LABELS[category];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a string is a valid category
|
||||
*/
|
||||
export function isValidCategory(value: string): value is Category {
|
||||
return CATEGORIES.includes(value as Category);
|
||||
}
|
||||
25
apps/zitare/packages/content/src/index.ts
Normal file
25
apps/zitare/packages/content/src/index.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// Types
|
||||
export type { Quote } from './types';
|
||||
export type { Category } from './categories';
|
||||
|
||||
// Data
|
||||
export { QUOTES, QUOTE_COUNT } from './quotes';
|
||||
export { CATEGORIES, CATEGORY_LABELS } from './categories';
|
||||
|
||||
// Utilities
|
||||
export {
|
||||
getRandomQuote,
|
||||
getDailyQuote,
|
||||
getQuotesByCategory,
|
||||
getRandomQuoteByCategory,
|
||||
searchQuotes,
|
||||
getQuoteById,
|
||||
getQuoteByIndex,
|
||||
getAllCategories,
|
||||
getCategoryByName,
|
||||
formatQuote,
|
||||
formatQuoteWithNumber,
|
||||
getTotalCount,
|
||||
} from './utils';
|
||||
|
||||
export { getCategoryLabel, isValidCategory } from './categories';
|
||||
375
apps/zitare/packages/content/src/quotes.ts
Normal file
375
apps/zitare/packages/content/src/quotes.ts
Normal file
|
|
@ -0,0 +1,375 @@
|
|||
import type { Quote } from './types';
|
||||
|
||||
/**
|
||||
* German inspirational quotes collection
|
||||
*/
|
||||
export const QUOTES: Quote[] = [
|
||||
// ============================================
|
||||
// MOTIVATION
|
||||
// ============================================
|
||||
{
|
||||
id: 'mot-1',
|
||||
text: 'Der einzige Weg, grossartige Arbeit zu leisten, ist zu lieben, was man tut.',
|
||||
author: 'Steve Jobs',
|
||||
category: 'motivation',
|
||||
},
|
||||
{
|
||||
id: 'mot-2',
|
||||
text: 'Erfolg ist nicht endgueltig, Misserfolg ist nicht fatal: Was zaehlt, ist der Mut weiterzumachen.',
|
||||
author: 'Winston Churchill',
|
||||
category: 'motivation',
|
||||
},
|
||||
{
|
||||
id: 'mot-3',
|
||||
text: 'Die Zukunft gehoert denen, die an die Schoenheit ihrer Traeume glauben.',
|
||||
author: 'Eleanor Roosevelt',
|
||||
category: 'motivation',
|
||||
},
|
||||
{
|
||||
id: 'mot-4',
|
||||
text: 'Es ist nie zu spaet, das zu werden, was man haette sein koennen.',
|
||||
author: 'George Eliot',
|
||||
category: 'motivation',
|
||||
},
|
||||
{
|
||||
id: 'mot-5',
|
||||
text: 'Gib jedem Tag die Chance, der schoenste deines Lebens zu werden.',
|
||||
author: 'Mark Twain',
|
||||
category: 'motivation',
|
||||
},
|
||||
{
|
||||
id: 'mot-6',
|
||||
text: 'Der Anfang ist die Haelfte des Ganzen.',
|
||||
author: 'Aristoteles',
|
||||
category: 'motivation',
|
||||
},
|
||||
{
|
||||
id: 'mot-7',
|
||||
text: 'Tue heute etwas, wofuer dein zukuenftiges Ich dir danken wird.',
|
||||
author: 'Sean Patrick Flanery',
|
||||
category: 'motivation',
|
||||
},
|
||||
{
|
||||
id: 'mot-8',
|
||||
text: 'Der beste Zeitpunkt einen Baum zu pflanzen war vor 20 Jahren. Der zweitbeste ist jetzt.',
|
||||
author: 'Chinesisches Sprichwort',
|
||||
category: 'motivation',
|
||||
},
|
||||
|
||||
// ============================================
|
||||
// WEISHEIT
|
||||
// ============================================
|
||||
{
|
||||
id: 'weis-1',
|
||||
text: 'Der Weg ist das Ziel.',
|
||||
author: 'Konfuzius',
|
||||
category: 'weisheit',
|
||||
},
|
||||
{
|
||||
id: 'weis-2',
|
||||
text: 'Wer kaempft, kann verlieren. Wer nicht kaempft, hat schon verloren.',
|
||||
author: 'Bertolt Brecht',
|
||||
category: 'weisheit',
|
||||
},
|
||||
{
|
||||
id: 'weis-3',
|
||||
text: 'Man sieht nur mit dem Herzen gut. Das Wesentliche ist fuer die Augen unsichtbar.',
|
||||
author: 'Antoine de Saint-Exupery',
|
||||
category: 'weisheit',
|
||||
},
|
||||
{
|
||||
id: 'weis-4',
|
||||
text: 'Nicht weil es schwer ist, wagen wir es nicht, sondern weil wir es nicht wagen, ist es schwer.',
|
||||
author: 'Seneca',
|
||||
category: 'weisheit',
|
||||
},
|
||||
{
|
||||
id: 'weis-5',
|
||||
text: 'Wissen ist Macht.',
|
||||
author: 'Francis Bacon',
|
||||
category: 'weisheit',
|
||||
},
|
||||
{
|
||||
id: 'weis-6',
|
||||
text: 'Ich weiss, dass ich nichts weiss.',
|
||||
author: 'Sokrates',
|
||||
category: 'weisheit',
|
||||
},
|
||||
{
|
||||
id: 'weis-7',
|
||||
text: 'Die einzige Konstante im Leben ist die Veraenderung.',
|
||||
author: 'Heraklit',
|
||||
category: 'weisheit',
|
||||
},
|
||||
{
|
||||
id: 'weis-8',
|
||||
text: 'Handle nur nach derjenigen Maxime, durch die du zugleich wollen kannst, dass sie ein allgemeines Gesetz werde.',
|
||||
author: 'Immanuel Kant',
|
||||
category: 'weisheit',
|
||||
},
|
||||
|
||||
// ============================================
|
||||
// LIEBE
|
||||
// ============================================
|
||||
{
|
||||
id: 'liebe-1',
|
||||
text: 'Wo Liebe ist, da ist auch Leben.',
|
||||
author: 'Mahatma Gandhi',
|
||||
category: 'liebe',
|
||||
},
|
||||
{
|
||||
id: 'liebe-2',
|
||||
text: 'Die Liebe allein versteht das Geheimnis, andere zu beschenken und dabei selbst reich zu werden.',
|
||||
author: 'Clemens Brentano',
|
||||
category: 'liebe',
|
||||
},
|
||||
{
|
||||
id: 'liebe-3',
|
||||
text: 'Es gibt nur ein Glueck in diesem Leben: zu lieben und geliebt zu werden.',
|
||||
author: 'George Sand',
|
||||
category: 'liebe',
|
||||
},
|
||||
{
|
||||
id: 'liebe-4',
|
||||
text: 'Liebe ist das einzige, was waechst, wenn wir es verschwenden.',
|
||||
author: 'Ricarda Huch',
|
||||
category: 'liebe',
|
||||
},
|
||||
{
|
||||
id: 'liebe-5',
|
||||
text: 'Die groesste Sache der Welt ist es, zu wissen, wie man sich selbst gehoert.',
|
||||
author: 'Michel de Montaigne',
|
||||
category: 'liebe',
|
||||
},
|
||||
|
||||
// ============================================
|
||||
// LEBEN
|
||||
// ============================================
|
||||
{
|
||||
id: 'leben-1',
|
||||
text: 'Das Leben ist wie Fahrrad fahren. Um die Balance zu halten, musst du in Bewegung bleiben.',
|
||||
author: 'Albert Einstein',
|
||||
category: 'leben',
|
||||
},
|
||||
{
|
||||
id: 'leben-2',
|
||||
text: 'Leben ist das, was passiert, waehrend du damit beschaeftigt bist, andere Plaene zu machen.',
|
||||
author: 'John Lennon',
|
||||
category: 'leben',
|
||||
},
|
||||
{
|
||||
id: 'leben-3',
|
||||
text: 'Das Leben ist zu kurz fuer spaeter.',
|
||||
author: 'Alexandra Reinwarth',
|
||||
category: 'leben',
|
||||
},
|
||||
{
|
||||
id: 'leben-4',
|
||||
text: 'Lebe jeden Tag, als waere es dein letzter.',
|
||||
author: 'Marcus Aurelius',
|
||||
category: 'leben',
|
||||
},
|
||||
{
|
||||
id: 'leben-5',
|
||||
text: 'Das Leben ist kein Problem, das geloest werden muss, sondern eine Wirklichkeit, die erfahren werden will.',
|
||||
author: 'Soeren Kierkegaard',
|
||||
category: 'leben',
|
||||
},
|
||||
{
|
||||
id: 'leben-6',
|
||||
text: 'Wer sein Leben so einrichtet, dass er niemals auf die Nase fallen kann, der kann nur auf dem Bauch kriechen.',
|
||||
author: 'Heinz Riesenhuber',
|
||||
category: 'leben',
|
||||
},
|
||||
|
||||
// ============================================
|
||||
// ERFOLG
|
||||
// ============================================
|
||||
{
|
||||
id: 'erfolg-1',
|
||||
text: 'Erfolg besteht darin, dass man genau die Faehigkeiten hat, die im Moment gefragt sind.',
|
||||
author: 'Henry Ford',
|
||||
category: 'erfolg',
|
||||
},
|
||||
{
|
||||
id: 'erfolg-2',
|
||||
text: 'Der Preis des Erfolges ist Hingabe, harte Arbeit und unablaessiger Einsatz.',
|
||||
author: 'Frank Lloyd Wright',
|
||||
category: 'erfolg',
|
||||
},
|
||||
{
|
||||
id: 'erfolg-3',
|
||||
text: 'Ich habe nicht versagt. Ich habe nur 10.000 Wege gefunden, die nicht funktionieren.',
|
||||
author: 'Thomas Edison',
|
||||
category: 'erfolg',
|
||||
},
|
||||
{
|
||||
id: 'erfolg-4',
|
||||
text: 'Der Erfolg ist nicht das Endergebnis, das Scheitern ist nicht toedlich: Was zaehlt, ist der Mut, weiterzumachen.',
|
||||
author: 'Winston Churchill',
|
||||
category: 'erfolg',
|
||||
},
|
||||
{
|
||||
id: 'erfolg-5',
|
||||
text: 'Erfolg hat drei Buchstaben: TUN.',
|
||||
author: 'Johann Wolfgang von Goethe',
|
||||
category: 'erfolg',
|
||||
},
|
||||
|
||||
// ============================================
|
||||
// GLUECK
|
||||
// ============================================
|
||||
{
|
||||
id: 'glueck-1',
|
||||
text: 'Glueck ist das Einzige, das sich verdoppelt, wenn man es teilt.',
|
||||
author: 'Albert Schweitzer',
|
||||
category: 'glueck',
|
||||
},
|
||||
{
|
||||
id: 'glueck-2',
|
||||
text: 'Glueck ist kein Ziel, sondern ein Weg.',
|
||||
author: 'Buddha',
|
||||
category: 'glueck',
|
||||
},
|
||||
{
|
||||
id: 'glueck-3',
|
||||
text: 'Nicht die Gluecklichen sind dankbar. Es sind die Dankbaren, die gluecklich sind.',
|
||||
author: 'Francis Bacon',
|
||||
category: 'glueck',
|
||||
},
|
||||
{
|
||||
id: 'glueck-4',
|
||||
text: 'Das Vergleichen ist das Ende des Gluecks und der Anfang der Unzufriedenheit.',
|
||||
author: 'Soeren Kierkegaard',
|
||||
category: 'glueck',
|
||||
},
|
||||
{
|
||||
id: 'glueck-5',
|
||||
text: 'Glueck entsteht oft durch Aufmerksamkeit in kleinen Dingen, Unglueck oft durch Vernachlaessigung kleiner Dinge.',
|
||||
author: 'Wilhelm Busch',
|
||||
category: 'glueck',
|
||||
},
|
||||
|
||||
// ============================================
|
||||
// FREUNDSCHAFT
|
||||
// ============================================
|
||||
{
|
||||
id: 'freund-1',
|
||||
text: 'Ein wahrer Freund ist jemand, der die Melodie deines Herzens kennt und sie dir vorsingt, wenn du sie vergessen hast.',
|
||||
author: 'Albert Einstein',
|
||||
category: 'freundschaft',
|
||||
},
|
||||
{
|
||||
id: 'freund-2',
|
||||
text: 'Freundschaft ist eine Seele in zwei Koerpern.',
|
||||
author: 'Aristoteles',
|
||||
category: 'freundschaft',
|
||||
},
|
||||
{
|
||||
id: 'freund-3',
|
||||
text: 'Ein Freund ist ein Mensch, vor dem man laut denken kann.',
|
||||
author: 'Ralph Waldo Emerson',
|
||||
category: 'freundschaft',
|
||||
},
|
||||
{
|
||||
id: 'freund-4',
|
||||
text: 'Die Freundschaft gehoert zum Notwendigsten in unserem Leben.',
|
||||
author: 'Aristoteles',
|
||||
category: 'freundschaft',
|
||||
},
|
||||
|
||||
// ============================================
|
||||
// MUT
|
||||
// ============================================
|
||||
{
|
||||
id: 'mut-1',
|
||||
text: 'Mut steht am Anfang des Handelns, Glueck am Ende.',
|
||||
author: 'Demokrit',
|
||||
category: 'mut',
|
||||
},
|
||||
{
|
||||
id: 'mut-2',
|
||||
text: 'Wer wagt, gewinnt.',
|
||||
author: 'Deutsches Sprichwort',
|
||||
category: 'mut',
|
||||
},
|
||||
{
|
||||
id: 'mut-3',
|
||||
text: 'Der Mutige hat nicht weniger Angst, er handelt trotzdem.',
|
||||
author: 'Mark Twain',
|
||||
category: 'mut',
|
||||
},
|
||||
{
|
||||
id: 'mut-4',
|
||||
text: 'Mut ist nicht die Abwesenheit von Angst, sondern die Erkenntnis, dass etwas anderes wichtiger ist als Angst.',
|
||||
author: 'Ambrose Redmoon',
|
||||
category: 'mut',
|
||||
},
|
||||
{
|
||||
id: 'mut-5',
|
||||
text: 'Inmitten der Schwierigkeit liegt die Moeglichkeit.',
|
||||
author: 'Albert Einstein',
|
||||
category: 'mut',
|
||||
},
|
||||
|
||||
// ============================================
|
||||
// HOFFNUNG
|
||||
// ============================================
|
||||
{
|
||||
id: 'hoff-1',
|
||||
text: 'Hoffnung ist ein Vogel, der singt, wenn die Nacht noch dunkel ist.',
|
||||
author: 'Rabindranath Tagore',
|
||||
category: 'hoffnung',
|
||||
},
|
||||
{
|
||||
id: 'hoff-2',
|
||||
text: 'Nach jedem Sturm scheint auch wieder die Sonne.',
|
||||
author: 'Deutsches Sprichwort',
|
||||
category: 'hoffnung',
|
||||
},
|
||||
{
|
||||
id: 'hoff-3',
|
||||
text: 'Auch aus Steinen, die einem in den Weg gelegt werden, kann man Schoenes bauen.',
|
||||
author: 'Johann Wolfgang von Goethe',
|
||||
category: 'hoffnung',
|
||||
},
|
||||
{
|
||||
id: 'hoff-4',
|
||||
text: 'Das Licht am Ende des Tunnels ist kein Zug.',
|
||||
author: 'Deutsches Sprichwort',
|
||||
category: 'hoffnung',
|
||||
},
|
||||
|
||||
// ============================================
|
||||
// NATUR
|
||||
// ============================================
|
||||
{
|
||||
id: 'natur-1',
|
||||
text: 'In der Natur ist nichts isoliert; alles haengt mit allem zusammen.',
|
||||
author: 'Johann Wolfgang von Goethe',
|
||||
category: 'natur',
|
||||
},
|
||||
{
|
||||
id: 'natur-2',
|
||||
text: 'Schau tief in die Natur, und dann wirst du alles besser verstehen.',
|
||||
author: 'Albert Einstein',
|
||||
category: 'natur',
|
||||
},
|
||||
{
|
||||
id: 'natur-3',
|
||||
text: 'Die Natur macht keine Spruenge.',
|
||||
author: 'Carl von Linne',
|
||||
category: 'natur',
|
||||
},
|
||||
{
|
||||
id: 'natur-4',
|
||||
text: 'Vergiss nicht, dass die Erde sich freut, deine nackten Fuesse zu fuehlen, und die Winde sich danach sehnen, mit deinem Haar zu spielen.',
|
||||
author: 'Khalil Gibran',
|
||||
category: 'natur',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* Total number of quotes
|
||||
*/
|
||||
export const QUOTE_COUNT = QUOTES.length;
|
||||
15
apps/zitare/packages/content/src/types.ts
Normal file
15
apps/zitare/packages/content/src/types.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import type { Category } from './categories';
|
||||
|
||||
/**
|
||||
* A quote with author and category
|
||||
*/
|
||||
export interface Quote {
|
||||
/** Unique identifier (e.g., 'mot-1', 'weis-2') */
|
||||
id: string;
|
||||
/** The quote text in German */
|
||||
text: string;
|
||||
/** Author name */
|
||||
author: string;
|
||||
/** Category for filtering */
|
||||
category: Category;
|
||||
}
|
||||
133
apps/zitare/packages/content/src/utils.ts
Normal file
133
apps/zitare/packages/content/src/utils.ts
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
import { QUOTES } from './quotes';
|
||||
import { CATEGORIES, CATEGORY_LABELS, type Category } from './categories';
|
||||
import type { Quote } from './types';
|
||||
|
||||
/**
|
||||
* Get a random quote
|
||||
*/
|
||||
export function getRandomQuote(): Quote {
|
||||
const index = Math.floor(Math.random() * QUOTES.length);
|
||||
return QUOTES[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get deterministic daily quote based on date
|
||||
*/
|
||||
export function getDailyQuote(date: Date = new Date()): Quote {
|
||||
const dateStr = date.toISOString().split('T')[0];
|
||||
const hash = hashString(dateStr);
|
||||
const index = Math.abs(hash) % QUOTES.length;
|
||||
return QUOTES[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get quotes by category
|
||||
*/
|
||||
export function getQuotesByCategory(category: Category): Quote[] {
|
||||
return QUOTES.filter((q) => q.category === category);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random quote from a specific category
|
||||
*/
|
||||
export function getRandomQuoteByCategory(category: Category): Quote | null {
|
||||
const quotes = getQuotesByCategory(category);
|
||||
if (quotes.length === 0) return null;
|
||||
const index = Math.floor(Math.random() * quotes.length);
|
||||
return quotes[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Search quotes by text or author
|
||||
*/
|
||||
export function searchQuotes(searchText: string): Quote[] {
|
||||
const lowerSearch = searchText.toLowerCase();
|
||||
return QUOTES.filter(
|
||||
(q) =>
|
||||
q.text.toLowerCase().includes(lowerSearch) || q.author.toLowerCase().includes(lowerSearch)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a quote by ID
|
||||
*/
|
||||
export function getQuoteById(id: string): Quote | undefined {
|
||||
return QUOTES.find((q) => q.id === id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get quote by index (1-based)
|
||||
*/
|
||||
export function getQuoteByIndex(index: number): Quote | null {
|
||||
if (index < 1 || index > QUOTES.length) return null;
|
||||
return QUOTES[index - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all categories with counts
|
||||
*/
|
||||
export function getAllCategories(): { category: Category; label: string; count: number }[] {
|
||||
return CATEGORIES.map((category) => ({
|
||||
category,
|
||||
label: CATEGORY_LABELS[category],
|
||||
count: QUOTES.filter((q) => q.category === category).length,
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find category by name (partial match)
|
||||
*/
|
||||
export function getCategoryByName(name: string): Category | null {
|
||||
const lowerName = name.toLowerCase();
|
||||
|
||||
// Exact match first
|
||||
if (CATEGORIES.includes(lowerName as Category)) {
|
||||
return lowerName as Category;
|
||||
}
|
||||
|
||||
// Partial match
|
||||
for (const category of CATEGORIES) {
|
||||
if (
|
||||
category.startsWith(lowerName) ||
|
||||
CATEGORY_LABELS[category].toLowerCase().startsWith(lowerName)
|
||||
) {
|
||||
return category;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a quote for display
|
||||
*/
|
||||
export function formatQuote(quote: Quote): string {
|
||||
const categoryLabel = CATEGORY_LABELS[quote.category];
|
||||
return `"${quote.text}"\n\n— *${quote.author}*\n\n[${categoryLabel}]`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a quote with number
|
||||
*/
|
||||
export function formatQuoteWithNumber(quote: Quote, number: number): string {
|
||||
const categoryLabel = CATEGORY_LABELS[quote.category];
|
||||
return `**#${number}**\n"${quote.text}"\n\n— *${quote.author}* [${categoryLabel}]`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total quote count
|
||||
*/
|
||||
export function getTotalCount(): number {
|
||||
return QUOTES.length;
|
||||
}
|
||||
|
||||
// Helper function
|
||||
function hashString(str: string): number {
|
||||
let hash = 0;
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
const char = str.charCodeAt(i);
|
||||
hash = (hash << 5) - hash + char;
|
||||
hash = hash & hash;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
16
apps/zitare/packages/content/tsconfig.json
Normal file
16
apps/zitare/packages/content/tsconfig.json
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
9
apps/zitare/packages/content/tsup.config.ts
Normal file
9
apps/zitare/packages/content/tsup.config.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import { defineConfig } from 'tsup';
|
||||
|
||||
export default defineConfig({
|
||||
entry: ['src/index.ts'],
|
||||
format: ['esm', 'cjs'],
|
||||
dts: true,
|
||||
clean: true,
|
||||
sourcemap: true,
|
||||
});
|
||||
736
pnpm-lock.yaml
generated
736
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
|
@ -25,6 +25,7 @@
|
|||
"dependencies": {
|
||||
"@manacore/bot-services": "workspace:*",
|
||||
"@manacore/matrix-bot-common": "workspace:*",
|
||||
"@zitare/content": "workspace:*",
|
||||
"@nestjs/common": "^10.4.15",
|
||||
"@nestjs/config": "^3.3.0",
|
||||
"@nestjs/core": "^10.4.15",
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ import {
|
|||
import { QuotesService } from '../quotes/quotes.service';
|
||||
import { ZitareService } from '../quotes/zitare.service';
|
||||
import { SessionService, TranscriptionService, CreditService } from '@manacore/bot-services';
|
||||
import { HELP_MESSAGE, Category } from '../config/configuration';
|
||||
import { HELP_MESSAGE } from '../config/configuration';
|
||||
import type { Category } from '@zitare/content';
|
||||
|
||||
@Injectable()
|
||||
export class MatrixService extends BaseMatrixService {
|
||||
|
|
|
|||
|
|
@ -18,10 +18,10 @@ export default () => ({
|
|||
},
|
||||
});
|
||||
|
||||
export const HELP_MESSAGE = `**Zitare Bot - Tagliche Inspiration**
|
||||
export const HELP_MESSAGE = `**Zitare Bot - Taegliche Inspiration**
|
||||
|
||||
**Zitate:**
|
||||
- \`!zitat\` - Zufalliges Zitat
|
||||
- \`!zitat\` - Zufaelliges Zitat
|
||||
- \`!heute\` - Zitat des Tages
|
||||
- \`!suche [text]\` - Zitate suchen
|
||||
- \`!kategorie [name]\` - Zitate nach Kategorie
|
||||
|
|
@ -36,7 +36,7 @@ export const HELP_MESSAGE = `**Zitare Bot - Tagliche Inspiration**
|
|||
**Listen:** (Login erforderlich)
|
||||
- \`!listen\` - Alle Listen anzeigen
|
||||
- \`!liste [name]\` - Neue Liste erstellen
|
||||
- \`!addliste [nr] [zitat-nr]\` - Zitat zur Liste hinzufugen
|
||||
- \`!addliste [nr] [zitat-nr]\` - Zitat zur Liste hinzufuegen
|
||||
|
||||
**Sonstiges:**
|
||||
- \`!status\` - Bot-Status
|
||||
|
|
@ -45,250 +45,11 @@ export const HELP_MESSAGE = `**Zitare Bot - Tagliche Inspiration**
|
|||
**Sprachnotizen:**
|
||||
Sende eine Sprachnotiz mit Befehlen wie "Zitat", "Motivation" oder einem Suchbegriff.
|
||||
|
||||
**Naturliche Sprache:**
|
||||
- "zitat", "inspiration" -> Zufalliges Zitat
|
||||
**Natuerliche Sprache:**
|
||||
- "zitat", "inspiration" -> Zufaelliges Zitat
|
||||
- "motiviere mich" -> Motivation-Zitat
|
||||
- "guten morgen" -> Morgenzitat`;
|
||||
|
||||
// Quote categories
|
||||
export const CATEGORIES = [
|
||||
'motivation',
|
||||
'weisheit',
|
||||
'liebe',
|
||||
'leben',
|
||||
'erfolg',
|
||||
'glueck',
|
||||
'freundschaft',
|
||||
'mut',
|
||||
'hoffnung',
|
||||
'natur',
|
||||
] as const;
|
||||
|
||||
export type Category = (typeof CATEGORIES)[number];
|
||||
|
||||
// German inspirational quotes collection
|
||||
export interface Quote {
|
||||
id: string;
|
||||
text: string;
|
||||
author: string;
|
||||
category: Category;
|
||||
}
|
||||
|
||||
export const QUOTES: Quote[] = [
|
||||
// Motivation
|
||||
{
|
||||
id: 'mot-1',
|
||||
text: 'Der einzige Weg, grossartige Arbeit zu leisten, ist zu lieben, was man tut.',
|
||||
author: 'Steve Jobs',
|
||||
category: 'motivation',
|
||||
},
|
||||
{
|
||||
id: 'mot-2',
|
||||
text: 'Erfolg ist nicht endgultig, Misserfolg ist nicht fatal: Was zahlt, ist der Mut weiterzumachen.',
|
||||
author: 'Winston Churchill',
|
||||
category: 'motivation',
|
||||
},
|
||||
{
|
||||
id: 'mot-3',
|
||||
text: 'Die Zukunft gehort denen, die an die Schonheit ihrer Traume glauben.',
|
||||
author: 'Eleanor Roosevelt',
|
||||
category: 'motivation',
|
||||
},
|
||||
{
|
||||
id: 'mot-4',
|
||||
text: 'Es ist nie zu spat, das zu werden, was man hatte sein konnen.',
|
||||
author: 'George Eliot',
|
||||
category: 'motivation',
|
||||
},
|
||||
{
|
||||
id: 'mot-5',
|
||||
text: 'Gib jedem Tag die Chance, der schonste deines Lebens zu werden.',
|
||||
author: 'Mark Twain',
|
||||
category: 'motivation',
|
||||
},
|
||||
// Weisheit
|
||||
{
|
||||
id: 'weis-1',
|
||||
text: 'Der Weg ist das Ziel.',
|
||||
author: 'Konfuzius',
|
||||
category: 'weisheit',
|
||||
},
|
||||
{
|
||||
id: 'weis-2',
|
||||
text: 'Wer kampft, kann verlieren. Wer nicht kampft, hat schon verloren.',
|
||||
author: 'Bertolt Brecht',
|
||||
category: 'weisheit',
|
||||
},
|
||||
{
|
||||
id: 'weis-3',
|
||||
text: 'Man sieht nur mit dem Herzen gut. Das Wesentliche ist fur die Augen unsichtbar.',
|
||||
author: 'Antoine de Saint-Exupery',
|
||||
category: 'weisheit',
|
||||
},
|
||||
{
|
||||
id: 'weis-4',
|
||||
text: 'Nicht weil es schwer ist, wagen wir es nicht, sondern weil wir es nicht wagen, ist es schwer.',
|
||||
author: 'Seneca',
|
||||
category: 'weisheit',
|
||||
},
|
||||
{
|
||||
id: 'weis-5',
|
||||
text: 'Wissen ist Macht.',
|
||||
author: 'Francis Bacon',
|
||||
category: 'weisheit',
|
||||
},
|
||||
// Liebe
|
||||
{
|
||||
id: 'liebe-1',
|
||||
text: 'Wo Liebe ist, da ist auch Leben.',
|
||||
author: 'Mahatma Gandhi',
|
||||
category: 'liebe',
|
||||
},
|
||||
{
|
||||
id: 'liebe-2',
|
||||
text: 'Die Liebe allein versteht das Geheimnis, andere zu beschenken und dabei selbst reich zu werden.',
|
||||
author: 'Clemens Brentano',
|
||||
category: 'liebe',
|
||||
},
|
||||
{
|
||||
id: 'liebe-3',
|
||||
text: 'Es gibt nur ein Gluck in diesem Leben: zu lieben und geliebt zu werden.',
|
||||
author: 'George Sand',
|
||||
category: 'liebe',
|
||||
},
|
||||
// Leben
|
||||
{
|
||||
id: 'leben-1',
|
||||
text: 'Das Leben ist wie Fahrrad fahren. Um die Balance zu halten, musst du in Bewegung bleiben.',
|
||||
author: 'Albert Einstein',
|
||||
category: 'leben',
|
||||
},
|
||||
{
|
||||
id: 'leben-2',
|
||||
text: 'Leben ist das, was passiert, wahrend du damit beschaftigt bist, andere Plane zu machen.',
|
||||
author: 'John Lennon',
|
||||
category: 'leben',
|
||||
},
|
||||
{
|
||||
id: 'leben-3',
|
||||
text: 'Das Leben ist zu kurz fur spater.',
|
||||
author: 'Alexandra Reinwarth',
|
||||
category: 'leben',
|
||||
},
|
||||
{
|
||||
id: 'leben-4',
|
||||
text: 'Lebe jeden Tag, als ware es dein letzter.',
|
||||
author: 'Marcus Aurelius',
|
||||
category: 'leben',
|
||||
},
|
||||
// Erfolg
|
||||
{
|
||||
id: 'erfolg-1',
|
||||
text: 'Erfolg besteht darin, dass man genau die Fahigkeiten hat, die im Moment gefragt sind.',
|
||||
author: 'Henry Ford',
|
||||
category: 'erfolg',
|
||||
},
|
||||
{
|
||||
id: 'erfolg-2',
|
||||
text: 'Der Preis des Erfolges ist Hingabe, harte Arbeit und unablassiger Einsatz.',
|
||||
author: 'Frank Lloyd Wright',
|
||||
category: 'erfolg',
|
||||
},
|
||||
{
|
||||
id: 'erfolg-3',
|
||||
text: 'Ich habe nicht versagt. Ich habe nur 10.000 Wege gefunden, die nicht funktionieren.',
|
||||
author: 'Thomas Edison',
|
||||
category: 'erfolg',
|
||||
},
|
||||
// Glueck
|
||||
{
|
||||
id: 'glueck-1',
|
||||
text: 'Gluck ist das Einzige, das sich verdoppelt, wenn man es teilt.',
|
||||
author: 'Albert Schweitzer',
|
||||
category: 'glueck',
|
||||
},
|
||||
{
|
||||
id: 'glueck-2',
|
||||
text: 'Gluck ist kein Ziel, sondern ein Weg.',
|
||||
author: 'Buddha',
|
||||
category: 'glueck',
|
||||
},
|
||||
{
|
||||
id: 'glueck-3',
|
||||
text: 'Nicht die Glucklichen sind dankbar. Es sind die Dankbaren, die glucklich sind.',
|
||||
author: 'Francis Bacon',
|
||||
category: 'glueck',
|
||||
},
|
||||
// Freundschaft
|
||||
{
|
||||
id: 'freund-1',
|
||||
text: 'Ein wahrer Freund ist jemand, der die Melodie deines Herzens kennt und sie dir vorsingt, wenn du sie vergessen hast.',
|
||||
author: 'Albert Einstein',
|
||||
category: 'freundschaft',
|
||||
},
|
||||
{
|
||||
id: 'freund-2',
|
||||
text: 'Freundschaft ist eine Seele in zwei Korpern.',
|
||||
author: 'Aristoteles',
|
||||
category: 'freundschaft',
|
||||
},
|
||||
// Mut
|
||||
{
|
||||
id: 'mut-1',
|
||||
text: 'Mut steht am Anfang des Handelns, Gluck am Ende.',
|
||||
author: 'Demokrit',
|
||||
category: 'mut',
|
||||
},
|
||||
{
|
||||
id: 'mut-2',
|
||||
text: 'Wer wagt, gewinnt.',
|
||||
author: 'Deutsches Sprichwort',
|
||||
category: 'mut',
|
||||
},
|
||||
{
|
||||
id: 'mut-3',
|
||||
text: 'Der Mutige hat nicht weniger Angst, er handelt trotzdem.',
|
||||
author: 'Mark Twain',
|
||||
category: 'mut',
|
||||
},
|
||||
// Hoffnung
|
||||
{
|
||||
id: 'hoff-1',
|
||||
text: 'Hoffnung ist ein Vogel, der singt, wenn die Nacht noch dunkel ist.',
|
||||
author: 'Rabindranath Tagore',
|
||||
category: 'hoffnung',
|
||||
},
|
||||
{
|
||||
id: 'hoff-2',
|
||||
text: 'Nach jedem Sturm scheint auch wieder die Sonne.',
|
||||
author: 'Deutsches Sprichwort',
|
||||
category: 'hoffnung',
|
||||
},
|
||||
// Natur
|
||||
{
|
||||
id: 'natur-1',
|
||||
text: 'In der Natur ist nichts isoliert; alles hangt mit allem zusammen.',
|
||||
author: 'Johann Wolfgang von Goethe',
|
||||
category: 'natur',
|
||||
},
|
||||
{
|
||||
id: 'natur-2',
|
||||
text: 'Schau tief in die Natur, und dann wirst du alles besser verstehen.',
|
||||
author: 'Albert Einstein',
|
||||
category: 'natur',
|
||||
},
|
||||
];
|
||||
|
||||
// Category labels in German
|
||||
export const CATEGORY_LABELS: Record<Category, string> = {
|
||||
motivation: 'Motivation',
|
||||
weisheit: 'Weisheit',
|
||||
liebe: 'Liebe',
|
||||
leben: 'Leben',
|
||||
erfolg: 'Erfolg',
|
||||
glueck: 'Gluck',
|
||||
freundschaft: 'Freundschaft',
|
||||
mut: 'Mut',
|
||||
hoffnung: 'Hoffnung',
|
||||
natur: 'Natur',
|
||||
};
|
||||
// Re-export types and utilities from @zitare/content
|
||||
export type { Quote, Category } from '@zitare/content';
|
||||
export { CATEGORIES, CATEGORY_LABELS } from '@zitare/content';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,23 @@
|
|||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { QUOTES, Quote, Category, CATEGORIES, CATEGORY_LABELS } from '../config/configuration';
|
||||
import {
|
||||
type Quote,
|
||||
type Category,
|
||||
QUOTES,
|
||||
CATEGORIES,
|
||||
CATEGORY_LABELS,
|
||||
getRandomQuote,
|
||||
getDailyQuote,
|
||||
getQuotesByCategory,
|
||||
getRandomQuoteByCategory,
|
||||
searchQuotes,
|
||||
getQuoteById,
|
||||
getQuoteByIndex,
|
||||
getAllCategories,
|
||||
getCategoryByName,
|
||||
formatQuote,
|
||||
formatQuoteWithNumber,
|
||||
getTotalCount,
|
||||
} from '@zitare/content';
|
||||
|
||||
@Injectable()
|
||||
export class QuotesService {
|
||||
|
|
@ -7,8 +25,7 @@ export class QuotesService {
|
|||
private dailyQuoteCache: { date: string; quote: Quote } | null = null;
|
||||
|
||||
getRandomQuote(): Quote {
|
||||
const index = Math.floor(Math.random() * QUOTES.length);
|
||||
return QUOTES[index];
|
||||
return getRandomQuote();
|
||||
}
|
||||
|
||||
getDailyQuote(): Quote {
|
||||
|
|
@ -19,95 +36,50 @@ export class QuotesService {
|
|||
return this.dailyQuoteCache.quote;
|
||||
}
|
||||
|
||||
// Generate deterministic quote based on date
|
||||
const dateHash = this.hashDate(today);
|
||||
const index = dateHash % QUOTES.length;
|
||||
const quote = QUOTES[index];
|
||||
|
||||
const quote = getDailyQuote();
|
||||
this.dailyQuoteCache = { date: today, quote };
|
||||
this.logger.log(`Daily quote for ${today}: "${quote.text.substring(0, 30)}..."`);
|
||||
|
||||
return quote;
|
||||
}
|
||||
|
||||
private hashDate(dateStr: string): number {
|
||||
let hash = 0;
|
||||
for (let i = 0; i < dateStr.length; i++) {
|
||||
const char = dateStr.charCodeAt(i);
|
||||
hash = (hash << 5) - hash + char;
|
||||
hash = hash & hash; // Convert to 32-bit integer
|
||||
}
|
||||
return Math.abs(hash);
|
||||
}
|
||||
|
||||
getQuotesByCategory(category: Category): Quote[] {
|
||||
return QUOTES.filter((q) => q.category === category);
|
||||
return getQuotesByCategory(category);
|
||||
}
|
||||
|
||||
getRandomQuoteByCategory(category: Category): Quote | null {
|
||||
const quotes = this.getQuotesByCategory(category);
|
||||
if (quotes.length === 0) return null;
|
||||
const index = Math.floor(Math.random() * quotes.length);
|
||||
return quotes[index];
|
||||
return getRandomQuoteByCategory(category);
|
||||
}
|
||||
|
||||
searchQuotes(searchText: string): Quote[] {
|
||||
const lowerSearch = searchText.toLowerCase();
|
||||
return QUOTES.filter(
|
||||
(q) =>
|
||||
q.text.toLowerCase().includes(lowerSearch) || q.author.toLowerCase().includes(lowerSearch)
|
||||
);
|
||||
return searchQuotes(searchText);
|
||||
}
|
||||
|
||||
getQuoteById(id: string): Quote | undefined {
|
||||
return QUOTES.find((q) => q.id === id);
|
||||
return getQuoteById(id);
|
||||
}
|
||||
|
||||
getQuoteByIndex(index: number): Quote | null {
|
||||
if (index < 1 || index > QUOTES.length) return null;
|
||||
return QUOTES[index - 1];
|
||||
return getQuoteByIndex(index);
|
||||
}
|
||||
|
||||
getAllCategories(): { category: Category; label: string; count: number }[] {
|
||||
return CATEGORIES.map((category) => ({
|
||||
category,
|
||||
label: CATEGORY_LABELS[category],
|
||||
count: QUOTES.filter((q) => q.category === category).length,
|
||||
}));
|
||||
return getAllCategories();
|
||||
}
|
||||
|
||||
getCategoryByName(name: string): Category | null {
|
||||
const lowerName = name.toLowerCase();
|
||||
|
||||
// Try exact match first
|
||||
if (CATEGORIES.includes(lowerName as Category)) {
|
||||
return lowerName as Category;
|
||||
}
|
||||
|
||||
// Try partial match
|
||||
for (const category of CATEGORIES) {
|
||||
if (
|
||||
category.startsWith(lowerName) ||
|
||||
CATEGORY_LABELS[category].toLowerCase().startsWith(lowerName)
|
||||
) {
|
||||
return category;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return getCategoryByName(name);
|
||||
}
|
||||
|
||||
getTotalCount(): number {
|
||||
return QUOTES.length;
|
||||
return getTotalCount();
|
||||
}
|
||||
|
||||
formatQuote(quote: Quote): string {
|
||||
const categoryLabel = CATEGORY_LABELS[quote.category];
|
||||
return `"${quote.text}"\n\n— *${quote.author}*\n\n[${categoryLabel}]`;
|
||||
return formatQuote(quote);
|
||||
}
|
||||
|
||||
formatQuoteWithNumber(quote: Quote, number: number): string {
|
||||
const categoryLabel = CATEGORY_LABELS[quote.category];
|
||||
return `**#${number}**\n"${quote.text}"\n\n— *${quote.author}* [${categoryLabel}]`;
|
||||
return formatQuoteWithNumber(quote, number);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue