diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..0ae6d55a --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,8 @@ +# +# https://help.github.com/articles/about-codeowners/ +# + +/php/ @zhangchunsheng +/python/ @wj-Mcat +/java/ @diaozxin007 +/go/ @dchaofei diff --git a/.github/workflows/csharp.yml b/.github/workflows/csharp.yml new file mode 100644 index 00000000..c90bb4f7 --- /dev/null +++ b/.github/workflows/csharp.yml @@ -0,0 +1,26 @@ +name: "csharp" +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] +jobs: + build-push: + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-dotnet@master + with: + dotnet-version: 3.1.100 + + - name: copy wechaty proto + run: .\copy.ps1 + working-directory: .\csharp\Wechaty.Grpc\buildTool + shell: powershell + + - name: publish on version change + uses: rohith/publish-nuget@v2 + with: + PROJECT_FILE_PATH: .\csharp\Wechaty.Grpc\Wechaty.Grpc.csproj + VERSION_FILE_PATH: .\csharp\Wechaty.Grpc\common.props + NUGET_KEY: ${{ secrets.NUGET_APIKEY }} diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 2404b2b8..19f42cbd 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -30,6 +30,8 @@ jobs: run: | cd go make generate + rm -rf `go env GOPATH`/src/github.com/wechaty/go-grpc/wechaty + ln -s `pwd`/generated/wechaty/ `go env GOPATH`/src/github.com/wechaty/go-grpc/wechaty go build -v generated/wechaty/puppet.pb.go publish: diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml index 5de62b4f..02dccee8 100644 --- a/.github/workflows/maven-publish.yml +++ b/.github/workflows/maven-publish.yml @@ -22,7 +22,7 @@ jobs: settings-path: ${{ github.workspace }} # location for the settings.xml file - name: Build with Maven - run: mvn -B package --file pom.xml + run: mvn -B package --file java/pom.xml - name: Publish to GitHub Packages Apache Maven run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 8e0990d4..db8eb4e7 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -21,4 +21,4 @@ jobs: with: java-version: 1.8 - name: Build with Maven - run: mvn -B package --file pom.xml + run: mvn -B package --file java/pom.xml diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index fb525670..9638cf2e 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -14,20 +14,17 @@ jobs: strategy: matrix: os: [macos-latest, ubuntu-latest] - node-version: [10.x, 11.x, 12.x] + node-version: [10.x, 11.x, 12.x, 14.x, 15] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@master - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + uses: actions/setup-node@master with: node-version: ${{ matrix.node-version }} - - name: Set up Go 1.14 + - name: Set up Go uses: actions/setup-go@master - with: - stable: false - go-version: 1.14 id: go - name: Install Protoc @@ -35,10 +32,16 @@ jobs: with: repo-token: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/cache@master + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package.json') }} + restore-keys: | + ${{ runner.os }}-node- - name: Install Dependencies run: | npm install - npm run install:lint:protoc + npm run install:protoc - name: Generate gRPC Stubs run: npm run generate diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index 7d633923..8e0eec8c 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -7,24 +7,27 @@ jobs: name: Build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@master - name: Use Node.js 12 - uses: actions/setup-node@v1 + uses: actions/setup-node@master with: node-version: 12 - - name: Set up Go 1.14 + - name: Set up Go uses: actions/setup-go@master - with: - stable: false - go-version: 1.14 id: go - name: Install Protoc uses: arduino/setup-protoc@master + - uses: actions/cache@master + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package.json') }} + restore-keys: | + ${{ runner.os }}-node- - name: Install Dependencies run: | npm install - npm run install:lint:protoc + npm run install:protoc - name: Generate gRPC Stubs run: npm run generate @@ -37,13 +40,24 @@ jobs: needs: build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/checkout@master + - uses: actions/setup-node@master with: node-version: 12 + - uses: actions/cache@master + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package.json') }} + restore-keys: | + ${{ runner.os }}-node- + - name: Set up Go + uses: actions/setup-go@master + id: go - name: Install Protoc uses: arduino/setup-protoc@master + - name: Install Protoc 3rd party protos + run: npm run install:protoc - name: Install Dependencies run: npm install @@ -60,13 +74,22 @@ jobs: needs: [build, pack] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/checkout@master + - uses: actions/setup-node@master with: node-version: 12 registry-url: https://registry.npmjs.org/ + - uses: actions/cache@master + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package.json') }} + restore-keys: | + ${{ runner.os }}-node- + - name: Install Protoc uses: arduino/setup-protoc@master + - name: Install Protoc 3rd party protos + run: npm run install:protoc - name: Install Dependencies run: npm install diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml new file mode 100644 index 00000000..aec31ec5 --- /dev/null +++ b/.github/workflows/php.yml @@ -0,0 +1,40 @@ +# For more information see: https://docs.github.com/en/actions/getting-started-with-github-actions +# For more setup-php see: https://github.com/shivammathur/setup-php +# For more setup-php protoc see: https://github.com/shivammathur/setup-php/issues/262 + +name: PHP + +on: [push, pull_request] + +jobs: + run: + name: Run + runs-on: ${{ matrix.operating-system }} + strategy: + fail-fast: false + matrix: + operating-system: [ubuntu-20.04] + php-versions: ['7.4'] + env: + extensions: xml, opcache, xdebug, pcov, grpc-1.30.0, protobuf-3.12.2 + key: cache-v3 + + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Setup PHP with extensions and custom config + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: ${{ env.extensions }} + ini-values: post_max_size=256M, short_open_tag=On, date.timezone=Asia/Shanghai + tools: protoc, grpc_php_plugin + - name: Testing PHP version + run: | + php -v + php -r "if(strpos(phpversion(), '${{ matrix.php-versions }}') === false) {throw new Exception('Wrong PHP version Installed');}" + - name: Test grpc_php_plugin and protoc + run: | + protoc --version + cd php + make generate diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index c165b8aa..a9c1e53a 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -8,7 +8,6 @@ jobs: strategy: matrix: os: [ubuntu-latest] - python-version: [3.7] runs-on: ${{ matrix.os }} steps: @@ -16,13 +15,24 @@ jobs: - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v1 with: - python-version: ${{ matrix.python-version }} + python-version: 3.9 + - uses: actions/cache@master + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('python/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Install Protoc + uses: arduino/setup-protoc@master + - name: Install Protoc 3rd party protos + run: scripts/install-protoc.sh + - name: Install dependencies run: | cd python python -m pip install --upgrade pip - pip install -r requirements.txt - pip install -r requirements-dev.txt + make install - name: Test run: | cd python @@ -37,7 +47,19 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-python@v1 with: - python-version: 3.7 + python-version: 3.9 + - uses: actions/cache@master + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('python/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Install Protoc + uses: arduino/setup-protoc@master + - name: Install Protoc 3rd party protos + run: scripts/install-protoc.sh + - name: Install dependencies run: | cd python @@ -61,12 +83,24 @@ jobs: - name: Set up Python uses: actions/setup-python@v1 with: - python-version: '3.7' + python-version: '3.9' + - uses: actions/cache@master + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('python/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Install Protoc + uses: arduino/setup-protoc@master + - name: Install Protoc 3rd party protos + run: scripts/install-protoc.sh + - name: Install dependencies run: | cd python python -m pip install --upgrade pip - pip install setuptools wheel twine + pip3 install setuptools wheel twine - name: Check Branch id: check-branch @@ -85,7 +119,7 @@ jobs: make install make generate make dist - python setup.py sdist bdist_wheel + python3 setup.py sdist bdist_wheel twine upload --skip-existing dist/* - name: Is Not A Publish Branch diff --git a/.gitignore b/.gitignore index d4d1259b..308fa391 100644 --- a/.gitignore +++ b/.gitignore @@ -75,3 +75,20 @@ t.* .idea target/ + +# csharp +*.nupkg +.vs/ +*.suo +*.user +*.userosscache +*.sln.docstates + +csharp/Wechaty.Grpc/.vs/ +csharp/Wechaty.Grpc/proto +csharp/Wechaty.Grpc/obj/ +csharp/Wechaty.Grpc/bin/ +csharp/Wechaty.Grpc/nupkg/package/ +csharp/Wechaty.Grpc/Properties + +third-party/ diff --git a/.vscode/settings.json b/.vscode/settings.json index 6ad64c06..d2802f65 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -55,7 +55,7 @@ }, "protoc": { "options": [ - "--proto_path=protobuf" + "--proto_path=source_relative" // https://github.com/zxh0/vscode-proto3/issues/31#issuecomment-628162495 ], }, "alignment": { @@ -75,6 +75,14 @@ "javascript", "typescript", ], + "cSpell.words": [ + "PYPI", + "bdist", + "proto", + "sdist", + "setuptools" + ], + "python.linting.pylintEnabled": true, } diff --git a/NOTICE b/NOTICE new file mode 100644 index 00000000..3661b712 --- /dev/null +++ b/NOTICE @@ -0,0 +1,8 @@ +Chatie GRPC Service +Copyright 2016 Huan LI (李卓桓) + +This product includes software developed at +The Chatie Organization (https://github.com/chatie). + +This software contains code derived from the Stackoverflow, +including various modifications by GitHub. diff --git a/README.md b/README.md index e81b0418..db5c9402 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,103 @@ -# GRPC [![NPM](https://github.com/Chatie/grpc/workflows/NPM/badge.svg)](https://github.com/Chatie/grpc/actions?query=workflow%3ANPM) [![PyPI](https://github.com/Chatie/grpc/workflows/PyPI/badge.svg)](https://github.com/Chatie/grpc/actions?query=workflow%3APyPI) [![Go](https://github.com/chatie/grpc/workflows/Go/badge.svg)](https://github.com/chatie/grpc/actions?query=workflow%3AGo) [![Maven](https://github.com/Chatie/grpc/workflows/Maven/badge.svg)](https://github.com/Chatie/grpc/actions?query=workflow%3A%22Maven%22) [![Node.js](https://github.com/Chatie/grpc/workflows/Node.js/badge.svg)](https://github.com/Chatie/grpc/actions?query=workflow%3ANode.js) +# Wechaty GRPC -![chatie grpc](https://chatie.io/grpc/images/grpc.png) +[![Node.js](https://github.com/Chatie/grpc/workflows/Node.js/badge.svg)](https://github.com/Chatie/grpc/actions?query=workflow%3ANode.js) +[![NPM](https://github.com/Chatie/grpc/workflows/NPM/badge.svg)](https://github.com/Chatie/grpc/actions?query=workflow%3ANPM) +[![PyPI](https://github.com/Chatie/grpc/workflows/PyPI/badge.svg)](https://github.com/Chatie/grpc/actions?query=workflow%3APyPI) +[![Maven](https://github.com/Chatie/grpc/workflows/Maven/badge.svg)](https://github.com/Chatie/grpc/actions?query=workflow%3A%22Maven%22) +[![PHP](https://github.com/Chatie/grpc/workflows/PHP/badge.svg)](https://github.com/Chatie/grpc/actions?query=workflow%3APHP) +[![Go](https://github.com/chatie/grpc/workflows/Go/badge.svg)](https://github.com/chatie/grpc/actions?query=workflow%3AGo) -[![NPM Version](https://img.shields.io/npm/v/@chatie/grpc?color=brightgreen&label=NPM)](https://www.npmjs.com/package/@chatie/grpc) +![Wechaty gRPC](docs/images/grpc.png) + +[![NPM Version](https://img.shields.io/npm/v/wechaty-grpc?color=brightgreen&label=NPM)](https://www.npmjs.com/package/wechaty-grpc) [![PyPI Version](https://img.shields.io/pypi/v/chatie-grpc?color=blue&label=PyPI)](https://pypi.org/project/chatie-grpc/) +[![Java Version](https://img.shields.io/maven-central/v/io.github.wechaty/grpc?label=Java)](https://mvnrepository.com/artifact/io.github.wechaty/grpc) +[![PHP Version](https://img.shields.io/packagist/v/wechaty/php-grpc)](https://packagist.org/packages/wechaty/php-grpc) + [![node](https://img.shields.io/node/v/wechaty.svg?maxAge=604800&label=Node.js)](https://nodejs.org/) [![Python 3.7](https://img.shields.io/badge/python-3.7+-blue.svg?label=Python)](https://www.python.org/downloads/release/python-370/) ![Go Version](https://img.shields.io/github/go-mod/go-version/wechaty/go-wechaty) -[![Java Version](https://img.shields.io/maven-central/v/io.github.wechaty/grpc?label=Java)](https://mvnrepository.com/artifact/io.github.wechaty/grpc) -gRPC for Chatie +gRPC for Wechaty Puppet Service -## Usage +## USAGE ### Node.js -[@chatie/grpc@NPM](https://www.npmjs.com/package/@chatie/grpc) +[wechaty-grpc@NPM](https://www.npmjs.com/package/wechaty-grpc) + +Maintainer: + +- [@huan](https://github.com/huan) - Huan LI (李卓桓) ### Python [chatie-grpc@PyPI](https://pypi.org/project/chatie-grpc) +Maintainer: + +- [@wj-Mcat](https://github.com/wj-Mcat) - Jingjing WU (吴京京) + ### Go [github.com/wechaty/go-grpc](https://github.com/wechaty/go-grpc) -## Build +Maintainer: + +- [@dchaofei](https://github.com/dchaofei) - Chaofei DING (丁超飞) + +### Java + +[https://mvnrepository.com/artifact/io.github.wechaty/grpc](https://mvnrepository.com/artifact/io.github.wechaty/grpc) + +Maven: + +```xml + + io.github.wechaty + 0.11.25 + grpc + +``` + +Gradle: + +```groovy +compile 'io.github.wechaty:grpc:0.11.25' +``` + +Maintainer: + +- [@diaozxin007](https://github.com/diaozxin007) - Zhengxin DIAO (刁政欣) + +### PHP + +[github.com/wechaty/php-grpc](https://github.comwechaty/php-grpc) + +Maintainer: + +- [@zhangchunsheng](https://github.com/zhangchunsheng) - Chunsheng ZHANG (张春生) + +### Csharp + +[Wechaty.Grpc @ Nuget](https://www.nuget.org/packages/Wechaty.Grpc) + +Maintainer: + +- [@Darren](https://github.com/jesn) - Darren (郑波) + +## DEVELOPMENT + +### Debug + +- [GUI Client for GRPC Services](https://github.com/uw-labs/bloomrpc) - BloomRPC aim to give the simplest and efficient developer experience for exploring and querying your GRPC services.(Inspired by Postman and GraphQL Playground) +- [A gRPC CLI interface for easy testing against gRPC servers with Node.js REPL](https://github.com/njpatel/grpcc) + + ```sh + grpcc --proto ./service/myservice.proto --address 127.0.0.1:3466 + ``` + +### Build ```shell ./scripts/install-protoc.sh @@ -34,13 +106,13 @@ npm install > -## Generate Stubs +### Generate Stubs ```shell npm run generate ``` -### 1. JS for Protocol Buffer +#### 1. JS for Protocol Buffer ```shell protoc \ @@ -49,7 +121,7 @@ protoc \ > -### 2. JS for gRPC Stubs +#### 2. JS for gRPC Stubs ```shell protoc \ @@ -59,7 +131,7 @@ protoc \ > -### 3. TypeScript Typing Definations for Protocol Buffer & gRPC Stubs +#### 3. TypeScript Typing Definations for Protocol Buffer & gRPC Stubs ```shell protoc \ @@ -69,7 +141,7 @@ protoc \ > -### 4. JS & TS for gRPC Web +#### 4. JS & TS for gRPC Web ```shell protoc \ @@ -79,17 +151,25 @@ protoc \ > -## Development +## OpenAPI -### gRPC CLI Debug +Thanks for the ecosystem of gRPC, we can generate OpenAPI Specification from our gRPC proto definitions automatically. -- [A gRPC CLI interface for easy testing against gRPC servers with Node.js REPL](https://github.com/njpatel/grpcc) +We are using [gRPC to JSON proxy generator following the gRPC HTTP spec](https://github.com/grpc-ecosystem/grpc-gateway) as the OpenAPI Specification generator ([protoc-gen-openapiv2](https://github.com/grpc-ecosystem/grpc-gateway/tree/master/protoc-gen-openapiv2)), and using [Like grpc-gateway, but written in node and dynamic](https://github.com/konsumer/grpc-dynamic-gateway) project to serve a HTTP RESTful API to gRPC proxy. -```sh -grpcc --proto ./service/myservice.proto --address 127.0.0.1:3466 -``` +[![gRPC Gateway](docs/images/grpc-gateway-architecture.svg)](https://github.com/wechaty/openapi) + +> Image credit: [grpc-gateway](https://grpc-ecosystem.github.io/grpc-gateway/) + +Learn more about the RESTful API service for Wechaty from [Wechaty OpenAPI](https://github.com/wechaty/openapi). -## Documentatoin +## gRPC Web + +- [gRPC-Web ReactJS client, Golang Server](https://github.com/longfellowone/grpcwebtest) + +## RESOURCES + +### Documentation - [Protocol Buffers Language Guide (proto3)](https://developers.google.com/protocol-buffers/docs/proto3) - [Google Protocol Buffers Style Guide](https://developers.google.com/protocol-buffers/docs/style) @@ -98,7 +178,7 @@ grpcc --proto ./service/myservice.proto --address 127.0.0.1:3466 - [gRPC environment variables](https://github.com/grpc/grpc/blob/master/doc/environment_variables.md) - [How to Interact With and Debug a gRPC Server](https://medium.com/@EdgePress/how-to-interact-with-and-debug-a-grpc-server-c4bc30ddeb0b) -## Resources +### Links - [探讨gRPC的Node技术生态及实现工具](https://xenojoshua.com/2018/02/grpc-node-ecosystem/) - [gRPC Basics - Node.js](https://grpc.io/docs/tutorials/basic/node.html) @@ -108,28 +188,28 @@ grpcc --proto ./service/myservice.proto --address 127.0.0.1:3466 - [gRPC to JSON proxy generator following the gRPC HTTP spec](https://github.com/grpc-ecosystem/grpc-gateway) - [如何在 Node.js 中更优雅地使用 gRPC:grpc-helper](https://github.com/xizhibei/blog/issues/86) -### Protocol Buffer +#### Protocol Buffer - [Protocol Buffers for JavaScript (& TypeScript)](https://github.com/dcodeIO/protobuf.js) - [Missing value/null support for scalar value types in proto 3](https://github.com/protocolbuffers/protobuf/issues/1606) - [How to Make a Nullable Field in Proto3 for a HTTP Response?](https://stackoverflow.com/questions/57908389/how-to-make-a-nullable-field-in-proto3-for-a-http-response) -### gRPC Web +#### gRPC Web - [gRPC-Web: Moving past REST+JSON towards type-safe Web APIs](https://improbable.io/blog/grpc-web-moving-past-restjson-towards-type-safe-web-apis) - [Library for making gRPC-Web requests intended for TypeScript from either a browser or Node.js.](https://github.com/improbable-eng/grpc-web/tree/master/ts) -### TypeScript Generator +#### TypeScript Generator - [A Typescript definition file generator for gRPC services](https://github.com/anfema/grpc-code-generator) - [gRPC Web TypeScript Code Generation](https://github.com/improbable-eng/grpc-web/blob/master/ts/docs/code-generation.md) - [Protocol Buffers Compiler (protoc) plugin for TypeScript and gRPC-Web.](https://github.com/improbable-eng/ts-protoc-gen) -### Zoo Keeper +#### Zoo Keeper - [ZooKeeper - The King of Coordination](https://www.elastic.co/blog/found-zookeeper-king-of-coordination) -### STUN +#### STUN - [How To TCP NAT Traversal using Node.js and a STUN Server](http://sogilis.com/blog/tcp-nat-traversal-nodejs-stun/) - [chownat, allows two peers behind two separate NATs to directly communicate with each other.](https://samy.pl/chownat/) @@ -143,15 +223,39 @@ grpcc --proto ./service/myservice.proto --address 127.0.0.1:3466 TCP hole punching -### Reverse Engineering +#### Reverse Engineering - [A toolset for reverse engineering and fuzzing Protobuf-based apps](https://github.com/marin-m/pbtk) -### Python Stub +#### Python Stub - [gRPC typing stubs for Python](https://github.com/shabbyrobe/grpc-stubs) -## History +#### CSharp grpc + +- [An introduction to NuGet (microsoft)](https://docs.microsoft.com/en-us/nuget/what-is-nuget) +- [Create a gRPC client and server in ASP.NET Core (microsoft)](https://docs.microsoft.com/en-us/aspnet/core/tutorials/grpc/grpc-start?view=aspnetcore-3.1&tabs=visual-studio) +- [ASP.NET Core 3.0 使用gRPC (晓晨Master)](https://www.cnblogs.com/stulzq/p/11581967.html) + +## HISTORY + +### master + +### v0.20 (Feb 21, 2021) + +1. Rename NPM module name from `@chatie/grpc` to `wechaty-grpc` +1. Add OpenAPI annotations & generators for supporting +1. Code clean. + +### v0.18 (Oct 15, 2020) + +- Add new `MessageFileStream` and `MessageImageStream` to replace the `MessageFile` and `MessageImage` method to avoid blocking nodejs event loop when sending large files ([#88](https://github.com/Chatie/grpc/pull/88)) by [@windmemory](https://github.com/windmemory) +- Add new `MessageSendFileStream` to replace the `MessageSendFile` method to avoid blocking nodejs event loop when sending large files ([#89](https://github.com/Chatie/grpc/pull/89)) by [@windmemory](https://github.com/windmemory) + +### v0.17 (Aug 5, 2020) + +- Add PHPH Support ([#76](https://github.com/Chatie/grpc/pull/76) [#78](https://github.com/Chatie/grpc/pull/78)) by [@zhangchunsheng](https://github.com/zhangchunsheng) +- Publish PHP Module at ### v0.13 (Apr 19, 2020) @@ -177,13 +281,13 @@ TCP hole punching Initial commiit -## Author +## MAINTAINER -[Huan LI](https://github.com/huan) ([李卓桓](http://linkedin.com/in/zixia)) zixia@zixia.net +[Huan LI](https://github.com/huan) ([李卓桓](http://linkedin.com/in/zixia)), Google Developer Expert in Machine Learning (ML GDE), [![Profile of Huan LI (李卓桓) on StackOverflow](https://stackexchange.com/users/flair/265499.png)](https://stackexchange.com/users/265499) -## Copyright & License +## COPYRIGHT & LICENSE - Code & Docs © 2018-now Huan LI \ - Code released under the Apache-2.0 License diff --git a/csharp/Wechaty.Grpc/Wechaty.Grpc.csproj b/csharp/Wechaty.Grpc/Wechaty.Grpc.csproj new file mode 100644 index 00000000..644dbc39 --- /dev/null +++ b/csharp/Wechaty.Grpc/Wechaty.Grpc.csproj @@ -0,0 +1,29 @@ + + + + true + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + True + + + + + diff --git a/csharp/Wechaty.Grpc/Wechaty.Grpc.sln b/csharp/Wechaty.Grpc/Wechaty.Grpc.sln new file mode 100644 index 00000000..3060d4ce --- /dev/null +++ b/csharp/Wechaty.Grpc/Wechaty.Grpc.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30225.117 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wechaty.Grpc", "Wechaty.Grpc.csproj", "{71241DF7-C770-45CC-9FEA-AF6A09CA96FC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {71241DF7-C770-45CC-9FEA-AF6A09CA96FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {71241DF7-C770-45CC-9FEA-AF6A09CA96FC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {71241DF7-C770-45CC-9FEA-AF6A09CA96FC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {71241DF7-C770-45CC-9FEA-AF6A09CA96FC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {56949C51-6758-44D0-8503-0729A013F881} + EndGlobalSection +EndGlobal diff --git a/csharp/Wechaty.Grpc/buildTool/common.ps1 b/csharp/Wechaty.Grpc/buildTool/common.ps1 new file mode 100644 index 00000000..a20b650b --- /dev/null +++ b/csharp/Wechaty.Grpc/buildTool/common.ps1 @@ -0,0 +1,20 @@ +# Paths + +# csharp build Folder +$buildFolder = (Get-Item -Path "./" -Verbose).FullName + +# wechaty root folder +$rootFolder = Join-Path $buildFolder "../../../" + +# wechaty proto folder +$wechatyProtoFolder=Join-Path $rootFolder "proto" + +# chsarp solution Folder +$solutionFolder = Join-Path $rootFolder "csharp/Wechaty.Grpc" + +# get package.json data +$packageData=Get-Content (Join-Path $rootFolder "package.json") | ConvertFrom-Json + +# get package.json version +$version=($packageData | Select-Object -Property version).version + diff --git a/csharp/Wechaty.Grpc/buildTool/copy.ps1 b/csharp/Wechaty.Grpc/buildTool/copy.ps1 new file mode 100644 index 00000000..bcc1563d --- /dev/null +++ b/csharp/Wechaty.Grpc/buildTool/copy.ps1 @@ -0,0 +1,51 @@ +. ".\common.ps1" + + +# Get-ChildItem $projectFolder | ?{$_.psiscontainer -eq $false} + +Set-Location $buildFolder + +# csharp wechaty proto folder +$csharpProtoFolder=Join-Path $solutionFolder "proto" + +# if csharp proto folder is exists, delete if exists +if(Test-Path $csharpProtoFolder) +{ + Remove-Item -Path $csharpProtoFolder -Recurse -Force +} + +# copy wechaty proto folder to csharp proto folder +Copy-Item $wechatyProtoFolder $solutionFolder -Recurse + +$puppetFilePath = Join-Path $csharpProtoFolder "wechaty/puppet.proto" +# get puppet.proto content +$file = Get-Content $puppetFilePath + +# update import as csharp catalog +$file.Replace("import public `"puppet/","import public `"proto/wechaty/puppet/") | set-Content $puppetFilePath + +$puppetChildPath = Join-Path $csharpProtoFolder "wechaty/puppet" +Get-ChildItem $puppetChildPath| ForEach-Object -Process{ + if($_ -is [System.IO.FileInfo]) + { + Write-Host($_.fullname); + + $childfile = Get-Content $_.fullname + $childfile.Replace("import `"puppet/","import `"proto/wechaty/puppet/") | set-Content $_.fullname + } +} + + + +# update common.props version as package.json version +$commonPropPath = Join-Path $solutionFolder "common.props" +$commonPropsData = Get-Content $commonPropPath + +$versionNode="" + $version + "" +echo $versionNode +$commonPropsData -Replace "(.*)" , $versionNode | set-Content $commonPropPath + +Set-Location $buildFolder + + + diff --git a/csharp/Wechaty.Grpc/common.props b/csharp/Wechaty.Grpc/common.props new file mode 100644 index 00000000..76a8d23b --- /dev/null +++ b/csharp/Wechaty.Grpc/common.props @@ -0,0 +1,23 @@ + + + netstandard2.0 + latest + 0.17.8 + Wechaty + Wechaty + .NET Wechaty Grpc + $(NoWarn);CS1591 + wechaty.png + https://github.com/wechaty/grpc + Apache-2.0 + git + https://github.com/wechaty/grpc + + + + + + + + + diff --git a/csharp/Wechaty.Grpc/wechaty.png b/csharp/Wechaty.Grpc/wechaty.png new file mode 100644 index 00000000..867fca95 Binary files /dev/null and b/csharp/Wechaty.Grpc/wechaty.png differ diff --git a/docs/images/grpc-gateway-architecture.svg b/docs/images/grpc-gateway-architecture.svg new file mode 100644 index 00000000..3c9347e3 --- /dev/null +++ b/docs/images/grpc-gateway-architecture.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/client.ts b/examples/client.ts index b45357cf..254214bc 100644 --- a/examples/client.ts +++ b/examples/client.ts @@ -13,7 +13,7 @@ import { EventResponse, ContactAliasRequest, // EventType, -} from '../src/' +} from '../src/mod' import { StringValue } from 'google-protobuf/google/protobuf/wrappers_pb' /** diff --git a/examples/server.ts b/examples/server.ts index 237ceb8d..fedd34b4 100644 --- a/examples/server.ts +++ b/examples/server.ts @@ -9,7 +9,7 @@ import { EventType, DingResponse, EventRequest, -} from '../src/index' +} from '../src/mod' // import { StringValue } from 'google-protobuf/google/protobuf/wrappers_pb' @@ -18,7 +18,7 @@ import { } from '../tests/puppet-server-impl' let eventStream: undefined | grpc.ServerWritableStream -let dingQueue = [] as string[] +const dingQueue = [] as string[] /** * Implements the SayHello RPC method. diff --git a/go/generate.sh b/go/generate.sh index bc4799b5..4d7856d6 100755 --- a/go/generate.sh +++ b/go/generate.sh @@ -2,12 +2,14 @@ set -eo pipefail -PROTO_BASE_DIR=../proto +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +PROTO_BASE_DIR=$ROOT/proto PROTO_PUPPET_DIR=$PROTO_BASE_DIR/wechaty/puppet PROTO_WECHATY_DIR=$PROTO_BASE_DIR/wechaty -OUT_WECHATY_DIR=./generated/wechaty -OUT_PUPPET_DIR=$OUT_WECHATY_DIR/puppet +OUT_WECHATY_DIR=$ROOT/go/generated/wechaty +OUT_PUPPET_DIR=$OUT_WECHATY_DIR if [ ! -d "$PUPPET_GEN_DIR" ]; then mkdir -p $OUT_PUPPET_DIR @@ -15,11 +17,11 @@ fi protoc --version -protoc \ - -I $PROTO_PUPPET_DIR \ +cd $PROTO_WECHATY_DIR && protoc \ + -I $PROTO_WECHATY_DIR \ --go_out=plugins=grpc:$OUT_PUPPET_DIR \ --go_opt=paths=source_relative \ - $PROTO_PUPPET_DIR/*.proto + puppet/*.proto protoc \ -I $PROTO_WECHATY_DIR \ diff --git a/pom.xml b/java/pom.xml similarity index 74% rename from pom.xml rename to java/pom.xml index 01a23c7c..ee6148c8 100644 --- a/pom.xml +++ b/java/pom.xml @@ -2,10 +2,11 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> io.github.wechaty - 0.11.25-SANPSHOT + 0.11.25 4.0.0 grpc jar + wechaty-grpc Wechaty is a Wechat Bot SDK for Personal Account that lets you create software to extend the functionality of the @@ -21,6 +22,32 @@ + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0 + + + + + + Zhengxin Diao + diaozxin@gmail.com + + + + + + + sonatype + https://oss.sonatype.org/content/repositories/snapshots + + + sonatype + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + https://github.com/Chatie/grpc scm:git:ssh://github.com/Chatie/grpc.git @@ -35,6 +62,7 @@ 1.25.0 0.1.1 3.11.4 + UTF-8 @@ -114,7 +142,8 @@ grpc-java - io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} + io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} + ${basedir}/proto/wechaty @@ -126,7 +155,8 @@ grpc-kotlin - io.grpc:protoc-gen-grpc-kotlin:${grpc.kotlin.version}:exe:${os.detected.classifier} + io.grpc:protoc-gen-grpc-kotlin:${grpc.kotlin.version}:exe:${os.detected.classifier} + ${basedir}/proto/wechaty @@ -206,7 +236,56 @@ copy-dependencies package - copy-dependencies + + copy-dependencies + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + --pinentry-mode + loopback + + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + package + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + + package + + jar + diff --git a/openapi/.gitignore b/openapi/.gitignore new file mode 100644 index 00000000..08cb523c --- /dev/null +++ b/openapi/.gitignore @@ -0,0 +1 @@ +go.sum diff --git a/openapi/Makefile b/openapi/Makefile new file mode 100644 index 00000000..833cb5ba --- /dev/null +++ b/openapi/Makefile @@ -0,0 +1,14 @@ +.PHONY: all +all: generate + +.PHONY: generate +generate: + ./generate.sh + +.PHONY: clean +clean: + echo clean + +.PHONY: install +install: + ./install.sh diff --git a/openapi/README.md b/openapi/README.md new file mode 100644 index 00000000..c6f32425 --- /dev/null +++ b/openapi/README.md @@ -0,0 +1,5 @@ +# GO gRPC Gateway with OpenAPI Specification + +- gRPC Gateway: +- Template: +- Google APIs Proto Files: Node.js Client: diff --git a/openapi/generate.sh b/openapi/generate.sh new file mode 100755 index 00000000..3e66fe95 --- /dev/null +++ b/openapi/generate.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +set -e +set -o pipefail + +# https://stackoverflow.com/a/4774063/1123955 +SCRIPTPATH="$( cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 ; pwd -P )" + +THIRD_PARTY_DIR="${SCRIPTPATH}/../third-party/" +GENERATED_DIR="${SCRIPTPATH}/../generated/" + +PACKAGE_JSON_FILE="${SCRIPTPATH}/../package.json" +SWAGGER_JSON_FILE="${GENERATED_DIR}/wechaty/puppet.swagger.json" + +function generate_swagger () { + PROTOC="protoc \ + -I ../proto/ \ + -I ../proto/wechaty/ \ + -I ${THIRD_PARTY_DIR} \ + ../proto/wechaty/puppet.proto \ + " + + ${PROTOC} \ + --openapiv2_out ${GENERATED_DIR} \ + --openapiv2_opt logtostderr=true \ + --openapiv2_opt generate_unbound_methods=true +} + +function update_version () { + [ -f "$SWAGGER_JSON_FILE" ] || { + echo "File not found: $SWAGGER_JSON_FILE" + exit 1 + } + + grpcVersion=$(jq -r .version ${PACKAGE_JSON_FILE}) + tmpFile="/tmp/openapi.$$" + cat "$SWAGGER_JSON_FILE" \ + | jq --arg version "$grpcVersion" \ + '.info.version = $version' \ + > "$tmpFile" + mv "$tmpFile" "$SWAGGER_JSON_FILE" + + echo "Swagger version synced with gRPC version $grpcVersion" +} + +function main () { + generate_swagger + update_version +} + +main diff --git a/openapi/go.mod b/openapi/go.mod new file mode 100644 index 00000000..0be16c01 --- /dev/null +++ b/openapi/go.mod @@ -0,0 +1,14 @@ +module github.com/wechaty/grpc/openapi + +go 1.16 + +require ( + github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b + github.com/golang/protobuf v1.4.3 // indirect + github.com/google/protobuf v3.15.0+incompatible // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.1.0 + github.com/wechaty/go-grpc v0.18.12 // indirect + google.golang.org/grpc v1.34.0 + google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 + google.golang.org/protobuf v1.25.0 +) diff --git a/openapi/install.sh b/openapi/install.sh new file mode 100755 index 00000000..9e17a69c --- /dev/null +++ b/openapi/install.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +set -e + +# https://stackoverflow.com/a/4774063/1123955 +SCRIPTPATH="$( cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 ; pwd -P )" +THIRD_PARTY_DIR="${SCRIPTPATH}/../third-party/" + +function go_install () { + go install \ + github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway \ + github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2 \ + google.golang.org/protobuf/cmd/protoc-gen-go \ + google.golang.org/grpc/cmd/protoc-gen-go-grpc +} + +function install_proto_protoc_gen_openapiv2 () { + if [ -d ${THIRD_PARTY_DIR}/protoc-gen-openapiv2/options ]; then + echo "install skipped: ${THIRD_PARTY_DIR}/protoc-gen-openapiv2/options exists" + return + fi + + mkdir -p ${THIRD_PARTY_DIR}/protoc-gen-openapiv2/options + curl https://raw.githubusercontent.com/grpc-ecosystem/grpc-gateway/master/protoc-gen-openapiv2/options/annotations.proto > ${THIRD_PARTY_DIR}/protoc-gen-openapiv2/options/annotations.proto + curl https://raw.githubusercontent.com/grpc-ecosystem/grpc-gateway/master/protoc-gen-openapiv2/options/openapiv2.proto > ${THIRD_PARTY_DIR}/protoc-gen-openapiv2/options/openapiv2.proto +} + +main () { + go_install + install_proto_protoc_gen_openapiv2 +} + +main diff --git a/package.json b/package.json index ecd2ef9d..5b029a01 100644 --- a/package.json +++ b/package.json @@ -1,26 +1,28 @@ { - "name": "@chatie/grpc", - "version": "0.13.9", - "description": "gRPC for Chatie", - "main": "dist/src/index.js", - "typings": "dist/src/index.d.js", + "name": "wechaty-grpc", + "version": "0.20.19", + "description": "gRPC for Wechaty", + "main": "dist/src/mod.js", + "typings": "dist/src/mod.d.js", "directories": { "example": "examples", "test": "tests" }, "scripts": { "clean": "shx rm -fr dist/* generated/*", - "dist": "npm run clean && npm run generate && tsc && shx mv generated/ dist/", + "dist": "npm-run-all clean generate tsc dist:cp ", + "dist:cp": "shx cp -R generated/ dist/ && shx cp -R proto/ dist/", "dist:py": "python3 setup.py sdist bdist_wheel", "publish:py": "twine upload dist/*", "example:server": "nodemon --exec ts-node examples/server.ts", "example:client": "ts-node examples/client.ts", "generate": "bash -x scripts/generate-stub.sh", - "lint": "npm run lint:es && npm run lint:ts && npm run lint:proto", + "lint": "npm-run-all lint:es lint:ts lint:proto", "lint:es": "eslint --ignore-pattern fixtures/ \"src/**/*.ts\" \"tests/**/*.ts\" \"examples/**/*.ts\"", "lint:ts": "tsc --noEmit", - "lint:proto": "bash -c 'protoc -I proto/wechaty --lint_out=. $(find proto/ -type f -name *.proto)'", - "install:lint:protoc": "bash -x scripts/install-protoc-gen-lint.sh", + "lint:proto": "bash -c 'protoc -I third-party -I proto --lint_out=. $(find proto/ -type f -name *.proto)'", + "install:protoc": "bash -x scripts/install-protoc.sh", + "tsc": "tsc", "test": "npm run lint && npm run test:unit", "test:pack": "bash -x scripts/npm-pack-testing.sh", "test:unit": "blue-tape -r ts-node/register \"src/**/*.spec.ts\" \"tests/**/*.spec.ts\"", @@ -28,7 +30,7 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/Chatie/grpc.git" + "url": "git+https://github.com/wechaty/grpc.git" }, "keywords": [ "grpc", @@ -41,30 +43,32 @@ "author": "Huan LI ", "license": "Apache-2.0", "bugs": { - "url": "https://github.com/Chatie/grpc/issues" + "url": "https://github.com/wechaty/grpc/issues" }, - "homepage": "https://github.com/Chatie/grpc#readme", + "homepage": "https://github.com/wechaty/grpc#readme", "dependencies": { - "grpc": "^1.24.2", - "google-protobuf": "^3.11.3" + "grpc": "^1.24.5", + "google-protobuf": "^3.15.1" }, "devDependencies": { - "@chatie/eslint-config": "^0.8.1", - "@chatie/git-scripts": "^0.2.5", + "@chatie/eslint-config": "^0.12.3", + "@chatie/git-scripts": "^0.6.2", "@chatie/semver": "^0.4.7", - "@chatie/tsconfig": "^0.8.0", - "@types/google-protobuf": "^3.7.2", + "@chatie/tsconfig": "^0.14.1", + "@types/google-protobuf": "^3.7.4", "@types/protobufjs": "^6.0.0", - "grpc-tools": "^1.8.0", - "grpc_tools_node_protoc_ts": "^2.5.9", + "grpc-tools": "^1.10.0", + "grpc_tools_node_protoc_ts": "^5.1.3", "grpcc": "^1.1.3", - "nodemon": "^2.0.0", - "shx": "^0.3.2", - "ts-protoc-gen": "^0.12.0", + "nodemon": "^2.0.7", + "npm-run-all": "^4.1.5", + "request": "^2.88.2", + "shx": "^0.3.3", + "ts-protoc-gen": "^0.14.0", "tstest": "^0.4.10" }, "engines": { - "node": ">= 10" + "node": ">= 12" }, "publishConfig": { "access": "public", diff --git a/php/.gitignore b/php/.gitignore new file mode 100644 index 00000000..2ab84e67 --- /dev/null +++ b/php/.gitignore @@ -0,0 +1 @@ +wechaty-php-grpc.*/ diff --git a/php/Makefile b/php/Makefile new file mode 100644 index 00000000..78f31cd6 --- /dev/null +++ b/php/Makefile @@ -0,0 +1,26 @@ +# Makefile for PHP Wechaty +# +# GitHb: https://github.com/wechaty/php-wechaty +# Author: Chunsheng Zhang https://git.io/JJmKd +# + +.PHONY: all +all : clean lint + +.PHONY: clean +clean: + rm -fr generated/* + +.PHONY: test +test: + bash -x ./generate.sh + php grpc_test.php + +.PHONY: generate +generate: + bash -x ./generate.sh + +.PHONY: publish +publish: clean generate + ./publish.sh + diff --git a/php/generate.sh b/php/generate.sh new file mode 100755 index 00000000..594affd6 --- /dev/null +++ b/php/generate.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +set -eo pipefail + +PROTO_BASE_DIR=../proto +PROTO_PUPPET_DIR=$PROTO_BASE_DIR/wechaty/puppet +PROTO_WECHATY_DIR=$PROTO_BASE_DIR/wechaty + +# /usr/local/include + +OUT_WECHATY_DIR=./generated/wechaty +OUT_PUPPET_DIR=$OUT_WECHATY_DIR + +if [ ! -d "$PUPPET_GEN_DIR" ]; then + mkdir -p $OUT_PUPPET_DIR +fi + +protoc --version + +protoc \ + -I $PROTO_PUPPET_DIR \ + --php_out=$OUT_PUPPET_DIR \ + --grpc_out=$OUT_PUPPET_DIR \ + --plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugin \ + $PROTO_PUPPET_DIR/*.proto + +protoc \ + -I $PROTO_WECHATY_DIR \ + -I $PROTO_PUPPET_DIR \ + --php_out=$OUT_WECHATY_DIR \ + --grpc_out=$OUT_WECHATY_DIR \ + --plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugin \ + $PROTO_WECHATY_DIR/*.proto diff --git a/php/grpc_test.php b/php/grpc_test.php new file mode 100644 index 00000000..8717d397 --- /dev/null +++ b/php/grpc_test.php @@ -0,0 +1,30 @@ + Grpc\ChannelCredentials::createInsecure() +]); +$request = new \Wechaty\Puppet\DingRequest(); +list($response, $status) = $client->Ding($request)->wait(); +echo sprintf("code: %s, msg: %s \n", $status->code, $status->details); diff --git a/php/publish.sh b/php/publish.sh new file mode 100755 index 00000000..07569314 --- /dev/null +++ b/php/publish.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +set -eo pipefail + +GENERATED_DIR="$(pwd)/generated" + +VERSION=$(jq -r .version ../package.json) +DEPLOY_DIR="wechaty-php-grpc.$$" + +mkdir "$DEPLOY_DIR" +pushd "$DEPLOY_DIR" +# trap "rm -rfv $(pwd)/$DEPLOY_DIR" EXIT + +git clone git@github.com:wechaty/php-grpc.git +cd php-grpc +cp -Rav "$GENERATED_DIR"/wechaty . +echo "$VERSION" > VERSION + +if [ -z "$(git status --porcelain)" ]; then + echo + echo "[Publish] There's no new generated code found" + echo + exit 0 +fi + +git \ + -c "user.name=zhangchunsheng" \ + -c "user.email=zhangchunsheng423@gmail.com" \ + \ + commit \ + -am "Deploy PHP Grpc Module v${VERSION}" + +git push +echo +echo '[Publish] New code has been generated and pushed' +echo + +git tag v"$VERSION" +git push origin v"$VERSION" +echo +echo "[Publish] New version ${VERSION} has been tagged" +echo + +git status +popd diff --git a/proto/wechaty/puppet.proto b/proto/wechaty/puppet.proto index fba37c92..2a76b5bf 100644 --- a/proto/wechaty/puppet.proto +++ b/proto/wechaty/puppet.proto @@ -1,7 +1,7 @@ /** * * Wechaty Puppet gRPC Protocol Buffers - * https://github.com/chatie/grpc/ + * https://github.com/wechaty/grpc/ * Huan LI * Apr 2018 * License: Apache-2.0 @@ -13,17 +13,52 @@ syntax = "proto3"; package wechaty; +import "wechaty/puppet/base.proto"; +import "wechaty/puppet/contact.proto"; +import "wechaty/puppet/event.proto"; +import "wechaty/puppet/friendship.proto"; +import "wechaty/puppet/message.proto"; +import "wechaty/puppet/room.proto"; +import "wechaty/puppet/room_invitation.proto"; +import "wechaty/puppet/room_member.proto"; +import "wechaty/puppet/tag.proto"; + +import "google/api/annotations.proto"; +import "protoc-gen-openapiv2/options/annotations.proto"; + option java_package="io.github.wechaty.grpc"; +option go_package="github.com/wechaty/go-grpc/wechaty"; -import public "puppet/base.proto"; -import public "puppet/contact.proto"; -import public "puppet/event.proto"; -import public "puppet/friendship.proto"; -import public "puppet/message.proto"; -import public "puppet/room.proto"; -import public "puppet/room_invitation.proto"; -import public "puppet/room_member.proto"; -import public "puppet/tag.proto"; +option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { + info: { + title: "Wechaty Puppet Service OpenAPI Specification" + description: "Wechaty is a Conversational RPA SDK for chatbot makers. With only 6 lines of code, you can create a bot on the most popular IMs like WeChat, Whatsapp, WeCom, Gitter, etc.\n\nWechaty Puppet Service is the RESTful API for Wechaty API, which is build on top of the Wechaty Puppet Abstraction and the gRPC proto definition." + license: { + name: "Apache-2.0" + url: "http://www.apache.org/licenses/LICENSE-2.0.html" + } + contact: { + name: "Wechaty" + url: "https://github.com/wechaty/openapi" + email: "wechaty@chatie.io" + } + version: "0.0.0" // MUST be 0.0.0 at here: will be synced with the Git Repo when generating. + } + // schemes: [HTTP,HTTPS,WS,WSS] + consumes: "application/json" + produces: "application/json" + responses: { + key: "default" + value: { + description: "" + schema: { + json_schema: { + ref: ".google.rpc.Status" + } + } + } + } +}; service Puppet { /** @@ -31,119 +66,407 @@ service Puppet { * Base * */ - rpc Start (puppet.StartRequest) returns (puppet.StartResponse) {} - rpc Stop (puppet.StopRequest) returns (puppet.StopResponse) {} + rpc Start (puppet.StartRequest) returns (puppet.StartResponse) { + option (google.api.http) = { + put: "/start" + }; + } + rpc Stop (puppet.StopRequest) returns (puppet.StopResponse) { + option (google.api.http) = { + put: "/stop" + }; + } - rpc Logout (puppet.LogoutRequest) returns (puppet.LogoutResponse) {} - rpc Ding (puppet.DingRequest) returns (puppet.DingResponse) {} - rpc Version (puppet.VersionRequest) returns (puppet.VersionResponse) {} + rpc Logout (puppet.LogoutRequest) returns (puppet.LogoutResponse) { + option (google.api.http) = { + put: "/logout" + }; + } + rpc Ding (puppet.DingRequest) returns (puppet.DingResponse) { + option (google.api.http) = { + post: "/ding" + body: "*" + }; + } + rpc Version (puppet.VersionRequest) returns (puppet.VersionResponse) { + option (google.api.http) = { + get: "/version" + }; + } /** * * Event - Server Stream * */ - rpc Event (puppet.EventRequest) returns (stream puppet.EventResponse) {} + rpc Event (puppet.EventRequest) returns (stream puppet.EventResponse) { + option (google.api.http) = { + get: "/events" + }; + } + + rpc DirtyPayload (puppet.DirtyPayloadRequest) returns (puppet.DirtyPayloadResponse) { + option (google.api.http) = { + additional_bindings { + put: "/message/{id}/dirty/{type=PAYLOAD_TYPE_MESSAGE}" + } + additional_bindings { + put: "/contacts/{id}/dirty/{type=PAYLOAD_TYPE_CONTACT}" + } + additional_bindings { + put: "/rooms/{id}/dirty/{type=PAYLOAD_TYPE_ROOM}" + } + additional_bindings { + put: "/rooms/{id}/dirty/members/{type=PAYLOAD_TYPE_ROOM_MEMBER}" + } + additional_bindings { + put: "/friendships/{id}/dirty/{type=PAYLOAD_TYPE_FRIENDSHIP}" + } + }; + } /** * * Contact Self * */ - rpc ContactSelfQRCode (puppet.ContactSelfQRCodeRequest) returns (puppet.ContactSelfQRCodeResponse) {} - rpc ContactSelfName (puppet.ContactSelfNameRequest) returns (puppet.ContactSelfNameResponse) {} - rpc ContactSelfSignature (puppet.ContactSelfSignatureRequest) returns (puppet.ContactSelfSignatureResponse) {} + rpc ContactSelfQRCode (puppet.ContactSelfQRCodeRequest) returns (puppet.ContactSelfQRCodeResponse) { + option (google.api.http) = { + get: "/contacts/self/qrcode" + }; + + } + rpc ContactSelfName (puppet.ContactSelfNameRequest) returns (puppet.ContactSelfNameResponse) { + option (google.api.http) = { + put: "/contacts/self/name/{name}" + }; + } + rpc ContactSelfSignature (puppet.ContactSelfSignatureRequest) returns (puppet.ContactSelfSignatureResponse) { + option (google.api.http) = { + put: "/contacts/self/signature" + body: "*" + }; + } /** * * Contact * */ - rpc ContactPayload (puppet.ContactPayloadRequest) returns (puppet.ContactPayloadResponse) {} + rpc ContactPayload (puppet.ContactPayloadRequest) returns (puppet.ContactPayloadResponse) { + option (google.api.http) = { + get: "/contacts/{id}" + }; + } + + rpc ContactAlias (puppet.ContactAliasRequest) returns (puppet.ContactAliasResponse) { + option (google.api.http) = { + put: "/contacts/{id}/alias" + body: "*" + }; + } + rpc ContactAvatar (puppet.ContactAvatarRequest) returns (puppet.ContactAvatarResponse) { + option (google.api.http) = { + get: "/contacts/{id}/avatar" // TODO: Huan(202002) disable the avatar query parameters + // additional_bindings { + // put: "/contacts/{id}/avatar" + // body: "*" + // } + }; + } + rpc ContactPhone (puppet.ContactPhoneRequest) returns (puppet.ContactPhoneResponse) { + option (google.api.http) = { + put: "/contacts/{contact_id}/phone" + body: "*" + }; - rpc ContactAlias (puppet.ContactAliasRequest) returns (puppet.ContactAliasResponse) {} - rpc ContactAvatar (puppet.ContactAvatarRequest) returns (puppet.ContactAvatarResponse) {} + } + rpc ContactCorporationRemark (puppet.ContactCorporationRemarkRequest) returns (puppet.ContactCorporationRemarkResponse) { + option (google.api.http) = { + put: "/contacts/{contact_id}/corporation-remark" + body: "*" + }; + } + rpc ContactDescription (puppet.ContactDescriptionRequest) returns (puppet.ContactDescriptionResponse) { + option (google.api.http) = { + put: "/contacts/{contact_id}/description" + body: "*" + }; + } - rpc ContactList (puppet.ContactListRequest) returns (puppet.ContactListResponse) {} + /** + * Huan(202002): consider changing response to a stream in the future for better performance + */ + rpc ContactList (puppet.ContactListRequest) returns (puppet.ContactListResponse) { + option (google.api.http) = { + get: "/contacts" + }; + } /** * * Friendship * */ - rpc FriendshipPayload (puppet.FriendshipPayloadRequest) returns (puppet.FriendshipPayloadResponse) {} + rpc FriendshipPayload (puppet.FriendshipPayloadRequest) returns (puppet.FriendshipPayloadResponse) { + option (google.api.http) = { + get: "/friendship/{id}" + }; + } - rpc FriendshipSearchPhone (puppet.FriendshipSearchPhoneRequest) returns (puppet.FriendshipSearchPhoneResponse) {} - rpc FriendshipSearchWeixin (puppet.FriendshipSearchWeixinRequest) returns (puppet.FriendshipSearchWeixinResponse) {} + rpc FriendshipSearchPhone (puppet.FriendshipSearchPhoneRequest) returns (puppet.FriendshipSearchPhoneResponse) { + option (google.api.http) = { + get: "/friendship/search/phone/{phone}" + }; + } + rpc FriendshipSearchWeixin (puppet.FriendshipSearchWeixinRequest) returns (puppet.FriendshipSearchWeixinResponse) { + option (google.api.http) = { + get: "/friendship/search/weixin/{weixin}" + }; + } - rpc FriendshipAdd (puppet.FriendshipAddRequest) returns (puppet.FriendshipAddResponse) {} - rpc FrendshipAccept (puppet.FriendshipAcceptRequest) returns (puppet.FriendshipAcceptResponse) {} + rpc FriendshipAdd (puppet.FriendshipAddRequest) returns (puppet.FriendshipAddResponse) { + option (google.api.http) = { + put: "/friendship/add/{contact_id}" + body: "*" + }; + } + rpc FriendshipAccept (puppet.FriendshipAcceptRequest) returns (puppet.FriendshipAcceptResponse) { + option (google.api.http) = { + put: "/friendship/accept/{id}" + }; + } /** * * Message * */ - rpc MessagePayload (puppet.MessagePayloadRequest) returns (puppet.MessagePayloadResponse) {} - rpc MessageContact (puppet.MessageContactRequest) returns (puppet.MessageContactResponse) {} - rpc MessageFile (puppet.MessageFileRequest) returns (puppet.MessageFileResponse) {} - rpc MessageImage (puppet.MessageImageRequest) returns (puppet.MessageImageResponse) {} - rpc MessageMiniProgram (puppet.MessageMiniProgramRequest) returns (puppet.MessageMiniProgramResponse) {} - rpc MessageUrl (puppet.MessageUrlRequest) returns (puppet.MessageUrlResponse) {} + /** + * @deprecated: using MessageFileStream to transfer files + * Huan(202010): will be removed (replaced by MessageFileStream) after Dec 31, 2021 + */ + rpc MessageFile (puppet.MessageFileRequest) returns (puppet.MessageFileResponse) { + option deprecated = true; + } + + /** + * @deprecated: using MessageImageStream to transfer images + * Huan(202010): will be removed (replaced by MessageImageStream) after Dec 31, 2021 + */ + rpc MessageImage (puppet.MessageImageRequest) returns (puppet.MessageImageResponse) { + option deprecated = true; + } + + /** + * @deprecated: using MesageSendFileStream to transfer file message to server + * Huan(202010): will be removed (replaced by MessageSendFileStream) after Dec 31, 2021 + */ + rpc MessageSendFile (puppet.MessageSendFileRequest) returns (puppet.MessageSendFileResponse) { + option deprecated = true; + } - rpc MessageSendContact (puppet.MessageSendContactRequest) returns (puppet.MessageSendContactResponse) {} - rpc MessageSendFile (puppet.MessageSendFileRequest) returns (puppet.MessageSendFileResponse) {} - rpc MessageSendText (puppet.MessageSendTextRequest) returns (puppet.MessageSendTextResponse) {} - rpc MessageSendMiniProgram (puppet.MessageSendMiniProgramRequest) returns (puppet.MessageSendMiniProgramResponse) {} - rpc MessageSendUrl (puppet.MessageSendUrlRequest) returns (puppet.MessageSendUrlResponse) {} + rpc MessagePayload (puppet.MessagePayloadRequest) returns (puppet.MessagePayloadResponse) { + option (google.api.http) = { + get: "/message/{id}" + }; + } - rpc MessageRecall (puppet.MessageRecallRequest) returns (puppet.MessageRecallResponse) {} + rpc MessageContact (puppet.MessageContactRequest) returns (puppet.MessageContactResponse) { + option (google.api.http) = { + get: "/message/{id}/contact" + }; + } + rpc MessageFileStream (puppet.MessageFileStreamRequest) returns (stream puppet.MessageFileStreamResponse) { + option (google.api.http) = { + get: "/message/{id}/filebox" + }; + } + rpc MessageImageStream (puppet.MessageImageStreamRequest) returns (stream puppet.MessageImageStreamResponse) { + option (google.api.http) = { + get: "/message/{id}/image/{type}" + }; + } + rpc MessageMiniProgram (puppet.MessageMiniProgramRequest) returns (puppet.MessageMiniProgramResponse) { + option (google.api.http) = { + get: "/message/{id}/mini-program" + }; + } + rpc MessageUrl (puppet.MessageUrlRequest) returns (puppet.MessageUrlResponse) { + option (google.api.http) = { + get: "/message/{id}/url-link" + }; + } + rpc MessageRecall (puppet.MessageRecallRequest) returns (puppet.MessageRecallResponse) { + option (google.api.http) = { + put: "/message/{id}/recall" + body: "*" + }; + } + + rpc MessageSendContact (puppet.MessageSendContactRequest) returns (puppet.MessageSendContactResponse) { + option (google.api.http) = { + post: "/conversations/{conversation_id}/contact" + body: "*" + }; + } + rpc MessageSendFileStream (stream puppet.MessageSendFileStreamRequest) returns (puppet.MessageSendFileStreamResponse) { + /** + * TODO: Add support for client upload files + * https://github.com/wechaty/openapi/issues/1 + */ + option (google.api.http) = { + post: "/conversations/-/filebox" + body: "*" + }; + } + rpc MessageSendText (puppet.MessageSendTextRequest) returns (puppet.MessageSendTextResponse) { + option (google.api.http) = { + post: "/conversations/{conversation_id}/text" + body: "*" + }; + } + rpc MessageSendMiniProgram (puppet.MessageSendMiniProgramRequest) returns (puppet.MessageSendMiniProgramResponse) { + option (google.api.http) = { + post: "/conversations/{conversation_id}/mini-program" + body: "*" + }; + } + rpc MessageSendUrl (puppet.MessageSendUrlRequest) returns (puppet.MessageSendUrlResponse) { + option (google.api.http) = { + post: "/conversations/{conversation_id}/url-link" + body: "*" + }; + } /** * * Room * */ - rpc RoomPayload (puppet.RoomPayloadRequest) returns (puppet.RoomPayloadResponse) {} + rpc RoomPayload (puppet.RoomPayloadRequest) returns (puppet.RoomPayloadResponse) { + option (google.api.http) = { + get: "/rooms/{id}" + }; + } - rpc RoomList (puppet.RoomListRequest) returns (puppet.RoomListResponse) {} + rpc RoomList (puppet.RoomListRequest) returns (puppet.RoomListResponse) { + option (google.api.http) = { + get: "/rooms" + }; + } - rpc RoomAdd (puppet.RoomAddRequest) returns (puppet.RoomAddResponse) {} - rpc RoomAvatar (puppet.RoomAvatarRequest) returns (puppet.RoomAvatarResponse) {} - rpc RoomCreate (puppet.RoomCreateRequest) returns (puppet.RoomCreateResponse) {} - rpc RoomDel (puppet.RoomDelRequest) returns (puppet.RoomDelResponse) {} - rpc RoomQuit (puppet.RoomQuitRequest) returns (puppet.RoomQuitResponse) {} + rpc RoomAdd (puppet.RoomAddRequest) returns (puppet.RoomAddResponse) { + option (google.api.http) = { + put: "/rooms/{id}/add/{contact_id}" + }; + } + rpc RoomAvatar (puppet.RoomAvatarRequest) returns (puppet.RoomAvatarResponse) { + option (google.api.http) = { + get: "/rooms/{id}/avatar" + }; + } + rpc RoomCreate (puppet.RoomCreateRequest) returns (puppet.RoomCreateResponse) { + option (google.api.http) = { + post: "/rooms" + body: "*" + }; + } + rpc RoomDel (puppet.RoomDelRequest) returns (puppet.RoomDelResponse) { + option (google.api.http) = { + delete: "/rooms/{id}/member/{contact_id}" + }; + } + rpc RoomQuit (puppet.RoomQuitRequest) returns (puppet.RoomQuitResponse) { + option (google.api.http) = { + delete: "/rooms/{id}" + }; + } - rpc RoomTopic (puppet.RoomTopicRequest) returns (puppet.RoomTopicResponse) {} - rpc RoomQRCode (puppet.RoomQRCodeRequest) returns (puppet.RoomQRCodeResponse) {} - rpc RoomAnnounce (puppet.RoomAnnounceRequest) returns (puppet.RoomAnnounceResponse) {} + rpc RoomTopic (puppet.RoomTopicRequest) returns (puppet.RoomTopicResponse) { + option (google.api.http) = { + put: "/rooms/{id}/topic/{topic}" + }; + } + rpc RoomQRCode (puppet.RoomQRCodeRequest) returns (puppet.RoomQRCodeResponse) { + option (google.api.http) = { + get: "/rooms/{id}/qrcode" + }; + } + rpc RoomAnnounce (puppet.RoomAnnounceRequest) returns (puppet.RoomAnnounceResponse) { + option (google.api.http) = { + get: "/rooms/{id}/announcement" // TODO: disable other get parameters + additional_bindings { + put: "/rooms/{id}/announcement" + body: "*" + } + }; + } /** * * Room Member * */ - rpc RoomMemberPayload (puppet.RoomMemberPayloadRequest) returns (puppet.RoomMemberPayloadResponse) {} + rpc RoomMemberPayload (puppet.RoomMemberPayloadRequest) returns (puppet.RoomMemberPayloadResponse) { + option (google.api.http) = { + get: "/rooms/{id}/members/{member_id}" + }; + } - rpc RoomMemberList (puppet.RoomMemberListRequest) returns (puppet.RoomMemberListResponse) {} + rpc RoomMemberList (puppet.RoomMemberListRequest) returns (puppet.RoomMemberListResponse) { + option (google.api.http) = { + get: "/rooms/{id}/members" + }; + } /** * * Room Invitation * */ - rpc RoomInvitationPayload (puppet.RoomInvitationPayloadRequest) returns (puppet.RoomInvitationPayloadResponse) {} - rpc RoomInvitationAccept (puppet.RoomInvitationAcceptRequest) returns (puppet.RoomInvitationAcceptResponse) {} + rpc RoomInvitationPayload (puppet.RoomInvitationPayloadRequest) returns (puppet.RoomInvitationPayloadResponse) { + option (google.api.http) = { + get: "/room-invitations/{id}" + }; + } + rpc RoomInvitationAccept (puppet.RoomInvitationAcceptRequest) returns (puppet.RoomInvitationAcceptResponse) { + option (google.api.http) = { + put: "/room-invitations/{id}/accept" + }; + } /** * * Tag * */ - rpc TagContactAdd (puppet.TagContactAddRequest) returns (puppet.TagContactAddResponse) {} - rpc TagContactRemove (puppet.TagContactRemoveRequest) returns (puppet.TagContactRemoveResponse) {} - rpc TagContactDelete (puppet.TagContactDeleteRequest) returns (puppet.TagContactDeleteResponse) {} - rpc TagContactList (puppet.TagContactListRequest) returns (puppet.TagContactListResponse) {} + rpc TagContactAdd (puppet.TagContactAddRequest) returns (puppet.TagContactAddResponse) { + option (google.api.http) = { + put: "/contacts/{contact_id}/tags/{id}" + }; + } + rpc TagContactRemove (puppet.TagContactRemoveRequest) returns (puppet.TagContactRemoveResponse) { + option (google.api.http) = { + delete: "/contacts/{contact_id}/tags/{id}" + }; + } + + /** + * Operate Sub-Collections + * https://cloud.google.com/apis/design/design_patterns#list_sub-collections + */ + rpc TagContactDelete (puppet.TagContactDeleteRequest) returns (puppet.TagContactDeleteResponse) { + option (google.api.http) = { + delete: "/contacts/-/tags/{id}" + }; + } + + rpc TagContactList (puppet.TagContactListRequest) returns (puppet.TagContactListResponse) { + option (google.api.http) = { + get: "/contacts/{contact_id}/tags" + }; + } } diff --git a/proto/wechaty/puppet/base.proto b/proto/wechaty/puppet/base.proto index e72be44e..7cf4f243 100644 --- a/proto/wechaty/puppet/base.proto +++ b/proto/wechaty/puppet/base.proto @@ -1,8 +1,18 @@ syntax = "proto3"; package wechaty.puppet; -option go_package="github.com/wechaty/go-grpc/wechaty/puppet"; -option java_package="io.github.wechaty.grpc.puppet"; +option go_package = "github.com/wechaty/go-grpc/wechaty/puppet"; +option java_package = "io.github.wechaty.grpc.puppet"; +option csharp_namespace = "github.wechaty.grpc.puppet"; + +enum PayloadType { + PAYLOAD_TYPE_UNKNOWN = 0; + PAYLOAD_TYPE_MESSAGE = 1; + PAYLOAD_TYPE_CONTACT = 2; + PAYLOAD_TYPE_ROOM = 3; + PAYLOAD_TYPE_ROOM_MEMBER = 4; + PAYLOAD_TYPE_FRIENDSHIP = 5; +} message StartRequest {} message StartResponse {} @@ -25,3 +35,10 @@ message DingResponse { // Ding has no return value // Puppet should emit a `ding` event when it receives a `ding()` call } + +message DirtyPayloadRequest { + PayloadType type = 1; + string id = 2; +} + +message DirtyPayloadResponse {} diff --git a/proto/wechaty/puppet/contact.proto b/proto/wechaty/puppet/contact.proto index cb14f8e4..de6ca129 100644 --- a/proto/wechaty/puppet/contact.proto +++ b/proto/wechaty/puppet/contact.proto @@ -3,6 +3,7 @@ package wechaty.puppet; option go_package="github.com/wechaty/go-grpc/wechaty/puppet"; option java_package="io.github.wechaty.grpc.puppet"; +option csharp_namespace = "github.wechaty.grpc.puppet"; import "google/protobuf/wrappers.proto"; @@ -16,6 +17,7 @@ enum ContactType { CONTACT_TYPE_UNSPECIFIED = 0; CONTACT_TYPE_PERSONAL = 1; CONTACT_TYPE_OFFICIAL = 2; + CONTACT_TYPE_CORPORATION = 3; } message ContactListRequest {} @@ -27,19 +29,24 @@ message ContactPayloadRequest { string id = 1; } message ContactPayloadResponse { - string id = 1; - ContactGender gender = 2; - ContactType type = 3; - string name = 4; - string avatar = 5; - string address = 6; - string alias = 7; - string city = 8; - bool friend = 9; - string province = 10; - string signature = 11; - bool star = 12; - string weixin = 13; + string id = 1; + ContactGender gender = 2; + ContactType type = 3; + string name = 4; + string avatar = 5; + string address = 6; + string alias = 7; + string city = 8; + bool friend = 9; + string province = 10; + string signature = 11; + bool star = 12; + string weixin = 13; + string corporation = 14; + string title = 15; + string description = 16; + bool coworker = 17; + repeated string phone = 18; } message ContactSelfQRCodeRequest {} @@ -69,9 +76,41 @@ message ContactAliasResponse { message ContactAvatarRequest { string id = 1; // nullable + /** + * Huan(202011) TODO: + * 1. rename to file_box + * 2. replace it by FileBoxChunk with stream support + */ google.protobuf.StringValue filebox = 2; } message ContactAvatarResponse { - google.protobuf.StringValue filebox = 1; + /** + * Huan(202011) TODO: + * 1. rename to file_box + * 2. replace it by FileBoxChunk with stream support + */ + google.protobuf.StringValue filebox = 1; } +message ContactPhoneRequest { + string contact_id = 1; + repeated string phone_list = 2; +} + +message ContactPhoneResponse { + repeated string phone_list = 2; +} + +message ContactCorporationRemarkRequest { + string contact_id = 1; + google.protobuf.StringValue corporation_remark = 2; +} + +message ContactCorporationRemarkResponse {} + +message ContactDescriptionRequest { + string contact_id = 1; + google.protobuf.StringValue description = 2; +} + +message ContactDescriptionResponse {} diff --git a/proto/wechaty/puppet/event.proto b/proto/wechaty/puppet/event.proto index 785e5e75..b3aa6f96 100644 --- a/proto/wechaty/puppet/event.proto +++ b/proto/wechaty/puppet/event.proto @@ -3,6 +3,7 @@ package wechaty.puppet; option go_package="github.com/wechaty/go-grpc/wechaty/puppet"; option java_package="io.github.wechaty.grpc.puppet"; +option csharp_namespace = "github.wechaty.grpc.puppet"; enum EventType { EVENT_TYPE_UNSPECIFIED = 0; @@ -24,6 +25,7 @@ enum EventType { EVENT_TYPE_RESET = 24; EVENT_TYPE_LOGIN = 25; EVENT_TYPE_LOGOUT = 26; + EVENT_TYPE_DIRTY = 27; } message EventRequest {} diff --git a/proto/wechaty/puppet/file_box.proto b/proto/wechaty/puppet/file_box.proto new file mode 100644 index 00000000..efaf5073 --- /dev/null +++ b/proto/wechaty/puppet/file_box.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; +package wechaty.puppet; + +option go_package="github.com/wechaty/go-grpc/wechaty/puppet"; +option csharp_namespace = "github.wechaty.grpc.puppet"; + +message FileBoxChunk { + oneof payload { + bytes data = 1; + string name = 2; + } +} diff --git a/proto/wechaty/puppet/friendship.proto b/proto/wechaty/puppet/friendship.proto index 15494ade..5043f541 100644 --- a/proto/wechaty/puppet/friendship.proto +++ b/proto/wechaty/puppet/friendship.proto @@ -3,6 +3,7 @@ package wechaty.puppet; option go_package="github.com/wechaty/go-grpc/wechaty/puppet"; option java_package="io.github.wechaty.grpc.puppet"; +option csharp_namespace = "github.wechaty.grpc.puppet"; import "google/protobuf/wrappers.proto"; diff --git a/proto/wechaty/puppet/message.proto b/proto/wechaty/puppet/message.proto index a3a9a503..03e3eb40 100644 --- a/proto/wechaty/puppet/message.proto +++ b/proto/wechaty/puppet/message.proto @@ -3,9 +3,12 @@ package wechaty.puppet; option go_package="github.com/wechaty/go-grpc/wechaty/puppet"; option java_package="io.github.wechaty.grpc.puppet"; +option csharp_namespace = "github.wechaty.grpc.puppet"; import "google/protobuf/wrappers.proto"; +import "wechaty/puppet/file_box.proto"; + enum MessageType { MESSAGE_TYPE_UNSPECIFIED = 0; @@ -52,7 +55,20 @@ message MessageImageRequest { ImageType type = 2; } message MessageImageResponse { - string filebox = 1; + /** + * Huan(202011) TODO: + * 1. rename to file_box + * 2. replace it by FileBoxChunk with stream support + */ + string filebox = 1; +} + +message MessageImageStreamRequest { + string id = 1; + ImageType type = 2; +} +message MessageImageStreamResponse { + FileBoxChunk file_box_chunk = 1; } message MessageContactRequest { @@ -66,7 +82,17 @@ message MessageFileRequest { string id = 1; } message MessageFileResponse { - string filebox = 1; + /** + * Huan(202011) deprecated: use MessageFileStreamResponse instead + */ + string filebox = 1; +} + +message MessageFileStreamRequest { + string id = 1; +} +message MessageFileStreamResponse { + FileBoxChunk file_box_chunk = 1; } message MessageMiniProgramRequest { @@ -100,9 +126,22 @@ message MessageSendFileResponse { google.protobuf.StringValue id = 1; } +message MessageSendFileStreamRequest { + oneof payload { + string conversation_id = 1; + FileBoxChunk file_box_chunk = 2; + }; +} +message MessageSendFileStreamResponse { + google.protobuf.StringValue id = 1; +} + message MessageSendTextRequest { string conversation_id = 1; string text = 2; + + // Huan(202011) FIXME: Issue #99 + // https://github.com/wechaty/grpc/issues/99 repeated string mentonal_ids = 3; } message MessageSendTextResponse { diff --git a/proto/wechaty/puppet/room.proto b/proto/wechaty/puppet/room.proto index e66ebe84..65a293cd 100644 --- a/proto/wechaty/puppet/room.proto +++ b/proto/wechaty/puppet/room.proto @@ -3,6 +3,7 @@ package wechaty.puppet; option go_package="github.com/wechaty/go-grpc/wechaty/puppet"; option java_package="io.github.wechaty.grpc.puppet"; +option csharp_namespace = "github.wechaty.grpc.puppet"; import "google/protobuf/wrappers.proto"; @@ -33,6 +34,11 @@ message RoomAvatarRequest { string id = 1; } message RoomAvatarResponse { + /** + * Huan(202011) TODO: + * 1. rename to file_box + * 2. replace it by FileBoxChunk with stream support + */ string filebox = 1; } diff --git a/proto/wechaty/puppet/room_invitation.proto b/proto/wechaty/puppet/room_invitation.proto index 7f2df8b1..c4f438c0 100644 --- a/proto/wechaty/puppet/room_invitation.proto +++ b/proto/wechaty/puppet/room_invitation.proto @@ -3,11 +3,17 @@ package wechaty.puppet; option go_package="github.com/wechaty/go-grpc/wechaty/puppet"; option java_package="io.github.wechaty.grpc.puppet"; +option csharp_namespace = "github.wechaty.grpc.puppet"; import "google/protobuf/wrappers.proto"; message RoomInvitationPayloadRequest { string id = 1; + /** + * Huan(202002): `payload` should be removed. + * The puppet server should take the responsibilities + * for storing the unaccepted friend-request payload. + */ google.protobuf.StringValue payload = 2; } message RoomInvitationPayloadResponse { diff --git a/proto/wechaty/puppet/room_member.proto b/proto/wechaty/puppet/room_member.proto index 4b2e34a6..a29b7d9f 100644 --- a/proto/wechaty/puppet/room_member.proto +++ b/proto/wechaty/puppet/room_member.proto @@ -3,6 +3,7 @@ package wechaty.puppet; option go_package="github.com/wechaty/go-grpc/wechaty/puppet"; option java_package="io.github.wechaty.grpc.puppet"; +option csharp_namespace = "github.wechaty.grpc.puppet"; message RoomMemberPayloadRequest { string id = 1; diff --git a/proto/wechaty/puppet/tag.proto b/proto/wechaty/puppet/tag.proto index 72207686..e9a42ab4 100644 --- a/proto/wechaty/puppet/tag.proto +++ b/proto/wechaty/puppet/tag.proto @@ -3,6 +3,7 @@ package wechaty.puppet; option go_package="github.com/wechaty/go-grpc/wechaty/puppet"; option java_package="io.github.wechaty.grpc.puppet"; +option csharp_namespace = "github.wechaty.grpc.puppet"; import "google/protobuf/wrappers.proto"; diff --git a/python/.gitignore b/python/.gitignore index bf891412..8eba6c8d 100644 --- a/python/.gitignore +++ b/python/.gitignore @@ -1 +1 @@ -chatie-grpc/ +src/ diff --git a/python/Makefile b/python/Makefile index b333887b..60ac0006 100644 --- a/python/Makefile +++ b/python/Makefile @@ -1,7 +1,7 @@ # Makefile for Python Wechaty # # GitHb: https://github.com/wechaty/python-wechaty -# Author: Huan LI git.io/zixia +# Author: Huan LI https://github.com/huan # .PHONY: all @@ -9,16 +9,17 @@ all : generate .PHONY: clean clean: - rm -fr generated/* + rm -fr src/* .PHONY: install install: - pip install -r requirements.txt - pip install -r requirements-dev.txt + pip3 install -r requirements.txt + pip3 install -r requirements-dev.txt + ../scripts/install-protoc.sh .PHONY: test -pytest: - pytest src/ tests/ +test: + python3 -m pytest tests/ code: code . diff --git a/python/generate.sh b/python/generate.sh index 69d91866..4f66f404 100755 --- a/python/generate.sh +++ b/python/generate.sh @@ -8,15 +8,38 @@ shopt -s globstar # # Directory to write generated code to (.js and .d.ts files) -OUT_DIR="./chatie-grpc" +OUT_DIR="./src/wechaty_grpc" [ -d ${OUT_DIR} ] || { - mkdir ${OUT_DIR} + mkdir -p ${OUT_DIR} } -./merge-proto.sh > "$OUT_DIR/chatie-grpc.proto" -PROTO_DIR="$OUT_DIR" +function generate_proto_stub () { + # ./merge-proto.sh > "$OUT_DIR/wechaty_grpc.proto" + # PROTO_DIR="$OUT_DIR" + PROTO_DIR=../proto -PROTOC_CMD="python3 -m grpc_tools.protoc --proto_path=${PROTO_DIR} --proto_path=/usr/local/include/ ${PROTO_DIR}/**/*.proto" + PROTOC_CMD="python3 \ + -m grpc_tools.protoc \ + --proto_path=${PROTO_DIR} \ + --proto_path=../third-party \ + --proto_path=/usr/local/include/ \ + wechaty/puppet.proto \ + " -$PROTOC_CMD \ - --python_betterproto_out=${OUT_DIR} + $PROTOC_CMD \ + --python_betterproto_out=${OUT_DIR} +} + +# https://github.com/wechaty/grpc/issues/120 +function workaround_issue_120 () { + sed -i \ + 's/from typing import AsyncIterable, AsyncIterator, Iterable, Optional, Union/from typing import AsyncIterable, AsyncIterator, Iterable, Optional, Union, List/' \ + ${OUT_DIR}/wechaty/__init__.py +} + +main () { + generate_proto_stub + workaround_issue_120 +} + +main diff --git a/python/merge-proto.sh b/python/merge-proto.sh index 74d1e4fa..2256f8a5 100755 --- a/python/merge-proto.sh +++ b/python/merge-proto.sh @@ -1,5 +1,12 @@ #!/usr/bin/env bash +# +# DEPRECATED: this script was deprecated +# https://github.com/wechaty/grpc/issues/46 +# +# Huan(20200222): betterproto[compiler]>=2.0.0b2 is OK +# + set -eo pipefail function echo_name () { @@ -25,7 +32,7 @@ function main () { cat <<'_EOF_' syntax = "proto3"; import "google/protobuf/wrappers.proto"; -package wechaty.puppet; +package wechaty; _EOF_ for file in ../proto/wechaty/puppet/*.proto; do diff --git a/python/requirements-dev.txt b/python/requirements-dev.txt index 3f97bf67..2c88e2ff 100644 --- a/python/requirements-dev.txt +++ b/python/requirements-dev.txt @@ -1,4 +1,4 @@ -betterproto[compiler] +betterproto[compiler]>=2.0.0b2 grpcio-tools pyee pylint_quotes diff --git a/python/requirements.txt b/python/requirements.txt index d2ee3d5f..8a34104e 100644 --- a/python/requirements.txt +++ b/python/requirements.txt @@ -1 +1 @@ -betterproto +betterproto>=2.0.0b2 diff --git a/python/setup.py b/python/setup.py index fd84460d..e0dd4552 100644 --- a/python/setup.py +++ b/python/setup.py @@ -35,22 +35,23 @@ def setup() -> None: version = versioning(pkg['version']) setuptools.setup( - name='chatie-grpc', + name='wechaty-grpc', version=version, author='Huan LI (李卓桓)', author_email='zixia@zixia.net', - description='gRPC for Chatie', + description='Wechaty Puppet Service gRPC API', long_description=long_description, long_description_content_type='text/markdown', license='Apache-2.0', - url='https://github.com/chatie/grpc', - packages=setuptools.find_packages('chatie-grpc'), - package_dir={'': 'chatie-grpc'}, + url='https://github.com/wechaty/grpc', + packages=setuptools.find_packages("src"), + package_dir={'': 'src'}, classifiers=[ 'Programming Language :: Python :: 3.7', 'License :: OSI Approved :: Apache Software License', 'Operating System :: OS Independent', ], + install_requires=['betterproto', 'grpclib'] ) diff --git a/python/integration_test.py b/python/tests/integration_test.py similarity index 86% rename from python/integration_test.py rename to python/tests/integration_test.py index e2a1b6a9..fd01c41c 100644 --- a/python/integration_test.py +++ b/python/tests/integration_test.py @@ -15,4 +15,4 @@ def test_smoke_testing() -> None: """ wechaty """ - assert pytest, 'should True' + assert pytest, 'To-be added' diff --git a/scripts/generate-stub.sh b/scripts/generate-stub.sh index 1053dcbb..b0da2a20 100755 --- a/scripts/generate-stub.sh +++ b/scripts/generate-stub.sh @@ -1,54 +1,84 @@ #!/usr/bin/env bash set -e -PROTO_DIR="./proto" +PROTO_DIR="./proto/" +THIRD_PARTY_DIR="./third-party/" # Directory to write generated code to (.js and .d.ts files) -OUT_DIR="./generated/wechaty" +OUT_DIR="./generated" [ -d ${OUT_DIR} ] || { mkdir -p ${OUT_DIR} } -PROTO_FILE_LIST=$(find $PROTO_DIR -type f -name *.proto) +PROTO_FILE_LIST=$(find $PROTO_DIR $THIRD_PARTY_DIR -type f -name *.proto) # --proto_path=/usr/local/include/ -PROTOC_CMD="protoc --proto_path=${PROTO_DIR}/wechaty $PROTO_FILE_LIST" - -# -# 1. JS for Protocol Buffer -# - https://github.com/google/protobuf/releases/latest -# -# Generate: wechaty-puppet_pb.js -$PROTOC_CMD \ - --js_out="import_style=commonjs,binary:${OUT_DIR}" - -# -# 2. JS for gRPC Stubs -# - https://www.npmjs.com/package/grpc-tools -# -# Generate: wechaty-puppet_grpc_pb.js -$PROTOC_CMD \ - --plugin="protoc-gen-grpc=`command -v grpc_tools_node_protoc_plugin`" \ - --grpc_out="${OUT_DIR}" - -# -# 3. TS for Protocol Buffer & gRPC Stubs -# - https://github.com/agreatfool/grpc_tools_node_protoc_ts -# -# Generate: -# wechaty-puppet_grpc_pb.d.ts -# wechaty-puppet_pb.d.ts -$PROTOC_CMD \ - --plugin="protoc-gen-grpc=node_modules/grpc_tools_node_protoc_ts/bin/protoc-gen-ts" \ - --grpc_out="${OUT_DIR}" - -# -# 4. JS & TS for gRPC Web -# - https://github.com/improbable-eng/ts-protoc-gen -# -# Generate: -# wechaty-puppet_pb_service.d.ts -# wechaty-puppet_pb_service.js -$PROTOC_CMD \ - --plugin="protoc-gen-ts=node_modules/ts-protoc-gen/bin/protoc-gen-ts" \ - --ts_out="service=true:${OUT_DIR}" +PROTOC_CMD="protoc \ + -I ${THIRD_PARTY_DIR} \ + -I ${PROTO_DIR} \ + $PROTO_FILE_LIST \ +" + +function gen_js_pb () { + # + # 1. JS for Protocol Buffer + # - https://github.com/google/protobuf/releases/latest + # + # Generate: wechaty-puppet_pb.js + $PROTOC_CMD \ + --js_out="import_style=commonjs,binary:${OUT_DIR}" +} + +function gen_js_stub () { + # + # 2. JS for gRPC Stubs + # - https://www.npmjs.com/package/grpc-tools + # + # Generate: wechaty-puppet_grpc_pb.js + $PROTOC_CMD \ + --plugin="protoc-gen-grpc=node_modules/.bin/grpc_tools_node_protoc_plugin" \ + --grpc_out="${OUT_DIR}" +} + +function gen_ts_typing () { + # + # 3. TS for Protocol Buffer & gRPC Stubs + # - https://github.com/agreatfool/grpc_tools_node_protoc_ts + # + # Generate: + # wechaty-puppet_grpc_pb.d.ts + # wechaty-puppet_pb.d.ts + $PROTOC_CMD \ + --plugin="protoc-gen-grpc=node_modules/grpc_tools_node_protoc_ts/bin/protoc-gen-ts" \ + --grpc_out="${OUT_DIR}" +} + +function gen_web_grpc () { + # + # 4. JS & TS for gRPC Web + # - https://github.com/improbable-eng/ts-protoc-gen + # + # Generate: + # wechaty-puppet_pb_service.d.ts + # wechaty-puppet_pb_service.js + $PROTOC_CMD \ + --plugin="protoc-gen-ts=node_modules/ts-protoc-gen/bin/protoc-gen-ts" \ + --ts_out="service=grpc-web:${OUT_DIR}" +} +function gen_openapi () { + pushd openapi + make generate + popd +} + +function main () { + gen_js_pb + gen_js_stub + gen_ts_typing + + gen_web_grpc + + gen_openapi +} + +main diff --git a/scripts/install-protoc-gen-lint.sh b/scripts/install-protoc-gen-lint.sh deleted file mode 100755 index d9b5d825..00000000 --- a/scripts/install-protoc-gen-lint.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -set -eo pipefail - -go get -u github.com/ckaznocha/protoc-gen-lint diff --git a/scripts/install-protoc.sh b/scripts/install-protoc.sh index e67be593..c6827377 100755 --- a/scripts/install-protoc.sh +++ b/scripts/install-protoc.sh @@ -1,44 +1,92 @@ #!/usr/bin/env bash set -e +set -o pipefail -# https://superuser.com/questions/603068/unzipping-file-whilst-getting-correct-permissions -umask 644 -SUDO=sudo - -# http://google.github.io/proto-lens/installing-protoc.html - -if [ $(uname) = 'Linux' ]; then - PROTOC_PLATFORM=linux - PROTOC_GEN_LINT_PLATFORM=linux -elif [ $(uname) = 'Darwin' ]; then - PROTOC_PLATFORM=osx - PROTOC_GEN_LINT_PLATFORM=darwin -elif [[ $(uname) =~ ^MINGW64 ]]; then # GitHub Actions in Windows - PROTOC_PLATFORM=win64 - PROTOC_GEN_LINT_PLATFORM=windows - # no sudo in win32 bash - SUDO= -else - echo UNKNOWN PLATFORM -fi - -PROTOC_VERSION='3.11.3' -PROTOC_ZIP="protoc-$PROTOC_VERSION-$PROTOC_PLATFORM-x86_64.zip" - -curl -OL "https://github.com/google/protobuf/releases/download/v$PROTOC_VERSION/$PROTOC_ZIP" -# See: https://github.com/grpc-ecosystem/grpc-gateway/issues/194 -$SUDO unzip -o $PROTOC_ZIP -d /usr/local bin/* include/* -$SUDO chmod -R 755 /usr/local/include/google/ -$SUDO chmod +x /usr/local/bin/protoc -rm -f $PROTOC_ZIP - -# -# https://github.com/ckaznocha/protoc-gen-lint -# -PROTOC_GEN_LINT_VERSION='0.2.1' -PROTOC_GEN_LINT_ZIP="protoc-gen-lint_${PROTOC_GEN_LINT_PLATFORM}_amd64.zip" - -curl -OL "https://github.com/ckaznocha/protoc-gen-lint/releases/download/v$PROTOC_GEN_LINT_VERSION/$PROTOC_GEN_LINT_ZIP" -$SUDO unzip -o "$PROTOC_GEN_LINT_ZIP" protoc-gen-lint -d /usr/local/bin protoc-gen-lint -$SUDO chmod +x /usr/local/bin/protoc-gen-lint -rm -f "$PROTOC_GEN_LINT_ZIP" +# https://stackoverflow.com/a/4774063/1123955 +SCRIPTPATH="$( cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 ; pwd -P )" + +THIRD_PARTY_DIR="${SCRIPTPATH}/../third-party/" + +function install_protoc () { + if command -v protoc > /dev/null; then + echo "install skipped: protoc exists" + return + fi + + # https://grpc.io/docs/protoc-installation/ + if [ $(uname) = 'Linux' ]; then + sudo apt install -y protobuf-compiler + elif [ $(uname) = 'Darwin' ]; then + brew install protobuf + else + echo "UNKNOWN PLATFORM: $(uname)" + exit 1 + fi + +} + +function check_protoc_version () { + # libprotoc 3.11.3 + protocVersion=$(protoc --version | cut -d' ' -f 2) + majorVer=$(echo $protocVersion | cut -d. -f 1) + minorVer=$(echo $protocVersion | cut -d. -f 2) + + (($majorVer == 3)) || { + echo "protoc major version must >= 3 (the installed version is $protocVersion)" + exit 1 + } + + # https://github.com/wechaty/grpc/issues/116 + (($minorVer >= 5)) || { + echo "protoc minor version must >= 5 (the installed version is $protocVersion)" + exit 1 + } + + echo "protoc version check: v${protocVersion} OK" +} + +function install_protoc_gen_lint () { + go get -u github.com/ckaznocha/protoc-gen-lint +} + +function install_proto_google_api () { + if [ -d ${THIRD_PARTY_DIR}/google/api ]; then + echo "install skipped: ${THIRD_PARTY_DIR}/google/api exists" + return + fi + + mkdir -p ${THIRD_PARTY_DIR}/google/api + curl https://raw.githubusercontent.com/googleapis/googleapis/master/google/api/annotations.proto > ${THIRD_PARTY_DIR}/google/api/annotations.proto + curl https://raw.githubusercontent.com/googleapis/googleapis/master/google/api/http.proto > ${THIRD_PARTY_DIR}/google/api/http.proto + curl https://raw.githubusercontent.com/googleapis/googleapis/master/google/api/http.proto > ${THIRD_PARTY_DIR}/google/api/http.proto +} + +function install_protoc_gen_openapiv2 () { + pushd "${SCRIPTPATH}/../openapi" + make install + popd +} + +# function install_google_protobuf_wrappers () { +# if [ -d ${THIRD_PARTY_DIR}/google/protobuf ]; then +# echo "install skipped: ${THIRD_PARTY_DIR}/google/protobuf exists" +# return +# fi + +# wget \ +# --directory-prefix ${THIRD_PARTY_DIR}/google/protobuf \ +# https://raw.githubusercontent.com/protocolbuffers/protobuf/master/src/google/protobuf/wrappers.proto \ +# https://raw.githubusercontent.com/protocolbuffers/protobuf/master/src/google/protobuf/descriptor.proto +# } + +function main () { + install_protoc + check_protoc_version + + install_protoc_gen_lint + install_protoc_gen_openapiv2 + + install_proto_google_api +} + +main diff --git a/src/config.ts b/src/config.ts index 7a1b7f75..3cbbbd8f 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1 +1,13 @@ export { VERSION } from './version' + +enum MajorVersionEnum { + v0 = 'v0', + // v1 = 'v1', +} + +export type ApiStore = { + [key in MajorVersionEnum]: { + file: string, + data: string, + } +} diff --git a/src/generated.ts b/src/generated.ts index f959ce5c..cd35632e 100644 --- a/src/generated.ts +++ b/src/generated.ts @@ -1,6 +1,7 @@ export * from '../generated/wechaty/puppet/base_pb' export * from '../generated/wechaty/puppet/contact_pb' export * from '../generated/wechaty/puppet/event_pb' +export * from '../generated/wechaty/puppet/file_box_pb' export * from '../generated/wechaty/puppet/friendship_pb' export * from '../generated/wechaty/puppet/message_pb' export * from '../generated/wechaty/puppet/room_invitation_pb' diff --git a/src/index.ts b/src/mod.ts similarity index 60% rename from src/index.ts rename to src/mod.ts index be79db01..d4745eaa 100644 --- a/src/index.ts +++ b/src/mod.ts @@ -1,9 +1,15 @@ -export * from './generated' - -export { +import * as proto from './proto' +import * as openApi from './openapi' +import { VERSION, } from './config' +export { + proto, + openApi, + VERSION, +} +export * from './generated' export { StringValue, } from 'google-protobuf/google/protobuf/wrappers_pb' diff --git a/src/openapi.spec.ts b/src/openapi.spec.ts new file mode 100755 index 00000000..28b9295f --- /dev/null +++ b/src/openapi.spec.ts @@ -0,0 +1,23 @@ +#!/usr/bin/env ts-node + +// tslint:disable:no-shadowed-variable +import test from 'tstest' + +import { + puppet, +} from './openapi' + +test('puppet.v0.file', async (t) => { + const EXPECTED_PATH_REG = /puppet.swagger.json$/ + t.true(EXPECTED_PATH_REG.test(puppet.v0.file), 'puppet OpenAPI file should be puppet.swagger.json') +}) + +test('puppet.v0.data', async (t) => { + t.true(puppet.v0.data.length > 0, 'should get JSON data for puppet.v0.data') + try { + const obj = JSON.parse(puppet.v0.data) + t.true(obj, 'should be able to parse JSON for puppet.v0.data') + } catch (e) { + t.fail('should be able to parse JSON data for puppet.v0.data') + } +}) diff --git a/src/openapi.ts b/src/openapi.ts new file mode 100644 index 00000000..a815fc58 --- /dev/null +++ b/src/openapi.ts @@ -0,0 +1,29 @@ +import path from 'path' +import fs from 'fs' + +import { ApiStore } from './config' + +function getOpenApiPath (...paths: string[]): string { + return path.join( + __dirname, + '..', + 'generated', + ...paths, + ) +} + +const puppetSwaggerFile = getOpenApiPath( + 'wechaty', + 'puppet.swagger.json', +) + +const puppet: ApiStore = { + v0: { + data: fs.readFileSync(puppetSwaggerFile).toString(), + file: puppetSwaggerFile, + }, +} + +export { + puppet, +} diff --git a/src/proto.spec.ts b/src/proto.spec.ts new file mode 100755 index 00000000..1f167af3 --- /dev/null +++ b/src/proto.spec.ts @@ -0,0 +1,17 @@ +#!/usr/bin/env ts-node + +// tslint:disable:no-shadowed-variable +import test from 'tstest' + +import { + puppet, +} from './proto' + +test('puppet.v0.file', async (t) => { + const EXPECTED_PATH_REG = /puppet\.proto$/ + t.true(EXPECTED_PATH_REG.test(puppet.v0.file), 'puppet proto file should be puppet.proto') +}) + +test('puppet.v0.data', async (t) => { + t.true(puppet.v0.data.length > 0, 'should get proto data for puppet.v0.data') +}) diff --git a/src/proto.ts b/src/proto.ts new file mode 100644 index 00000000..bf9afb60 --- /dev/null +++ b/src/proto.ts @@ -0,0 +1,28 @@ +/** + * Huan(20200222): inspired from googleapis/nodejs-proto-files + * https://github.com/googleapis/nodejs-proto-files/blob/920fe4e5f8dee9a187e1858903894810a9b5feca/src/index.ts#L18-L20 + */ +import path from 'path' +import fs from 'fs' + +import { ApiStore } from './config' + +function getProtoPath (...paths: string[]): string { + return path.join(__dirname, '..', 'proto', ...paths) +} + +const puppetProtoFile = getProtoPath( + 'wechaty', + 'puppet.proto', +) + +const puppet: ApiStore = { + v0: { + data: fs.readFileSync(puppetProtoFile).toString(), + file: puppetProtoFile, + }, +} + +export { + puppet, +} diff --git a/tests/fixtures/smoke-testing.ts b/tests/fixtures/smoke-testing.ts index 5e5421dc..5c550b0b 100644 --- a/tests/fixtures/smoke-testing.ts +++ b/tests/fixtures/smoke-testing.ts @@ -3,7 +3,7 @@ import { MessagePayloadResponse, VERSION, -} from '@chatie/grpc' +} from 'wechaty-grpc' async function main () { if (VERSION === '0.0.0') { @@ -12,7 +12,7 @@ async function main () { const messagePayloadResponse = new MessagePayloadResponse() messagePayloadResponse.setId('id') - console.info(`@chatie/grpc v${VERSION} smoking test passed.`) + console.info(`wechaty-grpc v${VERSION} smoking test passed.`) return 0 } diff --git a/tests/integration.spec.ts b/tests/integration.spec.ts index cc1f3c96..d88c0ccf 100644 --- a/tests/integration.spec.ts +++ b/tests/integration.spec.ts @@ -15,7 +15,7 @@ import { PuppetClient, DingRequest, EventRequest, -} from '../src/index' +} from '../src/mod' import { puppetServerImpl, @@ -53,7 +53,7 @@ test('integration testing', async (t) => { */ const eventStream = client.event(new EventRequest()) - const future = new Promise((resolve, reject) => { + const future = new Promise((resolve, reject) => { eventStream .on('data', (chunk: EventResponse) => { const payload = chunk.getPayload() @@ -90,7 +90,7 @@ test('integration testing', async (t) => { */ eventStream.cancel() - await new Promise(resolve => server.tryShutdown(resolve)) + await new Promise(resolve => server.tryShutdown(resolve)) // server.forceShutdown() }) diff --git a/tests/nullable.spec.ts b/tests/nullable.spec.ts index 39579da6..a413ef01 100644 --- a/tests/nullable.spec.ts +++ b/tests/nullable.spec.ts @@ -11,7 +11,7 @@ import { ContactAliasResponse, PuppetService, PuppetClient, -} from '../src/' +} from '../src/mod' import { puppetServerImpl } from './puppet-server-impl' @@ -95,7 +95,7 @@ test('use StringValue to support nullable values', async (t) => { t.ok(aliasWrapper, 'Should return an aliasWrapper') if (aliasWrapper) { - let alias = aliasWrapper.getValue() + const alias = aliasWrapper.getValue() t.equal(alias, ID + ALIAS, 'should get the right alias value') } else { t.fail('can not get alias value') diff --git a/tests/puppet-server-impl.ts b/tests/puppet-server-impl.ts index 7e251e61..b509ff0b 100644 --- a/tests/puppet-server-impl.ts +++ b/tests/puppet-server-impl.ts @@ -1,6 +1,6 @@ import { IPuppetServer, -} from '../src/' +} from '../src/mod' /** * Implements the SayHello RPC method. @@ -10,289 +10,329 @@ export const puppetServerImpl: IPuppetServer = { contactAlias: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, contactAvatar: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') + }, + + contactCorporationRemark: (call, callback) => { + void call + void callback + throw new Error('not implemented') + }, + + contactDescription: (call, callback) => { + void call + void callback + throw new Error('not implemented') }, contactList: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, contactPayload: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') + }, + + contactPhone: (call, callback) => { + void call + void callback + throw new Error('not implemented.') }, contactSelfName: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, contactSelfQRCode: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, contactSelfSignature: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, ding: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') + }, + + dirtyPayload: (call, callback) => { + void call + void callback + throw new Error('not implemented.') }, event: (streamnigCall) => { void streamnigCall - throw new Error('not implmented.') + throw new Error('not implemented.') }, - frendshipAccept: (call, callback) => { + friendshipAccept: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, friendshipAdd: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, friendshipPayload: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, friendshipSearchPhone: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, friendshipSearchWeixin: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, logout: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, messageContact: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, messageFile: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') + }, + + messageFileStream: (call) => { + void call + throw new Error('not implemented.') }, messageImage: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') + }, + + messageImageStream: (call) => { + void call + throw new Error('not implemented.') }, messageMiniProgram: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, messagePayload: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, messageRecall: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, messageSendContact: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, messageSendFile: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') + }, + + messageSendFileStream: (call, callback) => { + void call + void callback + throw new Error('not implemented.') }, messageSendMiniProgram: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, messageSendText: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, messageSendUrl: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, messageUrl: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, roomAdd: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, roomAnnounce: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, roomAvatar: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, roomCreate: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, roomDel: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, roomInvitationAccept: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, roomInvitationPayload: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, roomList: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, roomMemberList: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, roomMemberPayload: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, roomPayload: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, roomQRCode: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, roomQuit: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, roomTopic: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, start: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, stop: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, tagContactAdd: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, tagContactDelete: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, tagContactList: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, tagContactRemove: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, version: (call, callback) => { void call void callback - throw new Error('not implmented.') + throw new Error('not implemented.') }, }