Browse Source

feat: add IsOnWhatsApp endpoint to check user availability

- Add /user/check endpoint with phone query parameter
- Implement CheckRequest and CheckResponse domain types
- Add IsOnWhatsApp method to user usecase interface and implementation
- Create AccountUserCheck Vue component for UI interaction
- Update OpenAPI documentation with new endpoint schema
- Bump version to 6.1.0 for new feature release
pull/301/head
Aldino Kemal 9 months ago
parent
commit
93bf10b4ad
  1. 49
      docs/openapi.yaml
  2. 8
      src/domains/user/account.go
  3. 1
      src/domains/user/user.go
  4. 17
      src/ui/rest/user.go
  5. 10
      src/usecase/user.go
  6. 95
      src/views/components/AccountUserCheck.js
  7. 4
      src/views/index.html

49
docs/openapi.yaml

@ -1,7 +1,7 @@
openapi: "3.0.0"
info:
title: WhatsApp API MultiDevice
version: 6.0.0
version: 6.1.0
description: This API is used for sending whatsapp via API
servers:
- url: http://localhost:3000
@ -348,6 +348,38 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ErrorInternalServer'
/user/check:
get:
operationId: userCheck
tags:
- user
summary: Check if user is on WhatsApp
parameters:
- name: phone
in: query
schema:
type: string
example: '628912344551'
description: Phone number with country code
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/UserCheckResponse'
'400':
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorBadRequest'
'500':
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorInternalServer'
/send/message:
post:
@ -2138,3 +2170,18 @@ components:
type: string
format: date-time
example: "2024-10-11T21:27:29+07:00"
UserCheckResponse:
type: object
properties:
code:
type: string
example: SUCCESS
message:
type: string
example: Success check user
results:
type: object
properties:
is_on_whatsapp:
type: boolean
example: true

8
src/domains/user/account.go

@ -73,3 +73,11 @@ type MyListContactsResponseData struct {
type ChangePushNameRequest struct {
PushName string `json:"push_name" form:"push_name"`
}
type CheckRequest struct {
Phone string `json:"phone" query:"phone"`
}
type CheckResponse struct {
IsOnWhatsApp bool `json:"is_on_whatsapp"`
}

1
src/domains/user/user.go

@ -13,4 +13,5 @@ type IUserUsecase interface {
MyListNewsletter(ctx context.Context) (response MyListNewsletterResponse, err error)
MyPrivacySetting(ctx context.Context) (response MyPrivacySettingResponse, err error)
MyListContacts(ctx context.Context) (response MyListContactsResponse, err error)
IsOnWhatsApp(ctx context.Context, request CheckRequest) (response CheckResponse, err error)
}

17
src/ui/rest/user.go

@ -21,6 +21,7 @@ func InitRestUser(app *fiber.App, service domainUser.IUserUsecase) User {
app.Get("/user/my/groups", rest.UserMyListGroups)
app.Get("/user/my/newsletters", rest.UserMyListNewsletter)
app.Get("/user/my/contacts", rest.UserMyListContacts)
app.Get("/user/check", rest.UserCheck)
return rest
}
@ -141,3 +142,19 @@ func (controller *User) UserChangePushName(c *fiber.Ctx) error {
Message: "Success change push name",
})
}
func (controller *User) UserCheck(c *fiber.Ctx) error {
var request domainUser.CheckRequest
err := c.QueryParser(&request)
utils.PanicIfNeeded(err)
response, err := controller.Service.IsOnWhatsApp(c.UserContext(), request)
utils.PanicIfNeeded(err)
return c.JSON(utils.ResponseData{
Status: 200,
Code: "SUCCESS",
Message: "Success check user",
Results: response,
})
}

10
src/usecase/user.go

