Compare commits

..

13 Commits

Author SHA1 Message Date
1baf37ae41 upgrade dependencies
All checks were successful
Main / build-and-push-docker-image (20.x) (push) Successful in 4m34s
Daily Cron (Make New DailyStats Document) / cron (push) Successful in 2s
2026-01-27 11:47:42 -05:00
efa258fdde Update stats description
All checks were successful
Main / build-and-push-docker-image (20.x) (push) Successful in 4m49s
2026-01-27 10:11:00 -05:00
cab2eaa22c Update bot tagline.
All checks were successful
Main / build-and-push-docker-image (20.x) (push) Successful in 5m4s
Daily Cron (Make New DailyStats Document) / cron (push) Successful in 3s
2026-01-26 23:00:27 -05:00
49a74cf4df Updated the increment mutation to take a number instead of a boolean. For instances when more than 1 group is detected. Like when parsing embeds and captions.
All checks were successful
Main / build-and-push-docker-image (20.x) (push) Successful in 5m1s
2026-01-26 21:28:41 -05:00
e0a99cc455 added command list to site
All checks were successful
Main / build-and-push-docker-image (20.x) (push) Successful in 5m11s
2026-01-26 20:38:55 -05:00
1214b7e98a Update commands description. 2026-01-26 19:35:39 -05:00
369b3bf133 Added api route to retrieve bot commands list. 2026-01-26 18:15:50 -05:00
d15eab2421 Added command list. 2026-01-26 15:24:27 -05:00
b71fb89832 Upgraded dependencies. Updated terminology and wording. Updated bot name. FIx text center and line height.
All checks were successful
Main / build-and-push-docker-image (20.x) (push) Successful in 6m48s
Daily Cron (Make New DailyStats Document) / cron (push) Successful in 2s
2025-12-30 13:23:36 -05:00
788f1d24f7 Update src/app/page.tsx
All checks were successful
Main / build-and-push-docker-image (20.x) (push) Successful in 6m18s
Daily Cron (Make New DailyStats Document) / cron (push) Successful in 1s
fix shadow/outline
2025-12-28 19:02:51 -05:00
48b52edd38 Update line stroke
All checks were successful
Main / build-and-push-docker-image (20.x) (push) Successful in 4m52s
2025-12-28 13:06:42 -05:00
714b2d8bae remove run on push: main
All checks were successful
Main / build-and-push-docker-image (20.x) (push) Successful in 5m53s
Daily Cron (Make New DailyStats Document) / cron (push) Successful in 1s
2025-12-22 16:01:18 -05:00
f51580e8ea Updated graphql query in cron job. updated .gitignore. Updated conJob in typeDegf. Updated cron github action.
Some checks are pending
Main / build-and-push-docker-image (20.x) (push) Waiting to run
Daily Cron (Make New DailyStats Document) / cron (push) Successful in 3s
2025-12-22 15:58:39 -05:00
15 changed files with 1787 additions and 1953 deletions

View File

@@ -1,9 +1,8 @@
name: Daily Cron (Make New DailyStats Document)
on:
push:
branches: [main]
schedule:
- cron: "0 0 * * *"
- cron: "0 5 * * *"
jobs:
cron:
runs-on: ubuntu-24.04

View File

