| @@ -25,11 +25,6 @@ | |||||
| "type": "json", | "type": "json", | ||||
| "required": false | "required": false | ||||
| }, | }, | ||||
| "uuid": { | |||||
| "type": "uid", | |||||
| "targetField": "send_to", | |||||
| "required": false | |||||
| }, | |||||
| "attachment": { | "attachment": { | ||||
| "collection": "file", | "collection": "file", | ||||
| "via": "related", | "via": "related", | ||||
| @@ -47,6 +47,14 @@ | |||||
| "config": { | "config": { | ||||
| "policies": [] | "policies": [] | ||||
| } | } | ||||
| }, | |||||
| { | |||||
| "method": "POST", | |||||
| "path": "/initiate", | |||||
| "handler": "session-data.initiate", | |||||
| "config": { | |||||
| "policies": [] | |||||
| } | |||||
| } | } | ||||
| ] | ] | ||||
| } | } | ||||
| @@ -1,8 +1,67 @@ | |||||
| 'use strict'; | |||||
| const messageModel = require("../../../model/messageModel"); | |||||
| const { parseMultipartData, sanitizeEntity } = require("strapi-utils"); | |||||
| const { Client } = require("whatsapp-web.js"); | |||||
| /** | /** | ||||
| * Read the documentation (https://strapi.io/documentation/developer-docs/latest/concepts/controllers.html#core-controllers) | * Read the documentation (https://strapi.io/documentation/developer-docs/latest/concepts/controllers.html#core-controllers) | ||||
| * to customize this controller | * to customize this controller | ||||
| */ | */ | ||||
| module.exports = {}; | |||||
| module.exports = { | |||||
| initiate: async (ctx) => { | |||||
| ctx.respond = false; | |||||
| const { req, res } = ctx; | |||||
| res.setHeader("Content-Type", "text/html; charset=UTF-8"); | |||||
| res.setHeader("Transfer-Encoding", "chunked"); | |||||
| res.writeHead(200); | |||||
| messageModel.createNewClient(async function (data) { | |||||
| // console.log(data); | |||||
| var json = JSON.parse(data); | |||||
| if (json["STATUS"] == 1 && json["TYPE"] == "READY") { | |||||
| // console.log(json["DATA"]); | |||||
| let checkExist = await strapi | |||||
| .query("session-data") | |||||
| .findOne({ phonenumber: json["DATA"].wid.user }); | |||||
| if (checkExist) { | |||||
| // messageModel.loadClient(async function(data){ | |||||
| // let state = JSON.parse(data); | |||||
| // if (state["STATUS"] == 1 && state["TYPE"] == "READY"){ | |||||
| // let loaded = new Client(); | |||||
| // loaded = state["DATA"]; | |||||
| // await loaded.destroy(); | |||||
| // } | |||||
| // }); | |||||
| let id = checkExist.id; | |||||
| await strapi.services["session-data"].update({ id }, { | |||||
| name:json["DATA"].pushname, | |||||
| device_manufacturer:json["DATA"].phone.device_manufacturer, | |||||
| device_model:json["DATA"].phone.device_model, | |||||
| platform:json["DATA"].platform, | |||||
| os_version:json["DATA"].phone.os_version, | |||||
| phonenumber:json["DATA"].wid.user, | |||||
| session_data:json["DATA"].sessionData, | |||||
| }); | |||||
| } | |||||
| else { | |||||
| await strapi.services["session-data"].create({ | |||||
| name:json["DATA"].pushname, | |||||
| device_manufacturer:json["DATA"].phone.device_manufacturer, | |||||
| device_model:json["DATA"].phone.device_model, | |||||
| platform:json["DATA"].platform, | |||||
| os_version:json["DATA"].phone.os_version, | |||||
| phonenumber:json["DATA"].wid.user, | |||||
| session_data:json["DATA"].sessionData, | |||||
| }); | |||||
| // console.log(entry); | |||||
| } | |||||
| } | |||||
| res.write(data); | |||||
| if ( | |||||
| json["STATUS"] == 0 || | |||||
| (json["STATUS"] == 1 && json["TYPE"] == "READY") | |||||
| ) { | |||||
| return res.end(); | |||||
| } | |||||
| }); | |||||
| }, | |||||
| }; | |||||
| @@ -0,0 +1,13 @@ | |||||
| module.exports = { | |||||
| // | |||||
| graphql: { | |||||
| endpoint: '/graphql', | |||||
| shadowCRUD: true, | |||||
| playgroundAlways: true, | |||||
| depthLimit: 7, | |||||
| amountLimit: 100, | |||||
| apolloServer: { | |||||
| tracing: false, | |||||
| }, | |||||
| }, | |||||
| }; | |||||
| @@ -1,4 +1,4 @@ | |||||
| 'use strict'; | |||||
| "use strict"; | |||||
| /** | /** | ||||
| * Cron config that gives you an opportunity | * Cron config that gives you an opportunity | ||||
| @@ -11,11 +11,19 @@ | |||||
| */ | */ | ||||
| module.exports = { | module.exports = { | ||||
| /** | |||||
| * Simple example. | |||||
| * Every monday at 1am. | |||||
| */ | |||||
| // '0 1 * * 1': () => { | |||||
| // | |||||
| // } | |||||
| "*/3 * * * * *": async () => { | |||||
| const draftArticleToPublish = await strapi.api.message.services.message.find( | |||||
| { | |||||
| _sort: "send_from:desc", | |||||
| state: "QUEUE", | |||||
| } | |||||
| ); | |||||
| draftArticleToPublish.forEach(async (message) => { | |||||
| await strapi.api.message.services.message.update( | |||||
| { id: message.id }, | |||||
| { state: "SENT" } | |||||
| ); | |||||
| }); | |||||
| }, | |||||
| }; | }; | ||||
| @@ -1,9 +1,10 @@ | |||||
| module.exports = ({ env }) => ({ | module.exports = ({ env }) => ({ | ||||
| host: env('HOST', '0.0.0.0'), | |||||
| port: env.int('PORT', 1337), | |||||
| admin: { | |||||
| auth: { | |||||
| secret: env('ADMIN_JWT_SECRET', 'f4b5b7ba9c157b7f1f921ee91be34b8a'), | |||||
| }, | |||||
| }, | |||||
| host: env("HOST", "0.0.0.0"), | |||||
| port: env.int("PORT", 1337), | |||||
| admin: { | |||||
| auth: { | |||||
| secret: env("ADMIN_JWT_SECRET", "f4b5b7ba9c157b7f1f921ee91be34b8a"), | |||||
| }, | |||||
| }, | |||||
| cron: { enabled: true }, | |||||
| }); | }); | ||||
| @@ -0,0 +1,13 @@ | |||||
| module.exports = { | |||||
| apps : [{ | |||||
| name: "strapi", | |||||
| script: "index.js", | |||||
| exec_mode: "fork", | |||||
| env: { | |||||
| "NODE_ENV": "development", | |||||
| }, | |||||
| env_production : { | |||||
| "NODE_ENV": "production" | |||||
| } | |||||
| }] | |||||
| }; | |||||
| @@ -0,0 +1,4 @@ | |||||
| const strapi = require("strapi"); | |||||
| console.log("test starting script"); | |||||
| strapi(/* {...} */).start(); | |||||
| @@ -0,0 +1,218 @@ | |||||
| const qrcode = require("qrcode-terminal"); | |||||
| const fs = require("fs"); | |||||
| // const path = require("path"); | |||||
| const { Client } = require("whatsapp-web.js"); | |||||
| // const SESSION_FOLDER = path.join(__dirname, "../data/"); | |||||
| // const SESSION_FILE_PATH = path.join(__dirname, "../data/session.json"); | |||||
| // const sessions = require("../api/session_data"); | |||||
| const { parseMultipartData, sanitizeEntity } = require("strapi-utils"); | |||||
| var client; | |||||
| //Login Session when there is Session File | |||||
| function callbacks(client, callback,type="create") { | |||||
| let sessionData; | |||||
| client.on("auth_failure", (session) => { | |||||
| console.log("auth_failure"); | |||||
| // clearFileSession(phoneNumber); | |||||
| return callback( | |||||
| JSON.stringify({ | |||||
| STATUS: 0, | |||||
| TYPE: "AUTH_FAILURE", | |||||
| DATA: "SESSION HAS BEEN ENDED , PLEASE CREATE A NEW ONE !", | |||||
| }) | |||||
| ); | |||||
| }); | |||||
| client.on("disconnected", async function (session) { | |||||
| console.log("disconnected from loading"); | |||||
| if (session == "UNPAIRED") { | |||||
| try { | |||||
| if (client && client.info) { | |||||
| getID = await strapi | |||||
| .query("session-data") | |||||
| .findOne({ phonenumber: client.info.wid.user }); | |||||
| if (getID) { | |||||
| let id = getID["id"]; | |||||
| await strapi.query("session-data").delete({ id }); | |||||
| } | |||||
| } | |||||
| } catch (e) {} | |||||
| } | |||||
| }); | |||||
| client.on("ready", () => { | |||||
| var clientInfo = client.info; | |||||
| clientInfo["sessionData"] = sessionData; | |||||
| return callback( | |||||
| JSON.stringify({ | |||||
| STATUS: 1, | |||||
| TYPE: "READY", | |||||
| DATA: (type=="create")?clientInfo:client, | |||||
| }) | |||||
| ); | |||||
| }); | |||||
| client.on("message", async (msg) => { | |||||
| console.log("MESSAGE RECEIVED", msg.body); | |||||
| }); | |||||
| client.on("qr", (qr) => { | |||||
| return callback( | |||||
| JSON.stringify({ STATUS: 1, TYPE: "QR_AUTH", DATA: qr }) | |||||
| ); | |||||
| }); | |||||
| client.on("change_state", (state) => { | |||||
| console.log(`state => ${state}`); | |||||
| }); | |||||
| client.on("authenticated", (session) => { | |||||
| try { | |||||
| sessionData = session; | |||||
| // fs.writeFileSync(SESSION_FILE_PATH, JSON.stringify(session)); | |||||
| } catch (e) { | |||||
| return callback( | |||||
| JSON.stringify({ | |||||
| STATUS: 0, | |||||
| TYPE: "AUTHENTICATED_ERROR", | |||||
| DATA: e.message, | |||||
| }) | |||||
| ); | |||||
| } | |||||
| }); | |||||
| } | |||||
| var loadClient = async function (clientSessionData, callback) { | |||||
| try { | |||||
| // if(!client){ | |||||
| // console.log(client.info); | |||||
| // return callback({"STATUS" : 1 , "TYPE" : "READY" , "DATA" : client.info}) | |||||
| // } | |||||
| // let sessionPath = path.join(SESSION_FOLDER, `${phoneNumber}.json`); | |||||
| // if (fs.existsSync(sessionPath)) { | |||||
| // sessionData = require(sessionPath); | |||||
| client = new Client({ | |||||
| puppeteer: { | |||||
| args: ["--no-sandbox", "--disable-setuid-sandbox"], | |||||
| }, | |||||
| session: clientSessionData, | |||||
| restartOnAuthFail: true, | |||||
| }); | |||||
| callbacks(client, callback,"load"); | |||||
| console.log("initialize"); | |||||
| client.initialize(); | |||||
| } catch (e) { | |||||
| return callback({ | |||||
| STATUS: 0, | |||||
| TYPE: "ERROR", | |||||
| DATA: e.message, | |||||
| }); | |||||
| } | |||||
| }; | |||||
| var createNewClient = async function (callback) { | |||||
| try { | |||||
| client = new Client({ | |||||
| puppeteer: { | |||||
| args: ["--no-sandbox", "--disable-setuid-sandbox"], | |||||
| }, | |||||
| }); | |||||
| callbacks(client, callback); | |||||
| client.initialize(); | |||||
| //var clientInfo = await getClientInfo(); | |||||
| //return clientInfo; | |||||
| } catch (e) { | |||||
| return callback({ STATUS: 0, TYPE: "READY", DATA: e.message }); | |||||
| } | |||||
| }; | |||||
| var sendMessage = async function (phone_number, textMessage) { | |||||
| try { | |||||
| if (!client.info) { | |||||
| throw { message: "Client Is Not Ready !" }; | |||||
| } | |||||
| var phoneNumber = reformatMobilePhone(phone_number); | |||||
| // var state = await client.isRegisteredUser(phoneNumber); | |||||
| // console.log(state); | |||||
| await client.sendMessage(phoneNumber, textMessage); | |||||
| return { STATUS: 1, DATA: "Messages Succesfully send !" }; | |||||
| } catch (e) { | |||||
| return { STATUS: 0, DATA: e.message }; | |||||
| } | |||||
| }; | |||||
| var getClientInfo = function () { | |||||
| try { | |||||
| var a; | |||||
| while (!a) { | |||||
| a = client.info; | |||||
| } | |||||
| return { STATUS: 1, DATA: a }; | |||||
| } catch (e) { | |||||
| return { STATUS: 0, DATA: e.message }; | |||||
| } | |||||
| }; | |||||
| var getClientState = async function () { | |||||
| try { | |||||
| if (!client.info) { | |||||
| throw { message: "Client Is Not Ready !" }; | |||||
| } | |||||
| let state = await client.getState(); | |||||
| return { STATUS: 1, DATA: state }; | |||||
| } catch (e) { | |||||
| return { STATUS: 0, DATA: e.message }; | |||||
| } | |||||
| }; | |||||
| var destroySession = async function (phoneNumber) { | |||||
| try { | |||||
| if (client && client.info) { | |||||
| await client.logout(); | |||||
| await client.destroy(); | |||||
| clearFileSession(phoneNumber); | |||||
| return { STATUS: 1, DATA: "Session cleared" }; | |||||
| } else throw { message: "Client Is Not Ready !" }; | |||||
| } catch (e) { | |||||
| return { STATUS: 0, DATA: e.message }; | |||||
| } | |||||
| }; | |||||
| function reformatMobilePhone(phoneNumber) { | |||||
| var newPhoneNumber; | |||||
| if (phoneNumber[0].toString() == "0") { | |||||
| newPhoneNumber = "62" + phoneNumber.substring(1) + "@c.us"; | |||||
| } else if (phoneNumber[0] == "+") { | |||||
| newPhoneNumber = phoneNumber.substring(1) + "@c.us"; | |||||
| } else { | |||||
| newPhoneNumber = phoneNumber + "@c.us"; | |||||
| } | |||||
| return newPhoneNumber; | |||||
| } | |||||
| function clearFileSession(phoneNumber) { | |||||
| try { | |||||
| let sessionPath = path.join(SESSION_FOLDER, `${phoneNumber}.json`); | |||||
| if (fs.existsSync(sessionPath)) { | |||||
| console.log(`clearing session ${phoneNumber}`); | |||||
| fs.unlinkSync(sessionPath); | |||||
| } | |||||
| } catch (e) { | |||||
| throw e; | |||||
| } | |||||
| } | |||||
| module.exports = { | |||||
| sendMessage: sendMessage, | |||||
| createNewClient: createNewClient, | |||||
| loadClient: loadClient, | |||||
| getClientInfo: getClientInfo, | |||||
| destroySession: destroySession, | |||||
| getClientState: getClientState, | |||||
| getClientState: getClientState, | |||||
| }; | |||||
| @@ -13,6 +13,7 @@ | |||||
| "dependencies": { | "dependencies": { | ||||
| "knex": "<0.20.0", | "knex": "<0.20.0", | ||||
| "mysql": "latest", | "mysql": "latest", | ||||
| "qrcode-terminal": "^0.12.0", | |||||
| "strapi": "3.4.1", | "strapi": "3.4.1", | ||||
| "strapi-admin": "3.4.1", | "strapi-admin": "3.4.1", | ||||
| "strapi-connector-bookshelf": "3.4.1", | "strapi-connector-bookshelf": "3.4.1", | ||||
| @@ -22,7 +23,8 @@ | |||||
| "strapi-plugin-graphql": "3.4.1", | "strapi-plugin-graphql": "3.4.1", | ||||
| "strapi-plugin-upload": "3.4.1", | "strapi-plugin-upload": "3.4.1", | ||||
| "strapi-plugin-users-permissions": "3.4.1", | "strapi-plugin-users-permissions": "3.4.1", | ||||
| "strapi-utils": "3.4.1" | |||||
| "strapi-utils": "3.4.1", | |||||
| "whatsapp-web.js": "^1.12.0" | |||||
| }, | }, | ||||
| "author": { | "author": { | ||||
| "name": "A Strapi developer" | "name": "A Strapi developer" | ||||