[
  {
    "path": ".dockerignore",
    "content": "README.md\nREADME-en.md\nCONTRIBUTING.md\n"
  },
  {
    "path": ".github/hypertrons.json",
    "content": "{\n  \"label_setup\": {\n    \"version\": 1,\n    \"labels\": [\n      {\n        \"__merge__\": true\n      },\n      {\n        \"name\": \"pull/approved\",\n        \"description\": \"If a pull is approved, it will be automatically merged\",\n        \"color\": \"008672\"\n      }\n    ]\n  },\n  \"role\": {\n    \"version\": 1,\n    \"roles\": [\n      {\n        \"name\": \"replier\",\n        \"description\": \"Replier is responsible for reply issues in time\",\n        \"users\": [\n          \"LiuChangFreeman\",\n          \"JamesBonddu\"\n        ],\n        \"commands\": []\n      },\n      {\n        \"name\": \"approver\",\n        \"description\": \"After approvers' approve, pulls should be merged automatically\",\n        \"users\": [\n          \"LiuChangFreeman\",\n          \"JamesBonddu\"\n        ],\n        \"commands\": [\n          \"/approve\"\n        ]\n      },\n      {\n        \"name\": \"author\",\n        \"description\": \"Author of the issue or pull\",\n        \"users\": [],\n        \"commands\": []\n      },\n      {\n        \"name\": \"notauthor\",\n        \"description\": \"Not author of the issue or pull\",\n        \"users\": [],\n        \"commands\": [\n          \"/approve\"\n        ]\n      },\n      {\n        \"name\": \"anyone\",\n        \"description\": \"Anyone\",\n        \"users\": [],\n        \"commands\": [\n          \"/self-assign\"\n        ]\n      }\n    ]\n  },\n  \"command\": {\n    \"version\": 1,\n    \"commands\": [\n      {\n        \"name\": \"/approve\",\n        \"scopes\": [\n          \"review\",\n          \"review_comment\",\n          \"pull_comment\"\n        ]\n      }\n    ]\n  },\n  \"approve\": {\n    \"version\": 1\n  },\n  \"auto_merge\": {\n    \"version\": 1,\n    \"sched\": \"0 */5 * * * *\"\n  },\n  \"issue_reminder\": {\n    \"version\": 1\n  },\n  \"auto_label\": {\n    \"version\": 1\n  },\n  \"self_assign\": {\n    \"version\": 1\n  },\n  \"weekly_report\": {\n    \"version\": 1,\n    \"generateTime\": \"0 0 12 * * 1\"\n  }\n}\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "### Purpose | 本PR解决的问题\n<!-- Please include the GitHub issue this fixes or resolves, if applicable, please also explain any extra purpose of this PR  -->\n<!-- 请在下方附上本PR解决或实现的Issue编号, 例如 `#1`. 此外如果有, 请尽可能阐述本PR除issue所描述之外的目的 -->\n\n- Closes #\n\n### Changes | 本PR的更改\n<!-- Please list out what major changes were made in this PR to address the issue: -->\n<!-- 请尽可能详细的列出本PR的主要更改 -->\n\n- No changes.\n"
  },
  {
    "path": ".github/workflows/pythonapp.yml",
    "content": "name: Tests on Pull Requests and Master\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    steps:\n    - name: Checkout repo\n      uses: actions/checkout@v2\n\n    - name: Set up Python 3.6\n      uses: actions/setup-python@v1\n      with:\n        python-version: 3.6\n\n    - name: Install dependencies\n      run: |\n        python -m pip install --upgrade pip\n        pip install -r requirements.txt\n\n    - name: Lint with flake8\n      run: |\n        pip install flake8\n        # stop the build if there are Python syntax errors or undefined names\n        flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics\n        # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide\n        flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics\n\n    - name: Test with pytest\n      run: |\n        pip install pytest\n        pytest -v src/tests\n"
  },
  {
    "path": ".gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n*.pyc\n__pycache__/\n.vscode/\n.idea/\n.venv/\n.env\n*.swp\nauth/\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"wuhan2020\"]\n\tpath = wuhan2020\n\turl = git@github.com:wuhan2020/wuhan2020.git\n"
  },
  {
    "path": ".python-version",
    "content": "3.6.10\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing Guide\n\n## Structure\n\n![Tech Arch Diagram](https://www.lucidchart.com/publicSegments/view/6ab27659-257a-44ce-a478-46dad3328b9c/image.png)\n\nAs the above Tech Arch diagram shows (dot-line entities mean they are not there yet), this project is purely data-driven and the core layout looks like the following:\n\n```\nsrc\n├── __init__.py\n├── api/\n├── core/\n├── main.py\n├── swagger/\n├── tests/\n└── utils/\n```\n\n`main.py` is the entry point of the services and it helps:\n- glue all sub API YML files together to an aggregated YML\n- send the YML to connection which renders the Swagger UI and applies the API resolvers.\n- load required service-level connfigurations (such as debug, logging, path to the data sources, etc.).\n\n### To add new or edit on existing API endpoint(s)\n\nIn general you need to edit the `src/swagger/api.yml` and probably its dependencies (such as `donation.yml`). **Be aware that any changes to the YML files can change the data model and breaks the system and the API consumers.**\n\nIf you are using a local Python3.6 environment, setting `debug=True` in `main.py` will help you see the changes you made in the Swagger UI in real time. \n\nBe aware that the `operationId` field in the YML files works as automatic routers that map your endpoint to your Python views functions. To make the endpoints functional, you also have to add/edit the functions in `src/api`. The results of the functions need to be consistent with the data model defined in the API YML file(s).\n\n## Development\n\n![DevOps Pipeline](https://www.lucidchart.com/publicSegments/view/b853bf49-31fa-46ba-b732-2eb9de8a2cf8/image.png)\n\nThe above diagram shows how to work on this repo:\n\n### Development Process\n\nThe development process of this project requires every contributor to fork the repo and only make PRs from the fork to `master` branch. \n\n#### Setup upstream\n\nFrom within your fork, use:\n```\ngit remote add upstream git@github.com:wuhan2020/api-server.git\n```\nto setup this repo as the `upstream`.\n\n#### Keep up-to-date with the upstream\n\nEverytime before you want to make new changes to the repo, use:\n```\ngit fetch upstream\ngit rebase upstream/master\n```\nto update your fork with latest changes that have merged to `upstream`'s `master` branch.\n\n#### Address comments\nOnce you have finished committing and pushing your changes to your remote fork, please create a PR from your remote repo following the PR template. One of the maintainers of the repo will review and merge your PR. Please note PR that fails the tests cannot be reviewed or merged.\n\n## Deployment\n\nThe current deployment is under construction and subjects to change. New documentation is coming soon...\n"
  },
  {
    "path": "Dockerfile",
    "content": "# Align with the CI/CD YML\n# We cannot use alpine since\n# we need to call bash in entrypoint\nFROM python:3.6\n\n# Setup workdir\nWORKDIR /api-server\n\n# Copy src files\nCOPY . .\n\n# Install deps\nRUN pip install -r requirements.txt\n\n# Expose port 5000\nEXPOSE 9000\n\n# Start the server\nENTRYPOINT [ \"bash\", \"bootstrap\"]\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020 援助武汉\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README-cn.md",
    "content": "# API Server\n\n![Python3.6](https://img.shields.io/badge/python-3.6-green.svg?style=flat-square&logo=python&colorB=blue)\n[![Slack Channel](https://img.shields.io/badge/Slack%20Channel-%23api--server-green.svg?style=flat-square&colorB=blue)](https://app.slack.com/client/TT5U1VCPQ/CT3V5CDKJ)\n[![Built with love](https://img.shields.io/badge/BUILT%20WITH-LOVE-orange?style=flat-square)](https://img.shields.io/badge/BUILT%20WITH-LOVE-orange?style=flat-square&logo=love)\n![Build Status](https://github.com/wuhan2020/api-server/workflows/Tests%20on%20Pull%20Requests%20and%20Master/badge.svg?branch=master&event=push)\n\n[English Version](README.md)\n\n这是一个为了抗击在武汉乃至全球爆发的新型冠状病毒而建设的志愿信息收集和分享平台的后端API服务。\n\n此API使用Python 和 Flask 编写，意在轻量化和无状态，通过标准的RESTFul接口传输依靠从其他子项目收集并验证的数据。\n\n## 快速上手\n\n克隆此仓库及子模块仓库：\n```\ngit clone https://github.com/wuhan2020/api-server\ncd api-server\ngit clone https://github.com/wuhan2020/wuhan2020\n```\n\n### 在本地 Docker 容器运行（推荐）\n\n首先，你需要安装[Docker客户端](https://www.docker.com/products/docker-desktop).\n\n#### 构建 Docker 镜像 \n\n在克隆的本仓库根目录下运行:\n```\ndocker build -t api-server:default .\n```\n* 注意：这一步耗时取决于所在国家或地区\n\n#### 运行已构建的 Docker 镜像\n\n运行：\n```\ndocker run --name api-server --publish 9000:9000 api-server:default \n```\n然后在浏览器中打开 `http://localhost:9000`  。(使用 `-d` 来以后台模式（Detached mode）运行 Docker 容器)\n\n在这一步后你应该可以看到记录了可用的端点的Swagger页面。\n\n如果出现 `The container name \"/api-server\" is already in use` 报错可先执行 `docker rm api-server` 删除残留的同名容器.\n\n#### 停止运行中的 Docker 容器\n\n运行：\n```\ndocker stop api-server \n```\n停止运行中的容器.\n\n### 在Python环境中运行\n\n确保你已经安装 **Python3.6**  (一般来讲你应该会使用 [VirtualEnv](https://docs.python.org/3.6/tutorial/venv.html)\n或是 [PyEnv](https://github.com/pyenv/pyenv)). 然后在克隆仓库的根目录运行：\n\n```\npip install -U -r requirements.txt\n```\n\n启动服务器:\n\n```\nbash bootstrap\n```\n在浏览器中打开`http://localhost:9000`，你应该可以看到记录了可用的端点的Swagger页面。.\n\n\n## 开发\n\n待更新...\n\n## 部署\n待更新...\n\n## 贡献\n\n参照[贡献指南](CONTRIBUTING.md)\n\n## 前端issues\n\n请查阅[这里](https://github.com/wuhan2020/front-pages/issues)\n"
  },
  {
    "path": "README.md",
    "content": "# API Server\n\n![Python3.6](https://img.shields.io/badge/python-3.6-green.svg?style=flat-square&logo=python&colorB=blue)\n[![Slack Channel](https://img.shields.io/badge/Slack%20Channel-%23api--server-green.svg?style=flat-square&colorB=blue)](https://app.slack.com/client/TT5U1VCPQ/CT3V5CDKJ)\n[![Built with love](https://img.shields.io/badge/BUILT%20WITH-LOVE-orange?style=flat-square)](https://img.shields.io/badge/BUILT%20WITH-LOVE-orange?style=flat-square&logo=love)\n![Build Status](https://github.com/wuhan2020/api-server/workflows/Tests%20on%20Pull%20Requests%20and%20Master/badge.svg?branch=master&event=push)\n\n[中文文档](README-cn.md)\n\nThis a backend API service of the voluntary information collection and sharing platform to fight against the 2019-nCoV outbreak in Wuhan and the world. \n\nThe API is designed to be thin and stateless. It relies on the data collected and validated by other sub-projects, transform and expose them through standard RESTful APIs. The service is written in Python and Flask.\n\n![Tech Arch Diagram](https://www.lucidchart.com/publicSegments/view/6ab27659-257a-44ce-a478-46dad3328b9c/image.png)\n\n## Get Started\n\nPlease first clone this repository and the sub-module-repo by:\n\n```\ngit clone https://github.com/wuhan2020/api-server\ncd api-server\ngit clone https://github.com/wuhan2020/wuhan2020\n```\n\n### Running locally with Docker (Recommended)\n\n**Pre-requisite: You have to have [Docker client](https://www.docker.com/products/docker-desktop) installed on your machine.**\n\n#### Build the Docker image\n\nRun:\n```\ndocker build -t api-server:default .\n```\nfrom the root directory of the clone of this repo. Note this step could take a long time depends on where you are located in.\n\n#### Run built Docker image\n\nRun:\n```\ndocker run --name api-server --publish 9000:9000 api-server:default \n```\nand then open `http://localhost:9000` in your browser. _(Add `-d` to run the Docker container in detach/background mode)_\n\nYou should see a Swagger page documents the available endpoints now.\n\n_If you ran into error `The container name \"/api-server\" is already in use`, please run `docker rm api-server` to delete previous container which has the same name._\n\n#### Stop running Docker container\n\nRun:\n```\ndocker stop api-server \n```\nto stop the running container.\n\n### Running with your own Python environment\n\nPlease make sure you have **Python3.6** installed, (ideally you should be using a [VirtualEnv](https://docs.python.org/3.6/tutorial/venv.html)\nor something like [PyEnv](https://github.com/pyenv/pyenv)). Then from the root directory of the cloned repo, run:\n\n```\npip install -U -r requirements.txt\n```\n\nand then start the server by:\n\n```\nbash bootstrap\n```\nnow if you open `http://localhost:9000` in your browser, you should see a Swagger page documents the available endpoints.\n\n## Contributing Guide\n\nPlease see [Conntributing Guide](CONTRIBUTING.md) for more information about this project.\n\n## Front-end issues\n\nPlease check [here](https://github.com/wuhan2020/front-pages/issues)\n"
  },
  {
    "path": "bootstrap",
    "content": "#!/bin/bash\npython3 -m \"src.main\"\n"
  },
  {
    "path": "config/dev.py",
    "content": ""
  },
  {
    "path": "config/product.py",
    "content": ""
  },
  {
    "path": "config/settings.py",
    "content": "import os, sys\n\nDEBUG_FLAG = True\n\n\ndef get_cache_path():\n    path_home = './'\n    if DEBUG_FLAG:\n        path_home = os.path.join(path_home, 'test/data/')\n    else:\n        path_home = os.path.join(path_home, 'wuhan2020/data/')\n    # wuhan2020文件夹为https://github.com/wuhan2020/wuhan2020项目文件的本地clone\n    # 阿里云serverless使用挂载nas远程目录来存放缓存文件；在本机调试时，缓存文件夹将存放在项目根目录\n    if not os.path.exists(path_home):\n        os.mkdirs(path_home)\n    return path_home\n\n\nclass Config(object):\n    DEBUG = DEBUG_FLAG\n    # 使用aliyun默认端口9000\n    ENV = {\n        \"FC_SERVER_PORT\": 9000,\n    }\n\n\nclass CacheCfg(Config):\n    CACHE_DIR = get_cache_path()\n    # csv\n    CSV_CACHE = CACHE_DIR + 'csv/'\n    HOSPITAL_PATH = os.path.join(CSV_CACHE, \"HOSPITAL.csv\")\n    HOTEL_PATH = os.path.join(CSV_CACHE, \"HOTEL.csv\")\n    LOGISITICAL_PATH = os.path.join(CSV_CACHE, \"LOGISTICAL.csv\")\n    NEWS_PATH = os.path.join(CSV_CACHE, \"NEWS.csv\")\n    DONATION_PATH = os.path.join(CSV_CACHE, \"DONATION.csv\")\n    FACTORY_PATH = os.path.join(CSV_CACHE, \"FACTORY.csv\")\n    CLINIC_PATH = os.path.join(CSV_CACHE, \"CLINIC.csv\")\n    # json\n    JSON_CACHE = CACHE_DIR + 'json/'\n    JSON_HOSPITAL_PATH = os.path.join(JSON_CACHE, \"HOSPITAL.json\")\n    JSON_HOTEL_PATH = os.path.join(JSON_CACHE, \"HOTEL.json\")\n    JSON_LOGISITICAL_PATH = os.path.join(JSON_CACHE, \"LOGISTICAL.json\")\n    JSON_NEWS_PATH = os.path.join(JSON_CACHE, \"NEWS.json\")\n    JSON_DONATION_PATH = os.path.join(JSON_CACHE, \"DONATION.json\")\n    JSON_FACTORY_PATH = os.path.join(JSON_CACHE, \"FACTORY.json\")\n    JSON_CLINIC_PATH = os.path.join(JSON_CACHE, \"CLINIC.json\")\n"
  },
  {
    "path": "const.py",
    "content": "\"\"\"\nSUB HEADERS\nTODO: change to en\n\"\"\"\nfactory_medical_supplies = [\n    # 口罩\n    ('普通医用口罩', 'YY/T 0969-2013'),\n    ('医用外科口罩', 'YY 0469-2010'),\n    ('医用防护口罩 | N95口罩', 'GB 19083-2010, 建议3M 1860/1870/9123,防飞沫血液体液款'),\n    # 面罩\n    ('防冲击眼罩/护目镜/防护眼镜', 'GB 19083-2010, 建议3M 1860/1870/9123,防飞沫血液体液款'),\n    ('防护面罩', 'GB 19083-2010, 建议3M 1860/1870/9123,防飞沫血液体液款'),\n    ('防护帽/医用帽/圆帽', 'GB 19083-2010, 建议3M 1860/1870/9123,防飞沫血液体液款'),\n    # 衣物\n    ('隔离衣', ''),\n    ('防护服', 'GB 19082-2003'),\n    ('手术衣', ''),\n    # 手套\n    ('乳胶手套', '灭菌，GB 10213-2006'),\n    # 鞋\n    ('长筒胶鞋/防污染靴', ),\n    ('防污染鞋套', ),\n    ('防污染靴套', ),\n    # 消毒耗材\n    ('84消毒液', ),\n    ('过氧乙酸', ),\n    ('75%酒精', ),\n    ('手部皮肤消毒液', ),\n    ('活力碘', ),\n    # 其它耗材\n    ('床罩', ),\n    ('医用面罩式雾化器', ),\n    ('测体温设备', ),\n    ('空气消毒设备', ),\n    ('医用紫外线消毒车', ),\n]\n\n\"\"\"\nCSV HEADERS\n\"\"\"\nDONATION_HEADERS = [\n    'donate_sorce',\n    'donate_way',\n    'donate_link',\n    'donate_account_info',\n    'donate_cur_status',\n    'donate_audit_status',\n    'donate_audit_person',\n]\nFACTORY_HEADERS = [\n    'factory_prov',\n    'factory_name',\n    factory_medical_supplies,\n    'factory_qualification',\n    'factory_addr',\n    'factory_contact',\n    'factory_note',\n    'factory_link',\n    'factory_audit_status',\n    'factory_reviewer',\n]\nCLINIC_HEADERS = [\n    'clinic_unit',\n    'clinic_contact',\n    'clinic_note'\n]\nHOTEL_HEADERS = [\n    'hotel_name',\n    'hotel_prov',\n    'hotel_addr',\n    'hotel_room_num',\n    'hotel_acceptable_num',\n    'hotel_supplier',\n    'hotel_concat_person',\n    'hotel_concat_phone',\n    'hotel_note',\n    'hotel_link',\n    'hotel_audit_status',\n    'hotel_audit_person',\n]\nLOGISTICS_HEADERS = [\n    'logistics_name',\n    'logistics_area',\n    'logistics_power',\n    'logistics_link',\n    'logistics_contact'\n]\nNEWS_HEADERS = [\n    'news_title',\n    'news_summary',\n    'news_time',\n    'news_link'\n]\nHOSPITAL_HEADERS = [\n    'hospital_prov',\n    'hospital_name',\n    factory_medical_supplies,\n    'hospital_link',\n    'hospital_addr',\n    'hospital_contact',\n    'hospital_note',\n    'hospital_audit_status',\n    'hospital_audit_person',\n]\n"
  },
  {
    "path": "requirements.txt",
    "content": "Flask==1.1.1\nPyYAML==5.3\nflask-swagger==0.2.14\nxmltodict==0.12.0\nFlask-HTTPAuth==3.3.0\nconnexion[swagger-ui]==2.6.0\nprance==0.18.1\n"
  },
  {
    "path": "src/__init__.py",
    "content": ""
  },
  {
    "path": "src/api/__init__.py",
    "content": ""
  },
  {
    "path": "src/api/accommodations.py",
    "content": "def get_all():\n    \"\"\"List all available accomodations.\"\"\"\n    return {}\n\n\ndef get_by_name():\n    \"\"\"Search for accomodations by name.\"\"\"\n"
  },
  {
    "path": "src/api/hospitals.py",
    "content": "def get_all():\n    \"\"\"List all available hospitals.\"\"\"\n    return {}\n\n\ndef add():\n    \"\"\"Add new hospitals.\"\"\"\n    return {}\n"
  },
  {
    "path": "src/core/__init__.py",
    "content": ""
  },
  {
    "path": "src/main.py",
    "content": "import argparse\nimport flask\nfrom flask import Flask\nfrom flask import Response as ResponseBase\nimport connexion\nfrom swagger_ui_bundle import swagger_ui_3_path\nimport os\nfrom connexion.resolver import RestyResolver\nimport prance\nfrom pathlib import Path\nfrom typing import Dict, Any\n\n\nparser = argparse.ArgumentParser()\nparser.add_argument('--host', default='0.0.0.0')\nparser.add_argument('--port', type=int, default=9000)\nargs, _ = parser.parse_known_args()\n\n\ndef aggregate_specs(main_file: Path) -> Dict[str, Any]:\n    \"\"\"This function glues all seperate API Spec YML files together.\n\n    This enales we keep a set of small YML files while being able\n    to use something like $ref: 'another.yaml#/components/schemas/Foo'\n    in the YML files.\n    \"\"\"\n    parser = prance.ResolvingParser(str(main_file.absolute()), lazy=True, strict=True)\n    parser.parse()\n    return parser.specification\n\n\n# Use OpenAPI Swagger page, and redirct SwaggerUI to root\noptions = {'swagger_path': swagger_ui_3_path, \"swagger_url\": \"\"}\n\n# Note this app is a wrapper around FlaskAPP, use app.app to access\n# the actual Flask app\napp = connexion.App(__name__, options=options)\napp.add_api(\n    aggregate_specs(Path(__file__).parent / \"swagger/api.yml\"),\n    validate_responses=True,\n    resolver=RestyResolver('src.api'),\n)\n\n\ndef handler(environ, start_response) -> flask.Flask:\n    \"\"\"This function is required by the deployment.\n\n    For more information, check here:\n    https://www.alibabacloud.com/help/doc-detail/74756.htm?spm=a2c63.l28256.a3.18.a2543c943bYfKr\n    \"\"\"\n    # do something here\n    return app(environ, start_response)\n\n\nif __name__ == \"__main__\":\n    app.run(host=args.host, port=os.environ.get(\"FC_SERVER_PORT\", args.port), debug=False)\n"
  },
  {
    "path": "src/swagger/accommodations.yml",
    "content": "paths:\n  /accommodation/all:\n    get:\n      tags:\n        - Wuhan2020 Data\n      summary: Search for all available accommodations\n      operationId: src.api.accommodations.get_all\n      description: |\n        By passing in the appropriate options, \n        you can get all of the available accommodations\n        or query for specific accommodations in the system\n      parameters:\n        - in: query\n          name: skip\n          description: number of records to skip for pagination\n          schema:\n            type: integer\n            format: int32\n            minimum: 0\n            default: 0\n        - in: query\n          name: limit\n          description: maximum number of records to return\n          schema:\n            type: integer\n            format: int32\n            minimum: 0\n            maximum: 50\n            default: 50\n      responses:\n        \"200\":\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: \"#/components/schemas/AccommodationItem\"\n        \"400\":\n          $ref: \"errors.yml#/components/BadRequest\"\n        \"500\":\n          $ref: \"errors.yml#/components/InternalServerError\"\n        # Definition of all other error statuses\n        default:\n          description: Unexpected error\n          content:\n            application/json:\n              schema:\n                $ref: \"errors.yml#/components/schemas/Error\"\ncomponents:\n  schemas:\n    AccommodationItem:\n      type: object\n      required:\n        - id\n        - name\n        - address\n        - volume\n        - supportType\n        - contact\n        - validation\n      properties:\n        id:\n          type: string\n          format: uuid\n          example: d290f1ee-6c54-4b01-90e6-d701748f0851\n        name:\n          type: string\n          example: 第一大酒店\n        address:\n          type: string\n          example: 湖北省武汉市靖江大街12号 第一大酒店\n        supportType:\n          type: string\n          enum:\n            [\n              \"医护人员\",\n              \"运输司机\",\n              \"需隔离观察人员\",\n              \"支援人员\",\n              \"外出滞留人员\",\n            ]\n        contact:\n          $ref: \"validations.yaml#/components/schemas/Contact\"\n        validation:\n          $ref: \"validations.yaml#/components/schemas/ValidationItem\"\n        volume:\n          type: object\n          required:\n            - totalPeople\n          properties:\n            maxCapacity:\n              type: integer\n              format: int32\n              example: 55\n              description: 最多可接纳55人\n            rooms:\n              type: array\n              items:\n                type: object\n                required:\n                  - number\n                  - room\n                properties:\n                  number:\n                    type: integer\n                    format: int32\n                    example: 5\n                    description: 5间\n                  room:\n                    $ref: \"#/components/schemas/AccomodationRoom\"\n        releaseDate:\n          type: string\n          format: date-time\n          example: \"2020-01-01T09:12:33.001Z\"\n        availableState:\n          oneOf:\n            - type: boolean\n              default: true\n            - $ref: \"validations.yaml#/components/schemas/SuspendItem\"\n    AccomodationRoom:\n      type: object\n    required:\n      - capacity\n    properties:\n      capacity:\n        type: integer\n        format: int32\n        example: 2\n        description: 做多可接纳2个人\n      space:\n        type: number\n        format: float\n        example: 5.2\n        description: 5.2 平方米\n      roomtype:\n        type: string\n        enum: [\"单人间\", \"双人间\", \"多人间\", \"标准间\", \"套房\", \"豪华套房\", \"总统套房\", \"钟点房\", \"其他\"]\n"
  },
  {
    "path": "src/swagger/api.yml",
    "content": "openapi: 3.0.2\ninfo:\n  title: Wuhan2020 API service\n  description: This is the API service of the Wuhan2020 project, which aims at collecting all useful information to help people fight against the 2019-nCoV outbreak, check the developer website for more info\n  version: 0.1.0\n  contact:\n    name: \"Github Repo\"\n    url: https://github.com/wuhan2020/api-server\n\n# Let's version the APIs a bit later\n# servers:\n#   - url: /api/v1\n\ntags:\n  - name: Wuhan2020 Data\n    description: Get data that's collected and validated by Wuhan2020 volunteers\n\n# Refer to https://swagger.io/docs/specification/using-ref/ for Escape Characters e.g. ~1\npaths:\n  /accommodation/all:\n    $ref: \"accommodations.yml#/paths/~1accommodation~1all\"\n  /hospital/all:\n    $ref: \"hospitals.yml#/paths/~1hospital~1all\"\ncomponents:\n  schemas:\n    AccommodationItem:\n      $ref: \"accommodations.yml#/components/schemas/AccommodationItem\"\n    HospitalItem:\n      $ref: \"hospitals.yml#/components/schemas/HospitalItem\"\n"
  },
  {
    "path": "src/swagger/archived/accomodation.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  description: This API provides Hotel/motel/ Accomodation list\n  version: 0.1.0\n  title: Accomodation List API\n  contact:\n    email: wuhan2020@your-company.com\n  license:\n    name: Apache 2.0\n    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'\ntags:\n  - name: contributors\n    description: Secured write permission calls\n  - name: developers\n    description: Operations available to regular developers\npaths:\n  /acomodations:\n    get:\n      tags:\n        - developers\n      summary: searches accomodations\n      operationId: searchAccomodations\n      description: |\n        By passing in the appropriate options, you can search for\n        available accomodations in the system\n      parameters:\n        - in: query\n          name: searchString\n          description: pass an optional search string for looking up accomodations\n          required: false\n          schema:\n            type: string\n        - in: query\n          name: skip\n          description: number of records to skip for pagination\n          schema:\n            type: integer\n            format: int32\n            minimum: 0\n        - in: query\n          name: limit\n          description: maximum number of records to return\n          schema:\n            type: integer\n            format: int32\n            minimum: 0\n            maximum: 50\n      responses:\n        '200':\n          description: search results matching criteria\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#/components/schemas/AccomodationItem'\n        '400':\n          description: bad input parameter\n    post:\n      tags:\n        - contributors\n      summary: adds am accomodation item\n      operationId: addAccomodation\n      description: Adds an item to the system\n      responses:\n        '201':\n          description: item created\n        '400':\n          description: 'invalid input, object invalid'\n        '409':\n          description: an existing item already exists\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/AccomodationItem'\n        description: Accomodation item to add\n    put:\n      tags:\n      - contributors\n      summary: suspend am accomodation item\n      operationId: suspendAccomodation\n      description: suspend an item to the system\n      responses:\n        '201':\n          description: item suspended\n        '400':\n          description: 'invalid input, object invalid'\n        '403':\n          description: 'forbidden'\n        '404':\n          description: 'not found'\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: 'validations.yaml#/components/schemas/SuspendItem'\nservers:\n  - url: 'https://virtserver.swaggerhub.com/wuhan2020/accomodations/0.1.0'\ncomponents:\n  schemas:\n    AccomodationItem:\n      type: object\n      required:\n        - id\n        - name\n        - address\n        - volume\n        - supporttype\n        - contact\n        - validation\n      properties:\n        id:\n          type: string\n          format: uuid\n          example: d290f1ee-6c54-4b01-90e6-d701748f0851\n        name:\n          type: string\n          example: 第一大酒店\n        address:\n          type: string\n          example: 湖北省武汉市靖江大街12号 第一大酒店\n        supporttype:\n          type: string\n          enum: ['医护人员','运输司机','需隔离观察人员','支援人员','外出滞留人员']\n        contact:\n          $ref: 'validations.yaml#/components/schemas/Contact'\n        validation:\n          $ref: 'validations.yaml#/components/schemas/ValidationItem'\n        volume:\n          type: object\n          required:\n            - totalPpl         \n          properties:\n            totalPpl:\n              type: integer\n              format: int32\n              example: 55\n              description: 共可接纳55人\n            rooms:\n              type: array\n              items:\n                type: object\n                required:\n                  - number\n                  - room\n                properties:\n                  number:\n                    type: integer\n                    format: int32\n                    example: 5\n                    description: 5间\n                  room:  \n                    $ref: '#/components/schemas/AccomodationRoom'\n        releaseDate:\n          type: string\n          format: date-time\n          example: '2016-08-29T09:12:33.001Z'\n        availableState:\n          oneOf:\n          - type: boolean\n            default: true\n          - $ref: 'validations.yaml#/components/schemas/SuspendItem'\n    AccomodationRoom:\n      type: object\n      required:\n        - ppl\n      properties:\n        ppl:\n          type: integer\n          format: int32\n          example: 2\n          description: 2个人 \n        space:\n          type: number\n          format: float\n          example: 5.2\n          description: 5.2 平方米\n        roomtype:\n          type: string\n          enum: ['双人间','多人间','标准间','套房','豪华套房','总统套房']"
  },
  {
    "path": "src/swagger/archived/donation.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  description: This API provides Donation list\n  version: 0.2.0\n  title: Donation List API\n  contact:\n    email: wuhan2020@your-company.com\n  license:\n    name: Apache 2.0\n    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'\ntags:\n  - name: contributors\n    description: Secured write permission calls\n  - name: developers\n    description: Operations available to regular developers\npaths:\n  /donation:\n    get:\n      tags:\n        - developers\n      summary: searches donation\n      operationId: searchDonation\n      description: |\n        By passing in the appropriate options, you can search for\n        available inventory in the system\n      parameters:\n        - in: query\n          name: searchString\n          description: pass an optional search string for looking up inventory\n          required: false\n          schema:\n            type: string\n        - in: query\n          name: skip\n          description: number of records to skip for pagination\n          schema:\n            type: integer\n            format: int32\n            minimum: 0\n        - in: query\n          name: limit\n          description: maximum number of records to return\n          schema:\n            type: integer\n            format: int32\n            minimum: 0\n            maximum: 50\n      responses:\n        '200':\n          description: search results matching criteria\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#/components/schemas/DonationItem'\n        '400':\n          description: bad input parameter\n    post:\n      tags:\n        - contributors\n      summary: adds a donation item\n      operationId: addDonation\n      description: Adds an item to the system\n      responses:\n        '201':\n          description: item created\n        '400':\n          description: 'invalid input, object invalid'\n        '409':\n          description: an existing item already exists\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/DonationItem'\n        description: Donation item to add\nservers:\n  - url: 'https://virtserver.swaggerhub.com/wuhan2020/donation/0.2.0'\ncomponents:\n  schemas:\n    DonationItem:\n      type: object\n      required:\n        - id\n        - source\n        - donate_way\n        - offical_link\n        - contact\n        - cur_status\n        - source_link\n        - audit_status\n        - update_time\n      properties:\n        id:\n          type: string\n          format: uuid\n          example: d290f1ee-6c54-4b01-90e6-d701748f0851\n        source:\n          type: string\n          example: 红十字会\n        donate_way:\n          type: string\n          example: 支付宝\n        offical_link:\n          type: string\n          format: uri\n          example: https://mp.weixin.qq.com/s/qGAsMA4hsduP99CaabdQDg\n        contact:\n          type: array\n          items:\n            $ref: '#/components/schemas/ContactItem'\n        cur_status:\n          type: string\n          example: 已捐赠; 筹款中;\n        source_link:\n          type: string\n          format: uri\n          example: https://mp.weixin.qq.com/s/qGAsMA4hsduP99CaabdQDg\n        audit_status:\n          type: string\n          example: 已审计; 审计中;\n        update_time:\n          type: string\n          format: date-time\n          example: '2020-01-23T09:12:33.001Z'\n    ContactItem:\n      type: object\n      required:\n        - name\n        - phone\n      properties:\n        name:\n          type: string\n          example: xxx\n        phone:\n          type: string\n          example: 12315\n"
  },
  {
    "path": "src/swagger/archived/hospitaldemands.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  description: This is Hostpital Demands API\n\n  version: 0.2.0\n\n  title: Hostpital Demands API\n  # put the contact info for your development or API team\n  contact:\n    email: wuhan2020@inrganizing operations\ntags:\n- name: contributors\n  description: Secured write permission calls\n- name: developers\n  description: Operations available to regular developers\n\npaths:\n  /hospitaldemands:\n    get:\n      tags:\n      - developers\n      summary: searches hospital demands\n      operationId: searchHospitalDemands\n      description: |\n        By passing in the appropriate options, you can search for\n        recorded hospital demands in the system\n      parameters:\n        - in: query\n          name: searchString\n          description: pass an optional search string for looking up hospital demands\n          required: false\n          schema:\n            type: string\n        - in: query\n          name: skip\n          description: number of records to skip for pagination\n          schema:\n            type: integer\n            format: int32\n            minimum: 0\n        - in: query\n          name: limit\n          description: maximum number of records to return\n          schema:\n            type: integer\n            format: int32\n            minimum: 0\n            maximum: 50\n      responses:\n        '200':\n          description: search results matching criteria\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#/components/schemas/HospitalDemandItem'\n      \n        '400':\n          description: bad input parameter\n    post:\n      tags:\n      - contributors\n      summary: adds an hospital demands item\n      operationId: addHospitalDemands\n      description: Adds an item to the system\n      responses:\n        '201':\n          description: item created\n        '400':\n          description: 'invalid input, object invalid'\n        '409':\n          description: an existing item already exists\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/HospitalDemandItem'\n        description: Hospital Demands item to add\n    put:\n      tags:\n      - contributors\n      summary: suspend an hospital demands item\n      operationId: suspendHospitalDemands\n      description: suspend an item to the system\n      responses:\n        '201':\n          description: item suspended\n        '400':\n          description: 'invalid input, object invalid'\n        '403':\n          description: 'forbidden'\n        '404':\n          description: 'not found'\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: 'validations.yaml#/components/schemas/SuspendItem'\n        description: Hospital Demands item to suspend 取消医院需求item        \n\nservers:\n  - url: 'https://virtserver.swaggerhub.com/wuhan2020/hospitaldemands/0.2.0'\ncomponents:\n  schemas:\n    HospitalDemandItem:\n      type: object\n      required:\n      - hospitDevelopal      \n      - demands\n      - contact\n      - releaseDate\n      - validation\n      properties:\n        id:\n          type: string\n          format: uuid\n          example: d290f1ee-6c54-4b01-90e6-d701748f0851\n        hospital:\n          $ref: 'hospitals.yaml#/components/schemas/HospitalItem'\n\n        validation:\n          $ref: 'validations.yaml#/components/schemas/ValidationItem'\n        releaseDate:\n          type: string\n          format: date-time\n          example: 2016-08-29T09:12:33.001Z\n        contact:\n          $ref: 'validations.yaml#/components/schemas/Contact'\n        demands:\n          type: array\n          items:\n              type: object\n              required:\n              - supply\n              properties:\n                supply:\n                  $ref: 'supplies.yaml#/components/schemas/SupplyItem'\n                amount:\n                  oneOf:\n                    - type: integer\n                      format: int32\n                      description: 个\n                    - $ref: 'suppliesunits.yaml#/components/schemas/SupplyItemUnit'\n                    - $ref: 'suppliesunits.yaml#/components/schemas/Unit'\n                remark:\n                  type: string\n                  example: 需符合或高于下列国家标准,医用一次性防护服技术要求\n        availableState:\n          oneOf:\n          - type: boolean\n            default: true\n          - $ref: 'validations.yaml#/components/schemas/SuspendItem'\n"
  },
  {
    "path": "src/swagger/archived/supplies.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  description: This API provides Supplies list\n  version: 0.2.0\n  title: Supplies List API\n  contact:\n    email: wuhan2020@your-company.com\n  license:\n    name: Apache 2.0\n    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'\ntags:\n  - name: contributors\n    description: Secured write permission calls\n  - name: developers\n    description: Operations available to regular developers\npaths:\n  /supplies:\n    get:\n      tags:\n        - developers\n      summary: searches supplies\n      operationId: searchSupplies\n      description: |\n        By passing in the appropriate options, you can search for\n        available supplies in the system\n      parameters:\n        - in: query\n          name: searchString\n          description: pass an optional search string for looking up supplies\n          required: false\n          schema:\n            type: string\n        - in: query\n          name: skip\n          description: number of records to skip for pagination\n          schema:\n            type: integer\n            format: int32\n            minimum: 0\n        - in: query\n          name: limit\n          description: maximum number of records to return\n          schema:\n            type: integer\n            format: int32\n            minimum: 0\n            maximum: 50\n      responses:\n        '200':\n          description: search results matching criteria\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#/components/schemas/SupplyItem'\n        '400':\n          description: bad input parameter\n    post:\n      tags:\n        - contributors\n      summary: adds a supply item\n      operationId: addSupply\n      description: Adds an item to the system\n      responses:\n        '201':\n          description: item created\n        '400':\n          description: 'invalid input, object invalid'\n        '409':\n          description: an existing item already exists\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/SupplyItem'\n        description: Supply item to add\nservers:\n  - url: 'https://virtserver.swaggerhub.com/wuhan2020/supplies/0.2.0'\ncomponents:\n  schemas:\n    SupplyItem:\n      type: object\n      required:\n        - id\n        - name\n        - std\n      properties:\n        id:\n          type: string\n          format: uuid\n          example: d290f1ee-6c54-4b01-90e6-d701748f0851\n        name:\n          type: string\n          example: 医用口罩\n        std:\n          type: array\n          items:\n            $ref: '#/components/schemas/Standard'\n        releaseDate:\n          type: string\n          format: date-time\n          example: '2016-08-29T09:12:33.001Z'\n    Standard:\n      type: object\n      required:\n        - name\n      properties:\n        name:\n          type: string\n          example: GB 19083-2010\n        desc:\n          type: string\n          example: 国家标医用标准"
  },
  {
    "path": "src/swagger/archived/suppliesunits.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  description: This API provides Supplies list\n  version: 0.2.0\n  title: Supplies Units List API\n  contact:\n    email: wuhan2020@your-company.com\n  license:\n    name: Apache 2.0\n    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'\ntags:\n  - name: contributors\n    description: Secured write permission calls\n  - name: developers\n    description: Operations available to regular developers\npaths:\n  /suppliesunits:\n    get:\n      tags:\n        - developers\n      summary: searches supplies units\n      operationId: searchSuppliesUnits\n      description: |\n        By passing in the appropriate options, you can search for\n        available supplies units in the system\n      parameters:\n        - in: query\n          name: searchString\n          description: pass an optional search string for looking up inventory\n          required: false\n          schema:\n            type: string\n        - in: query\n          name: skip\n          description: number of records to skip for pagination\n          schema:\n            type: integer\n            format: int32\n            minimum: 0\n        - in: query\n          name: limit\n          description: maximum number of records to return\n          schema:\n            type: integer\n            format: int32\n            minimum: 0\n            maximum: 50\n      responses:\n        '200':\n          description: search results matching criteria\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#/components/schemas/SupplyItemUnit'\n        '400':\n          description: bad input parameter\n    post:\n      tags:\n        - contributors\n      summary: adds a supply item\n      operationId: addSupply\n      description: Adds an item to the system\n      responses:\n        '201':\n          description: item created\n        '400':\n          description: 'invalid input, object invalid'\n        '409':\n          description: an existing item already exists\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/SupplyItemUnit'\n        description: Supply item to add\nservers:\n  - url: 'https://virtserver.swaggerhub.com/wuhan2020/suppliesunits/0.2.0'\ncomponents:\n  schemas:\n    SupplyItemUnit:\n      type: object\n      required:\n        - id\n        - name\n        - unitamount\n        - volume\n      properties:\n        id:\n          type: string\n          format: uuid\n          example: d290f1ee-6c54-4b01-90e6-d701748f0851\n        name:\n          type: string\n          example: 箱\n        unitamount:\n          type: integer\n          format: int32\n          example: 250\n        desc:\n          type: string\n          example: 1箱口罩250个\n        volume: \n          type: object\n          required:\n            - length\n            - height\n            - width\n          properties:\n            length:\n              $ref: '#/components/schemas/Length'\n            height:\n              $ref: '#/components/schemas/Length'\n            width:\n              $ref: '#/components/schemas/Length'\n        weight:\n          $ref: '#/components/schemas/Weight'\n        releaseDate:\n          type: string\n          format: date-time\n          example: '2016-08-29T09:12:33.001Z'\n    Unit:\n      oneOf:\n        - $ref: '#/components/schemas/Length'\n        - $ref: '#/components/schemas/Size'\n        - $ref: '#/components/schemas/Weight'\n        - $ref: '#/components/schemas/Volume'\n    Size:\n      type: object\n      required:\n        - amount\n        - unit\n      properties:\n        amount: \n          type: integer\n          format: int32\n        unit:\n          type: string\n          enum: ['#']\n          description: 号\n    Length:      \n      type: object\n      required:\n        - amount\n        - unit\n      properties:\n        amount: \n          type: number\n          format: float\n        unit:\n          type: string\n          enum: [CM, M]\n          description: 米, 厘米\n    Weight:\n      type: object\n      required:\n        - amount\n        - unit\n      properties:\n        amount: \n          type: number\n          format: float\n        unit:\n          type: string\n          enum: [g, kg, ton]\n          description: 克, 千克, 吨\n    Volume:\n      type: object\n      required:\n        - amount\n        - unit\n      properties:\n        amount: \n          type: number\n          format: float\n        unit:\n          type: string\n          enum: [ml, L]\n          description: 毫升,升"
  },
  {
    "path": "src/swagger/errors.yml",
    "content": "# This YML defines the Error Response\n# for most of the errors\ncomponents:\n  # 500\n  InternalServerError:\n    description: The server cannot process the request for an unknown reason\n    content:\n      application/json:\n        schema:\n          $ref: \"#/components/schemas/Error\"\n  # 400\n  BadRequest:\n    description: The HTTP request that was sent to the server has invalid syntax\n    content:\n      application/json:\n        schema:\n          $ref: \"#/components/schemas/Error\"\n  # 404\n  NotFound:\n    description: The specified resource was not found\n    content:\n      application/json:\n        schema:\n          $ref: \"#/components/schemas/Error\"\n  # 401\n  Unauthorized:\n    description: Unauthorized\n    content:\n      application/json:\n        schema:\n          $ref: \"#/components/schemas/Error\"\n  schemas:\n    Error:\n      type: object\n      properties:\n        code:\n          type: string\n        message:\n          type: string\n          example: \"Error message shows here.\"\n      required:\n        - message\n"
  },
  {
    "path": "src/swagger/hospitals.yml",
    "content": "paths:\n  /hospital/all:\n    get:\n      tags:\n        - Wuhan2020 Data\n      summary: Search for all available hospitals\n      operationId: src.api.hospitals.get_all\n      description: |\n        By passing in the appropriate options, \n        you can get all of the available hospitals\n        or query for specific hospitals in the system\n      parameters:\n        - in: query\n          name: skip\n          description: number of records to skip for pagination\n          schema:\n            type: integer\n            format: int32\n            minimum: 0\n            default: 0\n        - in: query\n          name: limit\n          description: maximum number of records to return\n          schema:\n            type: integer\n            format: int32\n            minimum: 0\n            maximum: 50\n            default: 50\n      responses:\n        \"200\":\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: \"#/components/schemas/HospitalItem\"\n        \"400\":\n          $ref: \"errors.yml#/components/BadRequest\"\n        \"500\":\n          $ref: \"errors.yml#/components/InternalServerError\"\n        # Definition of all other error statuses\n        default:\n          description: Unexpected error\n          content:\n            application/json:\n              schema:\n                $ref: \"errors.yml#/components/schemas/Error\"\n\ncomponents:\n  schemas:\n    HospitalItem:\n      type: object\n      required:\n        - id\n        - name\n        - city\n        - address\n        - releaseDate\n      properties:\n        id:\n          type: string\n          format: uuid\n          example: d290f1ee-6c54-4b01-90e6-d701748f0851\n        name:\n          type: string\n          example: 武汉第一人民医院\n        city:\n          type: string\n          example: 武汉市\n        address:\n          type: string\n          example: 湖北省武汉市东湖路169号 武汉大学中南医院\n        releaseDate:\n          type: string\n          format: date-time\n          example: \"2016-08-29T09:12:33.001Z\"\n"
  },
  {
    "path": "src/swagger/validations.yaml",
    "content": "openapi: 3.0.2\ninfo:\n  description: This API provides Base Validation Item list and validation feature\n  version: 0.1.0\n  title: Validation API\n  contact:\n    email: wuhan2020@your-company.com\n  license:\n    name: Apache 2.0\n    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'\ntags:\n  - name: contributors\n    description: Secured write permission calls\n  - name: reviewers\n    description: Secured write 'reviewState' field permission update calls\n  - name: developers\n    description: Operations available to regular developers\npaths:\n  /validations:\n    get:\n      tags:\n        - developers\n      summary: searches validations\n      operationId: searchValidations\n      description: |\n        By passing in the appropriate options, you can search for\n        existing validations in the system\n      parameters:\n        - in: query\n          name: searchString\n          description: pass an optional search string for looking up validations\n          required: false\n          schema:\n            type: string\n        - in: query\n          name: skip\n          description: number of records to skip for pagination\n          schema:\n            type: integer\n            format: int32\n            minimum: 0\n        - in: query\n          name: limit\n          description: maximum number of records to return\n          schema:\n            type: integer\n            format: int32\n            minimum: 0\n            maximum: 50\n      responses:\n        '200':\n          description: search results matching criteria\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#/components/schemas/ValidationItem'\n        '400':\n          description: bad input parameter\n    post:\n      tags:\n        - contributors\n      summary: adds a accomodation item\n      operationId: addValidation\n      description: Adds an item to the system\n      responses:\n        '201':\n          description: item created\n        '400':\n          description: 'invalid input, object invalid'\n        '409':\n          description: an existing item already exists\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/ValidationItem'\n        description: Validation item to add\n    put:\n      tags:\n        - reviewers\n      summary: adds a accomodation item\n      operationId: updateValidation\n      description: Update an item with 'approved' status the system\n      responses:\n        '201':\n          description: 'item updated'\n        '400':\n          description: 'invalid input, object invalid'\n        '403':\n          description: 'forbidden'\n        '404':\n          description: 'item not found'\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/ValidationItem'\n        description: Validation item to add\nservers:\n  - url: 'https://virtserver.swaggerhub.com/wuhan2020/validations/0.1.0'\ncomponents:\n  schemas:\n    ValidationItem:\n      type: object\n      required:\n        - id\n        - url\n        - name\n        - source\n        - sourcetype\n        - releaseDate\n      properties:\n        id:\n          type: string\n          format: uuid\n          example: d290f1ee-6c54-4b01-90e6-d701748f0851\n        url:\n          type: string\n          format: uri\n          example: https://paper.people.com.cn\n        name:\n          type: string\n          example: 湖北紧急求援\n        source:\n          type: string\n          example: 人民日报海外版\n        sourcetype:\n          type: string\n          enum: ['hospitaldemand','patientreport','logistic','accommodation','supplies','general']\n        releaseDate:\n          type: string\n          format: date-time\n          example: '2016-08-29T09:12:33.001Z'\n        contributor:\n          $ref: '#/components/schemas/Operator'\n        reviewStates:\n          type: array\n          items:\n            $ref: '#/components/schemas/ReviewState'\n    Operator:\n      type: object\n      required:\n        - id\n        - username\n      properties:\n        id:\n          type: string\n          format: uuid\n          example: d290f1ee-6c54-4b01-90e6-d701748f0851        \n        username:\n          type: string\n          example: 我的网名是柱子\n        email:\n          type: string\n          format: email        \n    ReviewState:\n      type: object\n      required:\n        - status\n        - reviewDate\n      properties:\n        status:\n          type: string\n          enum: ['truth','uncertain','false']\n          example: 已验证为真实 truth\n          default: 'uncertain'\n        reviewDate:\n          type: string\n          format: date-time\n          example: '2016-08-29T09:12:33.001Z'\n        reviewer:\n          $ref: '#/components/schemas/Operator'    \n    Contact:\n      type: object\n      required:\n        - name\n        - phone\n      properties:\n        name:\n          type: string\n          example: 王老师,李经理\n        phone:\n          type: array\n          items:\n            type: string\n            example: 21-221111111\n        email:\n          type: string\n          example: example@163.com\n    SuspendItem:\n      type: object\n      required:\n        - id\n        - reason\n        - validation\n        - suspendDate\n      properties:\n        id:\n          type: string\n          format: uuid\n          example: d290f1ee-6c54-4b01-90e6-d701748f0851\n          description: 应取消的项目的id,例如医院需求id        \n        reason:\n          oneOf:\n           - type: string\n             enum: ['已过时','判定不真实','已撤销','已完成','已结束']\n           - type: object\n             properties:\n               desc:\n                 type: string\n                 example: 外界不可抗力\n        validation:\n          $ref: '#/components/schemas/ValidationItem'\n        suspendDate:\n          type: string\n          format: date-time\n          example: '2016-08-29T09:12:33.001Z'"
  },
  {
    "path": "src/tests/__init__.py",
    "content": ""
  },
  {
    "path": "src/tests/data/csv/DONATION.csv",
    "content": "¼ʱرŶ̬ȣһҪ¼ȷϢȻǵĺķ鷳Ϊ˷Ϣ׼ȷԣעϢԴӣȻΪЧд,,,,,,\n,տʽ,ٷ,տ˻,ǰ״̬,״̬,\nƱУѻ,пת,https://mp.weixin.qq.com/s/dXed5MIYgBisrV_pfQmV0w,\"˻\nxx\nУйб山·֧\n˺ţxxxxx\n˻ΪУѻ˻\",,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n,,,,,,\n"
  },
  {
    "path": "src/tests/data/csv/FACTORY.csv",
    "content": "¼ʱرŶ̬ȣһҪ¼ȷϢȻǵĺķ鷳Ϊ˷Ϣ׼ȷԣעϢԴӣȻΪЧд,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,\nʾд,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,\n,,,,,沿,,Ʒ,,,,,Ȳ,,,Ĳ,,,,,Ĳ,,豸,,,֤,̵ַ,ϵʽ,ע,ϢԴ,״̬,\n,,ͨҽÿ,ҽƿ,ҽ÷ | N95,/Ŀ/۾,,ñ/ҽñ/Բñ,,,,齺,ͲЬ/Ⱦѥ,ȾЬ,Ⱦѥ,84Һ,,75%ƾ,ֲƤҺ,,,ҽʽ,豸,豸,ҽ,,,,,,,\n׼/ƼƷ,,YY/T 0969-2013,YY 0469-2010,\"GB 19083-2010, 3M 1860/1870/9123,ĭѪҺҺ\",,,,,GB 19082-2003,,GB 10213-2006,,,,,,,,,,,,ҽеע֤,ҽеע֤,,,,,,,\n,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,\nɶнţ,ĴƼ޹˾,һҽÿ,,,,,,,,,,,,,,,,,,,,,,,,ĴʡɶйҵӶ·39,,,http://finance.sina.com.cn/wm/2020-01-26/doc-iihnzahk6405080.shtml,,Ǿ\n,ҽƷ޹˾,,ҽƷ֣2000ֻ,ҽ÷N95100ֻ,,,,,ҽһԷ10,,,,,,,,,,,,,,,,,й.ɽʡ·153,,ϵˣ꣨,http://finance.sina.com.cn/wm/2020-01-26/doc-iihnzahk6405080.shtml,,Ǿ\nϺ,Ϻ֮ҽҩƼ޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20203400057,Ϻ¿·58826¥1¥107Һ102,,͹״2019-nCoVԼУӫPCR,http://dy.163.com/v2/article/detail/F3GCB07P0530JPJ4.html,,\nϺ,ϺҽƿƼ޹˾,,,,,,,,,,,,,,,,,,,,,,,,е20180202,ϺֶƼ·908Ū18¥3¥,,Լ,http://dy.163.com/v2/article/detail/F3GCB07P0530JPJ4.html,,\nϺ,ϺƼ޹˾,,,,,,,,,,,,,,,,,,,,,,,,,Ϻмζ·137862279,,Լ,http://huiruibio.com/contact.asp,,\n,ȵƼ()޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20163401400,кҵ·36509510,,ʵʱӫⶨPCR,https://baijiahao.baidu.com/s?id=1656405518294494200&wfr=spider&for=pc,,\nʡɳ,ʥƼ޹˾,,,,,,,,,,,,,,,,,,,,,,,,泤е20150021,ɳ¼ҵ´·680,,Լ,https://baijiahao.baidu.com/s?id=1656405518294494200&wfr=spider&for=pc,,\nʡ̩,˶Ƽ޹˾,,,,,,,,,,,,,,,,,,,,,,,,̩е20150182,ʡ̩п︻Ұ,,Լ,https://baijiahao.baidu.com/s?id=1656405518294494200&wfr=spider&for=pc,,\nϺ,ϺŵƼ޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20203400058,Ϻ·466¥,,͹״2019-nCoVԼУӫPCR,https://baijiahao.baidu.com/s?id=1656405518294494200&wfr=spider&for=pc,,\n人,Ƽ人޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20203400060,人ж¼´666人ҵĿBCDз¥B2¥B1һ¥,,͹״2019-nCoVԼУӫPCR,https://baijiahao.baidu.com/s?id=1656405518294494200&wfr=spider&for=pc,,\n,ݰ˼ҽѧƼ޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20153400667,·320һ,,ʵʱӫⶨPCR,,,\nʡ,¡Ƽ޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20153400710,оü·389,,ʵʱӫⶨPCR,,,\n,̩ѧй޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20183401609,ͬ·2041101201301Ԫ2045101201501Ԫ,,ʵʱӫⶨPCR,,,\n,ݰԴ޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20183400126,ݸƼǽ·81¥41815¥103220311,,ʵʱӫⶨPCR,,,\n,ɽѧﰲɷ޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20183401526,и¼ҵɽ·19,,ʵʱӫⶨPCR,,,\nʡկ,ͬƼ޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20183400129,ʡկִҵ԰ͩҵ԰A7¥1¥2¥,,ʵʱӫⶨPCR,,,\n,＼޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20173401410,ݹҵ԰Ǻ218׿Ƽ԰C7¥101201,,ʵʱӫⶨPCR,,,\n,ŵ＼޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20153400948,бü·192405407408,,ʵʱӫⶨPCR,,,\n,ݵϰ＼޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20193220321,㽭ʡຼǰֵ·115㡢1¥4423,,ʵʱӫⶨPCR,,,\n,ݲտƼ޹˾,,,,,,,,,,,,,,,,,,,,,,,,еע׼20193220680,и¼ҵ·1192,,ʵʱӫⶨPCR,,,\n"
  },
  {
    "path": "src/tests/data/csv/HOSPITAL.csv",
    "content": "ҪֱдûҪֱ1ûдκϢ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,\n,,,,,沿,,Ʒ,,,,,Ȳ,,,Ĳ,,,,,Ĳ,,豸,,,ٷ,ҽԺַ,ϵʽ,ע,״̬,,,\n,,ͨҽÿ,ҽƿ,ҽ÷ | N95,/Ŀ/۾,,ñ/ҽñ/Բñ,,,,齺,ͲЬ/Ⱦѥ,ȾЬ,Ⱦѥ,84Һ,,75%ƾ,ֲƤҺ,,,ҽʽ,豸,豸,ҽ,,,,,,,,\n׼/ƼƷ,,YY/T 0969-2013,YY 0469-2010,\"GB 19083-2010, 3M 1860/1870/9123,ĭѪҺҺ\",,,,,GB 19082-2003,,GB 10213-2006,,,,,,,,,,,,ҽеע֤,ҽеע֤,,,,,,,,\n,ҽԺ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,\n,еڶҽԺ,1,1,1,1,1,1,,1,1,,,,,1,,,,,,,,,,https://mp.weixin.qq.com/s/EmDnJVak0MQ0W0N9aRbfHw,ɳ·241,,,,,\"ǵλٷϢ, Ϊ԰, Ӧɿ\",2020.01.27\n,еһҽԺ,1,1,1,1,1,1,,1,1,,,,,1,,,,,,,,,,http://www.jzyy1949.com/user_queryArticleById?article.aid=9726,ɳ·8 еһҽԺе,,,,,\"ǵλٷϢ, Ϊ԰, Ӧɿ\",2020.01.27\n,ҽԺ,1,YY 0469-2011,1,1,1,1,,1,,,,,,,,,,,,,,,,https://mp.weixin.qq.com/s/EmDnJVak0MQ0W0N9aRbfHw,о·60 ҽԺĿ,,,,,\"ǵλٷϢ, Ϊ԰, Ӧɿ\",2020.01.27\n,ؿҽԺ,,,,,,,,,,,,,,,,,,,,,,,,https://mp.weixin.qq.com/s/EmDnJVak0MQ0W0N9aRbfHw,ʡо·6,,,,,\"ǵλٷϢ, Ϊ԰, Ӧɿ\",2020.01.27\n,еҽԺ,1,1,1,1,1,1,,1,1,,,,,1,,,,,,,,,,https://mp.weixin.qq.com/s/EmDnJVak0MQ0W0N9aRbfHw,б·196,,,,,\"ǵλٷϢ, Ϊ԰, Ӧɿ\",2020.01.27\n,кʮֻ,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,http://www.jingzhou.gov.cn/zfwxw/jzyq/202001/t20200125_451837.shtml,غʮֻ/ܻͳһ,,,,,,\n,ҽԺ,1,1,1,1,1,1,,1,1,,,,,1,,,,,,,,,,,нغѨ29,,ݲ޹صʺ;,,,https://weibo.com/u/6989496719?refer_flag=1005055013_&is_all=1,\n,ؿҽԺ,1,1,1,1,1,1,,1,1,,,,,1,,,,,,,,,,,о6,,,,,,\n,иױԺ,1,1,1,1,1,1,,1,1,,,,,1,,,,,,,,,,,ʡо·233,,,,,,\n,мҽԺ,1,1,1,1,1,1,,1,1,,,,,1,,,,,,,,,,,ʡݳ344,,,,,,\n,ҽԺ,,,,,,,,,,,,,,,,,,,,,,,,,½152,,,,,,\n,ҽҽԺ,,,,,,,,,,,,,,,,,,,,,,,,,кִ·㴦,,޹棬ž http://news.jznews.com.cn/system/2020/01/26/011980374.shtml,,,,\n,ҽҽԺ,,,,,,,,,,,,,,,,,,,,,,,,,ʡкȪ·6,,޹棬ž http://news.jznews.com.cn/system/2020/01/26/011980374.shtml,,,,\nʯ,ʯкʮֻ,1,1,1,1,1,1,1,1,1,1,,1,,1,1,1,,,,,,,,,,,ݲ޹صʺ;޹棬ž http://news.jznews.com.cn/system/2020/01/26/011980374.shtml,,,,\n,ҽҽԺ,1,1,1,1,1,1,,1,1,,,,,1,,,,,,,,,,http://www.jzszyyy.com/z/yiyuandongtai/yiyuanxinwen/2020-01-25/1777.html,ʡҽҽԺ 豸ҽԺַн·172,,,,,,\n,йҽԺ,,,,,,,,,,,,,,,,,,,,,,,,,й119,,2020-1-27,,,,\nʯ,ʯҽԺ,1,\"YY 0469-2011\n5000\",2000,3000,1,3000,1000,2000,1,5000,,1000,,1,1,1,,,,,,,,https://mp.weixin.qq.com/s?__biz=MzU2Mzg1MzE5NA==&mid=2247486061&idx=1&sn=b92e03436c18c9ad12a6649a65ead2c3&chksm=fc52a888cb25219e93199201443fc69cd1e736afaa0cba932c12d73925a61c8dcb77a8be3bb7&mpshare=1&scene=1&srcid=&sharer_sharetime=1580280881992&sharer_shareid=5358617ddd2b35735212b40f5eac5301&key=3e858514d2c9d9aa83685104fbf96d3d0d178a06b862aa2a2c3bdecda704ff1ec2d68a213ec57fd19ec19ac168baf5abab36a561d40268957da0f45694a3d7c2de1f69dc6842433bb1ea4ad5caf980a3&ascene=1&uin=MTA5Nzg3NjQ4Mw%3D%3D&devicetype=Windows+10&version=6208006f?=zh_CN&exportkey=AdBnr5Dtk0s1m7%2FPWI3GaKE%3D&pass_ticket=YBuiHNZN%2Fqi2HS0PznCVi0YbW4jODt18BrmF3xRXH8jk2IXOe03FrxoDnP2j%2Bf3Y,ʡʯŶ·㴦,,2020-1-27,,,ٷϢѾ绰ȷ,\n"
  },
  {
    "path": "src/tests/data/csv/HOTEL.csv",
    "content": "¼ʱرŶ̬ȣһҪ¼ȷϢȻǵĺķ鷳Ϊ˷Ϣ׼ȷԣעϢԴӣȻΪЧд,,,,,,,,,,\nƵ,ƵϽ,Ƶַ,?Ƶṩ,ƵɽӴ,ϵ,ϵʽ,ע,ϢԴ,״̬,\nƵƸѨ,Ѩ,·,,,,,,https://m.traveldaily.cn/article/135333?scene=1&clicktime=1580130420&enterid=1580130420&from=singlemessage&isappinstalled=0,,\nбѨվ,Ѩ,188,,,,,,https://mp.weixin.qq.com/s/VuCa0DdBtw8vqgxb6P1xGA,,\nбѨ㳡,,ڴ99,,,,,,,,\nбϵ,,ɽǴ2,,,,,,,,\nбݺ찲㳡,찲,ʹ㳡Ա,,,,,,,,\n"
  },
  {
    "path": "src/tests/data/csv/LOGISTICAL.csv",
    "content": "¼ʱرŶ̬ȣһҪ¼ȷϢȻǵĺķ鷳Ϊ˷Ϣ׼ȷԣעϢԴӣȻΪЧд,,,,,,,,,,,,,,,,,,\n,,ϵʽ,,ע,״̬,,Ԯ,,,,,,,,,,,\n˳Ἧ,人ĳ,95338,https://mp.weixin.qq.com/s/42UEPYlYR1EDCM8JKZQyqw,,,,,,,,,,,,,,,\n,人,950616,https://mp.weixin.qq.com/s/5ZYvBOFSDdh3-AYFU7wzAQ,ܸ˾,,,,,,,,,,,,,,\n°,人,13917258981;18043320078,https://mp.weixin.qq.com/s/xCGmBHEOrgwfFDobjigHKQ,ܸ˾,,,,,,,,,,,,,,\n,人,400-900-5656,https://tech.sina.com.cn/i/2020-01-25/doc-iihnzahk6300507.shtml,,,,,,,,,,,,,,,\nԲͨٵ޹˾,人,95554,http://www.yto.net.cn/about/news/ytonews/detail.html/?id=7c257cc4-1291-4eba-9aeb-10414f389e88,ܸ˾,,,,,,,,,,,,,,\nͨݼ,人,95311,https://www.zto.com/companyIntroduce/newsListDetail.html?id=1267040,ܸ˾,,,,,,,,,,,,,,\nӿ,人,4000565666,https://mp.weixin.qq.com/s/D9orpDHGp2xJT1V8pIbSYw,ܸ˾,,,,,,,,,,,,,,\n˳,人,4008009999,https://weibo.com/2780826007/IrfwsAo3m?type=repost#_rnd1580099824814,,,,人ѧҽԺҽԺвսҽԺɽСɽҽԺ人ܱ,ɽɶϡ人,,,,,,,,,,\nغ,人,15915803827,https://weibo.com/2780826007/IrffCjDCa?from=page_1002062780826007_profile&wvr=6&mod=weibotime&type=comment#_rnd1580114854609,,,,,,,,,,,,,,,\n,人,10103636/appͷ,https://weibo.com/2780826007/IreEZaTrw?from=page_1002062780826007_profile&wvr=6&mod=weibotime&type=comment#_rnd1580114913374,,,,,,,,,,,,,,,\nй,人,11183,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,,,,,,,,,,,,,,,\nϴٵ,人,95546,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ܸ˾,,,,,,,,,,,,,,\n,人,051-56267288ֻ83424,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ܸ˾,,,,,,,,,,,,,,\n,人,95344,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ܸ˾,,,,,,,,,,,,,,\n,人,95315,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,˾󣬽뵱Ż֯ϵ,,,,,,,,,,,,,,\n,人,95006,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ܸ˾,,,,,,,,,,,,,,\n,人,400-866-5566,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ܸ˾Խӣվֻ19906791226 2ִתȷ񣺴13967130612 18601625459,,,,,,,,,,,,,,\nԽ,人,95324/18923876321,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ܸ˾,,,,,,,,,,,,,,\nլ,人,01053265090/ 13501275106,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ܸ˾,,,,,,,,,,,,,,\nػ,,400-808-6666,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ܸ˾,,,,,,,,,,,,,,\n,人,\"  17379175656/\n  18784733363/  18010017622/  18629291855/  18863932588/  13801500174\",https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ܸ˾,,,,,,,,,,,,,,\nҼ׵δ,人,95058,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,˾󣬽뵱Ż֯ϵ,,,,,,,,,,,,,,\nٿ,人,95349,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,˾󣬽뵱Ż֯ϵ,,,,,,,,,,,,,,\n칷,人,\"4008909009ͷʱ125-27Ϊ9:00-18:00,128պΪ8:00-20:00)\",https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ϵ人ؽշϵ칷,,,,,,,,,,,,,,\n,人,⽭֣ 18017713330/? 13916478826򱱳֣? 18911773800ɶ֣? 15208319985,https://weibo.com/ttarticle/p/show?id=2309404464719346925765,ҽƷʿɼ뷢⽭֡򱱳֡ϳɶ֣ڼв⼰ڲѡ,,,,,,,,,,,,,,\n׼ʱ﹩Ӧ,ī硢ձԽϡĴǡ̩ǡӡǡ¼¡ɱӡȡ̨ۡ,׼ʱɫͨߣ400 189 8868 䣺jusda-callcenter@jusdascm.com,https://weibo.com/2780826007/IrrjhFjaE,ݲΪṩɫ֧ͨ,,ӱ,,,,,,,,,,,,\nGOOD,ɼLos Angelesֿ/ŦԼNew Yorkֿ/˰Oregonֿ,\"ϵˣBryan ϵ绰6262976863ɼֿ 17421 East Gale Ave Unit C,City of Industry CA91748 / ŦԼֿ⣺75 Glendale Ave Edison NJ08817 / ˰ݲֿ 7021 NE 79th Court Portland OR97218\",https://mp.weixin.qq.com/s/PB_-X4HxjTKHbdVcIEwksw,עһ1.װ豸ע2. 豸עҪջϢ 3. 豸עڼƷƷ,,ӱ,,,,http://www.goodkuaidi.com/NewsDetail?GID=da62467c-102e-4b8d-b73d-0916c0df7489,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n,,,,,,,,,,,,,,,,,,\n"
  },
  {
    "path": "src/tests/data/test.json",
    "content": "{\"code\":0,\"data\":{},\"msg\":\"success\"}\n"
  },
  {
    "path": "src/tests/data/test.xml",
    "content": "<data>\n    <code>0</code>\n    <msg>success</msg>\n    <data>\n\n    </data>\n\n</data>\n"
  },
  {
    "path": "src/tests/test_nothing.py",
    "content": "def test_nothing():\n    \"\"\"Placeholder for Pytest on Github Actions.\"\"\"\n    assert True\n"
  },
  {
    "path": "src/utils/__init__.py",
    "content": ""
  },
  {
    "path": "tools.py",
    "content": "import os\nimport yaml\nimport xmltodict\nimport json\nimport functools\nimport logging\nfrom flask import abort\nfrom flask_httpauth import HTTPTokenAuth\n\nfrom config.settings import DEBUG_FLAG\n\n# TODO: use .gitignore hide token; i don't know how to use this auth in blueprint\nauth = HTTPTokenAuth(scheme='Bearer')\ntest_token = 'test-safe-wuhan'\nauth_file = os.path.join(os.path.abspath(__file__), 'auth/auth_info.json')\nauth_token = test_token if DEBUG_FLAG else json.load(auth_file)['token']\n\n\n@auth.verify_token\ndef auth_token_wrapper(token):\n    if token == auth_token:\n        return True\n    return False\n\n\ndef csv_helper(fpath, headers):\n    header_st = 2\n    result = []\n    with open(fpath) as f:\n        for line in f.readlines()[2:]:\n            csv_data = line.strip().split(\",\")\n            result.append(dict(zip(headers, csv_data)))\n    return result\n\n\ndef csv_with_medical_supplier(fpath, headers):\n    header_st, spliter = 5, '#'\n    result, total_header = [], []\n    for h in headers:\n        if isinstance(h, list):\n            for sub_h in h:\n                total_header.append(spliter.join(sub_h))\n        else:\n            total_header.append(h)\n    with open(fpath) as f:\n        for line in f.readlines()[header_st:]:\n            csv_data = line.strip().split(\",\")\n            result.append(dict(zip(total_header, csv_data)))\n    return result\n\n\ndef yaml_helper(fpath):\n    result = []\n    with open(fpath, 'r') as f:\n        result = yaml.load(f)\n    return result\n\n\ndef xml_helper(xml_path):\n    with open(xml_path, 'r') as f:\n        xml_str = f.read()\n    json = xmltodict.parse(xml_str)\n    return json\n\n\ndef json_helper(json_path):\n    with open(json_path, 'r', encoding='UTF-8') as f:\n        return json.loads(f.read())\n"
  },
  {
    "path": "utils.py",
    "content": "# -*- coding: utf-8 -*-\nfrom flask import Blueprint, current_app, request\nimport os\nimport json\nimport datetime\nimport platform\nimport csv\nimport os\nimport traceback\nimport yaml\nimport xmltodict\nimport json\n\nfrom const import *\nfrom tools import *\n\ndata = Blueprint('register', __name__)\n\n\n@data.route('/json_test')\ndef json_test():\n    path = os.path.join(\"/root/api-server/\", \"test.json\")\n    return json_helper(path)\n\n\n@data.route('/xml_test')\ndef xml_test():\n    path = os.path.join(\"/root/api-server/\", \"test.xml\")\n    return xml_helper(path)\n\n\n@data.route('/hospital_list')\ndef hospital_list():\n    resp = {\n        'success': False,\n        'data': [],\n        'msg': '',\n    }\n    try:\n        hosptials_data = csv_with_medical_supplier(current_app.config['HOSPITAL_PATH'], HOSPITAL_HEADERS)\n        if 'limit' in request.args or 'skip' in request.args:\n            skip = request.args.get('skip', type=int)\n            limit = request.args.get('limit', type=int)\n            hosptials_data_len = len(hosptials_data)\n            if skip < 0 or limit < 0 or limit > 50:\n                raise Exception('Bad input parameter.')\n            if skip > hosptials_data_len:\n                raise Exception(\"Index out of range.\")\n            if skip + limit > hosptials_data_len:\n                limit = hosptials_data_len - skip\n            resp['data'] = hosptials_data[skip:skip+limit]\n        else:\n            resp['data'] = hosptials_data\n        resp['success'] = True\n    except Exception as e:\n        resp['msg'] = str(e)\n    return json.dumps(resp, ensure_ascii=False),(400 if not resp['success'] else 200)\n\n\n@data.route('/hotel_list')\n@auth.login_required\ndef hotel_list():\n    resp = {\n        'success': False,\n        'data': [],\n        'msg': '',\n    }\n    try:\n        resp_data = csv_helper(current_app.config['HOTEL_PATH'], HOTEL_HEADERS)\n        resp['success'] = True\n        resp['data'] = resp_data\n    except Exception as e:\n        resp['msg'] = str(e)\n    return json.dumps(resp, ensure_ascii=False)\n\n\n@data.route('/logistical_list')\n@auth.login_required\ndef logistical_list():\n    resp = {\n        'success': False,\n        'data': [],\n        'msg': '',\n    }\n    try:\n        resp_data = csv_with_medical_supplier(current_app.config['LOGISITICAL_PATH'], LOGISTICS_HEADERS)\n        resp['success'] = True\n        resp['data'] = resp_data\n    except Exception as e:\n        resp['msg'] = str(e)\n    return json.dumps(resp, ensure_ascii=False)\n\n\n@data.route('/news_list')\n@auth.login_required\ndef news_list():\n    resp = {\n        'success': False,\n        'data': [],\n        'msg': '',\n    }\n    try:\n        resp_data = csv_helper(current_app.config['NEWS_PATH'], NEWS_HEADERS)\n        resp['success'] = True\n        resp['data'] = resp_data\n    except Exception as e:\n        resp['msg'] = str(e)\n    return json.dumps(resp, ensure_ascii=False)\n\n\n@data.route('/donation_list')\n@auth.login_required\ndef donation_list():\n    resp = {\n        'success': False,\n        'data': [],\n        'msg': '',\n    }\n    try:\n        resp_data = csv_helper(current_app.config['DONATION_PATH'], DONATION_HEADERS)\n        resp['success'] = True\n        resp['data'] = resp_data\n    except Exception as e:\n        resp['msg'] = str(e)\n    return json.dumps(resp, ensure_ascii=False)\n\n\n@data.route('/factory_list')\n@auth.login_required\ndef factory_list():\n    resp = {\n        'success': False,\n        'data': [],\n        'msg': '',\n    }\n    try:\n        resp_data = csv_with_medical_supplier(current_app.config['FACTORY_PATH'], FACTORY_HEADERS)\n        resp['success'] = True\n        resp['data'] = resp_data\n    except Exception as e:\n        resp['msg'] = str(e)\n    return json.dumps(resp, ensure_ascii=False)\n\n\n@data.route('/clinic_list')\n@auth.login_required\ndef clinic_list():\n    resp = {\n        'success': False,\n        'data': [],\n        'msg': '',\n    }\n    try:\n        resp_data = csv_helper(current_app.config['CLINIC_PATH'], CLINIC_HEADERS)\n        resp['success'] = True\n        resp['data'] = resp_data\n    except Exception as e:\n        resp['msg'] = str(e)\n    return json.dumps(resp, ensure_ascii=False)\n\n@data.route('/hospital_list_json')\ndef hospital_list_json():\n    resp = {\n        'success': False,\n        'data': [],\n        'msg': '',\n    }\n    try:\n        resp_data= json_helper(current_app.config['JSON_HOSPITAL_PATH'])\n        resp['success'] = True\n        resp['data'] = resp_data\n    except Exception as e:\n        resp['msg'] = str(e)\n    return json.dumps(resp, ensure_ascii=False)\n\n\n\n\n@data.route('/hotel_list_json')\ndef hotel_list_json():\n    resp = {\n        'success': False,\n        'data': [],\n        'msg': '',\n    }\n    try:\n        resp_data = json_helper(current_app.config['JSON_HOTEL_PATH'])\n        resp['success'] = True\n        resp['data'] = resp_data\n    except Exception as e:\n        resp['msg'] = str(e)\n    return json.dumps(resp, ensure_ascii=False)\n\n\n@data.route('/logstics_list_json')\ndef logstics_list_json():\n    resp = {\n        'success': False,\n        'data': [],\n        'msg': '',\n    }\n    try:\n        resp_data = json_helper(current_app.config['JSON_LOGISITICAL_PATH'])\n        resp['success'] = True\n        resp['data'] = resp_data\n    except Exception as e:\n        resp['msg'] = str(e)\n    return json.dumps(resp, ensure_ascii=False)\n\n\n@data.route('/news_list_json')\ndef news_list_json():\n    resp = {\n        'success': False,\n        'data': [],\n        'msg': '',\n    }\n    try:\n        resp_data = json_helper(current_app.config['JSON_NEWS_PATH'])\n        resp['success'] = True\n        resp['data'] = resp_data\n    except Exception as e:\n        resp['msg'] = str(e)\n    return json.dumps(resp, ensure_ascii=False)\n\n\n@data.route('/donation_list_json')\ndef donation_list_json():\n    resp = {\n        'success': False,\n        'data': [],\n        'msg': '',\n    }\n    try:\n        resp_data = json_helper(current_app.config['JSON_DONATION_PATH'])\n        resp['success'] = True\n        resp['data'] = resp_data\n    except Exception as e:\n        resp['msg'] = str(e)\n    return json.dumps(resp, ensure_ascii=False)\n\n\n@data.route('/factory_list_json')\ndef factory_list_json():\n    resp = {\n        'success': False,\n        'data': [],\n        'msg': '',\n    }\n    try:\n        resp_data = json_helper(current_app.config['JSON_FACTORY_PATH'])\n        resp['success'] = True\n        resp['data'] = resp_data\n    except Exception as e:\n        resp['msg'] = str(e)\n    return json.dumps(resp, ensure_ascii=False)\n\n\n@data.route('/clinic_list_json')\ndef clinic_list_json():\n    resp = {\n        'success': False,\n        'data': [],\n        'msg': '',\n    }\n    try:\n        resp_data = json_helper(current_app.config['JSON_CLINIC_PATH'])\n        resp['success'] = True\n        resp['data'] = resp_data\n    except Exception as e:\n        resp['msg'] = str(e)\n    return json.dumps(resp, ensure_ascii=False)\n"
  }
]