friendship.ts 6.2 KB
Newer Older
1
/**
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
2
 *   Wechaty - https://github.com/chatie/wechaty
3
 *
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
4
 *   @copyright 2016-2018 Huan LI <zixia@zixia.net>
5
 *
6 7 8
 *   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
9
 *
10 11 12 13 14 15 16
 *       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.
L
lijiarui 已提交
17
 *   @ignore
18 19 20
 *
 */

21
 /* tslint:disable:no-var-requires */
22
// const retryPromise  = require('retry-promise').default
23 24 25
import {
  instanceToClass,
}                   from 'clone-class'
26

27 28 29 30 31 32
import {
  Accessory,
}                   from './accessory'
import {
  Contact,
}                   from './contact'
33 34
import {
  log,
35 36 37 38
}                   from './config'
import {
  Misc,
}                   from './misc'
39

40 41 42 43
import {
  FriendRequestPayload,
  FriendRequestType,
}                         from './puppet/'
44

L
lijiarui 已提交
45 46 47 48 49 50 51
/**
 * Send, receive friend request, and friend confirmation events.
 *
 * 1. send request
 * 2. receive request(in friend event)
 * 3. confirmation friendship(friend event)
 *
52
 * [Examples/Friend-Bot]{@link https://github.com/Chatie/wechaty/blob/master/examples/friend-bot.ts}
L
lijiarui 已提交
53
 */
54
export class FriendRequest extends Accessory {
55

Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
56 57 58
  // tslint:disable-next-line:variable-name
  public static Type = FriendRequestType

59
  public static load<T extends typeof FriendRequest>(
60 61
    this : T,
    id   : string,
62 63
  ): T['prototype'] {
    const newFriendRequest = new (this as any)(id)
64
    // newFriendRequest.payload = this.puppet.cacheFriendRequestPayload.get(id)
65 66 67
    return newFriendRequest
  }

68 69 70 71 72
  /**
   * Send a Friend Request to a `contact` with message `hello`.
   * @param contact
   * @param hello
   */
73
  public static async send(
74 75
    contact : Contact,
    hello   : string,
76
  ): Promise<void> {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
77 78 79
    log.verbose('FriendRequest', 'static send(%s, %s)',
                                  contact.id,
                                  hello,
80
                )
81
    await this.puppet.friendRequestSend(contact.id, hello)
82 83
  }

84 85 86
  // public static createConfirm(
  //   contactId: string,
  // ): FriendRequestPayload {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
87
  //   log.verbose('FriendRequest', 'createConfirm(%s)',
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
  //                                         contactId,
  //               )

  //   const payload: FriendRequestPayloadConfirm = {
  //     type : FriendRequestType.Confirm,
  //     contactId,
  //   }

  //   return payload
  // }

  // public static createReceive(
  //   contactId : string,
  //   hello     : string,
  //   ticket    : string,
  // ): FriendRequestPayload {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
104
  //   log.verbose('FriendRequest', 'createReceive(%s, %s, %s)',
105 106 107 108 109 110 111 112 113 114 115 116 117 118
  //                                         contactId,
  //                                         hello,
  //                                         ticket,
  //               )

  //   const payload: FriendRequestPayloadReceive = {
  //     type : FriendRequestType.Receive,
  //     contactId,
  //     hello,
  //     ticket,
  //   }

  //   return payload
  // }
119

120 121 122 123 124
  /**
   *
   * Instance Properties
   *
   */
125

126
  protected get payload(): undefined | FriendRequestPayload {
127 128 129 130
    if (!this.id) {
      return undefined
    }

131 132
    return this.puppet.friendRequestPayloadCache(this.id)
  }
133

134
  constructor(
135
    public id: string,
136 137
  ) {
    super()
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
138
    log.verbose('FriendRequest', 'constructor(id=%s)', id)
139 140 141 142 143 144 145 146 147 148 149

    // tslint:disable-next-line:variable-name
    const MyClass = instanceToClass(this, FriendRequest)

    if (MyClass === FriendRequest) {
      throw new Error('FriendRequest class can not be instanciated directly! See: https://github.com/Chatie/wechaty/issues/1217')
    }

    if (!this.puppet) {
      throw new Error('FriendRequest class can not be instanciated without a puppet!')
    }
150 151
  }

152 153
  public toString() {
    if (!this.payload) {
154
      return this.constructor.name
155
    }
156 157 158 159 160 161 162
    return [
      'FriendRequest#',
      FriendRequestType[this.payload.type],
      '<',
      this.payload.contactId,
      '>',
    ].join('')
163 164
  }

165 166 167 168 169 170 171 172 173 174 175 176
  public isReady(): boolean {
    return !!this.payload && (Object.keys(this.payload).length > 0)
  }

  /**
   * no `noCache` support because FriendRequest has no rawPayload(yet)
   */
  public async ready(): Promise<void> {
    if (this.payload) {
      return
    }

177
    await this.puppet.friendRequestPayload(this.id)
178

179 180 181 182 183 184
    if (!this.payload) {
      throw new Error('no payload')
    }
  }

  public async accept(): Promise<void> {
185 186
    log.verbose('FriendRequest', 'accept()')

187 188 189 190
    if (!this.payload) {
      throw new Error('no payload')
    }

191 192 193
    if (this.payload.type !== FriendRequest.Type.Receive) {
      throw new Error('accept() need type to be FriendRequestType.Receive, but it got a ' + FriendRequest.Type[this.payload.type!])
    }
194

195
    log.silly('FriendRequest', 'accept() to %s', this.payload.contactId)
196

197
    await this.puppet.friendRequestAccept(this.id)
198

199
    const contact = this.contact()
200 201

    await Misc.retry(async (retry, attempt) => {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
202
      log.silly('FriendRequest', 'accept() retry() ready() attempt %d', attempt)
203

204
      await contact.ready()
205

206
      if (contact.isReady()) {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
207
        log.verbose('FriendRequest', 'accept() with contact %s ready()', contact.name())
208 209
        return
      }
210
      retry(new Error('FriendRequest.accept() content.ready() not ready'))
211 212

    }).catch((e: Error) => {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
213
      log.warn('FriendRequest', 'accept() contact %s not ready because of %s', contact, e && e.message || e)
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
    })

  }

  public hello(): string {
    if (!this.payload) {
      throw new Error('no payload')
    }
    return this.payload.hello || ''
  }

  public contact(): Contact {
    if (!this.payload) {
      throw new Error('no payload')
    }
229

230
    const contact = this.wechaty.Contact.load(this.payload.contactId)
231
    return contact
232
  }
233

234
  public async reject(): Promise<void> {
Huan (李卓桓)'s avatar
Huan (李卓桓) 已提交
235
    log.warn('FriendRequest', 'reject() not necessary, NOP.')
236 237
    return
  }
238

239
  public type(): FriendRequestType {
240 241 242
    return this.payload
            ? this.payload.type
            : FriendRequestType.Unknown
243
  }
244 245

}
Huan (李卓桓)'s avatar
merge  
Huan (李卓桓) 已提交
246 247

export default FriendRequest