Compare commits

..

9 Commits

Author SHA1 Message Date
werewolfkid 34dbc8d232 fix string value error
Main / build-and-push-docker-image (20.x) (push) Waiting to run
Daily Cron (Make New DailyStats Document) / cron (push) Successful in 1s
2025-12-18 21:46:08 -05:00
werewolfkid 5415c0c1f3 FORCE THIS SHIT TO RUN
Main / build-and-push-docker-image (20.x) (push) Waiting to run
Daily Cron (Make New DailyStats Document) / cron (push) Successful in 1s
2025-12-18 21:44:37 -05:00
werewolfkid 49218131f3 FIXED!
Main / build-and-push-docker-image (20.x) (push) Waiting to run
2025-12-18 21:42:56 -05:00
werewolfkid 0bbffd1b2a fixed?!
Main / build-and-push-docker-image (20.x) (push) Waiting to run
2025-12-18 21:40:40 -05:00
werewolfkid bfcfb8008a fiiiiiiiiiiix
Main / build-and-push-docker-image (20.x) (push) Waiting to run
2025-12-18 21:31:17 -05:00
werewolfkid 67c5bf86ed fiiiiix
Main / build-and-push-docker-image (20.x) (push) Waiting to run
2025-12-18 21:30:37 -05:00
werewolfkid 9890331139 fix cron?
Main / build-and-push-docker-image (20.x) (push) Waiting to run
2025-12-18 21:28:17 -05:00
werewolfkid 2ed31b8930 fix gitignore
Main / build-and-push-docker-image (20.x) (push) Successful in 4m46s
Daily Cron (Make New DailyStats Document) / cron (push) Successful in 1s
2025-12-18 17:34:24 -05:00
werewolfkid 9529e892f4 Fix cron?
Main / build-and-push-docker-image (20.x) (push) Waiting to run
2025-12-18 13:03:36 -05:00
16 changed files with 2026 additions and 2230 deletions
+5 -4
View File
@@ -1,8 +1,9 @@
name: Daily Cron (Make New DailyStats Document) name: Daily Cron (Make New DailyStats Document)
on: on:
push:
branches: [main]
schedule: schedule:
- cron: "0 4 * * *" - cron: "0 0 * * *"
jobs: jobs:
cron: cron:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
@@ -13,7 +14,7 @@ jobs:
- name: Daily cron job | Create new dailyStats document. - name: Daily cron job | Create new dailyStats document.
run: | run: |
curl --request POST \ curl --request POST \
--url 'https://bot-stats.werewolfkid.monster/api/graphql' \ --url 'https://bot-stats.lucids-cove.duckdns.org/api/graphql' \
--header 'x-api-key: ${{ secrets.NEXT_PUBLIC_API_TOKEN }}' \ --header 'x-api-key: ${{ secrets.NEXT_PUBLIC_API_TOKEN }}' \
--header 'Content-Type: application/json' \ --header 'Content-Type: application/json' \
--data '{ "query": "mutation Cron { cronJob ( mutationKey: \"${{ secrets.GRAPHQL_MUTATION_KEY }}\" ) { commandResponses createdAt linksDeleted timesTriggered updatedAt } }" }' \ --data '{ "query": "mutation Cron { cronJob ( mutationKey: \"${{ secrets.GRAPHQL_MUTATION_KEY }}\" ) { commandResponses createdAt linksDeleted timesTriggered updatedAt } }" }' \
-5
View File
@@ -1,6 +1 @@
approvedGitRepositories:
- "**"
enableScripts: true
nodeLinker: node-modules nodeLinker: node-modules
+28 -29
View File
@@ -1,6 +1,6 @@
{ {
"name": "no-twitter-bot-stats", "name": "no-twitter-bot-stats",
"version": "0.1.2", "version": "0.1.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
@@ -12,48 +12,47 @@
"prisma-update": "yarn prisma db push" "prisma-update": "yarn prisma db push"
}, },
"dependencies": { "dependencies": {
"@chakra-ui/charts": "^3.35.0", "@chakra-ui/charts": "^3.30.0",
"@chakra-ui/react": "^3.35.0", "@chakra-ui/react": "^3.30.0",
"@emotion/react": "^11.14.0", "@emotion/react": "^11.14.0",
"@escape.tech/graphql-armor": "^3.2.0", "@escape.tech/graphql-armor": "^3.1.7",
"@prisma/client": "^6.19.3", "@prisma/client": "^6.19.0",
"@prisma/extension-accelerate": "^3.0.1", "@prisma/extension-accelerate": "^2.0.2",
"@urql/next": "^2.0.0", "@urql/next": "^2.0.0",
"dotenv": "^17.4.2", "dotenv": "^17.2.3",
"graphql": "^16.13.2", "graphql": "^16.12.0",
"graphql-scalars": "^1.25.0", "graphql-scalars": "^1.25.0",
"graphql-yoga": "^5.21.0", "graphql-yoga": "^5.17.1",
"next": "16.2.4", "next": "16.0.7",
"next-themes": "^0.4.6", "next-themes": "^0.4.6",
"react": "19.2.5", "react": "19.2.1",
"react-dom": "19.2.5", "react-dom": "19.2.1",
"react-icons": "^5.6.0", "react-icons": "^5.5.0",
"recharts": "^3.8.1", "recharts": "^3.5.1",
"rxjs": "^7.8.2", "rxjs": "^7.8.2",
"urql": "^5.0.2" "urql": "^5.0.1"
}, },
"devDependencies": { "devDependencies": {
"@eslint/eslintrc": "^3.3.5", "@eslint/eslintrc": "^3.3.3",
"@eslint/js": "^10.0.1", "@eslint/js": "^9.39.1",
"@iconify/react": "^6.0.2", "@iconify/react": "^6.0.2",
"@types/node": "^25.6.0", "@types/node": "^24.10.1",
"@types/react": "^19.2.14", "@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
"@typescript-eslint/eslint-plugin": "^8.59.1", "@typescript-eslint/eslint-plugin": "^8.48.1",
"@typescript-eslint/parser": "^8.59.1", "@typescript-eslint/parser": "^8.48.1",
"baseline-browser-mapping": "^2.10.25", "eslint": "^9.39.1",
"eslint": "^9.39.4", "eslint-config-next": "16.0.7",
"eslint-config-next": "16.2.4",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
"eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-prettier": "^5.5.5", "eslint-plugin-prettier": "^5.5.4",
"eslint-plugin-react": "^7.37.5", "eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.1", "eslint-plugin-react-hooks": "^7.0.1",
"prettier": "3.8.3", "prettier": "3.7.4",
"prisma": "^6.19.3", "prisma": "^6.19.0",
"tsx": "^4.21.0", "tsx": "^4.21.0",
"typescript": "^5.9.3", "typescript": "^5.9.3",
"typescript-eslint": "^8.59.1" "typescript-eslint": "^8.48.1"
}, },
"packageManager": "yarn@4.14.1" "packageManager": "yarn@4.11.0"
} }
-57
View File
@@ -1,57 +0,0 @@
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;
+3 -3
View File
@@ -41,7 +41,7 @@ const StatsList = ({
groups >= 0 ? ( groups >= 0 ? (
<SingleStatComponent <SingleStatComponent
loading={loading} loading={loading}
title="Groups Helped" title="Groups Bot Helped"
error={error} error={error}
stat={groups} stat={groups}
/> />
@@ -55,13 +55,13 @@ const StatsList = ({
/> />
<SingleStatComponent <SingleStatComponent
loading={loading} loading={loading}
title="Commands Responses" title="Commands Responded To"
error={error} error={error}
stat={commands} stat={commands}
/> />
<SingleStatComponent <SingleStatComponent
loading={loading} loading={loading}
title="Triggers" title="Times Triggered"
error={error} error={error}
stat={triggers} stat={triggers}
/> />
+1 -1
View File
@@ -13,7 +13,7 @@ const TimedTriggeredChart = ({
return ( return (
<VStack gap={6} w="100%"> <VStack gap={6} w="100%">
<Heading as="h4" fontSize="2xl">{`Times Bot Was Triggered`}</Heading> <Heading as="h4" fontSize="2xl">{`Times Bot Was Triggered`}</Heading>
<LineChartComponent data={lineChartData} label="Triggers" /> <LineChartComponent data={lineChartData} label="Times Triggered" />
</VStack> </VStack>
); );
}; };
-37
View File
@@ -1,37 +0,0 @@
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
});
}
+3 -6
View File
@@ -1,7 +1,5 @@
"use client"; "use client";
import React, { useMemo } from "react";
import Script from "next/script";
import { Provider } from "@/components/ui/provider"; import { Provider } from "@/components/ui/provider";
import { import {
UrqlProvider, UrqlProvider,
@@ -10,6 +8,7 @@ import {
fetchExchange, fetchExchange,
createClient createClient
} from "@urql/next"; } from "@urql/next";
import React, { useMemo } from "react";
export default function RootLayout({ export default function RootLayout({
children children
@@ -35,9 +34,9 @@ export default function RootLayout({
return [client, ssr]; return [client, ssr];
}, []); }, []);
const title = "Anti Nazi-Sites Bot Stats"; const title = "Nazi Site Patrol Stats";
const description = const description =
"A website to display various stats for the Anti Nazi-Sites bot for Telegram. Developed and maintained by Werewolf Kid Creations."; "A website to display various stats for the Nazi Site Patrol bot for Telegram. Developed and maintained by Werewolf Kid Creations.";
const url = "https://bot-stats.werewolfkid.monster"; const url = "https://bot-stats.werewolfkid.monster";
const img = "/images/SPD-arrows.svg"; const img = "/images/SPD-arrows.svg";
const domain = "werewolfkid.monster"; const domain = "werewolfkid.monster";
@@ -74,8 +73,6 @@ export default function RootLayout({
<link rel="apple-touch-icon" sizes="180x180" href={img} /> <link rel="apple-touch-icon" sizes="180x180" href={img} />
<link rel="manifest" href={img} /> <link rel="manifest" href={img} />
<body> <body>
<div id="my-banner"></div>
<Script src="https://keepandroidopen.org/banner.js?size=mini&hidebutton=off&id=android-banner&animation=off?link=https://keepandroidopen.org" />
<UrqlProvider client={client} ssr={ssr}> <UrqlProvider client={client} ssr={ssr}>
<Provider>{children}</Provider> <Provider>{children}</Provider>
</UrqlProvider> </UrqlProvider>
+12 -35
View File
@@ -23,7 +23,6 @@ import GetTotalGroupsQuery from "@/graphql/queries/getTotalGroups";
import GetTotalStatsQuery from "@/graphql/queries/getTotalStats"; import GetTotalStatsQuery from "@/graphql/queries/getTotalStats";
import GetTodaysStatsQuery from "@/graphql/queries/getTodaysStats"; import GetTodaysStatsQuery from "@/graphql/queries/getTodaysStats";
import GetStatsRange from "@/graphql/queries/getStatsRange"; import GetStatsRange from "@/graphql/queries/getStatsRange";
import CommandsListTable from "./CommandsListTable";
export default function Home() { export default function Home() {
// * Total Groups * // // * Total Groups * //
@@ -63,7 +62,7 @@ export default function Home() {
useEffect(() => { useEffect(() => {
setCurrDate(new Date().toJSON()); setCurrDate(new Date().toJSON());
setDate30DaysAgo( setDate30DaysAgo(
new Date(new Date().setDate(new Date().getDate() - 30)).toJSON() new Date(new Date().setDate(new Date().getDay() - 30)).toJSON()
); );
}, []); }, []);
@@ -94,14 +93,7 @@ export default function Home() {
return ( return (
<Fragment> <Fragment>
<VStack <VStack bg="cyan.950" minH="100vh" h="100%" py="5vh" minW="fit-content">
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={{ base: "100%", md: "90%" }} gap={10} minW="fit-content">
<VStack w="80%" gap={10}> <VStack w="80%" gap={10}>
<Icon h="7.5rem" color="whiteAlpha"> <Icon h="7.5rem" color="whiteAlpha">
@@ -122,12 +114,8 @@ export default function Home() {
</svg> </svg>
</Icon> </Icon>
<VStack gap={4} maxW="34rem"> <VStack gap={4} maxW="34rem">
<Heading <Heading as="h1" fontSize="5xl">
as="h1" {"Anti Nazi Sites Bot Stats"}
fontSize="5xl"
lineHeight={{ base: "3rem", md: "" }}
>
{"Anti Nazi-Sites Bot Stats"}
</Heading> </Heading>
<Heading <Heading
as="h2" as="h2"
@@ -136,7 +124,7 @@ export default function Home() {
textAlign="center" textAlign="center"
> >
{ {
"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." "A telegram bot that removes links and embeds to sites that align with the Fascist Right political agenda."
} }
</Heading> </Heading>
</VStack> </VStack>
@@ -153,7 +141,6 @@ export default function Home() {
</Text> </Text>
</VStack> </VStack>
</VStack> </VStack>
<CommandsListTable />
<VStack gap={10} w="100%"> <VStack gap={10} w="100%">
{totalGroups ? ( {totalGroups ? (
<StatsList <StatsList
@@ -196,7 +183,7 @@ export default function Home() {
/> />
)} )}
</VStack> </VStack>
<VStack w="95%" gap="5dvh"> <VStack w="95%" gap="5vh">
<VStack gap={1}> <VStack gap={1}>
<Heading as="h1" fontSize="3xl">{`30 Day Stats`}</Heading> <Heading as="h1" fontSize="3xl">{`30 Day Stats`}</Heading>
<Text textAlign="center" fontSize="sm" color="whiteAlpha.800"> <Text textAlign="center" fontSize="sm" color="whiteAlpha.800">
@@ -242,21 +229,13 @@ export default function Home() {
rgb(147, 40, 142) rgb(147, 40, 142)
)`} )`}
w="100%" w="100%"
py="5dvh" py="5vh"
textAlign="center" textAlign="center"
> >
<VStack <VStack
color="white" color="white"
textShadow={` textShadow="0px 0px 5px black;"
2px 2px 0 #000, WebkitTextStroke="0.3px black;"
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} gap={6}
w="100%" w="100%"
> >
@@ -265,19 +244,17 @@ export default function Home() {
minW="fit-content" minW="fit-content"
w={{ base: "100%", sm: "auto" }} w={{ base: "100%", sm: "auto" }}
bg="blackAlpha.600" bg="blackAlpha.600"
maxW={{ base: "", sm: "62dvw" }} maxW={{ base: "", sm: "62vw" }}
px={2} px={2}
> >
{ {"Down with fascism! Fuck MAGA! Fuck Trump! Fuck Nazis!"}
"Down with fascism! Fuck MAGA! Fuck Trump! Fuck Nazis! Abolish ICE!"
}
</Text> </Text>
<Text <Text
fontSize="3xl" fontSize="3xl"
minW="fit-content" minW="fit-content"
w={{ base: "100%", sm: "auto" }} w={{ base: "100%", sm: "auto" }}
bg="blackAlpha.600" bg="blackAlpha.600"
maxW={{ base: "", sm: "62dvw" }} maxW={{ base: "", sm: "62vw" }}
px={2} px={2}
> >
{ {
+3 -3
View File
@@ -11,7 +11,7 @@ import {
import { LineChartArr } from "@/types/LineChartStats"; import { LineChartArr } from "@/types/LineChartStats";
interface LineChartComponentProps { interface LineChartComponentProps {
label: "Triggers" | "Links Deleted" | "Command Responses"; label: "Times Triggered" | "Links Deleted" | "Command Responses";
data: LineChartArr; data: LineChartArr;
} }
@@ -25,8 +25,8 @@ const LineChartComponent = ({
}); });
return ( return (
<Chart.Root maxH="xs" chart={chart} maxW="100dvw"> <Chart.Root maxH="xs" chart={chart} maxW="100vw">
<LineChart data={chart.data} responsive> <LineChart data={chart.data}>
<CartesianGrid stroke={chart.color("border")} vertical={false} /> <CartesianGrid stroke={chart.color("border")} vertical={false} />
<XAxis <XAxis
axisLine={false} axisLine={false}
-56
View File
@@ -1,56 +0,0 @@
// * 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;
+13 -85
View File
@@ -39,9 +39,6 @@ export const resolvers = {
const { startDate, endDate } = data; const { startDate, endDate } = data;
if (!startDate || !endDate) { if (!startDate || !endDate) {
console.info(
"GET STATS RANGE: REFUSED - one or both dates not provided."
);
return null; return null;
} }
@@ -82,44 +79,29 @@ export const resolvers = {
) => { ) => {
const { mutationKey } = data; const { mutationKey } = data;
// If env is not development check for the mutation key.
if (env !== "development") { if (env !== "development") {
// If mutation key was not provided.
if (!mutationKey) { if (!mutationKey) {
console.info("INIT: REFUSED - no mutation key was provided.");
return null; return null;
} }
// If provided mutation key is invalid.
if (mutationKey !== envMutationKey) { if (mutationKey !== envMutationKey) {
console.info("INIT: REFUSED - mutation key provided was incorrect.");
return null; return null;
} }
} }
const createdAtDate = new Date().toISOString(); const date = new Date().toISOString();
// How many tables were created let count = 0;
let newTablesCount = 0;
// Check for daily stats document count.
if ((await prisma.dailyStats.count()) === 0) { if ((await prisma.dailyStats.count()) === 0) {
// Make a daily stats document. await prisma.dailyStats.create({ data: { createdAt: date } });
console.info("INIT: created new document"); count++;
await prisma.dailyStats.create({ data: { createdAt: createdAtDate } });
newTablesCount++;
} }
// Check for a total stats document.
if ((await prisma.totalStats.count()) === 0) { if ((await prisma.totalStats.count()) === 0) {
// Make the total stats document. await prisma.totalStats.create({ data: { createdAt: date } });
console.info("INIT: created new document"); count++;
await prisma.totalStats.create({ data: { createdAt: createdAtDate } });
newTablesCount++;
} }
console.info( return `${count} tables have been initialized with data.`;
`INIT: ${newTablesCount} tables have been initialized with data.`
);
return `${newTablesCount} tables have been initialized with data.`;
}, },
cronJob: async ( cronJob: async (
_parent: unknown, _parent: unknown,
@@ -128,42 +110,30 @@ export const resolvers = {
) => { ) => {
const { mutationKey } = data; const { mutationKey } = data;
// If env is not development check for the mutation key.
if (env !== "development") { if (env !== "development") {
// If mutation key was not provided.
if (!mutationKey) { if (!mutationKey) {
console.info("CRONJOB: REFUSED - no mutation key was provided.");
return null; return null;
} }
// If provided mutation key is invalid.
if (mutationKey !== envMutationKey) { if (mutationKey !== envMutationKey) {
console.info(
"CRONJOB: REFUSED - mutation key provided was incorrect."
);
return null; return null;
} }
} }
const latestDailyStats = await getLatestDailyStat(); const latestDailyStats = await getLatestDailyStat();
// If there is a daily stats documents.
if (latestDailyStats !== null) { if (latestDailyStats !== null) {
// Check if the latest document is for today.
if (isDailyStatToday(String(latestDailyStats.createdAt))) { if (isDailyStatToday(String(latestDailyStats.createdAt))) {
console.info("Cron job refused: latest document is current date.");
return null; return null;
} }
} }
// Create new daily stats document. const date = new Date().toISOString();
const createdAtDate = new Date().toISOString();
await prisma.dailyStats.create({ data: { createdAt: createdAtDate } }); await prisma.dailyStats.create({ data: { createdAt: date } });
// Get every daily stats documents.
const allStats = await prisma.dailyStats.findMany({}); const allStats = await prisma.dailyStats.findMany({});
// Add all stats into one object.
const calculatedStats = allStats.reduce( const calculatedStats = allStats.reduce(
(acc, curr) => { (acc, curr) => {
const links = (acc.linksDeleted += curr.linksDeleted); const links = (acc.linksDeleted += curr.linksDeleted);
@@ -183,15 +153,12 @@ export const resolvers = {
} }
); );
// Take the total stats document.
const totalStats = await prisma.totalStats.findFirst({ const totalStats = await prisma.totalStats.findFirst({
orderBy: { orderBy: {
createdAt: "desc" createdAt: "desc"
} }
}); });
// Update the total stats document with the new total.
console.info("CRONJOB: Creating new document.");
return await prisma.totalStats.update({ return await prisma.totalStats.update({
where: { where: {
createdAt: totalStats?.createdAt createdAt: totalStats?.createdAt
@@ -214,37 +181,25 @@ export const resolvers = {
const { groupID, groupName, groupUsername, mutationKey } = data; const { groupID, groupName, groupUsername, mutationKey } = data;
const groupIDInt = BigInt(groupID); const groupIDInt = BigInt(groupID);
// If env is not development check for the mutation key.
if (env !== "development") { if (env !== "development") {
// If mutation key was not provided.
if (!mutationKey) { if (!mutationKey) {
console.info("ADD GROUP: REFUSED - no mutation key was provided.");
return null; return null;
} }
// If provided mutation key is invalid.
if (mutationKey !== envMutationKey) { if (mutationKey !== envMutationKey) {
console.info(
"ADD GROUP: REFUSED - mutation key provided was incorrect."
);
return null; return null;
} }
} }
// Attempt to find the group's document.
const existingGroup = await prisma.groups.findUnique({ const existingGroup = await prisma.groups.findUnique({
where: { telegramID: groupIDInt } where: { telegramID: groupIDInt }
}); });
// If the document was found.
if (existingGroup !== null) { if (existingGroup !== null) {
// Check if the document details are incorrect.
if ( if (
existingGroup.name !== groupName || existingGroup.name !== groupName ||
existingGroup.username !== groupUsername existingGroup.username !== groupUsername
) { ) {
// Return the document after updating the details.
console.info("ADD GROUP: Updated group document.");
return await prisma.groups.update({ return await prisma.groups.update({
where: { where: {
telegramID: existingGroup.telegramID telegramID: existingGroup.telegramID
@@ -253,12 +208,9 @@ export const resolvers = {
}); });
} }
// Return document without making changed.
return existingGroup; return existingGroup;
} }
// Return document after creating one for the group.
console.info("ADD GROUP: Created new group document.");
return await prisma.groups.create({ return await prisma.groups.create({
data: { data: {
telegramID: groupIDInt, telegramID: groupIDInt,
@@ -273,27 +225,16 @@ export const resolvers = {
) => { ) => {
const { groupID, linksDeleted, mutationKey } = data; const { groupID, linksDeleted, mutationKey } = data;
// If env is not development check for the mutation key.
if (env !== "development") { if (env !== "development") {
// If mutation key was not provided.
if (!mutationKey) { if (!mutationKey) {
console.info(
"INCREMENT GROUP: REFUSED - no mutation key was provided."
);
return null; return null;
} }
// If provided mutation key is invalid.
if (mutationKey !== envMutationKey) { if (mutationKey !== envMutationKey) {
console.info(
"INCREMENT GROUP: REFUSED - mutation key provided was incorrect."
);
return null; return null;
} }
} }
// Return updated group document after incrementing it.
console.info("INCREMENT GROUP: Incremented group document.");
return await prisma.groups.update({ return await prisma.groups.update({
where: { telegramID: BigInt(groupID) }, where: { telegramID: BigInt(groupID) },
data: { linksDeleted: { increment: linksDeleted } } data: { linksDeleted: { increment: linksDeleted } }
@@ -302,7 +243,7 @@ export const resolvers = {
increment: async ( increment: async (
_parent: unknown, _parent: unknown,
data: { data: {
link: number; link: boolean;
command: boolean; command: boolean;
trigger: boolean; trigger: boolean;
mutationKey?: string; mutationKey?: string;
@@ -311,33 +252,22 @@ export const resolvers = {
) => { ) => {
const { link, command, trigger, mutationKey } = data; const { link, command, trigger, mutationKey } = data;
// If env is not development check for the mutation key.
if (env !== "development") { if (env !== "development") {
// If mutation key was not provided.
if (!mutationKey) { if (!mutationKey) {
console.info("INCREMENT: REFUSED - no mutation key was provided.");
return null; return null;
} }
// If provided mutation key is invalid.
if (mutationKey !== envMutationKey) { if (mutationKey !== envMutationKey) {
console.info(
"INCREMENT: REFUSED - mutation key provided was incorrect."
);
return null; return null;
} }
} }
// Get latest daily stats.
let latestDailyStats = await getLatestDailyStat(); let latestDailyStats = await getLatestDailyStat();
// If there is a daily stats documents.
if (latestDailyStats !== null) { if (latestDailyStats !== null) {
// Check if the latest document is for today.
if (!isDailyStatToday(String(latestDailyStats.createdAt))) { if (!isDailyStatToday(String(latestDailyStats.createdAt))) {
// Create new daily stats document.
console.info("INCREMENT: Created new document.");
const date = new Date().toISOString(); const date = new Date().toISOString();
await prisma.dailyStats await prisma.dailyStats
.create({ data: { createdAt: date } }) .create({ data: { createdAt: date } })
.then(async () => { .then(async () => {
@@ -349,12 +279,10 @@ export const resolvers = {
}); });
} }
// Return latest daily stats after incrementing it.
console.info("INCREMENT: Incremented information on today's document.");
return await prisma.dailyStats.update({ return await prisma.dailyStats.update({
where: { createdAt: latestDailyStats.createdAt }, where: { createdAt: latestDailyStats.createdAt },
data: { data: {
linksDeleted: { increment: link ? link : 0 }, linksDeleted: { increment: link ? 1 : 0 },
commandResponses: { increment: command ? 1 : 0 }, commandResponses: { increment: command ? 1 : 0 },
timesTriggered: { increment: trigger ? 1 : 0 } timesTriggered: { increment: trigger ? 1 : 0 }
} }
+2 -2
View File
@@ -13,7 +13,7 @@ const typeDefs = /* GraphQL */ `
} }
type Mutation { type Mutation {
init(mutationKey: String): String! init(mutationKey: String): String!
cronJob(mutationKey: String): TotalStats cronJob(mutationKey: String): TotalStats!
addGroup( addGroup(
groupID: String! groupID: String!
groupName: String! groupName: String!
@@ -26,7 +26,7 @@ const typeDefs = /* GraphQL */ `
mutationKey: String mutationKey: String
): Groups! ): Groups!
increment( increment(
link: Int link: Boolean
command: Boolean command: Boolean
trigger: Boolean trigger: Boolean
mutationKey: String mutationKey: String
+1 -1
View File
@@ -15,7 +15,7 @@ const lineChartArr = (dailyStatsArr: DailyStats): LineChartArr => {
day, day,
"Links Deleted": linksDeleted, "Links Deleted": linksDeleted,
"Command Responses": commandResponses, "Command Responses": commandResponses,
Triggers: timesTriggered "Times Triggered": timesTriggered
}; };
lineChartArr.push(lineChartItem); lineChartArr.push(lineChartItem);
+1 -1
View File
@@ -2,7 +2,7 @@ export interface LineChartItem {
day: number; day: number;
"Links Deleted": number; "Links Deleted": number;
"Command Responses": number; "Command Responses": number;
Triggers: number; "Times Triggered": number;
} }
export type LineChartArr = LineChartItem[]; export type LineChartArr = LineChartItem[];
+1954 -1905
View File
File diff suppressed because it is too large Load Diff