diff --git a/.eslintrc.js b/.eslintrc.js index 55ec41e..c290178 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -29,4 +29,18 @@ module.exports = { "semi": "warn", "no-console": "warn" }, + overrides: [ + { + files: ["src/**/*.ts"], + + parserOptions: { + project: ["./tsconfig.json"], + }, + + rules: { + "@typescript-eslint/no-misused-promises": "warn", + "@typescript-eslint/no-floating-promises" : "warn" + } + }, + ], }; diff --git a/src/app.ts b/src/app.ts index b90daa9..e5502c4 100644 --- a/src/app.ts +++ b/src/app.ts @@ -85,18 +85,18 @@ function setupRoutes(router: Router) { } //add the get function - router.get("/api/getVideoSponsorTimes", oldGetVideoSponsorTimes); + router.get("/api/getVideoSponsorTimes", void oldGetVideoSponsorTimes); //add the oldpost function - router.get("/api/postVideoSponsorTimes", oldSubmitSponsorTimes); - router.post("/api/postVideoSponsorTimes", oldSubmitSponsorTimes); + router.get("/api/postVideoSponsorTimes", void oldSubmitSponsorTimes); + router.post("/api/postVideoSponsorTimes", void oldSubmitSponsorTimes); //add the skip segments functions - router.get("/api/skipSegments", getSkipSegments); - router.post("/api/skipSegments", postSkipSegments); + router.get("/api/skipSegments", void getSkipSegments); + router.post("/api/skipSegments", void postSkipSegments); // add the privacy protecting skip segments functions - router.get("/api/skipSegments/:prefix", getSkipSegmentsByHash); + router.get("/api/skipSegments/:prefix", void getSkipSegmentsByHash); //voting endpoint router.get("/api/voteOnSponsorTime", ...voteEndpoints); @@ -107,106 +107,106 @@ function setupRoutes(router: Router) { router.post("/api/viewedVideoSponsorTime", ...viewEndpoints); //To set your username for the stats view - router.post("/api/setUsername", setUsername); + router.post("/api/setUsername", void setUsername); //get what username this user has - router.get("/api/getUsername", getUsername); + router.get("/api/getUsername", void getUsername); //Endpoint used to hide a certain user's data - router.post("/api/shadowBanUser", shadowBanUser); + router.post("/api/shadowBanUser", void shadowBanUser); //Endpoint used to make a user a VIP user with special privileges - router.post("/api/addUserAsVIP", addUserAsVIP); + router.post("/api/addUserAsVIP", void addUserAsVIP); //Endpoint to add a user as a temporary VIP - router.post("/api/addUserAsTempVIP", addUserAsTempVIP); + router.post("/api/addUserAsTempVIP", void addUserAsTempVIP); //Gets all the views added up for one userID //Useful to see how much one user has contributed - router.get("/api/getViewsForUser", getViewsForUser); + router.get("/api/getViewsForUser", void getViewsForUser); //Gets all the saved time added up (views * sponsor length) for one userID //Useful to see how much one user has contributed //In minutes - router.get("/api/getSavedTimeForUser", getSavedTimeForUser); + router.get("/api/getSavedTimeForUser", void getSavedTimeForUser); - router.get("/api/getTopUsers", getTopUsers); - router.get("/api/getTopCategoryUsers", getTopCategoryUsers); + router.get("/api/getTopUsers", void getTopUsers); + router.get("/api/getTopCategoryUsers", void getTopCategoryUsers); //send out totals //send the total submissions, total views and total minutes saved - router.get("/api/getTotalStats", getTotalStats); + router.get("/api/getTotalStats", void getTotalStats); - router.get("/api/getUserInfo", getUserInfo); - router.get("/api/userInfo", getUserInfo); + router.get("/api/getUserInfo", void getUserInfo); + router.get("/api/userInfo", void getUserInfo); //send out a formatted time saved total - router.get("/api/getDaysSavedFormatted", getDaysSavedFormatted); + router.get("/api/getDaysSavedFormatted", void getDaysSavedFormatted); //submit video to lock categories - router.post("/api/noSegments", postLockCategories); - router.post("/api/lockCategories", postLockCategories); + router.post("/api/noSegments", void postLockCategories); + router.post("/api/lockCategories", void postLockCategories); - router.delete("/api/noSegments", deleteLockCategoriesEndpoint); - router.delete("/api/lockCategories", deleteLockCategoriesEndpoint); + router.delete("/api/noSegments", void deleteLockCategoriesEndpoint); + router.delete("/api/lockCategories", void deleteLockCategoriesEndpoint); //get if user is a vip - router.get("/api/isUserVIP", getIsUserVIP); + router.get("/api/isUserVIP", void getIsUserVIP); //sent user a warning - router.post("/api/warnUser", postWarning); + router.post("/api/warnUser", void postWarning); //get if user is a vip - router.post("/api/segmentShift", postSegmentShift); + router.post("/api/segmentShift", void postSegmentShift); //get segment info - router.get("/api/segmentInfo", getSegmentInfo); + router.get("/api/segmentInfo", void getSegmentInfo); //clear cache as VIP - router.post("/api/clearCache", postClearCache); + router.post("/api/clearCache", void postClearCache); //purge all segments for VIP - router.post("/api/purgeAllSegments", postPurgeAllSegments); + router.post("/api/purgeAllSegments", void postPurgeAllSegments); - router.post("/api/unlistedVideo", addUnlistedVideo); + router.post("/api/unlistedVideo", void addUnlistedVideo); // get userID from username - router.get("/api/userID", getUserID); + router.get("/api/userID", void getUserID); // get lock categores from userID - router.get("/api/lockCategories", getLockCategories); + router.get("/api/lockCategories", void getLockCategories); // get privacy protecting lock categories functions - router.get("/api/lockCategories/:prefix", getLockCategoriesByHash); + router.get("/api/lockCategories/:prefix", void getLockCategoriesByHash); // get all segments that match a search - router.get("/api/searchSegments", getSearchSegments); + router.get("/api/searchSegments", void getSearchSegments); // autocomplete chapter names - router.get("/api/chapterNames", getChapterNames); + router.get("/api/chapterNames", void getChapterNames); // get status - router.get("/api/status/:value", getStatus); - router.get("/api/status", getStatus); + router.get("/api/status/:value", void getStatus); + router.get("/api/status", void getStatus); - router.get("/api/youtubeApiProxy", youtubeApiProxy); + router.get("/api/youtubeApiProxy", void youtubeApiProxy); // get user category stats - router.get("/api/userStats", getUserStats); + router.get("/api/userStats", void getUserStats); - router.get("/api/lockReason", getLockReason); + router.get("/api/lockReason", void getLockReason); - router.post("/api/feature", addFeature); + router.post("/api/feature", void addFeature); - router.get("/api/generateToken/:type", generateTokenRequest); - router.get("/api/verifyToken", verifyTokenRequest); + router.get("/api/generateToken/:type", void generateTokenRequest); + router.get("/api/verifyToken", void verifyTokenRequest); if (config.postgres?.enabled) { - router.get("/database", (req, res) => dumpDatabase(req, res, true)); - router.get("/database.json", (req, res) => dumpDatabase(req, res, false)); - router.get("/database/*", downloadFile); + router.get("/database", (req, res) => void dumpDatabase(req, res, true)); + router.get("/database.json", (req, res) => void dumpDatabase(req, res, false)); + router.get("/database/*", void downloadFile); router.use("/download", express.static(appExportPath)); } else { router.get("/database.db", function (req: Request, res: Response) { res.sendFile("./databases/sponsorTimes.db", { root: "./" }); }); } -} +} \ No newline at end of file diff --git a/src/cronjob/downvoteSegmentArchiveJob.ts b/src/cronjob/downvoteSegmentArchiveJob.ts index 74d72ac..5ff2282 100644 --- a/src/cronjob/downvoteSegmentArchiveJob.ts +++ b/src/cronjob/downvoteSegmentArchiveJob.ts @@ -57,7 +57,7 @@ export const archiveDownvoteSegment = async (dayLimit: number, voteLimit: number const DownvoteSegmentArchiveJob = new CronJob( jobConfig?.schedule || "0 0 * * * 0", - () => archiveDownvoteSegment(jobConfig?.timeThresholdInDays, jobConfig?.voteThreshold) + () => void archiveDownvoteSegment(jobConfig?.timeThresholdInDays, jobConfig?.voteThreshold) ); if (serverConfig?.crons?.enabled && jobConfig && !jobConfig.schedule) { diff --git a/src/databases/Postgres.ts b/src/databases/Postgres.ts index ff97c6f..07879cb 100644 --- a/src/databases/Postgres.ts +++ b/src/databases/Postgres.ts @@ -177,7 +177,7 @@ export class Postgres implements IDatabase { ); } - client.end(); + client.end().catch(err => Logger.error(`closing db (postgres): ${err}`)); } private async upgradeDB(fileNamePrefix: string, schemaFolder: string) { diff --git a/src/index.ts b/src/index.ts index e538741..e34882a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -27,4 +27,4 @@ async function init() { }).setTimeout(15000); } -init(); +init().catch((err) => Logger.error(err)); \ No newline at end of file diff --git a/src/middleware/requestRateLimit.ts b/src/middleware/requestRateLimit.ts index 853738e..f7e40cc 100644 --- a/src/middleware/requestRateLimit.ts +++ b/src/middleware/requestRateLimit.ts @@ -22,6 +22,7 @@ export function rateLimitMiddleware(limitConfig: RateLimitConfig, getUserID?: (r keyGenerator: (req) => { return getHash(getIP(req), 1); }, + // eslint-disable-next-line @typescript-eslint/no-misused-promises handler: async (req, res, next) => { if (getUserID === undefined || !await isUserVIP(await getHashCache(getUserID(req)))) { return res.status(limitConfig.statusCode).send(limitConfig.message); diff --git a/src/routes/dumpDatabase.ts b/src/routes/dumpDatabase.ts index ca579d6..c3dc2ba 100644 --- a/src/routes/dumpDatabase.ts +++ b/src/routes/dumpDatabase.ts @@ -75,6 +75,7 @@ function removeOutdatedDumps(exportPath: string): Promise { }, {}); // read files in export directory + // eslint-disable-next-line @typescript-eslint/no-misused-promises fs.readdir(exportPath, async (err: any, files: string[]) => { if (err) Logger.error(err); if (err) return resolve(); diff --git a/src/routes/getTopCategoryUsers.ts b/src/routes/getTopCategoryUsers.ts index b9558dd..305bcf5 100644 --- a/src/routes/getTopCategoryUsers.ts +++ b/src/routes/getTopCategoryUsers.ts @@ -4,7 +4,7 @@ import { config } from "../config"; import { Request, Response } from "express"; const MILLISECONDS_IN_MINUTE = 60000; -const getTopCategoryUsersWithCache = createMemoryCache(generateTopCategoryUsersStats, config.getTopUsersCacheTimeMinutes * MILLISECONDS_IN_MINUTE); +const getTopCategoryUsersWithCache = createMemoryCache(void generateTopCategoryUsersStats, config.getTopUsersCacheTimeMinutes * MILLISECONDS_IN_MINUTE); const maxRewardTimePerSegmentInSeconds = config.maxRewardTimePerSegmentInSeconds ?? 86400; interface DBSegment { diff --git a/src/routes/getTopUsers.ts b/src/routes/getTopUsers.ts index 34d6bc5..d600f19 100644 --- a/src/routes/getTopUsers.ts +++ b/src/routes/getTopUsers.ts @@ -4,7 +4,7 @@ import { config } from "../config"; import { Request, Response } from "express"; const MILLISECONDS_IN_MINUTE = 60000; -const getTopUsersWithCache = createMemoryCache(generateTopUsersStats, config.getTopUsersCacheTimeMinutes * MILLISECONDS_IN_MINUTE); +const getTopUsersWithCache = createMemoryCache(void generateTopUsersStats, config.getTopUsersCacheTimeMinutes * MILLISECONDS_IN_MINUTE); const maxRewardTimePerSegmentInSeconds = config.maxRewardTimePerSegmentInSeconds ?? 86400; async function generateTopUsersStats(sortBy: string, categoryStatsEnabled = false) { diff --git a/src/routes/postSkipSegments.ts b/src/routes/postSkipSegments.ts index bca2062..755b5b7 100644 --- a/src/routes/postSkipSegments.ts +++ b/src/routes/postSkipSegments.ts @@ -76,7 +76,7 @@ async function sendWebhooks(apiVideoInfo: APIVideoInfo, userID: string, videoID: sendWebhookNotification(userID, videoID, UUID, userSubmissionCountRow.submissionCount, data, { submissionStart: startTime, submissionEnd: endTime, - }, segmentInfo); + }, segmentInfo).catch(Logger.error); // If it is a first time submission // Then send a notification to discord @@ -395,7 +395,7 @@ async function updateDataIfVideoDurationChange(videoID: VideoID, service: Servic await db.prepare("run", `UPDATE "sponsorTimes" SET "hidden" = 1 WHERE "UUID" = ?`, [submission.UUID]); } lockedCategoryList = []; - deleteLockCategories(videoID, null, null, service); + deleteLockCategories(videoID, null, null, service).catch(Logger.error); } return { @@ -614,7 +614,7 @@ export async function postSkipSegments(req: Request, res: Response): Promise(fetchFromDB: (values: U[]) => Pr if (valuesToBeFetched.length > 0) { data = await fetchFromDB(valuesToBeFetched); - new Promise(() => { + void new Promise(() => { const newResults: Record = {}; for (const item of data) { const splitValue = (item as unknown as Record)[splitKey]; diff --git a/src/utils/redis.ts b/src/utils/redis.ts index 90a56d1..8e8c6d0 100644 --- a/src/utils/redis.ts +++ b/src/utils/redis.ts @@ -28,7 +28,7 @@ let exportClient: RedisSB = { if (config.redis?.enabled) { Logger.info("Connected to redis"); const client = createClient(config.redis); - client.connect(); + void client.connect(); // void as we don't care about the promise exportClient = client as RedisSB; const get = client.get.bind(client); @@ -40,7 +40,7 @@ if (config.redis?.enabled) { }).catch((err) => reject(err)); }); exportClient.increment = (key) => new Promise((resolve, reject) => - client.multi() + void client.multi() .incr(key) .expire(key, 60) .exec() diff --git a/src/utils/youtubeApi.ts b/src/utils/youtubeApi.ts index 5f3dfe7..6580f5e 100644 --- a/src/utils/youtubeApi.ts +++ b/src/utils/youtubeApi.ts @@ -39,8 +39,8 @@ export class YouTubeAPI { } const apiResult = data as APIVideoData; DiskCache.set(cacheKey, apiResult) - .catch((err: any) => Logger.warn(err)) - .then(() => Logger.debug(`YouTube API: video information cache set for: ${videoID}`)); + .then(() => Logger.debug(`YouTube API: video information cache set for: ${videoID}`)) + .catch((err: any) => Logger.warn(err)); return { err: false, data: apiResult }; } else {