The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .github
    ├── FUNDING.yml
    ├── ISSUE_TEMPLATE
    │   ├── ----.md
    │   └── bug---.md
    ├── stale.yml
    └── workflows
    │   └── dockerimage.yml
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── VERSION
├── docker
    ├── Dockerfile
    └── DockerfileArm
├── docs
    ├── .buildinfo
    ├── .nojekyll
    ├── AI.html
    ├── ASR.html
    ├── Brain.html
    ├── ConfigMonitor.html
    ├── Conversation.html
    ├── Player.html
    ├── TTS.html
    ├── Updater.html
    ├── _modules
    │   ├── index.html
    │   ├── logging.html
    │   ├── plugins
    │   │   ├── Camera.html
    │   │   ├── CleanCache.html
    │   │   ├── Echo.html
    │   │   ├── Email.html
    │   │   ├── Geek.html
    │   │   ├── LocalPlayer.html
    │   │   └── Poem.html
    │   ├── robot
    │   │   ├── AI.html
    │   │   ├── ASR.html
    │   │   ├── Brain.html
    │   │   ├── ConfigMonitor.html
    │   │   ├── Conversation.html
    │   │   ├── NLU.html
    │   │   ├── Player.html
    │   │   ├── TTS.html
    │   │   ├── Updater.html
    │   │   ├── config.html
    │   │   ├── constants.html
    │   │   ├── drivers
    │   │   │   ├── apa102.html
    │   │   │   └── pixels.html
    │   │   ├── logging.html
    │   │   ├── plugin_loader.html
    │   │   ├── sdk
    │   │   │   ├── AbstractPlugin.html
    │   │   │   ├── AliSpeech.html
    │   │   │   ├── RASRsdk.html
    │   │   │   ├── TencentSpeech.html
    │   │   │   ├── XunfeiSpeech.html
    │   │   │   └── unit.html
    │   │   ├── statistic.html
    │   │   └── utils.html
    │   ├── snowboy
    │   │   ├── snowboydecoder.html
    │   │   └── snowboydetect.html
    │   └── wukong.html
    ├── _sources
    │   ├── AI.rst.txt
    │   ├── ASR.rst.txt
    │   ├── Brain.rst.txt
    │   ├── ConfigMonitor.rst.txt
    │   ├── Conversation.rst.txt
    │   ├── Player.rst.txt
    │   ├── TTS.rst.txt
    │   ├── Updater.rst.txt
    │   ├── config.rst.txt
    │   ├── constants.rst.txt
    │   ├── drivers.rst.txt
    │   ├── index.rst.txt
    │   ├── logging.rst.txt
    │   ├── modules.rst.txt
    │   ├── plugin_loader.rst.txt
    │   ├── plugins.rst.txt
    │   ├── robot.drivers.rst.txt
    │   ├── robot.rst.txt
    │   ├── robot.sdk.rst.txt
    │   ├── snowboy.rst.txt
    │   ├── statistic.rst.txt
    │   ├── utils.rst.txt
    │   └── wukong.rst.txt
    ├── _static
    │   ├── ajax-loader.gif
    │   ├── alabaster.css
    │   ├── basic.css
    │   ├── comment-bright.png
    │   ├── comment-close.png
    │   ├── comment.png
    │   ├── css
    │   │   ├── badge_only.css
    │   │   └── theme.css
    │   ├── custom.css
    │   ├── doctools.js
    │   ├── documentation_options.js
    │   ├── down-pressed.png
    │   ├── down.png
    │   ├── file.png
    │   ├── fonts
    │   │   ├── Inconsolata-Bold.ttf
    │   │   ├── Inconsolata-Regular.ttf
    │   │   ├── Inconsolata.ttf
    │   │   ├── Lato-Bold.ttf
    │   │   ├── Lato-Regular.ttf
    │   │   ├── Lato
    │   │   │   ├── lato-bold.eot
    │   │   │   ├── lato-bold.ttf
    │   │   │   ├── lato-bold.woff
    │   │   │   ├── lato-bold.woff2
    │   │   │   ├── lato-bolditalic.eot
    │   │   │   ├── lato-bolditalic.ttf
    │   │   │   ├── lato-bolditalic.woff
    │   │   │   ├── lato-bolditalic.woff2
    │   │   │   ├── lato-italic.eot
    │   │   │   ├── lato-italic.ttf
    │   │   │   ├── lato-italic.woff
    │   │   │   ├── lato-italic.woff2
    │   │   │   ├── lato-regular.eot
    │   │   │   ├── lato-regular.ttf
    │   │   │   ├── lato-regular.woff
    │   │   │   └── lato-regular.woff2
    │   │   ├── RobotoSlab-Bold.ttf
    │   │   ├── RobotoSlab-Regular.ttf
    │   │   ├── RobotoSlab
    │   │   │   ├── roboto-slab-v7-bold.eot
    │   │   │   ├── roboto-slab-v7-bold.ttf
    │   │   │   ├── roboto-slab-v7-bold.woff
    │   │   │   ├── roboto-slab-v7-bold.woff2
    │   │   │   ├── roboto-slab-v7-regular.eot
    │   │   │   ├── roboto-slab-v7-regular.ttf
    │   │   │   ├── roboto-slab-v7-regular.woff
    │   │   │   └── roboto-slab-v7-regular.woff2
    │   │   ├── fontawesome-webfont.eot
    │   │   ├── fontawesome-webfont.svg
    │   │   ├── fontawesome-webfont.ttf
    │   │   ├── fontawesome-webfont.woff
    │   │   └── fontawesome-webfont.woff2
    │   ├── jquery-3.2.1.js
    │   ├── jquery.js
    │   ├── js
    │   │   ├── modernizr.min.js
    │   │   └── theme.js
    │   ├── language_data.js
    │   ├── minus.png
    │   ├── plus.png
    │   ├── pygments.css
    │   ├── searchtools.js
    │   ├── translations.js
    │   ├── underscore-1.3.1.js
    │   ├── underscore.js
    │   ├── up-pressed.png
    │   ├── up.png
    │   └── websupport.js
    ├── config.html
    ├── constants.html
    ├── drivers.html
    ├── genindex.html
    ├── index.html
    ├── logging.html
    ├── modules.html
    ├── objects.inv
    ├── plugin_loader.html
    ├── plugins.html
    ├── py-modindex.html
    ├── robot.drivers.html
    ├── robot.html
    ├── robot.sdk.html
    ├── search.html
    ├── searchindex.js
    ├── snowboy.html
    ├── statistic.html
    ├── utils.html
    └── wukong.html
├── plugins
    ├── Camera.py
    ├── CleanCache.py
    ├── Echo.py
    ├── Email.py
    ├── Geek.py
    ├── Gossip.py
    ├── LocalPlayer.py
    ├── Poem.py
    ├── Reminder.py
    ├── Volume.py
    └── __init__.py
├── requirements.txt
├── robot
    ├── AI.py
    ├── ASR.py
    ├── BCI.py
    ├── Brain.py
    ├── ConfigMonitor.py
    ├── Conversation.py
    ├── LifeCycleHandler.py
    ├── NLU.py
    ├── Player.py
    ├── Scheduler.py
    ├── TTS.py
    ├── Updater.py
    ├── __init__.py
    ├── config.py
    ├── constants.py
    ├── detector.py
    ├── drivers
    │   ├── AIY.py
    │   ├── __init__.py
    │   ├── apa102.py
    │   └── pixels.py
    ├── logging.py
    ├── plugin_loader.py
    ├── sdk
    │   ├── AbstractPlugin.py
    │   ├── AliSpeech.py
    │   ├── BaiduSpeech.py
    │   ├── FunASREngine.py
    │   ├── History.py
    │   ├── LED.py
    │   ├── RASRsdk.py
    │   ├── TencentSpeech.py
    │   ├── Unihiker.py
    │   ├── VITSClient.py
    │   ├── VolcengineSpeech.py
    │   ├── XunfeiSpeech.py
    │   ├── __init__.py
    │   ├── atc.py
    │   └── unit.py
    ├── statistic.py
    └── utils.py
├── server
    ├── server.py
    ├── static
    │   ├── api.css
    │   ├── bootbox.js
    │   ├── bootstrap.min.css
    │   ├── bootstrap.min.js
    │   ├── bubble.css
    │   ├── config.js
    │   ├── decoderWorker.min.js
    │   ├── default.min.css
    │   ├── encoderWorker.min.js
    │   ├── favicon.png
    │   ├── highlight.min.js
    │   ├── index.js
    │   ├── jquery-3.3.1.min.js
    │   ├── jquery.fancybox.css
    │   ├── jquery.fancybox.js
    │   ├── log.js
    │   ├── main.js
    │   ├── markdown-it.min.js
    │   ├── mfb.min.css
    │   ├── mfb.min.js
    │   ├── modernizr.touch.js
    │   ├── monokai-sublime.css
    │   ├── popper.min.js
    │   ├── progress.min.js
    │   ├── progressjs.min.css
    │   ├── qa.js
    │   ├── recorder.min.js
    │   ├── robot.png
    │   ├── signin.css
    │   ├── spin.css
    │   ├── starter-template.css
    │   ├── static.js
    │   ├── toastr.min.css
    │   ├── toastr.min.js
    │   └── waveWorker.min.js
    └── templates
    │   ├── api.html
    │   ├── api.md
    │   ├── config.html
    │   ├── donate.html
    │   ├── index.html
    │   ├── layout.html
    │   ├── log.html
    │   ├── login.html
    │   └── qa.html
├── snowboy
    ├── __init__.py
    ├── resources
    │   ├── common.res
    │   ├── ding.wav
    │   └── dong.wav
    ├── snowboydecoder.py
    └── snowboydetect.py
├── static
    ├── background.png
    ├── beep_hi.wav
    ├── beep_lo.wav
    ├── camera.wav
    ├── default.yml
    ├── off.wav
    ├── on.wav
    ├── qa.csv
    ├── snowboy.umdl
    ├── wukong.pmdl
    ├── wukong_pi.pmdl
    └── zhimakaimen.pmdl
├── temp
    └── DIR
├── tools
    ├── changelog.sh
    ├── make_json.py
    ├── solr_api.py
    └── solr_tools.py
└── wukong.py


/.github/FUNDING.yml:
--------------------------------------------------------------------------------
 1 | # These are supported funding model platforms
 2 | 
 3 | github: #'wzpan'
 4 | patreon: # Replace with a single Patreon username
 5 | open_collective: wukong-robot
 6 | ko_fi: # Replace with a single Ko-fi username
 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
 9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: ['https://wukong.hahack.com/#/donate']
13 | 


--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/----.md:
--------------------------------------------------------------------------------
 1 | ---
 2 | name: 使用求助
 3 | about: 使用遇到问题,请求帮助
 4 | title: ''
 5 | labels: operation problem
 6 | assignees: wzpan
 7 | 
 8 | ---
 9 | 
10 | **确认已寻找过答案**
11 | 
12 | 我已确认在 [Github issue](https://github.com/wzpan/wukong-robot/issues) 页、[常见问题](https://github.com/wzpan/wukong-robot/wiki/troubleshooting)页、[文档](http://wukong.hahack.com) 中都查找过,没有找到类似问题和资料。我也没有 google / bing/ 百度 / duckduckgo 到相关解答。
13 | 
14 | **安装方式**
15 | 
16 | 手动安装/docker安装
17 | 
18 | **操作系统**
19 | 
20 | (例如 Raspbian Stretch、Ubuntu 16.04)
21 | 
22 | **离线唤醒相关**
23 | 
24 | 如果是离线唤醒相关的问题,是否已确保 `arecord temp.wav`、`aplay temp.wav` (Linux) 或 `rec temp.wav`、`play temp.wav` (Mac)已正常工作?(注意要求不能带任何其他参数)如果不能,请先配置好麦克风和音响再尝试。
25 | 
26 | —— 我已确保录音、播放都正常工作才尝试 wukong-robot 。
27 | 
28 | **问题描述**
29 | 
30 | 具体说明下问题
31 | 


--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug---.md:
--------------------------------------------------------------------------------
 1 | ---
 2 | name: Bug 反馈
 3 | about: 反馈一个bug,帮助改进 wukong-robot
 4 | title: ''
 5 | labels: bug
 6 | assignees: wzpan
 7 | 
 8 | ---
 9 | 
10 | **确认已寻找过答案**
11 | 
12 | 我已确认在 [Github issue](https://github.com/wzpan/wukong-robot/issues) 页、[常见问题](https://github.com/wzpan/wukong-robot/wiki/troubleshooting)页、[文档](http://wukong.hahack.com) 中都查找过,没有找到类似问题和资料。我也没有 google / bing/ 百度 / duckduckgo 到相关解答。
13 | 
14 | **安装方式**
15 | 
16 | 手动安装/docker安装
17 | 
18 | **操作系统**
19 | 
20 | (例如 Raspbian Stretch、Ubuntu 16.04)
21 | 
22 | **离线唤醒相关**
23 | 
24 | 如果是离线唤醒相关的问题,是否已确保 `arecord temp.wav`、`aplay temp.wav` (Linux) 或 `rec temp.wav`、`play temp.wav` (Mac)已正常工作?(注意要求不能带任何其他参数)如果不能,请先配置好麦克风和音响再尝试。
25 | 
26 | —— 我已确保录音、播放都正常工作才尝试 wukong-robot 。
27 | 
28 | **问题描述**
29 | 
30 | 具体说明下问题
31 | 
32 | **复现步骤**
33 | 
34 | 具体描述下复现步骤
35 | 


--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
 1 | # Number of days of inactivity before an issue becomes stale
 2 | daysUntilStale: 7
 3 | # Number of days of inactivity before a stale issue is closed
 4 | daysUntilClose: 3
 5 | # Issues with these labels will never be considered stale
 6 | exemptLabels:
 7 |   - pinned
 8 |   - security
 9 |   - bug
10 | # Label to use when marking an issue as stale
11 | staleLabel: wontfix
12 | # Comment to post when marking an issue as stale. Set to `false` to disable
13 | markComment: >
14 |   由于久无进展,这个 issue 已被标为过期。如果还没有后续进展,这个 issue 将被关闭。谢谢你的反馈!
15 | # Comment to post when closing a stale issue. Set to `false` to disable
16 | closeComment: false
17 | 


--------------------------------------------------------------------------------
/.github/workflows/dockerimage.yml:
--------------------------------------------------------------------------------
 1 | name: Docker Image CI
 2 | 
 3 | on:
 4 |   push:
 5 |     branches:
 6 |     - master
 7 | 
 8 | jobs:
 9 | 
10 |   build:
11 |  
12 |     runs-on: ubuntu-latest
13 |  
14 |     steps:
15 |     - uses: actions/checkout@master
16 |     - name: Publish to Docker Hub Registry
17 |       uses: elgohr/Publish-Docker-Github-Action@master
18 |       with:
19 |         name: wzpan/wukong-robot
20 |         username: ${{ secrets.DOCKER_GITHUB_USERNAME }}
21 |         password: ${{ secrets.DOCKER_PASSWORD }}
22 |         dockerfile: docker/Dockerfile
23 |     - name: Publish to Github Package Registry
24 |       uses: elgohr/Publish-Docker-Github-Action@master
25 |       with:
26 |         name: docker.pkg.github.com/wzpan/wukong-robot/wukong
27 |         username: ${{ secrets.DOCKER_GITHUB_USERNAME }}
28 |         password: ${{ secrets.DOCKER_GITHUB_PASSWORD }}
29 |         registry: docker.pkg.github.com
30 |         dockerfile: docker/Dockerfile    
31 | 
32 | 
33 | 


--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
 1 | # Generic files to ignore
 2 | *~
 3 | *.lock
 4 | *.DS_Store
 5 | *.swp
 6 | *.out
 7 | 
 8 | # Byte-compiled / optimized / DLL files
 9 | __pycache__/
10 | *.py[cod]
11 | 
12 | # C extensions
13 | *.so
14 | 
15 | # Distribution / packaging
16 | .Python
17 | env/
18 | build/
19 | develop-eggs/
20 | dist/
21 | downloads/
22 | eggs/
23 | lib/
24 | lib64/
25 | parts/
26 | sdist/
27 | var/
28 | *.egg-info/
29 | .installed.cfg
30 | *.egg
31 | 
32 | # PyInstaller
33 | #  Usually these files are written by a python script from a template
34 | #  before PyInstaller builds the exe, so as to inject date/other infos into it.
35 | *.manifest
36 | *.spec
37 | 
38 | # Installer logs
39 | pip-log.txt
40 | pip-delete-this-directory.txt
41 | 
42 | # Unit test / coverage reports
43 | htmlcov/
44 | .tox/
45 | .coverage
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | 
50 | # Translations
51 | *.mo
52 | *.pot
53 | 
54 | # Django stuff/Logfiles
55 | *.log
56 | 
57 | # Sphinx documentation
58 | docs/_build/
59 | 
60 | # PyBuilder
61 | target/
62 | 
63 | # Coverage reports for a specific version
64 | .coverage
65 | 
66 | # SublimeLinter config file
67 | .sublimelinterrc
68 | 
69 | # temp folder
70 | temp/*
71 | 
72 | # temp file
73 | #*.*#
74 | #*#
75 | \#*#
76 | *~
77 | .#*.*
78 | 
79 | # NetEase music account info
80 | userInfo
81 | 
82 | # wget log
83 | wget-log*
84 | 
85 | # some thirdparty libs
86 | client/mic_array
87 | login/wxqr.png
88 | .idea/
89 | sftp-config.json
90 | __pycache__
91 | 
92 | 


--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
 1 | env:
 2 |     - ARCH=x86
 3 | language: python
 4 | sudo: false
 5 | python:
 6 |     - "3.5"
 7 | cache:
 8 |   directories:
 9 |     - "$HOME/.pip-cache/"
10 |     - "/home/travis/virtualenv/python3.8"
11 | install: 
12 |     - "pip3 install pyflakes --cache-dir $HOME/.pip-cache"
13 | script:
14 |     - "pyflakes ."
15 | 


--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
 1 | MIT License
 2 | 
 3 | Copyright (c) 2016 - present Weizhou Pan
 4 | 
 5 | Permission is hereby granted, free of charge, to any person obtaining a copy
 6 | of this software and associated documentation files (the "Software"), to deal
 7 | in the Software without restriction, including without limitation the rights
 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 | 
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 | 
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 | 


--------------------------------------------------------------------------------
/VERSION:
--------------------------------------------------------------------------------
1 | 3.5.3
2 | 


--------------------------------------------------------------------------------
/docker/Dockerfile:
--------------------------------------------------------------------------------
 1 | # 使用官方 Python 3.8 基础镜像
 2 | FROM python:3.8-slim
 3 | 
 4 | # 设置工作目录
 5 | WORKDIR /app
 6 | 
 7 | # 安装依赖库
 8 | RUN apt-get update && apt-get install -y \
 9 |     git \
10 |     portaudio19-dev \
11 |     python3-pyaudio \
12 |     sox \
13 |     pulseaudio \
14 |     libsox-fmt-all \
15 |     ffmpeg \
16 |     wget \
17 |     swig \
18 |     libpcre3 \
19 |     libpcre3-dev \
20 |     libatlas-base-dev \
21 |     build-essential \
22 |     && rm -rf /var/lib/apt/lists/*
23 | 
24 | # 克隆项目仓库
25 | RUN git clone https://github.com/wzpan/wukong-robot.git .
26 | 
27 | # 安装 PyAudio
28 | RUN pip install pyaudio
29 | 
30 | # 安装 Python 依赖
31 | RUN pip install --trusted-host pypi.python.org -r requirements.txt
32 | 
33 | # 安装 wukong-contrib
34 | RUN mkdir -p $HOME/.wukong \
35 |     && cd $HOME/.wukong \
36 |     && git clone http://github.com/wzpan/wukong-contrib.git contrib \
37 |     && pip install -r contrib/requirements.txt
38 | 
39 | # 下载并编译 snowboy
40 | RUN wget https://wzpan-1253537070.cos.ap-guangzhou.myqcloud.com/misc/snowboy.tar.bz2 \
41 |     && tar -xvjf snowboy.tar.bz2 \
42 |     && cd snowboy/swig/Python3 \
43 |     && make \
44 |     && cp _snowboydetect.so /app/snowboy/
45 | 
46 | # 暴露端口
47 | EXPOSE 5001
48 | 
49 | # 设置 ENTRYPOINT
50 | ENTRYPOINT ["python", "wukong.py"]
51 | 


--------------------------------------------------------------------------------
/docker/DockerfileArm:
--------------------------------------------------------------------------------
 1 | # 使用官方 Python 3.8 基于 ARM 的镜像
 2 | FROM arm32v7/python:3.8-slim
 3 | 
 4 | MAINTAINER wzpan
 5 | 
 6 | # 设置工作目录
 7 | WORKDIR /app
 8 | 
 9 | # 安装依赖库
10 | RUN apt-get update && apt-get install -y \
11 |     git \
12 |     portaudio19-dev \
13 |     python3-pyaudio \
14 |     sox \
15 |     pulseaudio \
16 |     libsox-fmt-all \
17 |     ffmpeg \
18 |     wget \
19 |     swig \
20 |     libpcre3 \
21 |     libpcre3-dev \
22 |     libatlas-base-dev \
23 |     libffi-dev \
24 |     build-essential \
25 |     && rm -rf /var/lib/apt/lists/*
26 | 
27 | # 克隆项目仓库
28 | RUN git clone https://github.com/wzpan/wukong-robot.git .
29 | 
30 | # 安装 PyAudio
31 | RUN pip install pyaudio
32 | 
33 | # 安装 Python 依赖
34 | RUN pip install --trusted-host pypi.python.org -r requirements.txt
35 | 
36 | # 安装 wukong-contrib
37 | RUN mkdir -p $HOME/.wukong \
38 |     && cd $HOME/.wukong \
39 |     && git clone http://github.com/wzpan/wukong-contrib.git contrib \
40 |     && pip install -r contrib/requirements.txt
41 | 
42 | # 下载并编译 snowboy
43 | RUN wget https://wzpan-1253537070.cos.ap-guangzhou.myqcloud.com/misc/snowboy.tar.bz2 \
44 |     && tar -xvjf snowboy.tar.bz2 \
45 |     && cd snowboy/swig/Python3 \
46 |     && make \
47 |     && cp _snowboydetect.so /app/snowboy/
48 | 
49 | # 暴露端口
50 | EXPOSE 5001
51 | 
52 | # 设置 ENTRYPOINT
53 | ENTRYPOINT ["python", "wukong.py"]
54 | 


--------------------------------------------------------------------------------
/docs/.buildinfo:
--------------------------------------------------------------------------------
1 | # Sphinx build info version 1
2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
3 | config: bed81550a26bd552fac818a5876d05a1
4 | tags: 645f666f9bcd5a90fca523b33c5a78b7
5 | 


--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/.nojekyll


--------------------------------------------------------------------------------
/docs/AI.html:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  3 | <!DOCTYPE html>
  4 | <!--[if IE 8]><html class="no-js lt-ie9" lang="zh-CN" > <![endif]-->
  5 | <!--[if gt IE 8]><!--> <html class="no-js" lang="zh-CN" > <!--<![endif]-->
  6 | <head>
  7 |   <meta charset="utf-8">
  8 |   
  9 |   <meta name="viewport" content="width=device-width, initial-scale=1.0">
 10 |   
 11 |   <title>AI module &mdash; wukong-robot 1.2.0 文档</title>
 12 |   
 13 | 
 14 |   
 15 |   
 16 |   
 17 |   
 18 | 
 19 |   
 20 |   <script type="text/javascript" src="_static/js/modernizr.min.js"></script>
 21 |   
 22 |     
 23 |       <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
 24 |         <script type="text/javascript" src="_static/jquery.js"></script>
 25 |         <script type="text/javascript" src="_static/underscore.js"></script>
 26 |         <script type="text/javascript" src="_static/doctools.js"></script>
 27 |         <script type="text/javascript" src="_static/language_data.js"></script>
 28 |         <script type="text/javascript" src="_static/translations.js"></script>
 29 |     
 30 |     <script type="text/javascript" src="_static/js/theme.js"></script>
 31 | 
 32 |     
 33 | 
 34 |   
 35 |   <link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
 36 |   <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
 37 |     <link rel="index" title="索引" href="genindex.html" />
 38 |     <link rel="search" title="搜索" href="search.html" /> 
 39 | </head>
 40 | 
 41 | <body class="wy-body-for-nav">
 42 | 
 43 |    
 44 |   <div class="wy-grid-for-nav">
 45 |     
 46 |     <nav data-toggle="wy-nav-shift" class="wy-nav-side">
 47 |       <div class="wy-side-scroll">
 48 |         <div class="wy-side-nav-search" >
 49 |           
 50 | 
 51 |           
 52 |             <a href="index.html" class="icon icon-home"> wukong-robot
 53 |           
 54 | 
 55 |           
 56 |           </a>
 57 | 
 58 |           
 59 |             
 60 |             
 61 |           
 62 | 
 63 |           
 64 | <div role="search">
 65 |   <form id="rtd-search-form" class="wy-form" action="search.html" method="get">
 66 |     <input type="text" name="q" placeholder="Search docs" />
 67 |     <input type="hidden" name="check_keywords" value="yes" />
 68 |     <input type="hidden" name="area" value="default" />
 69 |   </form>
 70 | </div>
 71 | 
 72 |           
 73 |         </div>
 74 | 
 75 |         <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
 76 |           
 77 |             
 78 |             
 79 |               
 80 |             
 81 |             
 82 |               <!-- Local TOC -->
 83 |               <div class="local-toc"><ul>
 84 | <li><a class="reference internal" href="#">AI module</a></li>
 85 | </ul>
 86 | </div>
 87 |             
 88 |           
 89 |         </div>
 90 |       </div>
 91 |     </nav>
 92 | 
 93 |     <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
 94 | 
 95 |       
 96 |       <nav class="wy-nav-top" aria-label="top navigation">
 97 |         
 98 |           <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
 99 |           <a href="index.html">wukong-robot</a>
100 |         
101 |       </nav>
102 | 
103 | 
104 |       <div class="wy-nav-content">
105 |         
106 |         <div class="rst-content">
107 |         
108 |           
109 | 
110 | 
111 | 
112 | 
113 | 
114 | 
115 | 
116 | 
117 | 
118 | 
119 | 
120 | 
121 | 
122 | 
123 | 
124 | <div role="navigation" aria-label="breadcrumbs navigation">
125 | 
126 |   <ul class="wy-breadcrumbs">
127 |     
128 |       <li><a href="index.html">Docs</a> &raquo;</li>
129 |         
130 |       <li>AI module</li>
131 |     
132 |     
133 |       <li class="wy-breadcrumbs-aside">
134 |         
135 |             
136 |             <a href="_sources/AI.rst.txt" rel="nofollow"> View page source</a>
137 |           
138 |         
139 |       </li>
140 |     
141 |   </ul>
142 | 
143 |   
144 |   <hr/>
145 | </div>
146 |           <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
147 |            <div itemprop="articleBody">
148 |             
149 |   <div class="section" id="ai-module">
150 | <h1>AI module<a class="headerlink" href="#ai-module" title="永久链接至标题">¶</a></h1>
151 | </div>
152 | 
153 | 
154 |            </div>
155 |            
156 |           </div>
157 |           <footer>
158 |   
159 | 
160 |   <hr/>
161 | 
162 |   <div role="contentinfo">
163 |     <p>
164 |         &copy; Copyright 2019, wzpan
165 | 
166 |     </p>
167 |   </div>
168 |   Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. 
169 | 
170 | </footer>
171 | 
172 |         </div>
173 |       </div>
174 | 
175 |     </section>
176 | 
177 |   </div>
178 |   
179 | 
180 | 
181 |   <script type="text/javascript">
182 |       jQuery(function () {
183 |           SphinxRtdTheme.Navigation.enable(true);
184 |       });
185 |   </script>
186 | 
187 |   
188 |   
189 |     
190 |    
191 | 
192 | </body>
193 | </html>


--------------------------------------------------------------------------------
/docs/ASR.html:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  3 | <!DOCTYPE html>
  4 | <!--[if IE 8]><html class="no-js lt-ie9" lang="zh-CN" > <![endif]-->
  5 | <!--[if gt IE 8]><!--> <html class="no-js" lang="zh-CN" > <!--<![endif]-->
  6 | <head>
  7 |   <meta charset="utf-8">
  8 |   
  9 |   <meta name="viewport" content="width=device-width, initial-scale=1.0">
 10 |   
 11 |   <title>ASR module &mdash; wukong-robot 1.2.0 文档</title>
 12 |   
 13 | 
 14 |   
 15 |   
 16 |   
 17 |   
 18 | 
 19 |   
 20 |   <script type="text/javascript" src="_static/js/modernizr.min.js"></script>
 21 |   
 22 |     
 23 |       <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
 24 |         <script type="text/javascript" src="_static/jquery.js"></script>
 25 |         <script type="text/javascript" src="_static/underscore.js"></script>
 26 |         <script type="text/javascript" src="_static/doctools.js"></script>
 27 |         <script type="text/javascript" src="_static/language_data.js"></script>
 28 |         <script type="text/javascript" src="_static/translations.js"></script>
 29 |     
 30 |     <script type="text/javascript" src="_static/js/theme.js"></script>
 31 | 
 32 |     
 33 | 
 34 |   
 35 |   <link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
 36 |   <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
 37 |     <link rel="index" title="索引" href="genindex.html" />
 38 |     <link rel="search" title="搜索" href="search.html" /> 
 39 | </head>
 40 | 
 41 | <body class="wy-body-for-nav">
 42 | 
 43 |    
 44 |   <div class="wy-grid-for-nav">
 45 |     
 46 |     <nav data-toggle="wy-nav-shift" class="wy-nav-side">
 47 |       <div class="wy-side-scroll">
 48 |         <div class="wy-side-nav-search" >
 49 |           
 50 | 
 51 |           
 52 |             <a href="index.html" class="icon icon-home"> wukong-robot
 53 |           
 54 | 
 55 |           
 56 |           </a>
 57 | 
 58 |           
 59 |             
 60 |             
 61 |           
 62 | 
 63 |           
 64 | <div role="search">
 65 |   <form id="rtd-search-form" class="wy-form" action="search.html" method="get">
 66 |     <input type="text" name="q" placeholder="Search docs" />
 67 |     <input type="hidden" name="check_keywords" value="yes" />
 68 |     <input type="hidden" name="area" value="default" />
 69 |   </form>
 70 | </div>
 71 | 
 72 |           
 73 |         </div>
 74 | 
 75 |         <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
 76 |           
 77 |             
 78 |             
 79 |               
 80 |             
 81 |             
 82 |               <!-- Local TOC -->
 83 |               <div class="local-toc"><ul>
 84 | <li><a class="reference internal" href="#">ASR module</a></li>
 85 | </ul>
 86 | </div>
 87 |             
 88 |           
 89 |         </div>
 90 |       </div>
 91 |     </nav>
 92 | 
 93 |     <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
 94 | 
 95 |       
 96 |       <nav class="wy-nav-top" aria-label="top navigation">
 97 |         
 98 |           <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
 99 |           <a href="index.html">wukong-robot</a>
100 |         
101 |       </nav>
102 | 
103 | 
104 |       <div class="wy-nav-content">
105 |         
106 |         <div class="rst-content">
107 |         
108 |           
109 | 
110 | 
111 | 
112 | 
113 | 
114 | 
115 | 
116 | 
117 | 
118 | 
119 | 
120 | 
121 | 
122 | 
123 | 
124 | <div role="navigation" aria-label="breadcrumbs navigation">
125 | 
126 |   <ul class="wy-breadcrumbs">
127 |     
128 |       <li><a href="index.html">Docs</a> &raquo;</li>
129 |         
130 |       <li>ASR module</li>
131 |     
132 |     
133 |       <li class="wy-breadcrumbs-aside">
134 |         
135 |             
136 |             <a href="_sources/ASR.rst.txt" rel="nofollow"> View page source</a>
137 |           
138 |         
139 |       </li>
140 |     
141 |   </ul>
142 | 
143 |   
144 |   <hr/>
145 | </div>
146 |           <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
147 |            <div itemprop="articleBody">
148 |             
149 |   <div class="section" id="asr-module">
150 | <h1>ASR module<a class="headerlink" href="#asr-module" title="永久链接至标题">¶</a></h1>
151 | </div>
152 | 
153 | 
154 |            </div>
155 |            
156 |           </div>
157 |           <footer>
158 |   
159 | 
160 |   <hr/>
161 | 
162 |   <div role="contentinfo">
163 |     <p>
164 |         &copy; Copyright 2019, wzpan
165 | 
166 |     </p>
167 |   </div>
168 |   Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. 
169 | 
170 | </footer>
171 | 
172 |         </div>
173 |       </div>
174 | 
175 |     </section>
176 | 
177 |   </div>
178 |   
179 | 
180 | 
181 |   <script type="text/javascript">
182 |       jQuery(function () {
183 |           SphinxRtdTheme.Navigation.enable(true);
184 |       });
185 |   </script>
186 | 
187 |   
188 |   
189 |     
190 |    
191 | 
192 | </body>
193 | </html>


--------------------------------------------------------------------------------
/docs/Brain.html:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  3 | <!DOCTYPE html>
  4 | <!--[if IE 8]><html class="no-js lt-ie9" lang="zh-CN" > <![endif]-->
  5 | <!--[if gt IE 8]><!--> <html class="no-js" lang="zh-CN" > <!--<![endif]-->
  6 | <head>
  7 |   <meta charset="utf-8">
  8 |   
  9 |   <meta name="viewport" content="width=device-width, initial-scale=1.0">
 10 |   
 11 |   <title>Brain module &mdash; wukong-robot 1.2.0 文档</title>
 12 |   
 13 | 
 14 |   
 15 |   
 16 |   
 17 |   
 18 | 
 19 |   
 20 |   <script type="text/javascript" src="_static/js/modernizr.min.js"></script>
 21 |   
 22 |     
 23 |       <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
 24 |         <script type="text/javascript" src="_static/jquery.js"></script>
 25 |         <script type="text/javascript" src="_static/underscore.js"></script>
 26 |         <script type="text/javascript" src="_static/doctools.js"></script>
 27 |         <script type="text/javascript" src="_static/language_data.js"></script>
 28 |         <script type="text/javascript" src="_static/translations.js"></script>
 29 |     
 30 |     <script type="text/javascript" src="_static/js/theme.js"></script>
 31 | 
 32 |     
 33 | 
 34 |   
 35 |   <link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
 36 |   <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
 37 |     <link rel="index" title="索引" href="genindex.html" />
 38 |     <link rel="search" title="搜索" href="search.html" /> 
 39 | </head>
 40 | 
 41 | <body class="wy-body-for-nav">
 42 | 
 43 |    
 44 |   <div class="wy-grid-for-nav">
 45 |     
 46 |     <nav data-toggle="wy-nav-shift" class="wy-nav-side">
 47 |       <div class="wy-side-scroll">
 48 |         <div class="wy-side-nav-search" >
 49 |           
 50 | 
 51 |           
 52 |             <a href="index.html" class="icon icon-home"> wukong-robot
 53 |           
 54 | 
 55 |           
 56 |           </a>
 57 | 
 58 |           
 59 |             
 60 |             
 61 |           
 62 | 
 63 |           
 64 | <div role="search">
 65 |   <form id="rtd-search-form" class="wy-form" action="search.html" method="get">
 66 |     <input type="text" name="q" placeholder="Search docs" />
 67 |     <input type="hidden" name="check_keywords" value="yes" />
 68 |     <input type="hidden" name="area" value="default" />
 69 |   </form>
 70 | </div>
 71 | 
 72 |           
 73 |         </div>
 74 | 
 75 |         <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
 76 |           
 77 |             
 78 |             
 79 |               
 80 |             
 81 |             
 82 |               <!-- Local TOC -->
 83 |               <div class="local-toc"><ul>
 84 | <li><a class="reference internal" href="#">Brain module</a></li>
 85 | </ul>
 86 | </div>
 87 |             
 88 |           
 89 |         </div>
 90 |       </div>
 91 |     </nav>
 92 | 
 93 |     <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
 94 | 
 95 |       
 96 |       <nav class="wy-nav-top" aria-label="top navigation">
 97 |         
 98 |           <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
 99 |           <a href="index.html">wukong-robot</a>
100 |         
101 |       </nav>
102 | 
103 | 
104 |       <div class="wy-nav-content">
105 |         
106 |         <div class="rst-content">
107 |         
108 |           
109 | 
110 | 
111 | 
112 | 
113 | 
114 | 
115 | 
116 | 
117 | 
118 | 
119 | 
120 | 
121 | 
122 | 
123 | 
124 | <div role="navigation" aria-label="breadcrumbs navigation">
125 | 
126 |   <ul class="wy-breadcrumbs">
127 |     
128 |       <li><a href="index.html">Docs</a> &raquo;</li>
129 |         
130 |       <li>Brain module</li>
131 |     
132 |     
133 |       <li class="wy-breadcrumbs-aside">
134 |         
135 |             
136 |             <a href="_sources/Brain.rst.txt" rel="nofollow"> View page source</a>
137 |           
138 |         
139 |       </li>
140 |     
141 |   </ul>
142 | 
143 |   
144 |   <hr/>
145 | </div>
146 |           <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
147 |            <div itemprop="articleBody">
148 |             
149 |   <div class="section" id="brain-module">
150 | <h1>Brain module<a class="headerlink" href="#brain-module" title="永久链接至标题">¶</a></h1>
151 | </div>
152 | 
153 | 
154 |            </div>
155 |            
156 |           </div>
157 |           <footer>
158 |   
159 | 
160 |   <hr/>
161 | 
162 |   <div role="contentinfo">
163 |     <p>
164 |         &copy; Copyright 2019, wzpan
165 | 
166 |     </p>
167 |   </div>
168 |   Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. 
169 | 
170 | </footer>
171 | 
172 |         </div>
173 |       </div>
174 | 
175 |     </section>
176 | 
177 |   </div>
178 |   
179 | 
180 | 
181 |   <script type="text/javascript">
182 |       jQuery(function () {
183 |           SphinxRtdTheme.Navigation.enable(true);
184 |       });
185 |   </script>
186 | 
187 |   
188 |   
189 |     
190 |    
191 | 
192 | </body>
193 | </html>


--------------------------------------------------------------------------------
/docs/Player.html:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  3 | <!DOCTYPE html>
  4 | <!--[if IE 8]><html class="no-js lt-ie9" lang="zh-CN" > <![endif]-->
  5 | <!--[if gt IE 8]><!--> <html class="no-js" lang="zh-CN" > <!--<![endif]-->
  6 | <head>
  7 |   <meta charset="utf-8">
  8 |   
  9 |   <meta name="viewport" content="width=device-width, initial-scale=1.0">
 10 |   
 11 |   <title>Player module &mdash; wukong-robot 1.2.0 文档</title>
 12 |   
 13 | 
 14 |   
 15 |   
 16 |   
 17 |   
 18 | 
 19 |   
 20 |   <script type="text/javascript" src="_static/js/modernizr.min.js"></script>
 21 |   
 22 |     
 23 |       <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
 24 |         <script type="text/javascript" src="_static/jquery.js"></script>
 25 |         <script type="text/javascript" src="_static/underscore.js"></script>
 26 |         <script type="text/javascript" src="_static/doctools.js"></script>
 27 |         <script type="text/javascript" src="_static/language_data.js"></script>
 28 |         <script type="text/javascript" src="_static/translations.js"></script>
 29 |     
 30 |     <script type="text/javascript" src="_static/js/theme.js"></script>
 31 | 
 32 |     
 33 | 
 34 |   
 35 |   <link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
 36 |   <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
 37 |     <link rel="index" title="索引" href="genindex.html" />
 38 |     <link rel="search" title="搜索" href="search.html" /> 
 39 | </head>
 40 | 
 41 | <body class="wy-body-for-nav">
 42 | 
 43 |    
 44 |   <div class="wy-grid-for-nav">
 45 |     
 46 |     <nav data-toggle="wy-nav-shift" class="wy-nav-side">
 47 |       <div class="wy-side-scroll">
 48 |         <div class="wy-side-nav-search" >
 49 |           
 50 | 
 51 |           
 52 |             <a href="index.html" class="icon icon-home"> wukong-robot
 53 |           
 54 | 
 55 |           
 56 |           </a>
 57 | 
 58 |           
 59 |             
 60 |             
 61 |           
 62 | 
 63 |           
 64 | <div role="search">
 65 |   <form id="rtd-search-form" class="wy-form" action="search.html" method="get">
 66 |     <input type="text" name="q" placeholder="Search docs" />
 67 |     <input type="hidden" name="check_keywords" value="yes" />
 68 |     <input type="hidden" name="area" value="default" />
 69 |   </form>
 70 | </div>
 71 | 
 72 |           
 73 |         </div>
 74 | 
 75 |         <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
 76 |           
 77 |             
 78 |             
 79 |               
 80 |             
 81 |             
 82 |               <!-- Local TOC -->
 83 |               <div class="local-toc"><ul>
 84 | <li><a class="reference internal" href="#">Player module</a></li>
 85 | </ul>
 86 | </div>
 87 |             
 88 |           
 89 |         </div>
 90 |       </div>
 91 |     </nav>
 92 | 
 93 |     <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
 94 | 
 95 |       
 96 |       <nav class="wy-nav-top" aria-label="top navigation">
 97 |         
 98 |           <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
 99 |           <a href="index.html">wukong-robot</a>
100 |         
101 |       </nav>
102 | 
103 | 
104 |       <div class="wy-nav-content">
105 |         
106 |         <div class="rst-content">
107 |         
108 |           
109 | 
110 | 
111 | 
112 | 
113 | 
114 | 
115 | 
116 | 
117 | 
118 | 
119 | 
120 | 
121 | 
122 | 
123 | 
124 | <div role="navigation" aria-label="breadcrumbs navigation">
125 | 
126 |   <ul class="wy-breadcrumbs">
127 |     
128 |       <li><a href="index.html">Docs</a> &raquo;</li>
129 |         
130 |       <li>Player module</li>
131 |     
132 |     
133 |       <li class="wy-breadcrumbs-aside">
134 |         
135 |             
136 |             <a href="_sources/Player.rst.txt" rel="nofollow"> View page source</a>
137 |           
138 |         
139 |       </li>
140 |     
141 |   </ul>
142 | 
143 |   
144 |   <hr/>
145 | </div>
146 |           <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
147 |            <div itemprop="articleBody">
148 |             
149 |   <div class="section" id="player-module">
150 | <h1>Player module<a class="headerlink" href="#player-module" title="永久链接至标题">¶</a></h1>
151 | </div>
152 | 
153 | 
154 |            </div>
155 |            
156 |           </div>
157 |           <footer>
158 |   
159 | 
160 |   <hr/>
161 | 
162 |   <div role="contentinfo">
163 |     <p>
164 |         &copy; Copyright 2019, wzpan
165 | 
166 |     </p>
167 |   </div>
168 |   Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. 
169 | 
170 | </footer>
171 | 
172 |         </div>
173 |       </div>
174 | 
175 |     </section>
176 | 
177 |   </div>
178 |   
179 | 
180 | 
181 |   <script type="text/javascript">
182 |       jQuery(function () {
183 |           SphinxRtdTheme.Navigation.enable(true);
184 |       });
185 |   </script>
186 | 
187 |   
188 |   
189 |     
190 |    
191 | 
192 | </body>
193 | </html>


--------------------------------------------------------------------------------
/docs/TTS.html:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  3 | <!DOCTYPE html>
  4 | <!--[if IE 8]><html class="no-js lt-ie9" lang="zh-CN" > <![endif]-->
  5 | <!--[if gt IE 8]><!--> <html class="no-js" lang="zh-CN" > <!--<![endif]-->
  6 | <head>
  7 |   <meta charset="utf-8">
  8 |   
  9 |   <meta name="viewport" content="width=device-width, initial-scale=1.0">
 10 |   
 11 |   <title>TTS module &mdash; wukong-robot 1.2.0 文档</title>
 12 |   
 13 | 
 14 |   
 15 |   
 16 |   
 17 |   
 18 | 
 19 |   
 20 |   <script type="text/javascript" src="_static/js/modernizr.min.js"></script>
 21 |   
 22 |     
 23 |       <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
 24 |         <script type="text/javascript" src="_static/jquery.js"></script>
 25 |         <script type="text/javascript" src="_static/underscore.js"></script>
 26 |         <script type="text/javascript" src="_static/doctools.js"></script>
 27 |         <script type="text/javascript" src="_static/language_data.js"></script>
 28 |         <script type="text/javascript" src="_static/translations.js"></script>
 29 |     
 30 |     <script type="text/javascript" src="_static/js/theme.js"></script>
 31 | 
 32 |     
 33 | 
 34 |   
 35 |   <link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
 36 |   <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
 37 |     <link rel="index" title="索引" href="genindex.html" />
 38 |     <link rel="search" title="搜索" href="search.html" /> 
 39 | </head>
 40 | 
 41 | <body class="wy-body-for-nav">
 42 | 
 43 |    
 44 |   <div class="wy-grid-for-nav">
 45 |     
 46 |     <nav data-toggle="wy-nav-shift" class="wy-nav-side">
 47 |       <div class="wy-side-scroll">
 48 |         <div class="wy-side-nav-search" >
 49 |           
 50 | 
 51 |           
 52 |             <a href="index.html" class="icon icon-home"> wukong-robot
 53 |           
 54 | 
 55 |           
 56 |           </a>
 57 | 
 58 |           
 59 |             
 60 |             
 61 |           
 62 | 
 63 |           
 64 | <div role="search">
 65 |   <form id="rtd-search-form" class="wy-form" action="search.html" method="get">
 66 |     <input type="text" name="q" placeholder="Search docs" />
 67 |     <input type="hidden" name="check_keywords" value="yes" />
 68 |     <input type="hidden" name="area" value="default" />
 69 |   </form>
 70 | </div>
 71 | 
 72 |           
 73 |         </div>
 74 | 
 75 |         <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
 76 |           
 77 |             
 78 |             
 79 |               
 80 |             
 81 |             
 82 |               <!-- Local TOC -->
 83 |               <div class="local-toc"><ul>
 84 | <li><a class="reference internal" href="#">TTS module</a></li>
 85 | </ul>
 86 | </div>
 87 |             
 88 |           
 89 |         </div>
 90 |       </div>
 91 |     </nav>
 92 | 
 93 |     <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
 94 | 
 95 |       
 96 |       <nav class="wy-nav-top" aria-label="top navigation">
 97 |         
 98 |           <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
 99 |           <a href="index.html">wukong-robot</a>
100 |         
101 |       </nav>
102 | 
103 | 
104 |       <div class="wy-nav-content">
105 |         
106 |         <div class="rst-content">
107 |         
108 |           
109 | 
110 | 
111 | 
112 | 
113 | 
114 | 
115 | 
116 | 
117 | 
118 | 
119 | 
120 | 
121 | 
122 | 
123 | 
124 | <div role="navigation" aria-label="breadcrumbs navigation">
125 | 
126 |   <ul class="wy-breadcrumbs">
127 |     
128 |       <li><a href="index.html">Docs</a> &raquo;</li>
129 |         
130 |       <li>TTS module</li>
131 |     
132 |     
133 |       <li class="wy-breadcrumbs-aside">
134 |         
135 |             
136 |             <a href="_sources/TTS.rst.txt" rel="nofollow"> View page source</a>
137 |           
138 |         
139 |       </li>
140 |     
141 |   </ul>
142 | 
143 |   
144 |   <hr/>
145 | </div>
146 |           <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
147 |            <div itemprop="articleBody">
148 |             
149 |   <div class="section" id="tts-module">
150 | <h1>TTS module<a class="headerlink" href="#tts-module" title="永久链接至标题">¶</a></h1>
151 | </div>
152 | 
153 | 
154 |            </div>
155 |            
156 |           </div>
157 |           <footer>
158 |   
159 | 
160 |   <hr/>
161 | 
162 |   <div role="contentinfo">
163 |     <p>
164 |         &copy; Copyright 2019, wzpan
165 | 
166 |     </p>
167 |   </div>
168 |   Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. 
169 | 
170 | </footer>
171 | 
172 |         </div>
173 |       </div>
174 | 
175 |     </section>
176 | 
177 |   </div>
178 |   
179 | 
180 | 
181 |   <script type="text/javascript">
182 |       jQuery(function () {
183 |           SphinxRtdTheme.Navigation.enable(true);
184 |       });
185 |   </script>
186 | 
187 |   
188 |   
189 |     
190 |    
191 | 
192 | </body>
193 | </html>


--------------------------------------------------------------------------------
/docs/Updater.html:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  3 | <!DOCTYPE html>
  4 | <!--[if IE 8]><html class="no-js lt-ie9" lang="zh-CN" > <![endif]-->
  5 | <!--[if gt IE 8]><!--> <html class="no-js" lang="zh-CN" > <!--<![endif]-->
  6 | <head>
  7 |   <meta charset="utf-8">
  8 |   
  9 |   <meta name="viewport" content="width=device-width, initial-scale=1.0">
 10 |   
 11 |   <title>Updater module &mdash; wukong-robot 1.2.0 文档</title>
 12 |   
 13 | 
 14 |   
 15 |   
 16 |   
 17 |   
 18 | 
 19 |   
 20 |   <script type="text/javascript" src="_static/js/modernizr.min.js"></script>
 21 |   
 22 |     
 23 |       <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
 24 |         <script type="text/javascript" src="_static/jquery.js"></script>
 25 |         <script type="text/javascript" src="_static/underscore.js"></script>
 26 |         <script type="text/javascript" src="_static/doctools.js"></script>
 27 |         <script type="text/javascript" src="_static/language_data.js"></script>
 28 |         <script type="text/javascript" src="_static/translations.js"></script>
 29 |     
 30 |     <script type="text/javascript" src="_static/js/theme.js"></script>
 31 | 
 32 |     
 33 | 
 34 |   
 35 |   <link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
 36 |   <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
 37 |     <link rel="index" title="索引" href="genindex.html" />
 38 |     <link rel="search" title="搜索" href="search.html" /> 
 39 | </head>
 40 | 
 41 | <body class="wy-body-for-nav">
 42 | 
 43 |    
 44 |   <div class="wy-grid-for-nav">
 45 |     
 46 |     <nav data-toggle="wy-nav-shift" class="wy-nav-side">
 47 |       <div class="wy-side-scroll">
 48 |         <div class="wy-side-nav-search" >
 49 |           
 50 | 
 51 |           
 52 |             <a href="index.html" class="icon icon-home"> wukong-robot
 53 |           
 54 | 
 55 |           
 56 |           </a>
 57 | 
 58 |           
 59 |             
 60 |             
 61 |           
 62 | 
 63 |           
 64 | <div role="search">
 65 |   <form id="rtd-search-form" class="wy-form" action="search.html" method="get">
 66 |     <input type="text" name="q" placeholder="Search docs" />
 67 |     <input type="hidden" name="check_keywords" value="yes" />
 68 |     <input type="hidden" name="area" value="default" />
 69 |   </form>
 70 | </div>
 71 | 
 72 |           
 73 |         </div>
 74 | 
 75 |         <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
 76 |           
 77 |             
 78 |             
 79 |               
 80 |             
 81 |             
 82 |               <!-- Local TOC -->
 83 |               <div class="local-toc"><ul>
 84 | <li><a class="reference internal" href="#">Updater module</a></li>
 85 | </ul>
 86 | </div>
 87 |             
 88 |           
 89 |         </div>
 90 |       </div>
 91 |     </nav>
 92 | 
 93 |     <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
 94 | 
 95 |       
 96 |       <nav class="wy-nav-top" aria-label="top navigation">
 97 |         
 98 |           <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
 99 |           <a href="index.html">wukong-robot</a>
100 |         
101 |       </nav>
102 | 
103 | 
104 |       <div class="wy-nav-content">
105 |         
106 |         <div class="rst-content">
107 |         
108 |           
109 | 
110 | 
111 | 
112 | 
113 | 
114 | 
115 | 
116 | 
117 | 
118 | 
119 | 
120 | 
121 | 
122 | 
123 | 
124 | <div role="navigation" aria-label="breadcrumbs navigation">
125 | 
126 |   <ul class="wy-breadcrumbs">
127 |     
128 |       <li><a href="index.html">Docs</a> &raquo;</li>
129 |         
130 |       <li>Updater module</li>
131 |     
132 |     
133 |       <li class="wy-breadcrumbs-aside">
134 |         
135 |             
136 |             <a href="_sources/Updater.rst.txt" rel="nofollow"> View page source</a>
137 |           
138 |         
139 |       </li>
140 |     
141 |   </ul>
142 | 
143 |   
144 |   <hr/>
145 | </div>
146 |           <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
147 |            <div itemprop="articleBody">
148 |             
149 |   <div class="section" id="updater-module">
150 | <h1>Updater module<a class="headerlink" href="#updater-module" title="永久链接至标题">¶</a></h1>
151 | </div>
152 | 
153 | 
154 |            </div>
155 |            
156 |           </div>
157 |           <footer>
158 |   
159 | 
160 |   <hr/>
161 | 
162 |   <div role="contentinfo">
163 |     <p>
164 |         &copy; Copyright 2019, wzpan
165 | 
166 |     </p>
167 |   </div>
168 |   Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. 
169 | 
170 | </footer>
171 | 
172 |         </div>
173 |       </div>
174 | 
175 |     </section>
176 | 
177 |   </div>
178 |   
179 | 
180 | 
181 |   <script type="text/javascript">
182 |       jQuery(function () {
183 |           SphinxRtdTheme.Navigation.enable(true);
184 |       });
185 |   </script>
186 | 
187 |   
188 |   
189 |     
190 |    
191 | 
192 | </body>
193 | </html>


--------------------------------------------------------------------------------
/docs/_sources/AI.rst.txt:
--------------------------------------------------------------------------------
1 | AI module
2 | =========
3 | 
4 | .. automodule:: AI
5 |     :members:
6 |     :undoc-members:
7 |     :show-inheritance:
8 | 


--------------------------------------------------------------------------------
/docs/_sources/ASR.rst.txt:
--------------------------------------------------------------------------------
1 | ASR module
2 | ==========
3 | 
4 | .. automodule:: ASR
5 |     :members:
6 |     :undoc-members:
7 |     :show-inheritance:
8 | 


--------------------------------------------------------------------------------
/docs/_sources/Brain.rst.txt:
--------------------------------------------------------------------------------
1 | Brain module
2 | ============
3 | 
4 | .. automodule:: Brain
5 |     :members:
6 |     :undoc-members:
7 |     :show-inheritance:
8 | 


--------------------------------------------------------------------------------
/docs/_sources/ConfigMonitor.rst.txt:
--------------------------------------------------------------------------------
1 | ConfigMonitor module
2 | ====================
3 | 
4 | .. automodule:: ConfigMonitor
5 |     :members:
6 |     :undoc-members:
7 |     :show-inheritance:
8 | 


--------------------------------------------------------------------------------
/docs/_sources/Conversation.rst.txt:
--------------------------------------------------------------------------------
1 | Conversation module
2 | ===================
3 | 
4 | .. automodule:: Conversation
5 |     :members:
6 |     :undoc-members:
7 |     :show-inheritance:
8 | 


--------------------------------------------------------------------------------
/docs/_sources/Player.rst.txt:
--------------------------------------------------------------------------------
1 | Player module
2 | =============
3 | 
4 | .. automodule:: Player
5 |     :members:
6 |     :undoc-members:
7 |     :show-inheritance:
8 | 


--------------------------------------------------------------------------------
/docs/_sources/TTS.rst.txt:
--------------------------------------------------------------------------------
1 | TTS module
2 | ==========
3 | 
4 | .. automodule:: TTS
5 |     :members:
6 |     :undoc-members:
7 |     :show-inheritance:
8 | 


--------------------------------------------------------------------------------
/docs/_sources/Updater.rst.txt:
--------------------------------------------------------------------------------
1 | Updater module
2 | ==============
3 | 
4 | .. automodule:: Updater
5 |     :members:
6 |     :undoc-members:
7 |     :show-inheritance:
8 | 


--------------------------------------------------------------------------------
/docs/_sources/config.rst.txt:
--------------------------------------------------------------------------------
1 | config module
2 | =============
3 | 
4 | .. automodule:: config
5 |     :members:
6 |     :undoc-members:
7 |     :show-inheritance:
8 | 


--------------------------------------------------------------------------------
/docs/_sources/constants.rst.txt:
--------------------------------------------------------------------------------
1 | constants module
2 | ================
3 | 
4 | .. automodule:: constants
5 |     :members:
6 |     :undoc-members:
7 |     :show-inheritance:
8 | 


--------------------------------------------------------------------------------
/docs/_sources/drivers.rst.txt:
--------------------------------------------------------------------------------
 1 | drivers package
 2 | ===============
 3 | 
 4 | Submodules
 5 | ----------
 6 | 
 7 | drivers.apa102 module
 8 | ---------------------
 9 | 
10 | .. automodule:: drivers.apa102
11 |     :members:
12 |     :undoc-members:
13 |     :show-inheritance:
14 | 
15 | drivers.pixels module
16 | ---------------------
17 | 
18 | .. automodule:: drivers.pixels
19 |     :members:
20 |     :undoc-members:
21 |     :show-inheritance:
22 | 
23 | 
24 | Module contents
25 | ---------------
26 | 
27 | .. automodule:: drivers
28 |     :members:
29 |     :undoc-members:
30 |     :show-inheritance:
31 | 


--------------------------------------------------------------------------------
/docs/_sources/index.rst.txt:
--------------------------------------------------------------------------------
 1 | .. wukong-robot documentation master file, created by
 2 |    sphinx-quickstart on Sun Feb 17 01:03:29 2019.
 3 |    You can adapt this file completely to your liking, but it should at least
 4 |    contain the root `toctree` directive.
 5 | 
 6 | Welcome to wukong-robot's documentation!
 7 | ========================================
 8 | 
 9 | .. toctree::
10 |    :maxdepth: 2
11 |    :caption: Contents:
12 | 
13 | .. automodule:: wukong
14 |    :members:
15 | 
16 | 
17 | Indices and tables
18 | ==================
19 | 
20 | * :ref:`genindex`
21 | * :ref:`modindex`
22 | * :ref:`search`
23 | 


--------------------------------------------------------------------------------
/docs/_sources/logging.rst.txt:
--------------------------------------------------------------------------------
1 | logging module
2 | ==============
3 | 
4 | .. automodule:: logging
5 |     :members:
6 |     :undoc-members:
7 |     :show-inheritance:
8 | 


--------------------------------------------------------------------------------
/docs/_sources/modules.rst.txt:
--------------------------------------------------------------------------------
 1 | wukong-robot
 2 | ============
 3 | 
 4 | .. toctree::
 5 |    :maxdepth: 4
 6 | 
 7 |    plugins
 8 |    robot
 9 |    snowboy
10 |    wukong
11 | 


--------------------------------------------------------------------------------
/docs/_sources/plugin_loader.rst.txt:
--------------------------------------------------------------------------------
1 | plugin\_loader module
2 | =====================
3 | 
4 | .. automodule:: plugin_loader
5 |     :members:
6 |     :undoc-members:
7 |     :show-inheritance:
8 | 


--------------------------------------------------------------------------------
/docs/_sources/plugins.rst.txt:
--------------------------------------------------------------------------------
 1 | plugins package
 2 | ===============
 3 | 
 4 | Submodules
 5 | ----------
 6 | 
 7 | plugins.Camera module
 8 | ---------------------
 9 | 
10 | .. automodule:: plugins.Camera
11 |     :members:
12 |     :undoc-members:
13 |     :show-inheritance:
14 | 
15 | plugins.CleanCache module
16 | -------------------------
17 | 
18 | .. automodule:: plugins.CleanCache
19 |     :members:
20 |     :undoc-members:
21 |     :show-inheritance:
22 | 
23 | plugins.Echo module
24 | -------------------
25 | 
26 | .. automodule:: plugins.Echo
27 |     :members:
28 |     :undoc-members:
29 |     :show-inheritance:
30 | 
31 | plugins.Email module
32 | --------------------
33 | 
34 | .. automodule:: plugins.Email
35 |     :members:
36 |     :undoc-members:
37 |     :show-inheritance:
38 | 
39 | plugins.Geek module
40 | -------------------
41 | 
42 | .. automodule:: plugins.Geek
43 |     :members:
44 |     :undoc-members:
45 |     :show-inheritance:
46 | 
47 | plugins.LocalPlayer module
48 | --------------------------
49 | 
50 | .. automodule:: plugins.LocalPlayer
51 |     :members:
52 |     :undoc-members:
53 |     :show-inheritance:
54 | 
55 | plugins.Poem module
56 | -------------------
57 | 
58 | .. automodule:: plugins.Poem
59 |     :members:
60 |     :undoc-members:
61 |     :show-inheritance:
62 | 
63 | 
64 | Module contents
65 | ---------------
66 | 
67 | .. automodule:: plugins
68 |     :members:
69 |     :undoc-members:
70 |     :show-inheritance:
71 | 


--------------------------------------------------------------------------------
/docs/_sources/robot.drivers.rst.txt:
--------------------------------------------------------------------------------
 1 | robot.drivers package
 2 | =====================
 3 | 
 4 | Submodules
 5 | ----------
 6 | 
 7 | robot.drivers.apa102 module
 8 | ---------------------------
 9 | 
10 | .. automodule:: robot.drivers.apa102
11 |     :members:
12 |     :undoc-members:
13 |     :show-inheritance:
14 | 
15 | robot.drivers.pixels module
16 | ---------------------------
17 | 
18 | .. automodule:: robot.drivers.pixels
19 |     :members:
20 |     :undoc-members:
21 |     :show-inheritance:
22 | 
23 | 
24 | Module contents
25 | ---------------
26 | 
27 | .. automodule:: robot.drivers
28 |     :members:
29 |     :undoc-members:
30 |     :show-inheritance:
31 | 


--------------------------------------------------------------------------------
/docs/_sources/robot.rst.txt:
--------------------------------------------------------------------------------
  1 | robot package
  2 | =============
  3 | 
  4 | Subpackages
  5 | -----------
  6 | 
  7 | .. toctree::
  8 | 
  9 |     robot.sdk
 10 | 
 11 | Submodules
 12 | ----------
 13 | 
 14 | robot.AI module
 15 | ---------------
 16 | 
 17 | .. automodule:: robot.AI
 18 |     :members:
 19 |     :undoc-members:
 20 |     :show-inheritance:
 21 | 
 22 | robot.ASR module
 23 | ----------------
 24 | 
 25 | .. automodule:: robot.ASR
 26 |     :members:
 27 |     :undoc-members:
 28 |     :show-inheritance:
 29 | 
 30 | robot.Brain module
 31 | ------------------
 32 | 
 33 | .. automodule:: robot.Brain
 34 |     :members:
 35 |     :undoc-members:
 36 |     :show-inheritance:
 37 | 
 38 | robot.ConfigMonitor module
 39 | --------------------------
 40 | 
 41 | .. automodule:: robot.ConfigMonitor
 42 |     :members:
 43 |     :undoc-members:
 44 |     :show-inheritance:
 45 | 
 46 | robot.Conversation module
 47 | -------------------------
 48 | 
 49 | .. automodule:: robot.Conversation
 50 |     :members:
 51 |     :undoc-members:
 52 |     :show-inheritance:
 53 | 
 54 | robot.NLU module
 55 | ----------------
 56 | 
 57 | .. automodule:: robot.NLU
 58 |     :members:
 59 |     :undoc-members:
 60 |     :show-inheritance:
 61 | 
 62 | robot.Player module
 63 | -------------------
 64 | 
 65 | .. automodule:: robot.Player
 66 |     :members:
 67 |     :undoc-members:
 68 |     :show-inheritance:
 69 | 
 70 | robot.TTS module
 71 | ----------------
 72 | 
 73 | .. automodule:: robot.TTS
 74 |     :members:
 75 |     :undoc-members:
 76 |     :show-inheritance:
 77 | 
 78 | robot.Updater module
 79 | --------------------
 80 | 
 81 | .. automodule:: robot.Updater
 82 |     :members:
 83 |     :undoc-members:
 84 |     :show-inheritance:
 85 | 
 86 | robot.config module
 87 | -------------------
 88 | 
 89 | .. automodule:: robot.config
 90 |     :members:
 91 |     :undoc-members:
 92 |     :show-inheritance:
 93 | 
 94 | robot.constants module
 95 | ----------------------
 96 | 
 97 | .. automodule:: robot.constants
 98 |     :members:
 99 |     :undoc-members:
100 |     :show-inheritance:
101 | 
102 | robot.logging module
103 | --------------------
104 | 
105 | .. automodule:: robot.logging
106 |     :members:
107 |     :undoc-members:
108 |     :show-inheritance:
109 | 
110 | robot.plugin\_loader module
111 | ---------------------------
112 | 
113 | .. automodule:: robot.plugin_loader
114 |     :members:
115 |     :undoc-members:
116 |     :show-inheritance:
117 | 
118 | robot.statistic module
119 | ----------------------
120 | 
121 | .. automodule:: robot.statistic
122 |     :members:
123 |     :undoc-members:
124 |     :show-inheritance:
125 | 
126 | robot.utils module
127 | ------------------
128 | 
129 | .. automodule:: robot.utils
130 |     :members:
131 |     :undoc-members:
132 |     :show-inheritance:
133 | 
134 | 
135 | Module contents
136 | ---------------
137 | 
138 | .. automodule:: robot
139 |     :members:
140 |     :undoc-members:
141 |     :show-inheritance:
142 | 


--------------------------------------------------------------------------------
/docs/_sources/robot.sdk.rst.txt:
--------------------------------------------------------------------------------
 1 | robot.sdk package
 2 | =================
 3 | 
 4 | Submodules
 5 | ----------
 6 | 
 7 | robot.sdk.AbstractPlugin module
 8 | -------------------------------
 9 | 
10 | .. automodule:: robot.sdk.AbstractPlugin
11 |     :members:
12 |     :undoc-members:
13 |     :show-inheritance:
14 | 
15 | robot.sdk.AliSpeech module
16 | --------------------------
17 | 
18 | .. automodule:: robot.sdk.AliSpeech
19 |     :members:
20 |     :undoc-members:
21 |     :show-inheritance:
22 | 
23 | robot.sdk.RASRsdk module
24 | ------------------------
25 | 
26 | .. automodule:: robot.sdk.RASRsdk
27 |     :members:
28 |     :undoc-members:
29 |     :show-inheritance:
30 | 
31 | robot.sdk.TencentSpeech module
32 | ------------------------------
33 | 
34 | .. automodule:: robot.sdk.TencentSpeech
35 |     :members:
36 |     :undoc-members:
37 |     :show-inheritance:
38 | 
39 | robot.sdk.XunfeiSpeech module
40 | -----------------------------
41 | 
42 | .. automodule:: robot.sdk.XunfeiSpeech
43 |     :members:
44 |     :undoc-members:
45 |     :show-inheritance:
46 | 
47 | robot.sdk.unit module
48 | ---------------------
49 | 
50 | .. automodule:: robot.sdk.unit
51 |     :members:
52 |     :undoc-members:
53 |     :show-inheritance:
54 | 
55 | 
56 | Module contents
57 | ---------------
58 | 
59 | .. automodule:: robot.sdk
60 |     :members:
61 |     :undoc-members:
62 |     :show-inheritance:
63 | 


--------------------------------------------------------------------------------
/docs/_sources/snowboy.rst.txt:
--------------------------------------------------------------------------------
 1 | snowboy package
 2 | ===============
 3 | 
 4 | Submodules
 5 | ----------
 6 | 
 7 | snowboy.snowboydecoder module
 8 | -----------------------------
 9 | 
10 | .. automodule:: snowboy.snowboydecoder
11 |     :members:
12 |     :undoc-members:
13 |     :show-inheritance:
14 | 
15 | snowboy.snowboydetect module
16 | ----------------------------
17 | 
18 | .. automodule:: snowboy.snowboydetect
19 |     :members:
20 |     :undoc-members:
21 |     :show-inheritance:
22 | 
23 | 
24 | Module contents
25 | ---------------
26 | 
27 | .. automodule:: snowboy
28 |     :members:
29 |     :undoc-members:
30 |     :show-inheritance:
31 | 


--------------------------------------------------------------------------------
/docs/_sources/statistic.rst.txt:
--------------------------------------------------------------------------------
1 | statistic module
2 | ================
3 | 
4 | .. automodule:: statistic
5 |     :members:
6 |     :undoc-members:
7 |     :show-inheritance:
8 | 


--------------------------------------------------------------------------------
/docs/_sources/utils.rst.txt:
--------------------------------------------------------------------------------
1 | utils module
2 | ============
3 | 
4 | .. automodule:: utils
5 |     :members:
6 |     :undoc-members:
7 |     :show-inheritance:
8 | 


--------------------------------------------------------------------------------
/docs/_sources/wukong.rst.txt:
--------------------------------------------------------------------------------
1 | wukong module
2 | =============
3 | 
4 | .. automodule:: wukong
5 |     :members:
6 |     :undoc-members:
7 |     :show-inheritance:
8 | 


--------------------------------------------------------------------------------
/docs/_static/ajax-loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/ajax-loader.gif


--------------------------------------------------------------------------------
/docs/_static/comment-bright.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/comment-bright.png


--------------------------------------------------------------------------------
/docs/_static/comment-close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/comment-close.png


--------------------------------------------------------------------------------
/docs/_static/comment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/comment.png


--------------------------------------------------------------------------------
/docs/_static/css/badge_only.css:
--------------------------------------------------------------------------------
1 | .fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../fonts/fontawesome-webfont.eot");src:url("../fonts/fontawesome-webfont.eot?#iefix") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff") format("woff"),url("../fonts/fontawesome-webfont.ttf") format("truetype"),url("../fonts/fontawesome-webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}
2 | 


--------------------------------------------------------------------------------
/docs/_static/custom.css:
--------------------------------------------------------------------------------
1 | /* This file intentionally left blank. */
2 | 


--------------------------------------------------------------------------------
/docs/_static/documentation_options.js:
--------------------------------------------------------------------------------
 1 | var DOCUMENTATION_OPTIONS = {
 2 |     URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
 3 |     VERSION: '1.2.0',
 4 |     LANGUAGE: 'zh_CN',
 5 |     COLLAPSE_INDEX: false,
 6 |     FILE_SUFFIX: '.html',
 7 |     HAS_SOURCE: true,
 8 |     SOURCELINK_SUFFIX: '.txt',
 9 |     NAVIGATION_WITH_KEYS: false,
10 | };


--------------------------------------------------------------------------------
/docs/_static/down-pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/down-pressed.png


--------------------------------------------------------------------------------
/docs/_static/down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/down.png


--------------------------------------------------------------------------------
/docs/_static/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/file.png


--------------------------------------------------------------------------------
/docs/_static/fonts/Inconsolata-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Inconsolata-Bold.ttf


--------------------------------------------------------------------------------
/docs/_static/fonts/Inconsolata-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Inconsolata-Regular.ttf


--------------------------------------------------------------------------------
/docs/_static/fonts/Inconsolata.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Inconsolata.ttf


--------------------------------------------------------------------------------
/docs/_static/fonts/Lato-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Lato-Bold.ttf


--------------------------------------------------------------------------------
/docs/_static/fonts/Lato-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Lato-Regular.ttf


--------------------------------------------------------------------------------
/docs/_static/fonts/Lato/lato-bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Lato/lato-bold.eot


--------------------------------------------------------------------------------
/docs/_static/fonts/Lato/lato-bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Lato/lato-bold.ttf


--------------------------------------------------------------------------------
/docs/_static/fonts/Lato/lato-bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Lato/lato-bold.woff


--------------------------------------------------------------------------------
/docs/_static/fonts/Lato/lato-bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Lato/lato-bold.woff2


--------------------------------------------------------------------------------
/docs/_static/fonts/Lato/lato-bolditalic.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Lato/lato-bolditalic.eot


--------------------------------------------------------------------------------
/docs/_static/fonts/Lato/lato-bolditalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Lato/lato-bolditalic.ttf


--------------------------------------------------------------------------------
/docs/_static/fonts/Lato/lato-bolditalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Lato/lato-bolditalic.woff


--------------------------------------------------------------------------------
/docs/_static/fonts/Lato/lato-bolditalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Lato/lato-bolditalic.woff2


--------------------------------------------------------------------------------
/docs/_static/fonts/Lato/lato-italic.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Lato/lato-italic.eot


--------------------------------------------------------------------------------
/docs/_static/fonts/Lato/lato-italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Lato/lato-italic.ttf


--------------------------------------------------------------------------------
/docs/_static/fonts/Lato/lato-italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Lato/lato-italic.woff


--------------------------------------------------------------------------------
/docs/_static/fonts/Lato/lato-italic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Lato/lato-italic.woff2


--------------------------------------------------------------------------------
/docs/_static/fonts/Lato/lato-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Lato/lato-regular.eot


--------------------------------------------------------------------------------
/docs/_static/fonts/Lato/lato-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Lato/lato-regular.ttf


--------------------------------------------------------------------------------
/docs/_static/fonts/Lato/lato-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Lato/lato-regular.woff


--------------------------------------------------------------------------------
/docs/_static/fonts/Lato/lato-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/Lato/lato-regular.woff2


--------------------------------------------------------------------------------
/docs/_static/fonts/RobotoSlab-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/RobotoSlab-Bold.ttf


--------------------------------------------------------------------------------
/docs/_static/fonts/RobotoSlab-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/RobotoSlab-Regular.ttf


--------------------------------------------------------------------------------
/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot


--------------------------------------------------------------------------------
/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf


--------------------------------------------------------------------------------
/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff


--------------------------------------------------------------------------------
/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2


--------------------------------------------------------------------------------
/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot


--------------------------------------------------------------------------------
/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf


--------------------------------------------------------------------------------
/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff


--------------------------------------------------------------------------------
/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2


--------------------------------------------------------------------------------
/docs/_static/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/fontawesome-webfont.eot


--------------------------------------------------------------------------------
/docs/_static/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/fontawesome-webfont.ttf


--------------------------------------------------------------------------------
/docs/_static/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/fontawesome-webfont.woff


--------------------------------------------------------------------------------
/docs/_static/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/fonts/fontawesome-webfont.woff2


--------------------------------------------------------------------------------
/docs/_static/js/theme.js:
--------------------------------------------------------------------------------
1 | /* sphinx_rtd_theme version 0.4.3 | MIT license */
2 | /* Built 20190212 16:02 */
3 | require=function r(s,a,l){function c(e,n){if(!a[e]){if(!s[e]){var i="function"==typeof require&&require;if(!n&&i)return i(e,!0);if(u)return u(e,!0);var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}var o=a[e]={exports:{}};s[e][0].call(o.exports,function(n){return c(s[e][1][n]||n)},o,o.exports,r,s,a,l)}return a[e].exports}for(var u="function"==typeof require&&require,n=0;n<l.length;n++)c(l[n]);return c}({"sphinx-rtd-theme":[function(n,e,i){var jQuery="undefined"!=typeof window?window.jQuery:n("jquery");e.exports.ThemeNav={navBar:null,win:null,winScroll:!1,winResize:!1,linkScroll:!1,winPosition:0,winHeight:null,docHeight:null,isRunning:!1,enable:function(e){var i=this;void 0===e&&(e=!0),i.isRunning||(i.isRunning=!0,jQuery(function(n){i.init(n),i.reset(),i.win.on("hashchange",i.reset),e&&i.win.on("scroll",function(){i.linkScroll||i.winScroll||(i.winScroll=!0,requestAnimationFrame(function(){i.onScroll()}))}),i.win.on("resize",function(){i.winResize||(i.winResize=!0,requestAnimationFrame(function(){i.onResize()}))}),i.onResize()}))},enableSticky:function(){this.enable(!0)},init:function(i){i(document);var t=this;this.navBar=i("div.wy-side-scroll:first"),this.win=i(window),i(document).on("click","[data-toggle='wy-nav-top']",function(){i("[data-toggle='wy-nav-shift']").toggleClass("shift"),i("[data-toggle='rst-versions']").toggleClass("shift")}).on("click",".wy-menu-vertical .current ul li a",function(){var n=i(this);i("[data-toggle='wy-nav-shift']").removeClass("shift"),i("[data-toggle='rst-versions']").toggleClass("shift"),t.toggleCurrent(n),t.hashChange()}).on("click","[data-toggle='rst-current-version']",function(){i("[data-toggle='rst-versions']").toggleClass("shift-up")}),i("table.docutils:not(.field-list,.footnote,.citation)").wrap("<div class='wy-table-responsive'></div>"),i("table.docutils.footnote").wrap("<div class='wy-table-responsive footnote'></div>"),i("table.docutils.citation").wrap("<div class='wy-table-responsive citation'></div>"),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var e=i(this);expand=i('<span class="toctree-expand"></span>'),expand.on("click",function(n){return t.toggleCurrent(e),n.stopPropagation(),!1}),e.prepend(expand)})},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),i=e.find('[href="'+n+'"]');if(0===i.length){var t=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(i=e.find('[href="#'+t.attr("id")+'"]')).length&&(i=e.find('[href="#"]'))}0<i.length&&($(".wy-menu-vertical .current").removeClass("current"),i.addClass("current"),i.closest("li.toctree-l1").addClass("current"),i.closest("li.toctree-l1").parent().addClass("current"),i.closest("li.toctree-l1").addClass("current"),i.closest("li.toctree-l2").addClass("current"),i.closest("li.toctree-l3").addClass("current"),i.closest("li.toctree-l4").addClass("current"),i[0].scrollIntoView())}catch(o){console.log("Error expanding nav for anchor",o)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,i=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(i),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current"),e.siblings().find("li.current").removeClass("current"),e.find("> ul li.current").removeClass("current"),e.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:e.exports.ThemeNav,StickyNav:e.exports.ThemeNav}),function(){for(var r=0,n=["ms","moz","webkit","o"],e=0;e<n.length&&!window.requestAnimationFrame;++e)window.requestAnimationFrame=window[n[e]+"RequestAnimationFrame"],window.cancelAnimationFrame=window[n[e]+"CancelAnimationFrame"]||window[n[e]+"CancelRequestAnimationFrame"];window.requestAnimationFrame||(window.requestAnimationFrame=function(n,e){var i=(new Date).getTime(),t=Math.max(0,16-(i-r)),o=window.setTimeout(function(){n(i+t)},t);return r=i+t,o}),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(n){clearTimeout(n)})}()},{jquery:"jquery"}]},{},["sphinx-rtd-theme"]);


--------------------------------------------------------------------------------
/docs/_static/minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/minus.png


--------------------------------------------------------------------------------
/docs/_static/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/plus.png


--------------------------------------------------------------------------------
/docs/_static/pygments.css:
--------------------------------------------------------------------------------
 1 | .highlight .hll { background-color: #ffffcc }
 2 | .highlight  { background: #f8f8f8; }
 3 | .highlight .c { color: #408080; font-style: italic } /* Comment */
 4 | .highlight .err { border: 1px solid #FF0000 } /* Error */
 5 | .highlight .k { color: #008000; font-weight: bold } /* Keyword */
 6 | .highlight .o { color: #666666 } /* Operator */
 7 | .highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */
 8 | .highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
 9 | .highlight .cp { color: #BC7A00 } /* Comment.Preproc */
10 | .highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
11 | .highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
12 | .highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
13 | .highlight .gd { color: #A00000 } /* Generic.Deleted */
14 | .highlight .ge { font-style: italic } /* Generic.Emph */
15 | .highlight .gr { color: #FF0000 } /* Generic.Error */
16 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
17 | .highlight .gi { color: #00A000 } /* Generic.Inserted */
18 | .highlight .go { color: #888888 } /* Generic.Output */
19 | .highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
20 | .highlight .gs { font-weight: bold } /* Generic.Strong */
21 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
22 | .highlight .gt { color: #0044DD } /* Generic.Traceback */
23 | .highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
24 | .highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
25 | .highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
26 | .highlight .kp { color: #008000 } /* Keyword.Pseudo */
27 | .highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
28 | .highlight .kt { color: #B00040 } /* Keyword.Type */
29 | .highlight .m { color: #666666 } /* Literal.Number */
30 | .highlight .s { color: #BA2121 } /* Literal.String */
31 | .highlight .na { color: #7D9029 } /* Name.Attribute */
32 | .highlight .nb { color: #008000 } /* Name.Builtin */
33 | .highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
34 | .highlight .no { color: #880000 } /* Name.Constant */
35 | .highlight .nd { color: #AA22FF } /* Name.Decorator */
36 | .highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
37 | .highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
38 | .highlight .nf { color: #0000FF } /* Name.Function */
39 | .highlight .nl { color: #A0A000 } /* Name.Label */
40 | .highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
41 | .highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
42 | .highlight .nv { color: #19177C } /* Name.Variable */
43 | .highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
44 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */
45 | .highlight .mb { color: #666666 } /* Literal.Number.Bin */
46 | .highlight .mf { color: #666666 } /* Literal.Number.Float */
47 | .highlight .mh { color: #666666 } /* Literal.Number.Hex */
48 | .highlight .mi { color: #666666 } /* Literal.Number.Integer */
49 | .highlight .mo { color: #666666 } /* Literal.Number.Oct */
50 | .highlight .sa { color: #BA2121 } /* Literal.String.Affix */
51 | .highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
52 | .highlight .sc { color: #BA2121 } /* Literal.String.Char */
53 | .highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */
54 | .highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
55 | .highlight .s2 { color: #BA2121 } /* Literal.String.Double */
56 | .highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
57 | .highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
58 | .highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
59 | .highlight .sx { color: #008000 } /* Literal.String.Other */
60 | .highlight .sr { color: #BB6688 } /* Literal.String.Regex */
61 | .highlight .s1 { color: #BA2121 } /* Literal.String.Single */
62 | .highlight .ss { color: #19177C } /* Literal.String.Symbol */
63 | .highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
64 | .highlight .fm { color: #0000FF } /* Name.Function.Magic */
65 | .highlight .vc { color: #19177C } /* Name.Variable.Class */
66 | .highlight .vg { color: #19177C } /* Name.Variable.Global */
67 | .highlight .vi { color: #19177C } /* Name.Variable.Instance */
68 | .highlight .vm { color: #19177C } /* Name.Variable.Magic */
69 | .highlight .il { color: #666666 } /* Literal.Number.Integer.Long */


--------------------------------------------------------------------------------
/docs/_static/translations.js:
--------------------------------------------------------------------------------
1 | Documentation.addTranslations({"locale": "zh_Hans_CN", "messages": {"%(filename)s &#8212; %(docstitle)s": "%(filename)s &#8212; %(docstitle)s", "&#169; <a href=\"%(path)s\">Copyright</a> %(copyright)s.": "&#169; <a href=\"%(path)s\"> \u7248\u6743\u6240\u6709</a> %(copyright)s.", "&#169; Copyright %(copyright)s.": "&#169; \u7248\u6743\u6240\u6709 %(copyright)s.", ", in ": "\uff0c\u5728", "About these documents": "\u5173\u4e8e\u8fd9\u4e9b\u6587\u6863", "Automatically generated list of changes in version %(version)s": "\u81ea\u52a8\u751f\u6210\u7684 %(version)s \u7248\u672c\u4e2d\u7684\u66f4\u6539\u5217\u8868", "C API changes": "C API \u66f4\u6539", "Changes in Version %(version)s &#8212; %(docstitle)s": "\u66f4\u6539\u53d1\u751f\u5728\u7248\u672c %(version)s&#8212; %(docstitle)s", "Collapse sidebar": "\u6298\u53e0\u8fb9\u680f", "Complete Table of Contents": "\u5b8c\u6574\u7684\u5185\u5bb9\u8868", "Contents": "\u76ee\u5f55", "Copyright": "\u7248\u6743\u6240\u6709", "Created using <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s.": "\u7531 <a href=\"http://sphinx-doc.org/\">Sphinx</a> %(sphinx_version)s \u521b\u5efa\u3002", "Expand sidebar": "\u5c55\u5f00\u8fb9\u680f", "From here you can search these documents. Enter your search\n    words into the box below and click \"search\". Note that the search\n    function will automatically search for all of the words. Pages\n    containing fewer words won't appear in the result list.": "\u5728\u8fd9\u513f\uff0c\u4f60\u53ef\u4ee5\u5bf9\u8fd9\u4e9b\u6587\u6863\u8fdb\u884c\u641c\u7d22\u3002\u5411\u641c\u7d22\u6846\u4e2d\u8f93\u5165\u4f60\u6240\u8981\u641c\u7d22\u7684\u5173\u952e\u5b57\u5e76\u70b9\u51fb\u201c\u641c\u7d22\u201d\u3002\u6ce8\u610f\uff1a\u641c\u7d22\u5f15\u64ce\u4f1a\u81ea\u52a8\u641c\u7d22\u6240\u6709\u7684\u5173\u952e\u5b57\u3002\u5c06\u4e0d\u4f1a\u641c\u7d22\u5230\u90e8\u5206\u5173\u952e\u5b57\u7684\u9875\u9762.", "Full index on one page": "\u4e00\u9875\u7684\u5168\u90e8\u7d22\u5f15", "General Index": "\u603b\u76ee\u5f55", "Global Module Index": "\u5168\u5c40\u6a21\u5757\u7d22\u5f15", "Go": "\u8f6c\u5411", "Hide Search Matches": "\u9690\u85cf\u641c\u7d22\u7ed3\u679c", "Index": "\u7d22\u5f15", "Index &ndash; %(key)s": "\u7d22\u5f15 &ndash; %(key)s", "Index pages by letter": "\u6309\u7167\u5b57\u6bcd\u7684\u7d22\u5f15\u9875", "Indices and tables:": "\u7d22\u5f15\u548c\u8868\u683c\uff1a", "Last updated on %(last_updated)s.": "\u6700\u540e\u66f4\u65b0\u4e8e %(last_updated)s.", "Library changes": "\u5e93\u66f4\u6539", "Navigation": "\u5bfc\u822a", "Next topic": "\u4e0b\u4e00\u4e2a\u4e3b\u9898", "Other changes": "\u5176\u4ed6\u66f4\u6539", "Overview": "\u6982\u8ff0", "Permalink to this definition": "\u6c38\u4e45\u94fe\u63a5\u81f3\u76ee\u6807", "Permalink to this headline": "\u6c38\u4e45\u94fe\u63a5\u81f3\u6807\u9898", "Please activate JavaScript to enable the search\n    functionality.": "\u8bf7\u6fc0\u6d3b JavaScript \u4ee5\u5f00\u542f\u641c\u7d22\u529f\u80fd", "Preparing search...": "\u51c6\u5907\u641c\u7d22\u2026\u2026", "Previous topic": "\u4e0a\u4e00\u4e2a\u4e3b\u9898", "Quick search": "\u5feb\u901f\u641c\u7d22", "Search": "\u641c\u7d22", "Search Page": "\u641c\u7d22\u9875\u9762", "Search Results": "\u641c\u7d22\u7ed3\u679c", "Search finished, found %s page(s) matching the search query.": "\u641c\u7d22\u5b8c\u6210\uff0c\u6709 %s \u4e2a\u9875\u9762\u5339\u914d\u3002", "Search within %(docstitle)s": "\u5728 %(docstitle)s \u4e2d\u641c\u7d22", "Searching": "\u641c\u7d22\u4e2d", "Show Source": "\u663e\u793a\u6e90\u4ee3\u7801", "Table of Contents": "", "This Page": "\u672c\u9875", "Welcome! This is": "\u6b22\u8fce\uff01\u8fd9\u662f", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "\u6ca1\u6709\u4efb\u4f55\u6587\u6863\u5339\u914d\u60a8\u7684\u641c\u7d22\u3002\u8bf7\u786e\u4fdd\u4f60\u8f93\u5165\u7684\u8bcd\u62fc\u5199\u6b63\u786e\u5e76\u9009\u62e9\u4e86\u5408\u9002\u7684\u5206\u7c7b\u3002", "all functions, classes, terms": "\u6240\u7684\u51fd\u6570\uff0c\u7c7b\uff0c\u672f\u8bed", "can be huge": "\u53ef\u80fd\u4f1a\u5f88\u591a", "last updated": "\u6700\u540e\u66f4\u65b0\u4e8e", "lists all sections and subsections": "\u5217\u51fa\u6240\u6709\u7684\u7ae0\u8282\u548c\u90e8\u5206", "next chapter": "\u4e0b\u4e00\u7ae0", "previous chapter": "\u4e0a\u4e00\u7ae0", "quick access to all modules": "\u5feb\u901f\u67e5\u770b\u6240\u6709\u7684\u6a21\u5757", "search": "\u641c\u7d22", "search this documentation": "\u641c\u7d22\u6587\u6863", "the documentation for": "\u8fd9\u4efd\u6587\u6863\u662f"}, "plural_expr": "0"});
2 | 


--------------------------------------------------------------------------------
/docs/_static/up-pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/up-pressed.png


--------------------------------------------------------------------------------
/docs/_static/up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/_static/up.png


--------------------------------------------------------------------------------
/docs/config.html:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  3 | <!DOCTYPE html>
  4 | <!--[if IE 8]><html class="no-js lt-ie9" lang="zh-CN" > <![endif]-->
  5 | <!--[if gt IE 8]><!--> <html class="no-js" lang="zh-CN" > <!--<![endif]-->
  6 | <head>
  7 |   <meta charset="utf-8">
  8 |   
  9 |   <meta name="viewport" content="width=device-width, initial-scale=1.0">
 10 |   
 11 |   <title>config module &mdash; wukong-robot 1.2.0 文档</title>
 12 |   
 13 | 
 14 |   
 15 |   
 16 |   
 17 |   
 18 | 
 19 |   
 20 |   <script type="text/javascript" src="_static/js/modernizr.min.js"></script>
 21 |   
 22 |     
 23 |       <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
 24 |         <script type="text/javascript" src="_static/jquery.js"></script>
 25 |         <script type="text/javascript" src="_static/underscore.js"></script>
 26 |         <script type="text/javascript" src="_static/doctools.js"></script>
 27 |         <script type="text/javascript" src="_static/language_data.js"></script>
 28 |         <script type="text/javascript" src="_static/translations.js"></script>
 29 |     
 30 |     <script type="text/javascript" src="_static/js/theme.js"></script>
 31 | 
 32 |     
 33 | 
 34 |   
 35 |   <link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
 36 |   <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
 37 |     <link rel="index" title="索引" href="genindex.html" />
 38 |     <link rel="search" title="搜索" href="search.html" /> 
 39 | </head>
 40 | 
 41 | <body class="wy-body-for-nav">
 42 | 
 43 |    
 44 |   <div class="wy-grid-for-nav">
 45 |     
 46 |     <nav data-toggle="wy-nav-shift" class="wy-nav-side">
 47 |       <div class="wy-side-scroll">
 48 |         <div class="wy-side-nav-search" >
 49 |           
 50 | 
 51 |           
 52 |             <a href="index.html" class="icon icon-home"> wukong-robot
 53 |           
 54 | 
 55 |           
 56 |           </a>
 57 | 
 58 |           
 59 |             
 60 |             
 61 |           
 62 | 
 63 |           
 64 | <div role="search">
 65 |   <form id="rtd-search-form" class="wy-form" action="search.html" method="get">
 66 |     <input type="text" name="q" placeholder="Search docs" />
 67 |     <input type="hidden" name="check_keywords" value="yes" />
 68 |     <input type="hidden" name="area" value="default" />
 69 |   </form>
 70 | </div>
 71 | 
 72 |           
 73 |         </div>
 74 | 
 75 |         <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
 76 |           
 77 |             
 78 |             
 79 |               
 80 |             
 81 |             
 82 |               <!-- Local TOC -->
 83 |               <div class="local-toc"><ul>
 84 | <li><a class="reference internal" href="#">config module</a></li>
 85 | </ul>
 86 | </div>
 87 |             
 88 |           
 89 |         </div>
 90 |       </div>
 91 |     </nav>
 92 | 
 93 |     <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
 94 | 
 95 |       
 96 |       <nav class="wy-nav-top" aria-label="top navigation">
 97 |         
 98 |           <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
 99 |           <a href="index.html">wukong-robot</a>
100 |         
101 |       </nav>
102 | 
103 | 
104 |       <div class="wy-nav-content">
105 |         
106 |         <div class="rst-content">
107 |         
108 |           
109 | 
110 | 
111 | 
112 | 
113 | 
114 | 
115 | 
116 | 
117 | 
118 | 
119 | 
120 | 
121 | 
122 | 
123 | 
124 | <div role="navigation" aria-label="breadcrumbs navigation">
125 | 
126 |   <ul class="wy-breadcrumbs">
127 |     
128 |       <li><a href="index.html">Docs</a> &raquo;</li>
129 |         
130 |       <li>config module</li>
131 |     
132 |     
133 |       <li class="wy-breadcrumbs-aside">
134 |         
135 |             
136 |             <a href="_sources/config.rst.txt" rel="nofollow"> View page source</a>
137 |           
138 |         
139 |       </li>
140 |     
141 |   </ul>
142 | 
143 |   
144 |   <hr/>
145 | </div>
146 |           <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
147 |            <div itemprop="articleBody">
148 |             
149 |   <div class="section" id="config-module">
150 | <h1>config module<a class="headerlink" href="#config-module" title="永久链接至标题">¶</a></h1>
151 | </div>
152 | 
153 | 
154 |            </div>
155 |            
156 |           </div>
157 |           <footer>
158 |   
159 | 
160 |   <hr/>
161 | 
162 |   <div role="contentinfo">
163 |     <p>
164 |         &copy; Copyright 2019, wzpan
165 | 
166 |     </p>
167 |   </div>
168 |   Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. 
169 | 
170 | </footer>
171 | 
172 |         </div>
173 |       </div>
174 | 
175 |     </section>
176 | 
177 |   </div>
178 |   
179 | 
180 | 
181 |   <script type="text/javascript">
182 |       jQuery(function () {
183 |           SphinxRtdTheme.Navigation.enable(true);
184 |       });
185 |   </script>
186 | 
187 |   
188 |   
189 |     
190 |    
191 | 
192 | </body>
193 | </html>


--------------------------------------------------------------------------------
/docs/constants.html:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  3 | <!DOCTYPE html>
  4 | <!--[if IE 8]><html class="no-js lt-ie9" lang="zh-CN" > <![endif]-->
  5 | <!--[if gt IE 8]><!--> <html class="no-js" lang="zh-CN" > <!--<![endif]-->
  6 | <head>
  7 |   <meta charset="utf-8">
  8 |   
  9 |   <meta name="viewport" content="width=device-width, initial-scale=1.0">
 10 |   
 11 |   <title>constants module &mdash; wukong-robot 1.2.0 文档</title>
 12 |   
 13 | 
 14 |   
 15 |   
 16 |   
 17 |   
 18 | 
 19 |   
 20 |   <script type="text/javascript" src="_static/js/modernizr.min.js"></script>
 21 |   
 22 |     
 23 |       <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
 24 |         <script type="text/javascript" src="_static/jquery.js"></script>
 25 |         <script type="text/javascript" src="_static/underscore.js"></script>
 26 |         <script type="text/javascript" src="_static/doctools.js"></script>
 27 |         <script type="text/javascript" src="_static/language_data.js"></script>
 28 |         <script type="text/javascript" src="_static/translations.js"></script>
 29 |     
 30 |     <script type="text/javascript" src="_static/js/theme.js"></script>
 31 | 
 32 |     
 33 | 
 34 |   
 35 |   <link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
 36 |   <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
 37 |     <link rel="index" title="索引" href="genindex.html" />
 38 |     <link rel="search" title="搜索" href="search.html" /> 
 39 | </head>
 40 | 
 41 | <body class="wy-body-for-nav">
 42 | 
 43 |    
 44 |   <div class="wy-grid-for-nav">
 45 |     
 46 |     <nav data-toggle="wy-nav-shift" class="wy-nav-side">
 47 |       <div class="wy-side-scroll">
 48 |         <div class="wy-side-nav-search" >
 49 |           
 50 | 
 51 |           
 52 |             <a href="index.html" class="icon icon-home"> wukong-robot
 53 |           
 54 | 
 55 |           
 56 |           </a>
 57 | 
 58 |           
 59 |             
 60 |             
 61 |           
 62 | 
 63 |           
 64 | <div role="search">
 65 |   <form id="rtd-search-form" class="wy-form" action="search.html" method="get">
 66 |     <input type="text" name="q" placeholder="Search docs" />
 67 |     <input type="hidden" name="check_keywords" value="yes" />
 68 |     <input type="hidden" name="area" value="default" />
 69 |   </form>
 70 | </div>
 71 | 
 72 |           
 73 |         </div>
 74 | 
 75 |         <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
 76 |           
 77 |             
 78 |             
 79 |               
 80 |             
 81 |             
 82 |               <!-- Local TOC -->
 83 |               <div class="local-toc"><ul>
 84 | <li><a class="reference internal" href="#">constants module</a></li>
 85 | </ul>
 86 | </div>
 87 |             
 88 |           
 89 |         </div>
 90 |       </div>
 91 |     </nav>
 92 | 
 93 |     <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
 94 | 
 95 |       
 96 |       <nav class="wy-nav-top" aria-label="top navigation">
 97 |         
 98 |           <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
 99 |           <a href="index.html">wukong-robot</a>
100 |         
101 |       </nav>
102 | 
103 | 
104 |       <div class="wy-nav-content">
105 |         
106 |         <div class="rst-content">
107 |         
108 |           
109 | 
110 | 
111 | 
112 | 
113 | 
114 | 
115 | 
116 | 
117 | 
118 | 
119 | 
120 | 
121 | 
122 | 
123 | 
124 | <div role="navigation" aria-label="breadcrumbs navigation">
125 | 
126 |   <ul class="wy-breadcrumbs">
127 |     
128 |       <li><a href="index.html">Docs</a> &raquo;</li>
129 |         
130 |       <li>constants module</li>
131 |     
132 |     
133 |       <li class="wy-breadcrumbs-aside">
134 |         
135 |             
136 |             <a href="_sources/constants.rst.txt" rel="nofollow"> View page source</a>
137 |           
138 |         
139 |       </li>
140 |     
141 |   </ul>
142 | 
143 |   
144 |   <hr/>
145 | </div>
146 |           <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
147 |            <div itemprop="articleBody">
148 |             
149 |   <div class="section" id="constants-module">
150 | <h1>constants module<a class="headerlink" href="#constants-module" title="永久链接至标题">¶</a></h1>
151 | </div>
152 | 
153 | 
154 |            </div>
155 |            
156 |           </div>
157 |           <footer>
158 |   
159 | 
160 |   <hr/>
161 | 
162 |   <div role="contentinfo">
163 |     <p>
164 |         &copy; Copyright 2019, wzpan
165 | 
166 |     </p>
167 |   </div>
168 |   Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. 
169 | 
170 | </footer>
171 | 
172 |         </div>
173 |       </div>
174 | 
175 |     </section>
176 | 
177 |   </div>
178 |   
179 | 
180 | 
181 |   <script type="text/javascript">
182 |       jQuery(function () {
183 |           SphinxRtdTheme.Navigation.enable(true);
184 |       });
185 |   </script>
186 | 
187 |   
188 |   
189 |     
190 |    
191 | 
192 | </body>
193 | </html>


--------------------------------------------------------------------------------
/docs/objects.inv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/docs/objects.inv


--------------------------------------------------------------------------------
/docs/utils.html:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  3 | <!DOCTYPE html>
  4 | <!--[if IE 8]><html class="no-js lt-ie9" lang="zh-CN" > <![endif]-->
  5 | <!--[if gt IE 8]><!--> <html class="no-js" lang="zh-CN" > <!--<![endif]-->
  6 | <head>
  7 |   <meta charset="utf-8">
  8 |   
  9 |   <meta name="viewport" content="width=device-width, initial-scale=1.0">
 10 |   
 11 |   <title>utils module &mdash; wukong-robot 1.2.0 文档</title>
 12 |   
 13 | 
 14 |   
 15 |   
 16 |   
 17 |   
 18 | 
 19 |   
 20 |   <script type="text/javascript" src="_static/js/modernizr.min.js"></script>
 21 |   
 22 |     
 23 |       <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
 24 |         <script type="text/javascript" src="_static/jquery.js"></script>
 25 |         <script type="text/javascript" src="_static/underscore.js"></script>
 26 |         <script type="text/javascript" src="_static/doctools.js"></script>
 27 |         <script type="text/javascript" src="_static/language_data.js"></script>
 28 |         <script type="text/javascript" src="_static/translations.js"></script>
 29 |     
 30 |     <script type="text/javascript" src="_static/js/theme.js"></script>
 31 | 
 32 |     
 33 | 
 34 |   
 35 |   <link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
 36 |   <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
 37 |     <link rel="index" title="索引" href="genindex.html" />
 38 |     <link rel="search" title="搜索" href="search.html" /> 
 39 | </head>
 40 | 
 41 | <body class="wy-body-for-nav">
 42 | 
 43 |    
 44 |   <div class="wy-grid-for-nav">
 45 |     
 46 |     <nav data-toggle="wy-nav-shift" class="wy-nav-side">
 47 |       <div class="wy-side-scroll">
 48 |         <div class="wy-side-nav-search" >
 49 |           
 50 | 
 51 |           
 52 |             <a href="index.html" class="icon icon-home"> wukong-robot
 53 |           
 54 | 
 55 |           
 56 |           </a>
 57 | 
 58 |           
 59 |             
 60 |             
 61 |           
 62 | 
 63 |           
 64 | <div role="search">
 65 |   <form id="rtd-search-form" class="wy-form" action="search.html" method="get">
 66 |     <input type="text" name="q" placeholder="Search docs" />
 67 |     <input type="hidden" name="check_keywords" value="yes" />
 68 |     <input type="hidden" name="area" value="default" />
 69 |   </form>
 70 | </div>
 71 | 
 72 |           
 73 |         </div>
 74 | 
 75 |         <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
 76 |           
 77 |             
 78 |             
 79 |               
 80 |             
 81 |             
 82 |               <!-- Local TOC -->
 83 |               <div class="local-toc"><ul>
 84 | <li><a class="reference internal" href="#">utils module</a></li>
 85 | </ul>
 86 | </div>
 87 |             
 88 |           
 89 |         </div>
 90 |       </div>
 91 |     </nav>
 92 | 
 93 |     <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
 94 | 
 95 |       
 96 |       <nav class="wy-nav-top" aria-label="top navigation">
 97 |         
 98 |           <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
 99 |           <a href="index.html">wukong-robot</a>
100 |         
101 |       </nav>
102 | 
103 | 
104 |       <div class="wy-nav-content">
105 |         
106 |         <div class="rst-content">
107 |         
108 |           
109 | 
110 | 
111 | 
112 | 
113 | 
114 | 
115 | 
116 | 
117 | 
118 | 
119 | 
120 | 
121 | 
122 | 
123 | 
124 | <div role="navigation" aria-label="breadcrumbs navigation">
125 | 
126 |   <ul class="wy-breadcrumbs">
127 |     
128 |       <li><a href="index.html">Docs</a> &raquo;</li>
129 |         
130 |       <li>utils module</li>
131 |     
132 |     
133 |       <li class="wy-breadcrumbs-aside">
134 |         
135 |             
136 |             <a href="_sources/utils.rst.txt" rel="nofollow"> View page source</a>
137 |           
138 |         
139 |       </li>
140 |     
141 |   </ul>
142 | 
143 |   
144 |   <hr/>
145 | </div>
146 |           <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
147 |            <div itemprop="articleBody">
148 |             
149 |   <div class="section" id="utils-module">
150 | <h1>utils module<a class="headerlink" href="#utils-module" title="永久链接至标题">¶</a></h1>
151 | </div>
152 | 
153 | 
154 |            </div>
155 |            
156 |           </div>
157 |           <footer>
158 |   
159 | 
160 |   <hr/>
161 | 
162 |   <div role="contentinfo">
163 |     <p>
164 |         &copy; Copyright 2019, wzpan
165 | 
166 |     </p>
167 |   </div>
168 |   Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. 
169 | 
170 | </footer>
171 | 
172 |         </div>
173 |       </div>
174 | 
175 |     </section>
176 | 
177 |   </div>
178 |   
179 | 
180 | 
181 |   <script type="text/javascript">
182 |       jQuery(function () {
183 |           SphinxRtdTheme.Navigation.enable(true);
184 |       });
185 |   </script>
186 | 
187 |   
188 |   
189 |     
190 |    
191 | 
192 | </body>
193 | </html>


--------------------------------------------------------------------------------
/plugins/Camera.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | import subprocess
 5 | import time
 6 | from robot import config, constants, logging
 7 | from robot.sdk.AbstractPlugin import AbstractPlugin
 8 | 
 9 | logger = logging.getLogger(__name__)
10 | 
11 | 
12 | class Plugin(AbstractPlugin):
13 | 
14 |     SLUG = "camera"
15 | 
16 |     def handle(self, text, parsed):
17 |         quality = config.get("/camera/quality", 100)
18 |         count_down = config.get("/camera/count_down", 3)
19 |         dest_path = config.get("/camera/dest_path", os.path.expanduser("~/pictures"))
20 |         device = config.get("/camera/device", "/dev/video0")
21 |         vertical_flip = config.get("/camera/vetical_flip", False)
22 |         horizontal_flip = config.get("/camera/horizontal_flip", False)
23 |         sound = config.get("/camera/sound", True)
24 |         camera_type = config.get("/camera/type", 0)
25 |         if config.has("/camera/usb_camera") and config.get("/camera/usb_camera"):
26 |             camera_type = 0
27 |         if any(word in text for word in ["安静", "偷偷", "悄悄"]):
28 |             sound = False
29 |         try:
30 |             if not os.path.exists(dest_path):
31 |                 os.makedirs(dest_path)
32 |         except Exception:
33 |             self.say("抱歉,照片目录创建失败", cache=True)
34 |             return
35 |         dest_file = os.path.join(dest_path, "%s.jpg" % time.time()).replace(".", "", 1)
36 |         if camera_type == 0:
37 |             # usb camera
38 |             logger.info("usb camera")
39 |             command = ["fswebcam", "--no-banner", "-r", "1024x765", "-q", "-d", device]
40 |             if vertical_flip:
41 |                 command.extend(["-s", "v"])
42 |             if horizontal_flip:
43 |                 command.extend(["-s", "h"])
44 |             command.append(dest_file)
45 |         elif camera_type == 1:
46 |             # Raspberry Pi 5MP
47 |             logger.info("Raspberry Pi 5MP camera")
48 |             command = ["raspistill", "-o", dest_file, "-q", str(quality)]
49 |             if count_down > 0 and sound:
50 |                 command.extend(["-t", str(count_down * 1000)])
51 |             if vertical_flip:
52 |                 command.append("-vf")
53 |             if horizontal_flip:
54 |                 command.append("-hf")
55 |         else:
56 |             # notebook camera
57 |             logger.info("notebook camera")
58 |             command = ["imagesnap", dest_file]
59 |             if count_down > 0 and sound:
60 |                 command.extend(["-w", str(count_down)])
61 |         if sound and count_down > 0:
62 |             self.say("收到,%d秒后启动拍照" % (count_down), cache=True)
63 |             if camera_type == 0:
64 |                 time.sleep(count_down)
65 | 
66 |         try:
67 |             subprocess.run(command, shell=False, check=True)
68 |             if sound:
69 |                 self.play(constants.getData("camera.wav"))
70 |                 photo_url = "http://{}:{}/photo/{}".format(
71 |                     config.get("/server/host"),
72 |                     config.get("/server/port"),
73 |                     os.path.basename(dest_file),
74 |                 )
75 |                 self.say("拍照成功", cache=True)
76 |                 self.say(photo_url)
77 |         except subprocess.CalledProcessError as e:
78 |             logger.error(e, stack_info=True)
79 |             if sound:
80 |                 self.say("拍照失败,请检查相机是否连接正确", cache=True)
81 | 
82 |     def isValid(self, text, parsed):
83 |         return any(word in text for word in ["拍照", "拍张照"]) and not any(
84 |             word in text for word in ["拍照成功", "拍照失败", "后启动拍照"]
85 |         )
86 | 


--------------------------------------------------------------------------------
/plugins/CleanCache.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | from robot import constants, utils
 5 | from robot.sdk.AbstractPlugin import AbstractPlugin
 6 | 
 7 | 
 8 | class Plugin(AbstractPlugin):
 9 | 
10 |     SLUG = "cleancache"
11 | 
12 |     def handle(self, text, parsed):
13 |         temp = constants.TEMP_PATH
14 |         for f in os.listdir(temp):
15 |             if f != "DIR":
16 |                 utils.check_and_delete(os.path.join(temp, f))
17 |         self.say("缓存目录已清空", cache=True)
18 | 
19 |     def isValid(self, text, parsed):
20 |         return any(word in text.lower() for word in ["清除缓存", "清空缓存", "清缓存"])
21 | 


--------------------------------------------------------------------------------
/plugins/Echo.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | # author: wzpan
 3 | # 回声
 4 | 
 5 | import logging
 6 | from robot.sdk.AbstractPlugin import AbstractPlugin
 7 | 
 8 | logger = logging.getLogger(__name__)
 9 | 
10 | 
11 | class Plugin(AbstractPlugin):
12 |     def handle(self, text, parsed):
13 |         text = text.lower().replace("echo", "").replace("传话", "")
14 |         self.say(text, cache=False)
15 | 
16 |     def isValid(self, text, parsed):
17 |         return any(word in text.lower() for word in ["echo", "传话"])
18 | 


--------------------------------------------------------------------------------
/plugins/Geek.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | from robot import config, logging
 3 | from robot.sdk.AbstractPlugin import AbstractPlugin
 4 | 
 5 | logger = logging.getLogger(__name__)
 6 | 
 7 | 
 8 | class Plugin(AbstractPlugin):
 9 | 
10 |     IS_IMMERSIVE = True  # 这是个沉浸式技能
11 |     SLUG = "geek"
12 | 
13 |     def __init__(self, con):
14 |         super(Plugin, self).__init__(con)
15 |         self.silent_count = 0
16 | 
17 |     def handle(self, text, parsed):
18 |         if any(word in text for word in ["开启", "激活", "开始", "进入", "打开"]):
19 |             self.silent_count = 0
20 |             self.say(
21 |                 "进入极客模式",
22 |                 cache=True,
23 |                 onCompleted=lambda: self.onAsk(self.activeListen(silent=True)),
24 |             )
25 |         else:
26 |             self.say("退出极客模式", cache=True)
27 |             self.clearImmersive()
28 | 
29 |     def onAsk(self, input):
30 |         if input:
31 |             logger.debug(f"input: {input}")
32 |             self.silent_count = 0
33 |             self.con.doResponse(input)
34 |         else:
35 |             self.silent_count += 1
36 |             if self.silent_count >= config.get("/geek/max_silent_count", 20):
37 |                 self.say("退出极客模式", cache=True)
38 |                 self.clearImmersive()
39 |             else:
40 |                 self.onAsk(self.activeListen(silent=True))
41 | 
42 |     def restore(self):
43 |         self.onAsk(self.activeListen(silent=True))
44 | 
45 |     def isValidImmersive(self, text, parsed):
46 |         return (
47 |             "模式" in text
48 |             and any(word in text for word in ["即刻", "即可", "极客", "即客", "集团", "集客"])
49 |             and any(word in text for word in ["退出", "结束", "停止"])
50 |         )
51 | 
52 |     def isValid(self, text, parsed):
53 |         return (
54 |             "模式" in text
55 |             and any(word in text for word in ["即刻", "即可", "即客", "集团", "极客", "集客"])
56 |             and any(word in text for word in ["开启", "激活", "开始", "进入", "打开"])
57 |         )
58 | 


--------------------------------------------------------------------------------
/plugins/Gossip.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | # author: wzpan
 3 | # 闲聊一下
 4 | 
 5 | import logging
 6 | from robot.sdk.AbstractPlugin import AbstractPlugin
 7 | 
 8 | logger = logging.getLogger(__name__)
 9 | 
10 | ENTRY_WORDS = ["进入", "打开", "激活", "开启", "一下"]
11 | CLOSE_WORDS = ["退出", "结束", "停止"]
12 | 
13 | 
14 | class Plugin(AbstractPlugin):
15 | 
16 |     IS_IMMERSIVE = True
17 | 
18 |     def handle(self, text, parsed):
19 | 
20 |         if "闲聊一下" in text or "进入闲聊" in text:
21 |             # 进入闲聊模式
22 |             self.say("好的,已进入闲聊模式", cache=True)
23 |         else:
24 |             self.clearImmersive()  # 去掉沉浸式
25 |             self.say("结束闲聊", cache=True)
26 | 
27 |     def isValidImmersive(self, text, parsed):
28 |         return "闲聊" in text and any(word in text for word in CLOSE_WORDS)
29 | 
30 |     def isValid(self, text, parsed):
31 |         return "闲聊" in text and any(word in text for word in ENTRY_WORDS)
32 | 


--------------------------------------------------------------------------------
/plugins/LocalPlayer.py:
--------------------------------------------------------------------------------
  1 | # -*- coding: utf-8 -*-
  2 | import os
  3 | import platform
  4 | 
  5 | from robot import config, logging
  6 | from robot.Player import MusicPlayer
  7 | from robot.sdk.AbstractPlugin import AbstractPlugin
  8 | 
  9 | logger = logging.getLogger(__name__)
 10 | 
 11 | 
 12 | class Plugin(AbstractPlugin):
 13 | 
 14 |     IS_IMMERSIVE = True  # 这是个沉浸式技能
 15 | 
 16 |     def __init__(self, con):
 17 |         super(Plugin, self).__init__(con)
 18 |         self.player = None
 19 |         self.song_list = None
 20 | 
 21 |     def get_song_list(self, path):
 22 |         if not os.path.exists(path) or not os.path.isdir(path):
 23 |             return []
 24 |         song_list = list(
 25 |             filter(lambda d: d.endswith(".mp3") or d.endswith("wav"), os.listdir(path))
 26 |         )
 27 |         return [os.path.join(path, song) for song in song_list]
 28 | 
 29 |     def init_music_player(self):
 30 |         self.song_list = self.get_song_list(config.get("/LocalPlayer/path"))
 31 |         if self.song_list == None:
 32 |             logger.error(f"{self.SLUG} 插件配置有误", stack_info=True)
 33 |         logger.info(f"本地音乐列表:{self.song_list}")
 34 |         return MusicPlayer(self.song_list, self)
 35 | 
 36 |     def handle(self, text, parsed):
 37 |         if not self.player:
 38 |             self.player = self.init_music_player()
 39 |         if len(self.song_list) == 0:
 40 |             self.clearImmersive()  # 去掉沉浸式
 41 |             self.say("本地音乐目录并没有音乐文件,播放失败")
 42 |             return
 43 |         if self.nlu.hasIntent(parsed, "MUSICRANK"):
 44 |             self.player.play()
 45 |         elif self.nlu.hasIntent(parsed, "CHANGE_TO_NEXT"):
 46 |             self.player.next()
 47 |         elif self.nlu.hasIntent(parsed, "CHANGE_TO_LAST"):
 48 |             self.player.prev()
 49 |         elif self.nlu.hasIntent(parsed, "CHANGE_VOL"):
 50 |             slots = self.nlu.getSlots(parsed, "CHANGE_VOL")
 51 |             for slot in slots:
 52 |                 if slot["name"] == "user_d":
 53 |                     word = self.nlu.getSlotWords(parsed, "CHANGE_VOL", "user_d")[0]
 54 |                     if word == "--HIGHER--":
 55 |                         self.player.turnUp()
 56 |                     else:
 57 |                         self.player.turnDown()
 58 |                     return
 59 |                 elif slot["name"] == "user_vd":
 60 |                     word = self.nlu.getSlotWords(parsed, "CHANGE_VOL", "user_vd")[0]
 61 |                     if word == "--LOUDER--":
 62 |                         self.player.turnUp()
 63 |                     else:
 64 |                         self.player.turnDown()
 65 | 
 66 |         elif self.nlu.hasIntent(parsed, "CONTINUE"):
 67 |             logger.info("继续播放")
 68 |             self.player.resume()
 69 |         elif self.nlu.hasIntent(parsed, "CLOSE_MUSIC") or self.nlu.hasIntent(
 70 |             parsed, "PAUSE"
 71 |         ):
 72 |             logger.info("停止播放")
 73 |             self.player.stop()
 74 |             self.clearImmersive()  # 去掉沉浸式
 75 |         else:
 76 |             self.say("没听懂你的意思呢,要停止播放,请说停止播放")
 77 |             self.player.resume()
 78 | 
 79 |     def pause(self):
 80 |         if self.player:
 81 |             system = platform.system()
 82 |             # BigSur 以上 Mac 系统的 pkill 无法正常暂停音频,
 83 |             # 因此改成直接停止播放,不再支持沉浸模式
 84 |             if system == "Darwin" and float(platform.mac_ver()[0][:5]) >= 10.16:
 85 |                 logger.warning("注意:Mac BigSur 以上系统无法正常暂停音频,将停止播放,不支持恢复播放")
 86 |                 self.player.stop()
 87 |                 return
 88 |             self.player.pause()
 89 | 
 90 |     def restore(self):
 91 |         if self.player and self.player.is_pausing():
 92 |             self.player.resume()
 93 | 
 94 |     def isValidImmersive(self, text, parsed):
 95 |         return any(
 96 |             self.nlu.hasIntent(parsed, intent)
 97 |             for intent in [
 98 |                 "CHANGE_TO_LAST",
 99 |                 "CHANGE_TO_NEXT",
100 |                 "CHANGE_VOL",
101 |                 "CLOSE_MUSIC",
102 |                 "PAUSE",
103 |                 "CONTINUE",
104 |             ]
105 |         )
106 | 
107 |     def isValid(self, text, parsed):
108 |         return "本地音乐" in text
109 | 


--------------------------------------------------------------------------------
/plugins/Poem.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | # author: wzpan
 3 | # 写诗
 4 | 
 5 | import logging
 6 | from robot.sdk.AbstractPlugin import AbstractPlugin
 7 | 
 8 | INTENT = "BUILT_POEM"
 9 | 
10 | logger = logging.getLogger(__name__)
11 | 
12 | 
13 | class Plugin(AbstractPlugin):
14 | 
15 |     SLUG = "poem"
16 | 
17 |     def handle(self, text, parsed):
18 |         try:
19 |             responds = self.nlu.getSay(parsed, INTENT)
20 |             self.say(responds, cache=True)
21 |         except Exception as e:
22 |             logger.error(e, stack_info=True)
23 |             self.say("抱歉,写诗插件出问题了,请稍后再试", cache=True)
24 | 
25 |     def isValid(self, text, parsed):
26 |         return self.nlu.hasIntent(parsed, INTENT) and "写" in text and "诗" in text
27 | 


--------------------------------------------------------------------------------
/plugins/Volume.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | from robot.Player import MusicPlayer
 3 | from robot import logging
 4 | from robot.sdk.AbstractPlugin import AbstractPlugin
 5 | 
 6 | logger = logging.getLogger(__name__)
 7 | 
 8 | 
 9 | class Plugin(AbstractPlugin):
10 |     def __init__(self, con):
11 |         super(Plugin, self).__init__(con)
12 |         self.player = None
13 | 
14 |     def handle(self, text, parsed):
15 |         if not self.player:
16 |             self.player = MusicPlayer([], self)
17 |         if self.nlu.hasIntent(parsed, "CHANGE_VOL"):
18 |             slots = self.nlu.getSlots(parsed, "CHANGE_VOL")
19 |             for slot in slots:
20 |                 if slot["name"] == "user_d":
21 |                     word = self.nlu.getSlotWords(parsed, "CHANGE_VOL", "user_d")[0]
22 |                     if word == "--HIGHER--":
23 |                         self.player.turnUp()
24 |                         self.say("好的", cache=True)
25 |                     else:
26 |                         self.player.turnDown()
27 |                         self.say("好的", cache=True)
28 |                     return
29 |                 elif slot["name"] == "user_vd":
30 |                     word = self.nlu.getSlotWords(parsed, "CHANGE_VOL", "user_vd")[0]
31 |                     if word == "--LOUDER--":
32 |                         self.player.turnUp()
33 |                         self.say("好的", cache=True)
34 |                     else:
35 |                         self.player.turnDown()
36 |                         self.say("好的", cache=True)
37 | 
38 |     def isValid(self, text, parsed):
39 |         return self.nlu.hasIntent(parsed, "CHANGE_VOL")
40 | 


--------------------------------------------------------------------------------
/plugins/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/plugins/__init__.py


--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
 1 | pyyaml>=4.2b1
 2 | requests==2.31.0
 3 | baidu-aip==2.0.0.1
 4 | pydub==0.23.1
 5 | python-dateutil==2.7.5
 6 | watchdog==0.9.0
 7 | pytz==2018.9
 8 | fire==0.1.3
 9 | tornado==6.3.3
10 | markdown==3.0.1
11 | semver==2.8.1
12 | websocket==0.2.1
13 | websocket-client
14 | pypinyin
15 | jieba
16 | pvporcupine
17 | pvrecorder==1.1.1
18 | openai
19 | apscheduler
20 | asyncio
21 | edge-tts
22 | nest_asyncio
23 | funasr_onnx
24 | 


--------------------------------------------------------------------------------
/robot/BCI.py:
--------------------------------------------------------------------------------
 1 | import importlib
 2 | import multiprocessing
 3 | from robot import config, logging
 4 | from datetime import datetime, timedelta
 5 | 
 6 | logger = logging.getLogger(__name__)
 7 | 
 8 | 
 9 | class MuseBCI(object):
10 |     def __init__(self, event):
11 |         self._wakeup_event = event
12 |         self.last_blink = datetime.now() - timedelta(days=1.5)
13 |         self.last_jaw = datetime.now() - timedelta(days=1.5)
14 | 
15 |     def start(self):
16 |         osc_process = multiprocessing.Process(target=self._start_osc)
17 |         osc_process.start()
18 | 
19 |     def blink_handler(self, unused_addr, args, blink):
20 |         if blink:
21 |             logger.info("blink detected")
22 |             self.last_blink = datetime.now()
23 |             if (self.last_blink - self.last_jaw) <= timedelta(seconds=1):
24 |                 self._wakeup_event.set()
25 | 
26 |     def jaw_clench_handler(self, unused_addr, args, jaw):
27 |         if jaw:
28 |             logger.info("Jaw_Clench detected")
29 |             self.last_jaw = datetime.now()
30 |             if (self.last_jaw - self.last_blink) <= timedelta(seconds=1):
31 |                 self._wakeup_event.set()
32 | 
33 |     def _start_osc(self):
34 |         if not importlib.util.find_spec("pythonosc"):
35 |             logger.critical("错误:请先安装 python-osc !")
36 |             return
37 | 
38 |         from pythonosc import dispatcher as dsp
39 |         from pythonosc import osc_server
40 | 
41 |         dispatcher = dsp.Dispatcher()
42 |         dispatcher.map("/muse/elements/blink", self.blink_handler, "EEG")
43 |         dispatcher.map("/muse/elements/jaw_clench", self.jaw_clench_handler, "EEG")
44 | 
45 |         try:
46 |             server = osc_server.ThreadingOSCUDPServer(
47 |                 (
48 |                     config.get("/muse/ip", "127.0.0.1"),
49 |                     int(config.get("/muse/port", "5001")),
50 |                 ),
51 |                 dispatcher,
52 |             )
53 |             logger.info(f"Muse serving on {server.server_address}")
54 |             server.serve_forever()
55 |         except Exception as e:
56 |             logger.error(e, stack_info=True)
57 | 


--------------------------------------------------------------------------------
/robot/Brain.py:
--------------------------------------------------------------------------------
  1 | # -*- coding: utf-8 -*-
  2 | import re
  3 | import traceback
  4 | 
  5 | from robot import config
  6 | from robot import logging
  7 | from . import plugin_loader
  8 | 
  9 | logger = logging.getLogger(__name__)
 10 | 
 11 | 
 12 | class Brain(object):
 13 |     def __init__(self, conversation):
 14 |         """
 15 |         大脑模块,负责处理技能的匹配和响应
 16 | 
 17 |         参数:
 18 |         conversation -- 管理对话
 19 |         """
 20 |         self.conversation = conversation
 21 |         self.plugins = plugin_loader.get_plugins(self.conversation)
 22 |         self.handling = False
 23 | 
 24 |     def match(self, patterns, text):
 25 |         for pattern in patterns:
 26 |             if re.match(pattern, text):
 27 |                 return True
 28 |         return False
 29 | 
 30 |     def isValid(self, plugin, text, parsed):
 31 |         patterns = config.get(f"/{plugin.SLUG}/patterns", [])
 32 |         if len(patterns) > 0:
 33 |             return plugin.isValid(text, parsed) or self.match(patterns, text)
 34 |         else:
 35 |             return plugin.isValid(text, parsed)
 36 | 
 37 |     def isValidImmersive(self, plugin, text, parsed):
 38 |         patterns = config.get(f"/{plugin.SLUG}/patterns", [])
 39 |         if len(patterns) > 0:
 40 |             return plugin.isValidImmersive(text, parsed) or self.match(patterns, text)
 41 |         else:
 42 |             return plugin.isValidImmersive(text, parsed)
 43 | 
 44 |     def isImmersive(self, plugin, text, parsed):
 45 |         return (
 46 |             self.conversation.getImmersiveMode() == plugin.SLUG
 47 |             and self.isValidImmersive(plugin, text, parsed)
 48 |         )
 49 | 
 50 |     def printPlugins(self):
 51 |         plugin_list = []
 52 |         for plugin in self.plugins:
 53 |             plugin_list.append(plugin.SLUG)
 54 |         logger.info(f"已激活插件:{plugin_list}")
 55 | 
 56 |     def query(self, text, parsed):
 57 |         """
 58 |         query 模块
 59 | 
 60 |         Arguments:
 61 |         text -- 原文本
 62 |         parsed -- ULU解析出来的结果
 63 |         """
 64 | 
 65 |         for plugin in self.plugins:
 66 |             if not self.isValid(plugin, text, parsed) and not self.isImmersive(
 67 |                 plugin, text, parsed
 68 |             ):
 69 |                 continue
 70 | 
 71 |             logger.info(f"'{text}' 命中技能 {plugin.SLUG}")
 72 |             self.conversation.matchPlugin = plugin.SLUG
 73 | 
 74 |             if plugin.IS_IMMERSIVE:
 75 |                 self.conversation.setImmersiveMode(plugin.SLUG)
 76 | 
 77 |             continueHandle = False
 78 |             try:
 79 |                 self.handling = True
 80 |                 continueHandle = plugin.handle(text, parsed)
 81 |                 self.handling = False
 82 |             except Exception as e:
 83 |                 logger.critical(f"Failed to execute plugin: {e}", stack_info=True)
 84 |                 traceback.print_exc()
 85 |                 reply = f"抱歉,插件{plugin.SLUG}出故障了,晚点再试试吧"
 86 |                 self.conversation.say(reply, plugin=plugin.SLUG)
 87 |             else:
 88 |                 logger.debug(
 89 |                     "Handling of phrase '%s' by " + "plugin '%s' completed",
 90 |                     text,
 91 |                     plugin.SLUG,
 92 |                 )
 93 |             finally:
 94 |                 if not continueHandle:
 95 |                     return True
 96 | 
 97 |         logger.debug(f"No plugin was able to handle phrase {text} ")
 98 |         return False
 99 | 
100 |     def restore(self):
101 |         """恢复某个技能的处理"""
102 |         if not self.conversation.immersiveMode:
103 |             return
104 |         for plugin in self.plugins:
105 |             if plugin.SLUG == self.conversation.immersiveMode and plugin.restore:
106 |                 logger.warning(f"{plugin.SLUG}: restore")
107 |                 plugin.restore()
108 | 
109 |     def pause(self):
110 |         """暂停某个技能的处理"""
111 |         if not self.conversation.immersiveMode:
112 |             return
113 |         for plugin in self.plugins:
114 |             if plugin.SLUG == self.conversation.immersiveMode and plugin.pause:
115 |                 plugin.pause()
116 | 
117 |     def understand(self, fp):
118 |         if self.conversation and self.conversation.asr:
119 |             return self.conversation.asr.transcribe(fp)
120 |         return None
121 | 
122 |     def say(self, msg, cache=False):
123 |         if self.conversation and self.conversation.tts:
124 |             self.conversation.tts.say(msg, cache)
125 | 


--------------------------------------------------------------------------------
/robot/ConfigMonitor.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | 
 3 | import os
 4 | from robot import config, utils, logging
 5 | from watchdog.events import FileSystemEventHandler
 6 | 
 7 | logger = logging.getLogger(__name__)
 8 | 
 9 | 
10 | class ConfigMonitor(FileSystemEventHandler):
11 |     def __init__(self, conversation):
12 |         FileSystemEventHandler.__init__(self)
13 |         self._conversation = conversation
14 | 
15 |     # 文件修改
16 |     def on_modified(self, event):
17 |         if event.is_directory:
18 |             return
19 | 
20 |         filename = event.src_path
21 |         extension = os.path.splitext(filename)[-1].lower()
22 |         if extension in (".yaml", ".yml"):
23 |             if utils.validyaml(filename):
24 |                 logger.info(f"检测到文件 {filename} 发生变更")
25 |                 config.reload()
26 |                 self._conversation.reInit()
27 | 


--------------------------------------------------------------------------------
/robot/Updater.py:
--------------------------------------------------------------------------------
  1 | import os
  2 | import requests
  3 | import json
  4 | import semver
  5 | from subprocess import call
  6 | from robot import constants, logging
  7 | from datetime import datetime, timedelta
  8 | 
  9 | logger = logging.getLogger(__name__)
 10 | logger.setLevel(level=logging.INFO)
 11 | 
 12 | _updater = None
 13 | URL = "https://service-e32kknxi-1253537070.ap-hongkong.apigateway.myqcloud.com/release/wukong"
 14 | DEV_URL = "https://service-e32kknxi-1253537070.ap-hongkong.apigateway.myqcloud.com/release/wukong-dev"
 15 | 
 16 | 
 17 | class Updater(object):
 18 |     def __init__(self):
 19 |         self.last_check = datetime.now() - timedelta(days=1.5)
 20 |         self.update_info = {}
 21 | 
 22 |     def _pull(self, cwd, tag):
 23 |         if os.path.exists(cwd):
 24 |             return (
 25 |                 call(
 26 |                     [f"git checkout master && git pull && git checkout {tag}"],
 27 |                     cwd=cwd,
 28 |                     shell=True,
 29 |                 )
 30 |                 == 0
 31 |             )
 32 |         else:
 33 |             logger.error(f"目录 {cwd} 不存在")
 34 |             return False
 35 | 
 36 |     def _pip(self, cwd):
 37 |         if os.path.exists(cwd):
 38 |             return (
 39 |                 call(
 40 |                     ["pip3", "install", "-r", "requirements.txt"], cwd=cwd, shell=False
 41 |                 )
 42 |                 == 0
 43 |             )
 44 |         else:
 45 |             logger.error(f"目录 {cwd} 不存在")
 46 |             return False
 47 | 
 48 |     def update(self):
 49 |         update_info = self.fetch()
 50 |         success = True
 51 |         if update_info == {}:
 52 |             logger.info("恭喜你,wukong-robot 已经是最新!")
 53 |         if "main" in update_info:
 54 |             if self._pull(
 55 |                 constants.APP_PATH, update_info["main"]["version"]
 56 |             ) and self._pip(constants.APP_PATH):
 57 |                 logger.info("wukong-robot 更新成功!")
 58 |                 self.update_info.pop("main")
 59 |             else:
 60 |                 logger.info("wukong-robot 更新失败!")
 61 |                 success = False
 62 |         if "contrib" in update_info:
 63 |             if self._pull(
 64 |                 constants.CONTRIB_PATH, update_info["contrib"]["version"]
 65 |             ) and self._pip(constants.CONTRIB_PATH):
 66 |                 logger.info("wukong-contrib 更新成功!")
 67 |                 self.update_info.pop("contrib")
 68 |             else:
 69 |                 logger.info("wukong-contrib 更新失败!")
 70 |                 success = False
 71 |         return success
 72 | 
 73 |     def _get_version(self, path, current):
 74 |         if os.path.exists(os.path.join(path, "VERSION")):
 75 |             with open(os.path.join(path, "VERSION"), "r") as f:
 76 |                 return f.read().strip()
 77 |         else:
 78 |             return current
 79 | 
 80 |     def fetch(self):
 81 |         global URL, DEV_URL
 82 |         url = URL
 83 |         now = datetime.now()
 84 |         if (now - self.last_check).seconds <= 1800:
 85 |             logger.debug(f"30 分钟内已检查过更新,使用上次的检查结果:{self.update_info}")
 86 |             return self.update_info
 87 |         try:
 88 |             self.last_check = now
 89 |             r = requests.get(url, timeout=3)
 90 |             info = json.loads(r.text)
 91 |             main_version = info["main"]["version"]
 92 |             contrib_version = info["contrib"]["version"]
 93 |             # 检查主仓库
 94 |             current_main_version = self._get_version(constants.APP_PATH, main_version)
 95 |             current_contrib_version = self._get_version(
 96 |                 constants.CONTRIB_PATH, contrib_version
 97 |             )
 98 |             if semver.compare(main_version, current_main_version) > 0:
 99 |                 logger.info(f"主仓库检查到更新:{info['main']}")
100 |                 self.update_info["main"] = info["main"]
101 |             if semver.compare(contrib_version, current_contrib_version) > 0:
102 |                 logger.info(f"插件库检查到更新:{info['contrib']}")
103 |                 self.update_info["contrib"] = info["contrib"]
104 |             if "notices" in info:
105 |                 self.update_info["notices"] = info["notices"]
106 |             return self.update_info
107 |         except Exception as e:
108 |             logger.error(f"检查更新失败:{e}", stack_info=True)
109 |             return {}
110 | 
111 | 
112 | def fetch():
113 |     global _updater
114 |     if not _updater:
115 |         _updater = Updater()
116 |     return _updater.fetch()
117 | 
118 | 
119 | if __name__ == "__main__":
120 |     fetch()
121 | 


--------------------------------------------------------------------------------
/robot/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/robot/__init__.py


--------------------------------------------------------------------------------
/robot/config.py:
--------------------------------------------------------------------------------
  1 | # -*- coding: utf-8 -*-
  2 | import yaml
  3 | import logging
  4 | import os
  5 | from . import constants
  6 | 
  7 | logger = logging.getLogger(__name__)
  8 | 
  9 | _config = {}
 10 | has_init = False
 11 | 
 12 | 
 13 | def reload():
 14 |     """
 15 |     重新加载配置
 16 |     """
 17 |     logger.info("配置文件发生变更,重新加载配置文件")
 18 |     init()
 19 | 
 20 | 
 21 | def init():
 22 |     global has_init
 23 |     if os.path.isfile(constants.CONFIG_PATH):
 24 |         logger.critical(f"错误:{constants.CONFIG_PATH} 应该是个目录,而不应该是个文件")
 25 |     if not os.path.exists(constants.CONFIG_PATH):
 26 |         os.makedirs(constants.CONFIG_PATH)
 27 |     if not os.path.exists(constants.getConfigPath()):
 28 |         yes_no = input(f"配置文件{constants.getConfigPath()}不存在,要创建吗?(y/n)")
 29 |         if yes_no.lower() == "y":
 30 |             constants.newConfig()
 31 |             doInit(constants.getConfigPath())
 32 |         else:
 33 |             doInit(constants.getDefaultConfigPath())
 34 |     else:
 35 |         doInit(constants.getConfigPath())
 36 |     has_init = True
 37 | 
 38 | 
 39 | def doInit(config_file=constants.getDefaultConfigPath()):
 40 |     # Create config dir if it does not exist yet
 41 |     if not os.path.exists(constants.CONFIG_PATH):
 42 |         try:
 43 |             os.makedirs(constants.CONFIG_PATH)
 44 |         except OSError:
 45 |             logger.error(
 46 |                 f"Could not create config dir: '{constants.CONFIG_PATH}'",
 47 |                 stack_info=True,
 48 |             )
 49 |             raise
 50 | 
 51 |     # Check if config dir is writable
 52 |     if not os.access(constants.CONFIG_PATH, os.W_OK):
 53 |         logger.critical(
 54 |             "Config dir %s is not writable. Dingdang " + "won't work correctly.",
 55 |             constants.CONFIG_PATH,
 56 |         )
 57 | 
 58 |     global _config
 59 | 
 60 |     # Read config
 61 |     logger.debug("Trying to read config file: '%s'", config_file)
 62 |     try:
 63 |         with open(config_file, "r") as f:
 64 |             _config = yaml.safe_load(f)
 65 |     except Exception as e:
 66 |         logger.error(f"配置文件 {config_file} 读取失败: {e}", stack_info=True)
 67 |         raise
 68 | 
 69 | 
 70 | def get_path(items, default=None, warn=False):
 71 |     global _config
 72 |     curConfig = _config
 73 |     if isinstance(items, str) and items[0] == "/":
 74 |         items = items.split("/")[1:]
 75 |     for key in items:
 76 |         if key in curConfig:
 77 |             curConfig = curConfig[key]
 78 |         else:
 79 |             if warn:
 80 |                 logger.warning(
 81 |                     "/%s not specified in profile, defaulting to " "'%s'",
 82 |                     "/".join(items),
 83 |                     default,
 84 |                 )
 85 |             else:
 86 |                 logger.debug(
 87 |                     "/%s not specified in profile, defaulting to " "'%s'",
 88 |                     "/".join(items),
 89 |                     default,
 90 |                 )
 91 |             return default
 92 |     return curConfig
 93 | 
 94 | 
 95 | def has_path(items):
 96 |     global _config
 97 |     curConfig = _config
 98 |     if isinstance(items, str) and items[0] == "/":
 99 |         items = items.split("/")[1:]
100 |     else:
101 |         items = [items]
102 |     for key in items:
103 |         if key in curConfig:
104 |             curConfig = curConfig[key]
105 |         else:
106 |             return False
107 |     return True
108 | 
109 | 
110 | def has(item):
111 |     """
112 |     判断配置里是否包含某个配置项
113 | 
114 |     :param item: 配置项名
115 |     :returns: True: 包含; False: 不包含
116 |     """
117 |     return has_path(item)
118 | 
119 | 
120 | def get(item="", default=None, warn=False):
121 |     """
122 |     获取某个配置的值
123 | 
124 |     :param item: 配置项名。如果是多级配置,则以 "/a/b" 的形式提供
125 |     :param default: 默认值(可选)
126 |     :param warn: 不存在该配置时,是否告警
127 |     :returns: 这个配置的值。如果没有该配置,则提供一个默认值
128 |     """
129 |     global has_init
130 |     if not has_init:
131 |         init()
132 |     if not item:
133 |         return _config
134 |     if item[0] == "/":
135 |         return get_path(item, default, warn)
136 |     try:
137 |         return _config[item]
138 |     except KeyError:
139 |         if warn:
140 |             logger.warning(
141 |                 "%s not specified in profile, defaulting to '%s'", item, default
142 |             )
143 |         else:
144 |             logger.debug(
145 |                 "%s not specified in profile, defaulting to '%s'", item, default
146 |             )
147 |         return default
148 | 
149 | 
150 | def getConfig():
151 |     """
152 |     返回全部配置数据
153 | 
154 |     :returns: 全部配置数据(字典类型)
155 |     """
156 |     return _config
157 | 
158 | 
159 | def getText():
160 |     if os.path.exists(constants.getConfigPath()):
161 |         with open(constants.getConfigPath(), "r") as f:
162 |             return f.read()
163 |     return ""
164 | 
165 | 
166 | def dump(configStr):
167 |     with open(constants.getConfigPath(), "w") as f:
168 |         f.write(configStr)
169 | 


--------------------------------------------------------------------------------
/robot/constants.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | import os
 3 | import shutil
 4 | 
 5 | # Wukong main directory
 6 | APP_PATH = os.path.normpath(
 7 |     os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir)
 8 | )
 9 | 
10 | LIB_PATH = os.path.join(APP_PATH, "robot")
11 | DATA_PATH = os.path.join(APP_PATH, "static")
12 | TEMP_PATH = os.path.join(APP_PATH, "temp")
13 | TEMPLATE_PATH = os.path.join(APP_PATH, "server", "templates")
14 | PLUGIN_PATH = os.path.join(APP_PATH, "plugins")
15 | DEFAULT_CONFIG_NAME = "default.yml"
16 | CUSTOM_CONFIG_NAME = "config.yml"
17 | 
18 | CONFIG_PATH = os.path.expanduser(os.getenv("WUKONG_CONFIG", "~/.wukong"))
19 | CONTRIB_PATH = os.path.expanduser(os.getenv("WUKONG_CONFIG", "~/.wukong/contrib"))
20 | CUSTOM_PATH = os.path.expanduser(os.getenv("WUKONG_CONFIG", "~/.wukong/custom"))
21 | 
22 | 
23 | def getConfigPath():
24 |     """
25 |     获取配置文件的路径
26 | 
27 |     returns: 配置文件的存储路径
28 |     """
29 |     return os.path.join(CONFIG_PATH, CUSTOM_CONFIG_NAME)
30 | 
31 | 
32 | def getQAPath():
33 |     """
34 |     获取QA数据集文件的路径
35 | 
36 |     returns: QA数据集文件的存储路径
37 |     """
38 |     qa_source = os.path.join(DATA_PATH, "qa.csv")
39 |     qa_dst = os.path.join(CONFIG_PATH, "qa.csv")
40 |     if not os.path.exists(qa_dst):
41 |         shutil.copyfile(qa_source, qa_dst)
42 |     return qa_dst
43 | 
44 | 
45 | def getConfigData(*fname):
46 |     """
47 |     获取配置目录下的指定文件的路径
48 | 
49 |     :param *fname: 指定文件名。如果传多个,则自动拼接
50 |     :returns: 配置目录下的某个文件的存储路径
51 |     """
52 |     return os.path.join(CONFIG_PATH, *fname)
53 | 
54 | 
55 | def getData(*fname):
56 |     """
57 |     获取资源目录下指定文件的路径
58 | 
59 |     :param *fname: 指定文件名。如果传多个,则自动拼接
60 |     :returns: 配置文件的存储路径
61 |     """
62 |     return os.path.join(DATA_PATH, *fname)
63 | 
64 | 
65 | def getDefaultConfigPath():
66 |     return getData(DEFAULT_CONFIG_NAME)
67 | 
68 | 
69 | def newConfig():
70 |     shutil.copyfile(getDefaultConfigPath(), getConfigPath())
71 | 
72 | 
73 | def getHotwordModel(fname):
74 |     if os.path.exists(getData(fname)):
75 |         return getData(fname)
76 |     else:
77 |         return getConfigData(fname)
78 | 


--------------------------------------------------------------------------------
/robot/detector.py:
--------------------------------------------------------------------------------
  1 | import time
  2 | 
  3 | from snowboy import snowboydecoder
  4 | from robot import config, logging, utils, constants
  5 | 
  6 | logger = logging.getLogger(__name__)
  7 | 
  8 | detector = None
  9 | recorder = None
 10 | porcupine = None
 11 | 
 12 | 
 13 | def initDetector(wukong):
 14 |     """
 15 |     初始化离线唤醒热词监听器,支持 snowboy 和 porcupine 两大引擎
 16 |     """
 17 |     global porcupine, recorder, detector
 18 |     if config.get("detector", "snowboy") == "porcupine":
 19 |         logger.info("使用 porcupine 进行离线唤醒")
 20 | 
 21 |         import pvporcupine
 22 |         from pvrecorder import PvRecorder
 23 | 
 24 |         access_key = config.get("/porcupine/access_key")
 25 |         keyword_paths = config.get("/porcupine/keyword_paths")
 26 |         keywords = config.get("/porcupine/keywords", ["porcupine"])
 27 |         if keyword_paths:
 28 |             porcupine = pvporcupine.create(
 29 |                 access_key=access_key,
 30 |                 keyword_paths=[constants.getConfigData(kw) for kw in keyword_paths],
 31 |                 sensitivities=[config.get("sensitivity", 0.5)] * len(keyword_paths),
 32 |             )
 33 |         else:
 34 |             porcupine = pvporcupine.create(
 35 |                 access_key=access_key,
 36 |                 keywords=keywords,
 37 |                 sensitivities=[config.get("sensitivity", 0.5)] * len(keywords),
 38 |             )
 39 | 
 40 |         recorder = PvRecorder(device_index=-1, frame_length=porcupine.frame_length)
 41 |         recorder.start()
 42 | 
 43 |         try:
 44 |             while True:
 45 |                 pcm = recorder.read()
 46 | 
 47 |                 result = porcupine.process(pcm)
 48 |                 if result >= 0:
 49 |                     kw = keyword_paths[result] if keyword_paths else keywords[result]
 50 |                     logger.info(
 51 |                         "[porcupine] Keyword {} Detected at time {}".format(
 52 |                             kw,
 53 |                             time.strftime(
 54 |                                 "%Y-%m-%d %H:%M:%S", time.localtime(time.time())
 55 |                             ),
 56 |                         )
 57 |                     )
 58 |                     wukong._detected_callback(False)
 59 |                     recorder.stop()
 60 |                     wukong.conversation.interrupt()
 61 |                     query = wukong.conversation.activeListen()
 62 |                     wukong.conversation.doResponse(query)
 63 |                     recorder.start()
 64 |         except pvporcupine.PorcupineActivationError as e:
 65 |             logger.error("[Porcupine] AccessKey activation error", stack_info=True)
 66 |             raise e
 67 |         except pvporcupine.PorcupineActivationLimitError as e:
 68 |             logger.error(
 69 |                 f"[Porcupine] AccessKey {access_key} has reached it's temporary device limit",
 70 |                 stack_info=True,
 71 |             )
 72 |             raise e
 73 |         except pvporcupine.PorcupineActivationRefusedError as e:
 74 |             logger.error(
 75 |                 "[Porcupine] AccessKey '%s' refused" % access_key, stack_info=True
 76 |             )
 77 |             raise e
 78 |         except pvporcupine.PorcupineActivationThrottledError as e:
 79 |             logger.error(
 80 |                 "[Porcupine] AccessKey '%s' has been throttled" % access_key,
 81 |                 stack_info=True,
 82 |             )
 83 |             raise e
 84 |         except pvporcupine.PorcupineError as e:
 85 |             logger.error("[Porcupine] 初始化 Porcupine 失败", stack_info=True)
 86 |             raise e
 87 |         except KeyboardInterrupt:
 88 |             logger.info("Stopping ...")
 89 |         finally:
 90 |             porcupine and porcupine.delete()
 91 |             recorder and recorder.delete()
 92 | 
 93 |     else:
 94 |         logger.info("使用 snowboy 进行离线唤醒")
 95 |         detector and detector.terminate()
 96 |         models = constants.getHotwordModel(config.get("hotword", "wukong.pmdl"))
 97 |         detector = snowboydecoder.HotwordDetector(
 98 |             models, sensitivity=config.get("sensitivity", 0.5)
 99 |         )
100 |         # main loop
101 |         try:
102 |             callbacks = wukong._detected_callback
103 |             detector.start(
104 |                 detected_callback=callbacks,
105 |                 audio_recorder_callback=wukong.conversation.converse,
106 |                 interrupt_check=wukong._interrupt_callback,
107 |                 silent_count_threshold=config.get("silent_threshold", 15),
108 |                 recording_timeout=config.get("recording_timeout", 5) * 4,
109 |                 sleep_time=0.03,
110 |             )
111 |             detector.terminate()
112 |         except Exception as e:
113 |             logger.critical(f"离线唤醒机制初始化失败:{e}", stack_info=True)
114 | 


--------------------------------------------------------------------------------
/robot/drivers/AIY.py:
--------------------------------------------------------------------------------
 1 | import time
 2 | 
 3 | 
 4 | class AIY:
 5 |     def __init__(self):
 6 |         self._wakeup = False
 7 |         self._think = False
 8 | 
 9 |     def wakeup(self):
10 |         from aiy.board import Board, Led
11 |         from aiy.leds import Leds, Pattern, Color
12 | 
13 |         self._wakeup = True
14 |         with Board() as board:
15 |             with Leds() as leds:
16 |                 while self._wakeup:
17 |                     board.led.state = Led.ON
18 |                     leds.pattern = Pattern.breathe(1000)
19 |                     leds.update(Leds.rgb_pattern(Color.BLUE))
20 |                     time.sleep(1)
21 | 
22 |     def think(self):
23 |         from aiy.leds import Leds, Pattern, Color
24 | 
25 |         self._wakeup = False
26 |         self._think = True
27 |         with Leds() as leds:
28 |             while self._think:
29 |                 leds.pattern = Pattern.blink(500)
30 |                 leds.update(Leds.rgb_pattern(Color.GREEN))
31 |                 time.sleep(1)
32 | 
33 |     def off(self):
34 |         from aiy.board import Board, Led
35 | 
36 |         self._wakeup = False
37 |         self._think = False
38 |         with Board() as board:
39 |             board.led.state = Led.OFF
40 |         self.led = False
41 | 


--------------------------------------------------------------------------------
/robot/drivers/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/robot/drivers/__init__.py


--------------------------------------------------------------------------------
/robot/drivers/pixels.py:
--------------------------------------------------------------------------------
  1 | from . import apa102
  2 | import time
  3 | import threading
  4 | 
  5 | try:
  6 |     import queue as Queue
  7 | except ImportError:
  8 |     import Queue as Queue
  9 | 
 10 | 
 11 | class Pixels:
 12 |     PIXELS_N = 3
 13 | 
 14 |     def __init__(self):
 15 |         self.basis = [0] * 3 * self.PIXELS_N
 16 |         self.basis[0] = 1
 17 |         self.basis[4] = 1
 18 |         self.basis[8] = 2
 19 | 
 20 |         self.colors = [0] * 3 * self.PIXELS_N
 21 |         self.dev = apa102.APA102(num_led=self.PIXELS_N)
 22 | 
 23 |         self.next = threading.Event()
 24 |         self.queue = Queue.Queue()
 25 |         self.thread = threading.Thread(target=self._run)
 26 |         self.thread.daemon = True
 27 |         self.thread.start()
 28 | 
 29 |     def wakeup(self, direction=0):
 30 |         def f():
 31 |             self._wakeup(direction)
 32 | 
 33 |         self.next.set()
 34 |         self.queue.put(f)
 35 | 
 36 |     def listen(self):
 37 |         self.next.set()
 38 |         self.queue.put(self._listen)
 39 | 
 40 |     def think(self):
 41 |         self.next.set()
 42 |         self.queue.put(self._think)
 43 | 
 44 |     def speak(self):
 45 |         self.next.set()
 46 |         self.queue.put(self._speak)
 47 | 
 48 |     def off(self):
 49 |         self.next.set()
 50 |         self.queue.put(self._off)
 51 | 
 52 |     def _run(self):
 53 |         while True:
 54 |             func = self.queue.get()
 55 |             func()
 56 | 
 57 |     def _wakeup(self, direction=0):
 58 |         for i in range(1, 25):
 59 |             colors = [i * v for v in self.basis]
 60 |             self.write(colors)
 61 |             time.sleep(0.01)
 62 | 
 63 |         self.colors = colors
 64 | 
 65 |     def _listen(self):
 66 |         for i in range(1, 25):
 67 |             colors = [i * v for v in self.basis]
 68 |             self.write(colors)
 69 |             time.sleep(0.01)
 70 | 
 71 |         self.colors = colors
 72 | 
 73 |     def _think(self):
 74 |         colors = self.colors
 75 | 
 76 |         self.next.clear()
 77 |         while not self.next.is_set():
 78 |             colors = colors[3:] + colors[:3]
 79 |             self.write(colors)
 80 |             time.sleep(0.2)
 81 | 
 82 |         t = 0.1
 83 |         for i in range(0, 5):
 84 |             colors = colors[3:] + colors[:3]
 85 |             self.write([(v * (4 - i) / 4) for v in colors])
 86 |             time.sleep(t)
 87 |             t /= 2
 88 | 
 89 |         # time.sleep(0.5)
 90 | 
 91 |         self.colors = colors
 92 | 
 93 |     def _speak(self):
 94 |         colors = self.colors
 95 | 
 96 |         self.next.clear()
 97 |         while not self.next.is_set():
 98 |             for i in range(5, 25):
 99 |                 colors = [(v * i / 24) for v in colors]
100 |                 self.write(colors)
101 |                 time.sleep(0.01)
102 | 
103 |             time.sleep(0.3)
104 | 
105 |             for i in range(24, 4, -1):
106 |                 colors = [(v * i / 24) for v in colors]
107 |                 self.write(colors)
108 |                 time.sleep(0.01)
109 | 
110 |             time.sleep(0.3)
111 | 
112 |         self._off()
113 | 
114 |     def _off(self):
115 |         self.write([0] * 3 * self.PIXELS_N)
116 | 
117 |     def write(self, colors):
118 |         for i in range(self.PIXELS_N):
119 |             self.dev.set_pixel(
120 |                 i, int(colors[3 * i]), int(colors[3 * i + 1]), int(colors[3 * i + 2])
121 |             )
122 | 
123 |         self.dev.show()
124 | 
125 | 
126 | pixels = Pixels()
127 | 
128 | 
129 | if __name__ == "__main__":
130 |     while True:
131 | 
132 |         try:
133 |             pixels.wakeup()
134 |             time.sleep(3)
135 |             pixels.think()
136 |             time.sleep(3)
137 |             pixels.speak()
138 |             time.sleep(3)
139 |             pixels.off()
140 |             time.sleep(3)
141 |         except KeyboardInterrupt:
142 |             break
143 | 
144 |     pixels.off()
145 |     time.sleep(1)
146 | 


--------------------------------------------------------------------------------
/robot/logging.py:
--------------------------------------------------------------------------------
 1 | import logging
 2 | import os
 3 | 
 4 | from robot import constants
 5 | from logging.handlers import RotatingFileHandler
 6 | 
 7 | PAGE = 4096
 8 | 
 9 | DEBUG = logging.DEBUG
10 | INFO = logging.INFO
11 | WARNING = logging.WARNING
12 | ERROR = logging.ERROR
13 | 
14 | 
15 | def tail(filepath, n=10):
16 |     """
17 |     实现 tail -n
18 |     """
19 |     res = ""
20 |     with open(filepath, "rb") as f:
21 |         f_len = f.seek(0, 2)
22 |         rem = f_len % PAGE
23 |         page_n = f_len // PAGE
24 |         r_len = rem if rem else PAGE
25 |         while True:
26 |             # 如果读取的页大小>=文件大小,直接读取数据输出
27 |             if r_len >= f_len:
28 |                 f.seek(0)
29 |                 lines = f.readlines()[::-1]
30 |                 break
31 | 
32 |             f.seek(-r_len, 2)
33 |             lines = f.readlines()[::-1]
34 |             count = len(lines) - 1  # 末行可能不完整,减一行,加大读取量
35 | 
36 |             if count >= n:  # 如果读取到的行数>=指定行数,则退出循环读取数据
37 |                 break
38 |             else:  # 如果读取行数不够,载入更多的页大小读取数据
39 |                 r_len += PAGE
40 |                 page_n -= 1
41 | 
42 |     for line in lines[:n][::-1]:
43 |         res += line.decode("utf-8")
44 |     return res
45 | 
46 | 
47 | def getLogger(name):
48 |     """
49 |     作用同标准模块 logging.getLogger(name)
50 | 
51 |     :returns: logger
52 |     """
53 |     format = "%(asctime)s - %(name)s - %(filename)s - %(funcName)s - line %(lineno)s - %(levelname)s - %(message)s"
54 |     formatter = logging.Formatter(format)
55 |     logging.basicConfig(format=format)
56 |     logger = logging.getLogger(name)
57 |     logger.setLevel(logging.INFO)
58 | 
59 |     # FileHandler
60 |     file_handler = RotatingFileHandler(
61 |         os.path.join(constants.TEMP_PATH, "wukong.log"),
62 |         maxBytes=1024 * 1024,
63 |         backupCount=5,
64 |     )
65 |     file_handler.setLevel(level=logging.NOTSET)
66 |     file_handler.setFormatter(formatter)
67 |     logger.addHandler(file_handler)
68 | 
69 |     return logger
70 | 
71 | 
72 | def readLog(lines=200):
73 |     """
74 |     获取最新的指定行数的 log
75 | 
76 |     :param lines: 最大的行数
77 |     :returns: 最新指定行数的 log
78 |     """
79 |     log_path = os.path.join(constants.TEMP_PATH, "wukong.log")
80 |     if os.path.exists(log_path):
81 |         return tail(log_path, lines)
82 |     return ""
83 | 


--------------------------------------------------------------------------------
/robot/plugin_loader.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | import pkgutil
 3 | from . import config
 4 | from . import constants
 5 | from robot import logging
 6 | from robot.sdk.AbstractPlugin import AbstractPlugin
 7 | 
 8 | logger = logging.getLogger(__name__)
 9 | _has_init = False
10 | 
11 | # plugins run at query
12 | _plugins_query = []
13 | 
14 | 
15 | def init_plugins(con):
16 |     """
17 |     动态加载技能插件
18 | 
19 |     参数:
20 |     con -- 会话模块
21 |     """
22 | 
23 |     global _has_init
24 |     locations = [constants.PLUGIN_PATH, constants.CONTRIB_PATH, constants.CUSTOM_PATH]
25 |     logger.debug(f"检查插件目录:{locations}")
26 | 
27 |     global _plugins_query
28 |     nameSet = set()
29 | 
30 |     for finder, name, ispkg in pkgutil.walk_packages(locations):
31 |         try:
32 |             loader = finder.find_module(name)
33 |             mod = loader.load_module(name)
34 |         except Exception:
35 |             logger.warning(f"插件 {name} 加载出错,跳过", exc_info=True)
36 |             continue
37 | 
38 |         if not hasattr(mod, "Plugin"):
39 |             logger.debug(f"模块 {name} 非插件,跳过")
40 |             continue
41 | 
42 |         # plugins run at query
43 |         plugin = mod.Plugin(con)
44 | 
45 |         if plugin.SLUG == "AbstractPlugin":
46 |             plugin.SLUG = name
47 | 
48 |         # check conflict
49 |         if plugin.SLUG in nameSet:
50 |             logger.warning(f"插件 {name} SLUG({plugin.SLUG}) 重复,跳过")
51 |             continue
52 |         nameSet.add(plugin.SLUG)
53 | 
54 |         # whether a plugin is enabled
55 |         if config.has(plugin.SLUG) and "enable" in config.get(plugin.SLUG):
56 |             if not config.get(plugin.SLUG)["enable"]:
57 |                 logger.info(f"插件 {name} 已被禁用")
58 |                 continue
59 | 
60 |         if issubclass(mod.Plugin, AbstractPlugin):
61 |             logger.info(f"插件 {name} 加载成功 ")
62 |             _plugins_query.append(plugin)
63 | 
64 |     def sort_priority(m):
65 |         if hasattr(m, "PRIORITY"):
66 |             return m.PRIORITY
67 |         return 0
68 | 
69 |     _plugins_query.sort(key=sort_priority, reverse=True)
70 |     _has_init = True
71 | 
72 | 
73 | def get_plugins(con):
74 |     global _plugins_query
75 |     _plugins_query = []
76 |     init_plugins(con)
77 |     return _plugins_query
78 | 


--------------------------------------------------------------------------------
/robot/sdk/AbstractPlugin.py:
--------------------------------------------------------------------------------
  1 | import sys
  2 | from robot import logging
  3 | from robot import constants
  4 | from abc import ABCMeta, abstractmethod
  5 | 
  6 | logger = logging.getLogger(__name__)
  7 | 
  8 | try:
  9 |     sys.path.append(constants.CONTRIB_PATH)
 10 | except Exception as e:
 11 |     logger.error(f"未检测到插件目录, Error: {e}", stack_info=True)
 12 | 
 13 | 
 14 | class AbstractPlugin(metaclass=ABCMeta):
 15 |     """技能插件基类"""
 16 | 
 17 |     SLUG = "AbstractPlugin"
 18 |     IS_IMMERSIVE = False
 19 | 
 20 |     def __init__(self, con):
 21 |         if self.IS_IMMERSIVE:
 22 |             self.isImmersive = self.IS_IMMERSIVE
 23 |         else:
 24 |             self.isImmersive = False
 25 |         self.priority = 0
 26 |         self.con = con
 27 |         self.nlu = self.con.nlu
 28 | 
 29 |     def play(self, src, delete=False, onCompleted=None, volume=1):
 30 |         """
 31 |         播放音频
 32 | 
 33 |         :param play: 要播放的音频地址
 34 |         :param delete: 播放完成是否要删除,默认不删除
 35 |         :param onCompleted: 播放完后的回调
 36 |         :param volume: 音量
 37 |         """
 38 |         self.con.play(src, delete, onCompleted, volume)
 39 | 
 40 |     def say(self, text, cache=False, onCompleted=None, wait=False):
 41 |         """
 42 |         使用TTS说一句话
 43 | 
 44 |         :param text: 要说话的内容
 45 |         :param cache: 是否要缓存该音频,默认不缓存
 46 |         :param onCompleted: 播放完后的回调
 47 |         :param wait: 已废弃
 48 |         """
 49 |         self.con.say(text, cache=cache, plugin=self.SLUG, onCompleted=onCompleted)
 50 | 
 51 |     def activeListen(self, silent=False):
 52 |         if (
 53 |             self.SLUG != "geek"
 54 |             and self.con.immersiveMode
 55 |             and self.con.immersiveMode == "geek"
 56 |         ):
 57 |             # 极客模式下禁止其他插件主动聆听,以避免异常问题
 58 |             self.con.player.stop()
 59 |             self.critical("错误:请退出极客模式后再试")
 60 |             self.say("错误:请退出极客模式后再试")
 61 |             return ""
 62 |         return self.con.activeListen(silent)
 63 | 
 64 |     def clearImmersive(self):
 65 |         self.con.setImmersiveMode(None)
 66 | 
 67 |     def parse(self, query):
 68 |         """
 69 |         NLU 解析
 70 |         """
 71 |         return self.con.doParse(query)
 72 | 
 73 |     @abstractmethod
 74 |     def isValid(self, query, parsed):
 75 |         """
 76 |         是否适合由该插件处理
 77 | 
 78 |         参数:
 79 |         query -- 用户的指令字符串
 80 |         parsed -- 用户指令经过 NLU 解析后的结果
 81 | 
 82 |         返回:
 83 |         True: 适合由该插件处理
 84 |         False: 不适合由该插件处理
 85 |         """
 86 |         return False
 87 | 
 88 |     @abstractmethod
 89 |     def handle(self, query, parsed):
 90 |         """
 91 |         处理逻辑
 92 | 
 93 |         参数:
 94 |         query -- 用户的指令字符串
 95 |         parsed -- 用户指令经过 NLU 解析后的结果
 96 |         """
 97 |         pass
 98 | 
 99 |     def isValidImmersive(self, query, parsed):
100 |         """
101 |         是否适合在沉浸模式下处理,
102 |         仅适用于有沉浸模式的插件(如音乐等)
103 |         当用户唤醒时,可以响应更多指令集。
104 |         例如:“"上一首"、"下一首" 等
105 |         """
106 |         return False
107 | 
108 |     def pause(self):
109 |         """
110 |         暂停当前正在处理的任务,
111 |         当处于该沉浸模式下且被唤醒时,
112 |         将自动触发这个方法,
113 |         可以用于强制暂停一个耗时的操作
114 |         """
115 |         return
116 | 
117 |     def restore(self):
118 |         """
119 |         恢复当前插件,
120 |         仅适用于有沉浸模式的插件(如音乐等)
121 |         当用户误唤醒或者唤醒进行闲聊后,
122 |         可以自动恢复当前插件的处理逻辑
123 |         """
124 |         return
125 | 


--------------------------------------------------------------------------------
/robot/sdk/BaiduSpeech.py:
--------------------------------------------------------------------------------
 1 | # -*- coding:utf-8 -*-
 2 | import os
 3 | import json
 4 | import requests
 5 | import time
 6 | from robot import logging
 7 | 
 8 | logger = logging.getLogger(__name__)
 9 | TOKEN_PATH = os.path.expanduser("~/.wukong/.baiduSpeech_token")
10 | 
11 | # 百度语音识别 REST_API极速版
12 | class baiduSpeech(object):
13 |     def __init__(self, api_key, secret_key, dev_pid):
14 |         self.api_key, self.secret_key, self.dev_pid = api_key, secret_key, dev_pid
15 |         if not os.path.exists(TOKEN_PATH):
16 |             self.token = self.fetch_token()
17 |         else:
18 |             self.token = self.load()
19 | 
20 |     def fetch_token(self):
21 |         token_url = "http://openapi.baidu.com/oauth/2.0/token"
22 |         body = {
23 |             "grant_type": "client_credentials",
24 |             "client_id": self.api_key,
25 |             "client_secret": self.secret_key,
26 |         }
27 |         try:
28 |             req = requests.post(
29 |                 token_url,
30 |                 headers={"Content-Type": "application/json; charset=UTF-8"},
31 |                 data=body,
32 |             )
33 |             s = req.content.decode("utf-8", "ignore")
34 |             result = json.loads(s)
35 |             if "access_token" in result.keys() and "scope" in result.keys():
36 |                 if not "brain_enhanced_asr" in result["scope"].split(" "):
37 |                     logger.error("当前百度云api_id尚未有语音识别的授权。")
38 |                 #### 请求access_token成功.
39 |                 with open(TOKEN_PATH, "w") as f:
40 |                     result = {
41 |                         key: result.get(key) for key in ["access_token", "expires_in"]
42 |                     }
43 |                     result["get_time"] = time.time()
44 |                     data = json.dumps(result)
45 |                     f.write(data)
46 |                 return result["access_token"]
47 |         except Exception as err:
48 |             logger.error(f"请求token_access失败: {err}", stack_info=True)
49 | 
50 |     def load(self):
51 |         def is_json(f):
52 |             try:
53 |                 json_object = json.load(f)
54 |             except ValueError:
55 |                 return False
56 |             return json_object
57 | 
58 |         try:
59 |             with open(TOKEN_PATH, "r") as f:
60 |                 access_token = is_json(f)
61 |                 if not access_token:
62 |                     return self.fetch_token()
63 |                 elif (
64 |                     time.time() - access_token["expires_in"] - access_token["get_time"]
65 |                     >= 0
66 |                 ):
67 |                     return self.fetch_token()
68 |                 else:
69 |                     return access_token["access_token"]
70 |         except (OSError, KeyError, ValueError) as e:
71 |             print(f"加载.baiduSpeech_token文件失败,请检查!原因是{e}")
72 | 
73 |     def asr(self, pcm, file_type, sample_rate, dev_pid):
74 |         asr_url = "http://vop.baidu.com/pro_api"
75 |         length = len(pcm)
76 |         if length == 0:
77 |             logger.error(f"这个语音文件 {pcm} 是空的")
78 |         headers = {
79 |             "Content-Type": "audio/" + file_type + ";rate=" + str(sample_rate),
80 |             "Content-Length": str(length),
81 |         }
82 |         params = {"cuid": "wukong-Robot", "token": self.token, "dev_pid": self.dev_pid}
83 | 
84 |         try:
85 |             req = requests.post(asr_url, params=params, headers=headers, data=pcm)
86 |             s = req.content.decode("utf-8")
87 |             return json.loads(s)
88 |         except Exception as err:
89 |             logger.error(f"百度ASR极速版请求失败: {err}", stack_info=True)
90 | 


--------------------------------------------------------------------------------
/robot/sdk/FunASREngine.py:
--------------------------------------------------------------------------------
 1 | 
 2 | from typing import Any
 3 | 
 4 | 
 5 | class funASREngine(object):
 6 |     def __init__(self, inference_type, model_dir=''):
 7 |         assert inference_type in ['onnxruntime'] # 当前只实现了onnxruntime的推理方案
 8 |         self.inference_type = inference_type
 9 |         if self.inference_type == 'onnxruntime':
10 |             # 调用下面的引擎进初始化引擎太慢了,因此放在条件分支里面
11 |             from funasr_onnx import Paraformer
12 |             self.engine_model = Paraformer(model_dir, batch_size=1, quantize=True)
13 |     
14 |     def onnxruntime_engine(self, audio_path):
15 |         result = self.engine_model(audio_path)
16 |         return str(result[0]['preds'][0])
17 | 
18 |     def __call__(self, fp):
19 |         result = None
20 |         if self.inference_type == 'onnxruntime':
21 |             result = self.onnxruntime_engine(fp)
22 |         return result


--------------------------------------------------------------------------------
/robot/sdk/History.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | # 用于维护历史消息
 3 | import tornado.locks
 4 | 
 5 | 
 6 | def Singleton(cls):
 7 |     _instance = {}
 8 | 
 9 |     def _singleton(*args, **kargs):
10 |         if cls not in _instance:
11 |             _instance[cls] = cls(*args, **kargs)
12 |         return _instance[cls]
13 | 
14 |     return _singleton
15 | 
16 | 
17 | @Singleton
18 | class History(object):
19 |     def __init__(self):
20 |         # cond is notified whenever the message cache is updated
21 |         self.cond = tornado.locks.Condition()
22 |         self.cache = []
23 |         self.cache_size = 200
24 | 
25 |     def get_messages_since(self, cursor):
26 |         """Returns a list of messages newer than the given cursor.
27 | 
28 |         ``cursor`` should be the ``uuid`` of the last message received.
29 |         """
30 |         results = []
31 |         for msg in reversed(self.cache):
32 |             if msg["uuid"] == cursor:
33 |                 break
34 |             results.append(msg)
35 |         results.reverse()
36 |         return results
37 | 
38 |     def add_message(self, message):
39 |         self.cache.append(message)
40 |         if len(self.cache) > self.cache_size:
41 |             self.cache = self.cache[-self.cache_size :]
42 |         self.cond.notify_all()
43 | 


--------------------------------------------------------------------------------
/robot/sdk/LED.py:
--------------------------------------------------------------------------------
 1 | import _thread as thread
 2 | from robot import config, logging
 3 | from robot.drivers.AIY import AIY
 4 | 
 5 | logger = logging.getLogger(__name__)
 6 | 
 7 | aiy = AIY()
 8 | 
 9 | 
10 | def wakeup():
11 |     if config.get("/LED/enable", False):
12 |         if config.get("/LED/type") == "aiy":
13 |             thread.start_new_thread(aiy.wakeup, ())
14 |         elif config.get("/LED/type") == "respeaker":
15 |             from robot.drivers.pixels import pixels
16 | 
17 |             pixels.wakeup()
18 |         else:
19 |             logger.error("错误:不支持的灯光类型", stack_info=True)
20 | 
21 | 
22 | def think():
23 |     if config.get("/LED/enable", False):
24 |         if config.get("/LED/type") == "aiy":
25 |             thread.start_new_thread(aiy.think, ())
26 |         elif config.get("/LED/type") == "respeaker":
27 |             from robot.drivers.pixels import pixels
28 | 
29 |             pixels.think()
30 |         else:
31 |             logger.error("错误:不支持的灯光类型", stack_info=True)
32 | 
33 | 
34 | def off():
35 |     if config.get("/LED/enable", False):
36 |         if config.get("/LED/type") == "aiy":
37 |             thread.start_new_thread(aiy.off, ())
38 |         elif config.get("/LED/type") == "respeaker":
39 |             from robot.drivers.pixels import pixels
40 | 
41 |             pixels.off()
42 |         else:
43 |             logger.error("错误:不支持的灯光类型", stack_info=True)
44 | 


--------------------------------------------------------------------------------
/robot/sdk/Unihiker.py:
--------------------------------------------------------------------------------
 1 | from robot import constants, config
 2 | from unihiker import Audio, GUI
 3 | from pinpong.board import Board, Pin, Tone
 4 | from pinpong.extension.unihiker import *
 5 | 
 6 | 
 7 | class Unihiker(object):
 8 |     def __init__(self):
 9 |         Board().begin()
10 |         self._gui = GUI()
11 |         self._tone = Tone(Pin(Pin.P26))
12 |         self._gui.draw_image(w=240, h=320, image=constants.getData("background.png"))
13 |         self._my_bubble = self._gui.draw_text(
14 |             x=20, y=25, w=150, color="red", text="(请说唤醒词)", font_size=10
15 |         )
16 |         self._bot_bubble = self._gui.draw_text(
17 |             x=40, y=80, w=150, color="black", text="", font_size=10
18 |         )
19 | 
20 |     def _play_tones(self, tones, duration):
21 |         for tone in tones:
22 |             self._tone.freq(tone)
23 |             self._tone.on()
24 |             time.sleep(duration)
25 |             self._tone.off()
26 | 
27 |     def wakeup(self):
28 |         if config.get("/unihiker/beep", False):
29 |             self._play_tones([225, 329], 0.1)
30 | 
31 |     def think(self):
32 |         if config.get("/unihiker/beep", False):
33 |             self._play_tones([329, 225], 0.1)
34 | 
35 |     def record(self, t, text=""):
36 |         self._my_bubble.config(
37 |             text=text, color="black"
38 |         ) if t == 0 else self._bot_bubble.config(text=text)
39 | 


--------------------------------------------------------------------------------
/robot/sdk/VITSClient.py:
--------------------------------------------------------------------------------
 1 | # coding: utf-8
 2 | # !/usr/bin/env python3
 3 | 
 4 | """VITS TTS API"""
 5 | 
 6 | import requests
 7 | 
 8 | 
 9 | def tts(text, server_url, api_key, speaker_id, length, noise, noisew, max, timeout):
10 |     data = {
11 |         "text": text,
12 |         "id": speaker_id,
13 |         "format": "wav",
14 |         "lang": "auto",
15 |         "length": length,
16 |         "noise": noise,
17 |         "noisew": noisew,
18 |         "max": max
19 |     }
20 |     headers = {"X-API-KEY": api_key}
21 |     url = f"{server_url}/voice"
22 |     res = requests.post(url=url, data=data, headers=headers, timeout=timeout)
23 |     res.raise_for_status()
24 |     return res.content
25 | 


--------------------------------------------------------------------------------
/robot/sdk/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/robot/sdk/__init__.py


--------------------------------------------------------------------------------
/robot/sdk/atc.py:
--------------------------------------------------------------------------------
  1 | # # -*- coding=utf-8 -*-
  2 | # digit=['零','一','二','三','四','五','六','七','八','九']
  3 | # unit=['零','十','百','千','万','亿']
  4 | # def arabic_to_chinese(number):
  5 | # 	if number < 0:
  6 | # 		raise Exception("negative arg")
  7 | # 	if number < 10:
  8 | # 		return digit[number]
  9 | # 	elif number < 100:
 10 | # 		h = number // 10
 11 | # 		if h != 1:
 12 | # 			return str(h) + "十" + arabic_to_chinese(number % 10)
 13 | # 		else:
 14 | # 			return "十" + arabic_to_chinese(number % 10)
 15 | # 	elif number < 1000:
 16 | # 		th = number // 100
 17 | # 		return str(th) + "百" + arabic_to_chinese(number % 100)
 18 | # 	elif number < 10000:
 19 | # 		w = number // 1000
 20 | # 		return str(w) + "千" + arabic_to_chinese(number % 1000)
 21 | # 	else:
 22 | # 		pass
 23 | 
 24 | 
 25 | # c = 1
 26 | # def test(num, expected):
 27 | # 	global c
 28 | # 	actual = arabic_to_chinese(num)
 29 | # 	if (actual != expected):
 30 | # 		print(c, actual, expected)
 31 | # 	else:
 32 | # 		print(c, "pass")
 33 | # 	c+=1
 34 | 
 35 | 
 36 | # test(0, '零')
 37 | # test(1, '一')
 38 | # test(5, '五')
 39 | # test(12, '十二')
 40 | # test(30, '三十')
 41 | # test(37, '三十七')
 42 | # test(100, '一百')
 43 | # test(150,'一百五十')
 44 | # test(156,'一百五十六')
 45 | # test(999,'九百九十九')
 46 | # test(1000 ,'一千')
 47 | # test(1001 ,'一千零一')
 48 | # test(1001 ,'一千零一')
 49 | 
 50 | # -*- coding: utf-8 -*-
 51 | 
 52 | # Licensed under WTFPL or the Unlicense or CC0.
 53 | # This uses Python 3, but it's easy to port to Python 2 by changing
 54 | # strings to u'xx'.
 55 | 
 56 | import itertools
 57 | 
 58 | 
 59 | def num2chinese(num, big=False, simp=True, o=False, twoalt=False):
 60 |     """
 61 |     Converts numbers to Chinese representations.
 62 |     `big`   : use financial characters.
 63 |     `simp`  : use simplified characters instead of traditional characters.
 64 |     `o`     : use 〇 for zero.
 65 |     `twoalt`: use 两/兩 for two when appropriate.
 66 |     Note that `o` and `twoalt` is ignored when `big` is used,
 67 |     and `twoalt` is ignored when `o` is used for formal representations.
 68 |     """
 69 |     # check num first
 70 |     nd = str(num)
 71 |     if abs(float(nd)) >= 1e48:
 72 |         raise ValueError("number out of range")
 73 |     elif "e" in nd:
 74 |         raise ValueError("scientific notation is not supported")
 75 |     c_symbol = "正负点" if simp else "正負點"
 76 |     if o:  # formal
 77 |         twoalt = False
 78 |     if big:
 79 |         c_basic = "零壹贰叁肆伍陆柒捌玖" if simp else "零壹貳參肆伍陸柒捌玖"
 80 |         c_unit1 = "拾佰仟"
 81 |         c_twoalt = "贰" if simp else "貳"
 82 |     else:
 83 |         c_basic = "〇一二三四五六七八九" if o else "零一二三四五六七八九"
 84 |         c_unit1 = "十百千"
 85 |         if twoalt:
 86 |             c_twoalt = "两" if simp else "兩"
 87 |         else:
 88 |             c_twoalt = "二"
 89 |     c_unit2 = "万亿兆京垓秭穰沟涧正载" if simp else "萬億兆京垓秭穰溝澗正載"
 90 |     revuniq = lambda l: "".join(k for k, g in itertools.groupby(reversed(l)))
 91 |     nd = str(num)
 92 |     result = []
 93 |     if nd[0] == "+":
 94 |         result.append(c_symbol[0])
 95 |     elif nd[0] == "-":
 96 |         result.append(c_symbol[1])
 97 |     if "." in nd:
 98 |         integer, remainder = nd.lstrip("+-").split(".")
 99 |     else:
100 |         integer, remainder = nd.lstrip("+-"), None
101 |     if int(integer):
102 |         splitted = [integer[max(i - 4, 0) : i] for i in range(len(integer), 0, -4)]
103 |         intresult = []
104 |         for nu, unit in enumerate(splitted):
105 |             # special cases
106 |             if int(unit) == 0:  # 0000
107 |                 intresult.append(c_basic[0])
108 |                 continue
109 |             elif nu > 0 and int(unit) == 2:  # 0002
110 |                 intresult.append(c_twoalt + c_unit2[nu - 1])
111 |                 continue
112 |             ulist = []
113 |             unit = unit.zfill(4)
114 |             for nc, ch in enumerate(reversed(unit)):
115 |                 if ch == "0":
116 |                     if ulist:  # ???0
117 |                         ulist.append(c_basic[0])
118 |                 elif nc == 0:
119 |                     ulist.append(c_basic[int(ch)])
120 |                 elif nc == 1 and ch == "1" and unit[1] == "0":
121 |                     # special case for tens
122 |                     # edit the 'elif' if you don't like
123 |                     # 十四, 三千零十四, 三千三百一十四
124 |                     ulist.append(c_unit1[0])
125 |                 elif nc > 1 and ch == "2":
126 |                     ulist.append(c_twoalt + c_unit1[nc - 1])
127 |                 else:
128 |                     ulist.append(c_basic[int(ch)] + c_unit1[nc - 1])
129 |             ustr = revuniq(ulist)
130 |             if nu == 0:
131 |                 intresult.append(ustr)
132 |             else:
133 |                 intresult.append(ustr + c_unit2[nu - 1])
134 |         result.append(revuniq(intresult).strip(c_basic[0]))
135 |     else:
136 |         result.append(c_basic[0])
137 |     if remainder:
138 |         result.append(c_symbol[2])
139 |         result.append("".join(c_basic[int(ch)] for ch in remainder))
140 |     return "".join(result)
141 | 


--------------------------------------------------------------------------------
/robot/statistic.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf -8-*-
 2 | 
 3 | from . import config
 4 | import uuid
 5 | import requests
 6 | import threading
 7 | 
 8 | 
 9 | def getUUID():
10 |     mac = uuid.UUID(int=uuid.getnode()).hex[-12:]
11 |     return ":".join([mac[e : e + 2] for e in range(0, 11, 2)])
12 | 
13 | 
14 | def report(t):
15 |     ReportThread(t).start()
16 | 
17 | 
18 | class ReportThread(threading.Thread):
19 |     def __init__(self, t):
20 |         # 需要执行父类的初始化方法
21 |         threading.Thread.__init__(self)
22 |         self.t = t
23 | 
24 |     def run(self):
25 |         to_report = config.get("statistic", True)
26 |         if to_report:
27 |             try:
28 |                 persona = config.get("robot_name_cn", "孙悟空")
29 |                 url = "http://livecv.hahack.com:8022/statistic"
30 |                 payload = {
31 |                     "type": str(self.t),
32 |                     "uuid": getUUID(),
33 |                     "name": persona,
34 |                     "project": "wukong",
35 |                 }
36 |                 requests.post(url, data=payload, timeout=3)
37 |             except Exception:
38 |                 return
39 | 


--------------------------------------------------------------------------------
/server/static/api.css:
--------------------------------------------------------------------------------
 1 | table {
 2 |     margin-top:15px;
 3 |     border-collapse:collapse;
 4 |     border:1px solid #aaa;
 5 |     width:100%;
 6 |     margin-bottom:2em;
 7 | }
 8 | table th {
 9 |     vertical-align:baseline;
10 |     padding:5px 15px 5px 6px;
11 |     background-color:#3F3F3F;
12 |     border:1px solid #3F3F3F;
13 |     text-align:left;
14 |     color:#fff;
15 | }
16 | table td {
17 |     vertical-align:middle;
18 |     padding:6px 15px 6px 6px;
19 |     border:1px solid #aaa;
20 | }
21 | table tr:nth-child(odd) {
22 |     background-color:#F5F5F5;
23 | 
24 | }
25 | table tr:nth-child(even) {
26 |     background-color:#fff;
27 | }
28 | 
29 | h1{
30 |     line-height:1.2em;
31 | }
32 | 
33 | h2 {
34 |     margin-top:1em;
35 |     margin-bottom:0.6667em;
36 | }
37 | 
38 | h1,h2,h3,h4,h5,h6{
39 |     text-rendering:optimizelegibility;
40 |     font-weight:bold
41 | }
42 | pre {
43 |     word-break: break-all;
44 |     white-space: pre-wrap;
45 | }
46 | 


--------------------------------------------------------------------------------
/server/static/config.js:
--------------------------------------------------------------------------------
 1 | function saveConfig(msg) {
 2 |     if (window.location.href.indexOf('bot.hahack.com') >= 0) {
 3 |         bootbox.alert("demo 站点禁止修改配置!");
 4 |         return;
 5 |     }
 6 |     $.ajax({
 7 |         url: '/config',
 8 |         type: "POST",
 9 |         data: {"config": encodeURIComponent($('#config-input').val()), 'validate': getCookie('validation')},
10 |         success: function(res) {
11 |             var data = JSON.parse(res);
12 |             if (!msg) msg='';
13 |             if (data.code == 0) {
14 |                 toastr.success('设置成功'+msg);
15 |             } else {
16 |                 toastr.error(data.message, '设置失败');
17 |             }
18 |         },
19 |         error: function() {
20 |             toastr.error('服务器异常', '设置失败');
21 |         }
22 |     });
23 | }
24 | 
25 | $(function() {
26 |     $.ajax({
27 |         url: '/config',
28 |         type: "GET",
29 |         data: {'validate': getCookie('validation')},
30 |         success: function(res) {
31 |             var data = JSON.parse(res);            
32 |             if (data.code == 0) {
33 |                 let config = data.config;
34 |                 let sensitivity = data.sensitivity;
35 |                 if (config == '') {
36 |                     $('#config-placeholder').append(`
37 |     <center>
38 |     <p> 找不到配置文件 <code>~/.wukong/config.yml</code> ,请先创建一份!</p>
39 |     </center>
40 | `);
41 |                 } else {
42 |                     $('#config-placeholder').append(`
43 |     <form class="form config-form" action="#">
44 |     <div class="input-group" id="container">
45 |       <div class="input-group-prepend">
46 |         <span class="input-group-text">config.yml</span>
47 |       </div>
48 |         <textarea rows="20" class="form-control" id="config-input" placer='1' aria-label="With textarea">${config}</textarea>
49 |     </div>
50 |     <hr>
51 |     <center>
52 |     <button type="button" class="btn btn-primary mb-2" id="SAVE"><i class="fas fa-save"></i> 保存</button>&nbsp;
53 |     <button type="button" class="btn btn-danger mb-2" data-toggle="modal" data-target="#restartModal"><i class="fas fa-power-off"></i> 重启</button>
54 |     </center>
55 |   </form>
56 | `);
57 |                 }
58 |                 $('#sensitivitiy-value').text(sensitivity);
59 |                 $('input#sensitivitiy').val(parseFloat(sensitivity));
60 |                 $('input#sensitivity').on('input propertychange', function(e) {
61 |                     e.preventDefault();
62 |                     var value = $(this).val();
63 |                     $('#sensitivitiy-value').text(value);
64 |                 });
65 |                 $('input#sensitivity').on('change', function(e) {
66 |                     e.preventDefault();
67 |                     var value = $(this).val();
68 |                     var config = $('#config-input').val();
69 |                     config.indexOf('')
70 |                     var subStr=new RegExp('sensitivity: [0-9]+\.?[0-9]?')
71 |                     result = config.replace(subStr, "sensitivity: " + value + " ");
72 |                     $('#config-input').text(result);
73 |                     saveConfig(',请重启生效');
74 |                 });
75 |                 $('button#RESTART').on('click', function(e) {
76 |                     restart();
77 |                 });
78 |                 $('button#SAVE').on('click', function(e) {
79 |                     saveConfig();
80 |                 });
81 |             } else {
82 |                 toastr.error(data.message, '指令发送失败');
83 |             }
84 |         },
85 |         error: function() {
86 |             toastr.error('服务器异常', '指令发送失败');
87 |         }
88 |     });   
89 |     
90 | });
91 | 
92 | 


--------------------------------------------------------------------------------
/server/static/default.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 |   Theme: Default
3 |   Description: Original highlight.js style
4 |   Author: (c) Ivan Sagalaev <maniac@softwaremaniacs.org>
5 |   Maintainer: @highlightjs/core-team
6 |   Website: https://highlightjs.org/
7 |   License: see project LICENSE
8 |   Touched: 2021
9 | */pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#f3f3f3;color:#444}.hljs-comment{color:#697070}.hljs-punctuation,.hljs-tag{color:#444a}.hljs-tag .hljs-attr,.hljs-tag .hljs-name{color:#444}.hljs-attribute,.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-name,.hljs-selector-tag{font-weight:700}.hljs-deletion,.hljs-number,.hljs-quote,.hljs-selector-class,.hljs-selector-id,.hljs-string,.hljs-template-tag,.hljs-type{color:#800}.hljs-section,.hljs-title{color:#800;font-weight:700}.hljs-link,.hljs-operator,.hljs-regexp,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-symbol,.hljs-template-variable,.hljs-variable{color:#ab5656}.hljs-literal{color:#695}.hljs-addition,.hljs-built_in,.hljs-bullet,.hljs-code{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta .hljs-string{color:#38a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}


--------------------------------------------------------------------------------
/server/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/server/static/favicon.png


--------------------------------------------------------------------------------
/server/static/log.js:
--------------------------------------------------------------------------------
 1 | function refresh(msg) {
 2 |     $.ajax({
 3 |         url: '/getlog',
 4 |         type: "GET",
 5 |         data: $.param({'validate': getCookie('validation')}),
 6 |         success: function(res) {
 7 |             var data = JSON.parse(res);            
 8 |             if (data.code == 0) {
 9 |                 let log = data.log;
10 |                 $('#log-input').text(log);
11 |                 var scrollHeight = $('#log-input').prop("scrollHeight");
12 |                 $('#log-input').scrollTop(scrollHeight, 200);
13 |                 $('button#REFRESH').on('click', function(e) {
14 |                     refresh();
15 |                 });
16 |             } else {
17 |                 toastr.error(data.message, '日志读取失败');
18 |             }
19 |         },
20 |         error: function() {
21 |             toastr.error('服务器异常', '日志读取失败');
22 |         }
23 |     });   
24 | }
25 | 
26 | $(function() {
27 |     refresh();
28 | });
29 | 
30 | 


--------------------------------------------------------------------------------
/server/static/mfb.min.js:
--------------------------------------------------------------------------------
1 | !function(a,b){"use strict";function c(a,b){for(var c=0,d=a.length;d>c;c++)i=a[c].querySelector("."+r),i.addEventListener(b,f,!1)}function d(a){for(var b=0,c=a.length;c>b;b++)a[b].setAttribute(n,l),a[b].setAttribute(o,q)}function e(a){return b.querySelectorAll("["+n+'="'+a+'"]')}function f(a){for(j=a.target;j&&!j.getAttribute(n);)if(j=j.parentNode,!j)return;k=j.getAttribute(o)===p?q:p,j.setAttribute(o,k)}var g,h,i,j,k,l="click",m="hover",n="data-mfb-toggle",o="data-mfb-state",p="open",q="closed",r="mfb-component__button--main";a.Modernizr&&Modernizr.touch&&(h=e(m),d(h)),g=e(l),c(g,"click")}(window,document);


--------------------------------------------------------------------------------
/server/static/modernizr.touch.js:
--------------------------------------------------------------------------------
1 | /* Modernizr 2.8.3 (Custom Build) | MIT & BSD
2 |  * Build: http://modernizr.com/download/#-touch-teststyles-prefixes
3 |  */
4 | ;window.Modernizr=function(a,b,c){function v(a){i.cssText=a}function w(a,b){return v(l.join(a+";")+(b||""))}function x(a,b){return typeof a===b}function y(a,b){return!!~(""+a).indexOf(b)}function z(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:x(f,"function")?f.bind(d||b):f}return!1}var d="2.8.3",e={},f=b.documentElement,g="modernizr",h=b.createElement(g),i=h.style,j,k={}.toString,l=" -webkit- -moz- -o- -ms- ".split(" "),m={},n={},o={},p=[],q=p.slice,r,s=function(a,c,d,e){var h,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:g+(d+1),l.appendChild(j);return h=["&#173;",'<style id="s',g,'">',a,"</style>"].join(""),l.id=g,(m?l:n).innerHTML+=h,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=f.style.overflow,f.style.overflow="hidden",f.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),f.style.overflow=k),!!i},t={}.hasOwnProperty,u;!x(t,"undefined")&&!x(t.call,"undefined")?u=function(a,b){return t.call(a,b)}:u=function(a,b){return b in a&&x(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=q.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(q.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(q.call(arguments)))};return e}),m.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:s(["@media (",l.join("touch-enabled),("),g,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c};for(var A in m)u(m,A)&&(r=A.toLowerCase(),e[r]=m[A](),p.push((e[r]?"":"no-")+r));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)u(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof enableClasses!="undefined"&&enableClasses&&(f.className+=" "+(b?"":"no-")+a),e[a]=b}return e},v(""),h=j=null,e._version=d,e._prefixes=l,e.testStyles=s,e}(this,this.document);


--------------------------------------------------------------------------------
/server/static/monokai-sublime.css:
--------------------------------------------------------------------------------
 1 | /*
 2 |  *
 3 |  * Monokai Sublime style. Derived from Monokai by noformnocontent http://nn.mit-license.org/
 4 |  *
 5 |  * */
 6 | 
 7 | .hljs {
 8 |   display: block;
 9 |   overflow-x: auto;
10 |   padding: 0.5em;
11 |   background: #23241f;
12 | }
13 | 
14 | .hljs,
15 | .hljs-tag,
16 | .hljs-subst {
17 |   color: #f8f8f2;
18 | }
19 | 
20 | .hljs-strong,
21 | .hljs-emphasis {
22 |   color: #a8a8a2;
23 | }
24 | 
25 | .hljs-bullet,
26 | .hljs-quote,
27 | .hljs-number,
28 | .hljs-regexp,
29 | .hljs-literal,
30 | .hljs-link {
31 |   color: #ae81ff;
32 | }
33 | 
34 | .hljs-code,
35 | .hljs-title,
36 | .hljs-section,
37 | .hljs-selector-class {
38 |   color: #a6e22e;
39 | }
40 | 
41 | .hljs-strong {
42 |   font-weight: bold;
43 | }
44 | 
45 | .hljs-emphasis {
46 |   font-style: italic;
47 | }
48 | 
49 | .hljs-keyword,
50 | .hljs-selector-tag,
51 | .hljs-name,
52 | .hljs-attr {
53 |   color: #f92672;
54 | }
55 | 
56 | .hljs-symbol,
57 | .hljs-attribute {
58 |   color: #66d9ef;
59 | }
60 | 
61 | .hljs-params,
62 | .hljs-class .hljs-title {
63 |   color: #f8f8f2;
64 | }
65 | 
66 | .hljs-string,
67 | .hljs-type,
68 | .hljs-built_in,
69 | .hljs-builtin-name,
70 | .hljs-selector-id,
71 | .hljs-selector-attr,
72 | .hljs-selector-pseudo,
73 | .hljs-addition,
74 | .hljs-variable,
75 | .hljs-template-variable {
76 |   color: #e6db74;
77 | }
78 | 
79 | .hljs-comment,
80 | .hljs-deletion,
81 | .hljs-meta {
82 |   color: #75715e;
83 | }
84 | 


--------------------------------------------------------------------------------
/server/static/progressjs.min.css:
--------------------------------------------------------------------------------
1 | .progressjs-inner{width:0}.progressjs-progress{z-index:9999999}.progressjs-theme-blue .progressjs-inner{height:2px;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out;background-color:#3498db}.progressjs-theme-blue.progressjs-end{-webkit-transition:opacity .2s ease-out;-moz-transition:opacity .2s ease-out;-o-transition:opacity .2s ease-out;transition:opacity .2s ease-out;opacity:0}.progressjs-theme-blue .progressjs-percent{display:none}.progressjs-theme-blueOverlay{background-color:white;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out}.progressjs-theme-blueOverlay .progressjs-inner{height:100%;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out;background-color:#3498db}.progressjs-theme-blueOverlay.progressjs-end{opacity:0!important}.progressjs-theme-blueOverlay .progressjs-percent{display:none}.progressjs-theme-blueOverlay{background-color:white;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out}.progressjs-theme-blueOverlay .progressjs-inner{height:100%;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out;background-color:#3498db}.progressjs-theme-blueOverlay.progressjs-end{opacity:0!important}.progressjs-theme-blueOverlay .progressjs-percent{display:none}.progressjs-theme-blueOverlayRadius{background-color:white;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out;border-radius:5px}.progressjs-theme-blueOverlayRadius .progressjs-inner{height:100%;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out;background-color:#3498db;border-radius:5px}.progressjs-theme-blueOverlayRadius.progressjs-end{opacity:0!important}.progressjs-theme-blueOverlayRadius .progressjs-percent{display:none}.progressjs-theme-blueOverlayRadiusHalfOpacity{background-color:white;opacity:.5;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out;border-radius:5px}.progressjs-theme-blueOverlayRadiusHalfOpacity .progressjs-inner{height:100%;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out;background-color:#3498db;border-radius:5px}.progressjs-theme-blueOverlayRadiusHalfOpacity.progressjs-end{opacity:0!important}.progressjs-theme-blueOverlayRadiusHalfOpacity .progressjs-percent{display:none}.progressjs-theme-blueOverlayRadiusWithPercentBar{background-color:white;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out;border-radius:5px}.progressjs-theme-blueOverlayRadiusWithPercentBar .progressjs-inner{height:100%;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out;background-color:#3498db;border-radius:5px}.progressjs-theme-blueOverlayRadiusWithPercentBar.progressjs-end{opacity:0!important}.progressjs-theme-blueOverlayRadiusWithPercentBar .progressjs-percent{width:70px;text-align:center;height:40px;position:absolute;right:50%;margin-right:-35px;top:50%;margin-top:-20px;font-size:30px;opacity:.5}.progressjs-theme-blackRadiusInputs{height:10px;border-radius:10px;overflow:hidden}.progressjs-theme-blackRadiusInputs .progressjs-inner{height:2px;-webkit-transition:all 1s ease-out;-moz-transition:all 1s ease-out;-o-transition:all 1s ease-out;transition:all 1s ease-out;background-color:#34495e}.progressjs-theme-blackRadiusInputs.progressjs-end{-webkit-transition:opacity .2s ease-out;-moz-transition:opacity .2s ease-out;-o-transition:opacity .2s ease-out;transition:opacity .2s ease-out;opacity:0}.progressjs-theme-blackRadiusInputs .progressjs-percent{display:none}


--------------------------------------------------------------------------------
/server/static/qa.js:
--------------------------------------------------------------------------------
 1 | function upload() {
 2 |     $.ajax({
 3 |         url: '/qa',
 4 |         type: "POST",
 5 |         data: {"qa": $('#qa-input').val(), 'validate': getCookie('validation')},
 6 |         success: function(res) {
 7 |             var data = JSON.parse(res);
 8 |             if (data.code == 0) {
 9 |                 toastr.success('提交成功');
10 |             } else {
11 |                 toastr.error(data.message, '提交失败');
12 |             }
13 |         },
14 |         error: function() {
15 |             toastr.error('服务器异常', '设置失败');
16 |         }
17 |     });
18 | }
19 | 
20 | 
21 | $(function() {
22 |     $('button#UPLOAD').on('click', function(e) {
23 |         upload();
24 |     });
25 | });
26 | 
27 | 
28 | $(document).delegate('#qa-input', 'keydown', function(e) {
29 |     var keyCode = e.keyCode || e.which;
30 | 
31 |     if (keyCode == 9) {
32 |         e.preventDefault();
33 |         var start = this.selectionStart;
34 |         var end = this.selectionEnd;
35 | 
36 |         // set textarea value to: text before caret + tab + text after caret
37 |         $(this).val($(this).val().substring(0, start)
38 |                     + "\t"
39 |                     + $(this).val().substring(end));
40 | 
41 |         // put caret at right position again
42 |         this.selectionStart =
43 |             this.selectionEnd = start + 1;
44 |     }
45 | });
46 | 


--------------------------------------------------------------------------------
/server/static/robot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/server/static/robot.png


--------------------------------------------------------------------------------
/server/static/signin.css:
--------------------------------------------------------------------------------
 1 | html,
 2 | body {
 3 |     height: 100%;
 4 | }
 5 | 
 6 | body {
 7 |     display: -ms-flexbox;
 8 |     display: flex;
 9 |     -ms-flex-align: center;
10 |     align-items: center;
11 |     padding-top: 40px;
12 |     padding-bottom: 40px;
13 |     background-color: #f5f5f5;
14 | }
15 | 
16 | .form-signin {
17 |     width: 100%;
18 |     max-width: 330px;
19 |     padding: 15px;
20 |     margin: auto;
21 | }
22 | .form-signin .checkbox {
23 |     font-weight: 400;
24 | }
25 | .form-signin .form-control {
26 |     position: relative;
27 |     box-sizing: border-box;
28 |     height: auto;
29 |     padding: 10px;
30 |     font-size: 16px;
31 | }
32 | .form-signin .form-control:focus {
33 |     z-index: 2;
34 | }
35 | .form-signin input[type="email"] {
36 |     margin-bottom: -1px;
37 |     border-bottom-right-radius: 0;
38 |     border-bottom-left-radius: 0;
39 | }
40 | .form-signin input[type="password"] {
41 |     margin-bottom: 10px;
42 |     border-top-left-radius: 0;
43 |     border-top-right-radius: 0;
44 | }
45 | 
46 | .footer {
47 |     display: block;
48 |     width: 0;
49 |     height: 0;
50 | }
51 | 


--------------------------------------------------------------------------------
/server/static/spin.css:
--------------------------------------------------------------------------------
 1 | @keyframes spinner-line-fade-more {
 2 |   0%, 100% {
 3 |     opacity: 0; /* minimum opacity */
 4 |   }
 5 |   1% {
 6 |     opacity: 1;
 7 |   }
 8 | }
 9 | 
10 | @keyframes spinner-line-fade-quick {
11 |   0%, 39%, 100% {
12 |     opacity: 0.25; /* minimum opacity */
13 |   }
14 |   40% {
15 |     opacity: 1;
16 |   }
17 | }
18 | 
19 | @keyframes spinner-line-fade-default {
20 |   0%, 100% {
21 |     opacity: 0.22; /* minimum opacity */
22 |   }
23 |   1% {
24 |     opacity: 1;
25 |   }
26 | }
27 | 


--------------------------------------------------------------------------------
/server/static/starter-template.css:
--------------------------------------------------------------------------------
 1 | body {
 2 |     padding-top: 3rem;
 3 | }
 4 | 
 5 | .starter-template {
 6 |     padding-top: 3rem;    
 7 | }
 8 | 
 9 | .update-alert {
10 |     margin-left: 0;
11 |     margin-right: 0;
12 | }
13 | 
14 | .container div.history {
15 |     background: #EAEAEA;
16 |     border: 1px solid #e1e4e8;
17 |     border-radius: 3px;
18 |     box-shadow: inset 0 0 10px rgba(27,31,35,.05);
19 |     padding-top: 32px;
20 |     padding-bottom: 30px;
21 |     padding-left: 32px;
22 |     max-height: 400px;
23 |     overflow-y:scroll;
24 |     overflow-x:hidden;
25 | }
26 | 
27 | .container div.query-form {
28 |     margin-top: 2rem;
29 | }
30 | 
31 | .container.log {
32 |     padding-top: 32px;
33 | }
34 | 
35 | .container.config {
36 |     padding-top: 32px;
37 | }
38 | 
39 | .container.api {
40 |     padding-top: 32px;    
41 | }
42 | 
43 | .footer {
44 |     text-align: center;
45 |     margin-top: 10px;
46 |     padding-top: 10px;
47 |     margin-bottom: 10px;
48 |     padding-bottom: 10px;
49 |     min-height: 15px;
50 | }
51 | 
52 | .bubble img {
53 |     width:auto;
54 |     max-width: 100%;
55 | }
56 | 
57 | .divider {
58 |     margin: 5rem 0;
59 | }
60 | 
61 | @media (min-width: 40em)
62 | .featurette-heading {
63 |     font-size: 50px;
64 | }
65 | 
66 | .featurette-heading {
67 |     font-weight: 300;
68 |     line-height: 1;
69 |     letter-spacing: -.05rem;
70 | }
71 | 
72 | .quote {
73 |     padding: 1rem;
74 |     font-family: Lora,Georgia,"Times New Roman",'楷体',STKaiti,serif;
75 |     font-style: italic;
76 | }
77 | 
78 | .bubble .plugin{
79 |     float: right;
80 | }
81 | 
82 | .hljs {
83 |     border-radius: 4.5px;
84 | }


--------------------------------------------------------------------------------
/server/static/static.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/server/static/static.js


--------------------------------------------------------------------------------
/server/static/waveWorker.min.js:
--------------------------------------------------------------------------------
1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.WaveWorker=t():e.WaveWorker=t()}("undefined"!=typeof self?self:this,function(){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var s=t[n]={i:n,l:!1,exports:{}};return e[n].call(s.exports,s,s.exports,r),s.l=!0,s.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var s in e)r.d(n,s,function(t){return e[t]}.bind(null,s));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=0)}([function(e,t,r){"use strict";(function(t){var r;t.onmessage=function(e){switch(e.data.command){case"encode":r&&r.record(e.data.buffers);break;case"done":r&&(r.requestData(),r=null);break;case"close":t.close();break;case"init":r=new n(e.data),t.postMessage({message:"ready"})}};var n=function(e){if(!(e=Object.assign({wavBitDepth:16},e)).wavSampleRate)throw new Error("wavSampleRate value is required to record. NOTE: Audio is not resampled!");if(-1===[8,16,24,32].indexOf(e.wavBitDepth))throw new Error("Only 8, 16, 24 and 32 bits per sample are supported");this.bitDepth=e.wavBitDepth,this.sampleRate=e.wavSampleRate,this.recordedBuffers=[],this.bytesPerSample=this.bitDepth/8};n.prototype.record=function(e){this.numberOfChannels=this.numberOfChannels||e.length;for(var t=e[0].length,r=new Uint8Array(t*this.numberOfChannels*this.bytesPerSample),n=0;n<t;n++)for(var s=0;s<this.numberOfChannels;s++){var a=(n*this.numberOfChannels+s)*this.bytesPerSample,i=Math.max(-1,Math.min(1,e[s][n]));switch(this.bytesPerSample){case 4:i=2147483647.5*i-.5,r[a]=i,r[a+1]=i>>8,r[a+2]=i>>16,r[a+3]=i>>24;break;case 3:i=8388607.5*i-.5,r[a]=i,r[a+1]=i>>8,r[a+2]=i>>16;break;case 2:i=32767.5*i-.5,r[a]=i,r[a+1]=i>>8;break;case 1:r[a]=127.5*(i+1);break;default:throw new Error("Only 8, 16, 24 and 32 bits per sample are supported")}}this.recordedBuffers.push(r)},n.prototype.requestData=function(){var e=this.recordedBuffers[0].length,r=this.recordedBuffers.length*e,n=new Uint8Array(44+r),s=new DataView(n.buffer);s.setUint32(0,1380533830,!1),s.setUint32(4,36+r,!0),s.setUint32(8,1463899717,!1),s.setUint32(12,1718449184,!1),s.setUint32(16,16,!0),s.setUint16(20,1,!0),s.setUint16(22,this.numberOfChannels,!0),s.setUint32(24,this.sampleRate,!0),s.setUint32(28,this.sampleRate*this.bytesPerSample*this.numberOfChannels,!0),s.setUint16(32,this.bytesPerSample*this.numberOfChannels,!0),s.setUint16(34,this.bitDepth,!0),s.setUint32(36,1684108385,!1),s.setUint32(40,r,!0);for(var a=0;a<this.recordedBuffers.length;a++)n.set(this.recordedBuffers[a],a*e+44);t.postMessage({message:"page",page:n},[n.buffer]),t.postMessage({message:"done"})},e.exports=n}).call(this,r(1))},function(e,t){var r;r=function(){return this}();try{r=r||new Function("return this")()}catch(e){"object"==typeof window&&(r=window)}e.exports=r}])});


--------------------------------------------------------------------------------
/server/templates/api.html:
--------------------------------------------------------------------------------
 1 | {% extends "layout.html" %}
 2 | {% block body %}
 3 | <link rel="stylesheet" href="{{static_url('starter-template.css')}}" crossorigin="anonymous">
 4 | <link rel="stylesheet" href="{{static_url('api.css')}}" crossorigin="anonymous">
 5 | <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
 6 |   <a class="navbar-brand" href="/">wukong-robot</a>
 7 |   <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
 8 |     <span class="navbar-toggler-icon"></span>
 9 |   </button>
10 |   <div class="collapse navbar-collapse" id="navbarsExampleDefault">
11 |     <ul class="navbar-nav mr-auto">
12 |       <li class="nav-item">
13 |         <a class="nav-link" href="/">会话</a>
14 |       </li>
15 |       <li class="nav-item">
16 |         <a class="nav-link" href="/configpage">配置</a>
17 |       </li>
18 |       <li class="nav-item">
19 |         <a class="nav-link" href="/logpage">日志</a>
20 |       </li>
21 |       <li class="nav-item">
22 |         <a class="nav-link" href="/qa">QA集</a>
23 |       </li>
24 |       <li class="nav-item active">
25 |         <a class="nav-link" href="/api">API</a>
26 |       </li>
27 |       <li class="nav-item">
28 |         <a class="nav-link" href="/donate">捐赠</a>
29 |       </li>
30 |     </ul>
31 |     <div class="form-inline my-2 my-lg-0">
32 |     <a class="btn btn-outline-success my-2 my-sm-0" href="https://wukong.hahack.com" target="_blank">文档</a>
33 |     </div>
34 |   </div>
35 | </nav>
36 | 
37 | <div class="container api">
38 |   {% raw content %}
39 | </div>
40 | 
41 | <ul id="recorder" class="mfb-component--br mfb-zoomin" data-mfb-toggle="hover">
42 |       <li class="mfb-component__wrap">
43 |         <a href="#" id="record" class="mfb-component__button--main">
44 |           <i class="mfb-component__main-icon--resting fa fa-microphone"></i>
45 |           <i class="mfb-component__main-icon--active fa fa-times"></i>
46 |         </a>
47 |         <ul class="mfb-component__list">
48 |           <li>
49 |             <a href="#" id="stop-record" data-mfb-label="停止录制语音指令" class="mfb-component__button--child">
50 |               <i class="mfb-component__child-icon fas fa-stop"></i>
51 |             </a>
52 |           </li>
53 |           <li>
54 |             <a href="#" id="start-record" data-mfb-label="开始录制语音指令" class="mfb-component__button--child ">
55 |               <i class="mfb-component__child-icon fas fa-circle"></i>
56 |             </a>
57 |           </li>
58 |         </ul>
59 |       </li>
60 | </ul>
61 | 
62 | 
63 | <script src="{{static_url('main.js')}}" crossorigin="anonymous"></script>
64 | <script src="{{static_url('log.js')}}" crossorigin="anonymous"></script>
65 | <script src="./static/recorder.min.js"></script>
66 | {% end %}
67 | 


--------------------------------------------------------------------------------
/server/templates/config.html:
--------------------------------------------------------------------------------
 1 | {% extends "layout.html" %}
 2 | {% block body %}
 3 | <link rel="stylesheet" href="{{static_url('starter-template.css')}}" crossorigin="anonymous">
 4 | 
 5 | <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
 6 |   <a class="navbar-brand" href="/">wukong-robot</a>
 7 |   <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
 8 |     <span class="navbar-toggler-icon"></span>
 9 |   </button>
10 |   <div class="collapse navbar-collapse" id="navbarsExampleDefault">
11 |     <ul class="navbar-nav mr-auto">
12 |       <li class="nav-item">
13 |         <a class="nav-link" href="/">会话</a>
14 |       </li>
15 |       <li class="nav-item active">
16 |         <a class="nav-link" href="/configpage">配置</a>
17 |       </li>
18 |       <li class="nav-item">
19 |         <a class="nav-link" href="/logpage">日志</a>
20 |       </li>
21 |       <li class="nav-item">
22 |         <a class="nav-link" href="/qa">QA集</a>
23 |       </li>
24 |       <li class="nav-item">
25 |         <a class="nav-link" href="/api">API</a>
26 |       </li>
27 |       <li class="nav-item">
28 |         <a class="nav-link" href="/donate">捐赠</a>
29 |       </li>
30 |     </ul>
31 |     <div class="form-inline my-2 my-lg-0">
32 |       <a class="btn btn-outline-success my-2 my-sm-0" href="https://wukong.hahack.com" target="_blank">文档</a>
33 |     </div>
34 |   </div>
35 | </nav>
36 | 
37 | <div class="container config">
38 |   <div class="alert alert-info" role="alert">
39 |     <i class="fas fa-bell"></i> 唤醒词和敏感度的修改需重启 wukong-robot 后才生效。
40 |   </div>
41 |   <label for="sensitivity">离线唤醒敏感度:<span id="sensitivitiy-value"></span> </label>
42 |   <input type="range" class="custom-range" min="0" max="1" step="0.1" value="{{sensitivity}}" id="sensitivity">
43 |   <br/>
44 |   <label for="config-form">配置文件</label>
45 |   <div id="config-placeholder">
46 |   </div>
47 | </div>
48 | 
49 | <ul id="recorder" class="mfb-component--br mfb-zoomin" data-mfb-toggle="hover">
50 |       <li class="mfb-component__wrap">
51 |         <a href="#" id="record" class="mfb-component__button--main">
52 |           <i class="mfb-component__main-icon--resting fa fa-microphone"></i>
53 |           <i class="mfb-component__main-icon--active fa fa-times"></i>
54 |         </a>
55 |         <ul class="mfb-component__list">
56 |           <li>
57 |             <a href="#" id="stop-record" data-mfb-label="停止录制语音指令" class="mfb-component__button--child">
58 |               <i class="mfb-component__child-icon fas fa-stop"></i>
59 |             </a>
60 |           </li>
61 |           <li>
62 |             <a href="#" id="start-record" data-mfb-label="开始录制语音指令" class="mfb-component__button--child ">
63 |               <i class="mfb-component__child-icon fas fa-circle"></i>
64 |             </a>
65 |           </li>
66 |         </ul>
67 |       </li>
68 | </ul>
69 | 
70 | <div class="modal fade" id="restartModal" tabindex="-1" role="dialog" aria-labelledby="restartModalLabel" aria-hidden="true">
71 |   <div class="modal-dialog" role="document">
72 |     <div class="modal-content">
73 |       <div class="modal-header">
74 |         <h5 class="modal-title" id="restartModalLabel">你确定吗?</h5>
75 |         <button type="button" class="close" data-dismiss="modal" aria-label="Close">
76 |           <span aria-hidden="true">&times;</span>
77 |         </button>
78 |       </div>
79 |       <div class="modal-body">
80 |         确定要重启 wukong-robot 吗?
81 |       </div>
82 |       <div class="modal-footer">
83 |         <button type="button" class="btn btn-secondary" data-dismiss="modal">只是手抖</button>
84 |         <button type="button" class="btn btn-primary" id="RESTART" data-dismiss="modal">确定</button>
85 |       </div>
86 |     </div>
87 |   </div>
88 | </div>
89 | 
90 | 
91 | <script src="{{static_url('main.js')}}" crossorigin="anonymous"></script>
92 | <script src="{{static_url('config.js')}}" crossorigin="anonymous"></script>
93 | <script src="{{static_url('bootbox.js')}}" crossorigin="anonymous"></script>
94 | <script src="./static/recorder.min.js"></script>
95 | {% end %}
96 | 


--------------------------------------------------------------------------------
/server/templates/donate.html:
--------------------------------------------------------------------------------
 1 | {% extends "layout.html" %}
 2 | {% block body %}
 3 | <link rel="stylesheet" href="{{static_url('starter-template.css')}}" crossorigin="anonymous">
 4 | <link rel="stylesheet" href="{{static_url('api.css')}}" crossorigin="anonymous">
 5 | <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
 6 |   <a class="navbar-brand" href="/">wukong-robot</a>
 7 |   <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
 8 |     <span class="navbar-toggler-icon"></span>
 9 |   </button>
10 |   <div class="collapse navbar-collapse" id="navbarsExampleDefault">
11 |     <ul class="navbar-nav mr-auto">
12 |       <li class="nav-item">
13 |         <a class="nav-link" href="/">会话</a>
14 |       </li>
15 |       <li class="nav-item">
16 |         <a class="nav-link" href="/configpage">配置</a>
17 |       </li>
18 |       <li class="nav-item">
19 |         <a class="nav-link" href="/logpage">日志</a>
20 |       </li>
21 |       <li class="nav-item">
22 |         <a class="nav-link" href="/qa">QA集</a>
23 |       </li>
24 |       <li class="nav-item">
25 |         <a class="nav-link" href="/api">API</a>
26 |       </li>
27 |       <li class="nav-item active">
28 |         <a class="nav-link" href="/donate">捐赠</a>
29 |       </li>
30 |     </ul>
31 |     <div class="form-inline my-2 my-lg-0">
32 |     <a class="btn btn-outline-success my-2 my-sm-0" href="https://wukong.hahack.com" target="_blank">文档</a>
33 |     </div>
34 |   </div>
35 | </nav>
36 | 
37 | <div class="container api">
38 |   {% raw content %}
39 | </div>
40 | 
41 | <ul id="recorder" class="mfb-component--br mfb-zoomin" data-mfb-toggle="hover">
42 |       <li class="mfb-component__wrap">
43 |         <a href="#" id="record" class="mfb-component__button--main">
44 |           <i class="mfb-component__main-icon--resting fa fa-microphone"></i>
45 |           <i class="mfb-component__main-icon--active fa fa-times"></i>
46 |         </a>
47 |         <ul class="mfb-component__list">
48 |           <li>
49 |             <a href="#" id="stop-record" data-mfb-label="停止录制语音指令" class="mfb-component__button--child">
50 |               <i class="mfb-component__child-icon fas fa-stop"></i>
51 |             </a>
52 |           </li>
53 |           <li>
54 |             <a href="#" id="start-record" data-mfb-label="开始录制语音指令" class="mfb-component__button--child ">
55 |               <i class="mfb-component__child-icon fas fa-circle"></i>
56 |             </a>
57 |           </li>
58 |         </ul>
59 |       </li>
60 | </ul>
61 | 
62 | 
63 | <script src="{{static_url('main.js')}}" crossorigin="anonymous"></script>
64 | <script src="{{static_url('log.js')}}" crossorigin="anonymous"></script>
65 | <script src="./static/recorder.min.js"></script>
66 | {% end %}
67 | 


--------------------------------------------------------------------------------
/server/templates/layout.html:
--------------------------------------------------------------------------------
 1 | <!doctype html>
 2 | <html lang="en" class="h-100">
 3 |   <head>
 4 |     <meta charset="utf-8">
 5 |     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
 6 |     <meta name="description" content="">
 7 |     <meta name="author" content="Joseph Pan">
 8 |     <meta name="generator" content="Jekyll v3.8.5">
 9 |     <title>wukong-robot</title>
10 | 
11 |     <!-- Bootstrap core CSS -->
12 |     <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
13 |     <link rel="stylesheet" href="./static/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
14 |     <link rel="stylesheet" href="./static/toastr.min.css" crossorigin="anonymous">
15 |     <link href="./static/mfb.min.css" rel="stylesheet">
16 |     <link rel="stylesheet" type="text/css" href="./static/jquery.fancybox.css">
17 |     
18 |     <link rel="stylesheet" href="{{static_url('spin.css')}}" crossorigin="anonymous">
19 |     <link href="./static/favicon.png" rel='icon' type='image/x-icon'/>
20 |     <script src="./static/popper.min.js" crossorigin="anonymous"></script>
21 |     <script src="./static/jquery-3.3.1.min.js" crossorigin="anonymous"></script>
22 |     <script src="./static/jquery.fancybox.js"></script>
23 |     
24 | 
25 |     <style>
26 |       .bd-placeholder-img {
27 |           font-size: 1.125rem;
28 |           text-anchor: middle;
29 |       }
30 | 
31 |       @media (min-width: 768px) {
32 |           .bd-placeholder-img-lg {
33 |               font-size: 3.5rem;
34 |           }
35 |       }
36 |     </style>
37 |     <!-- Custom styles for this template -->
38 | 
39 |   </head>
40 |   <body>
41 |         {% block body %}
42 |         {% end %}
43 |         <div class="footer">
44 |           <span class="mt-5 mb-3 text-muted"><a href="http://github.com/wzpan/wukong-robot" target="_blank">wukong-robot</a> &copy; 2019 </span>
45 |         </div>
46 | 
47 |         <script src="./static/modernizr.touch.js"></script>
48 |         <script src="./static/mfb.min.js"></script>
49 |         <script src="./static/toastr.min.js" crossorigin="anonymous"></script>
50 |         <script src="./static/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
51 |   </body>
52 | </html>
53 | 


--------------------------------------------------------------------------------
/server/templates/log.html:
--------------------------------------------------------------------------------
 1 | {% extends "layout.html" %}
 2 | {% block body %}
 3 | <link rel="stylesheet" href="{{static_url('starter-template.css')}}" crossorigin="anonymous">
 4 | 
 5 | <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
 6 |   <a class="navbar-brand" href="/">wukong-robot</a>
 7 |   <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
 8 |     <span class="navbar-toggler-icon"></span>
 9 |   </button>
10 |   <div class="collapse navbar-collapse" id="navbarsExampleDefault">
11 |     <ul class="navbar-nav mr-auto">
12 |       <li class="nav-item">
13 |         <a class="nav-link" href="/">会话</a>
14 |       </li>
15 |       <li class="nav-item">
16 |         <a class="nav-link" href="/configpage">配置</a>
17 |       </li>
18 |       <li class="nav-item active">
19 |         <a class="nav-link" href="/logpage">日志</a>
20 |       </li>
21 |       <li class="nav-item">
22 |         <a class="nav-link" href="/qa">QA集</a>
23 |       </li>
24 |       <li class="nav-item">
25 |         <a class="nav-link" href="/api">API</a>
26 |       </li>
27 |       <li class="nav-item">
28 |         <a class="nav-link" href="/donate">捐赠</a>
29 |       </li>
30 |     </ul>
31 |     <div class="form-inline my-2 my-lg-0">
32 |       <a class="btn btn-outline-success my-2 my-sm-0" href="https://wukong.hahack.com" target="_blank">文档</a>
33 |     </div>
34 |   </div>
35 | </nav>
36 | 
37 | <div class="container log">
38 |   <div class="alert alert-info" role="alert">
39 |     <i class="fas fa-bell"></i> 日志不会自动刷新,要查看最新日志,请点击【刷新日志】按钮。
40 |   </div>
41 |   <label for="config-form">日志内容</label>
42 |   <form class="form log-form" action="#">
43 |     <div class="input-group" id="container">
44 |       <div class="input-group-prepend">
45 |         <span class="input-group-text">wukong.log</span>
46 |       </div>
47 |         <textarea rows="25" class="form-control" id="log-input" placer='1' aria-label="wukong.log" readonly></textarea>
48 |     </div>
49 |     <hr>
50 |     <center>
51 |     <button type="button" class="btn btn-primary mb-2" id="REFRESH"><i class="fas fa-sync"></i> 刷新日志</button>
52 |     </center>
53 |   </form>
54 | </div>
55 | 
56 | 
57 | <ul id="recorder" class="mfb-component--br mfb-zoomin" data-mfb-toggle="hover">
58 |       <li class="mfb-component__wrap">
59 |         <a href="#" id="record" class="mfb-component__button--main">
60 |           <i class="mfb-component__main-icon--resting fa fa-microphone"></i>
61 |           <i class="mfb-component__main-icon--active fa fa-times"></i>
62 |         </a>
63 |         <ul class="mfb-component__list">
64 |           <li>
65 |             <a href="#" id="stop-record" data-mfb-label="停止录制语音指令" class="mfb-component__button--child">
66 |               <i class="mfb-component__child-icon fas fa-stop"></i>
67 |             </a>
68 |           </li>
69 |           <li>
70 |             <a href="#" id="start-record" data-mfb-label="开始录制语音指令" class="mfb-component__button--child ">
71 |               <i class="mfb-component__child-icon fas fa-circle"></i>
72 |             </a>
73 |           </li>
74 |         </ul>
75 |       </li>
76 | </ul>
77 | 
78 | 
79 | <script src="{{static_url('main.js')}}" crossorigin="anonymous"></script>
80 | <script src="{{static_url('log.js')}}" crossorigin="anonymous"></script>
81 | <script src="./static/recorder.min.js"></script>
82 | {% end %}
83 | 


--------------------------------------------------------------------------------
/server/templates/login.html:
--------------------------------------------------------------------------------
 1 | {% extends "layout.html" %}
 2 | {% block body %}
 3 | <link href="{{static_url('signin.css')}}" rel="stylesheet">
 4 |   <div class="container">
 5 |   <form action="/login" class="form-signin" method=post>
 6 |     {% module xsrf_form_html() %}
 7 |     <center>
 8 |       <h1 class="h3 mb-3 font-weight-normal">Please login</h1>
 9 |       <label for="username" class="sr-only">User Name</label>
10 |       <input type="text" name="username" class="form-control" placeholder="User Name" required autofocus>
11 |       <label for="password" class="sr-only">Password</label>
12 |       <input type="password" name="password" class="form-control" placeholder="Password" required>
13 |       <p><input class="btn btn-lg btn-primary btn-block" type=submit value=Login></p>
14 |       {% if error %}
15 |       <p style="color:#ff0000">{{ error }}</p>
16 |       {% end %}
17 |     </center>
18 |   </form>
19 |   </div>
20 | {% end %}
21 | 


--------------------------------------------------------------------------------
/server/templates/qa.html:
--------------------------------------------------------------------------------
  1 | {% extends "layout.html" %}
  2 | {% block body %}
  3 | <link rel="stylesheet" href="{{static_url('starter-template.css')}}" crossorigin="anonymous">
  4 | <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
  5 |   <a class="navbar-brand" href="/">wukong-robot</a>
  6 |   <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
  7 |     <span class="navbar-toggler-icon"></span>
  8 |   </button>
  9 |   <div class="collapse navbar-collapse" id="navbarsExampleDefault">
 10 |     <ul class="navbar-nav mr-auto">
 11 |       <li class="nav-item">
 12 |         <a class="nav-link" href="/">会话</a>
 13 |       </li>
 14 |       <li class="nav-item">
 15 |         <a class="nav-link" href="/configpage">配置</a>
 16 |       </li>
 17 |       <li class="nav-item">
 18 |         <a class="nav-link" href="/logpage">日志</a>
 19 |       </li>
 20 |       <li class="nav-item active">
 21 |         <a class="nav-link" href="/qa">QA集</a>
 22 |       </li>
 23 |       <li class="nav-item">
 24 |         <a class="nav-link" href="/api">API</a>
 25 |       </li>
 26 |       <li class="nav-item">
 27 |         <a class="nav-link" href="/donate">捐赠</a>
 28 |       </li>
 29 |     </ul>
 30 |     <div class="form-inline my-2 my-lg-0">
 31 |     <a class="btn btn-outline-success my-2 my-sm-0" href="https://wukong.hahack.com" target="_blank">文档</a>
 32 |     </div>
 33 |   </div>
 34 | </nav>
 35 | 
 36 | <div class="container api">
 37 |   <div class="alert alert-info" role="alert">
 38 |     <i class="fas fa-bell"></i> 本页面用于维护 wukong-robot 的 <a href="http://github.com/baidu/AnyQ" target="_blank">AnyQ</a> QA 数据集。在配置中将 <code>robot</code> 设为 <code>anyq</code> 后,将会优先选择本 QA 集。<br/>
 39 |     <i class="fas fa-question"></i> 要了解如何安装配置 AnyQ 以及编辑和贡献 QA 数据,可以查看<a href="https://wukong.hahack.com/#/anyq" target="_blank">这篇教程</a>。
 40 |   </div>
 41 |   <label for="qa-form">数据集(请使用制表符 <code>TAB</code> 隔开问题和答案)</label>
 42 |   <form class="form qa-form" action="#">
 43 |     <div class="input-group" id="container">
 44 |       <div class="input-group-prepend">
 45 |         <span class="input-group-text">qa.csv</span>
 46 |       </div>
 47 |         <textarea rows="20" class="form-control" id="qa-input" placer='1' aria-label="With textarea">{% raw content %}</textarea>
 48 |     </div>
 49 |     <hr>
 50 |     <center>
 51 |       <button type="button" class="btn btn-primary mb-2" data-toggle="modal" data-target="#uploadModal"><i class="fas fa-upload"></i> 提交</button>
 52 |     </center>
 53 |   </form>
 54 |   
 55 | </div>
 56 | 
 57 | <div class="modal fade" id="uploadModal" tabindex="-1" role="dialog" aria-labelledby="restartModalLabel" aria-hidden="true">
 58 |   <div class="modal-dialog" role="document">
 59 |     <div class="modal-content">
 60 |       <div class="modal-header">
 61 |         <h5 class="modal-title" id="restartModalLabel">你确定吗?</h5>
 62 |         <button type="button" class="close" data-dismiss="modal" aria-label="Close">
 63 |           <span aria-hidden="true">&times;</span>
 64 |         </button>
 65 |       </div>
 66 |       <div class="modal-body">
 67 |         确定要覆盖现有的QA数据集吗?
 68 |       </div>
 69 |       <div class="modal-footer">
 70 |         <button type="button" class="btn btn-secondary" data-dismiss="modal">只是手抖</button>
 71 |         <button type="button" class="btn btn-primary" id="UPLOAD" data-dismiss="modal">确定</button>
 72 |       </div>
 73 |     </div>
 74 |   </div>
 75 | </div>
 76 | 
 77 | 
 78 | <ul id="recorder" class="mfb-component--br mfb-zoomin" data-mfb-toggle="hover">
 79 |       <li class="mfb-component__wrap">
 80 |         <a href="#" id="record" class="mfb-component__button--main">
 81 |           <i class="mfb-component__main-icon--resting fa fa-microphone"></i>
 82 |           <i class="mfb-component__main-icon--active fa fa-times"></i>
 83 |         </a>
 84 |         <ul class="mfb-component__list">
 85 |           <li>
 86 |             <a href="#" id="stop-record" data-mfb-label="停止录制语音指令" class="mfb-component__button--child">
 87 |               <i class="mfb-component__child-icon fas fa-stop"></i>
 88 |             </a>
 89 |           </li>
 90 |           <li>
 91 |             <a href="#" id="start-record" data-mfb-label="开始录制语音指令" class="mfb-component__button--child ">
 92 |               <i class="mfb-component__child-icon fas fa-circle"></i>
 93 |             </a>
 94 |           </li>
 95 |         </ul>
 96 |       </li>
 97 | </ul>
 98 | 
 99 | 
100 | <script src="{{static_url('main.js')}}" crossorigin="anonymous"></script>
101 | <script src="{{static_url('log.js')}}" crossorigin="anonymous"></script>
102 | <script src="{{static_url('qa.js')}}" crossorigin="anonymous"></script>
103 | <script src="./static/recorder.min.js"></script>
104 | {% end %}
105 | 


--------------------------------------------------------------------------------
/snowboy/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/snowboy/__init__.py


--------------------------------------------------------------------------------
/snowboy/resources/common.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/snowboy/resources/common.res


--------------------------------------------------------------------------------
/snowboy/resources/ding.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/snowboy/resources/ding.wav


--------------------------------------------------------------------------------
/snowboy/resources/dong.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/snowboy/resources/dong.wav


--------------------------------------------------------------------------------
/static/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/static/background.png


--------------------------------------------------------------------------------
/static/beep_hi.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/static/beep_hi.wav


--------------------------------------------------------------------------------
/static/beep_lo.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/static/beep_lo.wav


--------------------------------------------------------------------------------
/static/camera.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/static/camera.wav


--------------------------------------------------------------------------------
/static/off.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/static/off.wav


--------------------------------------------------------------------------------
/static/on.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/static/on.wav


--------------------------------------------------------------------------------
/static/snowboy.umdl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/static/snowboy.umdl


--------------------------------------------------------------------------------
/static/wukong.pmdl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/static/wukong.pmdl


--------------------------------------------------------------------------------
/static/wukong_pi.pmdl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/static/wukong_pi.pmdl


--------------------------------------------------------------------------------
/static/zhimakaimen.pmdl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/static/zhimakaimen.pmdl


--------------------------------------------------------------------------------
/temp/DIR:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wzpan/wukong-robot/3fd73e075bc3fb22a36191f5e656c52aebcc6834/temp/DIR


--------------------------------------------------------------------------------
/tools/changelog.sh:
--------------------------------------------------------------------------------
1 | conventional-changelog -p angular -i CHANGELOG.md -w


--------------------------------------------------------------------------------
/tools/make_json.py:
--------------------------------------------------------------------------------
 1 | # coding=utf-8
 2 | 
 3 | # Copyright (c) 2018 Baidu, Inc. All Rights Reserved.
 4 | #
 5 | # Licensed under the Apache License, Version 2.0 (the "License");
 6 | # you may not use this file except in compliance with the License.
 7 | # You may obtain a copy of the License at
 8 | #
 9 | #     http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | 
17 | import sys
18 | import json
19 | from robot import utils
20 | 
21 | 
22 | def write_format_file(fields, format_file_str):
23 |     """
24 |     write schema file for solr
25 |     """
26 |     solr_format = []
27 |     for f in fields:
28 |         if f == "id":
29 |             continue
30 |         if f == "question":
31 |             f_type = "text_multi_lang"
32 |             f_index = True
33 |         else:
34 |             f_type = "string"
35 |             f_index = False
36 |         f_str = {"indexed": f_index, "name": f, "stored": True, "type": f_type}
37 |         solr_format.append(f_str)
38 |     ff = open(format_file_str, "w")
39 |     ff.write(json.dumps(solr_format, indent=4) + "\n")
40 |     ff.close()
41 | 
42 | 
43 | def run(faq_file_str, json_file_str):
44 |     """
45 |     convert text file to json file, save schema file
46 |     """
47 |     idx = 0
48 |     header = 0
49 |     field_cnt = 0
50 |     auto_id = False
51 |     faq_file = open(faq_file_str, "r")
52 |     for line in faq_file:
53 |         arr = line.strip().split("\t")
54 |         if header == 0:
55 |             header = 1
56 |             field_names = arr
57 |             field_cnt = len(field_names)
58 |             if "question" not in field_names or "answer" not in field_names:
59 |                 print("need question and answer")
60 |                 sys.exit(6)
61 |             if "id" not in field_names:
62 |                 auto_id = True
63 |             # write_format_file(field_names, format_file_str)
64 |             json_file = open(json_file_str, "w")
65 |             continue
66 |         if len(arr) != field_cnt:
67 |             print(f"line {idx+2} error")
68 |             continue
69 |         idx += 1
70 |         data = dict([field_names[i], arr[i]] for i in range(field_cnt))
71 |         if auto_id:
72 |             data["id"] = str(idx)
73 |         json_file.write(json.dumps(data, ensure_ascii=False))
74 |         json_file.write("\n")
75 |     json_file.close()
76 |     faq_file.close()
77 | 
78 | 
79 | def convert(faq_str, json_file_str):
80 |     faq_file_str = utils.write_temp_file(faq_str, ".csv", mode="w")
81 |     run(faq_file_str, json_file_str)
82 | 
83 | 
84 | if __name__ == "__main__":
85 |     if len(sys.argv) < 3:
86 |         print("usage: python " + sys.argv[0] + " faq_file(input) json_file(output)")
87 |         sys.exit(2)
88 |     run(sys.argv[1], sys.argv[2])
89 | 


--------------------------------------------------------------------------------
/tools/solr_api.py:
--------------------------------------------------------------------------------
 1 | # coding=utf-8
 2 | 
 3 | # Copyright (c) 2018 Baidu, Inc. All Rights Reserved.
 4 | #
 5 | # Licensed under the Apache License, Version 2.0 (the "License");
 6 | # you may not use this file except in compliance with the License.
 7 | # You may obtain a copy of the License at
 8 | #
 9 | #     http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | 
17 | import sys
18 | import solr_tools
19 | 
20 | if sys.argv[1] == "add_engine":
21 |     solr_tools.add_engine(
22 |         sys.argv[2],
23 |         sys.argv[3],
24 |         sys.argv[4],
25 |         shard=1,
26 |         replica=1,
27 |         maxshardpernode=5,
28 |         conf="myconf",
29 |     )
30 | elif sys.argv[1] == "delete_engine":
31 |     solr_tools.delete_engine(sys.argv[2], sys.argv[3], sys.argv[4])
32 | elif sys.argv[1] == "upload_doc":
33 |     solr_tools.upload_documents(
34 |         sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5], num_thread=1
35 |     )
36 | elif sys.argv[1] == "clear_doc":
37 |     solr_tools.clear_documents(sys.argv[2], sys.argv[3], sys.argv[4])
38 | 


--------------------------------------------------------------------------------