Skip to content

Commit ba2d10a

Browse files
committed
feat: add whatsapp/sms message links forger
Fix CorentinTh#635
1 parent c6b75ca commit ba2d10a

File tree

3 files changed

+64
-5
lines changed

3 files changed

+64
-5
lines changed

components.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,9 @@ declare module '@vue/runtime-core' {
126126
MenuLayout: typeof import('./src/components/MenuLayout.vue')['default']
127127
MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default']
128128
MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default']
129+
NA: typeof import('naive-ui')['NA']
129130
NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default']
131+
NButton: typeof import('naive-ui')['NButton']
130132
NCode: typeof import('naive-ui')['NCode']
131133
NCollapseTransition: typeof import('naive-ui')['NCollapseTransition']
132134
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
@@ -145,6 +147,7 @@ declare module '@vue/runtime-core' {
145147
NMenu: typeof import('naive-ui')['NMenu']
146148
NScrollbar: typeof import('naive-ui')['NScrollbar']
147149
NSpin: typeof import('naive-ui')['NSpin']
150+
NTable: typeof import('naive-ui')['NTable']
148151
NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default']
149152
OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default']
150153
PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default']

src/tools/phone-parser-and-formatter/index.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { Phone } from '@vicons/tabler';
22
import { defineTool } from '../tool';
3-
import { translate } from '@/plugins/i18n.plugin';
43

54
export const tool = defineTool({
6-
name: translate('tools.phone-parser-and-formatter.title'),
5+
name: 'Phone parser and formatter',
76
path: '/phone-parser-and-formatter',
8-
description: translate('tools.phone-parser-and-formatter.description'),
7+
description:
8+
'Parse, validate and format phone numbers. Get information about the phone number, like the country code, type, etc. Forge link to send message in WhatsApp and SMS',
99
keywords: [
1010
'phone',
1111
'parser',
@@ -18,6 +18,9 @@ export const tool = defineTool({
1818
'cell',
1919
'international',
2020
'national',
21+
'whatsapp',
22+
'sms',
23+
'message',
2124
],
2225
component: () => import('./phone-parser-and-formatter.vue'),
2326
icon: Phone,

src/tools/phone-parser-and-formatter/phone-parser-and-formatter.vue

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,16 @@ const validation = useValidation({
2323
],
2424
});
2525
26-
const parsedDetails = computed(() => {
26+
const parsedRaw = computed(() => {
2727
if (!validation.isValid) {
2828
return undefined;
2929
}
3030
31-
const parsed = withDefaultOnError(() => parsePhoneNumber(rawPhone.value, defaultCountryCode.value), undefined);
31+
return withDefaultOnError(() => parsePhoneNumber(rawPhone.value, defaultCountryCode.value), undefined);
32+
});
3233
34+
const parsedDetails = computed(() => {
35+
const parsed = parsedRaw.value;
3336
if (!parsed) {
3437
return undefined;
3538
}
@@ -82,6 +85,27 @@ const countriesOptions = getCountries().map(code => ({
8285
label: `${lookup.byIso(code)?.country || code} (+${getCountryCallingCode(code)})`,
8386
value: code,
8487
}));
88+
89+
const messageToSend = ref('');
90+
const whatsAppLink = computed(() => {
91+
const parsed = parsedRaw.value;
92+
if (!parsed) {
93+
return undefined;
94+
}
95+
96+
const internationalNoPunts = parsed.formatInternational().replace(/^\+0*/g, '').replace(/\D/g, '');
97+
98+
return `https://wa.me/${internationalNoPunts}?text=${encodeURIComponent(messageToSend.value)}`;
99+
});
100+
const smsLink = computed(() => {
101+
const parsed = parsedRaw.value;
102+
if (!parsed) {
103+
return undefined;
104+
}
105+
106+
const internationalNoSpaces = parsed.formatInternational().replace(/\s/g, '');
107+
return `sms:${internationalNoSpaces}&body=${encodeURIComponent(messageToSend.value)}`;
108+
});
85109
</script>
86110

87111
<template>
@@ -111,5 +135,34 @@ const countriesOptions = getCountries().map(code => ({
111135
</tr>
112136
</tbody>
113137
</n-table>
138+
139+
<n-divider />
140+
141+
<c-input-text
142+
v-model:value="messageToSend"
143+
multiline
144+
rows="4"
145+
placeholder="Enter a message to send"
146+
label="Message to send:"
147+
mb-2
148+
/>
149+
150+
<c-card v-if="whatsAppLink" title="WhatsApp Send link" mb-2>
151+
<input-copyable :value="whatsAppLink" mb-2 />
152+
<div flex justify-center>
153+
<!-- //NOSONAR --><c-button :href="whatsAppLink" target="_blank">
154+
Send via WhatsApp
155+
</c-button>
156+
</div>
157+
</c-card>
158+
159+
<c-card v-if="smsLink" title="SMS Send link">
160+
<input-copyable :value="smsLink" mb-2 />
161+
<div flex justify-center>
162+
<!-- //NOSONAR --><c-button :href="smsLink" target="_blank">
163+
Send via SMS
164+
</c-button>
165+
</div>
166+
</c-card>
114167
</div>
115168
</template>

0 commit comments

Comments
 (0)