apexify.js 4.6.2 → 4.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/ai/ApexModules.d.ts.map +1 -1
- package/dist/cjs/ai/ApexModules.js +56 -7
- package/dist/cjs/ai/ApexModules.js.map +1 -1
- package/dist/cjs/ai/functions/readFiles.js +1 -1
- package/dist/cjs/ai/functions/readFiles.js.map +1 -1
- package/dist/cjs/ai/modals-chat/electronHub/chatmodels.d.ts.map +1 -1
- package/dist/cjs/ai/modals-chat/electronHub/chatmodels.js +2 -1
- package/dist/cjs/ai/modals-chat/electronHub/chatmodels.js.map +1 -1
- package/dist/cjs/ai/modals-chat/electronHub/speechModels.d.ts.map +1 -1
- package/dist/cjs/ai/modals-chat/electronHub/speechModels.js +1 -1
- package/dist/cjs/ai/modals-chat/electronHub/speechModels.js.map +1 -1
- package/dist/cjs/canvas/ApexPainter.d.ts.map +1 -1
- package/dist/cjs/canvas/ApexPainter.js +27 -28
- package/dist/cjs/canvas/ApexPainter.js.map +1 -1
- package/dist/cjs/canvas/Themes/Level-Up/levelup.d.ts +11 -0
- package/dist/cjs/canvas/Themes/Level-Up/levelup.d.ts.map +1 -0
- package/dist/cjs/canvas/Themes/Level-Up/levelup.js +163 -0
- package/dist/cjs/canvas/Themes/Level-Up/levelup.js.map +1 -0
- package/dist/cjs/canvas/utils/Background/bg.d.ts +17 -10
- package/dist/cjs/canvas/utils/Background/bg.d.ts.map +1 -1
- package/dist/cjs/canvas/utils/Background/bg.js +102 -27
- package/dist/cjs/canvas/utils/Background/bg.js.map +1 -1
- package/dist/cjs/canvas/utils/Custom/customLines.d.ts.map +1 -1
- package/dist/cjs/canvas/utils/Custom/customLines.js +43 -19
- package/dist/cjs/canvas/utils/Custom/customLines.js.map +1 -1
- package/dist/cjs/canvas/utils/General/general functions.d.ts +6 -1
- package/dist/cjs/canvas/utils/General/general functions.d.ts.map +1 -1
- package/dist/cjs/canvas/utils/General/general functions.js +19 -20
- package/dist/cjs/canvas/utils/General/general functions.js.map +1 -1
- package/dist/cjs/canvas/utils/Image/imageProperties.d.ts +3 -9
- package/dist/cjs/canvas/utils/Image/imageProperties.d.ts.map +1 -1
- package/dist/cjs/canvas/utils/Image/imageProperties.js +220 -214
- package/dist/cjs/canvas/utils/Image/imageProperties.js.map +1 -1
- package/dist/cjs/canvas/utils/Texts/textProperties.d.ts +12 -14
- package/dist/cjs/canvas/utils/Texts/textProperties.d.ts.map +1 -1
- package/dist/cjs/canvas/utils/Texts/textProperties.js +100 -91
- package/dist/cjs/canvas/utils/Texts/textProperties.js.map +1 -1
- package/dist/cjs/canvas/utils/types.d.ts +89 -109
- package/dist/cjs/canvas/utils/types.d.ts.map +1 -1
- package/dist/cjs/canvas/utils/types.js.map +1 -1
- package/dist/cjs/canvas/utils/utils.d.ts +2 -4
- package/dist/cjs/canvas/utils/utils.d.ts.map +1 -1
- package/dist/cjs/canvas/utils/utils.js +2 -5
- package/dist/cjs/canvas/utils/utils.js.map +1 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +31 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/ai/ApexModules.d.ts.map +1 -1
- package/dist/esm/ai/ApexModules.js +56 -7
- package/dist/esm/ai/ApexModules.js.map +1 -1
- package/dist/esm/ai/functions/readFiles.js +1 -1
- package/dist/esm/ai/functions/readFiles.js.map +1 -1
- package/dist/esm/ai/modals-chat/electronHub/chatmodels.d.ts.map +1 -1
- package/dist/esm/ai/modals-chat/electronHub/chatmodels.js +2 -1
- package/dist/esm/ai/modals-chat/electronHub/chatmodels.js.map +1 -1
- package/dist/esm/ai/modals-chat/electronHub/speechModels.d.ts.map +1 -1
- package/dist/esm/ai/modals-chat/electronHub/speechModels.js +1 -1
- package/dist/esm/ai/modals-chat/electronHub/speechModels.js.map +1 -1
- package/dist/esm/canvas/ApexPainter.d.ts.map +1 -1
- package/dist/esm/canvas/ApexPainter.js +27 -28
- package/dist/esm/canvas/ApexPainter.js.map +1 -1
- package/dist/esm/canvas/Themes/Level-Up/levelup.d.ts +11 -0
- package/dist/esm/canvas/Themes/Level-Up/levelup.d.ts.map +1 -0
- package/dist/esm/canvas/Themes/Level-Up/levelup.js +163 -0
- package/dist/esm/canvas/Themes/Level-Up/levelup.js.map +1 -0
- package/dist/esm/canvas/utils/Background/bg.d.ts +17 -10
- package/dist/esm/canvas/utils/Background/bg.d.ts.map +1 -1
- package/dist/esm/canvas/utils/Background/bg.js +102 -27
- package/dist/esm/canvas/utils/Background/bg.js.map +1 -1
- package/dist/esm/canvas/utils/Custom/customLines.d.ts.map +1 -1
- package/dist/esm/canvas/utils/Custom/customLines.js +43 -19
- package/dist/esm/canvas/utils/Custom/customLines.js.map +1 -1
- package/dist/esm/canvas/utils/General/general functions.d.ts +6 -1
- package/dist/esm/canvas/utils/General/general functions.d.ts.map +1 -1
- package/dist/esm/canvas/utils/General/general functions.js +19 -20
- package/dist/esm/canvas/utils/General/general functions.js.map +1 -1
- package/dist/esm/canvas/utils/Image/imageProperties.d.ts +3 -9
- package/dist/esm/canvas/utils/Image/imageProperties.d.ts.map +1 -1
- package/dist/esm/canvas/utils/Image/imageProperties.js +220 -214
- package/dist/esm/canvas/utils/Image/imageProperties.js.map +1 -1
- package/dist/esm/canvas/utils/Texts/textProperties.d.ts +12 -14
- package/dist/esm/canvas/utils/Texts/textProperties.d.ts.map +1 -1
- package/dist/esm/canvas/utils/Texts/textProperties.js +100 -91
- package/dist/esm/canvas/utils/Texts/textProperties.js.map +1 -1
- package/dist/esm/canvas/utils/types.d.ts +89 -109
- package/dist/esm/canvas/utils/types.d.ts.map +1 -1
- package/dist/esm/canvas/utils/types.js.map +1 -1
- package/dist/esm/canvas/utils/utils.d.ts +2 -4
- package/dist/esm/canvas/utils/utils.d.ts.map +1 -1
- package/dist/esm/canvas/utils/utils.js +2 -5
- package/dist/esm/canvas/utils/utils.js.map +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +31 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/lib/ai/ApexModules.ts +83 -11
- package/lib/ai/functions/readFiles.ts +1 -1
- package/lib/ai/modals-chat/electronHub/chatmodels.ts +4 -2
- package/lib/ai/modals-chat/electronHub/speechModels.ts +2 -1
- package/lib/canvas/ApexPainter.ts +52 -61
- package/lib/canvas/Themes/Level-Up/levelup.ts +183 -0
- package/lib/canvas/utils/Background/bg.ts +179 -65
- package/lib/canvas/utils/Custom/customLines.ts +53 -20
- package/lib/canvas/utils/General/general functions.ts +21 -29
- package/lib/canvas/utils/Image/imageProperties.ts +399 -318
- package/lib/canvas/utils/Texts/textProperties.ts +213 -162
- package/lib/canvas/utils/types.ts +74 -107
- package/lib/canvas/utils/utils.ts +2 -5
- package/lib/index.ts +38 -10
- package/package.json +3 -2
- package/dist/cjs/canvas/utils/Background/circular.d.ts +0 -3
- package/dist/cjs/canvas/utils/Background/circular.d.ts.map +0 -1
- package/dist/cjs/canvas/utils/Background/circular.js +0 -13
- package/dist/cjs/canvas/utils/Background/circular.js.map +0 -1
- package/dist/cjs/canvas/utils/Background/radius.d.ts +0 -18
- package/dist/cjs/canvas/utils/Background/radius.d.ts.map +0 -1
- package/dist/cjs/canvas/utils/Background/radius.js +0 -104
- package/dist/cjs/canvas/utils/Background/radius.js.map +0 -1
- package/dist/esm/canvas/utils/Background/circular.d.ts +0 -3
- package/dist/esm/canvas/utils/Background/circular.d.ts.map +0 -1
- package/dist/esm/canvas/utils/Background/circular.js +0 -13
- package/dist/esm/canvas/utils/Background/circular.js.map +0 -1
- package/dist/esm/canvas/utils/Background/radius.d.ts +0 -18
- package/dist/esm/canvas/utils/Background/radius.d.ts.map +0 -1
- package/dist/esm/canvas/utils/Background/radius.js +0 -104
- package/dist/esm/canvas/utils/Background/radius.js.map +0 -1
- package/lib/canvas/utils/Background/circular.ts +0 -17
- package/lib/canvas/utils/Background/radius.ts +0 -102
package/lib/ai/ApexModules.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { electronImagine } from './modals-chat/electronHub/imageModels';
|
|
|
8
8
|
import { electronChat } from './modals-chat/electronHub/chatmodels';
|
|
9
9
|
import { electronSpeech } from './modals-chat/electronHub/speechModels';
|
|
10
10
|
import { electronVideo } from './modals-chat/electronHub/videoModels';
|
|
11
|
+
import { GoogleGenerativeAI } from"@google/generative-ai";
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
const dbConfig = {
|
|
@@ -591,22 +592,26 @@ async function ApexImagine(model: string, prompt: string, options?: ApexImagineO
|
|
|
591
592
|
return response;
|
|
592
593
|
}
|
|
593
594
|
|
|
594
|
-
async function ApexChat(
|
|
595
|
+
async function ApexChat(
|
|
596
|
+
model: string,
|
|
597
|
+
prompt: string,
|
|
598
|
+
{ userId, memory, limit, instruction, Api_key }: { userId?: string; memory?: boolean; limit?: number; instruction?: string; Api_key?: string }
|
|
599
|
+
): Promise<string> {
|
|
595
600
|
try {
|
|
596
|
-
|
|
597
601
|
let enhancedPrompt: string = prompt;
|
|
598
602
|
let historyChat: string = `- This is Previous chat history between you (System) and the user (User). Don't use the history or reply back anything related to it unless being mentioned in user's new prompt\n`;
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
}
|
|
603
|
+
|
|
604
|
+
let commandString = instruction ? `- Given Constant instruction for the System (AI) to abide and to always follow:\n${instruction}\n\n` : '';
|
|
605
|
+
|
|
603
606
|
if (memory && userId) {
|
|
604
|
-
|
|
605
607
|
const userHistoryResult = (await db.find(`${userId}`, { userId })).results?.history || [];
|
|
606
|
-
const historyItems = Array.isArray(userHistoryResult) ? userHistoryResult
|
|
608
|
+
const historyItems = Array.isArray(userHistoryResult) ? userHistoryResult : [];
|
|
609
|
+
|
|
610
|
+
const relevantMessages = await getRelevantHistoryAI(prompt, historyItems, limit ?? 12);
|
|
611
|
+
|
|
607
612
|
|
|
608
613
|
let formattedHistory = '';
|
|
609
|
-
|
|
614
|
+
relevantMessages.forEach((item) => {
|
|
610
615
|
formattedHistory += `User: ${item.user}\nSystem: ${item.model}\n\n`;
|
|
611
616
|
});
|
|
612
617
|
|
|
@@ -628,7 +633,7 @@ async function ApexChat(model: string, prompt: string, { userId, memory, limit,
|
|
|
628
633
|
|
|
629
634
|
response = responses.join('');
|
|
630
635
|
} else {
|
|
631
|
-
response = await processChunk(model, enhancedPrompt, {});
|
|
636
|
+
response = await processChunk(model, enhancedPrompt, { ApiKey: Api_key, personality: instruction });
|
|
632
637
|
}
|
|
633
638
|
|
|
634
639
|
if (memory && userId && model !== 'gemini-pro' && model !== 'gemini-flash') {
|
|
@@ -637,11 +642,78 @@ async function ApexChat(model: string, prompt: string, { userId, memory, limit,
|
|
|
637
642
|
|
|
638
643
|
return response;
|
|
639
644
|
} catch (error: any) {
|
|
640
|
-
console.error(error.message);
|
|
645
|
+
console.error(error.message);
|
|
641
646
|
return '';
|
|
642
647
|
}
|
|
643
648
|
}
|
|
644
649
|
|
|
650
|
+
const genAI = new GoogleGenerativeAI('AIzaSyAdlBVg12yjqqGfBqxT5DLGMhP2jysG7Hk');
|
|
651
|
+
|
|
652
|
+
const model = genAI.getGenerativeModel({ model: "text-embedding-004" });
|
|
653
|
+
|
|
654
|
+
async function getRelevantHistoryAI(prompt: string, history: any[], maxResults: number): Promise<any[]> {
|
|
655
|
+
|
|
656
|
+
const trimmedPrompt = prompt.length > 20000 ? prompt.slice(0, 20000) : prompt;
|
|
657
|
+
const promptEmbedding = await generateEmbedding(trimmedPrompt);
|
|
658
|
+
|
|
659
|
+
const threshold = 0.7;
|
|
660
|
+
|
|
661
|
+
const scores = await Promise.all(
|
|
662
|
+
history.map(async (item) => {
|
|
663
|
+
const trimmedUser = item.user.length > 20000 ? item.user.slice(0, 20000) : item.user;
|
|
664
|
+
|
|
665
|
+
const messageEmbedding = await generateEmbedding(trimmedUser);
|
|
666
|
+
const score = cosineSimilarity(promptEmbedding, messageEmbedding);
|
|
667
|
+
return { item, score };
|
|
668
|
+
})
|
|
669
|
+
);
|
|
670
|
+
|
|
671
|
+
const filteredResults = scores.filter(entry => entry.score >= threshold);
|
|
672
|
+
filteredResults.sort((a, b) => b.score - a.score);
|
|
673
|
+
|
|
674
|
+
return filteredResults.slice(0, maxResults).map(entry => entry.item);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
async function generateEmbedding(text: string): Promise<number[]> {
|
|
678
|
+
let maxRetries = 5;
|
|
679
|
+
let delay = 5000;
|
|
680
|
+
let attempt = 0;
|
|
681
|
+
|
|
682
|
+
while (attempt < maxRetries) {
|
|
683
|
+
try {
|
|
684
|
+
|
|
685
|
+
const response = await model.embedContent(text);
|
|
686
|
+
|
|
687
|
+
|
|
688
|
+
return response.embedding.values;
|
|
689
|
+
} catch (error: any) {
|
|
690
|
+
if (error.response) {
|
|
691
|
+
console.warn(`❌ API Error - Status: ${error.response.status}, Message: ${error.response.statusText}`);
|
|
692
|
+
} else {
|
|
693
|
+
console.error("❌ Network or unknown error:", error.message);
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
if (error.response && error.response.status === 429) {
|
|
697
|
+
console.warn(`⚠️ Rate limited (429). Retrying in ${delay / 1000} seconds...`);
|
|
698
|
+
await new Promise(res => setTimeout(res, delay));
|
|
699
|
+
} else {
|
|
700
|
+
throw error;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
attempt++;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
throw new Error("Max retries reached. Failed to get embedding.");
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
function cosineSimilarity(a: number[], b: number[]): number {
|
|
711
|
+
const dotProduct = a.reduce((sum, val, i) => sum + val * b[i], 0);
|
|
712
|
+
const magnitudeA = Math.sqrt(a.reduce((sum, val) => sum + val * val, 0));
|
|
713
|
+
const magnitudeB = Math.sqrt(b.reduce((sum, val) => sum + val * val, 0));
|
|
714
|
+
return dotProduct / (magnitudeA * magnitudeB);
|
|
715
|
+
}
|
|
716
|
+
|
|
645
717
|
async function resetHistory({ id, last }: { id: string; last: number | string }): Promise<boolean> {
|
|
646
718
|
if (!id) return false;
|
|
647
719
|
|
|
@@ -32,14 +32,16 @@ export async function electronChat({
|
|
|
32
32
|
if (!modelExists) {
|
|
33
33
|
throw new Error('Invalid model name please check out Electron hub models for more info.')
|
|
34
34
|
}
|
|
35
|
-
|
|
35
|
+
console.log(prompt);
|
|
36
|
+
|
|
36
37
|
const completion = await openai.chat.completions.create({
|
|
37
|
-
model:
|
|
38
|
+
model: modelName,
|
|
38
39
|
messages: [
|
|
39
40
|
{"role": "system", "content": `${instruction}`},
|
|
40
41
|
{"role": "user", "content": `${prompt}`}
|
|
41
42
|
]
|
|
42
43
|
});
|
|
44
|
+
|
|
43
45
|
|
|
44
46
|
return completion.choices[0]?.message?.content;
|
|
45
47
|
} catch (e: any) {
|
|
@@ -17,9 +17,10 @@ export async function electronSpeech({
|
|
|
17
17
|
|
|
18
18
|
const validPersonalities = [
|
|
19
19
|
'will', 'maltida', 'liam', 'jessica', 'george', 'lily', 'sana',
|
|
20
|
-
'
|
|
20
|
+
'wahab', 'martin', 'darine', 'guillaume', 'leonie', 'kurt', 'leo',
|
|
21
21
|
'shakuntala', 'maciej', 'aneta', 'gabriela', 'juan'
|
|
22
22
|
];
|
|
23
|
+
|
|
23
24
|
if (personality && !validPersonalities.includes(personality)) {
|
|
24
25
|
throw new Error(`Invalid personality. Please choose from the following: ${validPersonalities.join(', ')}`);
|
|
25
26
|
}
|
|
@@ -6,13 +6,10 @@ import axios from 'axios';
|
|
|
6
6
|
import fs from "fs";
|
|
7
7
|
import path from "path";
|
|
8
8
|
import { OutputFormat, CanvasConfig, TextObject, ImageProperties, GIFOptions, GIFResults, CustomOptions, cropOptions,
|
|
9
|
-
drawBackgroundGradient, drawBackgroundColor, customBackground,
|
|
9
|
+
drawBackgroundGradient, drawBackgroundColor, customBackground, customLines, applyRotation, applyStroke,
|
|
10
10
|
applyShadow, imageRadius, drawShape, drawText, converter, resizingImg, applyColorFilters, imgEffects,verticalBarChart, pieChart,
|
|
11
11
|
lineChart, cropInner, cropOuter, bgRemoval, detectColors, removeColor, dataURL, base64, arrayBuffer, blob, url, GradientConfig, Frame,
|
|
12
|
-
PatternOptions, ExtractFramesOptions,
|
|
13
|
-
applyZoom,
|
|
14
|
-
ResizeOptions,
|
|
15
|
-
applyPerspective
|
|
12
|
+
PatternOptions, ExtractFramesOptions, backgroundRadius, applyZoom, ResizeOptions, applyPerspective
|
|
16
13
|
} from "./utils/utils";
|
|
17
14
|
|
|
18
15
|
interface CanvasResults {
|
|
@@ -49,7 +46,8 @@ export class ApexPainter {
|
|
|
49
46
|
shadow,
|
|
50
47
|
borderPosition = 'all',
|
|
51
48
|
opacity = 1,
|
|
52
|
-
zoom
|
|
49
|
+
zoom,
|
|
50
|
+
blur
|
|
53
51
|
} = canvas;
|
|
54
52
|
|
|
55
53
|
const canvasInstance = createCanvas(width, height);
|
|
@@ -64,23 +62,20 @@ export class ApexPainter {
|
|
|
64
62
|
applyShadow(ctx, shadow, x, y, width, height);
|
|
65
63
|
|
|
66
64
|
ctx.save();
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
} else if (typeof borderRadius === 'number') {
|
|
70
|
-
radiusBorder(ctx, x, y, width, height, borderRadius, borderPosition);
|
|
65
|
+
if (borderRadius) {
|
|
66
|
+
backgroundRadius(ctx, x, y, width, height, borderRadius, borderPosition);
|
|
71
67
|
}
|
|
72
68
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
// applyZoom(ctx, zoom);
|
|
69
|
+
ctx.translate(x, y);
|
|
76
70
|
|
|
77
71
|
if (customBg) {
|
|
78
|
-
await customBackground(ctx, canvas);
|
|
72
|
+
await customBackground(ctx, canvas, zoom, blur);
|
|
79
73
|
} else if (gradientBg) {
|
|
80
|
-
await drawBackgroundGradient(ctx, canvas);
|
|
74
|
+
await drawBackgroundGradient(ctx, canvas, zoom, blur);
|
|
81
75
|
} else {
|
|
82
|
-
await drawBackgroundColor(ctx, canvas);
|
|
76
|
+
await drawBackgroundColor(ctx, canvas, zoom, blur);
|
|
83
77
|
}
|
|
78
|
+
|
|
84
79
|
ctx.restore();
|
|
85
80
|
|
|
86
81
|
applyStroke(ctx, stroke, x, y, width, height);
|
|
@@ -165,12 +160,12 @@ export class ApexPainter {
|
|
|
165
160
|
|
|
166
161
|
GlobalFonts.registerFromPath(
|
|
167
162
|
path.join(process.cwd(), mergedTextOptions.fontPath),
|
|
168
|
-
mergedTextOptions.fontName,
|
|
163
|
+
(mergedTextOptions.fontName || 'customFont'),
|
|
169
164
|
);
|
|
170
165
|
}
|
|
171
166
|
|
|
172
167
|
const size = { width: existingImage.width, height: existingImage.height };
|
|
173
|
-
drawText(ctx, mergedTextOptions
|
|
168
|
+
drawText(ctx, mergedTextOptions);
|
|
174
169
|
}
|
|
175
170
|
|
|
176
171
|
return canvas.toBuffer("image/png");
|
|
@@ -469,87 +464,83 @@ async createGIF(gifFrames: { background: string; duration: number }[], options:
|
|
|
469
464
|
}
|
|
470
465
|
}
|
|
471
466
|
|
|
472
|
-
private async drawImage(
|
|
473
|
-
ctx: SKRSContext2D,
|
|
474
|
-
image: ImageProperties
|
|
475
|
-
): Promise<void> {
|
|
467
|
+
private async drawImage(ctx: SKRSContext2D, image: ImageProperties): Promise<void> {
|
|
476
468
|
const {
|
|
477
469
|
source,
|
|
478
|
-
x,
|
|
479
|
-
y,
|
|
480
|
-
width,
|
|
481
|
-
height,
|
|
470
|
+
x, y, width, height,
|
|
482
471
|
rotation = 0,
|
|
483
472
|
borderRadius = 0,
|
|
484
|
-
stroke,
|
|
485
|
-
|
|
486
|
-
isFilled,
|
|
487
|
-
color,
|
|
488
|
-
gradient,
|
|
473
|
+
stroke, shadow,
|
|
474
|
+
isFilled, color, gradient,
|
|
489
475
|
borderPosition = 'all',
|
|
490
476
|
opacity,
|
|
491
|
-
perspective
|
|
477
|
+
perspective,
|
|
478
|
+
blur = 0,
|
|
479
|
+
zoom,
|
|
480
|
+
filling
|
|
492
481
|
} = image;
|
|
493
482
|
|
|
494
|
-
if (
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
typeof y !== 'number' ||
|
|
498
|
-
typeof width !== 'number' ||
|
|
499
|
-
typeof height !== 'number'
|
|
500
|
-
) {
|
|
483
|
+
if (perspective) throw new Error("`perspective` Feature is under construction. Please refrain from using it.");
|
|
484
|
+
|
|
485
|
+
if (!source || typeof x !== 'number' || typeof y !== 'number' || typeof width !== 'number' || typeof height !== 'number') {
|
|
501
486
|
throw new Error('Invalid image properties: source, x, y, width, and height are required.');
|
|
502
487
|
}
|
|
503
|
-
|
|
504
|
-
const shapeNames = ['circle', 'square', 'triangle', 'pentagon', 'hexagon', 'heptagon', 'octagon', 'star', 'kite'];
|
|
488
|
+
|
|
489
|
+
const shapeNames = ['circle', 'square', 'triangle', 'pentagon', 'hexagon', 'heptagon', 'octagon', 'star', 'kite', 'arrow', 'star', 'oval', 'heart', 'diamond', 'trapezoid', 'cloud'];
|
|
505
490
|
const isShape = shapeNames.includes(source.toLowerCase());
|
|
506
|
-
|
|
491
|
+
|
|
507
492
|
if (opacity !== undefined) {
|
|
508
493
|
ctx.globalAlpha = opacity;
|
|
509
494
|
}
|
|
510
|
-
|
|
495
|
+
|
|
511
496
|
if (isShape) {
|
|
512
|
-
drawShape(ctx, { source, x, y, width, height, rotation, borderRadius, stroke, shadow, isFilled, color, gradient, borderPosition });
|
|
497
|
+
drawShape(ctx, { source, x, y, width, height, rotation, borderRadius, stroke, shadow, isFilled, color, gradient, borderPosition, filling });
|
|
513
498
|
ctx.globalAlpha = 1.0;
|
|
514
499
|
return;
|
|
515
500
|
}
|
|
516
|
-
|
|
501
|
+
|
|
517
502
|
let loadedImage: Image | undefined;
|
|
518
503
|
try {
|
|
519
504
|
if (source.startsWith('http')) {
|
|
520
505
|
loadedImage = await loadImage(source);
|
|
521
506
|
} else {
|
|
522
|
-
const imagePath = path.
|
|
507
|
+
const imagePath = path.resolve(process.cwd(), source);
|
|
523
508
|
loadedImage = await loadImage(imagePath);
|
|
524
509
|
}
|
|
525
510
|
} catch (e: any) {
|
|
526
511
|
throw new Error(`Error loading image: ${e.message}`);
|
|
527
512
|
}
|
|
528
|
-
|
|
513
|
+
|
|
529
514
|
if (!loadedImage) {
|
|
530
515
|
throw new Error('Invalid image source or failed to load image');
|
|
531
516
|
}
|
|
532
|
-
|
|
517
|
+
|
|
533
518
|
ctx.save();
|
|
519
|
+
|
|
520
|
+
const scale = zoom?.scale ?? 1;
|
|
521
|
+
const focusX = zoom?.x ?? 0.5;
|
|
522
|
+
const focusY = zoom?.y ?? 0.5;
|
|
523
|
+
|
|
524
|
+
if (scale !== 1) {
|
|
525
|
+
ctx.translate(focusX, focusY);
|
|
526
|
+
ctx.scale(scale, scale);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
if (blur > 0) {
|
|
530
|
+
ctx.filter = `blur(${blur}px)`;
|
|
531
|
+
}
|
|
532
|
+
|
|
534
533
|
applyRotation(ctx, rotation, x, y, width, height);
|
|
535
534
|
applyShadow(ctx, shadow, x, y, width, height);
|
|
536
535
|
|
|
537
536
|
if (perspective) {
|
|
538
|
-
throw new Error('Under construction')
|
|
539
|
-
// const offscreen = createCanvas(width, height);
|
|
540
|
-
// const offCtx = offscreen.getContext('2d') as SKRSContext2D;
|
|
541
|
-
// offCtx.clearRect(0, 0, width, height);
|
|
542
|
-
|
|
543
|
-
// await applyPerspective(offCtx, loadedImage, 0, 0, width, height, perspective, 10, 10);
|
|
544
|
-
|
|
545
|
-
// imageRadius(ctx, offscreen, x, y, width, height, borderRadius, borderPosition);
|
|
537
|
+
throw new Error('Under construction');
|
|
546
538
|
}
|
|
547
|
-
|
|
539
|
+
|
|
548
540
|
imageRadius(ctx, loadedImage, x, y, width, height, borderRadius, borderPosition);
|
|
549
|
-
|
|
550
|
-
|
|
541
|
+
applyStroke(ctx, stroke, x, y, width, height, undefined, true);
|
|
542
|
+
|
|
551
543
|
ctx.restore();
|
|
552
|
-
|
|
553
544
|
ctx.globalAlpha = 1.0;
|
|
554
545
|
}
|
|
555
546
|
|
|
@@ -997,7 +988,7 @@ async animate(
|
|
|
997
988
|
}
|
|
998
989
|
|
|
999
990
|
if (frame.onDrawCustom) {
|
|
1000
|
-
frame.onDrawCustom(ctx as unknown as
|
|
991
|
+
frame.onDrawCustom(ctx as unknown as SKRSContext2D, canvas);
|
|
1001
992
|
}
|
|
1002
993
|
|
|
1003
994
|
if (frame.transformations) {
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { ApexPainter, CanvasConfig, ImageProperties, TextObject } from "../../../index";
|
|
2
|
+
|
|
3
|
+
const Image = new ApexPainter();
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Generates a level-up card.
|
|
7
|
+
* @param {string} userPfp - User profile picture URL.
|
|
8
|
+
* @param {string} username - Username.
|
|
9
|
+
* @param {string} [levelUpmsg="Well done user. You had leveled up 🔥🔥"] - Custom level-up message.
|
|
10
|
+
* @param {string} prevLevel - Previous level before leveling up.
|
|
11
|
+
* @param {string} nextLevel - Next level after leveling up.
|
|
12
|
+
* @returns {Promise<Buffer>} - The generated level-up image.
|
|
13
|
+
*/
|
|
14
|
+
export async function level_up_1(
|
|
15
|
+
userPfp: string,
|
|
16
|
+
username: string,
|
|
17
|
+
levelUpmsg: string = "Well done user. You had leveled up 🔥🔥",
|
|
18
|
+
prevLevel: string,
|
|
19
|
+
nextLevel: string
|
|
20
|
+
): Promise<Buffer> {
|
|
21
|
+
|
|
22
|
+
/** Helper function to detect Arabic text */
|
|
23
|
+
const isArabic = (text: string) => /[\u0600-\u06FF]/.test(text);
|
|
24
|
+
|
|
25
|
+
/** Helper function to shuffle an array */
|
|
26
|
+
function shuffleArray<T>(array: T[]): T[] {
|
|
27
|
+
return array.sort(() => Math.random() - 0.5);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Extracts and returns random colors from the dominant colors */
|
|
31
|
+
function getRandomColors(colors: { color: string }[]): string[] {
|
|
32
|
+
if (colors.length === 0) return ["rgb(0, 255, 247)", "rgb(157, 0, 255)", "rgb(255, 94, 0)"];
|
|
33
|
+
return shuffleArray(colors).slice(0, 5).map(c => `rgb(${c.color})`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 1. **Canvas Configuration**
|
|
37
|
+
const canvasConfig: CanvasConfig = {
|
|
38
|
+
customBg: './bg.png',
|
|
39
|
+
width: 1599, height: 876,
|
|
40
|
+
zoom: {}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const bg = await Image.createCanvas(canvasConfig);
|
|
44
|
+
|
|
45
|
+
// 2. **Extract Dominant Colors for Gradients**
|
|
46
|
+
const dominantColors = await Image.colorAnalysis(userPfp);
|
|
47
|
+
const gradientColors = getRandomColors(dominantColors).map((color, index) => ({
|
|
48
|
+
stop: index / 4, color
|
|
49
|
+
}));
|
|
50
|
+
const shadowGradient = [...gradientColors];
|
|
51
|
+
|
|
52
|
+
// 3. **User Profile Picture Configuration**
|
|
53
|
+
const imgs: ImageProperties[] = [{
|
|
54
|
+
source: userPfp,
|
|
55
|
+
width: 240, height: 240,
|
|
56
|
+
x: 235, y: 235,
|
|
57
|
+
blur: 0.4,
|
|
58
|
+
borderRadius: 'circular',
|
|
59
|
+
stroke: {
|
|
60
|
+
width: 8, position: 5, blur: 0.5,
|
|
61
|
+
borderRadius: 'circular',
|
|
62
|
+
gradient: {
|
|
63
|
+
type: 'linear',
|
|
64
|
+
startX: 200, startY: 200,
|
|
65
|
+
endX: 290, endY: 290,
|
|
66
|
+
colors: gradientColors
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
shadow: {
|
|
70
|
+
gradient: {
|
|
71
|
+
type: 'linear',
|
|
72
|
+
startX: 220, startY: 220,
|
|
73
|
+
endX: 270, endY: 270,
|
|
74
|
+
colors: shadowGradient
|
|
75
|
+
},
|
|
76
|
+
opacity: 0.7,
|
|
77
|
+
blur: 25,
|
|
78
|
+
borderRadius: 90,
|
|
79
|
+
offsetX: 0, offsetY: 0,
|
|
80
|
+
}
|
|
81
|
+
}];
|
|
82
|
+
|
|
83
|
+
const img = await Image.createImage(imgs, bg);
|
|
84
|
+
|
|
85
|
+
// 4. **Username Text Handling**
|
|
86
|
+
const maxLength = isArabic(username) ? 12 : 10;
|
|
87
|
+
let displayName = username.length > maxLength
|
|
88
|
+
? isArabic(username)
|
|
89
|
+
? '...' + username.slice(-maxLength)
|
|
90
|
+
: username.slice(0, maxLength - 3) + '...'
|
|
91
|
+
: username;
|
|
92
|
+
|
|
93
|
+
let xPos = isArabic(username) ? Math.max(480 - (displayName.length - 4) * 3, 190) - 30 : 300 - Math.min((displayName.length - 3) * 10, 110);
|
|
94
|
+
|
|
95
|
+
// 5. **Message Text Alignment**
|
|
96
|
+
const container = { width: 590, height: 235, x: 810, y: 520 };
|
|
97
|
+
const fontName = isArabic(levelUpmsg) ? 'Segoe UI' : 'Segoe UI Emoji';
|
|
98
|
+
const textX = isArabic(levelUpmsg) ? container.x + 290 : container.x + 285;
|
|
99
|
+
|
|
100
|
+
// 6. **Dynamic Level Positioning Function**
|
|
101
|
+
function getLevelPosition(level: string, isNext: boolean) {
|
|
102
|
+
let x = isNext ? 1320 : 885;
|
|
103
|
+
let y = 455;
|
|
104
|
+
let fontSize = 72;
|
|
105
|
+
|
|
106
|
+
if (level.length === 3) {
|
|
107
|
+
x = isNext ? 1323 : 888;
|
|
108
|
+
y = 455;
|
|
109
|
+
fontSize = 63;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return { x, y, fontSize };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const prevLevelConfig = getLevelPosition(prevLevel, false);
|
|
116
|
+
const nextLevelConfig = getLevelPosition(nextLevel, true);
|
|
117
|
+
|
|
118
|
+
// 7. **Text Elements Configuration**
|
|
119
|
+
const txts: TextObject[] = [
|
|
120
|
+
{
|
|
121
|
+
text: displayName,
|
|
122
|
+
x: xPos, y: 600,
|
|
123
|
+
fontSize: 54,
|
|
124
|
+
fontName: 'Segoe UI',
|
|
125
|
+
textAlign: isArabic(username) ? 'right' : 'left',
|
|
126
|
+
gradient: {
|
|
127
|
+
type: 'linear',
|
|
128
|
+
startX: 0, startY: 0,
|
|
129
|
+
endX: 0, endY: 50,
|
|
130
|
+
colors: [
|
|
131
|
+
{ stop: 0, color: '#ffffff' },
|
|
132
|
+
{ stop: 1, color: '#66e6ff' }
|
|
133
|
+
]
|
|
134
|
+
},
|
|
135
|
+
stroke: { width: 3, color: '#9d00ff' },
|
|
136
|
+
shadow: { color: '#66e6ff', opacity: 0.4, blur: 8, offsetX: 0, offsetY: 0 }
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
text: levelUpmsg,
|
|
140
|
+
x: textX, y: container.y + 60,
|
|
141
|
+
fontSize: 34,
|
|
142
|
+
fontName: fontName,
|
|
143
|
+
textAlign: 'center',
|
|
144
|
+
maxWidth: container.width - 30,
|
|
145
|
+
lineHeight: 42,
|
|
146
|
+
maxHeight: container.height - 30,
|
|
147
|
+
gradient: {
|
|
148
|
+
type: 'linear',
|
|
149
|
+
startX: 0, startY: 0,
|
|
150
|
+
endX: 0, endY: 50,
|
|
151
|
+
colors: [
|
|
152
|
+
{ stop: 0, color: '#f9ff00' },
|
|
153
|
+
{ stop: 1, color: '#ff6a00' }
|
|
154
|
+
]
|
|
155
|
+
},
|
|
156
|
+
stroke: { width: 2, color: '#ff9d00' },
|
|
157
|
+
shadow: { color: '#ffcc00', opacity: 0.5, blur: 10, offsetX: 0, offsetY: 0 }
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
text: prevLevel,
|
|
161
|
+
x: prevLevelConfig.x, y: prevLevelConfig.y,
|
|
162
|
+
fontSize: prevLevelConfig.fontSize,
|
|
163
|
+
fontName: "Bahnschrift",
|
|
164
|
+
textAlign: "center",
|
|
165
|
+
gradient: { type: "linear", startX: 0, startY: 0, endX: 0, endY: 80, colors: [{ stop: 0, color: "#00FFFF" }, { stop: 1, color: "#007BFF" }] },
|
|
166
|
+
stroke: { width: 6, color: "#0033FF" },
|
|
167
|
+
shadow: { color: "#00BFFF", opacity: 0.6, blur: 15, offsetX: 0, offsetY: 0 }
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
text: nextLevel,
|
|
171
|
+
x: nextLevelConfig.x, y: nextLevelConfig.y,
|
|
172
|
+
fontSize: nextLevelConfig.fontSize,
|
|
173
|
+
fontName: "Bahnschrift",
|
|
174
|
+
textAlign: "center",
|
|
175
|
+
gradient: { type: "linear", startX: 0, startY: 0, endX: 0, endY: 80, colors: [{ stop: 0, color: "#00FFFF" }, { stop: 1, color: "#007BFF" }] },
|
|
176
|
+
stroke: { width: 6, color: "#0033FF" },
|
|
177
|
+
shadow: { color: "#00BFFF", opacity: 0.6, blur: 15, offsetX: 0, offsetY: 0 }
|
|
178
|
+
}
|
|
179
|
+
];
|
|
180
|
+
|
|
181
|
+
// 8. **Render Final Image**
|
|
182
|
+
return await Image.createText(txts, img);
|
|
183
|
+
}
|