Chart Generation & QuickChart
Relevant source files
The following files were used as context for generating this wiki page:
The Telegram History Bot generates visual representations of chat activity and violation statistics using a dual-layer approach. It produces ASCII-based charts for text-only environments and leverages the QuickChart.io API to generate high-quality image charts for Telegram photo messages and the web-based Admin Dashboard.
This system visualizes data trends across various periods (today, week, month) for metrics including message volume, user activity, profanity rates, and hourly distribution. Sources: src/features/stats/stats.ts, src/api/admin-html.ts
Core Charting Logic
The bot implements charting through specialized functions that aggregate data from Cloudflare KV or D1 databases and format it for the QuickChart API.
Technical Workflow
- Data Retrieval: The system fetches counts from KV namespaces using prefixes such as
stats_v2:,activity:, orprofanity:. Sources: src/features/stats/stats.ts:165-175, src/features/stats/stats.ts:515-525 - Aggregation: Data is bucketed by day, week, or hour depending on the requested period. Sources: src/features/stats/stats.ts:544-555
- QuickChart URL Generation: The function
createBarChartUrlconstructs a JSON configuration object, stringifies it, and appends it as a URL-encoded parameter to the QuickChart base URL. Sources: src/features/stats/stats.ts:480-505 - Delivery: The bot sends the resulting URL to Telegram via the
sendPhotoutility or renders it in the Admin Dashboard via Chart.js. Sources: src/features/stats/stats.ts:605, src/api/admin-html.ts:1145
The diagram shows the flow from a request to the final rendering of a chart via QuickChart or the internal dashboard. Sources: src/features/stats/stats.ts, src/api/admin-html.ts
Chart Types and Components
The system supports several chart configurations tailored to specific datasets.
Supported Visualization Metrics
| Feature | Chart Type | Data Source Key Prefix | Visualization Target |
|---|---|---|---|
| Activity Chart | Bar/ASCII | activity:{chatId}:{day} | Weekly/Monthly volume |
| User Activity | Bar (Image) | stats_v2:{chatId}:{day}:{userId} | Top active users |
| Hourly Activity | Bar (Image) | activity_hour:{chatId}:{day}:{hour} | Average messages per hour |
| Profanity Rate | Bar (Image) | profanity: & word_stats_v2: | Ratio of profanity per user |
| Profanity Trend | Bar/ASCII | profanity:{chatId}:{userId}:{day} | Violation trends over time |
Sources: src/features/stats/stats.ts:514-530, src/features/stats/stats.ts:610-630, src/features/stats/stats.ts:1075-1100
ASCII Fallback
When image generation is not required or fails, the drawGraph function generates a text-based bar chart using the █ character. This provides immediate visual feedback within a standard Telegram text message. Sources: src/features/stats/stats.ts:439-446
QuickChart Integration
The bot utilizes the createBarChartUrl helper to interface with the QuickChart.io service. This function enforces strict validation on labels and data arrays to prevent malformed API requests. Sources: src/features/stats/stats.ts:480-488
Chart Configuration Parameters
The ChartConfig interface defines the structure sent to the API:
- type: Fixed to
'bar'for most statistics. - data: Contains
labels(strings) anddatasets(arrays of numbers). - options: Configures titles, legend visibility, and datalabels (anchored at 'end', aligned 'top').
Sources: src/features/stats/stats.ts:460-478
// Example of Chart URL Construction
function createBarChartUrl(labels: string[], data: number[], name: string, title?: string): string {
const chart: ChartConfig = {
type: 'bar',
data: { labels, datasets: [{ label: name, data }] },
options: {
plugins: {
title: { display: Boolean(title), text: title ?? '' },
legend: { display: false },
datalabels: { anchor: 'end', align: 'top' },
},
},
};
return 'https://quickchart.io/chart?c=' + encodeURIComponent(JSON.stringify(chart));
}
Sources: src/features/stats/stats.ts:480-505
Admin Dashboard Charts
The web-based Admin Dashboard uses Chart.js (v4.4.7) on the client side rather than static QuickChart images to allow for interactive elements and theme synchronization. Sources: src/api/admin-html.ts:1053
Dashboard Implementation Details
- Theming: Charts dynamically update colors (text, grid lines, accents) based on the dashboard's light/dark mode. Sources: src/api/admin-html.ts:510-525
- Timezone Correction: The Hourly Activity chart allows users to shift the UTC-stored data to a local timezone offset via the
shiftHourlyAveragesfunction. Sources: src/api/admin-html.ts:1330-1345 - Responsive Layout: Charts are wrapped in
chartCanvascontainers to maintain aspect ratios across mobile and desktop views. Sources: src/api/admin-html.ts:250-265
Error Handling and Fallbacks
The system handles chart generation failures gracefully to ensure bot responsiveness.
- Empty Data: If a dataset contains no values, the system skips image generation and returns a "Нет данных" (No data) text message. Sources: tests/profanity-charts.test.ts:70-80, src/features/stats/stats.ts:1140
- API Errors: In
profanityChart, thesendPhotocall is wrapped in a try-catch block. If the QuickChart URL fails to load or send, the bot still successfully delivers the ASCII text version. Sources: src/features/stats/stats.ts:1175-1185, tests/profanity-charts.test.ts:175-185 - Validation: Labels are sanitized via
sanitizeLabelto remove special characters that might break URL encoding or Chart.js rendering. Sources: src/features/stats/stats.ts:448-454
Summary of Commands
| Command | Visualization Type | Period |
|---|---|---|
/activity_week | ASCII Chart | Last 7 days |
/activity_month | ASCII Chart | Last 30 days |
/activity_users_week | QuickChart Image | Last 7 days |
/profanity_chart_week | ASCII + QuickChart | Last 7 days |
/profanity_chart_month | ASCII + QuickChart | Last 30 days |
Sources: README.md:25-50, src/features/stats/stats.ts