Browse Source

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

pull/231/head
Ruan 1 year ago
parent
commit
001236e76f
  1. 2
      .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

2
.gitignore

@ -8,3 +8,5 @@ main.exe
*.jpe *.jpe
src/pkged.go 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). to [SwaggerEditor](https://editor.swagger.io).
- Furthermore you can generate HTTP Client from this API using [openapi-generator](https://openapi-generator.tech/#try) - 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 | | Feature | Menu | Method | URL |
|---------|------------------------------|--------|-------------------------------| |---------|------------------------------|--------|-------------------------------|
| ✅ | Login with Scan QR | GET | /app/login | | ✅ | Login with Scan QR | GET | /app/login |
@ -111,6 +119,7 @@ You can fork or edit this source code !
| ✅ | Reconnect | GET | /app/reconnect | | ✅ | Reconnect | GET | /app/reconnect |
| ✅ | Devices | GET | /app/devices | | ✅ | Devices | GET | /app/devices |
| ✅ | User Info | GET | /user/info | | ✅ | User Info | GET | /user/info |
| ✅ | Check User is on whatsapp | GET | /user/check |
| ✅ | User Avatar | GET | /user/avatar | | ✅ | User Avatar | GET | /user/avatar |
| ✅ | User My Groups | GET | /user/my/groups | | ✅ | User My Groups | GET | /user/my/groups |
| ✅ | User My Newsletter | GET | /user/my/newsletters | | ✅ | 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) | | 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) | | 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) | | 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) | | 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 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) | | 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"` Phone string `json:"phone" query:"phone"`
} }
type CheckRequest struct {
Phone string `json:"phone" query:"phone"`
}
type InfoResponseDataDevice struct { type InfoResponseDataDevice struct {
User string User string
Agent uint8 Agent uint8
@ -21,10 +25,25 @@ type InfoResponseData struct {
Devices []InfoResponseDataDevice `json:"devices"` 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 { type InfoResponse struct {
Data []InfoResponseData `json:"data"` Data []InfoResponseData `json:"data"`
} }
type CheckResponse struct {
Data []CheckResponseData `json:"data"`
}
type UserCollection struct {
Users []CheckResponseData
}
type AvatarRequest struct { type AvatarRequest struct {
Phone string `json:"phone" query:"phone"` Phone string `json:"phone" query:"phone"`
IsPreview bool `json:"is_preview" query:"is_preview"` IsPreview bool `json:"is_preview" query:"is_preview"`

1
src/domains/user/user.go

@ -6,6 +6,7 @@ import (
type IUserService interface { type IUserService interface {
Info(ctx context.Context, request InfoRequest) (response InfoResponse, err error) 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) Avatar(ctx context.Context, request AvatarRequest) (response AvatarResponse, err error)
MyListGroups(ctx context.Context) (response MyListGroupsResponse, err error) MyListGroups(ctx context.Context) (response MyListGroupsResponse, err error)
MyListNewsletter(ctx context.Context) (response MyListNewsletterResponse, 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 { func InitRestUser(app *fiber.App, service domainUser.IUserService) User {
rest := User{Service: service} rest := User{Service: service}
app.Get("/user/info", rest.UserInfo) app.Get("/user/info", rest.UserInfo)
app.Get("/user/check", rest.UserCheck)
app.Get("/user/avatar", rest.UserAvatar) app.Get("/user/avatar", rest.UserAvatar)
app.Get("/user/my/privacy", rest.UserMyPrivacySetting) app.Get("/user/my/privacy", rest.UserMyPrivacySetting)
app.Get("/user/my/groups", rest.UserMyListGroups) 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 { func (controller *User) UserAvatar(c *fiber.Ctx) error {
var request domainUser.AvatarRequest var request domainUser.AvatarRequest
err := c.QueryParser(&request) 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 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) { func (service userService) Avatar(ctx context.Context, request domainUser.AvatarRequest) (response domainUser.AvatarResponse, err error) {
chanResp := make(chan domainUser.AvatarResponse) 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 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 { func ValidateUserAvatar(ctx context.Context, request domainUser.AvatarRequest) error {
err := validation.ValidateStructWithContext(ctx, &request, err := validation.ValidateStructWithContext(ctx, &request,
validation.Field(&request.Phone, validation.Required), 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"> <div class="ui three column doubling grid cards">
<account-avatar></account-avatar> <account-avatar></account-avatar>
<account-user-info></account-user-info> <account-user-info></account-user-info>
<account-user-check></account-user-check>
<account-privacy></account-privacy> <account-privacy></account-privacy>
</div> </div>
@ -158,6 +159,7 @@
import GroupAddParticipants from "./components/GroupManageParticipants.js"; import GroupAddParticipants from "./components/GroupManageParticipants.js";
import AccountAvatar from "./components/AccountAvatar.js"; import AccountAvatar from "./components/AccountAvatar.js";
import AccountUserInfo from "./components/AccountUserInfo.js"; import AccountUserInfo from "./components/AccountUserInfo.js";
import AccountUserCheck from "./components/AccountUserCheck.js";
import AccountPrivacy from "./components/AccountPrivacy.js"; import AccountPrivacy from "./components/AccountPrivacy.js";
import NewsletterList from "./components/NewsletterList.js"; import NewsletterList from "./components/NewsletterList.js";
@ -198,7 +200,7 @@
MessageDelete, MessageUpdate, MessageReact, MessageRevoke, MessageDelete, MessageUpdate, MessageReact, MessageRevoke,
GroupList, GroupCreate, GroupJoinWithLink, GroupAddParticipants, GroupList, GroupCreate, GroupJoinWithLink, GroupAddParticipants,
NewsletterList, NewsletterList,
AccountAvatar, AccountUserInfo, AccountPrivacy
AccountAvatar, AccountUserInfo, AccountUserCheck, AccountPrivacy
}, },
delimiters: ['[[', ']]'], delimiters: ['[[', ']]'],
data() { data() {

Loading…
Cancel
Save