Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

appear bug when logout use padchat #1559

Closed
xiamao opened this issue Aug 17, 2018 · 0 comments
Closed

appear bug when logout use padchat #1559

xiamao opened this issue Aug 17, 2018 · 0 comments

Comments

@xiamao
Copy link

xiamao commented Aug 17, 2018

Provide Your Network Information

  1. Where is the location of your server? (i.e. City, or In/Out China) BeiJing
  2. Which cloud platform(AliYun/Qcloud/DigitalOcean/etc) are you using?
    AliYun docker

Expected behavior

1\logout but keep the docker(bot) instance alive
2\PS want get some single when the wechat login other platform such as mac os

Actual behavior

1\some bug appear and the docker exit
2\ can not get anything about the wechat login at other platform

Full Output Logs

Paste the full output logs here with WECHATY_LOG=silly set

# PASTE FULL LOG OUTPUT AT HERE:
9:19:50 SILL PadchatRpc initWebSocket() ws.on(message): {"type":-1,"msg":"掉线了"}
09:19:50 VERB PadchatRpc onSocket(payload.type=Logout) logout, payload=-1({"type":-1,"msg":"掉线了"})
09:19:50 VERB PadchatRpc reset(掉线了)
09:19:50 WARN PuppetPadchat startManager() manager.on(reset) for 掉线了. Restarting PuppetPadchat ...
09:19:50 SILL Puppet constructor() this.on(reset) reason: 掉线了
09:19:50 SILL Puppet constructor() resetThrottleQueue.subscribe() reason: 掉线了
09:19:50 VERB Puppet reset(掉线了)
09:19:50 SILL StateSwitch <PuppetPadchat> off() is false
09:19:50 VERB PuppetPadchat stop()
09:19:50 SILL StateSwitch <PuppetPadchat> off() is false
09:19:50 SILL StateSwitch <PuppetPadchat> off() is false
09:19:50 VERB StateSwitch <PuppetPadchat> off(pending) <- (false)
09:19:50 VERB PuppetPadchat logout()
09:19:50 SILL Contact ready() @ Puppet#0<PuppetPadchat>(12345)/PuppetPadchat#0
09:19:50 SILL Contact ready() isReady() true
09:19:50 VERB PuppetPadchatManager logout()
09:19:50 VERB PuppetPadchatManager releaseCache()
09:19:50 SILL PuppetPadchatManager releaseCache() closing caches ...
09:19:50 VERB ContactSelf name()
xiamao logouted
09:19:50 VERB MemoryCard <12345> save() to StorageFile</bot/12345.memory-card.json>
09:19:50 VERB StorageFile save() to /bot/12345.memory-card.json
/wechaty/bin/entrypoint.sh: line 174:    27 Segmentation fault      (core dumped) ts-node --type-check "$@"
  ____  _   _  ____   ____  _____ ____   ___  ____ _____
 | __ )| | | |/ ___| |  _ \| ____|  _ \ / _ \|  _ \_   _|
 |  _ \| | | | |  _  | |_) |  _| | |_) | | | | |_) || |
 | |_) | |_| | |_| | |  _ <| |___|  __/| |_| |  _ < | |
 |____/ \___/ \____| |_| \_\_____|_|    \___/|_| \_\|_|



### 1. source code of examples/test_sender.ts

/**
 *  martech wx-bot template script, need a token arg from backend
 *  first arg is token next is this bot's ref_uuid for unique
 *
 */
import {
    //   config,
    Contact,
    Message,
    Wechaty,
    Room,
} from 'wechaty'

import {
    PuppetPadchat
} from 'wechaty-puppet-padchat'

import { generate } from 'qrcode-terminal'
import * as http from 'http'
import * as https from 'https'


//  get the args from python server
const remoteHost = ''
const localHost = ''
const localPort = 1134
const argvs = process.argv;
/**
 *
 * 1. declare a bot
 *
 */
// set the token get from python server
const WECHATY_PUPPET_PADCHAT_TOKEN = argvs[2];
const puppet = new PuppetPadchat({
    token: WECHATY_PUPPET_PADCHAT_TOKEN,
})
// set the padchat puppet
const bot = new Wechaty({
    profile: argvs[3],
    puppet,
})


/**
 *
 * 2. Register event handlers for Bot
 *
 */
bot
    .on('logout', onLogout)
    .on('login', onLogin)
    .on('scan', onScan)
    .on('error', onError)
    .on('message', onMessage)
    .on('room-topic', onRoomTopic)

/**
 *
 * 3. start bot
 *
 */
bot.start()
    .catch(async e => {
        console.error('Bot start() fail:', e)
        await bot.stop()
        process.exit(-1)
    })


function loopGetCMD() {
    // const req = http.get(', function (res: any) {
    const req = http.get('d=' + argvs[3], function (res: any) {
        res.setEncoding('utf8');
        res.on('data', async function (chunk: any) {
            console.log('BODY: ' + chunk);
            let jsonChunkData = JSON.parse(chunk);
            // process this chunk if type 1: return the roomList 2: send message 3: get friendList
            switch (jsonChunkData['data']['name']) {
                // stop this bot
                case 'stop':
                    bot.stop();
                    // http.get('http://\?bot_uuid=' + argvs[3]);
                    http.get('d=' + argvs[3])
                    break;
                // get the room list
                case 'get_rooms':
                    console.log('get rooms');
                    //   const roomList = await bot.Room.findAll();
                    let contactList = await bot.Contact.findAll();
                    let path = '/v1/bot/receive/robot/contacts';
                    let data = {
                        bot_uuid: argvs[3],
                        contactList: contactList
                    }
                    postData(path, data, remoteHost, true, false)
                    let roomList = await bot.Room.findAll();
                    let datar = {
                        bot_uuid: argvs[3],
                        roomList: roomList
                    }
                    postData(path, datar, remoteHost, true, false);
                    break;
                case 'send':
                    console.log('send message to somebody');
                    //sender.say(msg);

            }
        });
    });
    req.on('error', function (e: any) {
        console.log('problem with request: ' + e.message);
    });
    req.end();
}
// request the bot-server to get the cmd of this bot to get something for front
// function test(){
// console.log('dadfadfadf');
// }
setTimeout(() => {
    setInterval(loopGetCMD, 2000);
}, 30000);


/**
 *
 * 4. Define Event Handler Functions for:
 *  `scan`, `login`, `logout`, `error`, and `message`
 *
 */
function onScan(qrcode: string, status: number) {
    generate(qrcode, { small: true })
    const qrcodeImageUrl = [
        'https://api.qrserver.com/v1/create-qr-code/?data=',
        encodeURIComponent(qrcode),
    ].join('')
    const data = {
        ref_uuid: argvs[3],
        url: qrcode,
    }
    console.log(qrcode)
    const path = '/post/bot/qrcode';
    postData(path, data, localHost, false, localPort);
    console.log(`[${status}] ${qrcodeImageUrl}\nScan QR Code above to log in: `)
}

async function onLogin(user: Contact) {
    console.log(`${user.name()} login`);
    console.log(user);
    console.log(user.avatar())
    //post userprofile
    const data = {
        profile: {
            id: user.id,
            name: user.name(),
            avatar: user.avatar()
        },
        ref_uuid: argvs[3],
        //     key: argvs[2]
    }
    const path = '/post/bot/profile'
    postData(path, data, localHost, false, localPort)
}

function onLogout(user: Contact) {
    const data = {
        bot_uuid: argvs[3]
    }
    const path = '/update/status';
    postData(path, data, localHost, false, localPort)
    console.log(`${user.name()} logouted`);
}

function onError(e: Error) {
    console.error('Bot error:', e)
    /*
    if (bot.logonoff()) {
      bot.say('Wechaty error: ' + e.message).catch(console.error)
    }
    */
}

/**
 *
 * 5. The most important handler is for:
 *    dealing with Messages.
 *
 */
async function onMessage(msg: Message) {
    console.log(msg.toString())

    if (msg.age() > 60) {
        console.log('Message discarded because its TOO OLD(than 1 minute)')
        return
    }
    const room = msg.room();
    const contactTo = msg.to();
    const contactFrom = msg.from();
    const data = {
        msgType: msg.type(),
        msgRoom: room,
        msgText: msg.text(),
        msgTo: contactTo,
        msgFrom: contactFrom,
        msgSendTime: msg.date(),
        mentionList: msg.mention(),
        botId: msg.puppet.selfId()
    }
    const options = {
        host: 'mtkbase.xiaolizhuli.com',
        path: '/v1/bot/post/msg',
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        }
    }
    const req = https.request(options);
    req.on('error', function (e: any) {
        console.log('problem with request: ' + e.message);
    });
    req.write(JSON.stringify(data));
    req.end();
    console.log(data.msgText, data.msgTo, data.msgFrom, data.msgRoom, data.msgType)

}

/**
 * 6.add the room topic change event, to push to the server change the mysql.
 */
async function onRoomTopic(room: Room, topic: any, oldTopic: any, changer: Contact) {
    try {
        console.log('Bot', 'EVENT: room-topic - Room "%s" change topic from "%s" to "%s" by member "%s"',
            room,
            oldTopic,
            topic,
            changer,
        );
        let data = {
            changer: changer,
            room: room,
            topic: topic
        };
        let path = "/receive/room/topic/change";
        postData(path, data, remoteHost, true, false);
        // await room.say(`room-topic - change topic from "${oldTopic}" to "${topic}" by member "${changer.name()}"`)
    } catch (e) {
        console.log('Bot', 'room-topic event exception: %s', e.stack)
    }
}
// define a function for post data
function postData(path: any, data: any, host: any, isHttps: boolean, Port: any) {
    const options = Port ? {
        host: host,
        path: path,
        method: 'POST',
        port: Port,
        headers: {
            'Content-Type': 'application/json',
        }
    } : {
            host: host,
            path: path,
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            }
        }
    let req = isHttps ? https.request(options) : http.request(options);
    req.on('error', function (e: any) {
        console.log('problem with request: ' + e.message);
    });
    req.write(JSON.stringify(data));
    req.end();

}


### 2. directory structor of /bot

total 144084
-rw-r--r--   1 root root     60081 Aug 17 08:40 03674b1e-aa86-4b5f-942c-1f7108f2b49c.log
-rw-r--r--   1 root root         0 Aug 17 08:40 03674b1e-aa86-4b5f-942c-1f7108f2b49c.memory-card.json
-rw-r--r--   1 root root         0 Aug 17 09:19 12345.memory-card.json
-rw-r--r--   1 root root       113 Aug 17 06:21 AUTHORS
-rw-r--r--   1 root root     79506 Aug 17 06:22 CHANGELOG.md
-rw-r--r--   1 root root       187 Aug 17 06:21 CODEOWNERS
-rw-r--r--   1 root root      3210 Aug 17 06:21 CODE_OF_CONDUCT.md
-rw-r--r--   1 root root      1147 Aug 17 06:21 CONTRIBUTING.md
-rw-r--r--   1 root root      3797 Aug 17 06:21 Dockerfile
-rw-r--r--   1 root root      2677 Aug 17 06:21 Dockerfile.alpine
-rw-r--r--   1 root root       299 Aug 17 06:21 Dockerfile.onbuild
-rw-r--r--   1 root root     11360 Aug 17 06:21 LICENSE
-rw-r--r--   1 root root     12304 Aug 17 06:22 README.md
-rw-r--r--   1 root root        40 Aug 17 06:21 TODO.md
-rw-r--r--   1 root root       812 Aug 17 06:21 app.json
-rw-r--r--   1 root root       829 Aug 17 06:21 appveyor.yml
drwxr-xr-x   2 root root      4096 Aug 17 06:22 bin
-rw-------   1 root root 254115840 Aug 17 09:19 core
-rw-r--r--   1 root root         0 Aug 17 09:17 default.memory-card.json
drwxr-xr-x   3 root root      4096 Aug 17 06:22 docs
drwxr-xr-x   2 root root      4096 Aug 17 08:50 examples
drwxr-xr-x 218 root root     12288 Aug 17 08:13 node_modules
-rw-r--r--   1 root root    864804 Aug 17 07:39 npm-debug.log
-rw-r--r--   1 root root     62372 Aug 17 08:13 package-lock.json
-rw-r--r--   1 root root      5404 Aug 17 08:13 package.json
drwxr-xr-x   2 root root      4096 Aug 17 06:21 scripts
-rw-r--r--   1 root root      1777 Aug 17 06:22 shippable.yml
drwxr-xr-x   4 root root      4096 Aug 17 06:22 src
drwxr-xr-x   3 root root      4096 Aug 17 06:21 tests
-rw-r--r--   1 root root      1130 Aug 17 06:21 tsconfig.json
-rw-r--r--   1 root root       453 Aug 17 06:21 tslint.json
-rw-r--r--   1 root root      1245 Aug 17 06:21 wercker.yml

### 3. package.json

{
  "name": "wechaty",
  "version": "0.19.139",
  "description": "Wechaty is a Bot SDK for Wechat Personal Account",
  "main": "dist/src/index.js",
  "typings": "dist/src/index.d.ts",
  "wechaty": {
    "DEFAULT_HEAD": 0,
    "DEFAULT_PORT": 8080,
    "DEFAULT_PROFILE": "default",
    "DEFAULT_PROTOCOL": "io|0.0.1",
    "DEFAULT_TOKEN": "WECHATY_IO_TOKEN",
    "DEFAULT_APIHOST": "api.chatie.io"
  },
  "scripts": {
    "clean": "shx rm -fr dist/*",
    "dist": "npm run clean && tsc",
    "pack": "npm pack",
    "doc": "bash -x scripts/generate-docs.sh",
    "coverage": "nyc report --reporter=text-lcov | coveralls",
    "changelog": "github_changelog_generator -u chatie -p wechaty && sed -i'.bak' /greenkeeper/d CHANGELOG.md && sed -i'.bak' '/An in-range update of/d' CHANGELOG.md && ts-node scripts/sort-contributiveness.ts < CHANGELOG.md > CHANGELOG.new.md 2>/dev/null && cat CHANGELOG.md >> CHANGELOG.new.md && mv CHANGELOG.new.md CHANGELOG.md",
    "doctor": "npm run check-node-version && ts-node bin/doctor",
    "check-node-version": "check-node-version --node \">= 10\"",
    "lint": "npm run check-node-version && npm run lint:ts && npm run lint:sh",
    "lint:md": "markdownlint README.md",
    "lint:ts": "tslint --project tsconfig.json && tsc --noEmit",
    "lint:sh": "bash -n bin/*.sh",
    "puppet-install": "ts-node bin/puppet-install.ts",
    "sloc": "sloc bin examples scripts src tests --details --format cli-table --keys total,source,comment && sloc bin examples scripts src tests",
    "ts-node": "ts-node",
    "test": "npm run lint && npm run test:unit && npm run test:shell && npm run sloc",
    "test:pack": "bash -x scripts/npm-pack-testing.sh",
    "test:shell": "shellcheck bin/*.sh",
    "test:unit": "blue-tape -r ts-node/register \"src/**/*.spec.ts\" \"src/*.spec.ts\" \"tests/*.spec.ts\" \"tests/**/*.spec.ts\"",
    "test:unit:retry": "ts-node scripts/retry-unit-tests",
    "test:debug": "blue-tape -r ts-node/register src/puppet-web/bridge.spec.ts",
    "typedoc": "bash scripts/typedoc.sh",
    "io-client": "ts-node bin/io-client",
    "demo": "ts-node examples/ding-dong-bot.ts",
    "start": "npm run demo"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/chatie/wechaty.git"
  },
  "bin": {
    "wechaty-doctor": "dist/bin/doctor.js",
    "wechaty-io-client": "dist/bin/io-client.js",
    "wechaty-puppet-install": "dist/bin/puppet-install.js",
    "wechaty-version": "dist/bin/version.js"
  },
  "keywords": [
    "wechat",
    "微信",
    "weixin",
    "personal",
    "bot",
    "robot",
    "chatbot",
    "framework",
    "sdk",
    "wechaty",
    "chatie",
    "微信控"
  ],
  "author": {
    "name": "Huan LI",
    "email": "[email protected]",
    "url": "https://www.zixia.net"
  },
  "license": "Apache-2.0",
  "bugs": {
    "url": "https://github.com/chatie/wechaty/issues"
  },
  "homepage": "https://chatie.io/wechaty/",
  "engines": {
    "node": ">= 10"
  },
  "dependencies": {
    "brolog": "^1.8.1",
    "clone-class": "^0.6.11",
    "cuid": "^2.1.1",
    "file-box": "^0.8.23",
    "hot-import": "^0.2.1",
    "memory-card": "^0.5.5",
    "n": "^2.1.12",
    "npm-programmatic": "0.0.11",
    "pkg-dir": "^3.0.0",
    "promise-retry": "^1.1.1",
    "qr-image": "^3.2.0",
    "raven": "^2.6.2",
    "read-pkg-up": "^4.0.0",
    "state-switch": "^0.6.2",
    "watchdog": "^0.8.1",
    "wechaty-puppet": "^0.11.3",
    "wechaty-puppet-padchat": "^0.9.32",
    "ws": "^6.0.0"
  },
  "devDependencies": {
    "@babel/core": "^7.0.0-beta.51",
    "@babel/node": "^7.0.0-beta.51",
    "@babel/preset-env": "^7.0.0-beta.51",
    "@types/blessed": "^0.1.10",
    "@types/blue-tape": "^0.1.0",
    "@types/cuid": "^1.3.0",
    "@types/fluent-ffmpeg": "^2.1.0",
    "@types/fs-extra": "^5.0.3",
    "@types/glob": "^5.0.0p",
    "@types/mime": "^2.0.0",
    "@types/node": "^10.3.0",
    "@types/pkg-dir": "^2.0.0",
    "@types/promise-retry": "^1.1.1",
    "@types/qr-image": "^3.2.1",
    "@types/raven": "^2.1.0",
    "@types/read-pkg-up": "^3.0.1",
    "@types/request": "^2.47.1",
    "@types/semver": "^5.5.0",
    "@types/sinon": "^5.0.0",
    "@types/ws": "^5.1.0",
    "apiai": "^4.0.0",
    "blessed": "^0.1.81",
    "blessed-contrib": "^4.8.5",
    "blue-tape": "^1.0.0",
    "check-node-version": "^3.0.0",
    "coveralls": "^3.0.0",
    "cross-env": "^5.1.6",
    "finis": "^0.4.1",
    "fluent-ffmpeg": "^2.1.0",
    "git-scripts": "git+https://github.com/nkzawa/git-scripts.git",
    "gl-matrix": "^2.6.1",
    "glob": "^7.1.0",
    "jsdoc-to-markdown": "^4.0.0",
    "markdownlint-cli": "^0.12.0",
    "nyc": "^12.0.1",
    "qrcode-terminal": "^0.12.0",
    "request": "^2.87.0",
    "semver": "^5.5.0",
    "shx": "^0.3.0",
    "sinon": "^6.0.0",
    "sloc": "^0.2.0",
    "ts-node": "^7.0.0",
    "tslint": "^5.11.0",
    "tslint-config-standard": "^7.0.0",
    "tuling123-client": "^0.0.2",
    "typedoc": "^0.11.1",
    "typescript": "^3.1.0-dev.20180731",
    "wechaty-puppet-mock": "^0.8.6"
  },
  "files_comment__whitelist_npm_publish": "http://stackoverflow.com/a/8617868/1123955",
  "files": [
    "CHANGELOG",
    "LICENSE",
    "README.md",
    "package.json",
    "bin",
    "dist/bin",
    "dist/index.*",
    "dist/src",
    "src"
  ],
  "git": {
    "scripts": {
      "pre-push": "./scripts/pre-push.sh"
    }
  },
  "publishConfig": {
    "access": "public",
    "tag": "latest"
  }
}

### 4. directory structor inside /bot/node_modules

@babel
abstract-leveldown
ajv
ansi-regex
app-root-path
aproba
are-we-there-yet
array-flatten
asn1
assert-plus
async-limiter
asynckit
aws-sign2
aws4
balanced-match
bcrypt-pbkdf
bignumber.js
bindings
bl
bluebird
bmp-js
brace-expansion
buffer-alloc
buffer-alloc-unsafe
buffer-equal
buffer-fill
builtin-modules
caseless
chownr
co
code-point-at
combined-stream
concat-map
console-control-strings
core-js
core-util-is
dashdash
decompress-response
deep-extend
deferred-leveldown
delayed-stream
delegates
detect-libc
dom-walk
ecc-jsbn
encoding-down
end-of-stream
err-code
errno
error-ex
es6-promise
exif-parser
expand-template
extend
extsprintf
fast-deep-equal
fast-future
fast-json-stable-stringify
file-type
find-up
flash-store
for-each
forever-agent
form-data
fs-constants
fs-extra
fs.realpath
gauge
getpass
github-from-package
glob
global
graceful-fs
har-schema
har-validator
has-unicode
hosted-git-info
http-signature
inflight
inherits
ini
ip-regex
is-arrayish
is-builtin-module
is-callable
is-fullwidth-code-point
is-function
is-typedarray
isarray
isstream
jimp
jpeg-js
jsbn
json-parse-better-errors
json-rpc-peer
json-rpc-protocol
json-schema
json-schema-traverse
json-stringify-safe
jsonfile
jsprim
jsqr
level-codec
level-errors
level-iterator-stream
leveldown
levelup
load-bmfont
load-json-file
locate-path
lodash
lru-cache
make-error
mime
mime-db
mime-types
mimic-response
min-document
minimatch
minimist
mkdirp
n
nan
node-abi
noop-logger
nop
normalize-package-data
npmlog
number-is-nan
oauth-sign
object-assign
once
os-homedir
p-limit
p-locate
p-try
parse-bmfont-ascii
parse-bmfont-binary
parse-bmfont-xml
parse-headers
parse-json
path-exists
path-is-absolute
path-type
performance-now
pify
pixelmatch
pngjs
prebuild-install
process
process-nextick-args
prr
pseudomap
psl
pump
punycode
qs
rc
read-chunk
read-pkg
readable-stream
regenerator-runtime
request
request-promise
request-promise-core
retry
rimraf
rx-queue
rxjs
safe-buffer
safer-buffer
sax
semver
set-blocking
signal-exit
simple-concat
simple-get
spdx-correct
spdx-exceptions
spdx-expression-parse
spdx-license-ids
sshpk
stealthy-require
stream-to
stream-to-buffer
string-width
string_decoder
strip-ansi
strip-bom
strip-json-comments
tar-fs
tar-stream
tinycolor2
to-buffer
tough-cookie
trim
tslib
tunnel-agent
tweetnacl
universalify
url-regex
util-deprecate
uuid
validate-npm-package-license
verror
wechaty-puppet-padchat
which-pm-runs
wide-align
wrappy
xhr
xml-parse-from-string
xml2js
xmlbuilder
xtend
yallist

### 5. wechaty doctor

09:19:51 SILL Config WECHATY_LOG set level to silly
09:19:51 INFO Config registering process.on("unhandledRejection") for development/debug
09:19:51 VERB Config constructor()
09:19:52 SILL Accessory #0<Wechaty> constructor()
09:19:52 VERB Wechaty contructor()
09:19:52 VERB MemoryCard constructor({"name":"default"})
09:19:52 VERB MemoryCard getStorage() for storage type: N/A
09:19:52 VERB getStorage name: default, options: {"type":"file"}
09:19:52 VERB StorageFile constructor(default, ...)
09:19:52 VERB StorageBackend constructor(default, { type: file })
09:19:52 VERB StateSwitch constructor(name=Wechaty)
09:19:52 VERB StateSwitch constructor(name=WechatyReady)
09:19:52 VERB Doctor constructor()
09:19:52 VERB Doctor testTcp()
09:19:52 SILL Doctor testTcp() client connected
09:19:52 SILL Wechaty version() form development environment is not availble: ENOENT: no such file or directory, stat '/wechaty/dist/.git'

  #### Wechaty Doctor

  1. Wechaty version: 0.19.139
  2. Linux x64 version 4.4.0-128-generic memory 490/16047 MB
  3. Docker: true
  4. Node version: v10.8.0
  5. Tcp IPC TEST: PASS


09:19:52 SILL Doctor testTcp() server closed
  ____        _               _ _             ___ ____ ____  _   _ _____
 / ___| _   _| |__  _ __ ___ (_) |_    __ _  |_ _/ ___/ ___|| | | | ____|
 \___ \| | | | '_ \| '_ ` _ \| | __|  / _` |  | |\___ \___ \| | | |  _|
  ___) | |_| | |_) | | | | | | | |_  | (_| |  | | ___) |__) | |_| | |___
 |____/ \__,_|_.__/|_| |_| |_|_|\__|  \__,_| |___|____/____/ \___/|_____|

_____________________________________________________________

@xiamao xiamao changed the title appear bug when logout appear bug when logout use padchat Aug 17, 2018
@xiamao xiamao closed this as completed Aug 17, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant