Skip to content

Commit

Permalink
Add tsyringe to handle DI (#298)
Browse files Browse the repository at this point in the history
  • Loading branch information
LamboCreeper authored Aug 11, 2024
1 parent a899584 commit 3ad6fc8
Show file tree
Hide file tree
Showing 29 changed files with 205 additions and 434 deletions.
4 changes: 3 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ module.exports = {
}
},
rules: {
"no-useless-constructor": "off",
"no-empty-function": "off",
"new-cap": "off",
"no-unused-vars": "off",
"no-invalid-this": "off",
Expand All @@ -27,4 +29,4 @@ module.exports = {
extends: [
"eslint-config-codesupport"
],
};
};
15 changes: 8 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
"build": "tsc",
"dev": "cross-env NODE_ENV=dev nodemon --watch src --ext ts --exec 'ts-node -r dotenv/config ./src/index.ts'",
"coverage": "nyc --reporter=lcov --reporter=text-summary npm test",
"test": "ts-mocha test/**/*Test.ts test/**/**/*Test.ts test/appTest.ts --exit",
"test:debug": "ts-mocha test/**/*Test.ts test/**/**/*Test.ts test/appTest.ts --timeout 999999999 --exit",
"test": "ts-mocha test/**/*Test.ts test/**/**/*Test.ts test/appTest.ts --require=test/test-setup.ts --exit",
"test:debug": "ts-mocha test/**/*Test.ts test/**/**/*Test.ts test/appTest.ts --timeout 999999999 --require=test/test-setup.ts --exit",
"lint": "eslint src test --ext .js,.ts"
},
"repository": {
Expand Down Expand Up @@ -40,7 +40,8 @@
"discordx": "^11.7.6",
"dotenv": "^16.3.1",
"node-schedule": "^2.1.0",
"reflect-metadata": "^0.1.13"
"reflect-metadata": "^0.1.13",
"tsyringe": "^4.8.0"
},
"devDependencies": {
"@istanbuljs/nyc-config-typescript": "^1.0.1",
Expand Down
10 changes: 8 additions & 2 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import "reflect-metadata";
import axios from "axios";
import { Client } from "discordx";
import {Client, DIService, tsyringeDependencyRegistryEngine} from "discordx";
import { TextChannel, Snowflake } from "discord.js";
import { config as env } from "dotenv";
import DirectoryUtils from "./utils/DirectoryUtils";
import DiscordUtils from "./utils/DiscordUtils";
import getConfigValue from "./utils/getConfigValue";
import Schedule from "./decorators/Schedule";
import {container} from "tsyringe";
import {setupCache} from "axios-cache-interceptor";

if (process.env.NODE_ENV !== getConfigValue<string>("PRODUCTION_ENV")) {
env({
Expand All @@ -28,6 +30,10 @@ class App {
intents: DiscordUtils.getAllIntentsApartFromPresence(),
silent: false
});

container.register("AXIOS_CACHED_INSTANCE", setupCache(axios));

DIService.engine = tsyringeDependencyRegistryEngine.setInjector(container);
}

@Schedule("*/5 * * * *")
Expand Down Expand Up @@ -76,4 +82,4 @@ class App {
}
}

export default App;
export default App;
22 changes: 11 additions & 11 deletions src/commands/AdventOfCodeCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,22 @@ import AdventOfCodeService from "../services/AdventOfCodeService";
import { AOCMember } from "../interfaces/AdventOfCode";
import getConfigValue from "../utils/getConfigValue";
import GenericObject from "../interfaces/GenericObject";
import {Discord, Slash, SlashOption} from "discordx";
import { Discord, Slash, SlashOption } from "discordx";
import { injectable as Injectable } from "tsyringe";

@Discord()
@Injectable()
class AdventOfCodeCommand {
constructor(
private readonly adventOfCodeService: AdventOfCodeService,
) {}

@Slash({ name: "aoc", description: "Advent Of Code" })
async onInteract(
@SlashOption({ name: "year", description: "AOC year", type: ApplicationCommandOptionType.Number, minValue: 2015, required: false }) year: number | undefined,
@SlashOption({ name: "name", description: "User's name", type: ApplicationCommandOptionType.String, required: false }) name: string | undefined,
interaction: CommandInteraction
): Promise<void> {
const adventOfCodeService = AdventOfCodeService.getInstance();
const embed = new EmbedBuilder();
const button = new ButtonBuilder();
let yearToQuery = this.getYear();
Expand All @@ -37,12 +42,7 @@ class AdventOfCodeCommand {

if (!!name) {
try {
const [position, user] = await adventOfCodeService.getSinglePlayer(getConfigValue<string>("ADVENT_OF_CODE_LEADERBOARD"), yearToQuery, name);

if (!user) {
await interaction.reply({embeds: [this.errorEmbed("Could not get the user requested\nPlease make sure you typed the name correctly")], ephemeral: true});
return;
}
const [position, user] = await this.adventOfCodeService.getSinglePlayer(getConfigValue<string>("ADVENT_OF_CODE_LEADERBOARD"), yearToQuery, name);

embed.setTitle("Advent Of Code");
embed.setDescription(description);
Expand All @@ -57,13 +57,13 @@ class AdventOfCodeCommand {
await interaction.reply({embeds: [embed], components: [row] });
return;
} catch {
await interaction.reply({embeds: [this.errorEmbed("Could not get the statistics for Advent Of Code.")], ephemeral: true});
await interaction.reply({embeds: [this.errorEmbed("Could not get the user requested\nPlease make sure you typed the name correctly")], ephemeral: true});
return;
}
}

try {
const members = await adventOfCodeService.getSortedPlayerList(getConfigValue<string>("ADVENT_OF_CODE_LEADERBOARD"), yearToQuery);
const members = await this.adventOfCodeService.getSortedPlayerList(getConfigValue<string>("ADVENT_OF_CODE_LEADERBOARD"), yearToQuery);
const playerList = this.generatePlayerList(members, getConfigValue<number>("ADVENT_OF_CODE_RESULTS_PER_PAGE"));

embed.setTitle("Advent Of Code");
Expand Down Expand Up @@ -141,4 +141,4 @@ class AdventOfCodeCommand {
}
}

export default AdventOfCodeCommand;
export default AdventOfCodeCommand;
13 changes: 9 additions & 4 deletions src/commands/GitHubCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@ import GitHubService from "../services/GitHubService";
import getConfigValue from "../utils/getConfigValue";
import GenericObject from "../interfaces/GenericObject";
import {Discord, Slash, SlashOption} from "discordx";
import { injectable as Injectable } from "tsyringe";

@Discord()
@Injectable()
class GitHubCommand {
constructor(
private readonly githubService: GitHubService
) {}

@Slash({ name: "github", description: "Shows information about a GitHub repository" })
async onInteract(
@SlashOption({ name: "user", description: "Github user/account", type: ApplicationCommandOptionType.String, required: true }) user: string,
Expand All @@ -15,9 +21,8 @@ class GitHubCommand {
const embed = new EmbedBuilder();

try {
const GitHub = GitHubService.getInstance();
const res = await GitHub.getRepository(user, repo);
const resPR = await GitHub.getPullRequest(user, repo);
const res = await this.githubService.getRepository(user, repo);
const resPR = await this.githubService.getPullRequest(user, repo);

let desc = `[View on GitHub](${res.url})`;

Expand Down Expand Up @@ -45,4 +50,4 @@ class GitHubCommand {
}
}

export default GitHubCommand;
export default GitHubCommand;
17 changes: 11 additions & 6 deletions src/commands/IssuesCommand.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {ColorResolvable, CommandInteraction, EmbedBuilder, ApplicationCommandOptionType} from "discord.js";
import {Discord, Slash, SlashOption} from "discordx";
import { ColorResolvable, CommandInteraction, EmbedBuilder, ApplicationCommandOptionType } from "discord.js";
import { Discord, Slash, SlashOption } from "discordx";
import { injectable as Injectable } from "tsyringe";
import GitHubService from "../services/GitHubService";
import GitHubIssue from "../interfaces/GitHubIssue";
import DateUtils from "../utils/DateUtils";
Expand All @@ -8,7 +9,12 @@ import getConfigValue from "../utils/getConfigValue";
import GenericObject from "../interfaces/GenericObject";

@Discord()
@Injectable()
class IssuesCommand {
constructor(
private readonly gitHubService: GitHubService
) {}

@Slash({ name: "issues", description: "Shows the open issues on a GitHub repository" })
async onInteract(
@SlashOption({ name: "user", description: "Github user/account", type: ApplicationCommandOptionType.String, required: true }) user: string,
Expand All @@ -18,9 +24,8 @@ class IssuesCommand {
const embed = new EmbedBuilder();

try {
const GitHub = GitHubService.getInstance();
const resIssues = await GitHub.getIssues(user, repoName);
const resRep = await GitHub.getRepository(user, repoName);
const resIssues = await this.gitHubService.getIssues(user, repoName);
const resRep = await this.gitHubService.getRepository(user, repoName);

if (resIssues.length) {
const issues = resIssues.slice(0, 3);
Expand Down Expand Up @@ -56,4 +61,4 @@ class IssuesCommand {
}
}

export default IssuesCommand;
export default IssuesCommand;
15 changes: 10 additions & 5 deletions src/commands/SearchCommand.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import {ColorResolvable, CommandInteraction, EmbedBuilder, ApplicationCommandOptionType} from "discord.js";
import {Discord, Slash, SlashOption} from "discordx";
import { ColorResolvable, CommandInteraction, EmbedBuilder, ApplicationCommandOptionType } from "discord.js";
import { Discord, Slash, SlashOption } from "discordx";
import { injectable as Injectable } from "tsyringe";
import InstantAnswerService from "../services/InstantAnswerService";
import getConfigValue from "../utils/getConfigValue";
import GenericObject from "../interfaces/GenericObject";

@Discord()
@Injectable()
class SearchCommand {
constructor(
private readonly instantAnswerService: InstantAnswerService
) {}

@Slash({ name: "search", description: "Search using the DuckDuckGo API" })
async onInteract(
@SlashOption({ name: "query", description: "Search query", type: ApplicationCommandOptionType.String, required: true }) query: string,
Expand All @@ -14,8 +20,7 @@ class SearchCommand {
const embed = new EmbedBuilder();

try {
const InstantAnswer = InstantAnswerService.getInstance();
const res = await InstantAnswer.query(query.replace(" ", "+"));
const res = await this.instantAnswerService.query(query.replace(" ", "+"));

if (res !== null) {
const [baseURL] = res.url.match(/[a-z]*\.[a-z]*(\.[a-z]*)*/) || [];
Expand All @@ -39,4 +44,4 @@ class SearchCommand {
}
}

export default SearchCommand;
export default SearchCommand;
11 changes: 7 additions & 4 deletions src/event/handlers/DiscordMessageLinkHandler.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import EventHandler from "../../abstracts/EventHandler";
import { Message, Events } from "discord.js";
import { injectable as Injectable } from "tsyringe";
import MessagePreviewService from "../../services/MessagePreviewService";

@Injectable()
class DiscordMessageLinkHandler extends EventHandler {
constructor() {
constructor(
private readonly messagePreviewService: MessagePreviewService
) {
super(Events.MessageCreate);
}

Expand All @@ -19,13 +23,12 @@ class DiscordMessageLinkHandler extends EventHandler {

if (message.content.charAt(index - 1) !== "<" || message.content.charAt(index + link.length) !== ">") {
link = link.replace(/app/, "").replace(/ptb\./, "");
const messagePreviewService = MessagePreviewService.getInstance();

await messagePreviewService.generatePreview(link, message);
await this.messagePreviewService.generatePreview(link, message);
}
}
}
}
}

export default DiscordMessageLinkHandler;
export default DiscordMessageLinkHandler;
20 changes: 7 additions & 13 deletions src/services/AdventOfCodeService.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
import axios from "axios";
import { setupCache } from "axios-cache-interceptor";
import {AxiosCacheInstance } from "axios-cache-interceptor";
import { injectable as Injectable, inject as Inject } from "tsyringe";
import { AOCLeaderBoard, AOCMember } from "../interfaces/AdventOfCode";

@Injectable()
export default class AdventOfCodeService {
// eslint-disable-next-line no-use-before-define
private static instance: AdventOfCodeService;
private api = setupCache(axios);

static getInstance(): AdventOfCodeService {
if (!this.instance) {
this.instance = new AdventOfCodeService();
}

return this.instance;
}
constructor(
@Inject("AXIOS_CACHED_INSTANCE")
private readonly api: AxiosCacheInstance
) {}

async getLeaderBoard(leaderBoard: string, year: number): Promise<AOCLeaderBoard> {
const { ADVENT_OF_CODE_TOKEN } = process.env;
Expand Down
19 changes: 3 additions & 16 deletions src/services/GitHubService.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,11 @@
import axios from "axios";
import { injectable as Injectable } from "tsyringe";
import GitHubRepository from "../interfaces/GitHubRepository";
import GitHubPullRequest from "../interfaces/GitHubPullRequest";
import GitHubIssue from "../interfaces/GitHubIssue";

@Injectable()
class GitHubService {
// eslint-disable-next-line no-use-before-define
private static instance: GitHubService;

/* eslint-disable */
private constructor() { }
/* eslint-enable */

static getInstance(): GitHubService {
if (!this.instance) {
this.instance = new GitHubService();
}

return this.instance;
}

async getRepository(user: string, repo: string): Promise<GitHubRepository> {
const url = `https://api.github.com/repos/${user}/${repo}`;
const { status, data } = await axios.get(url);
Expand Down Expand Up @@ -81,4 +68,4 @@ class GitHubService {
}
}

export default GitHubService;
export default GitHubService;
Loading

0 comments on commit 3ad6fc8

Please sign in to comment.