@ -242,3 +242,13 @@ func (service serviceUser) ChangePushName(ctx context.Context, request domainUse
}
return nil
}
func (service serviceUser) IsOnWhatsApp(ctx context.Context, request domainUser.CheckRequest) (response domainUser.CheckResponse, err error) {
whatsapp.MustLogin(service.WaCli)
whatsapp.SanitizePhone(&request.Phone)
response.IsOnWhatsApp = whatsapp.IsOnWhatsapp(service.WaCli, request.Phone)
return response, nil
}

95
src/views/components/AccountUserCheck.js

@ -0,0 +1,95 @@
import FormRecipient from "./generic/FormRecipient.js";
export default {
name: 'AccountUserCheck',
components: {
FormRecipient
},
data() {
return {
type: window.TYPEUSER,
phone: '',
isOnWhatsApp: null,
loading: false,
}
},
computed: {
phone_id() {
return this.phone + this.type;
}
},
methods: {
async openModal() {
this.handleReset();
$('#modalUserCheck').modal('show');
},
isValidForm() {
return this.phone.trim() !== '';
},
async handleSubmit() {
if (!this.isValidForm() || this.loading) {
return;
}
try {
await this.submitApi();
showSuccessInfo("Check completed")
} catch (err) {
showErrorInfo(err)
}
},
async submitApi() {
this.loading = true;
try {
let response = await window.http.get(`/user/check?phone=${this.phone_id}`)
this.isOnWhatsApp = response.data.results.is_on_whatsapp;
} catch (error) {
if (error.response) {
throw new Error(error.response.data.message);
}
throw new Error(error.message);
} finally {
this.loading = false;
}
},
handleReset() {
this.phone = '';
this.isOnWhatsApp = null;
this.type = window.TYPEUSER;
}
},
template: `
<div class="olive card" @click="openModal" style="cursor: pointer;">
<div class="content">
<a class="ui olive right ribbon label">Account</a>
<div class="header">User Check</div>
<div class="description">
Check if a user is on WhatsApp
</div>
</div>
</div>
<div class="ui small modal" id="modalUserCheck">
<i class="close icon"></i>
<div class="header">
Check if User is on WhatsApp
</div>
<div class="content">
<form class="ui form">
<FormRecipient v-model:type="type" v-model:phone="phone"/>
<button type="button" class="ui primary button" :class="{'loading': loading, 'disabled': !this.isValidForm() || this.loading}"
@click.prevent="handleSubmit">
Check
</button>
</form>
<div v-if="isOnWhatsApp !== null" class="ui message" :class="isOnWhatsApp ? 'positive' : 'negative'">
<div class="header">
<i :class="isOnWhatsApp ? 'check circle icon' : 'times circle icon'"></i>
{{ isOnWhatsApp ? 'User is on WhatsApp' : 'User is not on WhatsApp' }}
</div>
<p>Phone: {{ phone_id }}</p>
</div>
</div>
</div>
`
}

4
src/views/index.html

@ -161,6 +161,7 @@
<account-user-info></account-user-info>
<account-privacy></account-privacy>
<account-contact></account-contact>
<account-user-check></account-user-check>
</div>
</div>
@ -225,6 +226,7 @@
import AccountUserInfo from "./components/AccountUserInfo.js";
import AccountPrivacy from "./components/AccountPrivacy.js";
import AccountContact from "./components/AccountContact.js";
import AccountUserCheck from "./components/AccountUserCheck.js";
const showErrorInfo = (message) => {
$('body').toast({
@ -263,7 +265,7 @@
MessageDelete, MessageUpdate, MessageReact, MessageRevoke,
GroupList, GroupCreate, GroupJoinWithLink, GroupAddParticipants,
NewsletterList,
AccountAvatar, AccountUserInfo, AccountPrivacy, AccountChangeAvatar, AccountContact, AccountChangePushName
AccountAvatar, AccountUserInfo, AccountPrivacy, AccountChangeAvatar, AccountContact, AccountChangePushName, AccountUserCheck
},
delimiters: ['[[', ']]'],
data() {

Loading…
Cancel
Save