mirror of
https://github.com/sern-handler/handler
synced 2026-06-21 15:22:15 +00:00
feat: presence (#345)
* presence * from event presence and refactoring * refine presence api * add tests and more comments * sss --------- Co-authored-by: SrIzan10 <66965250+SrIzan10@users.noreply.github.com>
This commit is contained in:
@@ -6,9 +6,19 @@ import assert from 'assert';
|
||||
import { createRequire } from 'node:module';
|
||||
import type { ImportPayload, Wrapper } from '../types/core';
|
||||
import type { Module } from '../types/core-modules';
|
||||
import { existsSync } from 'fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
export const shouldHandle = (path: string, fpath: string) => {
|
||||
const newPath = new URL(fpath+extname(path), path).href;
|
||||
return {
|
||||
exists: existsSync(fileURLToPath(newPath)),
|
||||
path: newPath
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export type ModuleResult<T> = Promise<ImportPayload<T>>;
|
||||
|
||||
/**
|
||||
* Import any module based on the absolute path.
|
||||
* This can accept four types of exported modules
|
||||
@@ -66,6 +76,7 @@ const isSkippable = (filename: string) => {
|
||||
const validExtensions = ['.js', '.cjs', '.mts', '.mjs', '.cts', '.ts', ''];
|
||||
return filename[0] === '!' || !validExtensions.includes(extname(filename));
|
||||
};
|
||||
|
||||
async function deriveFileInfo(dir: string, file: string) {
|
||||
const fullPath = join(dir, file);
|
||||
return {
|
||||
@@ -74,6 +85,7 @@ async function deriveFileInfo(dir: string, file: string) {
|
||||
base: basename(file),
|
||||
};
|
||||
}
|
||||
|
||||
async function* readPaths(dir: string): AsyncGenerator<string> {
|
||||
try {
|
||||
const files = await readdir(dir);
|
||||
@@ -118,6 +130,8 @@ export function loadConfig(wrapper: Wrapper | 'file'): Wrapper {
|
||||
eventsPath = makePath('events');
|
||||
console.log('Events path is set to', eventsPath);
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
defaultPrefix: config.defaultPrefix,
|
||||
commands: commandsPath,
|
||||
|
||||
@@ -61,18 +61,19 @@ export function discordEvent<T extends keyof ClientEvents>(mod: {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
function prepareClassPlugins(c: Module) {
|
||||
const [onEvent, initPlugins] = partitionPlugins(c.plugins);
|
||||
c.plugins = initPlugins as InitPlugin[];
|
||||
c.onEvent = onEvent as ControlPlugin[];
|
||||
}
|
||||
//
|
||||
// Class modules:
|
||||
// Can be refactored.
|
||||
// Both implement singleton, could I make them inherit a singleton parent class?
|
||||
|
||||
/**
|
||||
* @Experimental
|
||||
* Will be refactored / changed in future
|
||||
* @deprecated
|
||||
* Will be removed in future
|
||||
*/
|
||||
export abstract class CommandExecutable<const Type extends CommandType = CommandType> {
|
||||
abstract type: Type;
|
||||
@@ -92,8 +93,8 @@ export abstract class CommandExecutable<const Type extends CommandType = Command
|
||||
}
|
||||
|
||||
/**
|
||||
* @Experimental
|
||||
* Will be refactored in future
|
||||
* @deprecated
|
||||
* Will be removed in future
|
||||
*/
|
||||
export abstract class EventExecutable<Type extends EventType> {
|
||||
abstract type: Type;
|
||||
|
||||
70
src/core/presences.ts
Normal file
70
src/core/presences.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import type { ActivitiesOptions } from "discord.js";
|
||||
import type { IntoDependencies } from "../types/ioc";
|
||||
import type { Emitter } from "./contracts/emitter";
|
||||
|
||||
type Status = 'online' | 'idle' | 'invisible' | 'dnd'
|
||||
type PresenceReduce = (previous: Result) => Result;
|
||||
|
||||
export interface Result {
|
||||
status?: Status;
|
||||
afk?: boolean;
|
||||
activities?: ActivitiesOptions[];
|
||||
shardId?: number[];
|
||||
repeat?: number | [Emitter, string];
|
||||
onRepeat?: (previous: Result) => Result;
|
||||
}
|
||||
|
||||
export type Config <T extends (keyof Dependencies)[]> =
|
||||
{
|
||||
inject?: [...T]
|
||||
execute: (...v: IntoDependencies<T>) => Result;
|
||||
};
|
||||
|
||||
/**
|
||||
* A small wrapper to provide type inference.
|
||||
* Create a Presence module which **MUST** be put in a file called presence.<language-extension>
|
||||
* adjacent to the file where **Sern.init** is CALLED.
|
||||
*/
|
||||
export function module<T extends (keyof Dependencies)[]>
|
||||
(conf: Config<T>) {
|
||||
return conf;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a Presence body which can be either:
|
||||
* - once, the presence is activated only once.
|
||||
* - repeated, per cycle or event, the presence can be changed.
|
||||
*/
|
||||
export function of(root: Omit<Result, 'repeat' | 'onRepeat'>) {
|
||||
return {
|
||||
/**
|
||||
* @example
|
||||
* Presence
|
||||
* .of({
|
||||
* activities: [{ name: "deez nuts" }]
|
||||
* }) //starts the presence with "deez nuts".
|
||||
* .repeated(prev => {
|
||||
* return {
|
||||
* afk: true,
|
||||
* activities: prev.activities?.map(s => ({ ...s, name: s.name+"s" }))
|
||||
* };
|
||||
* }, 10000)) //every 10 s, the callback sets the presence to the returned one.
|
||||
*/
|
||||
repeated: (onRepeat: PresenceReduce, repeat: number | [Emitter, string]) => {
|
||||
return { repeat, onRepeat, ...root }
|
||||
},
|
||||
/**
|
||||
* @example
|
||||
* Presence
|
||||
* .of({
|
||||
* activities: [
|
||||
* { name: "Chilling out" }
|
||||
* ]
|
||||
* })
|
||||
* .once() // Sets the presence once, with what's provided in '.of()'
|
||||
*/
|
||||
once: () => root
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user