/[sudobot]/branches/6.x/src/core/ServiceManager.ts
ViewVC logotype

Annotation of /branches/6.x/src/core/ServiceManager.ts

Parent Directory Parent Directory | Revision Log Revision Log


Revision 577 - (hide annotations)
Mon Jul 29 18:52:37 2024 UTC (8 months ago) by rakinar2
File MIME type: application/typescript
File size: 4803 byte(s)
chore: add old version archive branches (2.x to 9.x-dev)
1 rakinar2 577 /**
2     * This file is part of SudoBot.
3     *
4     * Copyright (C) 2021-2023 OSN Developers.
5     *
6     * SudoBot is free software; you can redistribute it and/or modify it
7     * under the terms of the GNU Affero General Public License as published by
8     * the Free Software Foundation, either version 3 of the License, or
9     * (at your option) any later version.
10     *
11     * SudoBot is distributed in the hope that it will be useful, but
12     * WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU Affero General Public License for more details.
15     *
16     * You should have received a copy of the GNU Affero General Public License
17     * along with SudoBot. If not, see <https://www.gnu.org/licenses/>.
18     */
19    
20     import { lstatSync } from "fs";
21     import { readdir } from "fs/promises";
22     import { join } from "path";
23     import { log, logInfo, logWarn } from "../utils/logger";
24     import Client from "./Client";
25     import Service from "./Service";
26    
27     type LoadServiceOptions = {
28     extensionName?: string;
29     serviceAliasName?: string;
30     log?: boolean;
31     };
32    
33     export default class ServiceManager {
34     constructor(protected client: Client) {}
35    
36     async loadServices() {
37     for (const service of this.client.services) {
38     let replacedService = service;
39    
40     for (const alias in this.client.aliases) {
41     replacedService = replacedService.replace(alias, this.client.aliases[alias as keyof typeof this.client.aliases]);
42     }
43    
44     await this.loadService(replacedService);
45     }
46     }
47    
48     async loadService(servicePath: string, { extensionName, serviceAliasName, log = true }: LoadServiceOptions = {}) {
49     const { default: Service, name } = await import(servicePath);
50     const wasPreviouslyLoaded = this.wasPreviouslyLoaded(name);
51     const finalName = extensionName ?? serviceAliasName ?? name;
52    
53     if (log) {
54     logInfo(`${wasPreviouslyLoaded ? "Rel" : "L"}oading service: `, finalName);
55     }
56    
57     const serviceInstance = new Service(this.client);
58     this.client[name as "services"] = serviceInstance;
59     this.client.loadEventListenersFromMetadata(Service, serviceInstance);
60     await this.serviceLifeCycle(serviceInstance, wasPreviouslyLoaded, finalName);
61     }
62    
63     wasPreviouslyLoaded(name: string) {
64     return this.client[name as "services"] instanceof Service;
65     }
66    
67     async deactivateService(name: string) {
68     if (!(this.client[name as "services"] instanceof Service)) {
69     return;
70     }
71    
72     logInfo("Deactivated service: ", name);
73     await (this.client[name as "services"] as any)?.deactivate();
74     this.client[name as "services"] = {} as any;
75     }
76    
77     async serviceLifeCycle(serviceInstance: Service, wasPreviouslyLoaded: boolean, finalName: string) {
78     if (wasPreviouslyLoaded) {
79     await serviceInstance.deactivate();
80     }
81    
82     if (!wasPreviouslyLoaded) {
83     await serviceInstance.boot();
84     }
85    
86     await serviceInstance.reboot();
87    
88     if (wasPreviouslyLoaded) {
89     await serviceInstance.rebootNext();
90     }
91     }
92    
93     async loadServiceFromFile(path: string, extension?: string) {
94     const {
95     default: Service,
96     name
97     }: {
98     name?: string;
99     default: new (client: Client) => Service;
100     } = await import(path);
101    
102     if (!name && extension) {
103     logWarn(
104     `Extension ${extension} has attempted to load a service that does not export a \`name\` constant. (file: ${path})`
105     );
106     return false;
107     }
108    
109     const wasPreviouslyLoaded = !!this.client[name as "services"];
110     const finalName = extension ? `${extension}:@services/${name}` : `@services/${name ?? path}`;
111    
112     logInfo("Loading service: ", finalName);
113    
114     const service = new Service(this.client);
115    
116     this.client[name as "services"] = service as any;
117     this.client.loadEventListenersFromMetadata(Service, service);
118    
119     await this.serviceLifeCycle(service, wasPreviouslyLoaded, name ?? path);
120     return true;
121     }
122    
123     async loadServiceFromDirectory(path: string) {
124     const files = await readdir(path);
125    
126     for (const file of files) {
127     const filePath = join(path, file);
128    
129     if (lstatSync(filePath).isDirectory()) {
130     await this.loadServiceFromDirectory(filePath);
131     continue;
132     }
133    
134     if (file.endsWith(".d.ts")) {
135     continue;
136     }
137    
138     if (file.endsWith(".js") || file.endsWith(".ts")) {
139     log("Attempting to load service from file: ", filePath);
140     await this.loadServiceFromFile(filePath);
141     }
142     }
143     }
144     }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26