├── .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 — 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> »</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 | © 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 — 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> »</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 | © 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 — 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> »</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 | © 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 — 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> »</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 | © 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 — 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> »</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 | © 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 — 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> »</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 | © 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 — %(docstitle)s": "%(filename)s — %(docstitle)s", "© <a href=\"%(path)s\">Copyright</a> %(copyright)s.": "© <a href=\"%(path)s\"> \u7248\u6743\u6240\u6709</a> %(copyright)s.", "© Copyright %(copyright)s.": "© \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 — %(docstitle)s": "\u66f4\u6539\u53d1\u751f\u5728\u7248\u672c %(version)s— %(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 – %(key)s": "\u7d22\u5f15 – %(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 — 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> »</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 | © 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 — 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> »</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 | © 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 — 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> »</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 | © 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> 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=["­",'<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">×</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> © 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">×</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 | --------------------------------------------------------------------------------