@@ -12,47 +12,48 @@
"prisma-update": "yarn prisma db push"
},
"dependencies": {
"@chakra-ui/charts": "^3.30.0",
"@chakra-ui/react": "^3.30.0",
"@chakra-ui/charts": "^3.31.0",
"@chakra-ui/react": "^3.31.0",
"@emotion/react": "^11.14.0",
"@escape.tech/graphql-armor": "^3.1.7",
"@prisma/client": "^6.19.0",
"@prisma/extension-accelerate": "^2.0.2",
"@escape.tech/graphql-armor": "^3.2.0",
"@prisma/client": "^6.19.2",
"@prisma/extension-accelerate": "^3.0.1",
"@urql/next": "^2.0.0",
"dotenv": "^17.2.3",
"graphql": "^16.12.0",
"graphql-scalars": "^1.25.0",
"graphql-yoga": "^5.17.1",
"next": "16.0.7",
"graphql-yoga": "^5.18.0",
"next": "16.1.5",
"next-themes": "^0.4.6",
"react": "19.2.1",
"react-dom": "19.2.1",
"react": "19.2.4",
"react-dom": "19.2.4",
"react-icons": "^5.5.0",
"recharts": "^3.5.1",
"recharts": "^3.7.0",
"rxjs": "^7.8.2",
"urql": "^5.0.1"
},
"devDependencies": {
"@eslint/eslintrc": "^3.3.3",
"@eslint/js": "^9.39.1",
"@eslint/js": "^9.39.2",
"@iconify/react": "^6.0.2",
"@types/node": "^24.10.1",
"@types/react": "^19.2.7",
"@types/node": "^25.0.10",
"@types/react": "^19.2.10",
"@types/react-dom": "^19.2.3",
"@typescript-eslint/eslint-plugin": "^8.48.1",
"@typescript-eslint/parser": "^8.48.1",
"eslint": "^9.39.1",
"eslint-config-next": "16.0.7",
"@typescript-eslint/eslint-plugin": "^8.54.0",
"@typescript-eslint/parser": "^8.54.0",
"baseline-browser-mapping": "^2.9.18",
"eslint": "^9.39.2",
"eslint-config-next": "16.1.5",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-prettier": "^5.5.4",
"eslint-plugin-prettier": "^5.5.5",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.1",
"prettier": "3.7.4",
"prisma": "^6.19.0",
"prettier": "3.8.1",
"prisma": "^6.19.2",
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"typescript-eslint": "^8.48.1"
"typescript-eslint": "^8.54.0"
},
"packageManager": "yarn@4.11.0"
"packageManager": "yarn@4.12.0"
}

View File

@@ -0,0 +1,57 @@
import { JSX } from "react";
import { Checkmark, Heading, Table, VStack } from "@chakra-ui/react";
import botCommands from "@/data/botCommands";
const CommandsListTable = (): JSX.Element => {
return (
<VStack gap={6} w={{ base: "90%", md: "100%" }}>
<Heading as="h3" fontSize="3xl">
{"Bot Commands"}
</Heading>
<Table.Root maxW="fit-content" interactive showColumnBorder>
<Table.Caption>
{"The bot will only respond to admins and moderators within groups."}
</Table.Caption>
<Table.Header>
<Table.Row bg="cyan.emphasized">
<Table.ColumnHeader> {"Command"}</Table.ColumnHeader>
<Table.ColumnHeader> {"Description"}</Table.ColumnHeader>
<Table.ColumnHeader> {"Private"}</Table.ColumnHeader>
<Table.ColumnHeader> {"Group"}</Table.ColumnHeader>
</Table.Row>
</Table.Header>
<Table.Body>
{botCommands.map((commandObj, index) => {
const { command, description, groups } = commandObj;
return (
<Table.Row
key={`${index}-${command}`}
bg="cyan.muted"
_hover={{ bg: "purple.emphasized" }}
>
<Table.Cell>{command}</Table.Cell>
<Table.Cell>{description.replaceAll("\\", "")}</Table.Cell>
<Table.Cell>
{groups ? (
<Checkmark colorPalette="purple" checked />
) : (
<Checkmark colorPalette="purple" indeterminate />
)}
</Table.Cell>
<Table.Cell>
{commandObj.private ? (
<Checkmark colorPalette="purple" checked />
) : (
<Checkmark colorPalette="purple" indeterminate />
)}
</Table.Cell>
</Table.Row>
);
})}
</Table.Body>
</Table.Root>
</VStack>
);
};
export default CommandsListTable;

View File

