Skip to content

Commit

Permalink
Fix discord error (#8)
Browse files Browse the repository at this point in the history
* remove interval logging; make eslint ignore any files outside of src or tests; add updateHandler unit test; remove unnecessary logging

* mock env in updateHandler

* mock env properly; change log,error to trace

* format code
  • Loading branch information
NewBieCoderXD authored Aug 22, 2024
1 parent c44eb20 commit 06e7a5e
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 31 deletions.
3 changes: 0 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ COOKIE=
# Integer(number), define delay time to fetch to prevent rate limit
DELAY=

# Boolean, true will enable annoying "new interval starts" discord message
INTERVAL_LOGGING=

# Boolean, true will enable annoying "Error fetching, Might be rate limited or server is down" discord message
ERROR_FETCHING_NOTIFICATION=

Expand Down
8 changes: 5 additions & 3 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import globals from "globals";
import tseslint from "typescript-eslint";
import tsPlugin from "@typescript-eslint/eslint-plugin";
import tsParser from "@typescript-eslint/parser";
import unusedImports from "eslint-plugin-unused-imports";
export default tseslint.config(
export default [
{
files: ["src/**/*.ts","tests/**/*.ts"],
languageOptions: {
Expand Down Expand Up @@ -31,4 +30,7 @@ export default tseslint.config(
"@typescript-eslint/no-explicit-any": "off"
}
},
)
{
ignores: ["*","!src","!tests"]
}
]
1 change: 0 additions & 1 deletion src/env/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ const env = cleanEnv(process.env, {
ADMIN_USER_ID: str(),
COOKIE: str(),
DELAY: num(),
INTERVAL_LOGGING: bool({ default: false }),
ERROR_FETCHING_NOTIFICATION: bool({ default: false }),
AUTO_DETERMINE_YEAR_AND_SEMESTER: bool(),
})
Expand Down
2 changes: 1 addition & 1 deletion src/scraper/determineYearAndSemester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export async function determineYearAndSemester($: cheerio.Root): Promise<void> {
const currentYearAndSemester = $('h2').first().text()
const split = /(\d+)\/(\d+)/.exec(currentYearAndSemester)
if (split == undefined) {
console.log('error cannot parse year and semester: ', split)
console.trace('error cannot parse year and semester: ', split)
return
}
const [_beforeSplit, currentYear, currentSemester] = split
Expand Down
11 changes: 4 additions & 7 deletions src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ export const client = new Client({
})

export let adminDM: DMChannel
let intervalId: NodeJS.Timeout
export let intervalId: MutableWrapper<NodeJS.Timeout | undefined> =
new MutableWrapper(undefined)
let commands: DiscordCommandHandler

client.on('interactionCreate', async (interaction: Interaction) => {
Expand All @@ -44,7 +45,7 @@ client.on('interactionCreate', async (interaction: Interaction) => {
await interaction.reply('command not found')
}
} catch (e) {
console.error('error occured', e)
console.trace('error occured', e)
if (e instanceof Error) {
adminDM.send('error: ' + (e as Error).stack)
} else {
Expand All @@ -60,7 +61,7 @@ client.on('ready', async () => {
adminDM.send('server is up!')

if (isSome(await updateHandler())) {
intervalId = setInterval(updateHandler, env.DELAY * 1000)
intervalId.value = setInterval(updateHandler, env.DELAY * 1000)
}
})

Expand All @@ -75,7 +76,3 @@ export async function start() {
console.log('found commands', Object.keys(commands))
client.login(env.DISCORD_TOKEN)
}

export function getIntervalId() {
return intervalId
}
1 change: 0 additions & 1 deletion src/utils/fetchAndCatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export default async function fetchAndCatch(
if (hasEncounteredError.value) {
return option.none
}
console.log(await response.text())
hasEncounteredError.value = true
await errorFetchingNotify(NotifyMessage.FetchingError)
return option.none
Expand Down
4 changes: 2 additions & 2 deletions src/utils/throwErrorToAdmin.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { adminDM, getIntervalId } from '../server'
import { adminDM, intervalId } from '../server'

export async function throwErrorToAdmin(msg: string) {
await adminDM.send(msg)
clearInterval(getIntervalId())
clearInterval(intervalId.value)
}
27 changes: 14 additions & 13 deletions src/utils/updateHandler.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
import { TextChannel } from 'discord.js'
import { DiscordAPIError, TextChannel } from 'discord.js'
import db from '../database/database'
import env from '../env/env'
import { updateAll } from '../scraper/updateAll'
import { client } from '../server'
import formatDateToBangkok from './formatDateToBangkok'
import { adminDM, client } from '../server'
import { none, Option, some } from 'fp-ts/lib/Option'

/**
* @description update assignments and send message to all notification channels
* */
export default async function updateHandler(): Promise<Option<boolean>> {
if (env.INTERVAL_LOGGING) {
console.log('new interval started at ' + formatDateToBangkok(new Date()))
}
let messages: Array<string> = []
try {
messages = await updateAll()
} catch (e) {
console.log(e)
console.trace(e)
return none
}
if (messages.length == 0) {
Expand All @@ -26,11 +21,17 @@ export default async function updateHandler(): Promise<Option<boolean>> {
const channels = await db.getAllChannels()
for (const message of messages) {
for await (const NotificationChannel of channels) {
const discordChannel = (await client.channels.fetch(
NotificationChannel.channelID
)) as TextChannel
// adminDM.send(message);
await discordChannel.send(message)
try {
const discordChannel = (await client.channels.fetch(
NotificationChannel.channelID
)) as TextChannel
await discordChannel.send(message)
} catch (err) {
console.trace(err)
if (!(err instanceof DiscordAPIError)) {
adminDM.send(JSON.stringify(err))
}
}
}
}
return some(false)
Expand Down
93 changes: 93 additions & 0 deletions tests/unit/updateHandler.unit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import db, { NotificationChannel } from '@/database/database'
import { updateAll } from '@/scraper/updateAll'
import { adminDM, client } from '@/server'
import updateHandler from '@/utils/updateHandler'
import { DiscordAPIError } from 'discord.js'

jest.mock('@/env/env', () => {})
jest.mock('@/server', () => {
return {
client: {
channels: {
fetch: jest.fn(),
},
},
adminDM: {
send: jest.fn(),
},
}
})
jest.mock('@/server')
jest.mock('@/scraper/updateAll')
jest.mock('@/database/database', () => {
return {
getAllChannels: jest.fn(),
}
})

describe('catch discord error', () => {
let channels: NotificationChannel[]
let error: any
let messages: string[]

beforeAll(() => {
;(updateAll as jest.Mock).mockImplementation(() => {
return messages
})
;(db.getAllChannels as jest.Mock).mockImplementation(() => {
return channels
})
;(client.channels.fetch as jest.Mock).mockImplementation(() => {
throw error
})
})

beforeEach(() => {
jest.clearAllMocks()
})

it('discord error', async () => {
channels = [
{
guildID: '123',
channelID: '456',
},
]

error = new DiscordAPIError(
{
code: 50001,
errors: {},
message: '',
},
50001,
403,
'GET',
'',
{}
)

messages = ['g']

await updateHandler()

expect(adminDM.send).toHaveBeenCalledTimes(0)
})

it('non-discord error', async () => {
channels = [
{
guildID: '123',
channelID: '456',
},
]

error = 'gg'

messages = ['g']

await updateHandler()

expect(adminDM.send).toHaveBeenCalledTimes(1)
})
})

0 comments on commit 06e7a5e

Please sign in to comment.