-
-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* presence * from event presence and refactoring * refine presence api * add tests and more comments * sss --------- Co-authored-by: SrIzan10 <[email protected]>
- Loading branch information
Showing
10 changed files
with
219 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
}; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { concatMap, from, interval, of, map, scan, startWith, fromEvent, take } from "rxjs" | ||
import { Files } from "../core/_internal"; | ||
import * as Presence from "../core/presences"; | ||
import { Services } from "../core/ioc"; | ||
import assert from "node:assert"; | ||
|
||
type SetPresence = (conf: Presence.Result) => Promise<unknown> | ||
|
||
const parseConfig = async (conf: Promise<Presence.Result>) => { | ||
return conf.then(s => { | ||
if('repeat' in s) { | ||
const { onRepeat, repeat } = s; | ||
assert(repeat !== undefined, "repeat option is undefined"); | ||
assert(onRepeat !== undefined, "onRepeat callback is undefined, but repeat exists"); | ||
const src$ = typeof repeat === 'number' | ||
? interval(repeat) | ||
: fromEvent(...repeat); | ||
return src$ | ||
.pipe(scan(onRepeat, s), | ||
startWith(s)); | ||
} | ||
//take 1? | ||
return of(s).pipe(take(1)); | ||
}) | ||
}; | ||
|
||
export const presenceHandler = (path: string, setPresence: SetPresence) => { | ||
interface PresenceModule { | ||
module: Presence.Config<(keyof Dependencies)[]> | ||
} | ||
const presence = Files | ||
.importModule<PresenceModule>(path) | ||
.then(({ module }) => { | ||
//fetch services with the order preserved, passing it to the execute fn | ||
const fetchedServices = Services(...module.inject ?? []); | ||
return async () => module.execute(...fetchedServices); | ||
}) | ||
const module$ = from(presence); | ||
return module$.pipe( | ||
//compose:. | ||
//call the execute function, passing that result into parseConfig. | ||
//concatMap resolves the promise, and passes it to the next concatMap. | ||
concatMap(fn => parseConfig(fn())), | ||
// subscribe to the observable parseConfig yields, and set the presence. | ||
concatMap(conf => conf.pipe(map(setPresence)))) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { describe, expect, it, vi } from 'vitest'; | ||
import { Presence } from '../../src'; | ||
|
||
|
||
// Example test suite for the module function | ||
describe('module function', () => { | ||
it('should return a valid configuration', () => { | ||
const config: Presence.Config<['dependency1', 'dependency2']> = Presence.module({ | ||
inject: ['dependency1', 'dependency2'], | ||
execute: vi.fn(), | ||
}); | ||
|
||
expect(config).toBeDefined(); | ||
expect(config.inject).toEqual(['dependency1', 'dependency2']); | ||
expect(typeof config.execute).toBe('function'); | ||
}); | ||
}); | ||
|
||
|
||
describe('of function', () => { | ||
it('should return a valid presence configuration without repeat and onRepeat', () => { | ||
const presenceConfig = Presence.of({ | ||
status: 'online', | ||
afk: false, | ||
activities: [{ name: 'Test Activity' }], | ||
shardId: [1, 2, 3], | ||
}).once(); | ||
|
||
expect(presenceConfig).toBeDefined(); | ||
//@ts-ignore Maybe fix? | ||
expect(presenceConfig.repeat).toBeUndefined(); | ||
//@ts-ignore Maybe fix? | ||
expect(presenceConfig.onRepeat).toBeUndefined(); | ||
expect(presenceConfig).toMatchObject({ | ||
status: 'online', | ||
afk: false, | ||
activities: [{ name: 'Test Activity' }], | ||
shardId: [1, 2, 3], | ||
}); | ||
}); | ||
|
||
it('should return a valid presence configuration with repeat and onRepeat', () => { | ||
const onRepeatCallback = vi.fn(); | ||
const presenceConfig = Presence.of({ | ||
status: 'idle', | ||
activities: [{ name: 'Another Test Activity' }], | ||
}).repeated(onRepeatCallback, 5000); | ||
|
||
expect(presenceConfig).toBeDefined(); | ||
expect(presenceConfig.repeat).toBe(5000); | ||
expect(presenceConfig.onRepeat).toBe(onRepeatCallback); | ||
expect(presenceConfig).toMatchObject({ | ||
status: 'idle', | ||
activities: [{ name: 'Another Test Activity' }], | ||
}); | ||
}); | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters