@kaikybrofc/omnizap-system 2.1.8
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/.env.example +534 -0
- package/LICENSE +21 -0
- package/README.md +431 -0
- package/RELEASE-v2.1.2.md +83 -0
- package/app/config/adminIdentity.js +87 -0
- package/app/config/baileysConfig.js +693 -0
- package/app/config/groupUtils.js +388 -0
- package/app/connection/socketController.js +992 -0
- package/app/controllers/messageController.js +354 -0
- package/app/modules/adminModule/groupCommandHandlers.js +1294 -0
- package/app/modules/adminModule/groupEventHandlers.js +355 -0
- package/app/modules/aiModule/catCommand.js +1006 -0
- package/app/modules/broadcastModule/noticeCommand.js +416 -0
- package/app/modules/gameModule/diceCommand.js +67 -0
- package/app/modules/menuModule/common.js +311 -0
- package/app/modules/menuModule/menus.js +59 -0
- package/app/modules/playModule/playCommand.js +1615 -0
- package/app/modules/quoteModule/quoteCommand.js +851 -0
- package/app/modules/rpgPokemonModule/rpgBattleCanvasRenderer.js +786 -0
- package/app/modules/rpgPokemonModule/rpgBattleService.js +2082 -0
- package/app/modules/rpgPokemonModule/rpgBattleService.test.js +760 -0
- package/app/modules/rpgPokemonModule/rpgEvolutionUtils.js +22 -0
- package/app/modules/rpgPokemonModule/rpgPokemonCommand.js +172 -0
- package/app/modules/rpgPokemonModule/rpgPokemonDomain.js +192 -0
- package/app/modules/rpgPokemonModule/rpgPokemonDomain.test.js +93 -0
- package/app/modules/rpgPokemonModule/rpgPokemonEvolution.test.js +46 -0
- package/app/modules/rpgPokemonModule/rpgPokemonMessages.js +746 -0
- package/app/modules/rpgPokemonModule/rpgPokemonRepository.js +1859 -0
- package/app/modules/rpgPokemonModule/rpgPokemonService.js +6738 -0
- package/app/modules/rpgPokemonModule/rpgProfileCanvasRenderer.js +354 -0
- package/app/modules/statsModule/globalRankingCommand.js +65 -0
- package/app/modules/statsModule/noMessageCommand.js +288 -0
- package/app/modules/statsModule/rankingCommand.js +60 -0
- package/app/modules/statsModule/rankingCommon.js +889 -0
- package/app/modules/stickerModule/addStickerMetadata.js +239 -0
- package/app/modules/stickerModule/convertToWebp.js +390 -0
- package/app/modules/stickerModule/stickerCommand.js +454 -0
- package/app/modules/stickerModule/stickerConvertCommand.js +156 -0
- package/app/modules/stickerModule/stickerTextCommand.js +657 -0
- package/app/modules/stickerPackModule/autoPackCollectorRuntime.js +20 -0
- package/app/modules/stickerPackModule/autoPackCollectorService.js +284 -0
- package/app/modules/stickerPackModule/semanticReclassificationEngine.js +466 -0
- package/app/modules/stickerPackModule/semanticReclassificationEngine.test.js +88 -0
- package/app/modules/stickerPackModule/semanticThemeClusterService.js +571 -0
- package/app/modules/stickerPackModule/stickerAssetClassificationRepository.js +449 -0
- package/app/modules/stickerPackModule/stickerAssetRepository.js +400 -0
- package/app/modules/stickerPackModule/stickerAssetReprocessQueueRepository.js +180 -0
- package/app/modules/stickerPackModule/stickerAutoPackByTagsRuntime.js +4078 -0
- package/app/modules/stickerPackModule/stickerClassificationBackgroundRuntime.js +598 -0
- package/app/modules/stickerPackModule/stickerClassificationService.js +588 -0
- package/app/modules/stickerPackModule/stickerMarketplaceDriftService.js +102 -0
- package/app/modules/stickerPackModule/stickerPackCatalogHttp.js +7506 -0
- package/app/modules/stickerPackModule/stickerPackCommandHandlers.js +1095 -0
- package/app/modules/stickerPackModule/stickerPackEngagementRepository.js +108 -0
- package/app/modules/stickerPackModule/stickerPackErrors.js +30 -0
- package/app/modules/stickerPackModule/stickerPackInteractionEventRepository.js +110 -0
- package/app/modules/stickerPackModule/stickerPackItemRepository.js +440 -0
- package/app/modules/stickerPackModule/stickerPackMarketplaceService.js +337 -0
- package/app/modules/stickerPackModule/stickerPackMessageService.js +296 -0
- package/app/modules/stickerPackModule/stickerPackRepository.js +442 -0
- package/app/modules/stickerPackModule/stickerPackService.js +788 -0
- package/app/modules/stickerPackModule/stickerPackServiceRuntime.js +51 -0
- package/app/modules/stickerPackModule/stickerPackUtils.js +97 -0
- package/app/modules/stickerPackModule/stickerStorageService.js +507 -0
- package/app/modules/stickerPackModule/stickerWorkerPipelineRuntime.js +233 -0
- package/app/modules/stickerPackModule/stickerWorkerTaskQueueRepository.js +205 -0
- package/app/modules/systemMetricsModule/pingCommand.js +421 -0
- package/app/modules/tiktokModule/tiktokCommand.js +798 -0
- package/app/modules/userModule/userCommand.js +1217 -0
- package/app/modules/waifuPicsModule/waifuPicsCommand.js +177 -0
- package/app/observability/metrics.js +734 -0
- package/app/services/captchaService.js +492 -0
- package/app/services/dbWriteQueue.js +572 -0
- package/app/services/groupMetadataService.js +279 -0
- package/app/services/lidMapService.js +663 -0
- package/app/services/messagePersistenceService.js +56 -0
- package/app/services/newsBroadcastService.js +351 -0
- package/app/services/pokeApiService.js +398 -0
- package/app/services/queueUtils.js +57 -0
- package/app/services/socketState.js +7 -0
- package/app/store/aiPromptStore.js +38 -0
- package/app/store/groupConfigStore.js +58 -0
- package/app/store/premiumUserStore.js +36 -0
- package/app/utils/antiLink/antiLinkModule.js +804 -0
- package/app/utils/http/getImageBufferModule.js +18 -0
- package/app/utils/json/jsonSanitizer.js +113 -0
- package/app/utils/json/jsonSanitizer.test.js +40 -0
- package/app/utils/logger/loggerModule.js +262 -0
- package/app/utils/systemMetrics/systemMetricsModule.js +91 -0
- package/database/index.js +2052 -0
- package/database/init.js +516 -0
- package/database/migrations/20260203_0001_sticker_packs.sql +54 -0
- package/database/migrations/20260210_0003_rpg_pokemon.sql +58 -0
- package/database/migrations/20260210_0004_rpg_shiny_biome.sql +9 -0
- package/database/migrations/20260210_0005_rpg_missions.sql +14 -0
- package/database/migrations/20260210_0006_rpg_world_pokedex_traits.sql +27 -0
- package/database/migrations/20260210_0007_rpg_raid_pvp.sql +56 -0
- package/database/migrations/20260210_0008_rpg_social_system.sql +195 -0
- package/database/migrations/20260211_0009_rpg_social_xp.sql +36 -0
- package/database/migrations/20260222_0010_remove_message_xp.sql +2 -0
- package/database/migrations/20260226_0011_sticker_asset_classification.sql +17 -0
- package/database/migrations/20260226_0012_sticker_pack_engagement.sql +16 -0
- package/database/migrations/20260226_0013_sticker_marketplace_intelligence.sql +19 -0
- package/database/migrations/20260226_0014_sticker_pack_publish_flow.sql +30 -0
- package/database/migrations/20260226_0014_sticker_worker_queues.sql +42 -0
- package/database/migrations/20260226_0015_sticker_auto_pack_curation_integrity.sql +18 -0
- package/database/migrations/20260226_0016_sticker_web_google_auth_persistence.sql +34 -0
- package/database/migrations/20260226_0017_sticker_web_admin_ban.sql +22 -0
- package/database/migrations/20260226_0018_sticker_web_admin_moderator.sql +18 -0
- package/database/migrations/20260227_0019_sticker_classification_v2_signals.sql +12 -0
- package/database/migrations/20260227_0020_semantic_theme_clusters.sql +35 -0
- package/docker-compose.yml +103 -0
- package/ecosystem.prod.config.cjs +35 -0
- package/eslint.config.js +61 -0
- package/index.js +437 -0
- package/ml/clip_classifier/Dockerfile +16 -0
- package/ml/clip_classifier/README.md +120 -0
- package/ml/clip_classifier/adaptive_scoring.py +40 -0
- package/ml/clip_classifier/classifier.py +654 -0
- package/ml/clip_classifier/embedding_store.py +481 -0
- package/ml/clip_classifier/env_loader.py +15 -0
- package/ml/clip_classifier/llm_label_expander.py +144 -0
- package/ml/clip_classifier/main.py +213 -0
- package/ml/clip_classifier/requirements.txt +10 -0
- package/ml/clip_classifier/similarity_engine.py +74 -0
- package/observability/alert-rules.yml +60 -0
- package/observability/grafana/dashboards/omnizap-mysql.json +136 -0
- package/observability/grafana/dashboards/omnizap-overview.json +170 -0
- package/observability/grafana/provisioning/dashboards/dashboards.yml +11 -0
- package/observability/grafana/provisioning/datasources/datasources.yml +15 -0
- package/observability/loki-config.yml +38 -0
- package/observability/mysql-exporter.cnf +5 -0
- package/observability/mysql-setup.sql +46 -0
- package/observability/prometheus.yml +32 -0
- package/observability/promtail-config.yml +84 -0
- package/package.json +109 -0
- package/public/api-docs/index.html +144 -0
- package/public/css/github-project-panel.css +297 -0
- package/public/css/stickers-admin.css +1272 -0
- package/public/css/styles.css +671 -0
- package/public/index.html +1311 -0
- package/public/js/apps/apiDocsApp.js +310 -0
- package/public/js/apps/createPackApp.js +2069 -0
- package/public/js/apps/homeApp.js +396 -0
- package/public/js/apps/stickersAdminApp.js +1744 -0
- package/public/js/apps/stickersApp.js +4830 -0
- package/public/js/catalog.js +1019 -0
- package/public/js/github-panel/components/CommitList.js +34 -0
- package/public/js/github-panel/components/ErrorState.js +16 -0
- package/public/js/github-panel/components/GithubProjectPanel.js +106 -0
- package/public/js/github-panel/components/ReleaseList.js +38 -0
- package/public/js/github-panel/components/SkeletonPanel.js +22 -0
- package/public/js/github-panel/components/StatCard.js +15 -0
- package/public/js/github-panel/index.js +15 -0
- package/public/js/github-panel/useGithubRepoData.js +154 -0
- package/public/js/github-panel/vendor/react.js +11 -0
- package/public/js/runtime/react-runtime.js +19 -0
- package/public/licenca/index.html +106 -0
- package/public/stickers/admin/index.html +23 -0
- package/public/stickers/create/index.html +47 -0
- package/public/stickers/index.html +48 -0
- package/public/termos-de-uso/index.html +125 -0
- package/scripts/cache-bust.mjs +107 -0
- package/scripts/deploy.sh +458 -0
- package/scripts/github-deploy-notify.mjs +174 -0
- package/scripts/release.sh +129 -0
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */
|
|
2
|
+
import logger from '../utils/logger/loggerModule.js';
|
|
3
|
+
import { findById, findAll, TABLES } from '../../database/index.js';
|
|
4
|
+
import { extractUserIdInfo, resolveUserIdCached } from '../services/lidMapService.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Valida um ID de grupo ou usuário.
|
|
8
|
+
* @param {string} id - O ID a ser validado.
|
|
9
|
+
* @param {string} type - O tipo de ID ('Grupo' ou 'Usuário').
|
|
10
|
+
* @returns {boolean} True se o ID for válido, false caso contrário.
|
|
11
|
+
*/
|
|
12
|
+
export function _isValidId(id, type = 'ID') {
|
|
13
|
+
if (typeof id !== 'string' || id.trim() === '') {
|
|
14
|
+
logger.warn(`Tentativa de operação com ${type} inválido.`, { id });
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Retorna todos os dados de um grupo específico.
|
|
22
|
+
* @param {string} groupId - O ID do grupo.
|
|
23
|
+
* @returns {object|null} Os dados do grupo ou null se não encontrado ou se o ID for inválido.
|
|
24
|
+
*/
|
|
25
|
+
export async function getGroupInfo(groupId) {
|
|
26
|
+
return await getGroupInfoAsync(groupId);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Retorna o assunto (nome) de um grupo específico.
|
|
31
|
+
* @param {string} groupId - O ID do grupo.
|
|
32
|
+
* @returns {string|null} O assunto do grupo ou null se não encontrado.
|
|
33
|
+
*/
|
|
34
|
+
export async function getGroupSubject(groupId) {
|
|
35
|
+
const group = await getGroupInfoAsync(groupId);
|
|
36
|
+
return group?.subject || null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Retorna a lista de participantes de um grupo específico.
|
|
41
|
+
* @param {string} groupId - O ID do grupo.
|
|
42
|
+
* @returns {Array<object>|null} A lista de participantes ou null se não encontrado.
|
|
43
|
+
*/
|
|
44
|
+
export async function getGroupParticipants(groupId) {
|
|
45
|
+
return await getGroupParticipantsAsync(groupId);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Extrai o ID do usuário (canônico quando possível).
|
|
50
|
+
* @param {object|string} userObj - Objeto de mensagem ou string do ID.
|
|
51
|
+
* @returns {string|null} O ID do usuário ou null se não encontrado.
|
|
52
|
+
*/
|
|
53
|
+
export function extractUserId(userObj) {
|
|
54
|
+
if (!userObj) return null;
|
|
55
|
+
const info = extractUserIdInfo(userObj);
|
|
56
|
+
const canonical = resolveUserIdCached(info);
|
|
57
|
+
return canonical || info.raw || null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Verifica se um usuário é administrador em um grupo específico.
|
|
62
|
+
* Aceita tanto string quanto objeto de mensagem para userId.
|
|
63
|
+
* @param {string} groupId - O ID do grupo.
|
|
64
|
+
* @param {string|object} userIdOrObj - O ID do usuário ou objeto de mensagem.
|
|
65
|
+
* @returns {boolean} True se o usuário for admin, false caso contrário.
|
|
66
|
+
*/
|
|
67
|
+
export async function isUserAdmin(groupId, userIdOrObj) {
|
|
68
|
+
return await isUserAdminAsync(groupId, userIdOrObj);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function _normalizeDigits(str) {
|
|
72
|
+
if (!str || typeof str !== 'string') return '';
|
|
73
|
+
return str.replace(/\D/g, '');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function _matchesParticipantId(participant, userId) {
|
|
77
|
+
if (!participant || !userId) return false;
|
|
78
|
+
if (participant.id && participant.id === userId) return true;
|
|
79
|
+
if (participant.lid && participant.lid === userId) return true;
|
|
80
|
+
if (participant.jid && participant.jid === userId) return true;
|
|
81
|
+
|
|
82
|
+
const participantCanonical = resolveUserIdCached({
|
|
83
|
+
lid: participant.lid || participant.id || null,
|
|
84
|
+
jid: participant.jid || participant.id || null,
|
|
85
|
+
participantAlt: null,
|
|
86
|
+
});
|
|
87
|
+
const userCanonical = resolveUserIdCached({ lid: userId, jid: userId, participantAlt: null });
|
|
88
|
+
if (participantCanonical && userCanonical && participantCanonical === userCanonical) return true;
|
|
89
|
+
|
|
90
|
+
const pDigits = _normalizeDigits(participant.id || participant.lid || participant.jid || '');
|
|
91
|
+
const uDigits = _normalizeDigits(userId);
|
|
92
|
+
if (pDigits && uDigits && (pDigits === uDigits || pDigits.endsWith(uDigits) || uDigits.endsWith(pDigits))) {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Busca as informações do grupo no banco de dados.
|
|
101
|
+
* @param {string} groupId
|
|
102
|
+
* @returns {Promise<object|null>} objeto do grupo ou null
|
|
103
|
+
*/
|
|
104
|
+
export async function getGroupInfoAsync(groupId) {
|
|
105
|
+
if (!_isValidId(groupId, 'Grupo')) return null;
|
|
106
|
+
try {
|
|
107
|
+
const row = await findById(TABLES.GROUPS_METADATA, groupId);
|
|
108
|
+
if (!row) return null;
|
|
109
|
+
const data = Array.isArray(row) ? row[0] : row;
|
|
110
|
+
if (!data) return null;
|
|
111
|
+
|
|
112
|
+
let participants = data.participants || data.participants_json || null;
|
|
113
|
+
if (typeof participants === 'string') {
|
|
114
|
+
try {
|
|
115
|
+
participants = JSON.parse(participants);
|
|
116
|
+
} catch (e) {
|
|
117
|
+
participants = null;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const group = {
|
|
122
|
+
id: data.id,
|
|
123
|
+
subject: data.subject || data.name || null,
|
|
124
|
+
desc: data.description || data.desc || null,
|
|
125
|
+
owner: data.owner_jid || data.owner || null,
|
|
126
|
+
creation: data.creation || null,
|
|
127
|
+
participants: Array.isArray(participants) ? participants : [],
|
|
128
|
+
};
|
|
129
|
+
group.size = group.participants.length;
|
|
130
|
+
return group;
|
|
131
|
+
} catch (error) {
|
|
132
|
+
logger.error(`Erro ao buscar grupo do DB ${groupId}: ${error.message}`, { error });
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export async function getGroupParticipantsAsync(groupId) {
|
|
138
|
+
const group = await getGroupInfoAsync(groupId);
|
|
139
|
+
return group ? group.participants : null;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export async function isUserAdminAsync(groupId, userIdOrObj) {
|
|
143
|
+
const userId = extractUserId(userIdOrObj);
|
|
144
|
+
if (!_isValidId(groupId, 'Grupo') || !_isValidId(userId, 'Usuário')) return false;
|
|
145
|
+
const participants = await getGroupParticipantsAsync(groupId);
|
|
146
|
+
if (!participants) return false;
|
|
147
|
+
const participant = participants.find((p) => _matchesParticipantId(p, userId));
|
|
148
|
+
return !!participant && (participant.admin === 'admin' || participant.admin === 'superadmin' || participant.isAdmin === true);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export async function getGroupAdminsAsync(groupId) {
|
|
152
|
+
const participants = await getGroupParticipantsAsync(groupId);
|
|
153
|
+
if (!participants) return [];
|
|
154
|
+
return participants
|
|
155
|
+
.filter((p) => p.admin === 'admin' || p.admin === 'superadmin' || p.isAdmin === true)
|
|
156
|
+
.map((p) => p.id || p.lid || p.jid || null)
|
|
157
|
+
.filter(Boolean);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Retorna todos os IDs de grupo disponíveis.
|
|
162
|
+
* @returns {Array<string>} Uma lista de IDs de grupo.
|
|
163
|
+
*/
|
|
164
|
+
export async function getAllGroupIds() {
|
|
165
|
+
try {
|
|
166
|
+
const rows = await findAll(TABLES.GROUPS_METADATA, 10000, 0);
|
|
167
|
+
if (!rows || !Array.isArray(rows)) return [];
|
|
168
|
+
return rows.map((r) => r.id || r[Object.keys(r)[0]]).filter(Boolean);
|
|
169
|
+
} catch (error) {
|
|
170
|
+
logger.error('Erro ao buscar todos os IDs de grupos do DB', { error });
|
|
171
|
+
return [];
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Retorna o proprietário de um grupo específico.
|
|
177
|
+
* @param {string} groupId - O ID do grupo.
|
|
178
|
+
* @returns {string|null} O ID do proprietário do grupo ou null se não encontrado.
|
|
179
|
+
*/
|
|
180
|
+
export async function getGroupOwner(groupId) {
|
|
181
|
+
const group = await getGroupInfoAsync(groupId);
|
|
182
|
+
return group?.owner || null;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Retorna o timestamp de criação de um grupo específico.
|
|
187
|
+
* @param {string} groupId - O ID do grupo.
|
|
188
|
+
* @returns {number|null} O timestamp de criação do grupo ou null se não encontrado.
|
|
189
|
+
*/
|
|
190
|
+
export async function getGroupCreationTime(groupId) {
|
|
191
|
+
const group = await getGroupInfoAsync(groupId);
|
|
192
|
+
return group?.creation || null;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Retorna a descrição de um grupo específico.
|
|
197
|
+
* @param {string} groupId - O ID do grupo.
|
|
198
|
+
* @returns {string|null} A descrição do grupo ou null se não encontrado.
|
|
199
|
+
*/
|
|
200
|
+
export async function getGroupDescription(groupId) {
|
|
201
|
+
const group = await getGroupInfoAsync(groupId);
|
|
202
|
+
return group?.desc || null;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Retorna o número de participantes de um grupo específico.
|
|
207
|
+
* @param {string} groupId - O ID do grupo.
|
|
208
|
+
* @returns {number|null} O número de participantes do grupo ou null se não encontrado.
|
|
209
|
+
*/
|
|
210
|
+
export async function getGroupSize(groupId) {
|
|
211
|
+
const group = await getGroupInfoAsync(groupId);
|
|
212
|
+
return group?.size || null;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Verifica se um grupo é restrito.
|
|
217
|
+
* @param {string} groupId - O ID do grupo.
|
|
218
|
+
* @returns {boolean} True se o grupo for restrito, false caso contrário.
|
|
219
|
+
*/
|
|
220
|
+
export async function isGroupRestricted(groupId) {
|
|
221
|
+
const group = await getGroupInfoAsync(groupId);
|
|
222
|
+
return !!group?.restrict;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Verifica se um grupo é apenas para anúncios.
|
|
227
|
+
* @param {string} groupId - O ID do grupo.
|
|
228
|
+
* @returns {boolean} True se o grupo for apenas para anúncios, false caso contrário.
|
|
229
|
+
*/
|
|
230
|
+
export async function isGroupAnnounceOnly(groupId) {
|
|
231
|
+
const group = await getGroupInfoAsync(groupId);
|
|
232
|
+
return !!group?.announce;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Verifica se um grupo é uma comunidade.
|
|
237
|
+
* @param {string} groupId - O ID do grupo.
|
|
238
|
+
* @returns {boolean} True se o grupo for uma comunidade, false caso contrário.
|
|
239
|
+
*/
|
|
240
|
+
export async function isGroupCommunity(groupId) {
|
|
241
|
+
const group = await getGroupInfoAsync(groupId);
|
|
242
|
+
return !!group?.isCommunity;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Retorna uma lista de IDs dos administradores de um grupo específico.
|
|
247
|
+
* @param {string} groupId - O ID do grupo.
|
|
248
|
+
* @returns {Array<string>} Uma lista de IDs dos administradores do grupo.
|
|
249
|
+
*/
|
|
250
|
+
export async function getGroupAdmins(groupId) {
|
|
251
|
+
return await getGroupAdminsAsync(groupId);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Executa uma função de grupo de forma segura, validando os parâmetros e tratando erros.
|
|
256
|
+
* @param {object} sock - A instância do socket Baileys.
|
|
257
|
+
* @param {string} functionName - O nome da função a ser executada.
|
|
258
|
+
* @param {Array} args - Os argumentos para a função.
|
|
259
|
+
* @param {string} errorMessage - A mensagem de erro a ser registrada.
|
|
260
|
+
*/
|
|
261
|
+
export async function _safeGroupApiCall(sock, functionName, args, errorMessage) {
|
|
262
|
+
if (!sock || typeof sock[functionName] !== 'function') {
|
|
263
|
+
logger.error(`Objeto de socket inválido ou função ${functionName} não encontrada.`);
|
|
264
|
+
throw new Error(`Socket inválido para a operação ${functionName}.`);
|
|
265
|
+
}
|
|
266
|
+
try {
|
|
267
|
+
return await sock[functionName](...args);
|
|
268
|
+
} catch (error) {
|
|
269
|
+
logger.error(errorMessage, {
|
|
270
|
+
function: functionName,
|
|
271
|
+
args,
|
|
272
|
+
error: error.message,
|
|
273
|
+
stack: error.stack,
|
|
274
|
+
});
|
|
275
|
+
throw error;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export async function createGroup(sock, title, participants) {
|
|
280
|
+
if (typeof title !== 'string' || title.trim() === '' || !Array.isArray(participants)) {
|
|
281
|
+
throw new Error('Título ou participantes inválidos.');
|
|
282
|
+
}
|
|
283
|
+
const result = await _safeGroupApiCall(sock, 'groupCreate', [title, participants], 'Erro ao criar grupo');
|
|
284
|
+
logger.info(`Grupo "${title}" criado com sucesso.`, { id: result.id });
|
|
285
|
+
return result;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export async function updateGroupParticipants(sock, groupId, participants, action) {
|
|
289
|
+
if (!_isValidId(groupId, 'Grupo') || !Array.isArray(participants) || !action) {
|
|
290
|
+
throw new Error('Argumentos inválidos para atualizar participantes.');
|
|
291
|
+
}
|
|
292
|
+
return _safeGroupApiCall(sock, 'groupParticipantsUpdate', [groupId, participants, action], `Erro ao ${action} participantes no grupo ${groupId}`);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export async function updateGroupSubject(sock, groupId, subject) {
|
|
296
|
+
if (!_isValidId(groupId, 'Grupo') || typeof subject !== 'string') {
|
|
297
|
+
throw new Error('Argumentos inválidos para atualizar assunto do grupo.');
|
|
298
|
+
}
|
|
299
|
+
return _safeGroupApiCall(sock, 'groupUpdateSubject', [groupId, subject], `Erro ao atualizar assunto do grupo ${groupId}`);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export async function updateGroupDescription(sock, groupId, description) {
|
|
303
|
+
if (!_isValidId(groupId, 'Grupo')) {
|
|
304
|
+
throw new Error('ID de grupo inválido.');
|
|
305
|
+
}
|
|
306
|
+
return _safeGroupApiCall(sock, 'groupUpdateDescription', [groupId, description], `Erro ao atualizar descrição do grupo ${groupId}`);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export async function updateGroupSettings(sock, groupId, setting) {
|
|
310
|
+
if (!_isValidId(groupId, 'Grupo') || !setting) {
|
|
311
|
+
throw new Error('Argumentos inválidos para atualizar configurações do grupo.');
|
|
312
|
+
}
|
|
313
|
+
return _safeGroupApiCall(sock, 'groupSettingUpdate', [groupId, setting], `Erro ao atualizar configurações do grupo ${groupId}`);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export async function leaveGroup(sock, groupId) {
|
|
317
|
+
if (!_isValidId(groupId, 'Grupo')) {
|
|
318
|
+
throw new Error('ID de grupo inválido.');
|
|
319
|
+
}
|
|
320
|
+
return _safeGroupApiCall(sock, 'groupLeave', [groupId], `Erro ao sair do grupo ${groupId}`);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export async function getGroupInviteCode(sock, groupId) {
|
|
324
|
+
if (!_isValidId(groupId, 'Grupo')) {
|
|
325
|
+
throw new Error('ID de grupo inválido.');
|
|
326
|
+
}
|
|
327
|
+
return _safeGroupApiCall(sock, 'groupInviteCode', [groupId], `Erro ao obter código de convite do grupo ${groupId}`);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export async function revokeGroupInviteCode(sock, groupId) {
|
|
331
|
+
if (!_isValidId(groupId, 'Grupo')) {
|
|
332
|
+
throw new Error('ID de grupo inválido.');
|
|
333
|
+
}
|
|
334
|
+
return _safeGroupApiCall(sock, 'groupRevokeInvite', [groupId], `Erro ao revogar código de convite do grupo ${groupId}`);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
export async function acceptGroupInvite(sock, code) {
|
|
338
|
+
if (typeof code !== 'string' || code.trim() === '') {
|
|
339
|
+
throw new Error('Código de convite inválido.');
|
|
340
|
+
}
|
|
341
|
+
return _safeGroupApiCall(sock, 'groupAcceptInvite', [code], 'Erro ao aceitar convite de grupo');
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
export async function getGroupInfoFromInvite(sock, code) {
|
|
345
|
+
if (typeof code !== 'string' || code.trim() === '') {
|
|
346
|
+
throw new Error('Código de convite inválido.');
|
|
347
|
+
}
|
|
348
|
+
return _safeGroupApiCall(sock, 'groupGetInviteInfo', [code], 'Erro ao obter informações do convite');
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export async function getGroupMetadata(sock, groupId) {
|
|
352
|
+
if (!_isValidId(groupId, 'Grupo')) {
|
|
353
|
+
throw new Error('ID de grupo inválido.');
|
|
354
|
+
}
|
|
355
|
+
return _safeGroupApiCall(sock, 'groupMetadata', [groupId], `Erro ao obter metadados do grupo ${groupId}`);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
export async function getGroupRequestParticipantsList(sock, groupId) {
|
|
359
|
+
if (!_isValidId(groupId, 'Grupo')) {
|
|
360
|
+
throw new Error('ID de grupo inválido.');
|
|
361
|
+
}
|
|
362
|
+
return _safeGroupApiCall(sock, 'groupRequestParticipantsList', [groupId], `Erro ao listar solicitações de entrada no grupo ${groupId}`);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
export async function updateGroupRequestParticipants(sock, groupId, participants, action) {
|
|
366
|
+
if (!_isValidId(groupId, 'Grupo') || !Array.isArray(participants) || !action) {
|
|
367
|
+
throw new Error('Argumentos inválidos para atualizar solicitações de entrada.');
|
|
368
|
+
}
|
|
369
|
+
return _safeGroupApiCall(sock, 'groupRequestParticipantsUpdate', [groupId, participants, action], `Erro ao atualizar solicitações de entrada no grupo ${groupId}`);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
export async function getAllParticipatingGroups(sock) {
|
|
373
|
+
return _safeGroupApiCall(sock, 'groupFetchAllParticipating', [], 'Erro ao obter todos os grupos participantes');
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export async function toggleEphemeral(sock, groupId, duration) {
|
|
377
|
+
if (!_isValidId(groupId, 'Grupo') || typeof duration !== 'number') {
|
|
378
|
+
throw new Error('Argumentos inválidos para alternar mensagens efêmeras.');
|
|
379
|
+
}
|
|
380
|
+
return _safeGroupApiCall(sock, 'groupToggleEphemeral', [groupId, duration], `Erro ao alternar mensagens efêmeras no grupo ${groupId}`);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
export async function updateGroupAddMode(sock, groupId, mode) {
|
|
384
|
+
if (!_isValidId(groupId, 'Grupo') || !mode) {
|
|
385
|
+
throw new Error('Argumentos inválidos para atualizar modo de adição.');
|
|
386
|
+
}
|
|
387
|
+
return _safeGroupApiCall(sock, 'groupMemberAddMode', [groupId, mode], `Erro ao atualizar modo de adição no grupo ${groupId}`);
|
|
388
|
+
}
|