Browse Source

feat: Adding new route for check if user is in whatsapp

pull/231/head
Ruan 1 year ago
parent
commit
001236e76f
  1. 4
      .gitignore
  2. 10
      readme.md
  3. 19
      src/domains/user/account.go
  4. 1
      src/domains/user/user.go
  5. 20
      src/internal/rest/user.go
  6. 35
      src/services/user.go
  7. 11
      src/validations/user_validation.go
  8. 117
      src/views/components/AccountUserCheck.js
  9. 50
      src/views/components/generic/FormCheckUserRecipient.js
  10. 4
      src/views/index.html

4
.gitignore

@ -7,4 +7,6 @@ main
main.exe
*.jpe
src/pkged.go
storages
storages
.tool-versions

10
readme.md

@ -103,6 +103,14 @@ You can fork or edit this source code !
to [SwaggerEditor](https://editor.swagger.io).
- Furthermore you can generate HTTP Client from this API using [openapi-generator](https://openapi-generator.tech/#try)
## CURL for the api
#### You need to encode to Base64 your user:pass [basic-auth] and pass in header
- curl -X 'GET' 'http://127.0.0.1:3000/user/check?phone=YOUR_PHONE' -H 'accept: application/json' \
-H 'Authorization: Basic qwertyASDFzxc='
- curl -X 'GET' 'http://127.0.0.1:3000/user/check?phone=YOUR_PHONE' -H 'accept: application/json'
| Feature | Menu | Method | URL |
|---------|------------------------------|--------|-------------------------------|
| ✅ | Login with Scan QR | GET | /app/login |
@ -111,6 +119,7 @@ You can fork or edit this source code !
| ✅ | Reconnect | GET | /app/reconnect |
| ✅ | Devices | GET | /app/devices |
| ✅ | User Info | GET | /user/info |
| ✅ | Check User is on whatsapp | GET | /user/check |
| ✅ | User Avatar | GET | /user/avatar |
| ✅ | User My Groups | GET | /user/my/groups |
| ✅ | User My Newsletter | GET | /user/my/newsletters |
@ -164,6 +173,7 @@ You can fork or edit this source code !
| Reaction Message | ![Reaction Message](https://i.ibb.co.com/BfHgSHG/react-message.png) |
| Edit Message | ![Edit Message](https://i.ibb.co.com/kXfpqJw/update-message.png) |
| User Info | ![User Info](https://i.ibb.co.com/3zjX6Cz/user-info.png?v=1) |
| Check User | ![Check User ](https://i.ibb.co/92gVZrx/Check-User.png?v=1) |
| User Avatar | ![User Avatar](https://i.ibb.co.com/ZmJZ4ZW/search-avatar.png?v=1) |
| My Privacy | ![My Privacy](https://i.ibb.co.com/Cw1sMQz/my-privacy.png) |
| My Group | ![My Group](https://i.ibb.co.com/WB268Xy/list-group.png) |

19
src/domains/user/account.go

@ -6,6 +6,10 @@ type InfoRequest struct {
Phone string `json:"phone" query:"phone"`
}
type CheckRequest struct {
Phone string `json:"phone" query:"phone"`
}
type InfoResponseDataDevice struct {
User string
Agent uint8
@ -21,10 +25,25 @@ type InfoResponseData struct {
Devices []InfoResponseDataDevice `json:"devices"`
}
type CheckResponseData struct {
Query string `json:"query"`
IsInWhatsapp bool `json:"IsInWhatsapp"`
VerifiedName string `json:"verified_name"`
JID string `json:"jid"`
}
type InfoResponse struct {
Data []InfoResponseData `json:"data"`
}
type CheckResponse struct {
Data []CheckResponseData `json:"data"`
}
type UserCollection struct {
Users []CheckResponseData
}
type AvatarRequest struct {
Phone string `json:"phone" query:"phone"`
IsPreview bool `json:"is_preview" query:"is_preview"`

1
src/domains/user/user.go

@ -6,6 +6,7 @@ import (
type IUserService interface {
Info(ctx context.Context, request InfoRequest) (response InfoResponse, err error)
Check(ctx context.Context, request CheckRequest) (response CheckResponse, err error)
Avatar(ctx context.Context, request AvatarRequest) (response AvatarResponse, err error)
MyListGroups(ctx context.Context) (response MyListGroupsResponse, err error)
MyListNewsletter(ctx context.Context) (response MyListNewsletterResponse, err error)

20
src/internal/rest/user.go

@ -14,6 +14,7 @@ type User struct {
func InitRestUser(app *fiber.App, service domainUser.IUserService) User {
rest := User{Service: service}
app.Get("/user/info", rest.UserInfo)
app.Get("/user/check", rest.UserCheck)
app.Get("/user/avatar", rest.UserAvatar)
app.Get("/user/my/privacy", rest.UserMyPrivacySetting)
app.Get("/user/my/groups", rest.UserMyListGroups)
@ -40,6 +41,25 @@ func (controller *User) UserInfo(c *fiber.Ctx) error {
})
}
func (controller *User) UserCheck(c *fiber.Ctx) error {
var request domainUser.CheckRequest
err := c.QueryParser(&request)
utils.PanicIfNeeded(err)
whatsapp.SanitizePhone(&request.Phone)
response, err := controller.Service.Check(c.UserContext(), request)
utils.PanicIfNeeded(err)
return c.JSON(utils.ResponseData{
Status: 200,
Code: "SUCCESS",
Message: "Success get user info",
Results: response.Data[0],
})
}
func (controller *User) UserAvatar(c *fiber.Ctx) error {
var request domainUser.AvatarRequest
err := c.QueryParser(&request)

35
src/services/user.go

@ -66,6 +66,41 @@ func (service userService) Info(ctx context.Context, request domainUser.InfoRequ
return response, nil
}
func (service userService) Check(ctx context.Context, request domainUser.CheckRequest) (response domainUser.CheckResponse, err error) {
err = validations.ValidateUserCheck(ctx, request)
if err != nil {
return response, err
}
var jids []types.JID
dataWaRecipient, err := whatsapp.ValidateJidWithLogin(service.WaCli, request.Phone)
if err != nil {
return response, err
}
jids = append(jids, dataWaRecipient)
resp, err := service.WaCli.IsOnWhatsApp([]string{request.Phone})
if err != nil {
return response, err
}
uc := new(domainUser.UserCollection)
for _, item := range resp {
if item.VerifiedName != nil {
var msg = domainUser.CheckResponseData{Query: item.Query, IsInWhatsapp: item.IsIn, JID: fmt.Sprintf("%s", item.JID), VerifiedName: item.VerifiedName.Details.GetVerifiedName()}
uc.Users = append(uc.Users, msg)
} else {
var msg = domainUser.CheckResponseData{Query: item.Query, IsInWhatsapp: item.IsIn, JID: fmt.Sprintf("%s", item.JID), VerifiedName: ""}
uc.Users = append(uc.Users, msg)
}
}
response.Data = append(response.Data, uc.Users[0])
// response := string(responseJson)
return response, err
}
func (service userService) Avatar(ctx context.Context, request domainUser.AvatarRequest) (response domainUser.AvatarResponse, err error) {
chanResp := make(chan domainUser.AvatarResponse)

11
src/validations/user_validation.go

@ -18,6 +18,17 @@ func ValidateUserInfo(ctx context.Context, request domainUser.InfoRequest) error
return nil
}
func ValidateUserCheck(ctx context.Context, request domainUser.CheckRequest) error {
err := validation.ValidateStructWithContext(ctx, &request,
validation.Field(&request.Phone, validation.Required),
)
if err != nil {
return pkgError.ValidationError(err.Error())
}
return nil
}
func ValidateUserAvatar(ctx context.Context, request domainUser.AvatarRequest) error {
err := validation.ValidateStructWithContext(ctx, &request,
validation.Field(&request.Phone, validation.Required),

117
src/views/components/AccountUserCheck.js

@ -0,0 +1,117 @@
import FormCheckUserRecipient from "./generic/FormCheckUserRecipient.js";
export default {
name: 'AccountUserCheck',
components: {
FormCheckUserRecipient
},
data() {
return {
type: window.TYPEUSER,
phone: '',
//
is_in_whatsapp: null,
jid: null,
verified_name: null,
query: null,
code: null,
//
loading: false,
}
},
computed: {
phone_id() {
return this.phone + this.type;
}
},
methods: {
async openModal() {
this.handleReset();
$('#modalUserCheck').modal('show');
},
async handleSubmit() {
try {
await this.submitApi();
showSuccessInfo("Info fetched")
} catch (err) {
showErrorInfo(err)
}
},
async submitApi() {
this.loading = true;
try {
let response = await window.http.get(`/user/check?phone=${this.phone_id}`)
this.is_in_whatsapp = response.data.results.IsInWhatsapp;
this.jid = response.data.results.jid;
this.verified_name = response.data.results.verified_name;
this.query = response.data.results.query;
this.code = response.code;
} catch (error) {
if (error.response) {
this.verified_name = null;
this.jid = null;
throw new Error(error.response.data.message);
}
this.verified_name = null;
this.jid = null;
throw new Error(error.message);
} finally {
this.loading = false;
}
},
handleReset() {
this.phone = '';
this.is_in_whatsapp = null;
this.jid = null;
this.verified_name = null;
this.query = null;
this.code = null;
this.type = window.TYPEUSER;
}
},
template: `
<div class="green card" @click="openModal" style="cursor: pointer;">
<div class="content">
<div class="header">User Check</div>
<div class="description">
You can check if the user exists on whatapp
</div>
</div>
</div>
<!-- Modal UserInfo -->
<div class="ui small modal" id="modalUserCheck">
<i class="close icon"></i>
<div class="header">
Search User Information
</div>
<div class="content">
<form class="ui form">
<FormCheckUserRecipient v-model:type="type" v-model:phone="phone"/>
<button type="button" class="ui primary button" :class="{'loading': loading}"
@click="handleSubmit">
Search
</button>
</form>
<div v-if="is_in_whatsapp != null" class="center">
<ol>
<li>Name: {{ verified_name }}</li>
<li>JID: {{ jid }}</li>
</ol>
</div>
<div v-else class="center">
<div v-if="code == 'INVALID_JID'" class="center">
<ol>
<li>Name: {{ verified_name }}</li>
<li>JID: {{ jid }}</li>
</ol>
</div>
</div>
</div>
</div>
`
}

50
src/views/components/generic/FormCheckUserRecipient.js

@ -0,0 +1,50 @@
export default {
name: 'FormCheckUserRecipient',
props: {
type: {
type: String,
required: true
},
phone: {
type: String,
required: true
},
},
data() {
return {
recipientTypes: []
};
},
computed: {
phone_id() {
return this.phone + this.type;
}
},
mounted() {
this.recipientTypes = [
{ value: window.TYPEUSER, text: 'Private Message' },
];
},
methods: {
updateType(event) {
this.$emit('update:type', event.target.value);
},
updatePhone(event) {
this.$emit('update:phone', event.target.value);
}
},
template: `
<div class="field">
<label>Type</label>
<select name="type" @change="updateType" class="ui dropdown">
<option v-for="type in recipientTypes" :value="type.value">{{ type.text }}</option>
</select>
</div>
<div class="field">
<label>Phone</label>
<input :value="phone" aria-label="wa identifier" @input="updatePhone">
<input :value="phone_id" disabled aria-label="whatsapp_id">
</div>
`
}

4
src/views/index.html

@ -101,6 +101,7 @@
<div class="ui three column doubling grid cards">
<account-avatar></account-avatar>
<account-user-info></account-user-info>
<account-user-check></account-user-check>
<account-privacy></account-privacy>
</div>
@ -158,6 +159,7 @@
import GroupAddParticipants from "./components/GroupManageParticipants.js";
import AccountAvatar from "./components/AccountAvatar.js";
import AccountUserInfo from "./components/AccountUserInfo.js";
import AccountUserCheck from "./components/AccountUserCheck.js";
import AccountPrivacy from "./components/AccountPrivacy.js";
import NewsletterList from "./components/NewsletterList.js";
@ -198,7 +200,7 @@
MessageDelete, MessageUpdate, MessageReact, MessageRevoke,
GroupList, GroupCreate, GroupJoinWithLink, GroupAddParticipants,
NewsletterList,
AccountAvatar, AccountUserInfo, AccountPrivacy
AccountAvatar, AccountUserInfo, AccountUserCheck, AccountPrivacy
},
delimiters: ['[[', ']]'],
data() {

Loading…
Cancel
Save