UNPKG

@juzi/wechaty

Version:

Wechaty is a RPA SDK for Chatbot Makers.

346 lines 11.6 kB
/** * Wechaty Chatbot SDK - https://github.com/wechaty/wechaty * * @copyright 2016 Huan LI (李卓桓) <https://github.com/huan>, and * Wechaty Contributors <https://github.com/wechaty>. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ import { EventEmitter } from 'events'; import * as PUPPET from '@juzi/wechaty-puppet'; import { log } from '@juzi/wechaty-puppet'; import { retryPolicy, } from '../pure-functions/mod.js'; import { wechatifyMixin, } from '../user-mixins/wechatify.js'; import { validationMixin } from '../user-mixins/validation.js'; const MixinBase = wechatifyMixin(EventEmitter); /** * Send, receive friend request, and friend confirmation events. * * 1. send request * 2. receive request(in friend event) * 3. confirmation friendship(friend event) * * [Examples/Friend-Bot]{@link https://github.com/wechaty/wechaty/blob/1523c5e02be46ebe2cc172a744b2fbe53351540e/examples/friend-bot.ts} */ class FriendshipMixin extends MixinBase { id; static Type = PUPPET.types.Friendship; /** * @ignore */ static load(id) { const newFriendship = new this(id); return newFriendship; } /** * Search a Friend by phone or weixin. * * The best practice is to search friend request once per minute. * Remember not to do this too frequently, or your account may be blocked. * * @param {FriendshipSearchCondition} condition - Search friend by phone or weixin. * @returns {Promise<ContactInterface>} * * @example * const friend_phone = await bot.Friendship.search({phone: '13112341234'}) * const friend_weixin = await bot.Friendship.search({weixin: 'weixin_account'}) * * console.log(`This is the new friend info searched by phone : ${friend_phone}`) * await bot.Friendship.add(friend_phone, 'hello') * */ static async search(queryFilter, type) { log.verbose('Friendship', 'static search("%s")', JSON.stringify(queryFilter)); if (typeof (type) === 'undefined') { type = PUPPET.types.Contact.Individual; } const contactId = await this.wechaty.puppet.friendshipSearch(queryFilter, type); if (!contactId) { return undefined; } const contact = await this.wechaty.Contact.find({ id: contactId }); return contact; } /** * Send a Friend Request to a `contact` with message `hello`. * * The best practice is to send friend request once per minute. * Remeber not to do this too frequently, or your account may be blocked. * * @param {ContactInterface} contact - Send friend request to contact * @param {FriendshipAddOptions} options - The friend request content * @returns {Promise<void>} * * @example * const contact = await bot.Friendship.search({phone: '13112341234'}) * await bot.Friendship.add(contact, 'Nice to meet you! I am wechaty bot!') * * const memberList = await room.memberList() * for (let i = 0; i < memberList.length; i++) { * await bot.Friendship.add(member, { * room: room, * hello: `Nice to meet you! I am wechaty bot from room: ${await room.topic()}!`, * }) * } * */ static async add(contact, options) { log.verbose('Friendship', 'static add(%s, %s)', contact.id, typeof options === 'string' ? options : options.hello); if (typeof options === 'string') { log.warn('Friendship', 'the params hello is deprecated in the next version, please put the attr hello into options object, e.g. { hello: "xxxx" }'); await this.wechaty.puppet.friendshipAdd(contact.id, { hello: options }); } else { const friendOption = { contactId: options.contact?.id, hello: options.hello, roomId: options.room && options.room.id, }; await this.wechaty.puppet.friendshipAdd(contact.id, friendOption); } } static async del(contact) { log.verbose('Friendship', 'static del(%s)', contact.id); throw new Error('to be implemented'); } /** * * Instance Properties * */ /** * @ignore */ payload; /* * @hideconstructor */ constructor(id) { super(); this.id = id; log.verbose('Friendship', 'constructor(id=%s)', id); } toString() { if (!this.payload) { return this.constructor.name; } return [ 'Friendship#', PUPPET.types.Friendship[this.payload.type], '<', this.payload.contactId, '>', ].join(''); } isReady() { return !!this.payload && (Object.keys(this.payload).length > 0); } /** * no `dirty` support because Friendship has no rawPayload(yet) * @ignore */ async ready() { if (this.isReady()) { return; } this.payload = await this.wechaty.puppet.friendshipPayload(this.id); // if (!this.#payload) { // throw new Error('no payload') // } await this.contact().ready(); } /** * Accept Friend Request * * @returns {Promise<void>} * * @example * const bot = new Wechaty() * bot.on('friendship', async friendship => { * try { * console.log(`received friend event.`) * switch (friendship.type()) { * * // 1. New Friend Request * * case Friendship.Type.Receive: * await friendship.accept() * break * * // 2. Friend Ship Confirmed * * case Friendship.Type.Confirm: * console.log(`friend ship confirmed`) * break * } * } catch (e) { * console.error(e) * } * } * .start() */ async accept() { log.verbose('Friendship', 'accept()'); if (!this.payload) { throw new Error('no payload'); } if (this.payload.type !== PUPPET.types.Friendship.Receive) { throw new Error('accept() need type to be FriendshipType.Receive, but it got a ' + FriendshipImpl.Type[this.payload.type]); } log.silly('Friendship', 'accept() to %s', this.payload.contactId); await this.wechaty.puppet.friendshipAccept(this.id); const contact = this.contact(); try { const doSync = async () => { await contact.ready(); if (!contact.isReady()) { throw new Error('Friendship.accept() contact.ready() not ready'); } log.verbose('Friendship', 'accept() with contact %s ready()', contact.name()); }; await retryPolicy.execute(doSync); } catch (e) { this.wechaty.emitError(e); log.warn('Friendship', 'accept() contact %s not ready because of %s', contact, (e && e.message) || e); // console.error(e) } // try to fix issue #293 - https://github.com/wechaty/wechaty/issues/293 await contact.sync(); } /** * Get verify message from * * @returns {string} * @example <caption>If request content is `ding`, then accept the friendship</caption> * const bot = new Wechaty() * bot.on('friendship', async friendship => { * try { * console.log(`received friend event from ${friendship.contact().name()}`) * if (friendship.type() === Friendship.Type.Receive && friendship.hello() === 'ding') { * await friendship.accept() * } * } catch (e) { * console.error(e) * } * } * .start() */ hello() { if (!this.payload) { throw new Error('no payload'); } return this.payload.hello || ''; } /** * Get the contact from friendship * * @returns {ContactInterface} * @example * const bot = new Wechaty() * bot.on('friendship', async friendship => { * const contact = friendship.contact() * const name = contact.name() * console.log(`received friend event from ${name}`) * } * .start() */ contact() { if (!this.payload) { throw new Error('no payload'); } const contact = this.wechaty.Contact.load(this.payload.contactId); return contact; } /** * Return the Friendship Type * > Tips: FriendshipType is enum here. </br> * - FriendshipType.Unknown </br> * - FriendshipType.Confirm </br> * - FriendshipType.Receive </br> * - FriendshipType.Verify </br> * * @returns {FriendshipType} * * @example <caption>If request content is `ding`, then accept the friendship</caption> * const bot = new Wechaty() * bot.on('friendship', async friendship => { * try { * if (friendship.type() === Friendship.Type.Receive && friendship.hello() === 'ding') { * await friendship.accept() * } * } catch (e) { * console.error(e) * } * } * .start() */ type() { return this.payload ? this.payload.type : PUPPET.types.Friendship.Unknown; } /** * get friendShipPayload Json * @returns {FriendshipPayload} * * @example * const bot = new Wechaty() * bot.on('friendship', async friendship => { * try { * // JSON.stringify(friendship) as well. * const payload = await friendship.toJSON() * } catch (e) { * console.error(e) * } * } * .start() */ toJSON() { log.verbose('Friendship', 'toJSON()'); if (!this.isReady()) { throw new Error(`Friendship<${this.id}> needs to be ready. Please call ready() before toJSON()`); } return JSON.stringify(this.payload); } /** * create friendShip by friendshipJson * @example * const bot = new Wechaty() * bot.start() * * const payload = '{...}' // your saved JSON payload * const friendship = bot.FriendShip.fromJSON(friendshipFromDisk) * await friendship.accept() */ static async fromJSON(payload) { log.verbose('Friendship', 'static fromJSON(%s)', typeof payload === 'string' ? payload : JSON.stringify(payload)); if (typeof payload === 'string') { payload = JSON.parse(payload); } /** * Set the payload back to the puppet for future use */ await this.wechaty.puppet.friendshipPayload(payload.id, payload); const instance = this.wechaty.Friendship.load(payload.id); await instance.ready(); return instance; } } class FriendshipImpl extends validationMixin(FriendshipMixin)() { } export { FriendshipImpl, }; //# sourceMappingURL=friendship.js.map