@@ -41,7 +41,7 @@ const StatsList = ({
groups >= 0 ? (
<SingleStatComponent
loading={loading}
title="Groups Bot Helped"
title="Groups Helped"
error={error}
stat={groups}
/>
@@ -55,13 +55,13 @@ const StatsList = ({
/>
<SingleStatComponent
loading={loading}
title="Commands Responded To"
title="Commands Responses"
error={error}
stat={commands}
/>
<SingleStatComponent
loading={loading}
title="Times Triggered"
title="Triggers"
error={error}
stat={triggers}
/>

View File

@@ -13,7 +13,7 @@ const TimedTriggeredChart = ({
return (
<VStack gap={6} w="100%">
<Heading as="h4" fontSize="2xl">{`Times Bot Was Triggered`}</Heading>
<LineChartComponent data={lineChartData} label="Times Triggered" />
<LineChartComponent data={lineChartData} label="Triggers" />
</VStack>
);
};

37
src/app/api/bot/route.ts Normal file
View File

@@ -0,0 +1,37 @@
import { headers } from "next/headers";
import botCommands from "@/data/botCommands";
const environment = process.env.NODE_ENV || "development";
const isValidApiKey = (apiKey: string): boolean => {
const envApiKey =
process.env.API_TOKEN || process.env.NEXT_PUBLIC_API_TOKEN || "";
return apiKey === envApiKey;
};
export async function GET(/*request: Request*/) {
const headersList = await headers();
const apiKey = headersList.get("x-api-key");
if (environment === "production") {
if (!apiKey || apiKey == null) {
return new Response("No API Key provided", {
status: 401,
headers: headersList
});
}
if (apiKey !== null && !(await isValidApiKey(apiKey))) {
return new Response("Invalid API Key", {
status: 403,
headers: headersList
});
}
}
return Response.json(botCommands, {
status: 200,
headers: headersList
});
}

View File

@@ -34,9 +34,9 @@ export default function RootLayout({
return [client, ssr];
}, []);
const title = "Nazi Site Patrol Stats";
const title = "Anti Nazi-Sites Bot Stats";
const description =
"A website to display various stats for the Nazi Site Patrol bot for Telegram. Developed and maintained by Werewolf Kid Creations.";
"A website to display various stats for the Anti Nazi-Sites bot for Telegram. Developed and maintained by Werewolf Kid Creations.";
const url = "https://bot-stats.werewolfkid.monster";
const img = "/images/SPD-arrows.svg";
const domain = "werewolfkid.monster";

View File

@@ -23,6 +23,7 @@ import GetTotalGroupsQuery from "@/graphql/queries/getTotalGroups";
import GetTotalStatsQuery from "@/graphql/queries/getTotalStats";
import GetTodaysStatsQuery from "@/graphql/queries/getTodaysStats";
import GetStatsRange from "@/graphql/queries/getStatsRange";
import CommandsListTable from "./CommandsListTable";
export default function Home() {
// * Total Groups * //
@@ -93,7 +94,14 @@ export default function Home() {
return (
<Fragment>
<VStack bg="cyan.950" minH="100vh" h="100%" py="5vh" minW="fit-content">
<VStack
bg="cyan.950"
minH="100dvh"
h="100%"
py="5dvh"
minW="fit-content"
textAlign="center"
>
<VStack w={{ base: "100%", md: "90%" }} gap={10} minW="fit-content">
<VStack w="80%" gap={10}>
<Icon h="7.5rem" color="whiteAlpha">
@@ -114,8 +122,12 @@ export default function Home() {
</svg>
</Icon>
<VStack gap={4} maxW="34rem">
<Heading as="h1" fontSize="5xl">
{"Anti Nazi Sites Bot Stats"}
<Heading
as="h1"
fontSize="5xl"
lineHeight={{ base: "3rem", md: "" }}
>
{"Anti Nazi-Sites Bot Stats"}
</Heading>
<Heading
as="h2"
@@ -124,7 +136,7 @@ export default function Home() {
textAlign="center"
>
{
"A telegram bot that removes links and embeds to sites that align with the Fascist Right political agenda."
"A Telegram bot that deletes links and embeds to sites that align with the Fascist Right political agenda or are otherwise a safety/privacy risk."
}
</Heading>
</VStack>
@@ -141,6 +153,7 @@ export default function Home() {
</Text>
</VStack>
</VStack>
<CommandsListTable />
<VStack gap={10} w="100%">
{totalGroups ? (
<StatsList
@@ -183,7 +196,7 @@ export default function Home() {
/>
)}
</VStack>
<VStack w="95%" gap="5vh">
<VStack w="95%" gap="5dvh">
<VStack gap={1}>
<Heading as="h1" fontSize="3xl">{`30 Day Stats`}</Heading>
<Text textAlign="center" fontSize="sm" color="whiteAlpha.800">
@@ -229,13 +242,21 @@ export default function Home() {
rgb(147, 40, 142)
)`}
w="100%"
py="5vh"
py="5dvh"
textAlign="center"
>
<VStack
color="white"
textShadow="0px 0px 5px black;"
WebkitTextStroke="0.3px black;"
textShadow={`
2px 2px 0 #000,
2px -2px 0 #000,
-2px 2px 0 #000,
-2px -2px 0 #000,
2px 0px 0 #000,
0px 2px 0 #000,
-2px 0px 0 #000,
0px -2px 0 #000
`}
gap={6}
w="100%"
>
@@ -244,17 +265,19 @@ export default function Home() {
minW="fit-content"
w={{ base: "100%", sm: "auto" }}
bg="blackAlpha.600"
maxW={{ base: "", sm: "62vw" }}
maxW={{ base: "", sm: "62dvw" }}
px={2}
>
{"Down with fascism! Fuck MAGA! Fuck Trump! Fuck Nazis!"}
{
"Down with fascism! Fuck MAGA! Fuck Trump! Fuck Nazis! Abolish ICE!"
}
</Text>
<Text
fontSize="3xl"
minW="fit-content"
w={{ base: "100%", sm: "auto" }}
bg="blackAlpha.600"
maxW={{ base: "", sm: "62vw" }}
maxW={{ base: "", sm: "62dvw" }}
px={2}
>
{

View File

@@ -11,7 +11,7 @@ import {
import { LineChartArr } from "@/types/LineChartStats";
interface LineChartComponentProps {
label: "Times Triggered" | "Links Deleted" | "Command Responses";
label: "Triggers" | "Links Deleted" | "Command Responses";
data: LineChartArr;
}
@@ -25,7 +25,7 @@ const LineChartComponent = ({
});
return (
<Chart.Root maxH="xs" chart={chart} maxW="100vw">
<Chart.Root maxH="xs" chart={chart} maxW="100dvw">
<LineChart data={chart.data}>
<CartesianGrid stroke={chart.color("border")} vertical={false} />
<XAxis

56
src/data/botCommands.ts Normal file
View File

@@ -0,0 +1,56 @@
// * Commands *
interface Commands {
command: String;
description: String;
groups: boolean;
private: boolean;
}
const botInfo: Commands = {
command: "/botInfo",
description:
"Lists information about the bot such as: creator, reason for my creation, purpose and goal, etc",
groups: true,
private: true
};
const getGroupStats: Commands = {
command: "/groupStats",
description:
"Displays the number of times the bot has deleted links in your group for the lifetime of the bot",
groups: true,
private: false
};
const help: Commands = {
command: "/help",
description:
"Lists information about how to setup the bot and the list of available commands",
groups: true,
private: true
};
const registerGroup: Commands = {
command: "/registerGroup",
description: `Will add your group to the database, if your group doesn't exist already\\. This is used to calculate the "total groups" count on the bot stats website`,
groups: true,
private: true
};
const botStatsSite: Commands = {
command: "/botStats",
description: "Provides the bot stats website link as an embed",
groups: true,
private: true
};
const commands: Commands[] = [
botInfo,
getGroupStats,
help,
registerGroup,
botStatsSite
];
export default commands;

View File

@@ -243,7 +243,7 @@ export const resolvers = {
increment: async (
_parent: unknown,
data: {
link: boolean;
link: number;
command: boolean;
trigger: boolean;
mutationKey?: string;
@@ -282,7 +282,7 @@ export const resolvers = {
return await prisma.dailyStats.update({
where: { createdAt: latestDailyStats.createdAt },
data: {
linksDeleted: { increment: link ? 1 : 0 },
linksDeleted: { increment: link ? link : 0 },
commandResponses: { increment: command ? 1 : 0 },
timesTriggered: { increment: trigger ? 1 : 0 }
}

View File

@@ -13,7 +13,7 @@ const typeDefs = /* GraphQL */ `
}
type Mutation {
init(mutationKey: String): String!
cronJob(mutationKey: String): TotalStats!
cronJob(mutationKey: String): TotalStats
addGroup(
groupID: String!
groupName: String!
@@ -26,7 +26,7 @@ const typeDefs = /* GraphQL */ `
mutationKey: String
): Groups!
increment(
link: Boolean
link: Int
command: Boolean
trigger: Boolean
mutationKey: String

View File

@@ -15,7 +15,7 @@ const lineChartArr = (dailyStatsArr: DailyStats): LineChartArr => {
day,
"Links Deleted": linksDeleted,
"Command Responses": commandResponses,
"Times Triggered": timesTriggered
Triggers: timesTriggered
};
lineChartArr.push(lineChartItem);

View File

@@ -2,7 +2,7 @@ export interface LineChartItem {
day: number;
"Links Deleted": number;
"Command Responses": number;
"Times Triggered": number;
Triggers: number;
}
export type LineChartArr = LineChartItem[];

3465
yarn.lock

File diff suppressed because it is too large Load Diff