forked from lug/matterbridge
		
	Compare commits
	
		
			201 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 1a5353d768 | ||
|   | eff41759bc | ||
|   | c23252ab53 | ||
|   | 1a3c57a031 | ||
|   | 4cc2c914e6 | ||
|   | cbb46293ab | ||
|   | 765e00c949 | ||
|   | 662359908b | ||
|   | 0d99766686 | ||
|   | ae3bc3358b | ||
|   | 1e0b4532bd | ||
|   | 4f8b19c686 | ||
|   | 84ab223b81 | ||
|   | 2bb21262d4 | ||
|   | 3188a9ffe6 | ||
|   | 61569a8610 | ||
|   | 075a84427f | ||
|   | 950f2759bd | ||
|   | 25c82ddf02 | ||
|   | 2d98df6122 | ||
|   | 219a5453f9 | ||
|   | 214a6a1386 | ||
|   | e7781dc79c | ||
|   | 10c4bd1ac8 | ||
|   | a42e488e58 | ||
|   | 06eb89b05b | ||
|   | 91c58ec027 | ||
|   | 8b26e42a3a | ||
|   | acca011f15 | ||
|   | 2f59abdda7 | ||
|   | 17747a5c88 | ||
|   | cec63546ff | ||
|   | 75f67d2de4 | ||
|   | 712385ffd5 | ||
|   | ad90cf09fe | ||
|   | f9928c9e25 | ||
|   | a0741d99b8 | ||
|   | c63f08c811 | ||
|   | 58b6c4d277 | ||
|   | 27c02549c8 | ||
|   | 88d371c71c | ||
|   | b339524613 | ||
|   | d5feda5c8a | ||
|   | 2f506425c2 | ||
|   | e8167ee3d7 | ||
|   | 2f5e211065 | ||
|   | 39f4fb3446 | ||
|   | 56159b9bce | ||
|   | b2af76e7dc | ||
|   | 491fe35397 | ||
|   | b451285af7 | ||
|   | 63a1847cdc | ||
|   | 4e50fd8649 | ||
|   | dfdffa0027 | ||
|   | ebd2073144 | ||
|   | 1e94b716fb | ||
|   | 2a41abb3d1 | ||
|   | 2d2bebe976 | ||
|   | e1629994bd | ||
|   | e3d8fe4fd8 | ||
|   | 23d8742f0d | ||
|   | 3b6a8be07b | ||
|   | 71a5b72aff | ||
|   | 213bf349c3 | ||
|   | a94fe55886 | ||
|   | 9b22f16497 | ||
|   | 2977a5957e | ||
|   | f70d1c897a | ||
|   | a4a3525265 | ||
|   | a6dd8446e4 | ||
|   | 7bf9e1cfb3 | ||
|   | f291832a77 | ||
|   | 1fee323247 | ||
|   | a41accd033 | ||
|   | 37f7caf7f3 | ||
|   | 5847f7758c | ||
|   | bce736993e | ||
|   | 5636992446 | ||
|   | f996a2b7ae | ||
|   | 587de96ab3 | ||
|   | 80eb1cd202 | ||
|   | bbf594c815 | ||
|   | 2f0f2ee40d | ||
|   | 96022d3aaf | ||
|   | 8eb5e3cbf8 | ||
|   | ddc2625934 | ||
|   | 7f7ca697a0 | ||
|   | 900375679b | ||
|   | 9440b9e313 | ||
|   | 393f9e998b | ||
|   | ba0bfe70a8 | ||
|   | 3c4a3e3f75 | ||
|   | 274fb09ed4 | ||
|   | d44598a900 | ||
|   | c9cfa59f54 | ||
|   | 7062234331 | ||
|   | 9754569525 | ||
|   | 52a071e34d | ||
|   | 2d8f749e36 | ||
|   | a18cb74f03 | ||
|   | 6c442e239d | ||
|   | eaf92fca4d | ||
|   | 06b7bad714 | ||
|   | 19eec2ed03 | ||
|   | d99c54343a | ||
|   | 308a110000 | ||
|   | 4f406b2ce6 | ||
|   | e564c555d7 | ||
|   | f7ec9af9e8 | ||
|   | 4d93a774ce | ||
|   | 2595dd30bf | ||
|   | 9190365289 | ||
|   | 57794b3b9f | ||
|   | 3c36f651be | ||
|   | 8e6ddadba2 | ||
|   | 8a87a71927 | ||
|   | 0047e6f523 | ||
|   | 7183095a28 | ||
|   | 13c90893c7 | ||
|   | 976fbcd07f | ||
|   | d97b077e85 | ||
|   | 8950575bfb | ||
|   | 11fc4c286f | ||
|   | 8d08e348a9 | ||
|   | a18807f19e | ||
|   | 29f658fd3c | ||
|   | a30bb8fed0 | ||
|   | 092ca1cd67 | ||
|   | 0df2539641 | ||
|   | 0f2d8a599c | ||
|   | 54b3143a1d | ||
|   | 148f7d2a91 | ||
|   | 1aa662f763 | ||
|   | 0b86b88de7 | ||
|   | 98033b1ba7 | ||
|   | 2b7eab629d | ||
|   | 0e4973e15c | ||
|   | af0acf0dae | ||
|   | 76e5fe5a87 | ||
|   | 802c80f40c | ||
|   | a51c5bd905 | ||
|   | 8c68556f52 | ||
|   | cca1ea2404 | ||
|   | 281016a501 | ||
|   | d4acdf2f89 | ||
|   | 0951e75c85 | ||
|   | 6b017b226a | ||
|   | 9e3bd7398c | ||
|   | 79f764c7a8 | ||
|   | b5dc4353fb | ||
|   | 2fbac73c29 | ||
|   | 6616d105d1 | ||
|   | 6b4b19194e | ||
|   | 9785edd263 | ||
|   | 2a0bc11b68 | ||
|   | dd0325a88d | ||
|   | 20783c0978 | ||
|   | 3f06a40bd5 | ||
|   | 68f43985ad | ||
|   | 915ca8f817 | ||
|   | a65a81610b | ||
|   | 8eb6ed5639 | ||
|   | 795a8705c3 | ||
|   | 3af0dc3b3a | ||
|   | 9cf9b958a3 | ||
|   | 3ac2ba8d5a | ||
|   | d893421c7b | ||
|   | 250b3bb579 | ||
|   | e9edbfc051 | ||
|   | e343db6f72 | ||
|   | 4d57d66f85 | ||
|   | 54ed6320c2 | ||
|   | 23083f3ae0 | ||
|   | 1985873494 | ||
|   | 8ae5917659 | ||
|   | c91bfd08d8 | ||
|   | 49110a5872 | ||
|   | c01c8edeb8 | ||
|   | ff8cf067b8 | ||
|   | 1420f68050 | ||
|   | c0be3e585a | ||
|   | 3049ef9151 | ||
|   | 4be00bbe6b | ||
|   | 9382dde098 | ||
|   | 1bf46b7711 | ||
|   | b85bae31d9 | ||
|   | 0898829313 | ||
|   | f8ad877601 | ||
|   | 585d1556c1 | ||
|   | 7486555875 | ||
|   | fc30b1bacc | ||
|   | 0dd19af6e8 | ||
|   | 4c44515f9d | ||
|   | 9d84d6dd64 | ||
|   | 0f708daf2d | ||
|   | b9354de8fd | ||
|   | c9d5f4c898 | ||
|   | 810c150781 | ||
|   | 31dd538c0b | ||
|   | 62e38e7c45 | ||
|   | b9da28a29b | 
							
								
								
									
										2
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| Dockerfile | ||||
| tgs.Dockerfile | ||||
							
								
								
									
										1
									
								
								.github/ISSUE_TEMPLATE/Bug_report.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/ISSUE_TEMPLATE/Bug_report.md
									
									
									
									
										vendored
									
									
								
							| @@ -1,6 +1,7 @@ | ||||
| --- | ||||
| name: Bug report | ||||
| about: Create a report to help us improve. (Check the FAQ on the wiki first) | ||||
| labels: bug | ||||
|  | ||||
| --- | ||||
|  | ||||
|   | ||||
							
								
								
									
										1
									
								
								.github/ISSUE_TEMPLATE/Feature_request.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/ISSUE_TEMPLATE/Feature_request.md
									
									
									
									
										vendored
									
									
								
							| @@ -1,6 +1,7 @@ | ||||
| --- | ||||
| name: Feature request | ||||
| about: Suggest an idea for this project | ||||
| labels: enhancement | ||||
|  | ||||
| --- | ||||
|  | ||||
|   | ||||
							
								
								
									
										71
									
								
								.github/workflows/codeql-analysis.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								.github/workflows/codeql-analysis.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| # For most projects, this workflow file will not need changing; you simply need | ||||
| # to commit it to your repository. | ||||
| # | ||||
| # You may wish to alter this file to override the set of languages analyzed, | ||||
| # or to provide custom queries or build logic. | ||||
| name: "CodeQL" | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: [master] | ||||
|   pull_request: | ||||
|     # The branches below must be a subset of the branches above | ||||
|     branches: [master] | ||||
|   schedule: | ||||
|     - cron: '0 16 * * 1' | ||||
|  | ||||
| jobs: | ||||
|   analyze: | ||||
|     name: Analyze | ||||
|     runs-on: ubuntu-latest | ||||
|  | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         # Override automatic language detection by changing the below list | ||||
|         # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] | ||||
|         language: ['go'] | ||||
|         # Learn more... | ||||
|         # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection | ||||
|  | ||||
|     steps: | ||||
|     - name: Checkout repository | ||||
|       uses: actions/checkout@v2 | ||||
|       with: | ||||
|         # We must fetch at least the immediate parents so that if this is | ||||
|         # a pull request then we can checkout the head. | ||||
|         fetch-depth: 2 | ||||
|  | ||||
|     # If this run was triggered by a pull request event, then checkout | ||||
|     # the head of the pull request instead of the merge commit. | ||||
|     - run: git checkout HEAD^2 | ||||
|       if: ${{ github.event_name == 'pull_request' }} | ||||
|  | ||||
|     # Initializes the CodeQL tools for scanning. | ||||
|     - name: Initialize CodeQL | ||||
|       uses: github/codeql-action/init@v1 | ||||
|       with: | ||||
|         languages: ${{ matrix.language }} | ||||
|         # If you wish to specify custom queries, you can do so here or in a config file. | ||||
|         # By default, queries listed here will override any specified in a config file.  | ||||
|         # Prefix the list here with "+" to use these queries and those in the config file. | ||||
|         # queries: ./path/to/local/query, your-org/your-repo/queries@main | ||||
|  | ||||
|     # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java). | ||||
|     # If this step fails, then you should remove it and run the build manually (see below) | ||||
|     - name: Autobuild | ||||
|       uses: github/codeql-action/autobuild@v1 | ||||
|  | ||||
|     # ℹ️ Command-line programs to run using the OS shell. | ||||
|     # 📚 https://git.io/JvXDl | ||||
|  | ||||
|     # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines | ||||
|     #    and modify them (or add more) to build your code if your project | ||||
|     #    uses a compiled language | ||||
|  | ||||
|     #- run: | | ||||
|     #   make bootstrap | ||||
|     #   make release | ||||
|  | ||||
|     - name: Perform CodeQL Analysis | ||||
|       uses: github/codeql-action/analyze@v1 | ||||
							
								
								
									
										57
									
								
								.github/workflows/development.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								.github/workflows/development.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| name: Development | ||||
| on: [push, pull_request] | ||||
| jobs: | ||||
|   lint: | ||||
|     name: golangci-lint | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: actions/checkout@v2 | ||||
|         with: | ||||
|           fetch-depth: 20 | ||||
|       - name: Run golangci-lint | ||||
|         uses: golangci/golangci-lint-action@v2 | ||||
|         with: | ||||
|           version: v1.29 | ||||
|           args: "-v --new-from-rev HEAD~5" | ||||
|   test-build-upload: | ||||
|     strategy: | ||||
|       matrix: | ||||
|         go-version: [1.14.x, 1.15.x] | ||||
|         platform: [ubuntu-latest] | ||||
|     runs-on: ${{ matrix.platform }} | ||||
|     steps: | ||||
|     - name: Install Go | ||||
|       uses: actions/setup-go@v2 | ||||
|       with: | ||||
|         go-version: ${{ matrix.go-version }} | ||||
|     - name: Checkout code | ||||
|       uses: actions/checkout@v2 | ||||
|       with: | ||||
|           fetch-depth: 0 | ||||
|     - name: Test | ||||
|       run: go test ./... -mod=vendor | ||||
|     - name: Build | ||||
|       run: | | ||||
|         mkdir -p output/{win,lin,arm,mac} | ||||
|         VERSION=$(git describe --tags) | ||||
|         GOOS=linux GOARCH=amd64 go build -mod=vendor -ldflags "-s -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o output/lin/matterbridge-$VERSION-linux-amd64 | ||||
|         GOOS=windows GOARCH=amd64 go build -mod=vendor -ldflags "-s -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o output/win/matterbridge-$VERSION-windows-amd64.exe | ||||
|         GOOS=darwin GOARCH=amd64 go build -mod=vendor -ldflags "-s -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o output/mac/matterbridge-$VERSION-darwin-amd64 | ||||
|     - name: Upload linux 64-bit | ||||
|       if: startsWith(matrix.go-version,'1.15') | ||||
|       uses: actions/upload-artifact@v2 | ||||
|       with: | ||||
|         name: matterbridge-linux-64bit | ||||
|         path: output/lin | ||||
|     - name: Upload windows 64-bit | ||||
|       if: startsWith(matrix.go-version,'1.15') | ||||
|       uses: actions/upload-artifact@v2 | ||||
|       with: | ||||
|         name: matterbridge-windows-64bit | ||||
|         path: output/win | ||||
|     - name: Upload darwin 64-bit | ||||
|       if: startsWith(matrix.go-version,'1.15') | ||||
|       uses: actions/upload-artifact@v2 | ||||
|       with: | ||||
|         name: matterbridge-darwin-64bit | ||||
|         path: output/mac | ||||
| @@ -23,7 +23,7 @@ run: | ||||
|   # default value is empty list, but next dirs are always skipped independently | ||||
|   # from this option's value: | ||||
|   #   	vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ | ||||
|   skip-dirs: | ||||
|   skip-dirs: gateway/bridgemap$ | ||||
|  | ||||
|   # which files to skip: they will be analyzed, but issues from them | ||||
|   # won't be reported. Default value is empty list, but there is | ||||
| @@ -175,7 +175,14 @@ linters: | ||||
|     - maligned | ||||
|     - prealloc | ||||
|     - wsl | ||||
|  | ||||
|     - gomnd | ||||
|     - godox | ||||
|     - goerr113 | ||||
|     - testpackage | ||||
|     - godot | ||||
|     - interfacer | ||||
|     - goheader | ||||
|     - noctx | ||||
|  | ||||
| # rules to deal with reported isues | ||||
| issues: | ||||
|   | ||||
							
								
								
									
										56
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								.travis.yml
									
									
									
									
									
								
							| @@ -1,56 +0,0 @@ | ||||
| language: go | ||||
| go_import_path: github.com/42wim/matterbridge | ||||
|  | ||||
| # We have everything vendored so this helps TravisCI not run `go get ...`. | ||||
| install: true | ||||
|  | ||||
| git: | ||||
|   depth: 200 | ||||
|  | ||||
| notifications: | ||||
|   email: false | ||||
|  | ||||
| branches: | ||||
|   only: | ||||
|   - master | ||||
|   - /.*/ | ||||
|  | ||||
| jobs: | ||||
|   include: | ||||
|   - stage: lint | ||||
|     # Run linting in one Go environment only. | ||||
|     script: ./ci/lint.sh | ||||
|     go: 1.13.x | ||||
|     env: | ||||
|     - GO111MODULE=on | ||||
|     - GOLANGCI_VERSION="v1.21.0" | ||||
|   - stage: test | ||||
|     # Run tests in a combination of Go environments. | ||||
|     script: ./ci/test.sh | ||||
|     go: 1.12.x | ||||
|     env: | ||||
|     - GO111MODULE=off | ||||
|   - script: ./ci/test.sh | ||||
|     go: 1.12.x | ||||
|     env: | ||||
|     - GO111MODULE=on | ||||
|   - script: ./ci/test.sh | ||||
|     go: 1.13.x | ||||
|     env: | ||||
|     - GO111MODULE=on | ||||
|     - REPORT_COVERAGE=1 | ||||
|     - BINDEPLOY=1 | ||||
|  | ||||
| before_deploy: /bin/bash ci/bintray.sh | ||||
|  | ||||
| deploy: | ||||
|   on: | ||||
|     all_branches: true | ||||
|     condition: $BINDEPLOY = 1 | ||||
|   provider: bintray | ||||
|   edge: | ||||
|     branch: v1.8.47 | ||||
|   file: ci/deploy.json | ||||
|   user: 42wim | ||||
|   key: | ||||
|     secure: "CeXXe6JOmt7HYR81MdWLua0ltQHhDdkIeRGBFbgd7hkb1wi8eF9DgpAcQrTso8NIlHNZmSAP46uhFgsRvkuezzX0ygalZ7DCJyAyn3sAMEh+UQSHV1WGThRehTtidqRGjetzsIGSwdrJOWil+XTfbO1Z8DGzfakhSuAZka8CM4BAoe3YeP9rYK8h+84x0GHfczvsLtXZ3mWLvQuwe4pK6+ItBCUg0ae7O7ZUpWHy0xQQkkWztY/6RAzXfaG7DuGjIw+20fhx3WOXRNpHCtZ6Bc3qERCpk0s1HhlQWlrN9wDaFTBWYwlvSnNgvxxMbNXJ6RrRJ0l0bA7FUswYwyroxhzrGLdzWDg8dHaQkypocngdalfhpsnoO9j3ApJhomUFJ3UoEq5nOGRUrKn8MPi+dP0zE4kNQ3e4VNa1ufNrvfpWolMg3xh8OXuhQdD5wIM5zFAbRJLqWSCVAjPq4DDPecmvXBOlIial7oa312lN5qnBnUjvAcxszZ+FUyDHT1Grxzna4tMwxY9obPzZUzm7359AOCCwIQFVB8GLqD2nwIstcXS0zGRz+fhviPipHuBa02q5bGUZwmkvrSNab0s8Jo7pCrel2Rz3nWPKaiCfq2WjbW1CLheSMkOQrjsdUd1hhbqNWFPUjJPInTc77NAKCfm5runv5uyowRLh4NNd0sI=" | ||||
							
								
								
									
										17
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -1,11 +1,16 @@ | ||||
| FROM alpine:edge | ||||
| ENTRYPOINT ["/bin/matterbridge"] | ||||
| FROM alpine AS builder | ||||
|  | ||||
| COPY . /go/src/github.com/42wim/matterbridge | ||||
| RUN apk update && apk add go git gcc musl-dev ca-certificates \ | ||||
| RUN apk update && apk add go git gcc musl-dev \ | ||||
|         && cd /go/src/github.com/42wim/matterbridge \ | ||||
|         && export GOPATH=/go \ | ||||
|         && go get \ | ||||
|         && go build -x -ldflags "-X main.githash=$(git log --pretty=format:'%h' -n 1)" -o /bin/matterbridge \ | ||||
|         && rm -rf /go \ | ||||
|         && apk del --purge git go gcc musl-dev | ||||
|         && go build -x -ldflags "-X main.githash=$(git log --pretty=format:'%h' -n 1)" -o /bin/matterbridge | ||||
|  | ||||
| FROM alpine | ||||
| RUN apk --no-cache add ca-certificates mailcap | ||||
| COPY --from=builder /bin/matterbridge /bin/matterbridge | ||||
| RUN mkdir /etc/matterbridge \ | ||||
|   && touch /etc/matterbridge/matterbridge.toml \ | ||||
|   && ln -sf /matterbridge.toml /etc/matterbridge/matterbridge.toml | ||||
| ENTRYPOINT ["/bin/matterbridge", "-conf", "/etc/matterbridge/matterbridge.toml"] | ||||
|   | ||||
							
								
								
									
										192
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										192
									
								
								README.md
									
									
									
									
									
								
							| @@ -9,26 +9,26 @@ Letting people be where they want to be.<br /> | ||||
|  | ||||
|    <sup> | ||||
|  | ||||
| [Discord][mb-discord] | | ||||
| [Gitter][mb-gitter] | | ||||
| [IRC][mb-irc] | | ||||
| [Discord][mb-discord] | | ||||
| [Keybase][mb-keybase] | | ||||
| [Matrix][mb-matrix] | | ||||
| [Slack][mb-slack] | | ||||
| [Mattermost][mb-mattermost] | | ||||
| [MSTeams][mb-msteams] | | ||||
| [Rocket.Chat][mb-rocketchat] | | ||||
| [XMPP][mb-xmpp] | | ||||
| [Slack][mb-slack] | | ||||
| [Telegram][mb-telegram] | | ||||
| [Twitch][mb-twitch] | | ||||
| [WhatsApp][mb-whatsapp] | | ||||
| [XMPP][mb-xmpp] | | ||||
| [Zulip][mb-zulip] | | ||||
| [Telegram][mb-telegram] | | ||||
| [Keybase][mb-keybase] | | ||||
| And more... | ||||
| </sup> | ||||
|  | ||||
| --- | ||||
|  | ||||
| [](https://github.com/42wim/matterbridge/releases/latest) | ||||
| [](https://bintray.com/42wim/nightly/Matterbridge/_latestVersion) | ||||
| [](https://codeclimate.com/github/42wim/matterbridge/maintainability) | ||||
| [](https://codeclimate.com/github/42wim/matterbridge/test_coverage)<br /> | ||||
|  | ||||
| @@ -44,28 +44,34 @@ And more... | ||||
|   </a> | ||||
| </p> | ||||
|  | ||||
| ### Table of Contents | ||||
| # Table of Contents | ||||
|  | ||||
| - [Features](https://github.com/42wim/matterbridge/wiki/Features) | ||||
|   - [Natively supported](#natively-supported) | ||||
|   - [3rd party via matterbridge api](#3rd-party-via-matterbridge-api) | ||||
|   - [API](#API) | ||||
| - [Chat with us](#chat-with-us) | ||||
| - [Screenshots](https://github.com/42wim/matterbridge/wiki/) | ||||
| - [Installing/upgrading](#installing--upgrading) | ||||
|   - [Binaries](#binaries) | ||||
| - [Building](#building) | ||||
| - [Configuration](#configuration) | ||||
|   - [Howto](https://github.com/42wim/matterbridge/wiki/How-to-create-your-config) | ||||
|   - [Settings](#settings) | ||||
|   - [Examples](#examples) | ||||
| - [Running](#running) | ||||
|   - [Docker](#docker) | ||||
| - [Changelog](#changelog) | ||||
| - [FAQ](#faq) | ||||
| - [Related projects](#related-projects) | ||||
| - [Articles](#articles) | ||||
| - [Thanks](#thanks) | ||||
| - [matterbridge](#matterbridge) | ||||
| - [Table of Contents](#table-of-contents) | ||||
|   - [Features](#features) | ||||
|     - [Natively supported](#natively-supported) | ||||
|     - [3rd party via matterbridge api](#3rd-party-via-matterbridge-api) | ||||
|     - [API](#api) | ||||
|   - [Chat with us](#chat-with-us) | ||||
|   - [Screenshots](#screenshots) | ||||
|   - [Installing / upgrading](#installing--upgrading) | ||||
|     - [Binaries](#binaries) | ||||
|     - [Packages](#packages) | ||||
|   - [Building](#building) | ||||
|   - [Configuration](#configuration) | ||||
|     - [Basic configuration](#basic-configuration) | ||||
|     - [Settings](#settings) | ||||
|     - [Advanced configuration](#advanced-configuration) | ||||
|     - [Examples](#examples) | ||||
|       - [Bridge mattermost (off-topic) - irc (#testing)](#bridge-mattermost-off-topic---irc-testing) | ||||
|       - [Bridge slack (#general) - discord (general)](#bridge-slack-general---discord-general) | ||||
|   - [Running](#running) | ||||
|     - [Docker](#docker) | ||||
|   - [Changelog](#changelog) | ||||
|   - [FAQ](#faq) | ||||
|   - [Related projects](#related-projects) | ||||
|   - [Articles](#articles) | ||||
|   - [Thanks](#thanks) | ||||
|  | ||||
| ## Features | ||||
|  | ||||
| @@ -80,29 +86,33 @@ And more... | ||||
|  | ||||
| ### Natively supported | ||||
|  | ||||
| - [Mattermost](https://github.com/mattermost/mattermost-server/) 4.x, 5.x | ||||
| - [IRC](http://www.mirc.com/servers.html) | ||||
| - [XMPP](https://xmpp.org) | ||||
| - [Gitter](https://gitter.im) | ||||
| - [Slack](https://slack.com) | ||||
| - [Discord](https://discordapp.com) | ||||
| - [Telegram](https://telegram.org) | ||||
| - [Rocket.chat](https://rocket.chat) | ||||
| - [Matrix](https://matrix.org) | ||||
| - [Steam](https://store.steampowered.com/) | ||||
| - [Twitch](https://twitch.tv) | ||||
| - [Ssh-chat](https://github.com/shazow/ssh-chat) | ||||
| - [WhatsApp](https://www.whatsapp.com/) | ||||
| - [Zulip](https://zulipchat.com) | ||||
| - [Gitter](https://gitter.im) | ||||
| - [IRC](http://www.mirc.com/servers.html) | ||||
| - [Keybase](https://keybase.io) | ||||
| - [Matrix](https://matrix.org) | ||||
| - [Mattermost](https://github.com/mattermost/mattermost-server/) 4.x, 5.x | ||||
| - [Microsoft Teams](https://teams.microsoft.com) | ||||
| - [Mumble](https://www.mumble.info/) | ||||
| - [Nextcloud Talk](https://nextcloud.com/talk/) | ||||
| - [Rocket.chat](https://rocket.chat) | ||||
| - [Slack](https://slack.com) | ||||
| - [Ssh-chat](https://github.com/shazow/ssh-chat) | ||||
| - [Steam](https://store.steampowered.com/) | ||||
| - [Telegram](https://telegram.org) | ||||
| - [Twitch](https://twitch.tv) | ||||
| - [WhatsApp](https://www.whatsapp.com/) | ||||
| - [XMPP](https://xmpp.org) | ||||
| - [Zulip](https://zulipchat.com) | ||||
|  | ||||
| ### 3rd party via matterbridge api | ||||
|  | ||||
| - [Discourse](https://github.com/DeclanHoare/matterbabble) | ||||
| - [Facebook messenger](https://github.com/VictorNine/fbridge) | ||||
| - [Minecraft](https://github.com/elytra/MatterLink) | ||||
| - [Reddit](https://github.com/bonehurtingjuice/mattereddit) | ||||
| - [Facebook messenger](https://github.com/VictorNine/fbridge) | ||||
| - [Discourse](https://github.com/DeclanHoare/matterbabble) | ||||
| - [Counter-Strike, half-life and more](https://forums.alliedmods.net/showthread.php?t=319430) | ||||
| - [MatterAMXX](https://github.com/GabeIggy/MatterAMXX) | ||||
|  | ||||
| ### API | ||||
|  | ||||
| @@ -122,34 +132,36 @@ Used by the projects below. Feel free to make a PR to add your project to this l | ||||
|  | ||||
| Questions or want to test on your favorite platform? Join below: | ||||
|  | ||||
| - [Discord][mb-discord] | ||||
| - [Gitter][mb-gitter] | ||||
| - [IRC][mb-irc] | ||||
| - [Discord][mb-discord] | ||||
| - [Keybase][mb-keybase] | ||||
| - [Matrix][mb-matrix] | ||||
| - [Slack][mb-slack] | ||||
| - [Mattermost][mb-mattermost] | ||||
| - [Rocket.Chat][mb-rocketchat] | ||||
| - [XMPP][mb-xmpp] (matterbridge@conference.jabber.de) | ||||
| - [Twitch][mb-twitch] | ||||
| - [Zulip][mb-zulip] | ||||
| - [Slack][mb-slack] | ||||
| - [Telegram][mb-telegram] | ||||
| - [Twitch][mb-twitch] | ||||
| - [XMPP][mb-xmpp] (matterbridge@conference.jabber.de) | ||||
| - [Zulip][mb-zulip] | ||||
|  | ||||
| ## Screenshots | ||||
|  | ||||
| See https://github.com/42wim/matterbridge/wiki | ||||
| See <https://github.com/42wim/matterbridge/wiki> | ||||
|  | ||||
| ## Installing / upgrading | ||||
|  | ||||
| ### Binaries | ||||
|  | ||||
| - Latest stable release [v1.16.3](https://github.com/42wim/matterbridge/releases/latest) | ||||
| - Development releases (follows master) can be downloaded [here](https://dl.bintray.com/42wim/nightly/) | ||||
| - Latest stable release [v1.20.0](https://github.com/42wim/matterbridge/releases/latest) | ||||
| - Development releases (follows master) can be downloaded [here](https://github.com/42wim/matterbridge/actions) selecting the latest green build and then artifacts. | ||||
|  | ||||
| To install or upgrade just download the latest [binary](https://github.com/42wim/matterbridge/releases/latest) and follow the instructions on the [howto](https://github.com/42wim/matterbridge/wiki/How-to-create-your-config) for a step by step walkthrough for creating your configuration. | ||||
|  | ||||
| ### Packages | ||||
|  | ||||
| - [Overview](https://repology.org/metapackage/matterbridge/versions) | ||||
| - [snap](https://snapcraft.io/matterbridge) | ||||
|  | ||||
| ## Building | ||||
|  | ||||
| @@ -158,14 +170,13 @@ Most people just want to use binaries, you can find those [here](https://github. | ||||
| If you really want to build from source, follow these instructions: | ||||
| Go 1.12+ is required. Make sure you have [Go](https://golang.org/doc/install) properly installed. | ||||
|  | ||||
|  | ||||
| ``` | ||||
| ```bash | ||||
| go get github.com/42wim/matterbridge | ||||
| ``` | ||||
|  | ||||
| You should now have matterbridge binary in the ~/go/bin directory: | ||||
|  | ||||
| ``` | ||||
| ```bash | ||||
| $ ls ~/go/bin/ | ||||
| matterbridge | ||||
| ``` | ||||
| @@ -248,7 +259,7 @@ RemoteNickFormat="[{PROTOCOL}/{BRIDGE}] <{NICK}> " | ||||
|  | ||||
| See [howto](https://github.com/42wim/matterbridge/wiki/How-to-create-your-config) for a step by step walkthrough for creating your configuration. | ||||
|  | ||||
| ``` | ||||
| ```bash | ||||
| Usage of ./matterbridge: | ||||
|   -conf string | ||||
|         config file (default "matterbridge.toml") | ||||
| @@ -262,11 +273,7 @@ Usage of ./matterbridge: | ||||
|  | ||||
| ### Docker | ||||
|  | ||||
| Create your matterbridge.toml file locally eg in `/tmp/matterbridge.toml` | ||||
|  | ||||
| ``` | ||||
| docker run -ti -v /tmp/matterbridge.toml:/matterbridge.toml 42wim/matterbridge | ||||
| ``` | ||||
| Please take a look at the [Docker Wiki page](https://github.com/42wim/matterbridge/wiki/Deploy:-Docker) for more information. | ||||
|  | ||||
| ## Changelog | ||||
|  | ||||
| @@ -278,7 +285,7 @@ See [FAQ](https://github.com/42wim/matterbridge/wiki/FAQ) | ||||
|  | ||||
| ## Related projects | ||||
|  | ||||
| - [FOSSRIT/infrastructure - roles/matterbridge](https://github.com/FOSSRIT/infrastructure/tree/master/roles/matterbridge) (Ansible role used to automate deployments of Matterbridge) | ||||
| - [jwflory/ansible-role-matterbridge](https://galaxy.ansible.com/jwflory/matterbridge) (Ansible role to simplify deploying Matterbridge) | ||||
| - [matterbridge autoconfig](https://github.com/patcon/matterbridge-autoconfig) | ||||
| - [matterbridge config viewer](https://github.com/patcon/matterbridge-heroku-viewer) | ||||
| - [matterbridge-heroku](https://github.com/cadecairos/matterbridge-heroku) | ||||
| @@ -293,14 +300,14 @@ See [FAQ](https://github.com/42wim/matterbridge/wiki/FAQ) | ||||
| ## Articles | ||||
|  | ||||
| - [matterbridge on kubernetes](https://medium.freecodecamp.org/using-kubernetes-to-deploy-a-chat-gateway-or-when-technology-works-like-its-supposed-to-a169a8cd69a3) | ||||
| - https://mattermost.com/blog/connect-irc-to-mattermost/ | ||||
| - https://blog.valvin.fr/2016/09/17/mattermost-et-un-channel-irc-cest-possible/ | ||||
| - https://blog.brightscout.com/top-10-mattermost-integrations/ | ||||
| - http://bencey.co.nz/2018/09/17/bridge/ | ||||
| - https://www.algoo.fr/blog/2018/01/19/recouvrez-votre-liberte-en-quittant-slack-pour-un-mattermost-auto-heberge/ | ||||
| - https://kopano.com/blog/matterbridge-bridging-mattermost-chat/ | ||||
| - https://www.stitcher.com/s/?eid=52382713 | ||||
| - https://daniele.tech/2019/02/how-to-use-matterbridge-to-connect-2-different-slack-workspaces/ | ||||
| - <https://mattermost.com/blog/connect-irc-to-mattermost/> | ||||
| - <https://blog.valvin.fr/2016/09/17/mattermost-et-un-channel-irc-cest-possible/> | ||||
| - <https://blog.brightscout.com/top-10-mattermost-integrations/> | ||||
| - <https://www.algoo.fr/blog/2018/01/19/recouvrez-votre-liberte-en-quittant-slack-pour-un-mattermost-auto-heberge/> | ||||
| - <https://kopano.com/blog/matterbridge-bridging-mattermost-chat/> | ||||
| - <https://www.stitcher.com/s/?eid=52382713> | ||||
| - <https://daniele.tech/2019/02/how-to-use-matterbridge-to-connect-2-different-slack-workspaces/> | ||||
| - <https://userlinux.net/mattermost-and-matterbridge.html> | ||||
|  | ||||
| ## Thanks | ||||
|  | ||||
| @@ -313,36 +320,41 @@ See [FAQ](https://github.com/42wim/matterbridge/wiki/FAQ) | ||||
|  | ||||
| Matterbridge wouldn't exist without these libraries: | ||||
|  | ||||
| - discord - https://github.com/bwmarrin/discordgo | ||||
| - echo - https://github.com/labstack/echo | ||||
| - gitter - https://github.com/sromku/go-gitter | ||||
| - gops - https://github.com/google/gops | ||||
| - gozulipbot - https://github.com/ifo/gozulipbot | ||||
| - irc - https://github.com/lrstanley/girc | ||||
| - mattermost - https://github.com/mattermost/mattermost-server | ||||
| - matrix - https://github.com/matrix-org/gomatrix | ||||
| - sshchat - https://github.com/shazow/ssh-chat | ||||
| - slack - https://github.com/nlopes/slack | ||||
| - steam - https://github.com/Philipp15b/go-steam | ||||
| - telegram - https://github.com/go-telegram-bot-api/telegram-bot-api | ||||
| - xmpp - https://github.com/mattn/go-xmpp | ||||
| - whatsapp - https://github.com/Rhymen/go-whatsapp/ | ||||
| - zulip - https://github.com/ifo/gozulipbot | ||||
| - tengo - https://github.com/d5/tengo | ||||
| - keybase - https://github.com/keybase/go-keybase-chat-bot | ||||
| - discord - <https://github.com/bwmarrin/discordgo> | ||||
| - echo - <https://github.com/labstack/echo> | ||||
| - gitter - <https://github.com/sromku/go-gitter> | ||||
| - gops - <https://github.com/google/gops> | ||||
| - gozulipbot - <https://github.com/ifo/gozulipbot> | ||||
| - gumble - <https://github.com/layeh/gumble> | ||||
| - irc - <https://github.com/lrstanley/girc> | ||||
| - keybase - <https://github.com/keybase/go-keybase-chat-bot> | ||||
| - matrix - <https://github.com/matrix-org/gomatrix> | ||||
| - mattermost - <https://github.com/mattermost/mattermost-server> | ||||
| - msgraph.go - <https://github.com/yaegashi/msgraph.go> | ||||
| - mumble - <https://github.com/layeh/gumble> | ||||
| - nctalk - <https://github.com/gary-kim/go-nc-talk> | ||||
| - slack - <https://github.com/nlopes/slack> | ||||
| - sshchat - <https://github.com/shazow/ssh-chat> | ||||
| - steam - <https://github.com/Philipp15b/go-steam> | ||||
| - telegram - <https://github.com/go-telegram-bot-api/telegram-bot-api> | ||||
| - tengo - <https://github.com/d5/tengo> | ||||
| - whatsapp - <https://github.com/Rhymen/go-whatsapp> | ||||
| - xmpp - <https://github.com/mattn/go-xmpp> | ||||
| - zulip - <https://github.com/ifo/gozulipbot> | ||||
|  | ||||
| <!-- Links --> | ||||
|  | ||||
| [mb-discord]: https://discord.gg/AkKPtrQ | ||||
| [mb-gitter]: https://gitter.im/42wim/matterbridge | ||||
| [mb-irc]: https://webchat.freenode.net/?channels=matterbridgechat | ||||
| [mb-discord]: https://discord.gg/AkKPtrQ | ||||
| [mb-keybase]: https://keybase.io/team/matterbridge | ||||
| [mb-matrix]: https://riot.im/app/#/room/#matterbridge:matrix.org | ||||
| [mb-slack]: https://join.slack.com/matterbridgechat/shared_invite/MjEwODMxNjU1NDMwLTE0OTk2MTU3NTMtMzZkZmRiNDZhOA | ||||
| [mb-mattermost]: https://framateam.org/signup_user_complete/?id=tfqm33ggop8x3qgu4boeieta6e | ||||
| [mb-msteams]: https://teams.microsoft.com/join/hj92x75gd3y7 | ||||
| [mb-rocketchat]: https://open.rocket.chat/channel/matterbridge | ||||
| [mb-xmpp]: https://inverse.chat/ | ||||
| [mb-slack]: https://join.slack.com/t/matterbridgechat/shared_invite/zt-2ourq2h2-7YvyYBq2WFGC~~zEzA68_Q | ||||
| [mb-telegram]: https://t.me/Matterbridge | ||||
| [mb-twitch]: https://www.twitch.tv/matterbridge | ||||
| [mb-whatsapp]: https://www.whatsapp.com/ | ||||
| [mb-keybase]: https://keybase.io | ||||
| [mb-xmpp]: https://inverse.chat/ | ||||
| [mb-zulip]: https://matterbridge.zulipchat.com/register/ | ||||
| [mb-telegram]: https://t.me/Matterbridge | ||||
|   | ||||
| @@ -6,17 +6,20 @@ import ( | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"gopkg.in/olahol/melody.v1" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge" | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/labstack/echo/v4" | ||||
| 	"github.com/labstack/echo/v4/middleware" | ||||
| 	"github.com/zfjagann/golang-ring" | ||||
| 	ring "github.com/zfjagann/golang-ring" | ||||
| ) | ||||
|  | ||||
| type API struct { | ||||
| 	Messages ring.Ring | ||||
| 	sync.RWMutex | ||||
| 	*bridge.Config | ||||
| 	mrouter *melody.Melody | ||||
| } | ||||
|  | ||||
| type Message struct { | ||||
| @@ -32,6 +35,32 @@ func New(cfg *bridge.Config) bridge.Bridger { | ||||
| 	e := echo.New() | ||||
| 	e.HideBanner = true | ||||
| 	e.HidePort = true | ||||
|  | ||||
| 	b.mrouter = melody.New() | ||||
| 	b.mrouter.HandleMessage(func(s *melody.Session, msg []byte) { | ||||
| 		message := config.Message{} | ||||
| 		err := json.Unmarshal(msg, &message) | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("failed to decode message from byte[] '%s'", string(msg)) | ||||
| 			return | ||||
| 		} | ||||
| 		b.handleWebsocketMessage(message, s) | ||||
| 	}) | ||||
| 	b.mrouter.HandleConnect(func(session *melody.Session) { | ||||
| 		greet := b.getGreeting() | ||||
| 		data, err := json.Marshal(greet) | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("failed to encode message '%v'", greet) | ||||
| 			return | ||||
| 		} | ||||
| 		err = session.Write(data) | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("failed to write message '%s'", string(data)) | ||||
| 			return | ||||
| 		} | ||||
| 		// TODO: send message history buffer from `b.Messages` here | ||||
| 	}) | ||||
|  | ||||
| 	b.Messages = ring.Ring{} | ||||
| 	if b.GetInt("Buffer") != 0 { | ||||
| 		b.Messages.SetCapacity(b.GetInt("Buffer")) | ||||
| @@ -41,9 +70,17 @@ func New(cfg *bridge.Config) bridge.Bridger { | ||||
| 			return key == b.GetString("Token"), nil | ||||
| 		})) | ||||
| 	} | ||||
|  | ||||
| 	// Set RemoteNickFormat to a sane default | ||||
| 	if !b.IsKeySet("RemoteNickFormat") { | ||||
| 		b.Log.Debugln("RemoteNickFormat is unset, defaulting to \"{NICK}\"") | ||||
| 		b.Config.Config.Viper().Set(b.GetConfigKey("RemoteNickFormat"), "{NICK}") | ||||
| 	} | ||||
|  | ||||
| 	e.GET("/api/health", b.handleHealthcheck) | ||||
| 	e.GET("/api/messages", b.handleMessages) | ||||
| 	e.GET("/api/stream", b.handleStream) | ||||
| 	e.GET("/api/websocket", b.handleWebsocket) | ||||
| 	e.POST("/api/message", b.handlePostMessage) | ||||
| 	go func() { | ||||
| 		if b.GetString("BindAddress") == "" { | ||||
| @@ -58,13 +95,13 @@ func New(cfg *bridge.Config) bridge.Bridger { | ||||
| func (b *API) Connect() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *API) Disconnect() error { | ||||
| 	return nil | ||||
|  | ||||
| } | ||||
|  | ||||
| func (b *API) JoinChannel(channel config.ChannelInfo) error { | ||||
| 	return nil | ||||
|  | ||||
| } | ||||
|  | ||||
| func (b *API) Send(msg config.Message) (string, error) { | ||||
| @@ -74,7 +111,14 @@ func (b *API) Send(msg config.Message) (string, error) { | ||||
| 	if msg.Event == config.EventMsgDelete { | ||||
| 		return "", nil | ||||
| 	} | ||||
| 	b.Messages.Enqueue(&msg) | ||||
| 	b.Log.Debugf("enqueueing message from %s on ring buffer", msg.Username) | ||||
| 	b.Messages.Enqueue(msg) | ||||
|  | ||||
| 	data, err := json.Marshal(msg) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("failed to encode message  '%s'", msg) | ||||
| 	} | ||||
| 	_ = b.mrouter.Broadcast(data) | ||||
| 	return "", nil | ||||
| } | ||||
|  | ||||
| @@ -106,18 +150,23 @@ func (b *API) handleMessages(c echo.Context) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *API) handleStream(c echo.Context) error { | ||||
| 	c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSON) | ||||
| 	c.Response().WriteHeader(http.StatusOK) | ||||
| 	greet := config.Message{ | ||||
| func (b *API) getGreeting() config.Message { | ||||
| 	return config.Message{ | ||||
| 		Event:     config.EventAPIConnected, | ||||
| 		Timestamp: time.Now(), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *API) handleStream(c echo.Context) error { | ||||
| 	c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSON) | ||||
| 	c.Response().WriteHeader(http.StatusOK) | ||||
| 	greet := b.getGreeting() | ||||
| 	if err := json.NewEncoder(c.Response()).Encode(greet); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	c.Response().Flush() | ||||
| 	for { | ||||
| 		// TODO: this causes issues, messages should be broadcasted to all connected clients | ||||
| 		msg := b.Messages.Dequeue() | ||||
| 		if msg != nil { | ||||
| 			if err := json.NewEncoder(c.Response()).Encode(msg); err != nil { | ||||
| @@ -128,3 +177,31 @@ func (b *API) handleStream(c echo.Context) error { | ||||
| 		time.Sleep(200 * time.Millisecond) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *API) handleWebsocketMessage(message config.Message, s *melody.Session) { | ||||
| 	message.Channel = "api" | ||||
| 	message.Protocol = "api" | ||||
| 	message.Account = b.Account | ||||
| 	message.ID = "" | ||||
| 	message.Timestamp = time.Now() | ||||
|  | ||||
| 	data, err := json.Marshal(message) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("failed to encode message for loopback '%v'", message) | ||||
| 		return | ||||
| 	} | ||||
| 	_ = b.mrouter.BroadcastOthers(data, s) | ||||
|  | ||||
| 	b.Log.Debugf("Sending websocket message from %s on %s to gateway", message.Username, "api") | ||||
| 	b.Remote <- message | ||||
| } | ||||
|  | ||||
| func (b *API) handleWebsocket(c echo.Context) error { | ||||
| 	err := b.mrouter.HandleRequest(c.Response(), c.Request()) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("error in websocket handling  '%v'", err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,10 @@ | ||||
| package bridge | ||||
|  | ||||
| import ( | ||||
| 	"log" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| @@ -41,6 +43,10 @@ type Factory func(*Config) Bridger | ||||
|  | ||||
| func New(bridge *config.Bridge) *Bridge { | ||||
| 	accInfo := strings.Split(bridge.Account, ".") | ||||
| 	if len(accInfo) != 2 { | ||||
| 		log.Fatalf("config failure, account incorrect: %s", bridge.Account) | ||||
| 	} | ||||
|  | ||||
| 	protocol := accInfo[0] | ||||
| 	name := accInfo[1] | ||||
|  | ||||
| @@ -69,6 +75,7 @@ func (b *Bridge) joinChannels(channels map[string]config.ChannelInfo, exists map | ||||
| 	for ID, channel := range channels { | ||||
| 		if !exists[ID] { | ||||
| 			b.Log.Infof("%s: joining %s (ID: %s)", b.Account, channel.Name, ID) | ||||
| 			time.Sleep(time.Duration(b.GetInt("JoinDelay")) * time.Millisecond) | ||||
| 			err := b.JoinChannel(channel) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| @@ -79,8 +86,16 @@ func (b *Bridge) joinChannels(channels map[string]config.ChannelInfo, exists map | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Bridge) GetConfigKey(key string) string { | ||||
| 	return b.Account + "." + key | ||||
| } | ||||
|  | ||||
| func (b *Bridge) IsKeySet(key string) bool { | ||||
| 	return b.Config.IsKeySet(b.GetConfigKey(key)) || b.Config.IsKeySet("general."+key) | ||||
| } | ||||
|  | ||||
| func (b *Bridge) GetBool(key string) bool { | ||||
| 	val, ok := b.Config.GetBool(b.Account + "." + key) | ||||
| 	val, ok := b.Config.GetBool(b.GetConfigKey(key)) | ||||
| 	if !ok { | ||||
| 		val, _ = b.Config.GetBool("general." + key) | ||||
| 	} | ||||
| @@ -88,7 +103,7 @@ func (b *Bridge) GetBool(key string) bool { | ||||
| } | ||||
|  | ||||
| func (b *Bridge) GetInt(key string) int { | ||||
| 	val, ok := b.Config.GetInt(b.Account + "." + key) | ||||
| 	val, ok := b.Config.GetInt(b.GetConfigKey(key)) | ||||
| 	if !ok { | ||||
| 		val, _ = b.Config.GetInt("general." + key) | ||||
| 	} | ||||
| @@ -96,7 +111,7 @@ func (b *Bridge) GetInt(key string) int { | ||||
| } | ||||
|  | ||||
| func (b *Bridge) GetString(key string) string { | ||||
| 	val, ok := b.Config.GetString(b.Account + "." + key) | ||||
| 	val, ok := b.Config.GetString(b.GetConfigKey(key)) | ||||
| 	if !ok { | ||||
| 		val, _ = b.Config.GetString("general." + key) | ||||
| 	} | ||||
| @@ -104,7 +119,7 @@ func (b *Bridge) GetString(key string) string { | ||||
| } | ||||
|  | ||||
| func (b *Bridge) GetStringSlice(key string) []string { | ||||
| 	val, ok := b.Config.GetStringSlice(b.Account + "." + key) | ||||
| 	val, ok := b.Config.GetStringSlice(b.GetConfigKey(key)) | ||||
| 	if !ok { | ||||
| 		val, _ = b.Config.GetStringSlice("general." + key) | ||||
| 	} | ||||
| @@ -112,7 +127,7 @@ func (b *Bridge) GetStringSlice(key string) []string { | ||||
| } | ||||
|  | ||||
| func (b *Bridge) GetStringSlice2D(key string) [][]string { | ||||
| 	val, ok := b.Config.GetStringSlice2D(b.Account + "." + key) | ||||
| 	val, ok := b.Config.GetStringSlice2D(b.GetConfigKey(key)) | ||||
| 	if !ok { | ||||
| 		val, _ = b.Config.GetStringSlice2D("general." + key) | ||||
| 	} | ||||
|   | ||||
| @@ -3,6 +3,8 @@ package config | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 	"time" | ||||
| @@ -76,23 +78,29 @@ type Protocol struct { | ||||
| 	BindAddress            string // mattermost, slack // DEPRECATED | ||||
| 	Buffer                 int    // api | ||||
| 	Charset                string // irc | ||||
| 	ClientID               string // msteams | ||||
| 	ColorNicks             bool   // only irc for now | ||||
| 	Debug                  bool   // general | ||||
| 	DebugLevel             int    // only for irc now | ||||
| 	DisableWebPagePreview  bool   // telegram | ||||
| 	EditSuffix             string // mattermost, slack, discord, telegram, gitter | ||||
| 	EditDisable            bool   // mattermost, slack, discord, telegram, gitter | ||||
| 	HTMLDisable            bool   // matrix | ||||
| 	IconURL                string // mattermost, slack | ||||
| 	IgnoreFailureOnStart   bool   // general | ||||
| 	IgnoreNicks            string // all protocols | ||||
| 	IgnoreMessages         string // all protocols | ||||
| 	Jid                    string // xmpp | ||||
| 	JoinDelay              string // all protocols | ||||
| 	Label                  string // all protocols | ||||
| 	Login                  string // mattermost, matrix | ||||
| 	LogFile                string // general | ||||
| 	MediaDownloadBlackList []string | ||||
| 	MediaDownloadPath      string // Basically MediaServerUpload, but instead of uploading it, just write it to a file on the same server. | ||||
| 	MediaDownloadSize      int    // all protocols | ||||
| 	MediaServerDownload    string | ||||
| 	MediaServerUpload      string | ||||
| 	MediaConvertTgs        string     // telegram | ||||
| 	MediaConvertWebPToPNG  bool       // telegram | ||||
| 	MessageDelay           int        // IRC, time in millisecond to wait between messages | ||||
| 	MessageFormat          string     // telegram | ||||
| @@ -109,19 +117,21 @@ type Protocol struct { | ||||
| 	NicksPerRow            int        // mattermost, slack | ||||
| 	NoHomeServerSuffix     bool       // matrix | ||||
| 	NoSendJoinPart         bool       // all protocols | ||||
| 	NoTLS                  bool       // mattermost | ||||
| 	NoTLS                  bool       // mattermost, xmpp | ||||
| 	Password               string     // IRC,mattermost,XMPP,matrix | ||||
| 	PrefixMessagesWithNick bool       // mattemost, slack | ||||
| 	PreserveThreading      bool       // slack | ||||
| 	Protocol               string     // all protocols | ||||
| 	QuoteDisable           bool       // telegram | ||||
| 	QuoteFormat            string     // telegram | ||||
| 	QuoteLengthLimit       int        // telegram | ||||
| 	RejoinDelay            int        // IRC | ||||
| 	ReplaceMessages        [][]string // all protocols | ||||
| 	ReplaceNicks           [][]string // all protocols | ||||
| 	RemoteNickFormat       string     // all protocols | ||||
| 	RunCommands            []string   // IRC | ||||
| 	Server                 string     // IRC,mattermost,XMPP,discord | ||||
| 	SessionFile            string     // msteams,whatsapp | ||||
| 	ShowJoinPart           bool       // all protocols | ||||
| 	ShowTopicChange        bool       // slack | ||||
| 	ShowUserTyping         bool       // slack | ||||
| @@ -129,18 +139,22 @@ type Protocol struct { | ||||
| 	SkipTLSVerify          bool       // IRC, mattermost | ||||
| 	SkipVersionCheck       bool       // mattermost | ||||
| 	StripNick              bool       // all protocols | ||||
| 	StripMarkdown          bool       // irc | ||||
| 	SyncTopic              bool       // slack | ||||
| 	TengoModifyMessage     string     // general | ||||
| 	Team                   string     // mattermost, keybase | ||||
| 	TeamID                 string     // msteams | ||||
| 	TenantID               string     // msteams | ||||
| 	Token                  string     // gitter, slack, discord, api | ||||
| 	Topic                  string     // zulip | ||||
| 	URL                    string     // mattermost, slack // DEPRECATED | ||||
| 	UseAPI                 bool       // mattermost, slack | ||||
| 	UseLocalAvatar         []string   // discord | ||||
| 	UseSASL                bool       // IRC | ||||
| 	UseTLS                 bool       // IRC | ||||
| 	UseDiscriminator       bool       // discord | ||||
| 	UseFirstName           bool       // telegram | ||||
| 	UseUserName            bool       // discord | ||||
| 	UseUserName            bool       // discord, matrix | ||||
| 	UseInsecureURL         bool       // telegram | ||||
| 	VerboseJoinPart        bool       // IRC | ||||
| 	WebhookBindAddress     string     // mattermost, slack | ||||
| @@ -199,6 +213,7 @@ type BridgeValues struct { | ||||
| 	WhatsApp           map[string]Protocol // TODO is this struct used? Search for "SlackLegacy" for example didn't return any results | ||||
| 	Zulip              map[string]Protocol | ||||
| 	Keybase            map[string]Protocol | ||||
| 	Mumble             map[string]Protocol | ||||
| 	General            Protocol | ||||
| 	Tengo              Tengo | ||||
| 	Gateway            []Gateway | ||||
| @@ -208,6 +223,7 @@ type BridgeValues struct { | ||||
| type Config interface { | ||||
| 	Viper() *viper.Viper | ||||
| 	BridgeValues() *BridgeValues | ||||
| 	IsKeySet(key string) bool | ||||
| 	GetBool(key string) (bool, bool) | ||||
| 	GetInt(key string) (int, bool) | ||||
| 	GetString(key string) (string, bool) | ||||
| @@ -233,7 +249,17 @@ func NewConfig(rootLogger *logrus.Logger, cfgfile string) Config { | ||||
| 		logger.Fatalf("Failed to read configuration file: %#v", err) | ||||
| 	} | ||||
|  | ||||
| 	mycfg := newConfigFromString(logger, input) | ||||
| 	cfgtype := detectConfigType(cfgfile) | ||||
| 	mycfg := newConfigFromString(logger, input, cfgtype) | ||||
| 	if mycfg.cv.General.LogFile != "" { | ||||
| 		logfile, err := os.OpenFile(mycfg.cv.General.LogFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) | ||||
| 		if err == nil { | ||||
| 			logger.Info("Opening log file ", mycfg.cv.General.LogFile) | ||||
| 			rootLogger.Out = logfile | ||||
| 		} else { | ||||
| 			logger.Warn("Failed to open ", mycfg.cv.General.LogFile) | ||||
| 		} | ||||
| 	} | ||||
| 	if mycfg.cv.General.MediaDownloadSize == 0 { | ||||
| 		mycfg.cv.General.MediaDownloadSize = 1000000 | ||||
| 	} | ||||
| @@ -244,14 +270,26 @@ func NewConfig(rootLogger *logrus.Logger, cfgfile string) Config { | ||||
| 	return mycfg | ||||
| } | ||||
|  | ||||
| // detectConfigType detects JSON and YAML formats, defaults to TOML. | ||||
| func detectConfigType(cfgfile string) string { | ||||
| 	fileExt := filepath.Ext(cfgfile) | ||||
| 	switch fileExt { | ||||
| 	case ".json": | ||||
| 		return "json" | ||||
| 	case ".yaml", ".yml": | ||||
| 		return "yaml" | ||||
| 	} | ||||
| 	return "toml" | ||||
| } | ||||
|  | ||||
| // NewConfigFromString instantiates a new configuration based on the specified string. | ||||
| func NewConfigFromString(rootLogger *logrus.Logger, input []byte) Config { | ||||
| 	logger := rootLogger.WithFields(logrus.Fields{"prefix": "config"}) | ||||
| 	return newConfigFromString(logger, input) | ||||
| 	return newConfigFromString(logger, input, "toml") | ||||
| } | ||||
|  | ||||
| func newConfigFromString(logger *logrus.Entry, input []byte) *config { | ||||
| 	viper.SetConfigType("toml") | ||||
| func newConfigFromString(logger *logrus.Entry, input []byte, cfgtype string) *config { | ||||
| 	viper.SetConfigType(cfgtype) | ||||
| 	viper.SetEnvPrefix("matterbridge") | ||||
| 	viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_")) | ||||
| 	viper.AutomaticEnv() | ||||
| @@ -279,6 +317,12 @@ func (c *config) Viper() *viper.Viper { | ||||
| 	return c.v | ||||
| } | ||||
|  | ||||
| func (c *config) IsKeySet(key string) bool { | ||||
| 	c.RLock() | ||||
| 	defer c.RUnlock() | ||||
| 	return c.v.IsSet(key) | ||||
| } | ||||
|  | ||||
| func (c *config) GetBool(key string) (bool, bool) { | ||||
| 	c.RLock() | ||||
| 	defer c.RUnlock() | ||||
| @@ -338,6 +382,11 @@ type TestConfig struct { | ||||
| 	Overrides map[string]interface{} | ||||
| } | ||||
|  | ||||
| func (c *TestConfig) IsKeySet(key string) bool { | ||||
| 	_, ok := c.Overrides[key] | ||||
| 	return ok || c.Config.IsKeySet(key) | ||||
| } | ||||
|  | ||||
| func (c *TestConfig) GetBool(key string) (bool, bool) { | ||||
| 	val, ok := c.Overrides[key] | ||||
| 	if ok { | ||||
|   | ||||
| @@ -10,7 +10,7 @@ import ( | ||||
| 	"github.com/42wim/matterbridge/bridge" | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/42wim/matterbridge/bridge/helper" | ||||
| 	"github.com/bwmarrin/discordgo" | ||||
| 	"github.com/matterbridge/discordgo" | ||||
| ) | ||||
|  | ||||
| const MessageLength = 1950 | ||||
| @@ -21,7 +21,7 @@ type Bdiscord struct { | ||||
| 	c *discordgo.Session | ||||
|  | ||||
| 	nick            string | ||||
| 	useChannelID    bool | ||||
| 	userID          string | ||||
| 	guildID         string | ||||
| 	webhookID       string | ||||
| 	webhookToken    string | ||||
| @@ -93,6 +93,7 @@ func (b *Bdiscord) Connect() error { | ||||
| 	} | ||||
| 	serverName := strings.Replace(b.GetString("Server"), "ID:", "", -1) | ||||
| 	b.nick = userinfo.Username | ||||
| 	b.userID = userinfo.ID | ||||
| 	b.channelsMutex.Lock() | ||||
| 	for _, guild := range guilds { | ||||
| 		if guild.Name == serverName || guild.ID == serverName { | ||||
| @@ -115,31 +116,42 @@ func (b *Bdiscord) Connect() error { | ||||
| 			b.Log.Infof("Server=\"%s\" # Server ID", guild.ID) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	b.channelsMutex.RLock() | ||||
| 	if b.GetString("WebhookURL") == "" { | ||||
| 		for _, channel := range b.channels { | ||||
| 			b.Log.Debugf("found channel %#v", channel) | ||||
| 		} | ||||
| 	} else { | ||||
| 		b.canEditWebhooks = true | ||||
| 		for _, channel := range b.channels { | ||||
| 			b.Log.Debugf("found channel %#v; verifying PermissionManageWebhooks", channel) | ||||
| 			perms, permsErr := b.c.State.UserChannelPermissions(userinfo.ID, channel.ID) | ||||
| 			manageWebhooks := discordgo.PermissionManageWebhooks | ||||
| 			if permsErr != nil || perms&manageWebhooks != manageWebhooks { | ||||
| 				b.Log.Warnf("Can't manage webhooks in channel \"%s\"", channel.Name) | ||||
| 				b.canEditWebhooks = false | ||||
| 		manageWebhooks := discordgo.PermissionManageWebhooks | ||||
| 		var channelsDenied []string | ||||
| 		for _, info := range b.Channels { | ||||
| 			id := b.getChannelID(info.Name) // note(qaisjp): this readlocks channelsMutex | ||||
| 			b.Log.Debugf("Verifying PermissionManageWebhooks for %s with ID %s", info.ID, id) | ||||
|  | ||||
| 			perms, permsErr := b.c.UserChannelPermissions(userinfo.ID, id) | ||||
| 			if permsErr != nil { | ||||
| 				b.Log.Warnf("Failed to check PermissionManageWebhooks in channel \"%s\": %s", info.Name, permsErr.Error()) | ||||
| 			} else if perms&manageWebhooks == manageWebhooks { | ||||
| 				continue | ||||
| 			} | ||||
| 			channelsDenied = append(channelsDenied, fmt.Sprintf("%#v", info.Name)) | ||||
| 		} | ||||
| 		if b.canEditWebhooks { | ||||
| 			b.Log.Info("Can manage webhooks; will edit channel for global webhook on send") | ||||
| 		} else { | ||||
| 			b.Log.Warn("Can't manage webhooks; won't edit channel for global webhook on send") | ||||
| 		} | ||||
|  | ||||
| 		b.canEditWebhooks = len(channelsDenied) == 0 | ||||
| 		b.canEditWebhooks = false | ||||
| 		b.Log.Info("Webhook editing is disabled because of ratelimit issues") | ||||
| 		/* | ||||
| 			if b.canEditWebhooks { | ||||
| 				b.Log.Info("Can manage webhooks; will edit channel for global webhook on send") | ||||
| 			} else { | ||||
| 				b.Log.Warn("Can't manage webhooks; won't edit channel for global webhook on send") | ||||
| 				b.Log.Warn("Can't manage webhooks in channels: ", strings.Join(channelsDenied, ", ")) | ||||
| 			} | ||||
| 		*/ | ||||
| 	} | ||||
| 	b.channelsMutex.RUnlock() | ||||
|  | ||||
| @@ -174,10 +186,6 @@ func (b *Bdiscord) JoinChannel(channel config.ChannelInfo) error { | ||||
| 	defer b.channelsMutex.Unlock() | ||||
|  | ||||
| 	b.channelInfoMap[channel.ID] = &channel | ||||
| 	idcheck := strings.Split(channel.Name, "ID:") | ||||
| 	if len(idcheck) > 1 { | ||||
| 		b.useChannelID = true | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @@ -220,21 +228,10 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) { | ||||
| 	// Use webhook to send the message | ||||
| 	if wID != "" && msg.Event != config.EventMsgDelete { | ||||
| 		// skip events | ||||
| 		if msg.Event != "" && msg.Event != config.EventJoinLeave && msg.Event != config.EventTopicChange { | ||||
| 		if msg.Event != "" && msg.Event != config.EventUserAction && msg.Event != config.EventJoinLeave && msg.Event != config.EventTopicChange { | ||||
| 			return "", nil | ||||
| 		} | ||||
|  | ||||
| 		// If we are editing a message, delete the old message | ||||
| 		if msg.ID != "" { | ||||
| 			b.Log.Debugf("Deleting edited webhook message") | ||||
| 			err := b.c.ChannelMessageDelete(channelID, msg.ID) | ||||
| 			if err != nil { | ||||
| 				b.Log.Errorf("Could not delete edited webhook message: %s", err) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		b.Log.Debugf("Broadcasting using Webhook") | ||||
|  | ||||
| 		// skip empty messages | ||||
| 		if msg.Text == "" && (msg.Extra == nil || len(msg.Extra["file"]) == 0) { | ||||
| 			b.Log.Debugf("Skipping empty message %#v", msg) | ||||
| @@ -247,11 +244,25 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) { | ||||
| 		if len(msg.Username) > 32 { | ||||
| 			msg.Username = msg.Username[0:32] | ||||
| 		} | ||||
|  | ||||
| 		if msg.ID != "" { | ||||
| 			b.Log.Debugf("Editing webhook message") | ||||
| 			uri := discordgo.EndpointWebhookToken(wID, wToken) + "/messages/" + msg.ID | ||||
| 			_, err := b.c.RequestWithBucketID("PATCH", uri, discordgo.WebhookParams{ | ||||
| 				Content:  msg.Text, | ||||
| 				Username: msg.Username, | ||||
| 			}, discordgo.EndpointWebhookToken("", "")) | ||||
| 			if err == nil { | ||||
| 				return msg.ID, nil | ||||
| 			} | ||||
| 			b.Log.Errorf("Could not edit webhook message: %s", err) | ||||
| 		} | ||||
|  | ||||
| 		b.Log.Debugf("Broadcasting using Webhook") | ||||
|  | ||||
| 		// if we have a global webhook for this Discord account, and permission | ||||
| 		// to modify webhooks (previously verified), then set its channel to | ||||
| 		// the message channel before using it | ||||
| 		// TODO: this isn't necessary if the last message from this webhook was | ||||
| 		// sent to the current channel | ||||
| 		// the message channel before using it. | ||||
| 		if isGlobalWebhook && b.canEditWebhooks { | ||||
| 			b.Log.Debugf("Setting webhook channel to \"%s\"", msg.Channel) | ||||
| 			_, err := b.c.WebhookEdit(wID, "", "", channelID) | ||||
| @@ -269,6 +280,7 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) { | ||||
| 		if msg == nil { | ||||
| 			return "", nil | ||||
| 		} | ||||
|  | ||||
| 		return msg.ID, nil | ||||
| 	} | ||||
|  | ||||
| @@ -385,6 +397,19 @@ func (b *Bdiscord) webhookSend(msg *config.Message, webhookID, token string) (*d | ||||
| 		err error | ||||
| 	) | ||||
|  | ||||
| 	// If avatar is unset, check if UseLocalAvatar contains the message's | ||||
| 	// account or protocol, and if so, try to find a local avatar | ||||
| 	if msg.Avatar == "" { | ||||
| 		for _, val := range b.GetStringSlice("UseLocalAvatar") { | ||||
| 			if msg.Protocol == val || msg.Account == val { | ||||
| 				if avatar := b.findAvatar(msg); avatar != "" { | ||||
| 					msg.Avatar = avatar | ||||
| 				} | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// WebhookParams can have either `Content` or `File`. | ||||
|  | ||||
| 	// We can't send empty messages. | ||||
| @@ -412,6 +437,10 @@ func (b *Bdiscord) webhookSend(msg *config.Message, webhookID, token string) (*d | ||||
| 				ContentType: "", | ||||
| 				Reader:      bytes.NewReader(*fi.Data), | ||||
| 			} | ||||
| 			content := "" | ||||
| 			if msg.Text == "" { | ||||
| 				content = fi.Comment | ||||
| 			} | ||||
| 			_, e2 := b.c.WebhookExecute( | ||||
| 				webhookID, | ||||
| 				token, | ||||
| @@ -420,6 +449,7 @@ func (b *Bdiscord) webhookSend(msg *config.Message, webhookID, token string) (*d | ||||
| 					Username:  msg.Username, | ||||
| 					AvatarURL: msg.Avatar, | ||||
| 					File:      &file, | ||||
| 					Content:   content, | ||||
| 				}, | ||||
| 			) | ||||
| 			if e2 != nil { | ||||
| @@ -429,3 +459,11 @@ func (b *Bdiscord) webhookSend(msg *config.Message, webhookID, token string) (*d | ||||
| 	} | ||||
| 	return res, err | ||||
| } | ||||
|  | ||||
| func (b *Bdiscord) findAvatar(m *config.Message) string { | ||||
| 	member, err := b.getGuildMemberByNick(m.Username) | ||||
| 	if err != nil { | ||||
| 		return "" | ||||
| 	} | ||||
| 	return member.User.AvatarURL("") | ||||
| } | ||||
|   | ||||
| @@ -2,15 +2,13 @@ package bdiscord | ||||
|  | ||||
| import ( | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/bwmarrin/discordgo" | ||||
| 	"github.com/matterbridge/discordgo" | ||||
| ) | ||||
|  | ||||
| func (b *Bdiscord) messageDelete(s *discordgo.Session, m *discordgo.MessageDelete) { //nolint:unparam | ||||
| 	rmsg := config.Message{Account: b.Account, ID: m.ID, Event: config.EventMsgDelete, Text: config.EventMsgDelete} | ||||
| 	rmsg.Channel = b.getChannelName(m.ChannelID) | ||||
| 	if b.useChannelID { | ||||
| 		rmsg.Channel = "ID:" + m.ChannelID | ||||
| 	} | ||||
|  | ||||
| 	b.Log.Debugf("<= Sending message from %s to gateway", b.Account) | ||||
| 	b.Log.Debugf("<= Message is %#v", rmsg) | ||||
| 	b.Remote <- rmsg | ||||
| @@ -24,11 +22,7 @@ func (b *Bdiscord) messageDeleteBulk(s *discordgo.Session, m *discordgo.MessageD | ||||
| 			ID:      msgID, | ||||
| 			Event:   config.EventMsgDelete, | ||||
| 			Text:    config.EventMsgDelete, | ||||
| 			Channel: "ID:" + m.ChannelID, | ||||
| 		} | ||||
|  | ||||
| 		if !b.useChannelID { | ||||
| 			rmsg.Channel = b.getChannelName(m.ChannelID) | ||||
| 			Channel: b.getChannelName(m.ChannelID), | ||||
| 		} | ||||
|  | ||||
| 		b.Log.Debugf("<= Sending message from %s to gateway", b.Account) | ||||
| @@ -42,11 +36,13 @@ func (b *Bdiscord) messageTyping(s *discordgo.Session, m *discordgo.TypingStart) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// Ignore our own typing messages | ||||
| 	if m.UserID == b.userID { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	rmsg := config.Message{Account: b.Account, Event: config.EventUserTyping} | ||||
| 	rmsg.Channel = b.getChannelName(m.ChannelID) | ||||
| 	if b.useChannelID { | ||||
| 		rmsg.Channel = "ID:" + m.ChannelID | ||||
| 	} | ||||
| 	b.Remote <- rmsg | ||||
| } | ||||
|  | ||||
| @@ -88,7 +84,6 @@ func (b *Bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreat | ||||
|  | ||||
| 	if m.Content != "" { | ||||
| 		b.Log.Debugf("== Receiving event %#v", m.Message) | ||||
| 		m.Message.Content = b.stripCustomoji(m.Message.Content) | ||||
| 		m.Message.Content = b.replaceChannelMentions(m.Message.Content) | ||||
| 		rmsg.Text, err = m.ContentWithMoreMentionsReplaced(b.c) | ||||
| 		if err != nil { | ||||
| @@ -99,16 +94,13 @@ func (b *Bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreat | ||||
|  | ||||
| 	// set channel name | ||||
| 	rmsg.Channel = b.getChannelName(m.ChannelID) | ||||
| 	if b.useChannelID { | ||||
| 		rmsg.Channel = "ID:" + m.ChannelID | ||||
| 	} | ||||
|  | ||||
| 	// set username | ||||
| 	if !b.GetBool("UseUserName") { | ||||
| 	fromWebhook := m.WebhookID != "" | ||||
| 	if !fromWebhook && !b.GetBool("UseUserName") { | ||||
| 		rmsg.Username = b.getNick(m.Author, m.GuildID) | ||||
| 	} else { | ||||
| 		rmsg.Username = m.Author.Username | ||||
| 		if b.GetBool("UseDiscriminator") { | ||||
| 		if !fromWebhook && b.GetBool("UseDiscriminator") { | ||||
| 			rmsg.Username += "#" + m.Author.Discriminator | ||||
| 		} | ||||
| 	} | ||||
| @@ -116,7 +108,7 @@ func (b *Bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreat | ||||
| 	// if we have embedded content add it to text | ||||
| 	if b.GetBool("ShowEmbeds") && m.Message.Embeds != nil { | ||||
| 		for _, embed := range m.Message.Embeds { | ||||
| 			rmsg.Text = rmsg.Text + "embed: " + embed.Title + " - " + embed.Description + " - " + embed.URL + "\n" | ||||
| 			rmsg.Text += handleEmbed(embed) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -132,6 +124,9 @@ func (b *Bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreat | ||||
| 		rmsg.Event = config.EventUserAction | ||||
| 	} | ||||
|  | ||||
| 	// Replace emotes | ||||
| 	rmsg.Text = replaceEmotes(rmsg.Text) | ||||
|  | ||||
| 	b.Log.Debugf("<= Sending message from %s on %s to gateway", m.Author.Username, b.Account) | ||||
| 	b.Log.Debugf("<= Message is %#v", rmsg) | ||||
| 	b.Remote <- rmsg | ||||
| @@ -205,3 +200,33 @@ func (b *Bdiscord) memberRemove(s *discordgo.Session, m *discordgo.GuildMemberRe | ||||
| 	b.Log.Debugf("<= Message is %#v", rmsg) | ||||
| 	b.Remote <- rmsg | ||||
| } | ||||
|  | ||||
| func handleEmbed(embed *discordgo.MessageEmbed) string { | ||||
| 	var t []string | ||||
| 	var result string | ||||
|  | ||||
| 	t = append(t, embed.Title) | ||||
| 	t = append(t, embed.Description) | ||||
| 	t = append(t, embed.URL) | ||||
|  | ||||
| 	i := 0 | ||||
| 	for _, e := range t { | ||||
| 		if e == "" { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		i++ | ||||
| 		if i == 1 { | ||||
| 			result += " embed: " + e | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		result += " - " + e | ||||
| 	} | ||||
|  | ||||
| 	if result != "" { | ||||
| 		result += "\n" | ||||
| 	} | ||||
|  | ||||
| 	return result | ||||
| } | ||||
|   | ||||
							
								
								
									
										58
									
								
								bridge/discord/handlers_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								bridge/discord/handlers_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| package bdiscord | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/matterbridge/discordgo" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestHandleEmbed(t *testing.T) { | ||||
| 	testcases := map[string]struct { | ||||
| 		embed  *discordgo.MessageEmbed | ||||
| 		result string | ||||
| 	}{ | ||||
| 		"allempty": { | ||||
| 			embed:  &discordgo.MessageEmbed{}, | ||||
| 			result: "", | ||||
| 		}, | ||||
| 		"one": { | ||||
| 			embed: &discordgo.MessageEmbed{ | ||||
| 				Title: "blah", | ||||
| 			}, | ||||
| 			result: " embed: blah\n", | ||||
| 		}, | ||||
| 		"two": { | ||||
| 			embed: &discordgo.MessageEmbed{ | ||||
| 				Title:       "blah", | ||||
| 				Description: "blah2", | ||||
| 			}, | ||||
| 			result: " embed: blah - blah2\n", | ||||
| 		}, | ||||
| 		"three": { | ||||
| 			embed: &discordgo.MessageEmbed{ | ||||
| 				Title:       "blah", | ||||
| 				Description: "blah2", | ||||
| 				URL:         "blah3", | ||||
| 			}, | ||||
| 			result: " embed: blah - blah2 - blah3\n", | ||||
| 		}, | ||||
| 		"twob": { | ||||
| 			embed: &discordgo.MessageEmbed{ | ||||
| 				Description: "blah2", | ||||
| 				URL:         "blah3", | ||||
| 			}, | ||||
| 			result: " embed: blah2 - blah3\n", | ||||
| 		}, | ||||
| 		"oneb": { | ||||
| 			embed: &discordgo.MessageEmbed{ | ||||
| 				URL: "blah3", | ||||
| 			}, | ||||
| 			result: " embed: blah3\n", | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for name, tc := range testcases { | ||||
| 		assert.Equalf(t, tc.result, handleEmbed(tc.embed), "Testcases %s", name) | ||||
| 	} | ||||
| } | ||||
| @@ -6,7 +6,7 @@ import ( | ||||
| 	"strings" | ||||
| 	"unicode" | ||||
|  | ||||
| 	"github.com/bwmarrin/discordgo" | ||||
| 	"github.com/matterbridge/discordgo" | ||||
| ) | ||||
|  | ||||
| func (b *Bdiscord) getNick(user *discordgo.User, guildID string) string { | ||||
| @@ -96,6 +96,13 @@ func (b *Bdiscord) getChannelName(id string) string { | ||||
| 	b.channelsMutex.RLock() | ||||
| 	defer b.channelsMutex.RUnlock() | ||||
|  | ||||
| 	for _, c := range b.channelInfoMap { | ||||
| 		if c.Name == "ID:"+id { | ||||
| 			// if we have ID: specified in our gateway configuration return this | ||||
| 			return c.Name | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for _, channel := range b.channels { | ||||
| 		if channel.ID == id { | ||||
| 			return b.getCategoryChannelName(channel.Name, channel.ParentID) | ||||
| @@ -129,8 +136,8 @@ func (b *Bdiscord) getCategoryChannelName(name, parentID string) string { | ||||
| var ( | ||||
| 	// See https://discordapp.com/developers/docs/reference#message-formatting. | ||||
| 	channelMentionRE = regexp.MustCompile("<#[0-9]+>") | ||||
| 	emojiRE          = regexp.MustCompile("<(:.*?:)[0-9]+>") | ||||
| 	userMentionRE    = regexp.MustCompile("@[^@\n]{1,32}") | ||||
| 	emoteRE          = regexp.MustCompile(`<a?(:\w+:)\d+>`) | ||||
| ) | ||||
|  | ||||
| func (b *Bdiscord) replaceChannelMentions(text string) string { | ||||
| @@ -176,13 +183,14 @@ func (b *Bdiscord) replaceUserMentions(text string) string { | ||||
| 	return userMentionRE.ReplaceAllStringFunc(text, replaceUserMentionFunc) | ||||
| } | ||||
|  | ||||
| func (b *Bdiscord) stripCustomoji(text string) string { | ||||
| 	return emojiRE.ReplaceAllString(text, `$1`) | ||||
| func replaceEmotes(text string) string { | ||||
| 	return emoteRE.ReplaceAllString(text, "$1") | ||||
| } | ||||
|  | ||||
| func (b *Bdiscord) replaceAction(text string) (string, bool) { | ||||
| 	if strings.HasPrefix(text, "_") && strings.HasSuffix(text, "_") { | ||||
| 		return text[1 : len(text)-1], true | ||||
| 	length := len(text) | ||||
| 	if length > 1 && text[0] == '_' && text[length-1] == '_' { | ||||
| 		return text[1 : length-1], true | ||||
| 	} | ||||
| 	return text, false | ||||
| } | ||||
|   | ||||
| @@ -5,7 +5,10 @@ import ( | ||||
| 	"fmt" | ||||
| 	"image/png" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| @@ -15,6 +18,7 @@ import ( | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/gomarkdown/markdown" | ||||
| 	"github.com/gomarkdown/markdown/html" | ||||
| 	"github.com/gomarkdown/markdown/parser" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
| @@ -179,16 +183,19 @@ func ClipMessage(text string, length int) string { | ||||
|  | ||||
| // ParseMarkdown takes in an input string as markdown and parses it to html | ||||
| func ParseMarkdown(input string) string { | ||||
| 	extensions := parser.HardLineBreak | ||||
| 	extensions := parser.HardLineBreak | parser.NoIntraEmphasis | ||||
| 	markdownParser := parser.NewWithExtensions(extensions) | ||||
| 	parsedMarkdown := markdown.ToHTML([]byte(input), markdownParser, nil) | ||||
| 	renderer := html.NewRenderer(html.RendererOptions{ | ||||
| 		Flags: 0, | ||||
| 	}) | ||||
| 	parsedMarkdown := markdown.ToHTML([]byte(input), markdownParser, renderer) | ||||
| 	res := string(parsedMarkdown) | ||||
| 	res = strings.TrimPrefix(res, "<p>") | ||||
| 	res = strings.TrimSuffix(res, "</p>\n") | ||||
| 	return res | ||||
| } | ||||
|  | ||||
| // ConvertWebPToPNG convert input data (which should be WebP format to PNG format) | ||||
| // ConvertWebPToPNG converts input data (which should be WebP format) to PNG format | ||||
| func ConvertWebPToPNG(data *[]byte) error { | ||||
| 	r := bytes.NewReader(*data) | ||||
| 	m, err := webp.Decode(r) | ||||
| @@ -203,3 +210,49 @@ func ConvertWebPToPNG(data *[]byte) error { | ||||
| 	*data = w.Bytes() | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // CanConvertTgsToX Checks whether the external command necessary for ConvertTgsToX works. | ||||
| func CanConvertTgsToX() error { | ||||
| 	// We depend on the fact that `lottie_convert.py --help` has exit status 0. | ||||
| 	// Hyrum's Law predicted this, and Murphy's Law predicts that this will break eventually. | ||||
| 	// However, there is no alternative like `lottie_convert.py --is-properly-installed` | ||||
| 	cmd := exec.Command("lottie_convert.py", "--help") | ||||
| 	return cmd.Run() | ||||
| } | ||||
|  | ||||
| // ConvertTgsToWebP convert input data (which should be tgs format) to WebP format | ||||
| // This relies on an external command, which is ugly, but works. | ||||
| func ConvertTgsToX(data *[]byte, outputFormat string, logger *logrus.Entry) error { | ||||
| 	// lottie can't handle input from a pipe, so write to a temporary file: | ||||
| 	tmpFile, err := ioutil.TempFile(os.TempDir(), "matterbridge-lottie-*.tgs") | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	tmpFileName := tmpFile.Name() | ||||
| 	defer func() { | ||||
| 		if removeErr := os.Remove(tmpFileName); removeErr != nil { | ||||
| 			logger.Errorf("Could not delete temporary file %s: %v", tmpFileName, removeErr) | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	if _, writeErr := tmpFile.Write(*data); writeErr != nil { | ||||
| 		return writeErr | ||||
| 	} | ||||
| 	// Must close before calling lottie to avoid data races: | ||||
| 	if closeErr := tmpFile.Close(); closeErr != nil { | ||||
| 		return closeErr | ||||
| 	} | ||||
|  | ||||
| 	// Call lottie to transform: | ||||
| 	cmd := exec.Command("lottie_convert.py", "--input-format", "lottie", "--output-format", outputFormat, tmpFileName, "/dev/stdout") | ||||
| 	cmd.Stderr = nil | ||||
| 	// NB: lottie writes progress into to stderr in all cases. | ||||
| 	stdout, stderr := cmd.Output() | ||||
| 	if stderr != nil { | ||||
| 		// 'stderr' already contains some parts of Stderr, because it was set to 'nil'. | ||||
| 		return stderr | ||||
| 	} | ||||
|  | ||||
| 	*data = stdout | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -10,8 +10,8 @@ import ( | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/42wim/matterbridge/bridge/helper" | ||||
| 	"github.com/dfordsoft/golib/ic" | ||||
| 	"github.com/lrstanley/girc" | ||||
| 	"github.com/missdeer/golib/ic" | ||||
| 	"github.com/paulrosania/go-charset/charset" | ||||
| 	"github.com/saintfish/chardet" | ||||
|  | ||||
| @@ -54,12 +54,12 @@ func (b *Birc) handleFiles(msg *config.Message) bool { | ||||
| 	for _, f := range msg.Extra["file"] { | ||||
| 		fi := f.(config.FileInfo) | ||||
| 		if fi.Comment != "" { | ||||
| 			msg.Text += fi.Comment + ": " | ||||
| 			msg.Text += fi.Comment + " : " | ||||
| 		} | ||||
| 		if fi.URL != "" { | ||||
| 			msg.Text = fi.URL | ||||
| 			if fi.Comment != "" { | ||||
| 				msg.Text = fi.Comment + ": " + fi.URL | ||||
| 				msg.Text = fi.Comment + " : " + fi.URL | ||||
| 			} | ||||
| 		} | ||||
| 		b.Local <- config.Message{Text: msg.Text, Username: msg.Username, Channel: msg.Channel, Event: msg.Event} | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import ( | ||||
| 	"crypto/tls" | ||||
| 	"fmt" | ||||
| 	"hash/crc32" | ||||
| 	"io/ioutil" | ||||
| 	"net" | ||||
| 	"sort" | ||||
| 	"strconv" | ||||
| @@ -14,6 +15,7 @@ import ( | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/42wim/matterbridge/bridge/helper" | ||||
| 	"github.com/lrstanley/girc" | ||||
| 	stripmd "github.com/writeas/go-strip-markdown" | ||||
|  | ||||
| 	// We need to import the 'data' package as an implicit dependency. | ||||
| 	// See: https://godoc.org/github.com/paulrosania/go-charset/charset | ||||
| @@ -156,6 +158,10 @@ func (b *Birc) Send(msg config.Message) (string, error) { | ||||
| 	} | ||||
|  | ||||
| 	var msgLines []string | ||||
| 	if b.GetBool("StripMarkdown") { | ||||
| 		msg.Text = stripmd.Strip(msg.Text) | ||||
| 	} | ||||
|  | ||||
| 	if b.GetBool("MessageSplit") { | ||||
| 		msgLines = helper.GetSubLines(msg.Text, b.MessageLength) | ||||
| 	} else { | ||||
| @@ -167,12 +173,8 @@ func (b *Birc) Send(msg config.Message) (string, error) { | ||||
| 			return "", nil | ||||
| 		} | ||||
|  | ||||
| 		b.Local <- config.Message{ | ||||
| 			Text:     msgLines[i], | ||||
| 			Username: msg.Username, | ||||
| 			Channel:  msg.Channel, | ||||
| 			Event:    msg.Event, | ||||
| 		} | ||||
| 		msg.Text = msgLines[i] | ||||
| 		b.Local <- msg | ||||
| 	} | ||||
| 	return "", nil | ||||
| } | ||||
| @@ -205,7 +207,7 @@ func (b *Birc) doSend() { | ||||
| 	for msg := range b.Local { | ||||
| 		<-throttle.C | ||||
| 		username := msg.Username | ||||
| 		if b.GetBool("Colornicks") { | ||||
| 		if b.GetBool("Colornicks") && len(username) > 1 { | ||||
| 			checksum := crc32.ChecksumIEEE([]byte(msg.Username)) | ||||
| 			colorCode := checksum%14 + 2 // quick fix - prevent white or black color codes | ||||
| 			username = fmt.Sprintf("\x03%02d%s\x0F", colorCode, msg.Username) | ||||
| @@ -239,6 +241,18 @@ func (b *Birc) getClient() (*girc.Client, error) { | ||||
| 		user = user[1:] | ||||
| 	} | ||||
|  | ||||
| 	debug := ioutil.Discard | ||||
| 	if b.GetInt("DebugLevel") == 2 { | ||||
| 		debug = b.Log.Writer() | ||||
| 	} | ||||
|  | ||||
| 	pingDelay, err := time.ParseDuration(b.GetString("pingdelay")) | ||||
| 	if err != nil || pingDelay == 0 { | ||||
| 		pingDelay = time.Minute | ||||
| 	} | ||||
|  | ||||
| 	b.Log.Debugf("setting pingdelay to %s", pingDelay) | ||||
|  | ||||
| 	i := girc.New(girc.Config{ | ||||
| 		Server:     server, | ||||
| 		ServerPass: b.GetString("Password"), | ||||
| @@ -248,7 +262,10 @@ func (b *Birc) getClient() (*girc.Client, error) { | ||||
| 		Name:       b.GetString("Nick"), | ||||
| 		SSL:        b.GetBool("UseTLS"), | ||||
| 		TLSConfig:  &tls.Config{InsecureSkipVerify: b.GetBool("SkipTLSVerify"), ServerName: server}, //nolint:gosec | ||||
| 		PingDelay:  time.Minute, | ||||
| 		PingDelay:  pingDelay, | ||||
| 		// skip gIRC internal rate limiting, since we have our own throttling | ||||
| 		AllowFlood: true, | ||||
| 		Debug:      debug, | ||||
| 	}) | ||||
| 	return i, nil | ||||
| } | ||||
|   | ||||
| @@ -4,7 +4,7 @@ import ( | ||||
| 	"strconv" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/keybase/go-keybase-chat-bot/kbchat" | ||||
| 	"github.com/keybase/go-keybase-chat-bot/kbchat/types/chat1" | ||||
| ) | ||||
|  | ||||
| func (b *Bkeybase) handleKeybase() { | ||||
| @@ -20,7 +20,7 @@ func (b *Bkeybase) handleKeybase() { | ||||
| 				b.Log.Errorf("failed to read message: %s", err.Error()) | ||||
| 			} | ||||
|  | ||||
| 			if msg.Message.Content.Type != "text" { | ||||
| 			if msg.Message.Content.TypeName != "text" { | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| @@ -34,7 +34,7 @@ func (b *Bkeybase) handleKeybase() { | ||||
| 	}() | ||||
| } | ||||
|  | ||||
| func (b *Bkeybase) handleMessage(msg kbchat.Message) { | ||||
| func (b *Bkeybase) handleMessage(msg chat1.MsgSummary) { | ||||
| 	b.Log.Debugf("== Receiving event: %#v", msg) | ||||
| 	if msg.Channel.TopicName != b.channel || msg.Channel.Name != b.team { | ||||
| 		return | ||||
| @@ -45,10 +45,10 @@ func (b *Bkeybase) handleMessage(msg kbchat.Message) { | ||||
| 		// TODO download avatar | ||||
|  | ||||
| 		// Create our message | ||||
| 		rmsg := config.Message{Username: msg.Sender.Username, Text: msg.Content.Text.Body, UserID: msg.Sender.Uid, Channel: msg.Channel.TopicName, ID: strconv.Itoa(msg.MsgID), Account: b.Account} | ||||
| 		rmsg := config.Message{Username: msg.Sender.Username, Text: msg.Content.Text.Body, UserID: string(msg.Sender.Uid), Channel: msg.Channel.TopicName, ID: strconv.Itoa(int(msg.Id)), Account: b.Account} | ||||
|  | ||||
| 		// Text must be a string | ||||
| 		if msg.Content.Type != "text" { | ||||
| 		if msg.Content.TypeName != "text" { | ||||
| 			b.Log.Errorf("message is not text") | ||||
| 			return | ||||
| 		} | ||||
|   | ||||
| @@ -90,16 +90,17 @@ func (b *Bkeybase) Send(msg config.Message) (string, error) { | ||||
| 				return "", err | ||||
| 			} | ||||
|  | ||||
| 			_, _ = b.kbc.SendAttachmentByTeam(b.team, fpath, fcaption, &b.channel) | ||||
| 			_, _ = b.kbc.SendAttachmentByTeam(b.team, &b.channel, fpath, fcaption) | ||||
| 		} | ||||
|  | ||||
| 		return "", nil | ||||
| 	} | ||||
|  | ||||
| 	// Send regular message | ||||
| 	resp, err := b.kbc.SendMessageByTeamName(b.team, msg.Username+msg.Text, &b.channel) | ||||
| 	text := msg.Username + msg.Text | ||||
| 	resp, err := b.kbc.SendMessageByTeamName(b.team, &b.channel, text) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return strconv.Itoa(resp.Result.MsgID), err | ||||
| 	return strconv.Itoa(int(*resp.Result.MessageID)), err | ||||
| } | ||||
|   | ||||
							
								
								
									
										166
									
								
								bridge/matrix/helpers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								bridge/matrix/helpers.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,166 @@ | ||||
| package bmatrix | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"html" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	matrix "github.com/matrix-org/gomatrix" | ||||
| ) | ||||
|  | ||||
| func newMatrixUsername(username string) *matrixUsername { | ||||
| 	mUsername := new(matrixUsername) | ||||
|  | ||||
| 	// check if we have a </tag>. if we have, we don't escape HTML. #696 | ||||
| 	if htmlTag.MatchString(username) { | ||||
| 		mUsername.formatted = username | ||||
| 		// remove the HTML formatting for beautiful push messages #1188 | ||||
| 		mUsername.plain = htmlReplacementTag.ReplaceAllString(username, "") | ||||
| 	} else { | ||||
| 		mUsername.formatted = html.EscapeString(username) | ||||
| 		mUsername.plain = username | ||||
| 	} | ||||
|  | ||||
| 	return mUsername | ||||
| } | ||||
|  | ||||
| // getRoomID retrieves a matching room ID from the channel name. | ||||
| func (b *Bmatrix) getRoomID(channel string) string { | ||||
| 	b.RLock() | ||||
| 	defer b.RUnlock() | ||||
| 	for ID, name := range b.RoomMap { | ||||
| 		if name == channel { | ||||
| 			return ID | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| // interface2Struct marshals and immediately unmarshals an interface. | ||||
| // Useful for converting map[string]interface{} to a struct. | ||||
| func interface2Struct(in interface{}, out interface{}) error { | ||||
| 	jsonObj, err := json.Marshal(in) | ||||
| 	if err != nil { | ||||
| 		return err //nolint:wrapcheck | ||||
| 	} | ||||
|  | ||||
| 	return json.Unmarshal(jsonObj, out) | ||||
| } | ||||
|  | ||||
| // getDisplayName retrieves the displayName for mxid, querying the homserver if the mxid is not in the cache. | ||||
| func (b *Bmatrix) getDisplayName(mxid string) string { | ||||
| 	if b.GetBool("UseUserName") { | ||||
| 		return mxid[1:] | ||||
| 	} | ||||
|  | ||||
| 	b.RLock() | ||||
| 	if val, present := b.NicknameMap[mxid]; present { | ||||
| 		b.RUnlock() | ||||
|  | ||||
| 		return val.displayName | ||||
| 	} | ||||
| 	b.RUnlock() | ||||
|  | ||||
| 	displayName, err := b.mc.GetDisplayName(mxid) | ||||
| 	var httpError *matrix.HTTPError | ||||
| 	if errors.As(err, &httpError) { | ||||
| 		b.Log.Warnf("Couldn't retrieve the display name for %s", mxid) | ||||
| 	} | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return b.cacheDisplayName(mxid, mxid[1:]) | ||||
| 	} | ||||
|  | ||||
| 	return b.cacheDisplayName(mxid, displayName.DisplayName) | ||||
| } | ||||
|  | ||||
| // cacheDisplayName stores the mapping between a mxid and a display name, to be reused later without performing a query to the homserver. | ||||
| // Note that old entries are cleaned when this function is called. | ||||
| func (b *Bmatrix) cacheDisplayName(mxid string, displayName string) string { | ||||
| 	now := time.Now() | ||||
|  | ||||
| 	// scan to delete old entries, to stop memory usage from becoming too high with old entries | ||||
| 	toDelete := []string{} | ||||
| 	b.RLock() | ||||
| 	for k, v := range b.NicknameMap { | ||||
| 		if now.Sub(v.lastUpdated) > 10*time.Minute { | ||||
| 			toDelete = append(toDelete, k) | ||||
| 		} | ||||
| 	} | ||||
| 	b.RUnlock() | ||||
|  | ||||
| 	b.Lock() | ||||
| 	for _, v := range toDelete { | ||||
| 		delete(b.NicknameMap, v) | ||||
| 	} | ||||
| 	b.NicknameMap[mxid] = NicknameCacheEntry{ | ||||
| 		displayName: displayName, | ||||
| 		lastUpdated: now, | ||||
| 	} | ||||
| 	b.Unlock() | ||||
|  | ||||
| 	return displayName | ||||
| } | ||||
|  | ||||
| // handleError converts errors into httpError. | ||||
| //nolint:exhaustivestruct | ||||
| func handleError(err error) *httpError { | ||||
| 	var mErr matrix.HTTPError | ||||
| 	if !errors.As(err, &mErr) { | ||||
| 		return &httpError{ | ||||
| 			Err: "not a HTTPError", | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var httpErr httpError | ||||
|  | ||||
| 	if err := json.Unmarshal(mErr.Contents, &httpErr); err != nil { | ||||
| 		return &httpError{ | ||||
| 			Err: "unmarshal failed", | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return &httpErr | ||||
| } | ||||
|  | ||||
| func (b *Bmatrix) containsAttachment(content map[string]interface{}) bool { | ||||
| 	// Skip empty messages | ||||
| 	if content["msgtype"] == nil { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	// Only allow image,video or file msgtypes | ||||
| 	if !(content["msgtype"].(string) == "m.image" || | ||||
| 		content["msgtype"].(string) == "m.video" || | ||||
| 		content["msgtype"].(string) == "m.file") { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| // getAvatarURL returns the avatar URL of the specified sender. | ||||
| func (b *Bmatrix) getAvatarURL(sender string) string { | ||||
| 	urlPath := b.mc.BuildURL("profile", sender, "avatar_url") | ||||
|  | ||||
| 	s := struct { | ||||
| 		AvatarURL string `json:"avatar_url"` | ||||
| 	}{} | ||||
|  | ||||
| 	err := b.mc.MakeRequest("GET", urlPath, nil, &s) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("getAvatarURL failed: %s", err) | ||||
|  | ||||
| 		return "" | ||||
| 	} | ||||
|  | ||||
| 	url := strings.ReplaceAll(s.AvatarURL, "mxc://", b.GetString("Server")+"/_matrix/media/r0/thumbnail/") | ||||
| 	if url != "" { | ||||
| 		url += "?width=37&height=37&method=crop" | ||||
| 	} | ||||
|  | ||||
| 	return url | ||||
| } | ||||
| @@ -3,31 +3,71 @@ package bmatrix | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"html" | ||||
| 	"mime" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge" | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/42wim/matterbridge/bridge/helper" | ||||
| 	matrix "github.com/matterbridge/gomatrix" | ||||
| 	matrix "github.com/matrix-org/gomatrix" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	htmlTag            = regexp.MustCompile("</.*?>") | ||||
| 	htmlReplacementTag = regexp.MustCompile("<[^>]*>") | ||||
| ) | ||||
|  | ||||
| type NicknameCacheEntry struct { | ||||
| 	displayName string | ||||
| 	lastUpdated time.Time | ||||
| } | ||||
|  | ||||
| type Bmatrix struct { | ||||
| 	mc      *matrix.Client | ||||
| 	UserID  string | ||||
| 	RoomMap map[string]string | ||||
| 	mc          *matrix.Client | ||||
| 	UserID      string | ||||
| 	NicknameMap map[string]NicknameCacheEntry | ||||
| 	RoomMap     map[string]string | ||||
| 	sync.RWMutex | ||||
| 	htmlTag *regexp.Regexp | ||||
| 	*bridge.Config | ||||
| } | ||||
|  | ||||
| type httpError struct { | ||||
| 	Errcode      string `json:"errcode"` | ||||
| 	Err          string `json:"error"` | ||||
| 	RetryAfterMs int    `json:"retry_after_ms"` | ||||
| } | ||||
|  | ||||
| type matrixUsername struct { | ||||
| 	plain     string | ||||
| 	formatted string | ||||
| } | ||||
|  | ||||
| // SubTextMessage represents the new content of the message in edit messages. | ||||
| type SubTextMessage struct { | ||||
| 	MsgType string `json:"msgtype"` | ||||
| 	Body    string `json:"body"` | ||||
| } | ||||
|  | ||||
| // MessageRelation explains how the current message relates to a previous message. | ||||
| // Notably used for message edits. | ||||
| type MessageRelation struct { | ||||
| 	EventID string `json:"event_id"` | ||||
| 	Type    string `json:"rel_type"` | ||||
| } | ||||
|  | ||||
| type EditedMessage struct { | ||||
| 	NewContent SubTextMessage  `json:"m.new_content"` | ||||
| 	RelatedTo  MessageRelation `json:"m.relates_to"` | ||||
| 	matrix.TextMessage | ||||
| } | ||||
|  | ||||
| func New(cfg *bridge.Config) bridge.Bridger { | ||||
| 	b := &Bmatrix{Config: cfg} | ||||
| 	b.htmlTag = regexp.MustCompile("</.*?>") | ||||
| 	b.RoomMap = make(map[string]string) | ||||
| 	b.NicknameMap = make(map[string]NicknameCacheEntry) | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| @@ -39,9 +79,10 @@ func (b *Bmatrix) Connect() error { | ||||
| 		return err | ||||
| 	} | ||||
| 	resp, err := b.mc.Login(&matrix.ReqLogin{ | ||||
| 		Type:     "m.login.password", | ||||
| 		User:     b.GetString("Login"), | ||||
| 		Password: b.GetString("Password"), | ||||
| 		Type:       "m.login.password", | ||||
| 		User:       b.GetString("Login"), | ||||
| 		Password:   b.GetString("Password"), | ||||
| 		Identifier: matrix.NewUserIdentifier(b.GetString("Login")), | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| @@ -58,14 +99,25 @@ func (b *Bmatrix) Disconnect() error { | ||||
| } | ||||
|  | ||||
| func (b *Bmatrix) JoinChannel(channel config.ChannelInfo) error { | ||||
| retry: | ||||
| 	resp, err := b.mc.JoinRoom(channel.Name, "", nil) | ||||
| 	if err != nil { | ||||
| 		httpErr := handleError(err) | ||||
| 		if httpErr.Errcode == "M_LIMIT_EXCEEDED" { | ||||
| 			b.Log.Infof("getting ratelimited by matrix, sleeping approx %d seconds before joining %s", httpErr.RetryAfterMs/1000, channel.Name) | ||||
| 			time.Sleep((time.Duration(httpErr.RetryAfterMs) * time.Millisecond)) | ||||
|  | ||||
| 			goto retry | ||||
| 		} | ||||
|  | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	b.Lock() | ||||
| 	b.RoomMap[resp.RoomID] = channel.Name | ||||
| 	b.Unlock() | ||||
| 	return err | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Bmatrix) Send(msg config.Message) (string, error) { | ||||
| @@ -74,11 +126,14 @@ func (b *Bmatrix) Send(msg config.Message) (string, error) { | ||||
| 	channel := b.getRoomID(msg.Channel) | ||||
| 	b.Log.Debugf("Channel %s maps to channel id %s", msg.Channel, channel) | ||||
|  | ||||
| 	username := newMatrixUsername(msg.Username) | ||||
|  | ||||
| 	// Make a action /me of the message | ||||
| 	if msg.Event == config.EventUserAction { | ||||
| 		m := matrix.TextMessage{ | ||||
| 			MsgType: "m.emote", | ||||
| 			Body:    msg.Username + msg.Text, | ||||
| 			MsgType:       "m.emote", | ||||
| 			Body:          username.plain + msg.Text, | ||||
| 			FormattedBody: username.formatted + msg.Text, | ||||
| 		} | ||||
| 		resp, err := b.mc.SendMessageEvent(channel, "m.room.message", m) | ||||
| 		if err != nil { | ||||
| @@ -113,45 +168,68 @@ func (b *Bmatrix) Send(msg config.Message) (string, error) { | ||||
| 	} | ||||
|  | ||||
| 	// Edit message if we have an ID | ||||
| 	// matrix has no editing support | ||||
| 	if msg.ID != "" { | ||||
| 		rmsg := EditedMessage{TextMessage: matrix.TextMessage{ | ||||
| 			Body:    username.plain + msg.Text, | ||||
| 			MsgType: "m.text", | ||||
| 		}} | ||||
| 		if b.GetBool("HTMLDisable") { | ||||
| 			rmsg.TextMessage.FormattedBody = username.formatted + "* " + msg.Text | ||||
| 		} else { | ||||
| 			rmsg.Format = "org.matrix.custom.html" | ||||
| 			rmsg.TextMessage.FormattedBody = username.formatted + "* " + helper.ParseMarkdown(msg.Text) | ||||
| 		} | ||||
| 		rmsg.NewContent = SubTextMessage{ | ||||
| 			Body:    rmsg.TextMessage.Body, | ||||
| 			MsgType: "m.text", | ||||
| 		} | ||||
| 		rmsg.RelatedTo = MessageRelation{ | ||||
| 			EventID: msg.ID, | ||||
| 			Type:    "m.replace", | ||||
| 		} | ||||
| 		_, err := b.mc.SendMessageEvent(channel, "m.room.message", rmsg) | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
|  | ||||
| 		return msg.ID, nil | ||||
| 	} | ||||
|  | ||||
| 	// Use notices to send join/leave events | ||||
| 	if msg.Event == config.EventJoinLeave { | ||||
| 		resp, err := b.mc.SendNotice(channel, msg.Username+msg.Text) | ||||
| 		m := matrix.TextMessage{ | ||||
| 			MsgType:       "m.notice", | ||||
| 			Body:          username.plain + msg.Text, | ||||
| 			FormattedBody: username.formatted + msg.Text, | ||||
| 		} | ||||
| 		resp, err := b.mc.SendMessageEvent(channel, "m.room.message", m) | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
| 		return resp.EventID, err | ||||
| 	} | ||||
|  | ||||
| 	username := html.EscapeString(msg.Username) | ||||
| 	// check if we have a </tag>. if we have, we don't escape HTML. #696 | ||||
| 	if b.htmlTag.MatchString(msg.Username) { | ||||
| 		username = msg.Username | ||||
| 	if b.GetBool("HTMLDisable") { | ||||
| 		resp, err := b.mc.SendText(channel, username.plain+msg.Text) | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
| 		return resp.EventID, err | ||||
| 	} | ||||
|  | ||||
| 	// Post normal message with HTML support (eg riot.im) | ||||
| 	resp, err := b.mc.SendHTML(channel, msg.Username+msg.Text, username+helper.ParseMarkdown(msg.Text)) | ||||
| 	resp, err := b.mc.SendFormattedText(channel, username.plain+msg.Text, username.formatted+helper.ParseMarkdown(msg.Text)) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return resp.EventID, err | ||||
| } | ||||
|  | ||||
| func (b *Bmatrix) getRoomID(channel string) string { | ||||
| 	b.RLock() | ||||
| 	defer b.RUnlock() | ||||
| 	for ID, name := range b.RoomMap { | ||||
| 		if name == channel { | ||||
| 			return ID | ||||
| 		} | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (b *Bmatrix) handlematrix() { | ||||
| 	syncer := b.mc.Syncer.(*matrix.DefaultSyncer) | ||||
| 	syncer.OnEventType("m.room.redaction", b.handleEvent) | ||||
| 	syncer.OnEventType("m.room.message", b.handleEvent) | ||||
| 	syncer.OnEventType("m.room.member", b.handleMemberChange) | ||||
| 	go func() { | ||||
| 		for { | ||||
| 			if err := b.mc.Sync(); err != nil { | ||||
| @@ -161,6 +239,45 @@ func (b *Bmatrix) handlematrix() { | ||||
| 	}() | ||||
| } | ||||
|  | ||||
| func (b *Bmatrix) handleEdit(ev *matrix.Event, rmsg config.Message) bool { | ||||
| 	relationInterface, present := ev.Content["m.relates_to"] | ||||
| 	newContentInterface, present2 := ev.Content["m.new_content"] | ||||
| 	if !(present && present2) { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	var relation MessageRelation | ||||
| 	if err := interface2Struct(relationInterface, &relation); err != nil { | ||||
| 		b.Log.Warnf("Couldn't parse 'm.relates_to' object with value %#v", relationInterface) | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	var newContent SubTextMessage | ||||
| 	if err := interface2Struct(newContentInterface, &newContent); err != nil { | ||||
| 		b.Log.Warnf("Couldn't parse 'm.new_content' object with value %#v", newContentInterface) | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	if relation.Type != "m.replace" { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	rmsg.ID = relation.EventID | ||||
| 	rmsg.Text = newContent.Body | ||||
| 	b.Remote <- rmsg | ||||
|  | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| func (b *Bmatrix) handleMemberChange(ev *matrix.Event) { | ||||
| 	// Update the displayname on join messages, according to https://matrix.org/docs/spec/client_server/r0.6.1#events-on-change-of-profile-information | ||||
| 	if ev.Content["membership"] == "join" { | ||||
| 		if dn, ok := ev.Content["displayname"].(string); ok { | ||||
| 			b.cacheDisplayName(ev.Sender, dn) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *Bmatrix) handleEvent(ev *matrix.Event) { | ||||
| 	b.Log.Debugf("== Receiving event: %#v", ev) | ||||
| 	if ev.Sender != b.UserID { | ||||
| @@ -172,10 +289,15 @@ func (b *Bmatrix) handleEvent(ev *matrix.Event) { | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		// TODO download avatar | ||||
|  | ||||
| 		// Create our message | ||||
| 		rmsg := config.Message{Username: ev.Sender[1:], Channel: channel, Account: b.Account, UserID: ev.Sender, ID: ev.ID} | ||||
| 		rmsg := config.Message{ | ||||
| 			Username: b.getDisplayName(ev.Sender), | ||||
| 			Channel:  channel, | ||||
| 			Account:  b.Account, | ||||
| 			UserID:   ev.Sender, | ||||
| 			ID:       ev.ID, | ||||
| 			Avatar:   b.getAvatarURL(ev.Sender), | ||||
| 		} | ||||
|  | ||||
| 		// Text must be a string | ||||
| 		if rmsg.Text, ok = ev.Content["body"].(string); !ok { | ||||
| @@ -204,6 +326,11 @@ func (b *Bmatrix) handleEvent(ev *matrix.Event) { | ||||
| 			rmsg.Event = config.EventUserAction | ||||
| 		} | ||||
|  | ||||
| 		// Is it an edit? | ||||
| 		if b.handleEdit(ev, rmsg) { | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		// Do we have attachments | ||||
| 		if b.containsAttachment(ev.Content) { | ||||
| 			err := b.handleDownloadFile(&rmsg, ev.Content) | ||||
| @@ -288,25 +415,16 @@ func (b *Bmatrix) handleUploadFiles(msg *config.Message, channel string) (string | ||||
|  | ||||
| // handleUploadFile handles native upload of a file. | ||||
| func (b *Bmatrix) handleUploadFile(msg *config.Message, channel string, fi *config.FileInfo) { | ||||
| 	username := newMatrixUsername(msg.Username) | ||||
| 	content := bytes.NewReader(*fi.Data) | ||||
| 	sp := strings.Split(fi.Name, ".") | ||||
| 	mtype := mime.TypeByExtension("." + sp[len(sp)-1]) | ||||
| 	if !(strings.Contains(mtype, "image") || strings.Contains(mtype, "video") || | ||||
| 		strings.Contains(mtype, "application") || strings.Contains(mtype, "audio")) { | ||||
| 		return | ||||
| 	} | ||||
| 	if fi.Comment != "" { | ||||
| 		_, err := b.mc.SendText(channel, msg.Username+fi.Comment) | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("file comment failed: %#v", err) | ||||
| 		} | ||||
| 	} else { | ||||
| 		// image and video uploads send no username, we have to do this ourself here #715 | ||||
| 		_, err := b.mc.SendText(channel, msg.Username) | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("file comment failed: %#v", err) | ||||
| 		} | ||||
| 	// image and video uploads send no username, we have to do this ourself here #715 | ||||
| 	_, err := b.mc.SendFormattedText(channel, username.plain+fi.Comment, username.formatted+fi.Comment) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("file comment failed: %#v", err) | ||||
| 	} | ||||
|  | ||||
| 	b.Log.Debugf("uploading file: %s %s", fi.Name, mtype) | ||||
| 	res, err := b.mc.UploadToContentRepo(content, mtype, int64(len(*fi.Data))) | ||||
| 	if err != nil { | ||||
| @@ -327,34 +445,34 @@ func (b *Bmatrix) handleUploadFile(msg *config.Message, channel string, fi *conf | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("sendImage failed: %#v", err) | ||||
| 		} | ||||
| 	case strings.Contains(mtype, "application"): | ||||
| 		b.Log.Debugf("sendFile %s", res.ContentURI) | ||||
| 		_, err = b.mc.SendFile(channel, fi.Name, res.ContentURI, mtype, uint(len(*fi.Data))) | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("sendFile failed: %#v", err) | ||||
| 		} | ||||
| 	case strings.Contains(mtype, "audio"): | ||||
| 		b.Log.Debugf("sendAudio %s", res.ContentURI) | ||||
| 		_, err = b.mc.SendAudio(channel, fi.Name, res.ContentURI, mtype, uint(len(*fi.Data))) | ||||
| 		_, err = b.mc.SendMessageEvent(channel, "m.room.message", matrix.AudioMessage{ | ||||
| 			MsgType: "m.audio", | ||||
| 			Body:    fi.Name, | ||||
| 			URL:     res.ContentURI, | ||||
| 			Info: matrix.AudioInfo{ | ||||
| 				Mimetype: mtype, | ||||
| 				Size:     uint(len(*fi.Data)), | ||||
| 			}, | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("sendAudio failed: %#v", err) | ||||
| 		} | ||||
| 	default: | ||||
| 		b.Log.Debugf("sendFile %s", res.ContentURI) | ||||
| 		_, err = b.mc.SendMessageEvent(channel, "m.room.message", matrix.FileMessage{ | ||||
| 			MsgType: "m.file", | ||||
| 			Body:    fi.Name, | ||||
| 			URL:     res.ContentURI, | ||||
| 			Info: matrix.FileInfo{ | ||||
| 				Mimetype: mtype, | ||||
| 				Size:     uint(len(*fi.Data)), | ||||
| 			}, | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("sendFile failed: %#v", err) | ||||
| 		} | ||||
| 	} | ||||
| 	b.Log.Debugf("result: %#v", res) | ||||
| } | ||||
|  | ||||
| // skipMessages returns true if this message should not be handled | ||||
| func (b *Bmatrix) containsAttachment(content map[string]interface{}) bool { | ||||
| 	// Skip empty messages | ||||
| 	if content["msgtype"] == nil { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	// Only allow image,video or file msgtypes | ||||
| 	if !(content["msgtype"].(string) == "m.image" || | ||||
| 		content["msgtype"].(string) == "m.video" || | ||||
| 		content["msgtype"].(string) == "m.file") { | ||||
| 		return false | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
|   | ||||
							
								
								
									
										28
									
								
								bridge/matrix/matrix_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								bridge/matrix/matrix_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| package bmatrix | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestPlainUsername(t *testing.T) { | ||||
| 	uut := newMatrixUsername("MyUser") | ||||
|  | ||||
| 	assert.Equal(t, "MyUser", uut.formatted) | ||||
| 	assert.Equal(t, "MyUser", uut.plain) | ||||
| } | ||||
|  | ||||
| func TestHTMLUsername(t *testing.T) { | ||||
| 	uut := newMatrixUsername("<b>MyUser</b>") | ||||
|  | ||||
| 	assert.Equal(t, "<b>MyUser</b>", uut.formatted) | ||||
| 	assert.Equal(t, "MyUser", uut.plain) | ||||
| } | ||||
|  | ||||
| func TestFancyUsername(t *testing.T) { | ||||
| 	uut := newMatrixUsername("<MyUser>") | ||||
|  | ||||
| 	assert.Equal(t, "<MyUser>", uut.formatted) | ||||
| 	assert.Equal(t, "<MyUser>", uut.plain) | ||||
| } | ||||
| @@ -4,7 +4,7 @@ import ( | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/42wim/matterbridge/bridge/helper" | ||||
| 	"github.com/42wim/matterbridge/matterclient" | ||||
| 	"github.com/mattermost/mattermost-server/model" | ||||
| 	"github.com/mattermost/mattermost-server/v5/model" | ||||
| ) | ||||
|  | ||||
| // handleDownloadAvatar downloads the avatar of userid from channel | ||||
|   | ||||
| @@ -7,7 +7,7 @@ import ( | ||||
| 	"github.com/42wim/matterbridge/bridge/helper" | ||||
| 	"github.com/42wim/matterbridge/matterclient" | ||||
| 	"github.com/42wim/matterbridge/matterhook" | ||||
| 	"github.com/mattermost/mattermost-server/model" | ||||
| 	"github.com/mattermost/mattermost-server/v5/model" | ||||
| ) | ||||
|  | ||||
| func (b *Bmattermost) doConnectWebhookBind() error { | ||||
|   | ||||
							
								
								
									
										101
									
								
								bridge/msteams/handler.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								bridge/msteams/handler.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | ||||
| package bmsteams | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/42wim/matterbridge/bridge/helper" | ||||
|  | ||||
| 	msgraph "github.com/yaegashi/msgraph.go/beta" | ||||
| ) | ||||
|  | ||||
| func (b *Bmsteams) findFile(weburl string) (string, error) { | ||||
| 	itemRB, err := b.gc.GetDriveItemByURL(b.ctx, weburl) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	itemRB.Workbook().Worksheets() | ||||
| 	b.gc.Workbooks() | ||||
| 	item, err := itemRB.Request().Get(b.ctx) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	if url, ok := item.GetAdditionalData("@microsoft.graph.downloadUrl"); ok { | ||||
| 		return url.(string), nil | ||||
| 	} | ||||
| 	return "", nil | ||||
| } | ||||
|  | ||||
| // handleDownloadFile handles file download | ||||
| func (b *Bmsteams) handleDownloadFile(rmsg *config.Message, filename, weburl string) error { | ||||
| 	realURL, err := b.findFile(weburl) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	// Actually download the file. | ||||
| 	data, err := helper.DownloadFile(realURL) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("download %s failed %#v", weburl, err) | ||||
| 	} | ||||
|  | ||||
| 	// If a comment is attached to the file(s) it is in the 'Text' field of the teams messge event | ||||
| 	// and should be added as comment to only one of the files. We reset the 'Text' field to ensure | ||||
| 	// that the comment is not duplicated. | ||||
| 	comment := rmsg.Text | ||||
| 	rmsg.Text = "" | ||||
| 	helper.HandleDownloadData(b.Log, rmsg, filename, comment, weburl, data, b.General) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Bmsteams) handleAttachments(rmsg *config.Message, msg msgraph.ChatMessage) { | ||||
| 	for _, a := range msg.Attachments { | ||||
| 		//remove the attachment tags from the text | ||||
| 		rmsg.Text = attachRE.ReplaceAllString(rmsg.Text, "") | ||||
|  | ||||
| 		//handle a code snippet (code block) | ||||
| 		if *a.ContentType == "application/vnd.microsoft.card.codesnippet" { | ||||
| 			b.handleCodeSnippet(rmsg, a) | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		//handle the download | ||||
| 		err := b.handleDownloadFile(rmsg, *a.Name, *a.ContentURL) | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("download of %s failed: %s", *a.Name, err) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type AttachContent struct { | ||||
| 	Language       string `json:"language"` | ||||
| 	CodeSnippetURL string `json:"codeSnippetUrl"` | ||||
| } | ||||
|  | ||||
| func (b *Bmsteams) handleCodeSnippet(rmsg *config.Message, attach msgraph.ChatMessageAttachment) { | ||||
| 	var content AttachContent | ||||
| 	err := json.Unmarshal([]byte(*attach.Content), &content) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("unmarshal codesnippet failed: %s", err) | ||||
| 		return | ||||
| 	} | ||||
| 	s := strings.Split(content.CodeSnippetURL, "/") | ||||
| 	if len(s) != 13 { | ||||
| 		b.Log.Errorf("codesnippetUrl has unexpected size: %s", content.CodeSnippetURL) | ||||
| 		return | ||||
| 	} | ||||
| 	resp, err := b.gc.Teams().Request().Client().Get(content.CodeSnippetURL) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("retrieving snippet content failed:%s", err) | ||||
| 		return | ||||
| 	} | ||||
| 	defer resp.Body.Close() | ||||
| 	res, err := ioutil.ReadAll(resp.Body) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("reading snippet data failed: %s", err) | ||||
| 		return | ||||
| 	} | ||||
| 	rmsg.Text = rmsg.Text + "\n```" + content.Language + "\n" + string(res) + "\n```\n" | ||||
| } | ||||
							
								
								
									
										224
									
								
								bridge/msteams/msteams.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								bridge/msteams/msteams.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,224 @@ | ||||
| package bmsteams | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge" | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/davecgh/go-spew/spew" | ||||
|  | ||||
| 	"github.com/mattn/godown" | ||||
| 	msgraph "github.com/yaegashi/msgraph.go/beta" | ||||
| 	"github.com/yaegashi/msgraph.go/msauth" | ||||
|  | ||||
| 	"golang.org/x/oauth2" | ||||
| ) | ||||
|  | ||||
| var defaultScopes = []string{"openid", "profile", "offline_access", "Group.Read.All", "Group.ReadWrite.All"} | ||||
| var attachRE = regexp.MustCompile(`<attachment id=.*?attachment>`) | ||||
|  | ||||
| type Bmsteams struct { | ||||
| 	gc    *msgraph.GraphServiceRequestBuilder | ||||
| 	ctx   context.Context | ||||
| 	botID string | ||||
| 	*bridge.Config | ||||
| } | ||||
|  | ||||
| func New(cfg *bridge.Config) bridge.Bridger { | ||||
| 	return &Bmsteams{Config: cfg} | ||||
| } | ||||
|  | ||||
| func (b *Bmsteams) Connect() error { | ||||
| 	tokenCachePath := b.GetString("sessionFile") | ||||
| 	if tokenCachePath == "" { | ||||
| 		tokenCachePath = "msteams_session.json" | ||||
| 	} | ||||
| 	ctx := context.Background() | ||||
| 	m := msauth.NewManager() | ||||
| 	m.LoadFile(tokenCachePath) //nolint:errcheck | ||||
| 	ts, err := m.DeviceAuthorizationGrant(ctx, b.GetString("TenantID"), b.GetString("ClientID"), defaultScopes, nil) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	err = m.SaveFile(tokenCachePath) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("Couldn't save sessionfile in %s: %s", tokenCachePath, err) | ||||
| 	} | ||||
| 	// make file readable only for matterbridge user | ||||
| 	err = os.Chmod(tokenCachePath, 0600) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("Couldn't change permissions for %s: %s", tokenCachePath, err) | ||||
| 	} | ||||
| 	httpClient := oauth2.NewClient(ctx, ts) | ||||
| 	graphClient := msgraph.NewClient(httpClient) | ||||
| 	b.gc = graphClient | ||||
| 	b.ctx = ctx | ||||
|  | ||||
| 	err = b.setBotID() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	b.Log.Info("Connection succeeded") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Bmsteams) Disconnect() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Bmsteams) JoinChannel(channel config.ChannelInfo) error { | ||||
| 	go func(name string) { | ||||
| 		for { | ||||
| 			err := b.poll(name) | ||||
| 			if err != nil { | ||||
| 				b.Log.Errorf("polling failed for %s: %s. retrying in 5 seconds", name, err) | ||||
| 			} | ||||
| 			time.Sleep(time.Second * 5) | ||||
| 		} | ||||
| 	}(channel.Name) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Bmsteams) Send(msg config.Message) (string, error) { | ||||
| 	b.Log.Debugf("=> Receiving %#v", msg) | ||||
| 	if msg.ParentID != "" && msg.ParentID != "msg-parent-not-found" { | ||||
| 		return b.sendReply(msg) | ||||
| 	} | ||||
| 	if msg.ParentID == "msg-parent-not-found" { | ||||
| 		msg.ParentID = "" | ||||
| 		msg.Text = fmt.Sprintf("[thread]: %s", msg.Text) | ||||
| 	} | ||||
| 	ct := b.gc.Teams().ID(b.GetString("TeamID")).Channels().ID(msg.Channel).Messages().Request() | ||||
| 	text := msg.Username + msg.Text | ||||
| 	content := &msgraph.ItemBody{Content: &text} | ||||
| 	rmsg := &msgraph.ChatMessage{Body: content} | ||||
| 	res, err := ct.Add(b.ctx, rmsg) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return *res.ID, nil | ||||
| } | ||||
|  | ||||
| func (b *Bmsteams) sendReply(msg config.Message) (string, error) { | ||||
| 	ct := b.gc.Teams().ID(b.GetString("TeamID")).Channels().ID(msg.Channel).Messages().ID(msg.ParentID).Replies().Request() | ||||
| 	// Handle prefix hint for unthreaded messages. | ||||
|  | ||||
| 	text := msg.Username + msg.Text | ||||
| 	content := &msgraph.ItemBody{Content: &text} | ||||
| 	rmsg := &msgraph.ChatMessage{Body: content} | ||||
| 	res, err := ct.Add(b.ctx, rmsg) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return *res.ID, nil | ||||
| } | ||||
|  | ||||
| func (b *Bmsteams) getMessages(channel string) ([]msgraph.ChatMessage, error) { | ||||
| 	ct := b.gc.Teams().ID(b.GetString("TeamID")).Channels().ID(channel).Messages().Request() | ||||
| 	rct, err := ct.Get(b.ctx) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	b.Log.Debugf("got %#v messages", len(rct)) | ||||
| 	return rct, nil | ||||
| } | ||||
|  | ||||
| //nolint:gocognit | ||||
| func (b *Bmsteams) poll(channelName string) error { | ||||
| 	msgmap := make(map[string]time.Time) | ||||
| 	b.Log.Debug("getting initial messages") | ||||
| 	res, err := b.getMessages(channelName) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	for _, msg := range res { | ||||
| 		msgmap[*msg.ID] = *msg.CreatedDateTime | ||||
| 		if msg.LastModifiedDateTime != nil { | ||||
| 			msgmap[*msg.ID] = *msg.LastModifiedDateTime | ||||
| 		} | ||||
| 	} | ||||
| 	time.Sleep(time.Second * 5) | ||||
| 	b.Log.Debug("polling for messages") | ||||
| 	for { | ||||
| 		res, err := b.getMessages(channelName) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		for i := len(res) - 1; i >= 0; i-- { | ||||
| 			msg := res[i] | ||||
| 			if mtime, ok := msgmap[*msg.ID]; ok { | ||||
| 				if mtime == *msg.CreatedDateTime && msg.LastModifiedDateTime == nil { | ||||
| 					continue | ||||
| 				} | ||||
| 				if msg.LastModifiedDateTime != nil && mtime == *msg.LastModifiedDateTime { | ||||
| 					continue | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			if b.GetBool("debug") { | ||||
| 				b.Log.Debug("Msg dump: ", spew.Sdump(msg)) | ||||
| 			} | ||||
|  | ||||
| 			// skip non-user message for now. | ||||
| 			if msg.From.User == nil { | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			if *msg.From.User.ID == b.botID { | ||||
| 				b.Log.Debug("skipping own message") | ||||
| 				msgmap[*msg.ID] = *msg.CreatedDateTime | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			msgmap[*msg.ID] = *msg.CreatedDateTime | ||||
| 			if msg.LastModifiedDateTime != nil { | ||||
| 				msgmap[*msg.ID] = *msg.LastModifiedDateTime | ||||
| 			} | ||||
| 			b.Log.Debugf("<= Sending message from %s on %s to gateway", *msg.From.User.DisplayName, b.Account) | ||||
| 			text := b.convertToMD(*msg.Body.Content) | ||||
| 			rmsg := config.Message{ | ||||
| 				Username: *msg.From.User.DisplayName, | ||||
| 				Text:     text, | ||||
| 				Channel:  channelName, | ||||
| 				Account:  b.Account, | ||||
| 				Avatar:   "", | ||||
| 				UserID:   *msg.From.User.ID, | ||||
| 				ID:       *msg.ID, | ||||
| 				Extra:    make(map[string][]interface{}), | ||||
| 			} | ||||
|  | ||||
| 			b.handleAttachments(&rmsg, msg) | ||||
| 			b.Log.Debugf("<= Message is %#v", rmsg) | ||||
| 			b.Remote <- rmsg | ||||
| 		} | ||||
| 		time.Sleep(time.Second * 5) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *Bmsteams) setBotID() error { | ||||
| 	req := b.gc.Me().Request() | ||||
| 	r, err := req.Get(b.ctx) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	b.botID = *r.ID | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Bmsteams) convertToMD(text string) string { | ||||
| 	if !strings.Contains(text, "<div>") { | ||||
| 		return text | ||||
| 	} | ||||
| 	var sb strings.Builder | ||||
| 	err := godown.Convert(&sb, strings.NewReader(text), nil) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("Couldn't convert message to markdown %s", text) | ||||
| 		return text | ||||
| 	} | ||||
| 	return sb.String() | ||||
| } | ||||
							
								
								
									
										90
									
								
								bridge/mumble/handlers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								bridge/mumble/handlers.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| package bmumble | ||||
|  | ||||
| import ( | ||||
| 	"strconv" | ||||
| 	"time" | ||||
|  | ||||
| 	"layeh.com/gumble/gumble" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/42wim/matterbridge/bridge/helper" | ||||
| ) | ||||
|  | ||||
| func (b *Bmumble) handleServerConfig(event *gumble.ServerConfigEvent) { | ||||
| 	b.serverConfigUpdate <- *event | ||||
| } | ||||
|  | ||||
| func (b *Bmumble) handleTextMessage(event *gumble.TextMessageEvent) { | ||||
| 	sender := "unknown" | ||||
| 	if event.TextMessage.Sender != nil { | ||||
| 		sender = event.TextMessage.Sender.Name | ||||
| 	} | ||||
| 	// Convert Mumble HTML messages to markdown | ||||
| 	parts, err := b.convertHTMLtoMarkdown(event.TextMessage.Message) | ||||
| 	if err != nil { | ||||
| 		b.Log.Error(err) | ||||
| 	} | ||||
| 	now := time.Now().UTC() | ||||
| 	for i, part := range parts { | ||||
| 		// Construct matterbridge message and pass on to the gateway | ||||
| 		rmsg := config.Message{ | ||||
| 			Channel:  strconv.FormatUint(uint64(event.Client.Self.Channel.ID), 10), | ||||
| 			Username: sender, | ||||
| 			UserID:   sender + "@" + b.Host, | ||||
| 			Account:  b.Account, | ||||
| 		} | ||||
| 		if part.Image == nil { | ||||
| 			rmsg.Text = part.Text | ||||
| 		} else { | ||||
| 			fname := b.Account + "_" + strconv.FormatInt(now.UnixNano(), 10) + "_" + strconv.Itoa(i) + part.FileExtension | ||||
| 			rmsg.Extra = make(map[string][]interface{}) | ||||
| 			if err = helper.HandleDownloadSize(b.Log, &rmsg, fname, int64(len(part.Image)), b.General); err != nil { | ||||
| 				b.Log.WithError(err).Warn("not including image in message") | ||||
| 				continue | ||||
| 			} | ||||
| 			helper.HandleDownloadData(b.Log, &rmsg, fname, "", "", &part.Image, b.General) | ||||
| 		} | ||||
| 		b.Log.Debugf("Sending message to gateway: %+v", rmsg) | ||||
| 		b.Remote <- rmsg | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *Bmumble) handleConnect(event *gumble.ConnectEvent) { | ||||
| 	// Set the user's "bio"/comment | ||||
| 	if comment := b.GetString("UserComment"); comment != "" && event.Client.Self != nil { | ||||
| 		event.Client.Self.SetComment(comment) | ||||
| 	} | ||||
| 	// No need to talk or listen | ||||
| 	event.Client.Self.SetSelfDeafened(true) | ||||
| 	event.Client.Self.SetSelfMuted(true) | ||||
| 	// if the Channel variable is set, this is a reconnect -> rejoin channel | ||||
| 	if b.Channel != nil { | ||||
| 		if err := b.doJoin(event.Client, *b.Channel); err != nil { | ||||
| 			b.Log.Error(err) | ||||
| 		} | ||||
| 		b.Remote <- config.Message{ | ||||
| 			Username: "system", | ||||
| 			Text:     "rejoin", | ||||
| 			Channel:  "", | ||||
| 			Account:  b.Account, | ||||
| 			Event:    config.EventRejoinChannels, | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *Bmumble) handleUserChange(event *gumble.UserChangeEvent) { | ||||
| 	// Only care about changes to self | ||||
| 	if event.User != event.Client.Self { | ||||
| 		return | ||||
| 	} | ||||
| 	// Someone attempted to move the user out of the configured channel; attempt to join back | ||||
| 	if b.Channel != nil { | ||||
| 		if err := b.doJoin(event.Client, *b.Channel); err != nil { | ||||
| 			b.Log.Error(err) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *Bmumble) handleDisconnect(event *gumble.DisconnectEvent) { | ||||
| 	b.connected <- *event | ||||
| } | ||||
							
								
								
									
										143
									
								
								bridge/mumble/helpers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								bridge/mumble/helpers.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | ||||
| package bmumble | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"mime" | ||||
| 	"net/http" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/mattn/godown" | ||||
| 	"github.com/vincent-petithory/dataurl" | ||||
| ) | ||||
|  | ||||
| type MessagePart struct { | ||||
| 	Text          string | ||||
| 	FileExtension string | ||||
| 	Image         []byte | ||||
| } | ||||
|  | ||||
| func (b *Bmumble) decodeImage(uri string, parts *[]MessagePart) error { | ||||
| 	// Decode the data:image/... URI | ||||
| 	image, err := dataurl.DecodeString(uri) | ||||
| 	if err != nil { | ||||
| 		b.Log.WithError(err).Info("No image extracted") | ||||
| 		return err | ||||
| 	} | ||||
| 	// Determine the file extensions for that image | ||||
| 	ext, err := mime.ExtensionsByType(image.MediaType.ContentType()) | ||||
| 	if err != nil || len(ext) == 0 { | ||||
| 		b.Log.WithError(err).Infof("No file extension registered for MIME type '%s'", image.MediaType.ContentType()) | ||||
| 		return err | ||||
| 	} | ||||
| 	// Add the image to the MessagePart slice | ||||
| 	*parts = append(*parts, MessagePart{"", ext[0], image.Data}) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Bmumble) tokenize(t *string) ([]MessagePart, error) { | ||||
| 	// `^(.*?)` matches everything before the image | ||||
| 	// `!\[[^\]]*\]\(` matches the `]+)` matches the data: URI used by Mumble | ||||
| 	// `\)` matches the closing parenthesis after the URI | ||||
| 	// `(.*)$` matches the remaining text to be examined in the next iteration | ||||
| 	p := regexp.MustCompile(`^(?ms)(.*?)!\[[^\]]*\]\((data:image\/[^)]+)\)(.*)$`) | ||||
| 	remaining := *t | ||||
| 	var parts []MessagePart | ||||
| 	for { | ||||
| 		tokens := p.FindStringSubmatch(remaining) | ||||
| 		if tokens == nil { | ||||
| 			// no match -> remaining string is non-image text | ||||
| 			pre := strings.TrimSpace(remaining) | ||||
| 			if len(pre) > 0 { | ||||
| 				parts = append(parts, MessagePart{pre, "", nil}) | ||||
| 			} | ||||
| 			return parts, nil | ||||
| 		} | ||||
|  | ||||
| 		// tokens[1] is the text before the image | ||||
| 		if len(tokens[1]) > 0 { | ||||
| 			pre := strings.TrimSpace(tokens[1]) | ||||
| 			parts = append(parts, MessagePart{pre, "", nil}) | ||||
| 		} | ||||
| 		// tokens[2] is the image URL | ||||
| 		uri, err := dataurl.UnescapeToString(strings.TrimSpace(strings.ReplaceAll(tokens[2], " ", ""))) | ||||
| 		if err != nil { | ||||
| 			b.Log.WithError(err).Info("URL unescaping failed") | ||||
| 			remaining = strings.TrimSpace(tokens[3]) | ||||
| 			continue | ||||
| 		} | ||||
| 		err = b.decodeImage(uri, &parts) | ||||
| 		if err != nil { | ||||
| 			b.Log.WithError(err).Info("Decoding the image failed") | ||||
| 		} | ||||
| 		// tokens[3] is the text after the image, processed in the next iteration | ||||
| 		remaining = strings.TrimSpace(tokens[3]) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *Bmumble) convertHTMLtoMarkdown(html string) ([]MessagePart, error) { | ||||
| 	var sb strings.Builder | ||||
| 	err := godown.Convert(&sb, strings.NewReader(html), nil) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	markdown := sb.String() | ||||
| 	b.Log.Debugf("### to markdown: %s", markdown) | ||||
| 	return b.tokenize(&markdown) | ||||
| } | ||||
|  | ||||
| func (b *Bmumble) extractFiles(msg *config.Message) []config.Message { | ||||
| 	var messages []config.Message | ||||
| 	if msg.Extra == nil || len(msg.Extra["file"]) == 0 { | ||||
| 		return messages | ||||
| 	} | ||||
| 	// Create a separate message for each file | ||||
| 	for _, f := range msg.Extra["file"] { | ||||
| 		fi := f.(config.FileInfo) | ||||
| 		imsg := config.Message{ | ||||
| 			Channel:   msg.Channel, | ||||
| 			Username:  msg.Username, | ||||
| 			UserID:    msg.UserID, | ||||
| 			Account:   msg.Account, | ||||
| 			Protocol:  msg.Protocol, | ||||
| 			Timestamp: msg.Timestamp, | ||||
| 			Event:     "mumble_image", | ||||
| 		} | ||||
| 		// If no data is present for the file, send a link instead | ||||
| 		if fi.Data == nil || len(*fi.Data) == 0 { | ||||
| 			if len(fi.URL) > 0 { | ||||
| 				imsg.Text = fmt.Sprintf(`<a href="%s">%s</a>`, fi.URL, fi.URL) | ||||
| 				messages = append(messages, imsg) | ||||
| 			} else { | ||||
| 				b.Log.Infof("Not forwarding file without local data") | ||||
| 			} | ||||
| 			continue | ||||
| 		} | ||||
| 		mimeType := http.DetectContentType(*fi.Data) | ||||
| 		// Mumble only supports images natively, send a link instead | ||||
| 		if !strings.HasPrefix(mimeType, "image/") { | ||||
| 			if len(fi.URL) > 0 { | ||||
| 				imsg.Text = fmt.Sprintf(`<a href="%s">%s</a>`, fi.URL, fi.URL) | ||||
| 				messages = append(messages, imsg) | ||||
| 			} else { | ||||
| 				b.Log.Infof("Not forwarding file of type %s", mimeType) | ||||
| 			} | ||||
| 			continue | ||||
| 		} | ||||
| 		mimeType = strings.TrimSpace(strings.Split(mimeType, ";")[0]) | ||||
| 		// Build data:image/...;base64,... style image URL and embed image directly into the message | ||||
| 		du := dataurl.New(*fi.Data, mimeType) | ||||
| 		dataURL, err := du.MarshalText() | ||||
| 		if err != nil { | ||||
| 			b.Log.WithError(err).Infof("Image Serialization into data URL failed (type: %s, length: %d)", mimeType, len(*fi.Data)) | ||||
| 			continue | ||||
| 		} | ||||
| 		imsg.Text = fmt.Sprintf(`<img src="%s"/>`, dataURL) | ||||
| 		messages = append(messages, imsg) | ||||
| 	} | ||||
| 	// Remove files from original message | ||||
| 	msg.Extra["file"] = nil | ||||
| 	return messages | ||||
| } | ||||
							
								
								
									
										259
									
								
								bridge/mumble/mumble.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								bridge/mumble/mumble.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,259 @@ | ||||
| package bmumble | ||||
|  | ||||
| import ( | ||||
| 	"crypto/tls" | ||||
| 	"crypto/x509" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"net" | ||||
| 	"strconv" | ||||
| 	"time" | ||||
|  | ||||
| 	"layeh.com/gumble/gumble" | ||||
| 	"layeh.com/gumble/gumbleutil" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge" | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/42wim/matterbridge/bridge/helper" | ||||
| 	stripmd "github.com/writeas/go-strip-markdown" | ||||
|  | ||||
| 	// We need to import the 'data' package as an implicit dependency. | ||||
| 	// See: https://godoc.org/github.com/paulrosania/go-charset/charset | ||||
| 	_ "github.com/paulrosania/go-charset/data" | ||||
| ) | ||||
|  | ||||
| type Bmumble struct { | ||||
| 	client             *gumble.Client | ||||
| 	Nick               string | ||||
| 	Host               string | ||||
| 	Channel            *uint32 | ||||
| 	local              chan config.Message | ||||
| 	running            chan error | ||||
| 	connected          chan gumble.DisconnectEvent | ||||
| 	serverConfigUpdate chan gumble.ServerConfigEvent | ||||
| 	serverConfig       gumble.ServerConfigEvent | ||||
| 	tlsConfig          tls.Config | ||||
|  | ||||
| 	*bridge.Config | ||||
| } | ||||
|  | ||||
| func New(cfg *bridge.Config) bridge.Bridger { | ||||
| 	b := &Bmumble{} | ||||
| 	b.Config = cfg | ||||
| 	b.Nick = b.GetString("Nick") | ||||
| 	b.local = make(chan config.Message) | ||||
| 	b.running = make(chan error) | ||||
| 	b.connected = make(chan gumble.DisconnectEvent) | ||||
| 	b.serverConfigUpdate = make(chan gumble.ServerConfigEvent) | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| func (b *Bmumble) Connect() error { | ||||
| 	b.Log.Infof("Connecting %s", b.GetString("Server")) | ||||
| 	host, portstr, err := net.SplitHostPort(b.GetString("Server")) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	b.Host = host | ||||
| 	_, err = strconv.Atoi(portstr) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if err = b.buildTLSConfig(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	go b.doSend() | ||||
| 	go b.connectLoop() | ||||
| 	err = <-b.running | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func (b *Bmumble) Disconnect() error { | ||||
| 	return b.client.Disconnect() | ||||
| } | ||||
|  | ||||
| func (b *Bmumble) JoinChannel(channel config.ChannelInfo) error { | ||||
| 	cid, err := strconv.ParseUint(channel.Name, 10, 32) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	channelID := uint32(cid) | ||||
| 	if b.Channel != nil && *b.Channel != channelID { | ||||
| 		b.Log.Fatalf("Cannot join channel ID '%d', already joined to channel ID %d", channelID, *b.Channel) | ||||
| 		return errors.New("the Mumble bridge can only join a single channel") | ||||
| 	} | ||||
| 	b.Channel = &channelID | ||||
| 	return b.doJoin(b.client, channelID) | ||||
| } | ||||
|  | ||||
| func (b *Bmumble) Send(msg config.Message) (string, error) { | ||||
| 	// Only process text messages | ||||
| 	b.Log.Debugf("=> Received local message %#v", msg) | ||||
| 	if msg.Event != "" && msg.Event != config.EventUserAction { | ||||
| 		return "", nil | ||||
| 	} | ||||
|  | ||||
| 	attachments := b.extractFiles(&msg) | ||||
| 	b.local <- msg | ||||
| 	for _, a := range attachments { | ||||
| 		b.local <- a | ||||
| 	} | ||||
| 	return "", nil | ||||
| } | ||||
|  | ||||
| func (b *Bmumble) buildTLSConfig() error { | ||||
| 	b.tlsConfig = tls.Config{} | ||||
| 	// Load TLS client certificate keypair required for registered user authentication | ||||
| 	if cpath := b.GetString("TLSClientCertificate"); cpath != "" { | ||||
| 		if ckey := b.GetString("TLSClientKey"); ckey != "" { | ||||
| 			cert, err := tls.LoadX509KeyPair(cpath, ckey) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			b.tlsConfig.Certificates = []tls.Certificate{cert} | ||||
| 		} | ||||
| 	} | ||||
| 	// Load TLS CA used for server verification.  If not provided, the Go system trust anchor is used | ||||
| 	if capath := b.GetString("TLSCACertificate"); capath != "" { | ||||
| 		ca, err := ioutil.ReadFile(capath) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		b.tlsConfig.RootCAs = x509.NewCertPool() | ||||
| 		b.tlsConfig.RootCAs.AppendCertsFromPEM(ca) | ||||
| 	} | ||||
| 	b.tlsConfig.InsecureSkipVerify = b.GetBool("SkipTLSVerify") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Bmumble) connectLoop() { | ||||
| 	firstConnect := true | ||||
| 	for { | ||||
| 		err := b.doConnect() | ||||
| 		if firstConnect { | ||||
| 			b.running <- err | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("Connection to server failed: %#v", err) | ||||
| 			if firstConnect { | ||||
| 				break | ||||
| 			} else { | ||||
| 				b.Log.Info("Retrying in 10s") | ||||
| 				time.Sleep(10 * time.Second) | ||||
| 				continue | ||||
| 			} | ||||
| 		} | ||||
| 		firstConnect = false | ||||
| 		d := <-b.connected | ||||
| 		switch d.Type { | ||||
| 		case gumble.DisconnectError: | ||||
| 			b.Log.Errorf("Lost connection to the server (%s), attempting reconnect", d.String) | ||||
| 			continue | ||||
| 		case gumble.DisconnectKicked: | ||||
| 			b.Log.Errorf("Kicked from the server (%s), attempting reconnect", d.String) | ||||
| 			continue | ||||
| 		case gumble.DisconnectBanned: | ||||
| 			b.Log.Errorf("Banned from the server (%s), not attempting reconnect", d.String) | ||||
| 			close(b.connected) | ||||
| 			close(b.running) | ||||
| 			return | ||||
| 		case gumble.DisconnectUser: | ||||
| 			b.Log.Infof("Disconnect successful") | ||||
| 			close(b.connected) | ||||
| 			close(b.running) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *Bmumble) doConnect() error { | ||||
| 	// Create new gumble config and attach event handlers | ||||
| 	gumbleConfig := gumble.NewConfig() | ||||
| 	gumbleConfig.Attach(gumbleutil.Listener{ | ||||
| 		ServerConfig: b.handleServerConfig, | ||||
| 		TextMessage:  b.handleTextMessage, | ||||
| 		Connect:      b.handleConnect, | ||||
| 		Disconnect:   b.handleDisconnect, | ||||
| 		UserChange:   b.handleUserChange, | ||||
| 	}) | ||||
| 	gumbleConfig.Username = b.GetString("Nick") | ||||
| 	if password := b.GetString("Password"); password != "" { | ||||
| 		gumbleConfig.Password = password | ||||
| 	} | ||||
|  | ||||
| 	client, err := gumble.DialWithDialer(new(net.Dialer), b.GetString("Server"), gumbleConfig, &b.tlsConfig) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	b.client = client | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Bmumble) doJoin(client *gumble.Client, channelID uint32) error { | ||||
| 	channel, ok := client.Channels[channelID] | ||||
| 	if !ok { | ||||
| 		return fmt.Errorf("no channel with ID %d", channelID) | ||||
| 	} | ||||
| 	client.Self.Move(channel) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Bmumble) doSend() { | ||||
| 	// Message sending loop that makes sure server-side | ||||
| 	// restrictions and client-side message traits don't conflict | ||||
| 	// with each other. | ||||
| 	for { | ||||
| 		select { | ||||
| 		case serverConfig := <-b.serverConfigUpdate: | ||||
| 			b.Log.Debugf("Received server config update: AllowHTML=%#v, MaximumMessageLength=%#v", serverConfig.AllowHTML, serverConfig.MaximumMessageLength) | ||||
| 			b.serverConfig = serverConfig | ||||
| 		case msg := <-b.local: | ||||
| 			b.processMessage(&msg) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *Bmumble) processMessage(msg *config.Message) { | ||||
| 	b.Log.Debugf("Processing message %s", msg.Text) | ||||
|  | ||||
| 	allowHTML := true | ||||
| 	if b.serverConfig.AllowHTML != nil { | ||||
| 		allowHTML = *b.serverConfig.AllowHTML | ||||
| 	} | ||||
|  | ||||
| 	// If this is a specially generated image message, send it unmodified | ||||
| 	if msg.Event == "mumble_image" { | ||||
| 		if allowHTML { | ||||
| 			b.client.Self.Channel.Send(msg.Username+msg.Text, false) | ||||
| 		} else { | ||||
| 			b.Log.Info("Can't send image, server does not allow HTML messages") | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// Don't process empty messages | ||||
| 	if len(msg.Text) == 0 { | ||||
| 		return | ||||
| 	} | ||||
| 	// If HTML is allowed, convert markdown into HTML, otherwise strip markdown | ||||
| 	if allowHTML { | ||||
| 		msg.Text = helper.ParseMarkdown(msg.Text) | ||||
| 	} else { | ||||
| 		msg.Text = stripmd.Strip(msg.Text) | ||||
| 	} | ||||
|  | ||||
| 	// If there is a maximum message length, split and truncate the lines | ||||
| 	var msgLines []string | ||||
| 	if maxLength := b.serverConfig.MaximumMessageLength; maxLength != nil { | ||||
| 		msgLines = helper.GetSubLines(msg.Text, *maxLength-len(msg.Username)) | ||||
| 	} else { | ||||
| 		msgLines = helper.GetSubLines(msg.Text, 0) | ||||
| 	} | ||||
| 	// Send the individual lindes | ||||
| 	for i := range msgLines { | ||||
| 		b.client.Self.Channel.Send(msg.Username+msgLines[i], false) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										203
									
								
								bridge/nctalk/nctalk.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								bridge/nctalk/nctalk.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,203 @@ | ||||
| package nctalk | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"crypto/tls" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge" | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
|  | ||||
| 	"gomod.garykim.dev/nc-talk/ocs" | ||||
| 	"gomod.garykim.dev/nc-talk/room" | ||||
| 	"gomod.garykim.dev/nc-talk/user" | ||||
| ) | ||||
|  | ||||
| type Btalk struct { | ||||
| 	user  *user.TalkUser | ||||
| 	rooms []Broom | ||||
| 	*bridge.Config | ||||
| } | ||||
|  | ||||
| func New(cfg *bridge.Config) bridge.Bridger { | ||||
| 	return &Btalk{Config: cfg} | ||||
| } | ||||
|  | ||||
| type Broom struct { | ||||
| 	room      *room.TalkRoom | ||||
| 	ctx       context.Context | ||||
| 	ctxCancel context.CancelFunc | ||||
| } | ||||
|  | ||||
| func (b *Btalk) Connect() error { | ||||
| 	b.Log.Info("Connecting") | ||||
| 	tconfig := &user.TalkUserConfig{ | ||||
| 		TLSConfig: &tls.Config{ | ||||
| 			InsecureSkipVerify: b.GetBool("SkipTLSVerify"), //nolint:gosec | ||||
| 		}, | ||||
| 	} | ||||
| 	var err error | ||||
| 	b.user, err = user.NewUser(b.GetString("Server"), b.GetString("Login"), b.GetString("Password"), tconfig) | ||||
| 	if err != nil { | ||||
| 		b.Log.Error("Config could not be used") | ||||
| 		return err | ||||
| 	} | ||||
| 	_, err = b.user.Capabilities() | ||||
| 	if err != nil { | ||||
| 		b.Log.Error("Cannot Connect") | ||||
| 		return err | ||||
| 	} | ||||
| 	b.Log.Info("Connected") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Btalk) Disconnect() error { | ||||
| 	for _, r := range b.rooms { | ||||
| 		r.ctxCancel() | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Btalk) JoinChannel(channel config.ChannelInfo) error { | ||||
| 	tr, err := room.NewTalkRoom(b.user, channel.Name) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	newRoom := Broom{ | ||||
| 		room: tr, | ||||
| 	} | ||||
| 	newRoom.ctx, newRoom.ctxCancel = context.WithCancel(context.Background()) | ||||
| 	c, err := newRoom.room.ReceiveMessages(newRoom.ctx) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	b.rooms = append(b.rooms, newRoom) | ||||
|  | ||||
| 	// Config | ||||
| 	guestSuffix := " (Guest)" | ||||
| 	if b.IsKeySet("GuestSuffix") { | ||||
| 		guestSuffix = b.GetString("GuestSuffix") | ||||
| 	} | ||||
|  | ||||
| 	go func() { | ||||
| 		for msg := range c { | ||||
| 			msg := msg | ||||
| 			// ignore messages that are one of the following | ||||
| 			// * not a message from a user | ||||
| 			// * from ourselves | ||||
| 			if msg.MessageType != ocs.MessageComment || msg.ActorID == b.user.User { | ||||
| 				continue | ||||
| 			} | ||||
| 			remoteMessage := config.Message{ | ||||
| 				Text:     formatRichObjectString(msg.Message, msg.MessageParameters), | ||||
| 				Channel:  newRoom.room.Token, | ||||
| 				Username: DisplayName(msg, guestSuffix), | ||||
| 				UserID:   msg.ActorID, | ||||
| 				Account:  b.Account, | ||||
| 			} | ||||
| 			// It is possible for the ID to not be set on older versions of Talk so we only set it if | ||||
| 			// the ID is not blank | ||||
| 			if msg.ID != 0 { | ||||
| 				remoteMessage.ID = strconv.Itoa(msg.ID) | ||||
| 			} | ||||
|  | ||||
| 			// Handle Files | ||||
| 			err = b.handleFiles(&remoteMessage, &msg) | ||||
| 			if err != nil { | ||||
| 				b.Log.Errorf("Error handling file: %#v", msg) | ||||
|  | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			b.Log.Debugf("<= Message is %#v", remoteMessage) | ||||
| 			b.Remote <- remoteMessage | ||||
| 		} | ||||
| 	}() | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Btalk) Send(msg config.Message) (string, error) { | ||||
| 	r := b.getRoom(msg.Channel) | ||||
| 	if r == nil { | ||||
| 		b.Log.Errorf("Could not find room for %v", msg.Channel) | ||||
| 		return "", nil | ||||
| 	} | ||||
|  | ||||
| 	// Talk currently only supports sending normal messages | ||||
| 	if msg.Event != "" { | ||||
| 		return "", nil | ||||
| 	} | ||||
| 	sentMessage, err := r.room.SendMessage(msg.Username + msg.Text) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("Could not send message to room %v from %v: %v", msg.Channel, msg.Username, err) | ||||
| 		return "", nil | ||||
| 	} | ||||
| 	return strconv.Itoa(sentMessage.ID), nil | ||||
| } | ||||
|  | ||||
| func (b *Btalk) getRoom(token string) *Broom { | ||||
| 	for _, r := range b.rooms { | ||||
| 		if r.room.Token == token { | ||||
| 			return &r | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Btalk) handleFiles(mmsg *config.Message, message *ocs.TalkRoomMessageData) error { | ||||
| 	for _, parameter := range message.MessageParameters { | ||||
| 		if parameter.Type == ocs.ROSTypeFile { | ||||
| 			// Get the file | ||||
| 			file, err := b.user.DownloadFile(parameter.Path) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
|  | ||||
| 			if mmsg.Extra == nil { | ||||
| 				mmsg.Extra = make(map[string][]interface{}) | ||||
| 			} | ||||
|  | ||||
| 			mmsg.Extra["file"] = append(mmsg.Extra["file"], config.FileInfo{ | ||||
| 				Name:   parameter.Name, | ||||
| 				Data:   file, | ||||
| 				Size:   int64(len(*file)), | ||||
| 				Avatar: false, | ||||
| 			}) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Spec: https://github.com/nextcloud/server/issues/1706#issue-182308785 | ||||
| func formatRichObjectString(message string, parameters map[string]ocs.RichObjectString) string { | ||||
| 	for id, parameter := range parameters { | ||||
| 		text := parameter.Name | ||||
|  | ||||
| 		switch parameter.Type { | ||||
| 		case ocs.ROSTypeUser, ocs.ROSTypeGroup: | ||||
| 			text = "@" + text | ||||
| 		case ocs.ROSTypeFile: | ||||
| 			if parameter.Link != "" { | ||||
| 				text = parameter.Name | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		message = strings.ReplaceAll(message, "{"+id+"}", text) | ||||
| 	} | ||||
|  | ||||
| 	return message | ||||
| } | ||||
|  | ||||
| func DisplayName(msg ocs.TalkRoomMessageData, suffix string) string { | ||||
| 	if msg.ActorType == ocs.ActorGuest { | ||||
| 		if msg.ActorDisplayName == "" { | ||||
| 			return "Guest" | ||||
| 		} | ||||
|  | ||||
| 		return msg.ActorDisplayName + suffix | ||||
| 	} | ||||
|  | ||||
| 	return msg.ActorDisplayName | ||||
| } | ||||
| @@ -2,6 +2,7 @@ package brocketchat | ||||
|  | ||||
| import ( | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/matterbridge/Rocket.Chat.Go.SDK/models" | ||||
| ) | ||||
|  | ||||
| func (b *Brocketchat) handleRocket() { | ||||
| @@ -38,6 +39,23 @@ func (b *Brocketchat) handleRocketHook(messages chan *config.Message) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *Brocketchat) handleStatusEvent(ev models.Message, rmsg *config.Message) bool { | ||||
| 	switch ev.Type { | ||||
| 	case "": | ||||
| 		// this is a normal message, no processing needed | ||||
| 		// return true so the message is not dropped | ||||
| 		return true | ||||
| 	case sUserJoined, sUserLeft: | ||||
| 		rmsg.Event = config.EventJoinLeave | ||||
| 		return true | ||||
| 	case sRoomChangedTopic: | ||||
| 		rmsg.Event = config.EventTopicChange | ||||
| 		return true | ||||
| 	} | ||||
| 	b.Log.Debugf("Dropping message with unknown type: %s", ev.Type) | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func (b *Brocketchat) handleRocketClient(messages chan *config.Message) { | ||||
| 	for message := range b.messageChan { | ||||
| 		// skip messages with same ID, apparently messages get duplicated for an unknown reason | ||||
| @@ -59,7 +77,12 @@ func (b *Brocketchat) handleRocketClient(messages chan *config.Message) { | ||||
| 			UserID:   message.User.ID, | ||||
| 			ID:       message.ID, | ||||
| 		} | ||||
| 		messages <- rmsg | ||||
|  | ||||
| 		// handleStatusEvent returns false if the message should be dropped | ||||
| 		// in that case it is probably some modification to the channel we do not want to relay | ||||
| 		if b.handleStatusEvent(m, rmsg) { | ||||
| 			messages <- rmsg | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -29,6 +29,12 @@ type Brocketchat struct { | ||||
| 	sync.RWMutex | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	sUserJoined       = "uj" | ||||
| 	sUserLeft         = "ul" | ||||
| 	sRoomChangedTopic = "room_changed_topic" | ||||
| ) | ||||
|  | ||||
| func New(cfg *bridge.Config) bridge.Bridger { | ||||
| 	newCache, err := lru.New(100) | ||||
| 	if err != nil { | ||||
|   | ||||
| @@ -1,18 +1,22 @@ | ||||
| package bslack | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"html" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/42wim/matterbridge/bridge/helper" | ||||
| 	"github.com/nlopes/slack" | ||||
| 	"github.com/slack-go/slack" | ||||
| ) | ||||
|  | ||||
| // ErrEventIgnored is for events that should be ignored | ||||
| var ErrEventIgnored = errors.New("this event message should ignored") | ||||
|  | ||||
| func (b *Bslack) handleSlack() { | ||||
| 	messages := make(chan *config.Message) | ||||
| 	if b.GetString(incomingWebhookConfig) != "" { | ||||
| 	if b.GetString(incomingWebhookConfig) != "" && b.GetString(tokenConfig) == "" { | ||||
| 		b.Log.Debugf("Choosing webhooks based receiving") | ||||
| 		go b.handleMatterHook(messages) | ||||
| 	} else { | ||||
| @@ -53,7 +57,9 @@ func (b *Bslack) handleSlackClient(messages chan *config.Message) { | ||||
| 				continue | ||||
| 			} | ||||
| 			rmsg, err := b.handleTypingEvent(ev) | ||||
| 			if err != nil { | ||||
| 			if err == ErrEventIgnored { | ||||
| 				continue | ||||
| 			} else if err != nil { | ||||
| 				b.Log.Errorf("%#v", err) | ||||
| 				continue | ||||
| 			} | ||||
| @@ -87,7 +93,7 @@ func (b *Bslack) handleSlackClient(messages chan *config.Message) { | ||||
| 			b.Log.Errorf("Connection failed %#v %#v", ev.Error(), ev.ErrorObj) | ||||
| 		case *slack.MemberJoinedChannelEvent: | ||||
| 			b.users.populateUser(ev.User) | ||||
| 		case *slack.HelloEvent, *slack.LatencyReport: | ||||
| 		case *slack.HelloEvent, *slack.LatencyReport, *slack.ConnectingEvent: | ||||
| 			continue | ||||
| 		default: | ||||
| 			b.Log.Debugf("Unhandled incoming event: %T", ev) | ||||
| @@ -124,11 +130,11 @@ func (b *Bslack) skipMessageEvent(ev *slack.MessageEvent) bool { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Skip any messages that we made ourselves or from 'slackbot' (see #527). | ||||
| 	if ev.Username == sSlackBotUser || | ||||
| 		(b.rtm != nil && ev.Username == b.si.User.Name) || | ||||
| 		(len(ev.Attachments) > 0 && ev.Attachments[0].CallbackID == "matterbridge_"+b.uuid) { | ||||
| 		return true | ||||
| 	// Check for our callback ID | ||||
| 	hasOurCallbackID := false | ||||
| 	if len(ev.Blocks.BlockSet) == 1 { | ||||
| 		block, ok := ev.Blocks.BlockSet[0].(*slack.SectionBlock) | ||||
| 		hasOurCallbackID = ok && block.BlockID == "matterbridge_"+b.uuid | ||||
| 	} | ||||
|  | ||||
| 	if ev.SubMessage != nil { | ||||
| @@ -143,6 +149,16 @@ func (b *Bslack) skipMessageEvent(ev *slack.MessageEvent) bool { | ||||
| 		if ev.SubType == "message_replied" && ev.Hidden { | ||||
| 			return true | ||||
| 		} | ||||
| 		if len(ev.SubMessage.Blocks.BlockSet) == 1 { | ||||
| 			block, ok := ev.SubMessage.Blocks.BlockSet[0].(*slack.SectionBlock) | ||||
| 			hasOurCallbackID = ok && block.BlockID == "matterbridge_"+b.uuid | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Skip any messages that we made ourselves or from 'slackbot' (see #527). | ||||
| 	if ev.Username == sSlackBotUser || | ||||
| 		(b.rtm != nil && ev.Username == b.si.User.Name) || hasOurCallbackID { | ||||
| 		return true | ||||
| 	} | ||||
|  | ||||
| 	if len(ev.Files) > 0 { | ||||
| @@ -270,6 +286,9 @@ func (b *Bslack) handleAttachments(ev *slack.MessageEvent, rmsg *config.Message) | ||||
| } | ||||
|  | ||||
| func (b *Bslack) handleTypingEvent(ev *slack.UserTypingEvent) (*config.Message, error) { | ||||
| 	if ev.User == b.si.User.ID { | ||||
| 		return nil, ErrEventIgnored | ||||
| 	} | ||||
| 	channelInfo, err := b.channels.getChannelByID(ev.Channel) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
|   | ||||
| @@ -7,8 +7,8 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/nlopes/slack" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/slack-go/slack" | ||||
| ) | ||||
|  | ||||
| // populateReceivedMessage shapes the initial Matterbridge message that we will forward to the | ||||
|   | ||||
| @@ -5,7 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge" | ||||
| 	"github.com/42wim/matterbridge/matterhook" | ||||
| 	"github.com/nlopes/slack" | ||||
| 	"github.com/slack-go/slack" | ||||
| ) | ||||
|  | ||||
| type BLegacy struct { | ||||
|   | ||||
| @@ -13,8 +13,8 @@ import ( | ||||
| 	"github.com/42wim/matterbridge/bridge/helper" | ||||
| 	"github.com/42wim/matterbridge/matterhook" | ||||
| 	lru "github.com/hashicorp/golang-lru" | ||||
| 	"github.com/nlopes/slack" | ||||
| 	"github.com/rs/xid" | ||||
| 	"github.com/slack-go/slack" | ||||
| ) | ||||
|  | ||||
| type Bslack struct { | ||||
| @@ -64,6 +64,7 @@ const ( | ||||
| 	editSuffixConfig      = "EditSuffix" | ||||
| 	iconURLConfig         = "iconurl" | ||||
| 	noSendJoinConfig      = "nosendjoinpart" | ||||
| 	messageLength         = 3000 | ||||
| ) | ||||
|  | ||||
| func New(cfg *bridge.Config) bridge.Bridger { | ||||
| @@ -194,6 +195,7 @@ func (b *Bslack) Send(msg config.Message) (string, error) { | ||||
| 		b.Log.Debugf("=> Receiving %#v", msg) | ||||
| 	} | ||||
|  | ||||
| 	msg.Text = helper.ClipMessage(msg.Text, messageLength) | ||||
| 	msg.Text = b.replaceCodeFence(msg.Text) | ||||
|  | ||||
| 	// Make a action /me of the message | ||||
| @@ -202,7 +204,7 @@ func (b *Bslack) Send(msg config.Message) (string, error) { | ||||
| 	} | ||||
|  | ||||
| 	// Use webhook to send the message | ||||
| 	if b.GetString(outgoingWebhookConfig) != "" { | ||||
| 	if b.GetString(outgoingWebhookConfig) != "" && b.GetString(tokenConfig) == "" { | ||||
| 		return "", b.sendWebhook(msg) | ||||
| 	} | ||||
| 	return b.sendRTM(msg) | ||||
| @@ -408,7 +410,6 @@ func (b *Bslack) editMessage(msg *config.Message, channelInfo *slack.Channel) (b | ||||
| 	} | ||||
| 	messageOptions := b.prepareMessageOptions(msg) | ||||
| 	for { | ||||
| 		messageOptions = append(messageOptions, slack.MsgOptionText(msg.Text, false)) | ||||
| 		_, _, _, err := b.rtm.UpdateMessage(channelInfo.ID, msg.ID, messageOptions...) | ||||
| 		if err == nil { | ||||
| 			return true, nil | ||||
| @@ -427,11 +428,6 @@ func (b *Bslack) postMessage(msg *config.Message, channelInfo *slack.Channel) (s | ||||
| 		return "", nil | ||||
| 	} | ||||
| 	messageOptions := b.prepareMessageOptions(msg) | ||||
| 	messageOptions = append( | ||||
| 		messageOptions, | ||||
| 		slack.MsgOptionText(msg.Text, false), | ||||
| 		slack.MsgOptionEnableLinkUnfurl(), | ||||
| 	) | ||||
| 	for { | ||||
| 		_, id, err := b.rtm.PostMessage(channelInfo.ID, messageOptions...) | ||||
| 		if err == nil { | ||||
| @@ -497,8 +493,6 @@ func (b *Bslack) prepareMessageOptions(msg *config.Message) []slack.MsgOption { | ||||
| 	} | ||||
|  | ||||
| 	var attachments []slack.Attachment | ||||
| 	// add a callback ID so we can see we created it | ||||
| 	attachments = append(attachments, slack.Attachment{CallbackID: "matterbridge_" + b.uuid}) | ||||
| 	// add file attachments | ||||
| 	attachments = append(attachments, b.createAttach(msg.Extra)...) | ||||
| 	// add slack attachments (from another slack bridge) | ||||
| @@ -509,6 +503,19 @@ func (b *Bslack) prepareMessageOptions(msg *config.Message) []slack.MsgOption { | ||||
| 	} | ||||
|  | ||||
| 	var opts []slack.MsgOption | ||||
| 	opts = append(opts, | ||||
| 		// provide regular text field (fallback used in Slack notifications, etc.) | ||||
| 		slack.MsgOptionText(msg.Text, false), | ||||
|  | ||||
| 		// add a callback ID so we can see we created it | ||||
| 		slack.MsgOptionBlocks(slack.NewSectionBlock( | ||||
| 			slack.NewTextBlockObject(slack.MarkdownType, msg.Text, false, false), | ||||
| 			nil, nil, | ||||
| 			slack.SectionBlockOptionBlockID("matterbridge_"+b.uuid), | ||||
| 		)), | ||||
|  | ||||
| 		slack.MsgOptionEnableLinkUnfurl(), | ||||
| 	) | ||||
| 	opts = append(opts, slack.MsgOptionAttachments(attachments...)) | ||||
| 	opts = append(opts, slack.MsgOptionPostMessageParameters(params)) | ||||
| 	return opts | ||||
|   | ||||
| @@ -8,8 +8,8 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/nlopes/slack" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/slack-go/slack" | ||||
| ) | ||||
|  | ||||
| const minimumRefreshInterval = 10 * time.Second | ||||
|   | ||||
| @@ -130,6 +130,10 @@ func (b *Bsshchat) handleSSHChat() error { | ||||
| 			if strings.Contains(b.r.Text(), "Rate limiting is in effect") { | ||||
| 				continue | ||||
| 			} | ||||
| 			// skip our own messages | ||||
| 			if !strings.HasPrefix(b.r.Text(), "["+b.GetString("Nick")+"] \x1b") { | ||||
| 				continue | ||||
| 			} | ||||
| 			res := strings.Split(stripPrompt(b.r.Text()), ":") | ||||
| 			if res[0] == "-> Set theme" { | ||||
| 				wait = false | ||||
|   | ||||
| @@ -39,22 +39,32 @@ func (b *Btelegram) handleGroups(rmsg *config.Message, message *tgbotapi.Message | ||||
|  | ||||
| // handleForwarded handles forwarded messages | ||||
| func (b *Btelegram) handleForwarded(rmsg *config.Message, message *tgbotapi.Message) { | ||||
| 	if message.ForwardFrom != nil { | ||||
| 		usernameForward := "" | ||||
| 		if b.GetBool("UseFirstName") { | ||||
| 	if message.ForwardDate == 0 { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if message.ForwardFrom == nil { | ||||
| 		rmsg.Text = "Forwarded from " + unknownUser + ": " + rmsg.Text | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	usernameForward := "" | ||||
| 	if b.GetBool("UseFirstName") { | ||||
| 		usernameForward = message.ForwardFrom.FirstName | ||||
| 	} | ||||
|  | ||||
| 	if usernameForward == "" { | ||||
| 		usernameForward = message.ForwardFrom.UserName | ||||
| 		if usernameForward == "" { | ||||
| 			usernameForward = message.ForwardFrom.FirstName | ||||
| 		} | ||||
| 		if usernameForward == "" { | ||||
| 			usernameForward = message.ForwardFrom.UserName | ||||
| 			if usernameForward == "" { | ||||
| 				usernameForward = message.ForwardFrom.FirstName | ||||
| 			} | ||||
| 		} | ||||
| 		if usernameForward == "" { | ||||
| 			usernameForward = unknownUser | ||||
| 		} | ||||
| 		rmsg.Text = "Forwarded from " + usernameForward + ": " + rmsg.Text | ||||
| 	} | ||||
|  | ||||
| 	if usernameForward == "" { | ||||
| 		usernameForward = unknownUser | ||||
| 	} | ||||
|  | ||||
| 	rmsg.Text = "Forwarded from " + usernameForward + ": " + rmsg.Text | ||||
| } | ||||
|  | ||||
| // handleQuoting handles quoting of previous messages | ||||
| @@ -95,7 +105,7 @@ func (b *Btelegram) handleUsername(rmsg *config.Message, message *tgbotapi.Messa | ||||
| 			} | ||||
| 		} | ||||
| 		// only download avatars if we have a place to upload them (configured mediaserver) | ||||
| 		if b.General.MediaServerUpload != "" { | ||||
| 		if b.General.MediaServerUpload != "" || (b.General.MediaServerDownload != "" && b.General.MediaDownloadPath != "") { | ||||
| 			b.handleDownloadAvatar(message.From.ID, rmsg.Channel) | ||||
| 		} | ||||
| 	} | ||||
| @@ -207,6 +217,46 @@ func (b *Btelegram) handleDownloadAvatar(userid int, channel string) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *Btelegram) maybeConvertTgs(name *string, data *[]byte) { | ||||
| 	var format string | ||||
| 	switch b.GetString("MediaConvertTgs") { | ||||
| 	case FormatWebp: | ||||
| 		b.Log.Debugf("Tgs to WebP conversion enabled, converting %v", name) | ||||
| 		format = FormatWebp | ||||
| 	case FormatPng: | ||||
| 		// The WebP to PNG converter can't handle animated webp files yet, | ||||
| 		// and I'm not going to write a path for x/image/webp. | ||||
| 		// The error message would be: | ||||
| 		//     conversion failed: webp: non-Alpha VP8X is not implemented | ||||
| 		// So instead, we tell lottie to directly go to PNG. | ||||
| 		b.Log.Debugf("Tgs to PNG conversion enabled, converting %v", name) | ||||
| 		format = FormatPng | ||||
| 	default: | ||||
| 		// Otherwise, no conversion was requested. Trying to run the usual webp | ||||
| 		// converter would fail, because '.tgs.webp' is actually a gzipped JSON | ||||
| 		// file, and has nothing to do with WebP. | ||||
| 		return | ||||
| 	} | ||||
| 	err := helper.ConvertTgsToX(data, format, b.Log) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("conversion failed: %v", err) | ||||
| 	} else { | ||||
| 		*name = strings.Replace(*name, "tgs.webp", format, 1) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *Btelegram) maybeConvertWebp(name *string, data *[]byte) { | ||||
| 	if b.GetBool("MediaConvertWebPToPNG") { | ||||
| 		b.Log.Debugf("WebP to PNG conversion enabled, converting %v", name) | ||||
| 		err := helper.ConvertWebPToPNG(data) | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("conversion failed: %v", err) | ||||
| 		} else { | ||||
| 			*name = strings.Replace(*name, ".webp", ".png", 1) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // handleDownloadFile handles file download | ||||
| func (b *Btelegram) handleDownload(rmsg *config.Message, message *tgbotapi.Message) error { | ||||
| 	size := 0 | ||||
| @@ -254,15 +304,13 @@ func (b *Btelegram) handleDownload(rmsg *config.Message, message *tgbotapi.Messa | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if strings.HasSuffix(name, ".webp") && b.GetBool("MediaConvertWebPToPNG") { | ||||
| 		b.Log.Debugf("WebP to PNG conversion enabled, converting %s", name) | ||||
| 		err := helper.ConvertWebPToPNG(data) | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("conversion failed: %s", err) | ||||
| 		} else { | ||||
| 			name = strings.Replace(name, ".webp", ".png", 1) | ||||
| 		} | ||||
|  | ||||
| 	if strings.HasSuffix(name, ".tgs.webp") { | ||||
| 		b.maybeConvertTgs(&name, data) | ||||
| 	} else if strings.HasSuffix(name, ".webp") { | ||||
| 		b.maybeConvertWebp(&name, data) | ||||
| 	} | ||||
|  | ||||
| 	helper.HandleDownloadData(b.Log, rmsg, name, message.Caption, "", data, b.General) | ||||
| 	return nil | ||||
| } | ||||
| @@ -312,6 +360,9 @@ func (b *Btelegram) handleEdit(msg *config.Message, chatid int64) (string, error | ||||
| 	case "Markdown": | ||||
| 		b.Log.Debug("Using mode markdown") | ||||
| 		m.ParseMode = tgbotapi.ModeMarkdown | ||||
| 	case MarkdownV2: | ||||
| 		b.Log.Debug("Using mode MarkdownV2") | ||||
| 		m.ParseMode = MarkdownV2 | ||||
| 	} | ||||
| 	if strings.ToLower(b.GetString("MessageFormat")) == HTMLNick { | ||||
| 		b.Log.Debug("Using mode HTML - nick only") | ||||
| @@ -357,6 +408,14 @@ func (b *Btelegram) handleQuote(message, quoteNick, quoteMessage string) string | ||||
| 	if format == "" { | ||||
| 		format = "{MESSAGE} (re @{QUOTENICK}: {QUOTEMESSAGE})" | ||||
| 	} | ||||
| 	quoteMessagelength := len(quoteMessage) | ||||
| 	if b.GetInt("QuoteLengthLimit") != 0 && quoteMessagelength >= b.GetInt("QuoteLengthLimit") { | ||||
| 		runes := []rune(quoteMessage) | ||||
| 		quoteMessage = string(runes[0:b.GetInt("QuoteLengthLimit")]) | ||||
| 		if quoteMessagelength > b.GetInt("QuoteLengthLimit") { | ||||
| 			quoteMessage += "..." | ||||
| 		} | ||||
| 	} | ||||
| 	format = strings.Replace(format, "{MESSAGE}", message, -1) | ||||
| 	format = strings.Replace(format, "{QUOTENICK}", quoteNick, -1) | ||||
| 	format = strings.Replace(format, "{QUOTEMESSAGE}", quoteMessage, -1) | ||||
|   | ||||
| @@ -2,19 +2,23 @@ package btelegram | ||||
|  | ||||
| import ( | ||||
| 	"html" | ||||
| 	"log" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge" | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/42wim/matterbridge/bridge/helper" | ||||
| 	"github.com/go-telegram-bot-api/telegram-bot-api" | ||||
| 	tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	unknownUser = "unknown" | ||||
| 	HTMLFormat  = "HTML" | ||||
| 	HTMLNick    = "htmlnick" | ||||
| 	MarkdownV2  = "MarkdownV2" | ||||
| 	FormatPng   = "png" | ||||
| 	FormatWebp  = "webp" | ||||
| ) | ||||
|  | ||||
| type Btelegram struct { | ||||
| @@ -24,6 +28,16 @@ type Btelegram struct { | ||||
| } | ||||
|  | ||||
| func New(cfg *bridge.Config) bridge.Bridger { | ||||
| 	tgsConvertFormat := cfg.GetString("MediaConvertTgs") | ||||
| 	if tgsConvertFormat != "" { | ||||
| 		err := helper.CanConvertTgsToX() | ||||
| 		if err != nil { | ||||
| 			log.Fatalf("Telegram bridge configured to convert .tgs files to '%s', but lottie does not appear to work:\n%#v", tgsConvertFormat, err) | ||||
| 		} | ||||
| 		if tgsConvertFormat != FormatPng && tgsConvertFormat != FormatWebp { | ||||
| 			log.Fatalf("Telegram bridge configured to convert .tgs files to '%s', but only '%s' and '%s' are supported.", FormatPng, FormatWebp, tgsConvertFormat) | ||||
| 		} | ||||
| 	} | ||||
| 	return &Btelegram{Config: cfg, avatarMap: make(map[string]string)} | ||||
| } | ||||
|  | ||||
| @@ -81,8 +95,8 @@ func (b *Btelegram) Send(msg config.Message) (string, error) { | ||||
| 	// Upload a file if it exists | ||||
| 	if msg.Extra != nil { | ||||
| 		for _, rmsg := range helper.HandleExtra(&msg, b.General) { | ||||
| 			if _, err := b.sendMessage(chatid, rmsg.Username, rmsg.Text); err != nil { | ||||
| 				b.Log.Errorf("sendMessage failed: %s", err) | ||||
| 			if _, msgErr := b.sendMessage(chatid, rmsg.Username, rmsg.Text); msgErr != nil { | ||||
| 				b.Log.Errorf("sendMessage failed: %s", msgErr) | ||||
| 			} | ||||
| 		} | ||||
| 		// check if we have files to upload (from slack, telegram or mattermost) | ||||
| @@ -97,7 +111,14 @@ func (b *Btelegram) Send(msg config.Message) (string, error) { | ||||
| 	} | ||||
|  | ||||
| 	// Post normal message | ||||
| 	return b.sendMessage(chatid, msg.Username, msg.Text) | ||||
| 	// TODO: recheck it. | ||||
| 	// Ignore empty text field needs for prevent double messages from whatsapp to telegram | ||||
| 	// when sending media with text caption | ||||
| 	if msg.Text != "" { | ||||
| 		return b.sendMessage(chatid, msg.Username, msg.Text) | ||||
| 	} | ||||
|  | ||||
| 	return "", nil | ||||
| } | ||||
|  | ||||
| func (b *Btelegram) getFileDirectURL(id string) string { | ||||
| @@ -119,11 +140,18 @@ func (b *Btelegram) sendMessage(chatid int64, username, text string) (string, er | ||||
| 		b.Log.Debug("Using mode markdown") | ||||
| 		m.ParseMode = tgbotapi.ModeMarkdown | ||||
| 	} | ||||
| 	if b.GetString("MessageFormat") == MarkdownV2 { | ||||
| 		b.Log.Debug("Using mode MarkdownV2") | ||||
| 		m.ParseMode = MarkdownV2 | ||||
| 	} | ||||
| 	if strings.ToLower(b.GetString("MessageFormat")) == HTMLNick { | ||||
| 		b.Log.Debug("Using mode HTML - nick only") | ||||
| 		m.Text = username + html.EscapeString(text) | ||||
| 		m.ParseMode = tgbotapi.ModeHTML | ||||
| 	} | ||||
|  | ||||
| 	m.DisableWebPagePreview = b.GetBool("DisableWebPagePreview") | ||||
|  | ||||
| 	res, err := b.c.Send(m) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
|   | ||||
| @@ -1,11 +1,15 @@ | ||||
| package bwhatsapp | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"mime" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/42wim/matterbridge/bridge/helper" | ||||
| 	"github.com/Rhymen/go-whatsapp" | ||||
| 	"github.com/jpillora/backoff" | ||||
| ) | ||||
|  | ||||
| /* | ||||
| @@ -19,10 +23,43 @@ Check: | ||||
| // HandleError received from WhatsApp | ||||
| func (b *Bwhatsapp) HandleError(err error) { | ||||
| 	// ignore received invalid data errors. https://github.com/42wim/matterbridge/issues/843 | ||||
| 	if strings.Contains(err.Error(), "error processing data: received invalid data") { | ||||
| 	// ignore tag 174 errors. https://github.com/42wim/matterbridge/issues/1094 | ||||
| 	if strings.Contains(err.Error(), "error processing data: received invalid data") || strings.Contains(err.Error(), "invalid string with tag 174") { | ||||
| 		return | ||||
| 	} | ||||
| 	b.Log.Errorf("%v", err) // TODO implement proper handling? at least respond to different error types | ||||
|  | ||||
| 	switch err.(type) { | ||||
| 	case *whatsapp.ErrConnectionClosed, *whatsapp.ErrConnectionFailed: | ||||
| 		b.reconnect(err) | ||||
| 	default: | ||||
| 		switch err { | ||||
| 		case whatsapp.ErrConnectionTimeout: | ||||
| 			b.reconnect(err) | ||||
| 		default: | ||||
| 			b.Log.Errorf("%v", err) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *Bwhatsapp) reconnect(err error) { | ||||
| 	bf := &backoff.Backoff{ | ||||
| 		Min:    time.Second, | ||||
| 		Max:    5 * time.Minute, | ||||
| 		Jitter: true, | ||||
| 	} | ||||
| 	for { | ||||
| 		d := bf.Duration() | ||||
| 		b.Log.Errorf("Connection failed, underlying error: %v", err) | ||||
| 		b.Log.Infof("Waiting %s...", d) | ||||
| 		time.Sleep(d) | ||||
| 		b.Log.Info("Reconnecting...") | ||||
| 		err := b.conn.Restore() | ||||
| 		if err == nil { | ||||
| 			bf.Reset() | ||||
| 			b.startedAt = uint64(time.Now().Unix()) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // HandleTextMessage sent from WhatsApp, relay it to the brige | ||||
| @@ -36,16 +73,18 @@ func (b *Bwhatsapp) HandleTextMessage(message whatsapp.TextMessage) { | ||||
| 	} | ||||
|  | ||||
| 	messageTime := time.Unix(int64(message.Info.Timestamp), 0) // TODO check how behaves between timezones | ||||
| 	groupJid := message.Info.RemoteJid | ||||
| 	groupJID := message.Info.RemoteJid | ||||
|  | ||||
| 	senderJid := message.Info.SenderJid | ||||
| 	if len(senderJid) == 0 { | ||||
| 	senderJID := message.Info.SenderJid | ||||
| 	if len(senderJID) == 0 { | ||||
| 		// TODO workaround till https://github.com/Rhymen/go-whatsapp/issues/86 resolved | ||||
| 		senderJid = *message.Info.Source.Participant | ||||
| 		if message.Info.Source != nil && message.Info.Source.Participant != nil { | ||||
| 			senderJID = *message.Info.Source.Participant | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// translate sender's Jid to the nicest username we can get | ||||
| 	senderName := b.getSenderName(senderJid) | ||||
| 	// translate sender's JID to the nicest username we can get | ||||
| 	senderName := b.getSenderName(senderJID) | ||||
| 	if senderName == "" { | ||||
| 		senderName = "Someone" // don't expose telephone number | ||||
| 	} | ||||
| @@ -53,8 +92,8 @@ func (b *Bwhatsapp) HandleTextMessage(message whatsapp.TextMessage) { | ||||
| 	extText := message.Info.Source.Message.ExtendedTextMessage | ||||
| 	if extText != nil && extText.ContextInfo != nil && extText.ContextInfo.MentionedJid != nil { | ||||
| 		// handle user mentions | ||||
| 		for _, mentionedJid := range extText.ContextInfo.MentionedJid { | ||||
| 			numberAndSuffix := strings.SplitN(mentionedJid, "@", 2) | ||||
| 		for _, mentionedJID := range extText.ContextInfo.MentionedJid { | ||||
| 			numberAndSuffix := strings.SplitN(mentionedJID, "@", 2) | ||||
|  | ||||
| 			// mentions comes as telephone numbers and we don't want to expose it to other bridges | ||||
| 			// replace it with something more meaninful to others | ||||
| @@ -66,22 +105,22 @@ func (b *Bwhatsapp) HandleTextMessage(message whatsapp.TextMessage) { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	b.Log.Debugf("<= Sending message from %s on %s to gateway", senderJid, b.Account) | ||||
| 	b.Log.Debugf("<= Sending message from %s on %s to gateway", senderJID, b.Account) | ||||
| 	rmsg := config.Message{ | ||||
| 		UserID:    senderJid, | ||||
| 		UserID:    senderJID, | ||||
| 		Username:  senderName, | ||||
| 		Text:      message.Text, | ||||
| 		Timestamp: messageTime, | ||||
| 		Channel:   groupJid, | ||||
| 		Channel:   groupJID, | ||||
| 		Account:   b.Account, | ||||
| 		Protocol:  b.Protocol, | ||||
| 		Extra:     make(map[string][]interface{}), | ||||
| 		//		ParentID: TODO, // TODO handle thread replies  // map from Info.QuotedMessageID string | ||||
| 		//	ParentID: TODO, // TODO handle thread replies  // map from Info.QuotedMessageID string | ||||
| 		//	Event     string    `json:"event"` | ||||
| 		//	Gateway   string  // will be added during message processing | ||||
| 		ID: message.Info.Id} | ||||
|  | ||||
| 	if avatarURL, exists := b.userAvatars[senderJid]; exists { | ||||
| 	if avatarURL, exists := b.userAvatars[senderJID]; exists { | ||||
| 		rmsg.Avatar = avatarURL | ||||
| 	} | ||||
|  | ||||
| @@ -89,11 +128,77 @@ func (b *Bwhatsapp) HandleTextMessage(message whatsapp.TextMessage) { | ||||
| 	b.Remote <- rmsg | ||||
| } | ||||
|  | ||||
| // | ||||
| //func (b *Bwhatsapp) HandleImageMessage(message whatsapp.ImageMessage) { | ||||
| //	fmt.Println(message) // TODO implement | ||||
| //} | ||||
| // | ||||
| // HandleImageMessage sent from WhatsApp, relay it to the brige | ||||
| func (b *Bwhatsapp) HandleImageMessage(message whatsapp.ImageMessage) { | ||||
| 	if message.Info.FromMe { // || !strings.Contains(strings.ToLower(message.Text), "@echo") { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// whatsapp sends last messages to show context , cut them | ||||
| 	if message.Info.Timestamp < b.startedAt { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	messageTime := time.Unix(int64(message.Info.Timestamp), 0) // TODO check how behaves between timezones | ||||
| 	groupJID := message.Info.RemoteJid | ||||
|  | ||||
| 	senderJID := message.Info.SenderJid | ||||
| 	if len(senderJID) == 0 { | ||||
| 		// TODO workaround till https://github.com/Rhymen/go-whatsapp/issues/86 resolved | ||||
| 		if message.Info.Source != nil && message.Info.Source.Participant != nil { | ||||
| 			senderJID = *message.Info.Source.Participant | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// translate sender's Jid to the nicest username we can get | ||||
| 	senderName := b.getSenderName(senderJID) | ||||
| 	if senderName == "" { | ||||
| 		senderName = "Someone" // don't expose telephone number | ||||
| 	} | ||||
|  | ||||
| 	b.Log.Debugf("<= Sending message from %s on %s to gateway", senderJID, b.Account) | ||||
| 	rmsg := config.Message{ | ||||
| 		UserID:    senderJID, | ||||
| 		Username:  senderName, | ||||
| 		Timestamp: messageTime, | ||||
| 		Channel:   groupJID, | ||||
| 		Account:   b.Account, | ||||
| 		Protocol:  b.Protocol, | ||||
| 		Extra:     make(map[string][]interface{}), | ||||
| 		//  ParentID: TODO,      // TODO handle thread replies  // map from Info.QuotedMessageID string | ||||
| 		//  Event     string    `json:"event"` | ||||
| 		//  Gateway   string     // will be added during message processing | ||||
| 		ID: message.Info.Id} | ||||
|  | ||||
| 	if avatarURL, exists := b.userAvatars[senderJID]; exists { | ||||
| 		rmsg.Avatar = avatarURL | ||||
| 	} | ||||
|  | ||||
| 	// Download and unencrypt content | ||||
| 	data, err := message.Download() | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("%v", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// Get file extension by mimetype | ||||
| 	fileExt, err := mime.ExtensionsByType(message.Type) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("%v", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	filename := fmt.Sprintf("%v%v", message.Info.Id, fileExt[0]) | ||||
|  | ||||
| 	b.Log.Debugf("<= Image downloaded and unencrypted") | ||||
|  | ||||
| 	// Move file to bridge storage | ||||
| 	helper.HandleDownloadData(b.Log, &rmsg, filename, message.Caption, "", &data, b.General) | ||||
|  | ||||
| 	b.Log.Debugf("<= Image Message is %#v", rmsg) | ||||
| 	b.Remote <- rmsg | ||||
| } | ||||
|  | ||||
| //func (b *Bwhatsapp) HandleVideoMessage(message whatsapp.VideoMessage) { | ||||
| //	fmt.Println(message) // TODO implement | ||||
| //} | ||||
|   | ||||
| @@ -80,8 +80,33 @@ func (b *Bwhatsapp) getSenderName(senderJid string) string { | ||||
| 		// if user is not in phone contacts | ||||
| 		// it is the most obvious scenario unless you sync your phone contacts with some remote updated source | ||||
| 		// users can change it in their WhatsApp settings -> profile -> click on Avatar | ||||
| 		return sender.Notify | ||||
| 		if sender.Notify != "" { | ||||
| 			return sender.Notify | ||||
| 		} | ||||
|  | ||||
| 		if sender.Short != "" { | ||||
| 			return sender.Short | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// try to reload this contact | ||||
| 	_, err := b.conn.Contacts() | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("error on update of contacts: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	if contact, exists := b.conn.Store.Contacts[senderJid]; exists { | ||||
| 		// Add it to the user map | ||||
| 		b.users[senderJid] = contact | ||||
|  | ||||
| 		if contact.Name != "" { | ||||
| 			return contact.Name | ||||
| 		} | ||||
| 		// if user is not in phone contacts | ||||
| 		// same as above | ||||
| 		return contact.Notify | ||||
| 	} | ||||
|  | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,11 +1,14 @@ | ||||
| package bwhatsapp | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"crypto/rand" | ||||
| 	"encoding/hex" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"mime" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| @@ -180,7 +183,7 @@ func (b *Bwhatsapp) Disconnect() error { | ||||
| } | ||||
|  | ||||
| func isGroupJid(identifier string) bool { | ||||
| 	return strings.HasSuffix(identifier, "@g.us") || strings.HasSuffix(identifier, "@temp") | ||||
| 	return strings.HasSuffix(identifier, "@g.us") || strings.HasSuffix(identifier, "@temp") || strings.HasSuffix(identifier, "@broadcast") | ||||
| } | ||||
|  | ||||
| // JoinChannel Join a WhatsApp group specified in gateway config as channel='number-id@g.us' or channel='Channel name' | ||||
| @@ -230,6 +233,66 @@ func (b *Bwhatsapp) JoinChannel(channel config.ChannelInfo) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Post a document message from the bridge to WhatsApp | ||||
| func (b *Bwhatsapp) PostDocumentMessage(msg config.Message, filetype string) (string, error) { | ||||
| 	fi := msg.Extra["file"][0].(config.FileInfo) | ||||
|  | ||||
| 	// Post document message | ||||
| 	message := whatsapp.DocumentMessage{ | ||||
| 		Info: whatsapp.MessageInfo{ | ||||
| 			RemoteJid: msg.Channel, | ||||
| 		}, | ||||
| 		Title:    fi.Name, | ||||
| 		FileName: fi.Name, | ||||
| 		Type:     filetype, | ||||
| 		Content:  bytes.NewReader(*fi.Data), | ||||
| 	} | ||||
|  | ||||
| 	b.Log.Debugf("=> Sending %#v", msg) | ||||
|  | ||||
| 	// create message ID | ||||
| 	// TODO follow and act if https://github.com/Rhymen/go-whatsapp/issues/101 implemented | ||||
| 	idBytes := make([]byte, 10) | ||||
| 	if _, err := rand.Read(idBytes); err != nil { | ||||
| 		b.Log.Warn(err.Error()) | ||||
| 	} | ||||
|  | ||||
| 	message.Info.Id = strings.ToUpper(hex.EncodeToString(idBytes)) | ||||
| 	_, err := b.conn.Send(message) | ||||
|  | ||||
| 	return message.Info.Id, err | ||||
| } | ||||
|  | ||||
| // Post an image message from the bridge to WhatsApp | ||||
| // Handle, for sure image/jpeg, image/png and image/gif MIME types | ||||
| func (b *Bwhatsapp) PostImageMessage(msg config.Message, filetype string) (string, error) { | ||||
| 	fi := msg.Extra["file"][0].(config.FileInfo) | ||||
|  | ||||
| 	// Post image message | ||||
| 	message := whatsapp.ImageMessage{ | ||||
| 		Info: whatsapp.MessageInfo{ | ||||
| 			RemoteJid: msg.Channel, | ||||
| 		}, | ||||
| 		Type:    filetype, | ||||
| 		Caption: msg.Username + fi.Comment, | ||||
| 		Content: bytes.NewReader(*fi.Data), | ||||
| 	} | ||||
|  | ||||
| 	b.Log.Debugf("=> Sending %#v", msg) | ||||
|  | ||||
| 	// create message ID | ||||
| 	// TODO follow and act if https://github.com/Rhymen/go-whatsapp/issues/101 implemented | ||||
| 	idBytes := make([]byte, 10) | ||||
| 	if _, err := rand.Read(idBytes); err != nil { | ||||
| 		b.Log.Warn(err.Error()) | ||||
| 	} | ||||
|  | ||||
| 	message.Info.Id = strings.ToUpper(hex.EncodeToString(idBytes)) | ||||
| 	_, err := b.conn.Send(message) | ||||
|  | ||||
| 	return message.Info.Id, err | ||||
| } | ||||
|  | ||||
| // Send a message from the bridge to WhatsApp | ||||
| // Required implementation of the Bridger interface | ||||
| // https://github.com/42wim/matterbridge/blob/2cfd880cdb0df29771bf8f31df8d990ab897889d/bridge/bridge.go#L11-L16 | ||||
| @@ -259,18 +322,25 @@ func (b *Bwhatsapp) Send(msg config.Message) (string, error) { | ||||
| 		// TODO handle edit as a message reply with updated text | ||||
| 	} | ||||
|  | ||||
| 	//// TODO Handle Upload a file | ||||
| 	//if msg.Extra != nil { | ||||
| 	//	for _, rmsg := range helper.HandleExtra(&msg, b.General) { | ||||
| 	//		b.c.SendMessage(roomID, rmsg.Username+rmsg.Text) | ||||
| 	//	} | ||||
| 	//	if len(msg.Extra["file"]) > 0 { | ||||
| 	//		return b.handleUploadFile(&msg, roomID) | ||||
| 	//	} | ||||
| 	//} | ||||
| 	// Handle Upload a file | ||||
| 	if msg.Extra["file"] != nil { | ||||
| 		fi := msg.Extra["file"][0].(config.FileInfo) | ||||
| 		filetype := mime.TypeByExtension(filepath.Ext(fi.Name)) | ||||
|  | ||||
| 		b.Log.Debugf("Extra file is %#v", filetype) | ||||
|  | ||||
| 		// TODO: add different types | ||||
| 		// TODO: add webp conversion | ||||
| 		switch filetype { | ||||
| 		case "image/jpeg", "image/png", "image/gif": | ||||
| 			return b.PostImageMessage(msg, filetype) | ||||
| 		default: | ||||
| 			return b.PostDocumentMessage(msg, filetype) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Post text message | ||||
| 	text := whatsapp.TextMessage{ | ||||
| 	message := whatsapp.TextMessage{ | ||||
| 		Info: whatsapp.MessageInfo{ | ||||
| 			RemoteJid: msg.Channel, // which equals to group id | ||||
| 		}, | ||||
| @@ -281,15 +351,14 @@ func (b *Bwhatsapp) Send(msg config.Message) (string, error) { | ||||
|  | ||||
| 	// create message ID | ||||
| 	// TODO follow and act if https://github.com/Rhymen/go-whatsapp/issues/101 implemented | ||||
| 	bytes := make([]byte, 10) | ||||
| 	if _, err := rand.Read(bytes); err != nil { | ||||
| 	idBytes := make([]byte, 10) | ||||
| 	if _, err := rand.Read(idBytes); err != nil { | ||||
| 		b.Log.Warn(err.Error()) | ||||
| 	} | ||||
| 	text.Info.Id = strings.ToUpper(hex.EncodeToString(bytes)) | ||||
| 	message.Info.Id = strings.ToUpper(hex.EncodeToString(idBytes)) | ||||
| 	_, err := b.conn.Send(message) | ||||
|  | ||||
| 	_, err := b.conn.Send(text) | ||||
|  | ||||
| 	return text.Info.Id, err | ||||
| 	return message.Info.Id, err | ||||
| } | ||||
|  | ||||
| // TODO do we want that? to allow login with QR code from a bridged channel? https://github.com/tulir/mautrix-whatsapp/blob/513eb18e2d59bada0dd515ee1abaaf38a3bfe3d5/commands.go#L76 | ||||
|   | ||||
							
								
								
									
										34
									
								
								bridge/xmpp/handler.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								bridge/xmpp/handler.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| package bxmpp | ||||
|  | ||||
| import ( | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/42wim/matterbridge/bridge/helper" | ||||
| 	"github.com/matterbridge/go-xmpp" | ||||
| ) | ||||
|  | ||||
| // handleDownloadAvatar downloads the avatar of userid from channel | ||||
| // sends a EVENT_AVATAR_DOWNLOAD message to the gateway if successful. | ||||
| // logs an error message if it fails | ||||
| func (b *Bxmpp) handleDownloadAvatar(avatar xmpp.AvatarData) { | ||||
| 	rmsg := config.Message{ | ||||
| 		Username: "system", | ||||
| 		Text:     "avatar", | ||||
| 		Channel:  b.parseChannel(avatar.From), | ||||
| 		Account:  b.Account, | ||||
| 		UserID:   avatar.From, | ||||
| 		Event:    config.EventAvatarDownload, | ||||
| 		Extra:    make(map[string][]interface{}), | ||||
| 	} | ||||
| 	if _, ok := b.avatarMap[avatar.From]; !ok { | ||||
| 		b.Log.Debugf("Avatar.From: %s", avatar.From) | ||||
|  | ||||
| 		err := helper.HandleDownloadSize(b.Log, &rmsg, avatar.From+".png", int64(len(avatar.Data)), b.General) | ||||
| 		if err != nil { | ||||
| 			b.Log.Error(err) | ||||
| 			return | ||||
| 		} | ||||
| 		helper.HandleDownloadData(b.Log, &rmsg, avatar.From+".png", rmsg.Text, "", &avatar.Data, b.General) | ||||
| 		b.Log.Debugf("Avatar download complete") | ||||
| 		b.Remote <- rmsg | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										30
									
								
								bridge/xmpp/helpers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								bridge/xmpp/helpers.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| package bxmpp | ||||
|  | ||||
| import ( | ||||
| 	"regexp" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| ) | ||||
|  | ||||
| var pathRegex = regexp.MustCompile("[^a-zA-Z0-9]+") | ||||
|  | ||||
| // GetAvatar constructs a URL for a given user-avatar if it is available in the cache. | ||||
| func getAvatar(av map[string]string, userid string, general *config.Protocol) string { | ||||
| 	if hash, ok := av[userid]; ok { | ||||
| 		// NOTE: This does not happen in bridge/helper/helper.go but messes up XMPP | ||||
| 		id := pathRegex.ReplaceAllString(userid, "_") | ||||
| 		return general.MediaServerDownload + "/" + hash + "/" + id + ".png" | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (b *Bxmpp) cacheAvatar(msg *config.Message) string { | ||||
| 	fi := msg.Extra["file"][0].(config.FileInfo) | ||||
| 	/* if we have a sha we have successfully uploaded the file to the media server, | ||||
| 	so we can now cache the sha */ | ||||
| 	if fi.SHA != "" { | ||||
| 		b.Log.Debugf("Added %s to %s in avatarMap", fi.SHA, msg.UserID) | ||||
| 		b.avatarMap[msg.UserID] = fi.SHA | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
| @@ -23,12 +23,17 @@ type Bxmpp struct { | ||||
| 	xmppMap   map[string]string | ||||
| 	connected bool | ||||
| 	sync.RWMutex | ||||
|  | ||||
| 	avatarAvailability map[string]bool | ||||
| 	avatarMap          map[string]string | ||||
| } | ||||
|  | ||||
| func New(cfg *bridge.Config) bridge.Bridger { | ||||
| 	return &Bxmpp{ | ||||
| 		Config:  cfg, | ||||
| 		xmppMap: make(map[string]string), | ||||
| 		Config:             cfg, | ||||
| 		xmppMap:            make(map[string]string), | ||||
| 		avatarAvailability: make(map[string]bool), | ||||
| 		avatarMap:          make(map[string]string), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -67,8 +72,19 @@ func (b *Bxmpp) Send(msg config.Message) (string, error) { | ||||
| 	if msg.Event == config.EventMsgDelete { | ||||
| 		return "", nil | ||||
| 	} | ||||
|  | ||||
| 	b.Log.Debugf("=> Receiving %#v", msg) | ||||
|  | ||||
| 	if msg.Event == config.EventAvatarDownload { | ||||
| 		return b.cacheAvatar(&msg), nil | ||||
| 	} | ||||
|  | ||||
| 	// Make a action /me of the message, prepend the username with it. | ||||
| 	// https://xmpp.org/extensions/xep-0245.html | ||||
| 	if msg.Event == config.EventUserAction { | ||||
| 		msg.Username = "/me " + msg.Username | ||||
| 	} | ||||
|  | ||||
| 	// Upload a file (in XMPP case send the upload URL because XMPP has no native upload support). | ||||
| 	if msg.Extra != nil { | ||||
| 		for _, rmsg := range helper.HandleExtra(&msg, b.General) { | ||||
| @@ -114,20 +130,22 @@ func (b *Bxmpp) createXMPP() error { | ||||
| 		ServerName:         strings.Split(b.GetString("Jid"), "@")[1], | ||||
| 		InsecureSkipVerify: b.GetBool("SkipTLSVerify"), // nolint: gosec | ||||
| 	} | ||||
|  | ||||
| 	xmpp.DebugWriter = b.Log.Writer() | ||||
|  | ||||
| 	options := xmpp.Options{ | ||||
| 		Host:                         b.GetString("Server"), | ||||
| 		User:                         b.GetString("Jid"), | ||||
| 		Password:                     b.GetString("Password"), | ||||
| 		NoTLS:                        true, | ||||
| 		StartTLS:                     true, | ||||
| 		StartTLS:                     !b.GetBool("NoTLS"), | ||||
| 		TLSConfig:                    tc, | ||||
| 		Debug:                        b.GetBool("debug"), | ||||
| 		Logger:                       b.Log.Writer(), | ||||
| 		Session:                      true, | ||||
| 		Status:                       "", | ||||
| 		StatusMessage:                "", | ||||
| 		Resource:                     "", | ||||
| 		InsecureAllowUnencryptedAuth: false, | ||||
| 		InsecureAllowUnencryptedAuth: b.GetBool("NoTLS"), | ||||
| 	} | ||||
| 	var err error | ||||
| 	b.xc, err = options.NewClient() | ||||
| @@ -228,6 +246,16 @@ func (b *Bxmpp) handleXMPP() error { | ||||
| 					event = config.EventTopicChange | ||||
| 				} | ||||
|  | ||||
| 				available, sok := b.avatarAvailability[v.Remote] | ||||
| 				avatar := "" | ||||
| 				if !sok { | ||||
| 					b.Log.Debugf("Requesting avatar data") | ||||
| 					b.avatarAvailability[v.Remote] = false | ||||
| 					b.xc.AvatarRequestData(v.Remote) | ||||
| 				} else if available { | ||||
| 					avatar = getAvatar(b.avatarMap, v.Remote, b.General) | ||||
| 				} | ||||
|  | ||||
| 				msgID := v.ID | ||||
| 				if v.ReplaceID != "" { | ||||
| 					msgID = v.ReplaceID | ||||
| @@ -237,6 +265,7 @@ func (b *Bxmpp) handleXMPP() error { | ||||
| 					Text:     v.Text, | ||||
| 					Channel:  b.parseChannel(v.Remote), | ||||
| 					Account:  b.Account, | ||||
| 					Avatar:   avatar, | ||||
| 					UserID:   v.Remote, | ||||
| 					ID:       msgID, | ||||
| 					Event:    event, | ||||
| @@ -253,6 +282,10 @@ func (b *Bxmpp) handleXMPP() error { | ||||
| 				b.Log.Debugf("<= Message is %#v", rmsg) | ||||
| 				b.Remote <- rmsg | ||||
| 			} | ||||
| 		case xmpp.AvatarData: | ||||
| 			b.handleDownloadAvatar(v) | ||||
| 			b.avatarAvailability[v.From] = true | ||||
| 			b.Log.Debugf("Avatar for %s is now available", v.From) | ||||
| 		case xmpp.Presence: | ||||
| 			// Do nothing. | ||||
| 		} | ||||
|   | ||||
| @@ -135,19 +135,25 @@ func (b *Bzulip) handleQueue() error { | ||||
| 			if m.SenderEmail == b.GetString("login") { | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			avatarURL := m.AvatarURL | ||||
| 			if !strings.HasPrefix(avatarURL, "http") { | ||||
| 				avatarURL = b.GetString("server") + avatarURL | ||||
| 			} | ||||
|  | ||||
| 			rmsg := config.Message{ | ||||
| 				Username: m.SenderFullName, | ||||
| 				Text:     m.Content, | ||||
| 				Channel:  b.getChannel(m.StreamID) + "/topic:" + m.Subject, | ||||
| 				Account:  b.Account, | ||||
| 				UserID:   strconv.Itoa(m.SenderID), | ||||
| 				Avatar:   m.AvatarURL, | ||||
| 				Avatar:   avatarURL, | ||||
| 			} | ||||
| 			b.Log.Debugf("<= Sending message from %s on %s to gateway", rmsg.Username, b.Account) | ||||
| 			b.Log.Debugf("<= Message is %#v", rmsg) | ||||
| 			b.Remote <- rmsg | ||||
| 			b.q.LastEventID = m.ID | ||||
| 		} | ||||
|  | ||||
| 		time.Sleep(time.Second * 3) | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										270
									
								
								changelog.md
									
									
									
									
									
								
							
							
						
						
									
										270
									
								
								changelog.md
									
									
									
									
									
								
							| @@ -1,3 +1,273 @@ | ||||
| # v1.20.0 | ||||
|  | ||||
| ## Breaking | ||||
|  | ||||
| - matrix: Send the display name instead of the user name (matrix) (#1282)   | ||||
|   Matrix now sends the displayname if set instead of the username. If you want to keep the username, add  `UseUsername=true` to your matrix config. <https://github.com/42wim/matterbridge/wiki/Settings#useusername-1> | ||||
| - discord: Disable webhook editing (discord) (#1296)   | ||||
|   Because of issues with ratelimiting of webhook editing, this feature is now disabled. If you have multiple discord channels you bridge, you'll need to add a `webhookURL` to the `[gateway.inout.options]`. See <https://github.com/42wim/matterbridge/blob/master/matterbridge.toml.sample#L1864-L1870> for an example. | ||||
|  | ||||
| ## New features | ||||
|  | ||||
| - general: Allow tengo to drop messages using msgDrop (#1272) | ||||
| - general: Update libraries (whatsapp,markdown,mattermost,ssh-chat) | ||||
| - irc: Add PingDelay option (irc) (#1269) | ||||
| - matrix: Allow message edits on matrix (#1286) | ||||
| - xmpp: add NoTLS option to allow plaintext XMPP connections (#1288) | ||||
|  | ||||
| ## Enhancements | ||||
|  | ||||
| - discord: Edit messages via webhook (1287) | ||||
| - general: Add extra debug to log time spent sending a message per bridge (#1299) | ||||
|  | ||||
| This release couldn't exist without the following contributors: | ||||
| @nightmared, @zhoreeq | ||||
|  | ||||
| # v1.19.0 | ||||
|  | ||||
| ## New features | ||||
|  | ||||
| - mumble: new protocol added: Add Mumble support (#1245) | ||||
| - nctalk: Add support for downloading files (nctalk) (#1249) | ||||
| - nctalk: Append a suffix if user is a guest user (nctalk) (#1250) | ||||
|  | ||||
| ## Enhancements | ||||
|  | ||||
| - irc: Add even more debug for irc (#1266) | ||||
| - matrix: Add username formatting for all events (matrix) (#1233) | ||||
| - matrix: Permit uploading files of other mimetypes (#1237) | ||||
| - whatsapp: Use vendored whatsapp version (#1258) | ||||
| - whatsapp: Add username for images from WhatsApp (#1232) | ||||
|  | ||||
| This release couldn't exist without the following contributors: | ||||
| @Dellle, @42wim, @gary-kim, @s3lph, @BenWiederhake | ||||
|  | ||||
| # v1.18.3 | ||||
|  | ||||
| ## Enhancements | ||||
|  | ||||
| - nctalk: Add TLSConfig to nctalk (#1195) | ||||
| - whatsapp: Handle broadcasts as groups in Whatsapp #1213 | ||||
| - matrix: switch to upstream gomatrix #1219 | ||||
| - api: support multiple websocket clients #1205 | ||||
|  | ||||
| ## Bugfix | ||||
|  | ||||
| - general: update vendor | ||||
| - zulip: Check location of avatarURL (zulip). Fixes #1214 (#1227) | ||||
| - nctalk: Fix issue with too many open files #1223 | ||||
| - nctalk: Fix mentions #1222 | ||||
| - nctalk: Fix message replays #1220 | ||||
|  | ||||
| This release couldn't exist without the following contributors: | ||||
| @gary-kim, @tilosp, @NikkyAI, @escoand, @42wim | ||||
|  | ||||
| # v1.18.2 | ||||
|  | ||||
| ## Bugfix | ||||
|  | ||||
| - zulip: Fix error loop (zulip) (#1210) | ||||
| - whatsapp: Update whatsapp vendor and fix a panic (#1209) | ||||
|  | ||||
| This release couldn't exist without the following contributors: | ||||
| @SuperSandro2000, @42wim | ||||
|  | ||||
| # v1.18.1 | ||||
|  | ||||
| ## New features | ||||
|  | ||||
| - telegram: Support Telegram animated stickers (tgs) format (#1173). See https://github.com/42wim/matterbridge/wiki/Settings#mediaConverttgs for more info | ||||
|  | ||||
| ## Enhancements | ||||
|  | ||||
| - matrix: Remove HTML formatting for push messages (#1188) (#1189) | ||||
| - mattermost: Use mattermost v5 module (#1192) | ||||
|  | ||||
| ## Bugfix | ||||
|  | ||||
| - whatsapp: Handle panic in whatsapp. Fixes #1180 (#1184) | ||||
| - nctalk: Fix Nextcloud Talk connection failure (#1179) | ||||
| - matrix: Sleep when ratelimited on joins (matrix). Fixes #1201 (#1206) | ||||
|  | ||||
| This release couldn't exist without the following contributors: | ||||
| @42wim, @BenWiederhake, @Dellle, @gary-kim | ||||
|  | ||||
| # v1.18.0 | ||||
|  | ||||
| ## New features | ||||
|  | ||||
| - nctalk: new protocol added. Add Nextcloud Talk support #1167 | ||||
| - general: Add an option to log into a file rather than stdout (#1168) | ||||
| - api: Add websocket to API (#970) | ||||
|  | ||||
| ## Enhancements | ||||
|  | ||||
| - telegram: Fix MarkdownV2 support in Telegram (#1169) | ||||
| - whatsapp: Reload user information when a new contact is detected (whatsapp) (#1160) | ||||
| - api: Add sane RemoteNickFormat default for API (#1157) | ||||
| - irc: Skip gIRC built-in rate limiting (irc) (#1164) | ||||
| - irc: Only colour IRC nicks if there is one. (#1161) | ||||
| - docker: Combine runs to one layer (#1151) | ||||
|  | ||||
| ## Bugfix | ||||
|  | ||||
| - general: Update dependencies for 1.18.0 release (#1175) | ||||
|  | ||||
| Discord users are encouraged to upgrade, this release works with the move to the discord.com domain. | ||||
|  | ||||
| This release couldn't exist without the following contributors: | ||||
| @42wim, @jlu5, @qaisjp, @TheHolyRoger, @SuperSandro2000, @gary-kim, @z3bra, @greenx, @haykam821, @nathanaelhoun | ||||
|  | ||||
| # v1.17.5 | ||||
|  | ||||
| ## Enhancements | ||||
|  | ||||
| - irc: Add StripMarkdown option (irc). (#1145) | ||||
| - general: Increase debug logging with function,file and linenumber (#1147) | ||||
| - general: Update Dockerfile so inotify works (#1148) | ||||
| - matrix: Add an option to disable sending HTML to matrix. Fixes #1022 (#1135) | ||||
| - xmpp: Implement xep-0245 (xmpp). Closes #1137 (#1144) | ||||
|  | ||||
| ## Bugfix | ||||
|  | ||||
| - discord: Fix #1120: replaceAction "_" crash (discord) (#1121) | ||||
| - discord: Fix #1049: missing space before embeds (discord) (#1124) | ||||
| - discord: Fix webhook EventUserAction messages being skipped (discord) (#1133) | ||||
| - matrix: Avoid creating invalid url when the user doesn't have an avatar (matrix) (#1130) | ||||
| - msteams: Ignore non-user messages (msteams). Fixes #1141 (#1149) | ||||
| - slack: Do not use webhooks when token is configured (slack) (fixes #1123) (#1134) | ||||
| - telegram: Fix forward from hidden users (telegram). Closes #1131 (#1143) | ||||
| - xmpp: Prevent re-requesting avatar data (xmpp) (#1117) | ||||
|  | ||||
| This release couldn't exist without the following contributors: | ||||
| @qaisjp, @xnaas, @42wim, @Polynomdivision, @tfve | ||||
|  | ||||
| # v1.17.4 | ||||
|  | ||||
| ## Bugfix | ||||
|  | ||||
| - general: Lowercase account names. Fixes #1108 (#1110) | ||||
| - msteams: Remove panics and retry polling on failure (msteams). Fixes #1104 (#1105 | ||||
| - whatsapp: Update Rhymen/go-whatsapp. Fixes #1107 (#1109) (make whatsapp working again) | ||||
| - discord: Add an ID cache (discord). Fixes #1106 (#1111) (fix delete/edits with webhooks) | ||||
|  | ||||
| # v1.17.3 | ||||
|  | ||||
| ## Enhancements | ||||
|  | ||||
| - xmpp: Implement User Avatar spoofing of XMPP users #1090 | ||||
| - rocketchat: Relay Joins/Topic changes in RocketChat bridge (#1085) | ||||
| - irc: Add JoinDelay option (irc). Fixes #1084 (#1098) | ||||
| - slack: Clip too long messages on 3000 length (slack). Fixes #1081 (#1102) | ||||
|  | ||||
| ## Bugfix | ||||
|  | ||||
| - general: Fix the behavior of ShowTopicChange and SyncTopic (#1086) | ||||
| - slack: Prevent image/message looping (slack). Fixes #1088 (#1096) | ||||
| - whatsapp: Ignore non-critical errors (whatsapp). Fixes #1094 (#1100) | ||||
| - irc: Add extra space before colon in attachments (irc). Fixes #1089 (#1101) | ||||
|  | ||||
| This release couldn't exist without the following contributors: | ||||
| @42wim, @ldruschk, @qaisjp, @Polynomdivision | ||||
|  | ||||
| # v1.17.2 | ||||
|  | ||||
| ## Enhancements | ||||
|  | ||||
| - slack: Update vendor slack-go/slack (#1068) | ||||
| - general: Update vendor d5/tengo (#1066) | ||||
| - general: Clarify terminology used in mapping group chat IDs to channels in config (#1079) | ||||
|  | ||||
| ## Bugfix | ||||
|  | ||||
| - whatsapp: Update Rhymen/go-whatsapp vendor and whatsapp version (#1078). Fixes Media upload #1074 | ||||
| - whatsapp: Reset start timestamp on reconnect (whatsapp). Fixes #1059 (#1064) | ||||
|  | ||||
| This release couldn't exist without the following contributors: | ||||
| @42wim, @jheiselman | ||||
|  | ||||
| # v1.17.1 | ||||
|  | ||||
| ## Enhancements | ||||
|  | ||||
| - docker: Remove build dependencies from final image (multistage build) #1057 | ||||
|  | ||||
| ## Bugfix | ||||
|  | ||||
| - general: Don't transmit typing events from ourselves #1056 | ||||
| - general: Add support for build tags #1054 | ||||
| - discord: Strip extra info from emotes (discord) #1052 | ||||
| - msteams: fix macos build: Update vendor yaegashi/msgraph.go to v0.1.2 #1036 | ||||
| - whatsapp: Update client version whatsapp. Fixes #1061 #1062 | ||||
|  | ||||
| This release couldn't exist without the following contributors: | ||||
| @awigen, @qaisjp, @42wim | ||||
|  | ||||
| # v1.17.0 | ||||
|  | ||||
| ## New features | ||||
|  | ||||
| - msteams: new protocol added. Add initial Microsoft Teams support #967 | ||||
|   See https://github.com/42wim/matterbridge/wiki/MS-Teams-setup for a complete walkthrough | ||||
| - discord: Add ability to procure avatars from the destination bridge #1000 | ||||
| - matrix: Add support for avatars from matrix. #1007 | ||||
| - general: support JSON and YAML config formats #1045 | ||||
|  | ||||
| ## Enhancements | ||||
|  | ||||
| - discord: Check only bridged channels for PermManageWebhooks #1001 | ||||
| - irc: Be less lossy when throttling IRC messages #1004 | ||||
| - keybase: updated library #1002, #1019 | ||||
| - matrix: Rebase gomatrix vendor with upstream #1006 | ||||
| - slack: Use upstream slack-go/slack again #1018 | ||||
| - slack: Ignore ConnectingEvent #1041 | ||||
| - slack: use blocks not attachments #1048 | ||||
| - sshchat: Update vendor shazow/ssh-chat #1029 | ||||
| - telegram: added markdownv2 mode for telegram #1037 | ||||
| - whatsapp: Implement basic reconnect (whatsapp). Fixes #987 #1003 | ||||
|  | ||||
| ## Bugfix | ||||
|  | ||||
| - discord: Fix webhook permission checks sometimes failing #1043 | ||||
| - discord: Fix #1027: warning when handling inbound webhooks #1044 | ||||
| - discord: Fix duplicate separator on empty description/url (discord) #1035 | ||||
| - matrix: Fix issue with underscores in links #999 | ||||
| - slack: Fix #1039: messages sent to Slack being synced back #1046 | ||||
| - telegram: Make avatars download work with mediaserverdownload (telegram). Fixes #920  | ||||
|  | ||||
| This release couldn't exist without the following contributors: | ||||
| @qaisjp, @jakubgs, @burner1024, @notpushkin, @MartijnBraam, @42wim | ||||
|  | ||||
| # v1.16.5 | ||||
|  | ||||
| - Fix version bump | ||||
|  | ||||
| # v1.16.4 | ||||
|  | ||||
| ## New features | ||||
|  | ||||
| - whatsapp: Add support for WhatsApp media (jpeg/png/gif) bridging (#974) | ||||
| - telegram: Add QuoteLengthLimit option (telegram) fixes #963 (#985) | ||||
| - telegram: Add DisableWebPagePreview option (telegram). Closes #980 (#994) | ||||
|  | ||||
| ## Enhancements | ||||
|  | ||||
| - general: update dependencies | ||||
| - tengo: update to tengo v2 | ||||
| - general: Add Docker Compose configuration (#990) | ||||
|  | ||||
| ## Bugfix | ||||
|  | ||||
| - general: Fail with message instead of panic. #988 (#991) | ||||
| - telegram: Add extra mimetypes to docker image. Fixes #969 | ||||
| - discord: Fix channel ID problem with multiple gateways (discord). Fixes #953 (#977) | ||||
| - discord: Show file comment in webhook if normal message is empty (discord). Fixes #962 (#995) | ||||
| - matrix: Fix parsing issues - Disable smartypants in markdown parser. Fixes #989, #983 (#993) | ||||
| - sshchat: Fix duplicated messages (sshchat). Fixes #950 (#996) | ||||
|  | ||||
| This release couldn't exist without the following contributors: | ||||
| @jwflory, @42wim, @pbek, @Humorhenker, @c0ncord2, @glazzara | ||||
|  | ||||
| # v1.16.3 | ||||
|  | ||||
| ## Bugfix | ||||
|   | ||||
| @@ -1,30 +0,0 @@ | ||||
| #!/usr/bin/env bash | ||||
| set -u -e -x -o pipefail | ||||
|  | ||||
| go version | grep go1.13 || exit | ||||
|  | ||||
| VERSION=$(git describe --tags) | ||||
| mkdir ci/binaries | ||||
| GOOS=windows GOARCH=amd64 go build -ldflags "-s -w -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o ci/binaries/matterbridge-$VERSION-windows-amd64.exe | ||||
| GOOS=linux GOARCH=amd64 go build -ldflags "-s -w -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o ci/binaries/matterbridge-$VERSION-linux-amd64 | ||||
| GOOS=linux GOARCH=arm go build -ldflags "-s -w -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o ci/binaries/matterbridge-$VERSION-linux-arm | ||||
| GOOS=darwin GOARCH=amd64 go build -ldflags "-s -w -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o ci/binaries/matterbridge-$VERSION-darwin-amd64 | ||||
| cd ci | ||||
| cat > deploy.json <<EOF | ||||
| { | ||||
|     "package": { | ||||
|         "name": "Matterbridge", | ||||
|         "repo": "nightly", | ||||
|         "subject": "42wim" | ||||
|     }, | ||||
|     "version": { | ||||
|         "name": "$VERSION" | ||||
|     }, | ||||
|     "files": | ||||
|         [ | ||||
|         {"includePattern": "ci/binaries/(.*)", "uploadPattern":"\$1"} | ||||
|         ], | ||||
|     "publish": true | ||||
| } | ||||
| EOF | ||||
|  | ||||
							
								
								
									
										17
									
								
								ci/lint.sh
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								ci/lint.sh
									
									
									
									
									
								
							| @@ -1,17 +0,0 @@ | ||||
| #!/usr/bin/env bash | ||||
| set -u -e -x -o pipefail | ||||
|  | ||||
| if [[ -n "${GOLANGCI_VERSION-}" ]]; then | ||||
|   # Retrieve the golangci-lint linter binary. | ||||
|   curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b ${GOPATH}/bin ${GOLANGCI_VERSION} | ||||
| fi | ||||
|  | ||||
| # Run the linter. | ||||
| golangci-lint run | ||||
|  | ||||
| # if [[ "${GO111MODULE-off}" == "on" ]]; then | ||||
| #   # If Go modules are active then check that dependencies are correctly maintained. | ||||
| #   go mod tidy | ||||
| #   go mod vendor | ||||
| #   git diff --exit-code --quiet || (echo "Please run 'go mod tidy' to clean up the 'go.mod' and 'go.sum' files."; false) | ||||
| # fi | ||||
							
								
								
									
										17
									
								
								ci/test.sh
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								ci/test.sh
									
									
									
									
									
								
							| @@ -1,17 +0,0 @@ | ||||
| #!/usr/bin/env bash | ||||
| set -u -e -x -o pipefail | ||||
|  | ||||
| if [[ -n "${REPORT_COVERAGE+cover}" ]]; then | ||||
|   # Retrieve and prepare CodeClimate's test coverage reporter. | ||||
|   curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter | ||||
|   chmod +x ./cc-test-reporter | ||||
|   ./cc-test-reporter before-build | ||||
| fi | ||||
|  | ||||
| # Run all the tests with the race detector and generate coverage. | ||||
| go test -v -race -coverprofile c.out ./... | ||||
|  | ||||
| if [[ -n "${REPORT_COVERAGE+cover}" && "${TRAVIS_SECURE_ENV_VARS}" == "true" ]]; then | ||||
|   # Upload test coverage to CodeClimate. | ||||
|   ./cc-test-reporter after-build | ||||
| fi | ||||
							
								
								
									
										10
									
								
								contrib/outmessage-discordemoji.tengo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								contrib/outmessage-discordemoji.tengo
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| text := import("text") | ||||
|  | ||||
| // if we're not sending to a discord bridge, | ||||
| // then convert custom emoji tags into url's | ||||
| if (inProtocol == "discord" && outProtocol != "discord") { | ||||
|     rePNG := text.re_compile(`<:.*?:([0-9]+)>`) | ||||
|     msgText=rePNG.replace(msgText,"https://cdn.discordapp.com/emojis/$1.png") | ||||
|     reGIF := text.re_compile(`<a:.*?:([0-9]+)>`) | ||||
|     msgText=reGIF.replace(msgText,"https://cdn.discordapp.com/emojis/$1.gif") | ||||
| } | ||||
							
								
								
									
										11
									
								
								gateway/bridgemap/api.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								gateway/bridgemap/api.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !noapi | ||||
|  | ||||
| package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	"github.com/42wim/matterbridge/bridge/api" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	FullMap["api"] = api.New | ||||
| } | ||||
							
								
								
									
										12
									
								
								gateway/bridgemap/bdiscord.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								gateway/bridgemap/bdiscord.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| // +build !nodiscord | ||||
|  | ||||
| package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	bdiscord "github.com/42wim/matterbridge/bridge/discord" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	FullMap["discord"] = bdiscord.New | ||||
| 	UserTypingSupport["discord"] = struct{}{} | ||||
| } | ||||
							
								
								
									
										11
									
								
								gateway/bridgemap/bgitter.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								gateway/bridgemap/bgitter.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !nogitter | ||||
|  | ||||
| package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	bgitter "github.com/42wim/matterbridge/bridge/gitter" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	FullMap["gitter"] = bgitter.New | ||||
| } | ||||
							
								
								
									
										11
									
								
								gateway/bridgemap/birc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								gateway/bridgemap/birc.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !noirc | ||||
|  | ||||
| package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	birc "github.com/42wim/matterbridge/bridge/irc" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	FullMap["irc"] = birc.New | ||||
| } | ||||
							
								
								
									
										11
									
								
								gateway/bridgemap/bkeybase.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								gateway/bridgemap/bkeybase.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !nokeybase | ||||
|  | ||||
| package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	bkeybase "github.com/42wim/matterbridge/bridge/keybase" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	FullMap["keybase"] = bkeybase.New | ||||
| } | ||||
							
								
								
									
										11
									
								
								gateway/bridgemap/bmatrix.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								gateway/bridgemap/bmatrix.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !nomatrix | ||||
|  | ||||
| package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	bmatrix "github.com/42wim/matterbridge/bridge/matrix" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	FullMap["matrix"] = bmatrix.New | ||||
| } | ||||
							
								
								
									
										11
									
								
								gateway/bridgemap/bmattermost.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								gateway/bridgemap/bmattermost.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !nomattermost | ||||
|  | ||||
| package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	bmattermost "github.com/42wim/matterbridge/bridge/mattermost" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	FullMap["mattermost"] = bmattermost.New | ||||
| } | ||||
							
								
								
									
										11
									
								
								gateway/bridgemap/bmsteams.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								gateway/bridgemap/bmsteams.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !nomsteams | ||||
|  | ||||
| package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	bmsteams "github.com/42wim/matterbridge/bridge/msteams" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	FullMap["msteams"] = bmsteams.New | ||||
| } | ||||
							
								
								
									
										11
									
								
								gateway/bridgemap/bmumble.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								gateway/bridgemap/bmumble.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !nomumble | ||||
|  | ||||
| package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	bmumble "github.com/42wim/matterbridge/bridge/mumble" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	FullMap["mumble"] = bmumble.New | ||||
| } | ||||
							
								
								
									
										11
									
								
								gateway/bridgemap/bnctalk.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								gateway/bridgemap/bnctalk.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !nonctalk | ||||
|  | ||||
| package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	btalk "github.com/42wim/matterbridge/bridge/nctalk" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	FullMap["nctalk"] = btalk.New | ||||
| } | ||||
| @@ -2,45 +2,9 @@ package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	"github.com/42wim/matterbridge/bridge" | ||||
| 	"github.com/42wim/matterbridge/bridge/api" | ||||
| 	bdiscord "github.com/42wim/matterbridge/bridge/discord" | ||||
| 	bgitter "github.com/42wim/matterbridge/bridge/gitter" | ||||
| 	birc "github.com/42wim/matterbridge/bridge/irc" | ||||
| 	bkeybase "github.com/42wim/matterbridge/bridge/keybase" | ||||
| 	bmatrix "github.com/42wim/matterbridge/bridge/matrix" | ||||
| 	bmattermost "github.com/42wim/matterbridge/bridge/mattermost" | ||||
| 	brocketchat "github.com/42wim/matterbridge/bridge/rocketchat" | ||||
| 	bslack "github.com/42wim/matterbridge/bridge/slack" | ||||
| 	bsshchat "github.com/42wim/matterbridge/bridge/sshchat" | ||||
| 	bsteam "github.com/42wim/matterbridge/bridge/steam" | ||||
| 	btelegram "github.com/42wim/matterbridge/bridge/telegram" | ||||
| 	bwhatsapp "github.com/42wim/matterbridge/bridge/whatsapp" | ||||
| 	bxmpp "github.com/42wim/matterbridge/bridge/xmpp" | ||||
| 	bzulip "github.com/42wim/matterbridge/bridge/zulip" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	FullMap = map[string]bridge.Factory{ | ||||
| 		"api":          api.New, | ||||
| 		"discord":      bdiscord.New, | ||||
| 		"gitter":       bgitter.New, | ||||
| 		"irc":          birc.New, | ||||
| 		"mattermost":   bmattermost.New, | ||||
| 		"matrix":       bmatrix.New, | ||||
| 		"rocketchat":   brocketchat.New, | ||||
| 		"slack-legacy": bslack.NewLegacy, | ||||
| 		"slack":        bslack.New, | ||||
| 		"sshchat":      bsshchat.New, | ||||
| 		"steam":        bsteam.New, | ||||
| 		"telegram":     btelegram.New, | ||||
| 		"whatsapp":     bwhatsapp.New, | ||||
| 		"xmpp":         bxmpp.New, | ||||
| 		"zulip":        bzulip.New, | ||||
| 		"keybase":      bkeybase.New, | ||||
| 	} | ||||
|  | ||||
| 	UserTypingSupport = map[string]struct{}{ | ||||
| 		"slack":   {}, | ||||
| 		"discord": {}, | ||||
| 	} | ||||
| 	FullMap           = map[string]bridge.Factory{} | ||||
| 	UserTypingSupport = map[string]struct{}{} | ||||
| ) | ||||
|   | ||||
							
								
								
									
										11
									
								
								gateway/bridgemap/brocketchat.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								gateway/bridgemap/brocketchat.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !norocketchat | ||||
|  | ||||
| package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	brocketchat "github.com/42wim/matterbridge/bridge/rocketchat" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	FullMap["rocketchat"] = brocketchat.New | ||||
| } | ||||
							
								
								
									
										13
									
								
								gateway/bridgemap/bslack.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								gateway/bridgemap/bslack.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| // +build !noslack | ||||
|  | ||||
| package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	bslack "github.com/42wim/matterbridge/bridge/slack" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	FullMap["slack-legacy"] = bslack.NewLegacy | ||||
| 	FullMap["slack"] = bslack.New | ||||
| 	UserTypingSupport["slack"] = struct{}{} | ||||
| } | ||||
							
								
								
									
										11
									
								
								gateway/bridgemap/bsshchat.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								gateway/bridgemap/bsshchat.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !nosshchat | ||||
|  | ||||
| package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	bsshchat "github.com/42wim/matterbridge/bridge/sshchat" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	FullMap["sshchat"] = bsshchat.New | ||||
| } | ||||
							
								
								
									
										11
									
								
								gateway/bridgemap/bsteam.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								gateway/bridgemap/bsteam.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !nosteam | ||||
|  | ||||
| package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	bsteam "github.com/42wim/matterbridge/bridge/steam" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	FullMap["steam"] = bsteam.New | ||||
| } | ||||
							
								
								
									
										11
									
								
								gateway/bridgemap/btelegram.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								gateway/bridgemap/btelegram.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !notelegram | ||||
|  | ||||
| package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	btelegram "github.com/42wim/matterbridge/bridge/telegram" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	FullMap["telegram"] = btelegram.New | ||||
| } | ||||
							
								
								
									
										11
									
								
								gateway/bridgemap/bwhatsapp.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								gateway/bridgemap/bwhatsapp.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !nowhatsapp | ||||
|  | ||||
| package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	bwhatsapp "github.com/42wim/matterbridge/bridge/whatsapp" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	FullMap["whatsapp"] = bwhatsapp.New | ||||
| } | ||||
							
								
								
									
										11
									
								
								gateway/bridgemap/bxmpp.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								gateway/bridgemap/bxmpp.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !noxmpp | ||||
|  | ||||
| package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	bxmpp "github.com/42wim/matterbridge/bridge/xmpp" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	FullMap["xmpp"] = bxmpp.New | ||||
| } | ||||
							
								
								
									
										11
									
								
								gateway/bridgemap/bzulip.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								gateway/bridgemap/bzulip.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !nozulip | ||||
|  | ||||
| package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	bzulip "github.com/42wim/matterbridge/bridge/zulip" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	FullMap["zulip"] = bzulip.New | ||||
| } | ||||
| @@ -1,6 +1,7 @@ | ||||
| package gateway | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"regexp" | ||||
| @@ -10,8 +11,8 @@ import ( | ||||
| 	"github.com/42wim/matterbridge/bridge" | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/42wim/matterbridge/internal" | ||||
| 	"github.com/d5/tengo/script" | ||||
| 	"github.com/d5/tengo/stdlib" | ||||
| 	"github.com/d5/tengo/v2" | ||||
| 	"github.com/d5/tengo/v2/stdlib" | ||||
| 	lru "github.com/hashicorp/golang-lru" | ||||
| 	"github.com/matterbridge/emoji" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| @@ -108,7 +109,7 @@ func (gw *Gateway) AddBridge(cfg *config.Bridge) error { | ||||
| func (gw *Gateway) checkConfig(cfg *config.Bridge) { | ||||
| 	match := false | ||||
| 	for _, key := range gw.Router.Config.Viper().AllKeys() { | ||||
| 		if strings.HasPrefix(key, cfg.Account) { | ||||
| 		if strings.HasPrefix(key, strings.ToLower(cfg.Account)) { | ||||
| 			match = true | ||||
| 			break | ||||
| 		} | ||||
| @@ -306,8 +307,6 @@ func (gw *Gateway) ignoreMessage(msg *config.Message) bool { | ||||
| } | ||||
|  | ||||
| func (gw *Gateway) modifyUsername(msg *config.Message, dest *bridge.Bridge) string { | ||||
| 	br := gw.Bridges[msg.Account] | ||||
| 	msg.Protocol = br.Protocol | ||||
| 	if dest.GetBool("StripNick") { | ||||
| 		re := regexp.MustCompile("[^a-zA-Z0-9]+") | ||||
| 		msg.Username = re.ReplaceAllString(msg.Username, "") | ||||
| @@ -315,6 +314,7 @@ func (gw *Gateway) modifyUsername(msg *config.Message, dest *bridge.Bridge) stri | ||||
| 	nick := dest.GetString("RemoteNickFormat") | ||||
|  | ||||
| 	// loop to replace nicks | ||||
| 	br := gw.Bridges[msg.Account] | ||||
| 	for _, outer := range br.GetStringSlice2D("ReplaceNicks") { | ||||
| 		search := outer[0] | ||||
| 		replace := outer[1] | ||||
| @@ -364,10 +364,23 @@ func (gw *Gateway) modifyAvatar(msg *config.Message, dest *bridge.Bridge) string | ||||
| } | ||||
|  | ||||
| func (gw *Gateway) modifyMessage(msg *config.Message) { | ||||
| 	if err := modifyMessageTengo(gw.BridgeValues().General.TengoModifyMessage, msg); err != nil { | ||||
| 	if gw.BridgeValues().General.TengoModifyMessage != "" { | ||||
| 		gw.logger.Warnf("General TengoModifyMessage=%s is deprecated and will be removed in v1.20.0, please move to Tengo InMessage=%s", gw.BridgeValues().General.TengoModifyMessage, gw.BridgeValues().General.TengoModifyMessage) | ||||
| 	} | ||||
|  | ||||
| 	if err := modifyInMessageTengo(gw.BridgeValues().General.TengoModifyMessage, msg); err != nil { | ||||
| 		gw.logger.Errorf("TengoModifyMessage failed: %s", err) | ||||
| 	} | ||||
| 	if err := modifyMessageTengo(gw.BridgeValues().Tengo.Message, msg); err != nil { | ||||
|  | ||||
| 	inMessage := gw.BridgeValues().Tengo.InMessage | ||||
| 	if inMessage == "" { | ||||
| 		inMessage = gw.BridgeValues().Tengo.Message | ||||
| 		if inMessage != "" { | ||||
| 			gw.logger.Warnf("Tengo Message=%s is deprecated and will be removed in v1.20.0, please move to Tengo InMessage=%s", inMessage, inMessage) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if err := modifyInMessageTengo(inMessage, msg); err != nil { | ||||
| 		gw.logger.Errorf("Tengo.Message failed: %s", err) | ||||
| 	} | ||||
|  | ||||
| @@ -418,8 +431,9 @@ func (gw *Gateway) SendMessage( | ||||
| 	} | ||||
|  | ||||
| 	// Too noisy to log like other events | ||||
| 	debugSendMessage := "" | ||||
| 	if msg.Event != config.EventUserTyping { | ||||
| 		gw.logger.Debugf("=> Sending %#v from %s (%s) to %s (%s)", msg, msg.Account, rmsg.Channel, dest.Account, channel.Name) | ||||
| 		debugSendMessage = fmt.Sprintf("=> Sending %#v from %s (%s) to %s (%s)", msg, msg.Account, rmsg.Channel, dest.Account, channel.Name) | ||||
| 	} | ||||
|  | ||||
| 	msg.Channel = channel.Name | ||||
| @@ -444,17 +458,29 @@ func (gw *Gateway) SendMessage( | ||||
| 		msg.ParentID = "msg-parent-not-found" | ||||
| 	} | ||||
|  | ||||
| 	err := gw.modifySendMessageTengo(rmsg, &msg, dest) | ||||
| 	drop, err := gw.modifyOutMessageTengo(rmsg, &msg, dest) | ||||
| 	if err != nil { | ||||
| 		gw.logger.Errorf("modifySendMessageTengo: %s", err) | ||||
| 	} | ||||
|  | ||||
| 	if drop { | ||||
| 		gw.logger.Debugf("=> Tengo dropping %#v from %s (%s) to %s (%s)", msg, msg.Account, rmsg.Channel, dest.Account, channel.Name) | ||||
| 		return "", nil | ||||
| 	} | ||||
|  | ||||
| 	if debugSendMessage != "" { | ||||
| 		gw.logger.Debug(debugSendMessage) | ||||
| 	} | ||||
| 	// if we are using mattermost plugin account, send messages to MattermostPlugin channel | ||||
| 	// that can be picked up by the mattermost matterbridge plugin | ||||
| 	if dest.Account == "mattermost.plugin" { | ||||
| 		gw.Router.MattermostPlugin <- msg | ||||
| 	} | ||||
|  | ||||
| 	defer func(t time.Time) { | ||||
| 		gw.logger.Debugf("=> Send from %s (%s) to %s (%s) took %s", msg.Account, rmsg.Channel, dest.Account, channel.Name, time.Since(t)) | ||||
| 	}(time.Now()) | ||||
|  | ||||
| 	mID, err := dest.Send(msg) | ||||
| 	if err != nil { | ||||
| 		return mID, err | ||||
| @@ -506,7 +532,7 @@ func getProtocol(msg *config.Message) string { | ||||
| 	return p[0] | ||||
| } | ||||
|  | ||||
| func modifyMessageTengo(filename string, msg *config.Message) error { | ||||
| func modifyInMessageTengo(filename string, msg *config.Message) error { | ||||
| 	if filename == "" { | ||||
| 		return nil | ||||
| 	} | ||||
| @@ -514,7 +540,7 @@ func modifyMessageTengo(filename string, msg *config.Message) error { | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	s := script.New(res) | ||||
| 	s := tengo.NewScript(res) | ||||
| 	s.SetImports(stdlib.GetModuleMap(stdlib.AllModuleNames()...)) | ||||
| 	_ = s.Add("msgText", msg.Text) | ||||
| 	_ = s.Add("msgUsername", msg.Username) | ||||
| @@ -541,7 +567,7 @@ func (gw *Gateway) modifyUsernameTengo(msg *config.Message, br *bridge.Bridge) ( | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	s := script.New(res) | ||||
| 	s := tengo.NewScript(res) | ||||
| 	s.SetImports(stdlib.GetModuleMap(stdlib.AllModuleNames()...)) | ||||
| 	_ = s.Add("result", "") | ||||
| 	_ = s.Add("msgText", msg.Text) | ||||
| @@ -565,22 +591,28 @@ func (gw *Gateway) modifyUsernameTengo(msg *config.Message, br *bridge.Bridge) ( | ||||
| 	return c.Get("result").String(), nil | ||||
| } | ||||
|  | ||||
| func (gw *Gateway) modifySendMessageTengo(origmsg *config.Message, msg *config.Message, br *bridge.Bridge) error { | ||||
| func (gw *Gateway) modifyOutMessageTengo(origmsg *config.Message, msg *config.Message, br *bridge.Bridge) (bool, error) { | ||||
| 	filename := gw.BridgeValues().Tengo.OutMessage | ||||
| 	var res []byte | ||||
| 	var err error | ||||
| 	var ( | ||||
| 		res  []byte | ||||
| 		err  error | ||||
| 		drop bool | ||||
| 	) | ||||
|  | ||||
| 	if filename == "" { | ||||
| 		res, err = internal.Asset("tengo/outmessage.tengo") | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 			return drop, err | ||||
| 		} | ||||
| 	} else { | ||||
| 		res, err = ioutil.ReadFile(filename) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 			return drop, err | ||||
| 		} | ||||
| 	} | ||||
| 	s := script.New(res) | ||||
|  | ||||
| 	s := tengo.NewScript(res) | ||||
|  | ||||
| 	s.SetImports(stdlib.GetModuleMap(stdlib.AllModuleNames()...)) | ||||
| 	_ = s.Add("inAccount", origmsg.Account) | ||||
| 	_ = s.Add("inProtocol", origmsg.Protocol) | ||||
| @@ -594,14 +626,19 @@ func (gw *Gateway) modifySendMessageTengo(origmsg *config.Message, msg *config.M | ||||
| 	_ = s.Add("outEvent", msg.Event) | ||||
| 	_ = s.Add("msgText", msg.Text) | ||||
| 	_ = s.Add("msgUsername", msg.Username) | ||||
| 	_ = s.Add("msgDrop", drop) | ||||
| 	c, err := s.Compile() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 		return drop, err | ||||
| 	} | ||||
|  | ||||
| 	if err := c.Run(); err != nil { | ||||
| 		return err | ||||
| 		return drop, err | ||||
| 	} | ||||
|  | ||||
| 	drop = c.Get("msgDrop").Bool() | ||||
| 	msg.Text = c.Get("msgText").String() | ||||
| 	msg.Username = c.Get("msgUsername").String() | ||||
| 	return nil | ||||
|  | ||||
| 	return drop, nil | ||||
| } | ||||
|   | ||||
| @@ -533,7 +533,7 @@ func (s *ignoreTestSuite) TestIgnoreNicks() { | ||||
| func BenchmarkTengo(b *testing.B) { | ||||
| 	msg := &config.Message{Username: "user", Text: "blah testing", Account: "protocol.account", Channel: "mychannel"} | ||||
| 	for n := 0; n < b.N; n++ { | ||||
| 		err := modifyMessageTengo("bench.tengo", msg) | ||||
| 		err := modifyInMessageTengo("bench.tengo", msg) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
|   | ||||
| @@ -169,7 +169,7 @@ func (gw *Gateway) ignoreEvent(event string, dest *bridge.Bridge) bool { | ||||
| 	switch event { | ||||
| 	case config.EventAvatarDownload: | ||||
| 		// Avatar downloads are only relevant for telegram and mattermost for now | ||||
| 		if dest.Protocol != "mattermost" && dest.Protocol != "telegram" { | ||||
| 		if dest.Protocol != "mattermost" && dest.Protocol != "telegram" && dest.Protocol != "xmpp" { | ||||
| 			return true | ||||
| 		} | ||||
| 	case config.EventJoinLeave: | ||||
| @@ -179,7 +179,7 @@ func (gw *Gateway) ignoreEvent(event string, dest *bridge.Bridge) bool { | ||||
| 		} | ||||
| 	case config.EventTopicChange: | ||||
| 		// only relay topic change when used in some way on other side | ||||
| 		if dest.GetBool("ShowTopicChange") && dest.GetBool("SyncTopic") { | ||||
| 		if !dest.GetBool("ShowTopicChange") && !dest.GetBool("SyncTopic") { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
| @@ -132,6 +132,9 @@ func (r *Router) handleReceive() { | ||||
| 		r.handleEventFailure(&msg) | ||||
| 		r.handleEventRejoinChannels(&msg) | ||||
|  | ||||
| 		// Set message protocol based on the account it came from | ||||
| 		msg.Protocol = r.getBridge(msg.Account).Protocol | ||||
|  | ||||
| 		filesHandled := false | ||||
| 		for _, gw := range r.Gateways { | ||||
| 			// record all the message ID's of the different bridges | ||||
|   | ||||
							
								
								
									
										87
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										87
									
								
								go.mod
									
									
									
									
									
								
							| @@ -4,68 +4,55 @@ require ( | ||||
| 	github.com/42wim/go-gitter v0.0.0-20170828205020-017310c2d557 | ||||
| 	github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f | ||||
| 	github.com/Jeffail/gabs v1.1.1 // indirect | ||||
| 	github.com/Philipp15b/go-steam v1.0.1-0.20190816133340-b04c5a83c1c0 | ||||
| 	github.com/Rhymen/go-whatsapp v0.0.3-0.20191003184814-fc3f792c814c | ||||
| 	github.com/bwmarrin/discordgo v0.19.0 | ||||
| 	// github.com/bwmarrin/discordgo v0.19.0 | ||||
| 	github.com/d5/tengo v1.24.8 | ||||
| 	github.com/dfordsoft/golib v0.0.0-20180902042739-76ee6ab99bec | ||||
| 	github.com/fsnotify/fsnotify v1.4.7 | ||||
| 	github.com/go-telegram-bot-api/telegram-bot-api v4.6.5-0.20181225215658-ec221ba9ea45+incompatible | ||||
| 	github.com/gomarkdown/markdown v0.0.0-20190912180731-281270bc6d83 | ||||
| 	github.com/google/gops v0.3.6 | ||||
| 	github.com/Philipp15b/go-steam v1.0.1-0.20200727090957-6ae9b3c0a560 | ||||
| 	github.com/Rhymen/go-whatsapp v0.1.2-0.20201122130733-6e5488ac98df | ||||
| 	github.com/d5/tengo/v2 v2.6.2 | ||||
| 	github.com/davecgh/go-spew v1.1.1 | ||||
| 	github.com/fsnotify/fsnotify v1.4.9 | ||||
| 	github.com/go-telegram-bot-api/telegram-bot-api v1.0.1-0.20200524105306-7434b0456e81 | ||||
| 	github.com/gomarkdown/markdown v0.0.0-20201113031856-722100d81a8e | ||||
| 	github.com/google/gops v0.3.13 | ||||
| 	github.com/gopackage/ddp v0.0.0-20170117053602-652027933df4 // indirect | ||||
| 	github.com/gopherjs/gopherjs v0.0.0-20180628210949-0892b62f0d9f // indirect | ||||
| 	github.com/gorilla/schema v1.1.0 | ||||
| 	github.com/gorilla/websocket v1.4.1 | ||||
| 	github.com/hashicorp/golang-lru v0.5.3 | ||||
| 	github.com/hpcloud/tail v1.0.0 // indirect | ||||
| 	github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7 | ||||
| 	github.com/jtolds/gls v4.2.1+incompatible // indirect | ||||
| 	github.com/keybase/go-keybase-chat-bot v0.0.0-20190816161829-561f10822eb2 | ||||
| 	github.com/labstack/echo/v4 v4.1.10 | ||||
| 	github.com/gorilla/schema v1.2.0 | ||||
| 	github.com/gorilla/websocket v1.4.2 | ||||
| 	github.com/hashicorp/golang-lru v0.5.4 | ||||
| 	github.com/jpillora/backoff v1.0.0 | ||||
| 	github.com/keybase/go-keybase-chat-bot v0.0.0-20200505163032-5cacf52379da | ||||
| 	github.com/labstack/echo/v4 v4.1.17 | ||||
| 	github.com/lrstanley/girc v0.0.0-20190801035559-4fc93959e1a7 | ||||
| 	github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20190210153444-cc9d05784d5d | ||||
| 	github.com/matrix-org/gomatrix v0.0.0-20200827122206-7dd5e2a05bcd | ||||
| 	github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20200411204219-d5c18ce75048 | ||||
| 	github.com/matterbridge/discordgo v0.22.0 | ||||
| 	github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible | ||||
| 	github.com/matterbridge/go-xmpp v0.0.0-20180529212104-cd19799fba91 | ||||
| 	github.com/matterbridge/gomatrix v0.0.0-20191026211822-6fc7accd00ca | ||||
| 	github.com/matterbridge/gozulipbot v0.0.0-20190212232658-7aa251978a18 | ||||
| 	github.com/matterbridge/logrus-prefixed-formatter v0.0.0-20180806162718-01618749af61 | ||||
| 	github.com/mattermost/mattermost-server v5.5.0+incompatible | ||||
| 	github.com/matterbridge/go-xmpp v0.0.0-20200418225040-c8a3a57b4050 | ||||
| 	github.com/matterbridge/gozulipbot v0.0.0-20200820220548-be5824faa913 | ||||
| 	github.com/matterbridge/logrus-prefixed-formatter v0.5.3-0.20200523233437-d971309a77ba | ||||
| 	github.com/mattermost/mattermost-server/v5 v5.29.0 | ||||
| 	github.com/mattn/godown v0.0.0-20201027140031-2c7783b24de7 | ||||
| 	github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect | ||||
| 	github.com/missdeer/golib v1.0.4 | ||||
| 	github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474 // indirect | ||||
| 	github.com/mrexodia/wray v0.0.0-20160318003008-78a2c1f284ff // indirect | ||||
| 	github.com/nelsonken/gomf v0.0.0-20180504123937-a9dd2f9deae9 | ||||
| 	github.com/nicksnyder/go-i18n v1.4.0 // indirect | ||||
| 	github.com/nlopes/slack v0.6.0 | ||||
| 	//github.com/nlopes/slack v0.6.0 | ||||
| 	github.com/onsi/ginkgo v1.6.0 // indirect | ||||
| 	github.com/onsi/gomega v1.4.1 // indirect | ||||
| 	github.com/paulrosania/go-charset v0.0.0-20190326053356-55c9d7a5834c | ||||
| 	github.com/pborman/uuid v0.0.0-20160216163710-c55201b03606 // indirect | ||||
| 	github.com/rs/xid v1.2.1 | ||||
| 	github.com/russross/blackfriday v1.5.2 | ||||
| 	github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca | ||||
| 	github.com/shazow/ssh-chat v1.8.2 | ||||
| 	github.com/sirupsen/logrus v1.4.2 | ||||
| 	github.com/smartystreets/assertions v0.0.0-20180803164922-886ec427f6b9 // indirect | ||||
| 	github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a // indirect | ||||
| 	github.com/spf13/viper v1.4.0 | ||||
| 	github.com/stretchr/testify v1.4.0 | ||||
| 	github.com/technoweenie/multipartstreamer v1.0.1 // indirect | ||||
| 	github.com/shazow/ssh-chat v1.10.1 | ||||
| 	github.com/sirupsen/logrus v1.7.0 | ||||
| 	github.com/slack-go/slack v0.7.2 | ||||
| 	github.com/spf13/viper v1.7.1 | ||||
| 	github.com/stretchr/testify v1.6.1 | ||||
| 	github.com/vincent-petithory/dataurl v0.0.0-20191104211930-d1553a71de50 | ||||
| 	github.com/writeas/go-strip-markdown v2.0.1+incompatible | ||||
| 	github.com/x-cray/logrus-prefixed-formatter v0.5.2 // indirect | ||||
| 	github.com/yaegashi/msgraph.go v0.1.4 | ||||
| 	github.com/zfjagann/golang-ring v0.0.0-20190304061218-d34796e0a6c2 | ||||
| 	golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 // indirect | ||||
| 	golang.org/x/image v0.0.0-20190902063713-cb417be4ba39 | ||||
| 	golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 // indirect | ||||
| 	golang.org/x/text v0.3.2 // indirect | ||||
| 	gopkg.in/fsnotify.v1 v1.4.7 // indirect | ||||
| 	gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect | ||||
| 	gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect | ||||
| 	golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 | ||||
| 	golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58 | ||||
| 	gomod.garykim.dev/nc-talk v0.1.5 | ||||
| 	gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376 | ||||
| 	layeh.com/gumble v0.0.0-20200818122324-146f9205029b | ||||
| ) | ||||
|  | ||||
| replace github.com/nlopes/slack v0.6.0 => github.com/matterbridge/slack v0.1.1-0.20191208194820-95190f11bfb6 | ||||
|  | ||||
| replace github.com/bwmarrin/discordgo v0.19.0 => github.com/matterbridge/discordgo v0.0.0-20191026232317-01823f4ebba4 | ||||
|  | ||||
| go 1.13 | ||||
| go 1.15 | ||||
|   | ||||
| @@ -12,8 +12,14 @@ text := import("text") | ||||
|  | ||||
| // start - strip irc colors  | ||||
| // if we're not sending to an irc bridge we strip the IRC colors | ||||
| if inProtocol == "irc" { | ||||
| if inProtocol == "irc" && outProtocol != "irc" { | ||||
|     re := text.re_compile(`\x03(?:\d{1,2}(?:,\d{1,2})?)?|[[:cntrl:]]`) | ||||
|     msgText=re.replace(msgText,"") | ||||
| } | ||||
| // end - strip irc colors | ||||
|  | ||||
| // strip custom emoji | ||||
| if inProtocol == "discord" { | ||||
|     re := text.re_compile(`<a?(:.*?:)[0-9]+>`) | ||||
|     msgText=re.replace(msgText,"$1") | ||||
| } | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import ( | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"runtime" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| @@ -15,7 +16,7 @@ import ( | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	version = "1.16.3" | ||||
| 	version = "1.20.0" | ||||
| 	githash string | ||||
|  | ||||
| 	flagConfig  = flag.String("conf", "matterbridge.toml", "config file") | ||||
| @@ -50,6 +51,15 @@ func main() { | ||||
| 	cfg := config.NewConfig(rootLogger, *flagConfig) | ||||
| 	cfg.BridgeValues().General.Debug = *flagDebug | ||||
|  | ||||
| 	// if logging to a file, ensure it is closed when the program terminates | ||||
| 	// nolint:errcheck | ||||
| 	defer func() { | ||||
| 		if f, ok := rootLogger.Out.(*os.File); ok { | ||||
| 			f.Sync() | ||||
| 			f.Close() | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	r, err := gateway.NewRouter(rootLogger, cfg, bridgemap.FullMap) | ||||
| 	if err != nil { | ||||
| 		logger.Fatalf("Starting gateway failed: %s", err) | ||||
| @@ -67,17 +77,31 @@ func setupLogger() *logrus.Logger { | ||||
| 		Formatter: &prefixed.TextFormatter{ | ||||
| 			PrefixPadding: 13, | ||||
| 			DisableColors: true, | ||||
| 			FullTimestamp: true, | ||||
| 		}, | ||||
| 		Level: logrus.InfoLevel, | ||||
| 	} | ||||
| 	if *flagDebug || os.Getenv("DEBUG") == "1" { | ||||
| 		logger.SetReportCaller(true) | ||||
| 		logger.Formatter = &prefixed.TextFormatter{ | ||||
| 			PrefixPadding:   13, | ||||
| 			DisableColors:   true, | ||||
| 			FullTimestamp:   false, | ||||
| 			ForceFormatting: true, | ||||
| 			PrefixPadding: 13, | ||||
| 			DisableColors: true, | ||||
| 			FullTimestamp: false, | ||||
|  | ||||
| 			CallerFormatter: func(function, file string) string { | ||||
| 				return fmt.Sprintf(" [%s:%s]", function, file) | ||||
| 			}, | ||||
| 			CallerPrettyfier: func(f *runtime.Frame) (string, string) { | ||||
| 				sp := strings.SplitAfter(f.File, "/matterbridge/") | ||||
| 				filename := f.File | ||||
| 				if len(sp) > 1 { | ||||
| 					filename = sp[1] | ||||
| 				} | ||||
| 				s := strings.Split(f.Function, ".") | ||||
| 				funcName := s[len(s)-1] | ||||
| 				return funcName, fmt.Sprintf("%s:%d", filename, f.Line) | ||||
| 			}, | ||||
| 		} | ||||
|  | ||||
| 		logger.Level = logrus.DebugLevel | ||||
| 		logger.WithFields(logrus.Fields{"prefix": "main"}).Info("Enabling debug logging.") | ||||
| 	} | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -4,7 +4,7 @@ import ( | ||||
| 	"errors" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/mattermost/mattermost-server/model" | ||||
| 	"github.com/mattermost/mattermost-server/v5/model" | ||||
| ) | ||||
|  | ||||
| // GetChannels returns all channels we're members off | ||||
| @@ -167,7 +167,7 @@ func (m *MMClient) JoinChannel(channelId string) error { //nolint:golint | ||||
| } | ||||
|  | ||||
| func (m *MMClient) UpdateChannelsTeam(teamID string) error { | ||||
| 	mmchannels, resp := m.Client.GetChannelsForTeamForUser(teamID, m.User.Id, "") | ||||
| 	mmchannels, resp := m.Client.GetChannelsForTeamForUser(teamID, m.User.Id, false, "") | ||||
| 	if resp.Error != nil { | ||||
| 		return errors.New(resp.Error.DetailedError) | ||||
| 	} | ||||
|   | ||||
| @@ -13,7 +13,7 @@ import ( | ||||
|  | ||||
| 	"github.com/gorilla/websocket" | ||||
| 	"github.com/jpillora/backoff" | ||||
| 	"github.com/mattermost/mattermost-server/model" | ||||
| 	"github.com/mattermost/mattermost-server/v5/model" | ||||
| ) | ||||
|  | ||||
| func (m *MMClient) doLogin(firstConnection bool, b *backoff.Backoff) error { | ||||
| @@ -154,7 +154,7 @@ func (m *MMClient) initUser() error { | ||||
|  | ||||
| 		t := &Team{Team: team, Users: usermap, Id: team.Id} | ||||
|  | ||||
| 		mmchannels, resp := m.Client.GetChannelsForTeamForUser(team.Id, m.User.Id, "") | ||||
| 		mmchannels, resp := m.Client.GetChannelsForTeamForUser(team.Id, m.User.Id, false, "") | ||||
| 		if resp.Error != nil { | ||||
| 			return resp.Error | ||||
| 		} | ||||
|   | ||||
| @@ -11,7 +11,7 @@ import ( | ||||
| 	lru "github.com/hashicorp/golang-lru" | ||||
| 	"github.com/jpillora/backoff" | ||||
| 	prefixed "github.com/matterbridge/logrus-prefixed-formatter" | ||||
| 	"github.com/mattermost/mattermost-server/model" | ||||
| 	"github.com/mattermost/mattermost-server/v5/model" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| @@ -69,6 +69,7 @@ type MMClient struct { | ||||
| 	logger     *logrus.Entry | ||||
| 	rootLogger *logrus.Logger | ||||
| 	lruCache   *lru.Cache | ||||
| 	allevents  bool | ||||
| } | ||||
|  | ||||
| // New will instantiate a new Matterclient with the specified login details without connecting. | ||||
| @@ -119,6 +120,10 @@ func (m *MMClient) SetLogLevel(level string) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (m *MMClient) EnableAllEvents() { | ||||
| 	m.allevents = true | ||||
| } | ||||
|  | ||||
| // Login tries to connect the client with the loging details with which it was initialized. | ||||
| func (m *MMClient) Login() error { | ||||
| 	// check if this is a first connect or a reconnection | ||||
| @@ -220,6 +225,10 @@ func (m *MMClient) WsReceiver() { | ||||
| 					continue | ||||
| 				} | ||||
| 			} | ||||
| 			if m.allevents { | ||||
| 				m.MessageChan <- msg | ||||
| 				continue | ||||
| 			} | ||||
| 			switch msg.Raw.Event { | ||||
| 			case model.WEBSOCKET_EVENT_USER_ADDED, | ||||
| 				model.WEBSOCKET_EVENT_USER_REMOVED, | ||||
|   | ||||
| @@ -3,7 +3,7 @@ package matterclient | ||||
| import ( | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/mattermost/mattermost-server/model" | ||||
| 	"github.com/mattermost/mattermost-server/v5/model" | ||||
| ) | ||||
|  | ||||
| func (m *MMClient) parseActionPost(rmsg *Message) { | ||||
|   | ||||
| @@ -4,7 +4,7 @@ import ( | ||||
| 	"errors" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/mattermost/mattermost-server/model" | ||||
| 	"github.com/mattermost/mattermost-server/v5/model" | ||||
| ) | ||||
|  | ||||
| func (m *MMClient) GetNickName(userId string) string { //nolint:golint | ||||
|   | ||||
| @@ -14,7 +14,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/gorilla/schema" | ||||
| 	"github.com/nlopes/slack" | ||||
| 	"github.com/slack-go/slack" | ||||
| ) | ||||
|  | ||||
| // OMessage for mattermost incoming webhook. (send to mattermost) | ||||
|   | ||||
							
								
								
									
										38
									
								
								tgs.Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								tgs.Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| FROM alpine AS builder | ||||
|  | ||||
| COPY . /go/src/github.com/42wim/matterbridge | ||||
| RUN apk add \ | ||||
|     go \ | ||||
|     git \ | ||||
|     gcc \ | ||||
|     musl-dev \ | ||||
|   && cd /go/src/github.com/42wim/matterbridge \ | ||||
|   && export GOPATH=/go \ | ||||
|   && go get \ | ||||
|   && go build -x -ldflags "-X main.githash=$(git log --pretty=format:'%h' -n 1)" -o /bin/matterbridge | ||||
|  | ||||
| FROM alpine | ||||
| RUN apk --no-cache add \ | ||||
|     ca-certificates \ | ||||
|     cairo \ | ||||
|     libjpeg-turbo \ | ||||
|     mailcap \ | ||||
|     py3-webencodings \ | ||||
|     python3 \ | ||||
|   && apk --no-cache add --virtual .compile \ | ||||
|     gcc \ | ||||
|     libffi-dev \ | ||||
|     libjpeg-turbo-dev \ | ||||
|     musl-dev \ | ||||
|     py3-pip \ | ||||
|     py3-wheel \ | ||||
|     python3-dev \ | ||||
|     zlib-dev \ | ||||
|   && pip3 install --no-cache-dir lottie[PNG] \ | ||||
|   && apk --no-cache del .compile | ||||
|  | ||||
| COPY --from=builder /bin/matterbridge /bin/matterbridge | ||||
| RUN mkdir /etc/matterbridge \ | ||||
|   && touch /etc/matterbridge/matterbridge.toml \ | ||||
|   && ln -sf /matterbridge.toml /etc/matterbridge/matterbridge.toml | ||||
| ENTRYPOINT ["/bin/matterbridge", "-conf", "/etc/matterbridge/matterbridge.toml"] | ||||
							
								
								
									
										5
									
								
								vendor/github.com/Philipp15b/go-steam/.gitmodules
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/Philipp15b/go-steam/.gitmodules
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,3 +1,6 @@ | ||||
| [submodule "generator/SteamKit"] | ||||
| 	path = generator/SteamKit | ||||
| 	url = https://github.com/Philipp15b/SteamKit.git | ||||
| 	url = https://github.com/SteamRE/SteamKit.git | ||||
| [submodule "generator/Protobufs"] | ||||
| 	path = generator/Protobufs | ||||
| 	url = https://github.com/SteamDatabase/Protobufs.git | ||||
|   | ||||
							
								
								
									
										4
									
								
								vendor/github.com/Philipp15b/go-steam/auth.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/Philipp15b/go-steam/auth.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -119,7 +119,7 @@ func (a *Auth) handleLogOnResponse(packet *Packet) { | ||||
| 			ExtendedResult:            EResult(body.GetEresultExtended()), | ||||
| 			OutOfGameSecsPerHeartbeat: body.GetOutOfGameHeartbeatSeconds(), | ||||
| 			InGameSecsPerHeartbeat:    body.GetInGameHeartbeatSeconds(), | ||||
| 			PublicIp:                  body.GetPublicIp(), | ||||
| 			PublicIp:                  body.GetDeprecatedPublicIp(), | ||||
| 			ServerTime:                body.GetRtime32ServerTime(), | ||||
| 			AccountFlags:              EAccountFlags(body.GetAccountFlags()), | ||||
| 			ClientSteamId:             SteamId(body.GetClientSuppliedSteamid()), | ||||
| @@ -127,7 +127,7 @@ func (a *Auth) handleLogOnResponse(packet *Packet) { | ||||
| 			CellId:                    body.GetCellId(), | ||||
| 			CellIdPingThreshold:       body.GetCellIdPingThreshold(), | ||||
| 			Steam2Ticket:              body.GetSteam2Ticket(), | ||||
| 			UsePics:                   body.GetUsePics(), | ||||
| 			UsePics:                   body.GetDeprecatedUsePics(), | ||||
| 			WebApiUserNonce:           body.GetWebapiAuthenticateUserNonce(), | ||||
| 			IpCountryCode:             body.GetIpCountryCode(), | ||||
| 			VanityUrl:                 body.GetVanityUrl(), | ||||
|   | ||||
							
								
								
									
										8
									
								
								vendor/github.com/Philipp15b/go-steam/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/Philipp15b/go-steam/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| module github.com/Philipp15b/go-steam | ||||
|  | ||||
| go 1.14 | ||||
|  | ||||
| require ( | ||||
| 	github.com/davecgh/go-spew v1.1.1 | ||||
| 	github.com/golang/protobuf v1.4.2 | ||||
| ) | ||||
							
								
								
									
										22
									
								
								vendor/github.com/Philipp15b/go-steam/go.sum
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/Philipp15b/go-steam/go.sum
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||||
| github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= | ||||
| github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= | ||||
| github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= | ||||
| github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= | ||||
| github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= | ||||
| github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= | ||||
| github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= | ||||
| github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | ||||
| github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | ||||
| github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= | ||||
| github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= | ||||
| google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= | ||||
| google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= | ||||
| google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= | ||||
| google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= | ||||
| google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= | ||||
| google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | ||||
							
								
								
									
										32
									
								
								vendor/github.com/Philipp15b/go-steam/protocol/protobuf/app_ticket.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								vendor/github.com/Philipp15b/go-steam/protocol/protobuf/app_ticket.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -21,11 +21,11 @@ var _ = math.Inf | ||||
| const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package | ||||
|  | ||||
| type EncryptedAppTicket struct { | ||||
| 	TicketVersionNo               *uint32  `protobuf:"varint,1,opt,name=ticket_version_no" json:"ticket_version_no,omitempty"` | ||||
| 	CrcEncryptedticket            *uint32  `protobuf:"varint,2,opt,name=crc_encryptedticket" json:"crc_encryptedticket,omitempty"` | ||||
| 	CbEncrypteduserdata           *uint32  `protobuf:"varint,3,opt,name=cb_encrypteduserdata" json:"cb_encrypteduserdata,omitempty"` | ||||
| 	CbEncryptedAppownershipticket *uint32  `protobuf:"varint,4,opt,name=cb_encrypted_appownershipticket" json:"cb_encrypted_appownershipticket,omitempty"` | ||||
| 	EncryptedTicket               []byte   `protobuf:"bytes,5,opt,name=encrypted_ticket" json:"encrypted_ticket,omitempty"` | ||||
| 	TicketVersionNo               *uint32  `protobuf:"varint,1,opt,name=ticket_version_no,json=ticketVersionNo" json:"ticket_version_no,omitempty"` | ||||
| 	CrcEncryptedticket            *uint32  `protobuf:"varint,2,opt,name=crc_encryptedticket,json=crcEncryptedticket" json:"crc_encryptedticket,omitempty"` | ||||
| 	CbEncrypteduserdata           *uint32  `protobuf:"varint,3,opt,name=cb_encrypteduserdata,json=cbEncrypteduserdata" json:"cb_encrypteduserdata,omitempty"` | ||||
| 	CbEncryptedAppownershipticket *uint32  `protobuf:"varint,4,opt,name=cb_encrypted_appownershipticket,json=cbEncryptedAppownershipticket" json:"cb_encrypted_appownershipticket,omitempty"` | ||||
| 	EncryptedTicket               []byte   `protobuf:"bytes,5,opt,name=encrypted_ticket,json=encryptedTicket" json:"encrypted_ticket,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral          struct{} `json:"-"` | ||||
| 	XXX_unrecognized              []byte   `json:"-"` | ||||
| 	XXX_sizecache                 int32    `json:"-"` | ||||
| @@ -98,16 +98,18 @@ func init() { | ||||
| func init() { proto.RegisterFile("encrypted_app_ticket.proto", fileDescriptor_c6d69fd1cac4e8d5) } | ||||
|  | ||||
| var fileDescriptor_c6d69fd1cac4e8d5 = []byte{ | ||||
| 	// 164 bytes of a gzipped FileDescriptorProto | ||||
| 	// 202 bytes of a gzipped FileDescriptorProto | ||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4a, 0xcd, 0x4b, 0x2e, | ||||
| 	0xaa, 0x2c, 0x28, 0x49, 0x4d, 0x89, 0x4f, 0x2c, 0x28, 0x88, 0x2f, 0xc9, 0x4c, 0xce, 0x4e, 0x2d, | ||||
| 	0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x57, 0x5a, 0xcb, 0xc8, 0x25, 0xe4, 0x0a, 0x93, 0x76, 0x2c, | ||||
| 	0x28, 0x08, 0x01, 0x4b, 0x0a, 0x49, 0x72, 0x09, 0x42, 0x94, 0xc5, 0x97, 0xa5, 0x16, 0x15, 0x67, | ||||
| 	0xe6, 0xe7, 0xc5, 0xe7, 0xe5, 0x4b, 0x30, 0x2a, 0x30, 0x6a, 0xf0, 0x0a, 0x49, 0x73, 0x09, 0x27, | ||||
| 	0x17, 0x25, 0xc7, 0xc3, 0xcd, 0x84, 0xa8, 0x93, 0x60, 0x02, 0x4b, 0xca, 0x70, 0x89, 0x24, 0x27, | ||||
| 	0x21, 0xe4, 0x4a, 0x8b, 0x53, 0x8b, 0x52, 0x12, 0x4b, 0x12, 0x25, 0x98, 0xc1, 0xb2, 0xea, 0x5c, | ||||
| 	0xf2, 0xc8, 0xb2, 0x20, 0xd7, 0xe4, 0x97, 0xe7, 0xa5, 0x16, 0x15, 0x67, 0x64, 0x16, 0x40, 0x8d, | ||||
| 	0x61, 0x01, 0x2b, 0x94, 0xe0, 0x12, 0x40, 0xa8, 0x82, 0xca, 0xb0, 0x2a, 0x30, 0x6a, 0xf0, 0x38, | ||||
| 	0xb1, 0x7a, 0x30, 0x36, 0x30, 0x32, 0x00, 0x02, 0x00, 0x00, 0xff, 0xff, 0x03, 0x8c, 0xdb, 0x92, | ||||
| 	0xd3, 0x00, 0x00, 0x00, | ||||
| 	0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x57, 0x9a, 0xce, 0xc4, 0x25, 0xe4, 0x0a, 0x93, 0x76, 0x2c, | ||||
| 	0x28, 0x08, 0x01, 0x4b, 0x0a, 0x69, 0x71, 0x09, 0x42, 0x94, 0xc5, 0x97, 0xa5, 0x16, 0x15, 0x67, | ||||
| 	0xe6, 0xe7, 0xc5, 0xe7, 0xe5, 0x4b, 0x30, 0x2a, 0x30, 0x6a, 0xf0, 0x06, 0xf1, 0x43, 0x24, 0xc2, | ||||
| 	0x20, 0xe2, 0x7e, 0xf9, 0x42, 0xfa, 0x5c, 0xc2, 0xc9, 0x45, 0xc9, 0xf1, 0x70, 0x4b, 0x20, 0xf2, | ||||
| 	0x12, 0x4c, 0x60, 0xd5, 0x42, 0xc9, 0x45, 0xc9, 0xae, 0xa8, 0x32, 0x42, 0x86, 0x5c, 0x22, 0xc9, | ||||
| 	0x49, 0x08, 0xf5, 0xa5, 0xc5, 0xa9, 0x45, 0x29, 0x89, 0x25, 0x89, 0x12, 0xcc, 0x60, 0x1d, 0xc2, | ||||
| 	0xc9, 0x49, 0xae, 0xe8, 0x52, 0x42, 0x6e, 0x5c, 0xf2, 0xc8, 0x5a, 0x40, 0xfe, 0xc8, 0x2f, 0xcf, | ||||
| 	0x4b, 0x2d, 0x2a, 0xce, 0xc8, 0x2c, 0x80, 0xda, 0xc7, 0x02, 0xd6, 0x2d, 0x8b, 0xa4, 0xdb, 0x11, | ||||
| 	0x43, 0x91, 0x90, 0x26, 0x97, 0x00, 0xc2, 0x10, 0xa8, 0x46, 0x56, 0x05, 0x46, 0x0d, 0x9e, 0x20, | ||||
| 	0x7e, 0xb8, 0x38, 0x24, 0x08, 0x9c, 0x58, 0x3d, 0x18, 0x1b, 0x18, 0x19, 0x00, 0x01, 0x00, 0x00, | ||||
| 	0xff, 0xff, 0xe8, 0x03, 0x98, 0x21, 0x3d, 0x01, 0x00, 0x00, | ||||
| } | ||||
|   | ||||
							
								
								
									
										1221
									
								
								vendor/github.com/Philipp15b/go-steam/protocol/protobuf/base.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1221
									
								
								vendor/github.com/Philipp15b/go-steam/protocol/protobuf/base.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2801
									
								
								vendor/github.com/Philipp15b/go-steam/protocol/protobuf/client_server.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2801
									
								
								vendor/github.com/Philipp15b/go-steam/protocol/protobuf/client_server.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2860
									
								
								vendor/github.com/Philipp15b/go-steam/protocol/protobuf/client_server_2.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2860
									
								
								vendor/github.com/Philipp15b/go-steam/protocol/protobuf/client_server_2.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										531
									
								
								vendor/github.com/Philipp15b/go-steam/protocol/protobuf/client_server_friends.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										531
									
								
								vendor/github.com/Philipp15b/go-steam/protocol/protobuf/client_server_friends.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -22,10 +22,10 @@ const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package | ||||
|  | ||||
| type CMsgClientFriendMsg struct { | ||||
| 	Steamid                *uint64  `protobuf:"fixed64,1,opt,name=steamid" json:"steamid,omitempty"` | ||||
| 	ChatEntryType          *int32   `protobuf:"varint,2,opt,name=chat_entry_type" json:"chat_entry_type,omitempty"` | ||||
| 	ChatEntryType          *int32   `protobuf:"varint,2,opt,name=chat_entry_type,json=chatEntryType" json:"chat_entry_type,omitempty"` | ||||
| 	Message                []byte   `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` | ||||
| 	Rtime32ServerTimestamp *uint32  `protobuf:"fixed32,4,opt,name=rtime32_server_timestamp" json:"rtime32_server_timestamp,omitempty"` | ||||
| 	EchoToSender           *bool    `protobuf:"varint,5,opt,name=echo_to_sender" json:"echo_to_sender,omitempty"` | ||||
| 	Rtime32ServerTimestamp *uint32  `protobuf:"fixed32,4,opt,name=rtime32_server_timestamp,json=rtime32ServerTimestamp" json:"rtime32_server_timestamp,omitempty"` | ||||
| 	EchoToSender           *bool    `protobuf:"varint,5,opt,name=echo_to_sender,json=echoToSender" json:"echo_to_sender,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral   struct{} `json:"-"` | ||||
| 	XXX_unrecognized       []byte   `json:"-"` | ||||
| 	XXX_sizecache          int32    `json:"-"` | ||||
| @@ -92,11 +92,11 @@ func (m *CMsgClientFriendMsg) GetEchoToSender() bool { | ||||
| } | ||||
|  | ||||
| type CMsgClientFriendMsgIncoming struct { | ||||
| 	SteamidFrom            *uint64  `protobuf:"fixed64,1,opt,name=steamid_from" json:"steamid_from,omitempty"` | ||||
| 	ChatEntryType          *int32   `protobuf:"varint,2,opt,name=chat_entry_type" json:"chat_entry_type,omitempty"` | ||||
| 	FromLimitedAccount     *bool    `protobuf:"varint,3,opt,name=from_limited_account" json:"from_limited_account,omitempty"` | ||||
| 	SteamidFrom            *uint64  `protobuf:"fixed64,1,opt,name=steamid_from,json=steamidFrom" json:"steamid_from,omitempty"` | ||||
| 	ChatEntryType          *int32   `protobuf:"varint,2,opt,name=chat_entry_type,json=chatEntryType" json:"chat_entry_type,omitempty"` | ||||
| 	FromLimitedAccount     *bool    `protobuf:"varint,3,opt,name=from_limited_account,json=fromLimitedAccount" json:"from_limited_account,omitempty"` | ||||
| 	Message                []byte   `protobuf:"bytes,4,opt,name=message" json:"message,omitempty"` | ||||
| 	Rtime32ServerTimestamp *uint32  `protobuf:"fixed32,5,opt,name=rtime32_server_timestamp" json:"rtime32_server_timestamp,omitempty"` | ||||
| 	Rtime32ServerTimestamp *uint32  `protobuf:"fixed32,5,opt,name=rtime32_server_timestamp,json=rtime32ServerTimestamp" json:"rtime32_server_timestamp,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral   struct{} `json:"-"` | ||||
| 	XXX_unrecognized       []byte   `json:"-"` | ||||
| 	XXX_sizecache          int32    `json:"-"` | ||||
| @@ -163,8 +163,8 @@ func (m *CMsgClientFriendMsgIncoming) GetRtime32ServerTimestamp() uint32 { | ||||
| } | ||||
|  | ||||
| type CMsgClientAddFriend struct { | ||||
| 	SteamidToAdd            *uint64  `protobuf:"fixed64,1,opt,name=steamid_to_add" json:"steamid_to_add,omitempty"` | ||||
| 	AccountnameOrEmailToAdd *string  `protobuf:"bytes,2,opt,name=accountname_or_email_to_add" json:"accountname_or_email_to_add,omitempty"` | ||||
| 	SteamidToAdd            *uint64  `protobuf:"fixed64,1,opt,name=steamid_to_add,json=steamidToAdd" json:"steamid_to_add,omitempty"` | ||||
| 	AccountnameOrEmailToAdd *string  `protobuf:"bytes,2,opt,name=accountname_or_email_to_add,json=accountnameOrEmailToAdd" json:"accountname_or_email_to_add,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral    struct{} `json:"-"` | ||||
| 	XXX_unrecognized        []byte   `json:"-"` | ||||
| 	XXX_sizecache           int32    `json:"-"` | ||||
| @@ -211,8 +211,8 @@ func (m *CMsgClientAddFriend) GetAccountnameOrEmailToAdd() string { | ||||
|  | ||||
| type CMsgClientAddFriendResponse struct { | ||||
| 	Eresult              *int32   `protobuf:"varint,1,opt,name=eresult,def=2" json:"eresult,omitempty"` | ||||
| 	SteamIdAdded         *uint64  `protobuf:"fixed64,2,opt,name=steam_id_added" json:"steam_id_added,omitempty"` | ||||
| 	PersonaNameAdded     *string  `protobuf:"bytes,3,opt,name=persona_name_added" json:"persona_name_added,omitempty"` | ||||
| 	SteamIdAdded         *uint64  `protobuf:"fixed64,2,opt,name=steam_id_added,json=steamIdAdded" json:"steam_id_added,omitempty"` | ||||
| 	PersonaNameAdded     *string  `protobuf:"bytes,3,opt,name=persona_name_added,json=personaNameAdded" json:"persona_name_added,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| @@ -355,9 +355,9 @@ func (m *CMsgClientHideFriend) GetHide() bool { | ||||
| type CMsgClientFriendsList struct { | ||||
| 	Bincremental         *bool                           `protobuf:"varint,1,opt,name=bincremental" json:"bincremental,omitempty"` | ||||
| 	Friends              []*CMsgClientFriendsList_Friend `protobuf:"bytes,2,rep,name=friends" json:"friends,omitempty"` | ||||
| 	MaxFriendCount       *uint32                         `protobuf:"varint,3,opt,name=max_friend_count" json:"max_friend_count,omitempty"` | ||||
| 	ActiveFriendCount    *uint32                         `protobuf:"varint,4,opt,name=active_friend_count" json:"active_friend_count,omitempty"` | ||||
| 	FriendsLimitHit      *bool                           `protobuf:"varint,5,opt,name=friends_limit_hit" json:"friends_limit_hit,omitempty"` | ||||
| 	MaxFriendCount       *uint32                         `protobuf:"varint,3,opt,name=max_friend_count,json=maxFriendCount" json:"max_friend_count,omitempty"` | ||||
| 	ActiveFriendCount    *uint32                         `protobuf:"varint,4,opt,name=active_friend_count,json=activeFriendCount" json:"active_friend_count,omitempty"` | ||||
| 	FriendsLimitHit      *bool                           `protobuf:"varint,5,opt,name=friends_limit_hit,json=friendsLimitHit" json:"friends_limit_hit,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{}                        `json:"-"` | ||||
| 	XXX_unrecognized     []byte                          `json:"-"` | ||||
| 	XXX_sizecache        int32                           `json:"-"` | ||||
| @@ -826,7 +826,7 @@ func (m *CMsgClientSetPlayerNicknameResponse) GetEresult() uint32 { | ||||
| } | ||||
|  | ||||
| type CMsgClientRequestFriendData struct { | ||||
| 	PersonaStateRequested *uint32  `protobuf:"varint,1,opt,name=persona_state_requested" json:"persona_state_requested,omitempty"` | ||||
| 	PersonaStateRequested *uint32  `protobuf:"varint,1,opt,name=persona_state_requested,json=personaStateRequested" json:"persona_state_requested,omitempty"` | ||||
| 	Friends               []uint64 `protobuf:"fixed64,2,rep,name=friends" json:"friends,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral  struct{} `json:"-"` | ||||
| 	XXX_unrecognized      []byte   `json:"-"` | ||||
| @@ -873,14 +873,14 @@ func (m *CMsgClientRequestFriendData) GetFriends() []uint64 { | ||||
| } | ||||
|  | ||||
| type CMsgClientChangeStatus struct { | ||||
| 	PersonaState         *uint32  `protobuf:"varint,1,opt,name=persona_state" json:"persona_state,omitempty"` | ||||
| 	PlayerName           *string  `protobuf:"bytes,2,opt,name=player_name" json:"player_name,omitempty"` | ||||
| 	IsAutoGeneratedName  *bool    `protobuf:"varint,3,opt,name=is_auto_generated_name" json:"is_auto_generated_name,omitempty"` | ||||
| 	HighPriority         *bool    `protobuf:"varint,4,opt,name=high_priority" json:"high_priority,omitempty"` | ||||
| 	PersonaSetByUser     *bool    `protobuf:"varint,5,opt,name=persona_set_by_user" json:"persona_set_by_user,omitempty"` | ||||
| 	PersonaStateFlags    *uint32  `protobuf:"varint,6,opt,name=persona_state_flags,def=0" json:"persona_state_flags,omitempty"` | ||||
| 	NeedPersonaResponse  *bool    `protobuf:"varint,7,opt,name=need_persona_response" json:"need_persona_response,omitempty"` | ||||
| 	IsClientIdle         *bool    `protobuf:"varint,8,opt,name=is_client_idle" json:"is_client_idle,omitempty"` | ||||
| 	PersonaState         *uint32  `protobuf:"varint,1,opt,name=persona_state,json=personaState" json:"persona_state,omitempty"` | ||||
| 	PlayerName           *string  `protobuf:"bytes,2,opt,name=player_name,json=playerName" json:"player_name,omitempty"` | ||||
| 	IsAutoGeneratedName  *bool    `protobuf:"varint,3,opt,name=is_auto_generated_name,json=isAutoGeneratedName" json:"is_auto_generated_name,omitempty"` | ||||
| 	HighPriority         *bool    `protobuf:"varint,4,opt,name=high_priority,json=highPriority" json:"high_priority,omitempty"` | ||||
| 	PersonaSetByUser     *bool    `protobuf:"varint,5,opt,name=persona_set_by_user,json=personaSetByUser" json:"persona_set_by_user,omitempty"` | ||||
| 	PersonaStateFlags    *uint32  `protobuf:"varint,6,opt,name=persona_state_flags,json=personaStateFlags,def=0" json:"persona_state_flags,omitempty"` | ||||
| 	NeedPersonaResponse  *bool    `protobuf:"varint,7,opt,name=need_persona_response,json=needPersonaResponse" json:"need_persona_response,omitempty"` | ||||
| 	IsClientIdle         *bool    `protobuf:"varint,8,opt,name=is_client_idle,json=isClientIdle" json:"is_client_idle,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| @@ -971,7 +971,7 @@ func (m *CMsgClientChangeStatus) GetIsClientIdle() bool { | ||||
|  | ||||
| type CMsgPersonaChangeResponse struct { | ||||
| 	Result               *uint32  `protobuf:"varint,1,opt,name=result" json:"result,omitempty"` | ||||
| 	PlayerName           *string  `protobuf:"bytes,2,opt,name=player_name" json:"player_name,omitempty"` | ||||
| 	PlayerName           *string  `protobuf:"bytes,2,opt,name=player_name,json=playerName" json:"player_name,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| @@ -1017,7 +1017,7 @@ func (m *CMsgPersonaChangeResponse) GetPlayerName() string { | ||||
| } | ||||
|  | ||||
| type CMsgClientPersonaState struct { | ||||
| 	StatusFlags          *uint32                          `protobuf:"varint,1,opt,name=status_flags" json:"status_flags,omitempty"` | ||||
| 	StatusFlags          *uint32                          `protobuf:"varint,1,opt,name=status_flags,json=statusFlags" json:"status_flags,omitempty"` | ||||
| 	Friends              []*CMsgClientPersonaState_Friend `protobuf:"bytes,2,rep,name=friends" json:"friends,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{}                         `json:"-"` | ||||
| 	XXX_unrecognized     []byte                           `json:"-"` | ||||
| @@ -1065,34 +1065,33 @@ func (m *CMsgClientPersonaState) GetFriends() []*CMsgClientPersonaState_Friend { | ||||
|  | ||||
| type CMsgClientPersonaState_Friend struct { | ||||
| 	Friendid                   *uint64                                 `protobuf:"fixed64,1,opt,name=friendid" json:"friendid,omitempty"` | ||||
| 	PersonaState               *uint32                                 `protobuf:"varint,2,opt,name=persona_state" json:"persona_state,omitempty"` | ||||
| 	GamePlayedAppId            *uint32                                 `protobuf:"varint,3,opt,name=game_played_app_id" json:"game_played_app_id,omitempty"` | ||||
| 	GameServerIp               *uint32                                 `protobuf:"varint,4,opt,name=game_server_ip" json:"game_server_ip,omitempty"` | ||||
| 	GameServerPort             *uint32                                 `protobuf:"varint,5,opt,name=game_server_port" json:"game_server_port,omitempty"` | ||||
| 	PersonaStateFlags          *uint32                                 `protobuf:"varint,6,opt,name=persona_state_flags" json:"persona_state_flags,omitempty"` | ||||
| 	OnlineSessionInstances     *uint32                                 `protobuf:"varint,7,opt,name=online_session_instances" json:"online_session_instances,omitempty"` | ||||
| 	PublishedInstanceId        *uint32                                 `protobuf:"varint,8,opt,name=published_instance_id" json:"published_instance_id,omitempty"` | ||||
| 	PersonaSetByUser           *bool                                   `protobuf:"varint,10,opt,name=persona_set_by_user" json:"persona_set_by_user,omitempty"` | ||||
| 	PlayerName                 *string                                 `protobuf:"bytes,15,opt,name=player_name" json:"player_name,omitempty"` | ||||
| 	QueryPort                  *uint32                                 `protobuf:"varint,20,opt,name=query_port" json:"query_port,omitempty"` | ||||
| 	SteamidSource              *uint64                                 `protobuf:"fixed64,25,opt,name=steamid_source" json:"steamid_source,omitempty"` | ||||
| 	AvatarHash                 []byte                                  `protobuf:"bytes,31,opt,name=avatar_hash" json:"avatar_hash,omitempty"` | ||||
| 	LastLogoff                 *uint32                                 `protobuf:"varint,45,opt,name=last_logoff" json:"last_logoff,omitempty"` | ||||
| 	LastLogon                  *uint32                                 `protobuf:"varint,46,opt,name=last_logon" json:"last_logon,omitempty"` | ||||
| 	LastSeenOnline             *uint32                                 `protobuf:"varint,47,opt,name=last_seen_online" json:"last_seen_online,omitempty"` | ||||
| 	ClanRank                   *uint32                                 `protobuf:"varint,50,opt,name=clan_rank" json:"clan_rank,omitempty"` | ||||
| 	GameName                   *string                                 `protobuf:"bytes,55,opt,name=game_name" json:"game_name,omitempty"` | ||||
| 	PersonaState               *uint32                                 `protobuf:"varint,2,opt,name=persona_state,json=personaState" json:"persona_state,omitempty"` | ||||
| 	GamePlayedAppId            *uint32                                 `protobuf:"varint,3,opt,name=game_played_app_id,json=gamePlayedAppId" json:"game_played_app_id,omitempty"` | ||||
| 	GameServerIp               *uint32                                 `protobuf:"varint,4,opt,name=game_server_ip,json=gameServerIp" json:"game_server_ip,omitempty"` | ||||
| 	GameServerPort             *uint32                                 `protobuf:"varint,5,opt,name=game_server_port,json=gameServerPort" json:"game_server_port,omitempty"` | ||||
| 	PersonaStateFlags          *uint32                                 `protobuf:"varint,6,opt,name=persona_state_flags,json=personaStateFlags" json:"persona_state_flags,omitempty"` | ||||
| 	OnlineSessionInstances     *uint32                                 `protobuf:"varint,7,opt,name=online_session_instances,json=onlineSessionInstances" json:"online_session_instances,omitempty"` | ||||
| 	PersonaSetByUser           *bool                                   `protobuf:"varint,10,opt,name=persona_set_by_user,json=personaSetByUser" json:"persona_set_by_user,omitempty"` | ||||
| 	PlayerName                 *string                                 `protobuf:"bytes,15,opt,name=player_name,json=playerName" json:"player_name,omitempty"` | ||||
| 	QueryPort                  *uint32                                 `protobuf:"varint,20,opt,name=query_port,json=queryPort" json:"query_port,omitempty"` | ||||
| 	SteamidSource              *uint64                                 `protobuf:"fixed64,25,opt,name=steamid_source,json=steamidSource" json:"steamid_source,omitempty"` | ||||
| 	AvatarHash                 []byte                                  `protobuf:"bytes,31,opt,name=avatar_hash,json=avatarHash" json:"avatar_hash,omitempty"` | ||||
| 	LastLogoff                 *uint32                                 `protobuf:"varint,45,opt,name=last_logoff,json=lastLogoff" json:"last_logoff,omitempty"` | ||||
| 	LastLogon                  *uint32                                 `protobuf:"varint,46,opt,name=last_logon,json=lastLogon" json:"last_logon,omitempty"` | ||||
| 	LastSeenOnline             *uint32                                 `protobuf:"varint,47,opt,name=last_seen_online,json=lastSeenOnline" json:"last_seen_online,omitempty"` | ||||
| 	ClanRank                   *uint32                                 `protobuf:"varint,50,opt,name=clan_rank,json=clanRank" json:"clan_rank,omitempty"` | ||||
| 	GameName                   *string                                 `protobuf:"bytes,55,opt,name=game_name,json=gameName" json:"game_name,omitempty"` | ||||
| 	Gameid                     *uint64                                 `protobuf:"fixed64,56,opt,name=gameid" json:"gameid,omitempty"` | ||||
| 	GameDataBlob               []byte                                  `protobuf:"bytes,60,opt,name=game_data_blob" json:"game_data_blob,omitempty"` | ||||
| 	ClanData                   *CMsgClientPersonaState_Friend_ClanData `protobuf:"bytes,64,opt,name=clan_data" json:"clan_data,omitempty"` | ||||
| 	ClanTag                    *string                                 `protobuf:"bytes,65,opt,name=clan_tag" json:"clan_tag,omitempty"` | ||||
| 	RichPresence               []*CMsgClientPersonaState_Friend_KV     `protobuf:"bytes,71,rep,name=rich_presence" json:"rich_presence,omitempty"` | ||||
| 	BroadcastId                *uint64                                 `protobuf:"fixed64,72,opt,name=broadcast_id" json:"broadcast_id,omitempty"` | ||||
| 	GameLobbyId                *uint64                                 `protobuf:"fixed64,73,opt,name=game_lobby_id" json:"game_lobby_id,omitempty"` | ||||
| 	WatchingBroadcastAccountid *uint32                                 `protobuf:"varint,74,opt,name=watching_broadcast_accountid" json:"watching_broadcast_accountid,omitempty"` | ||||
| 	WatchingBroadcastAppid     *uint32                                 `protobuf:"varint,75,opt,name=watching_broadcast_appid" json:"watching_broadcast_appid,omitempty"` | ||||
| 	WatchingBroadcastViewers   *uint32                                 `protobuf:"varint,76,opt,name=watching_broadcast_viewers" json:"watching_broadcast_viewers,omitempty"` | ||||
| 	WatchingBroadcastTitle     *string                                 `protobuf:"bytes,77,opt,name=watching_broadcast_title" json:"watching_broadcast_title,omitempty"` | ||||
| 	GameDataBlob               []byte                                  `protobuf:"bytes,60,opt,name=game_data_blob,json=gameDataBlob" json:"game_data_blob,omitempty"` | ||||
| 	ClanData                   *CMsgClientPersonaState_Friend_ClanData `protobuf:"bytes,64,opt,name=clan_data,json=clanData" json:"clan_data,omitempty"` | ||||
| 	ClanTag                    *string                                 `protobuf:"bytes,65,opt,name=clan_tag,json=clanTag" json:"clan_tag,omitempty"` | ||||
| 	RichPresence               []*CMsgClientPersonaState_Friend_KV     `protobuf:"bytes,71,rep,name=rich_presence,json=richPresence" json:"rich_presence,omitempty"` | ||||
| 	BroadcastId                *uint64                                 `protobuf:"fixed64,72,opt,name=broadcast_id,json=broadcastId" json:"broadcast_id,omitempty"` | ||||
| 	GameLobbyId                *uint64                                 `protobuf:"fixed64,73,opt,name=game_lobby_id,json=gameLobbyId" json:"game_lobby_id,omitempty"` | ||||
| 	WatchingBroadcastAccountid *uint32                                 `protobuf:"varint,74,opt,name=watching_broadcast_accountid,json=watchingBroadcastAccountid" json:"watching_broadcast_accountid,omitempty"` | ||||
| 	WatchingBroadcastAppid     *uint32                                 `protobuf:"varint,75,opt,name=watching_broadcast_appid,json=watchingBroadcastAppid" json:"watching_broadcast_appid,omitempty"` | ||||
| 	WatchingBroadcastViewers   *uint32                                 `protobuf:"varint,76,opt,name=watching_broadcast_viewers,json=watchingBroadcastViewers" json:"watching_broadcast_viewers,omitempty"` | ||||
| 	WatchingBroadcastTitle     *string                                 `protobuf:"bytes,77,opt,name=watching_broadcast_title,json=watchingBroadcastTitle" json:"watching_broadcast_title,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral       struct{}                                `json:"-"` | ||||
| 	XXX_unrecognized           []byte                                  `json:"-"` | ||||
| 	XXX_sizecache              int32                                   `json:"-"` | ||||
| @@ -1172,13 +1171,6 @@ func (m *CMsgClientPersonaState_Friend) GetOnlineSessionInstances() uint32 { | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientPersonaState_Friend) GetPublishedInstanceId() uint32 { | ||||
| 	if m != nil && m.PublishedInstanceId != nil { | ||||
| 		return *m.PublishedInstanceId | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientPersonaState_Friend) GetPersonaSetByUser() bool { | ||||
| 	if m != nil && m.PersonaSetByUser != nil { | ||||
| 		return *m.PersonaSetByUser | ||||
| @@ -1327,8 +1319,8 @@ func (m *CMsgClientPersonaState_Friend) GetWatchingBroadcastTitle() string { | ||||
| } | ||||
|  | ||||
| type CMsgClientPersonaState_Friend_ClanData struct { | ||||
| 	OggAppId             *uint32  `protobuf:"varint,1,opt,name=ogg_app_id" json:"ogg_app_id,omitempty"` | ||||
| 	ChatGroupId          *uint64  `protobuf:"varint,2,opt,name=chat_group_id" json:"chat_group_id,omitempty"` | ||||
| 	OggAppId             *uint32  `protobuf:"varint,1,opt,name=ogg_app_id,json=oggAppId" json:"ogg_app_id,omitempty"` | ||||
| 	ChatGroupId          *uint64  `protobuf:"varint,2,opt,name=chat_group_id,json=chatGroupId" json:"chat_group_id,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| @@ -1423,7 +1415,7 @@ func (m *CMsgClientPersonaState_Friend_KV) GetValue() string { | ||||
| } | ||||
|  | ||||
| type CMsgClientFriendProfileInfo struct { | ||||
| 	SteamidFriend        *uint64  `protobuf:"fixed64,1,opt,name=steamid_friend" json:"steamid_friend,omitempty"` | ||||
| 	SteamidFriend        *uint64  `protobuf:"fixed64,1,opt,name=steamid_friend,json=steamidFriend" json:"steamid_friend,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| @@ -1463,12 +1455,12 @@ func (m *CMsgClientFriendProfileInfo) GetSteamidFriend() uint64 { | ||||
|  | ||||
| type CMsgClientFriendProfileInfoResponse struct { | ||||
| 	Eresult              *int32   `protobuf:"varint,1,opt,name=eresult,def=2" json:"eresult,omitempty"` | ||||
| 	SteamidFriend        *uint64  `protobuf:"fixed64,2,opt,name=steamid_friend" json:"steamid_friend,omitempty"` | ||||
| 	TimeCreated          *uint32  `protobuf:"varint,3,opt,name=time_created" json:"time_created,omitempty"` | ||||
| 	RealName             *string  `protobuf:"bytes,4,opt,name=real_name" json:"real_name,omitempty"` | ||||
| 	CityName             *string  `protobuf:"bytes,5,opt,name=city_name" json:"city_name,omitempty"` | ||||
| 	StateName            *string  `protobuf:"bytes,6,opt,name=state_name" json:"state_name,omitempty"` | ||||
| 	CountryName          *string  `protobuf:"bytes,7,opt,name=country_name" json:"country_name,omitempty"` | ||||
| 	SteamidFriend        *uint64  `protobuf:"fixed64,2,opt,name=steamid_friend,json=steamidFriend" json:"steamid_friend,omitempty"` | ||||
| 	TimeCreated          *uint32  `protobuf:"varint,3,opt,name=time_created,json=timeCreated" json:"time_created,omitempty"` | ||||
| 	RealName             *string  `protobuf:"bytes,4,opt,name=real_name,json=realName" json:"real_name,omitempty"` | ||||
| 	CityName             *string  `protobuf:"bytes,5,opt,name=city_name,json=cityName" json:"city_name,omitempty"` | ||||
| 	StateName            *string  `protobuf:"bytes,6,opt,name=state_name,json=stateName" json:"state_name,omitempty"` | ||||
| 	CountryName          *string  `protobuf:"bytes,7,opt,name=country_name,json=countryName" json:"country_name,omitempty"` | ||||
| 	Headline             *string  `protobuf:"bytes,8,opt,name=headline" json:"headline,omitempty"` | ||||
| 	Summary              *string  `protobuf:"bytes,9,opt,name=summary" json:"summary,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| @@ -1569,7 +1561,7 @@ func (m *CMsgClientFriendProfileInfoResponse) GetSummary() string { | ||||
| type CMsgClientCreateFriendsGroup struct { | ||||
| 	Steamid              *uint64  `protobuf:"fixed64,1,opt,name=steamid" json:"steamid,omitempty"` | ||||
| 	Groupname            *string  `protobuf:"bytes,2,opt,name=groupname" json:"groupname,omitempty"` | ||||
| 	SteamidFriends       []uint64 `protobuf:"fixed64,3,rep,name=steamid_friends" json:"steamid_friends,omitempty"` | ||||
| 	SteamidFriends       []uint64 `protobuf:"fixed64,3,rep,name=steamid_friends,json=steamidFriends" json:"steamid_friends,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| @@ -1757,8 +1749,8 @@ func (m *CMsgClientDeleteFriendsGroupResponse) GetEresult() uint32 { | ||||
| type CMsgClientManageFriendsGroup struct { | ||||
| 	Groupid               *int32   `protobuf:"varint,1,opt,name=groupid" json:"groupid,omitempty"` | ||||
| 	Groupname             *string  `protobuf:"bytes,2,opt,name=groupname" json:"groupname,omitempty"` | ||||
| 	SteamidFriendsAdded   []uint64 `protobuf:"fixed64,3,rep,name=steamid_friends_added" json:"steamid_friends_added,omitempty"` | ||||
| 	SteamidFriendsRemoved []uint64 `protobuf:"fixed64,4,rep,name=steamid_friends_removed" json:"steamid_friends_removed,omitempty"` | ||||
| 	SteamidFriendsAdded   []uint64 `protobuf:"fixed64,3,rep,name=steamid_friends_added,json=steamidFriendsAdded" json:"steamid_friends_added,omitempty"` | ||||
| 	SteamidFriendsRemoved []uint64 `protobuf:"fixed64,4,rep,name=steamid_friends_removed,json=steamidFriendsRemoved" json:"steamid_friends_removed,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral  struct{} `json:"-"` | ||||
| 	XXX_unrecognized      []byte   `json:"-"` | ||||
| 	XXX_sizecache         int32    `json:"-"` | ||||
| @@ -2063,6 +2055,8 @@ var xxx_messageInfo_CMsgClientGetEmoticonList proto.InternalMessageInfo | ||||
|  | ||||
| type CMsgClientEmoticonList struct { | ||||
| 	Emoticons            []*CMsgClientEmoticonList_Emoticon `protobuf:"bytes,1,rep,name=emoticons" json:"emoticons,omitempty"` | ||||
| 	Stickers             []*CMsgClientEmoticonList_Sticker  `protobuf:"bytes,2,rep,name=stickers" json:"stickers,omitempty"` | ||||
| 	Effects              []*CMsgClientEmoticonList_Effect   `protobuf:"bytes,3,rep,name=effects" json:"effects,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{}                           `json:"-"` | ||||
| 	XXX_unrecognized     []byte                             `json:"-"` | ||||
| 	XXX_sizecache        int32                              `json:"-"` | ||||
| @@ -2100,12 +2094,26 @@ func (m *CMsgClientEmoticonList) GetEmoticons() []*CMsgClientEmoticonList_Emotic | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientEmoticonList) GetStickers() []*CMsgClientEmoticonList_Sticker { | ||||
| 	if m != nil { | ||||
| 		return m.Stickers | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientEmoticonList) GetEffects() []*CMsgClientEmoticonList_Effect { | ||||
| 	if m != nil { | ||||
| 		return m.Effects | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type CMsgClientEmoticonList_Emoticon struct { | ||||
| 	Name                 *string  `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` | ||||
| 	Count                *int32   `protobuf:"varint,2,opt,name=count" json:"count,omitempty"` | ||||
| 	TimeLastUsed         *uint32  `protobuf:"varint,3,opt,name=time_last_used" json:"time_last_used,omitempty"` | ||||
| 	UseCount             *uint32  `protobuf:"varint,4,opt,name=use_count" json:"use_count,omitempty"` | ||||
| 	TimeReceived         *uint32  `protobuf:"varint,5,opt,name=time_received" json:"time_received,omitempty"` | ||||
| 	TimeLastUsed         *uint32  `protobuf:"varint,3,opt,name=time_last_used,json=timeLastUsed" json:"time_last_used,omitempty"` | ||||
| 	UseCount             *uint32  `protobuf:"varint,4,opt,name=use_count,json=useCount" json:"use_count,omitempty"` | ||||
| 	TimeReceived         *uint32  `protobuf:"varint,5,opt,name=time_received,json=timeReceived" json:"time_received,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| @@ -2171,6 +2179,140 @@ func (m *CMsgClientEmoticonList_Emoticon) GetTimeReceived() uint32 { | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| type CMsgClientEmoticonList_Sticker struct { | ||||
| 	Name                 *string  `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` | ||||
| 	Count                *int32   `protobuf:"varint,2,opt,name=count" json:"count,omitempty"` | ||||
| 	TimeReceived         *uint32  `protobuf:"varint,3,opt,name=time_received,json=timeReceived" json:"time_received,omitempty"` | ||||
| 	Appid                *uint32  `protobuf:"varint,4,opt,name=appid" json:"appid,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientEmoticonList_Sticker) Reset()         { *m = CMsgClientEmoticonList_Sticker{} } | ||||
| func (m *CMsgClientEmoticonList_Sticker) String() string { return proto.CompactTextString(m) } | ||||
| func (*CMsgClientEmoticonList_Sticker) ProtoMessage()    {} | ||||
| func (*CMsgClientEmoticonList_Sticker) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_4f7c18b08a29999e, []int{28, 1} | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientEmoticonList_Sticker) XXX_Unmarshal(b []byte) error { | ||||
| 	return xxx_messageInfo_CMsgClientEmoticonList_Sticker.Unmarshal(m, b) | ||||
| } | ||||
| func (m *CMsgClientEmoticonList_Sticker) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	return xxx_messageInfo_CMsgClientEmoticonList_Sticker.Marshal(b, m, deterministic) | ||||
| } | ||||
| func (m *CMsgClientEmoticonList_Sticker) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_CMsgClientEmoticonList_Sticker.Merge(m, src) | ||||
| } | ||||
| func (m *CMsgClientEmoticonList_Sticker) XXX_Size() int { | ||||
| 	return xxx_messageInfo_CMsgClientEmoticonList_Sticker.Size(m) | ||||
| } | ||||
| func (m *CMsgClientEmoticonList_Sticker) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_CMsgClientEmoticonList_Sticker.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_CMsgClientEmoticonList_Sticker proto.InternalMessageInfo | ||||
|  | ||||
| func (m *CMsgClientEmoticonList_Sticker) GetName() string { | ||||
| 	if m != nil && m.Name != nil { | ||||
| 		return *m.Name | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientEmoticonList_Sticker) GetCount() int32 { | ||||
| 	if m != nil && m.Count != nil { | ||||
| 		return *m.Count | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientEmoticonList_Sticker) GetTimeReceived() uint32 { | ||||
| 	if m != nil && m.TimeReceived != nil { | ||||
| 		return *m.TimeReceived | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientEmoticonList_Sticker) GetAppid() uint32 { | ||||
| 	if m != nil && m.Appid != nil { | ||||
| 		return *m.Appid | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| type CMsgClientEmoticonList_Effect struct { | ||||
| 	Name                 *string  `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` | ||||
| 	Count                *int32   `protobuf:"varint,2,opt,name=count" json:"count,omitempty"` | ||||
| 	TimeReceived         *uint32  `protobuf:"varint,3,opt,name=time_received,json=timeReceived" json:"time_received,omitempty"` | ||||
| 	InfiniteUse          *bool    `protobuf:"varint,4,opt,name=infinite_use,json=infiniteUse" json:"infinite_use,omitempty"` | ||||
| 	Appid                *uint32  `protobuf:"varint,5,opt,name=appid" json:"appid,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientEmoticonList_Effect) Reset()         { *m = CMsgClientEmoticonList_Effect{} } | ||||
| func (m *CMsgClientEmoticonList_Effect) String() string { return proto.CompactTextString(m) } | ||||
| func (*CMsgClientEmoticonList_Effect) ProtoMessage()    {} | ||||
| func (*CMsgClientEmoticonList_Effect) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_4f7c18b08a29999e, []int{28, 2} | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientEmoticonList_Effect) XXX_Unmarshal(b []byte) error { | ||||
| 	return xxx_messageInfo_CMsgClientEmoticonList_Effect.Unmarshal(m, b) | ||||
| } | ||||
| func (m *CMsgClientEmoticonList_Effect) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	return xxx_messageInfo_CMsgClientEmoticonList_Effect.Marshal(b, m, deterministic) | ||||
| } | ||||
| func (m *CMsgClientEmoticonList_Effect) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_CMsgClientEmoticonList_Effect.Merge(m, src) | ||||
| } | ||||
| func (m *CMsgClientEmoticonList_Effect) XXX_Size() int { | ||||
| 	return xxx_messageInfo_CMsgClientEmoticonList_Effect.Size(m) | ||||
| } | ||||
| func (m *CMsgClientEmoticonList_Effect) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_CMsgClientEmoticonList_Effect.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_CMsgClientEmoticonList_Effect proto.InternalMessageInfo | ||||
|  | ||||
| func (m *CMsgClientEmoticonList_Effect) GetName() string { | ||||
| 	if m != nil && m.Name != nil { | ||||
| 		return *m.Name | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientEmoticonList_Effect) GetCount() int32 { | ||||
| 	if m != nil && m.Count != nil { | ||||
| 		return *m.Count | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientEmoticonList_Effect) GetTimeReceived() uint32 { | ||||
| 	if m != nil && m.TimeReceived != nil { | ||||
| 		return *m.TimeReceived | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientEmoticonList_Effect) GetInfiniteUse() bool { | ||||
| 	if m != nil && m.InfiniteUse != nil { | ||||
| 		return *m.InfiniteUse | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientEmoticonList_Effect) GetAppid() uint32 { | ||||
| 	if m != nil && m.Appid != nil { | ||||
| 		return *m.Appid | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	proto.RegisterType((*CMsgClientFriendMsg)(nil), "CMsgClientFriendMsg") | ||||
| 	proto.RegisterType((*CMsgClientFriendMsgIncoming)(nil), "CMsgClientFriendMsgIncoming") | ||||
| @@ -2209,6 +2351,8 @@ func init() { | ||||
| 	proto.RegisterType((*CMsgClientGetEmoticonList)(nil), "CMsgClientGetEmoticonList") | ||||
| 	proto.RegisterType((*CMsgClientEmoticonList)(nil), "CMsgClientEmoticonList") | ||||
| 	proto.RegisterType((*CMsgClientEmoticonList_Emoticon)(nil), "CMsgClientEmoticonList.Emoticon") | ||||
| 	proto.RegisterType((*CMsgClientEmoticonList_Sticker)(nil), "CMsgClientEmoticonList.Sticker") | ||||
| 	proto.RegisterType((*CMsgClientEmoticonList_Effect)(nil), "CMsgClientEmoticonList.Effect") | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| @@ -2216,106 +2360,141 @@ func init() { | ||||
| } | ||||
|  | ||||
| var fileDescriptor_4f7c18b08a29999e = []byte{ | ||||
| 	// 1607 bytes of a gzipped FileDescriptorProto | ||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x57, 0x4b, 0x73, 0x1b, 0xc7, | ||||
| 	0x11, 0xce, 0x8a, 0x24, 0x1e, 0x0d, 0x82, 0xa4, 0x96, 0x0f, 0xad, 0x40, 0x3d, 0x90, 0xb5, 0xab, | ||||
| 	0x8c, 0x4a, 0x25, 0x70, 0x8a, 0x2a, 0xd9, 0x8e, 0x2a, 0x0f, 0xd9, 0x54, 0x2c, 0x2a, 0x32, 0x1d, | ||||
| 	0x95, 0x94, 0xf2, 0x25, 0x87, 0xa9, 0xc1, 0x6e, 0x13, 0x98, 0xd2, 0xee, 0x2c, 0x3c, 0x33, 0x4b, | ||||
| 	0x07, 0xb7, 0x54, 0x8e, 0xf9, 0x0f, 0xf9, 0x1f, 0xa9, 0xdc, 0xf3, 0x27, 0x72, 0xc9, 0x3d, 0x97, | ||||
| 	0xfc, 0x82, 0x54, 0xa5, 0xa6, 0x67, 0x16, 0x5c, 0x10, 0x00, 0x69, 0xdf, 0x80, 0x9e, 0xe9, 0xaf, | ||||
| 	0xbf, 0xee, 0xe9, 0xd7, 0xc2, 0x40, 0x1b, 0xe4, 0x79, 0x8e, 0x5a, 0xf3, 0x31, 0x6a, 0x96, 0x64, | ||||
| 	0x02, 0xa5, 0xd1, 0xa8, 0x2e, 0x51, 0xb1, 0x0b, 0x25, 0x50, 0xa6, 0x7a, 0x38, 0x55, 0x85, 0x29, | ||||
| 	0x7a, 0xd1, 0xe2, 0xcd, 0x11, 0xd7, 0xe8, 0x4e, 0xe2, 0xbf, 0x06, 0xb0, 0x7f, 0x7a, 0xae, 0xc7, | ||||
| 	0xa7, 0xa4, 0xfc, 0x25, 0x69, 0x9d, 0xeb, 0x71, 0xb8, 0x0b, 0x4d, 0xd2, 0x11, 0x69, 0x14, 0xf4, | ||||
| 	0x83, 0x41, 0x23, 0xbc, 0x07, 0xbb, 0xc9, 0x84, 0x1b, 0x86, 0xd2, 0xa8, 0x19, 0x33, 0xb3, 0x29, | ||||
| 	0x46, 0x77, 0xfa, 0xc1, 0x60, 0xcb, 0xde, 0xf4, 0xc0, 0xd1, 0x46, 0x3f, 0x18, 0x6c, 0x87, 0x7d, | ||||
| 	0x88, 0x94, 0x11, 0x39, 0x3e, 0x39, 0x61, 0x9e, 0x8c, 0xfd, 0xa7, 0x0d, 0xcf, 0xa7, 0xd1, 0x66, | ||||
| 	0x3f, 0x18, 0x34, 0xc3, 0x23, 0xd8, 0xc1, 0x64, 0x52, 0x30, 0x53, 0x30, 0x8d, 0x32, 0x45, 0x15, | ||||
| 	0x6d, 0xf5, 0x83, 0x41, 0x2b, 0xfe, 0x5b, 0x00, 0xc7, 0x2b, 0xc8, 0xbc, 0x92, 0x49, 0x91, 0x0b, | ||||
| 	0x39, 0x0e, 0x0f, 0x60, 0xdb, 0x93, 0x62, 0x17, 0xaa, 0xc8, 0x6f, 0x63, 0xf6, 0x00, 0x0e, 0xec, | ||||
| 	0x35, 0x96, 0x89, 0x5c, 0x18, 0x4c, 0x19, 0x4f, 0x92, 0xa2, 0x94, 0x86, 0x68, 0xb6, 0xea, 0xbc, | ||||
| 	0x37, 0x6f, 0xe5, 0x6d, 0xf9, 0x35, 0xe3, 0xb7, 0xf5, 0x58, 0x7d, 0x9e, 0xa6, 0x8e, 0xa1, 0x75, | ||||
| 	0xa7, 0xa2, 0x65, 0x0a, 0xc6, 0xd3, 0x2a, 0x64, 0x1f, 0xc0, 0xb1, 0x37, 0x29, 0x79, 0x8e, 0xac, | ||||
| 	0x50, 0x0c, 0x73, 0x2e, 0xb2, 0xea, 0x92, 0x25, 0xd9, 0x8e, 0xb1, 0xee, 0xf2, 0x1c, 0xf3, 0x2d, | ||||
| 	0xea, 0x69, 0x21, 0x35, 0x86, 0x21, 0x34, 0x51, 0xa1, 0x2e, 0x33, 0x43, 0xa0, 0x5b, 0xcf, 0x82, | ||||
| 	0x93, 0xb9, 0x3d, 0x26, 0x52, 0x0b, 0x84, 0x0e, 0xaa, 0x11, 0xf6, 0x20, 0x9c, 0xa2, 0xd2, 0x85, | ||||
| 	0xe4, 0x8c, 0x0c, 0xba, 0xb3, 0x0d, 0x32, 0xf3, 0x13, 0x38, 0xba, 0x32, 0xf3, 0x16, 0xf3, 0xe2, | ||||
| 	0x12, 0x3d, 0xfb, 0x3d, 0x68, 0xb9, 0x64, 0xa9, 0x9e, 0x3a, 0xfe, 0x04, 0x0e, 0xae, 0xee, 0x9e, | ||||
| 	0x89, 0x74, 0xed, 0xcd, 0x70, 0x1b, 0x36, 0x27, 0x22, 0x75, 0xf1, 0x6e, 0xc5, 0xff, 0x09, 0xe0, | ||||
| 	0xf0, 0xfa, 0xf3, 0xe9, 0xaf, 0x84, 0x36, 0xf6, 0xe1, 0x46, 0x42, 0x26, 0x0a, 0x73, 0x94, 0x86, | ||||
| 	0x67, 0xa4, 0xdd, 0x0a, 0x87, 0xd0, 0xf4, 0x69, 0x1a, 0xdd, 0xe9, 0x6f, 0x0c, 0x3a, 0x27, 0x0f, | ||||
| 	0x87, 0x2b, 0xd5, 0x87, 0xde, 0x7e, 0x04, 0x7b, 0x39, 0xff, 0x93, 0x4f, 0x6d, 0x76, 0xf5, 0x96, | ||||
| 	0xdd, 0xf0, 0x18, 0xf6, 0x79, 0x62, 0xc4, 0x25, 0x2e, 0x1e, 0x6e, 0xd2, 0xe1, 0x7d, 0xb8, 0xeb, | ||||
| 	0xcd, 0xb8, 0x4c, 0x60, 0x13, 0x61, 0x5c, 0xc2, 0xf5, 0x7e, 0x01, 0x0d, 0x8f, 0x1d, 0x02, 0x94, | ||||
| 	0xd9, 0x35, 0xef, 0x8e, 0x61, 0x1f, 0x9d, 0x48, 0x61, 0xc6, 0x8d, 0x28, 0xa4, 0x9e, 0x88, 0x29, | ||||
| 	0x39, 0xdb, 0x8d, 0xff, 0x79, 0x67, 0x39, 0x57, 0xf5, 0x4b, 0x55, 0x94, 0x53, 0xe7, 0xf2, 0x1e, | ||||
| 	0xb4, 0x46, 0xca, 0xc6, 0x79, 0xee, 0xee, 0xf5, 0x20, 0x50, 0xd0, 0xc2, 0x5f, 0xc3, 0xb6, 0xb3, | ||||
| 	0xe1, 0x74, 0xa3, 0x0d, 0x8a, 0xc4, 0x60, 0x78, 0x03, 0xb6, 0x8f, 0x07, 0x09, 0xc2, 0x33, 0xe8, | ||||
| 	0xe4, 0x98, 0x8f, 0x50, 0x59, 0x6e, 0x3a, 0xda, 0x24, 0xf5, 0x27, 0xdf, 0x57, 0x5d, 0x9f, 0xcf, | ||||
| 	0x75, 0x7b, 0x4f, 0xa1, 0x53, 0x07, 0xde, 0x83, 0x96, 0xa4, 0x5f, 0xaf, 0x5e, 0xb8, 0xd4, 0x73, | ||||
| 	0xe5, 0xa7, 0x48, 0xf6, 0x35, 0xcf, 0xdd, 0xab, 0xb7, 0x7b, 0xbf, 0x82, 0xa3, 0xd5, 0x80, 0xe1, | ||||
| 	0x5d, 0x68, 0x97, 0xd9, 0x3b, 0x9b, 0xa9, 0x1e, 0xa2, 0xb1, 0x00, 0x4a, 0x45, 0x1a, 0xff, 0x23, | ||||
| 	0x80, 0x07, 0x57, 0x64, 0xdf, 0x64, 0x7c, 0x86, 0xea, 0x6b, 0x91, 0xbc, 0xb7, 0x19, 0x4c, 0x81, | ||||
| 	0xdc, 0x85, 0xe6, 0x62, 0x1c, 0xf7, 0xa1, 0xb3, 0x1c, 0xc6, 0xdf, 0x40, 0x5b, 0x7a, 0xad, 0x2a, | ||||
| 	0x86, 0x3f, 0x1d, 0xde, 0x84, 0x3b, 0x5c, 0x14, 0xf5, 0x9e, 0xc0, 0xce, 0xa2, 0x64, 0xb9, 0x05, | ||||
| 	0x5a, 0xf2, 0xfe, 0xd0, 0x57, 0xd5, 0xf3, 0x7a, 0x0e, 0xbc, 0x43, 0xf3, 0x43, 0x10, 0x5c, 0xf9, | ||||
| 	0x7f, 0x02, 0x1f, 0xdc, 0x80, 0x30, 0x6f, 0x03, 0xbb, 0x8b, 0x6d, 0xa0, 0x1b, 0xff, 0xbe, 0x6e, | ||||
| 	0xf9, 0x2d, 0x7e, 0x5b, 0xa2, 0xf6, 0x2f, 0xfd, 0x82, 0x1b, 0x1e, 0x3e, 0x86, 0x7b, 0x55, 0x2b, | ||||
| 	0xd0, 0x86, 0x1b, 0x64, 0xca, 0x5d, 0x41, 0xc7, 0xa4, 0x6b, 0x01, 0xeb, 0xb5, 0xd7, 0x88, 0xff, | ||||
| 	0x1b, 0xd4, 0x3b, 0xc4, 0xe9, 0x84, 0xcb, 0x31, 0xbe, 0x33, 0xdc, 0x94, 0x3a, 0x3c, 0x84, 0xee, | ||||
| 	0x02, 0x98, 0x87, 0xd8, 0x87, 0xce, 0x94, 0xd8, 0xb2, 0x2b, 0x7f, 0xc2, 0x47, 0x70, 0x24, 0x34, | ||||
| 	0xe3, 0xa5, 0x29, 0xd8, 0x18, 0x25, 0x2a, 0x6e, 0x1b, 0xef, 0x3c, 0x62, 0x2d, 0x8b, 0x35, 0x11, | ||||
| 	0xe3, 0x09, 0x9b, 0x2a, 0x51, 0x28, 0x61, 0x66, 0x54, 0xa3, 0x2d, 0x5b, 0x6a, 0x73, 0x13, 0x68, | ||||
| 	0xd8, 0x68, 0xc6, 0x4a, 0x5d, 0x8d, 0x85, 0xf0, 0x51, 0xed, 0x90, 0x9c, 0xb9, 0xc8, 0xf8, 0x58, | ||||
| 	0x47, 0x0d, 0xcb, 0xe2, 0x59, 0xf0, 0xf3, 0xf0, 0x21, 0x1c, 0x4a, 0xc4, 0x94, 0x55, 0x97, 0x94, | ||||
| 	0x8f, 0x5a, 0xd4, 0x24, 0xf5, 0x23, 0xd8, 0x11, 0xd5, 0x74, 0x64, 0x22, 0xcd, 0x30, 0x6a, 0x51, | ||||
| 	0xbb, 0x7a, 0x0e, 0xf7, 0xad, 0xc3, 0x6f, 0x9c, 0x96, 0xf3, 0x78, 0x1e, 0xf0, 0x1d, 0x68, 0xd4, | ||||
| 	0xe3, 0xbd, 0xd2, 0xd9, 0xf8, 0xdf, 0xcd, 0x7a, 0xcc, 0x3c, 0x90, 0x0d, 0x1a, 0xba, 0x5a, 0xb1, | ||||
| 	0xd1, 0xf3, 0x64, 0x1d, 0xca, 0xc7, 0xd7, 0x3b, 0xde, 0xa3, 0xe1, 0x6a, 0x7d, 0x5f, 0xa3, 0xbd, | ||||
| 	0xff, 0x35, 0xe6, 0x1d, 0x6a, 0xb9, 0xfb, 0x2e, 0xbd, 0x0b, 0x75, 0x26, 0x3b, 0x06, 0xc6, 0xb6, | ||||
| 	0xfd, 0x13, 0xdf, 0x94, 0xf1, 0xe9, 0x94, 0x89, 0xd4, 0x37, 0xca, 0x23, 0xd8, 0xa1, 0x33, 0x3f, | ||||
| 	0xe0, 0xc4, 0xd4, 0xf7, 0xc8, 0x08, 0xf6, 0xea, 0xf2, 0x69, 0xa1, 0x5c, 0x8b, 0xec, 0x2e, 0xbc, | ||||
| 	0xcc, 0xf5, 0xe0, 0xdb, 0x91, 0x59, 0xc8, 0x4c, 0x48, 0xab, 0xa8, 0xb5, 0x28, 0x24, 0x13, 0x52, | ||||
| 	0x1b, 0x2e, 0x13, 0xd4, 0x14, 0xfc, 0xae, 0x7d, 0x9b, 0x69, 0x39, 0xca, 0x84, 0x9e, 0x60, 0x3a, | ||||
| 	0x3f, 0xb4, 0x7c, 0x5a, 0x4b, 0xe8, 0xb5, 0x77, 0x87, 0xaa, 0xd0, 0xeb, 0x31, 0xdf, 0xa5, 0x04, | ||||
| 	0x0b, 0x01, 0xbe, 0x2d, 0x51, 0xcd, 0x1c, 0xc7, 0x83, 0xca, 0xab, 0x6a, 0x00, 0xeb, 0xa2, 0x54, | ||||
| 	0x09, 0x46, 0xf7, 0x29, 0x40, 0xfb, 0xd0, 0xe1, 0x97, 0xdc, 0x70, 0xc5, 0x26, 0x5c, 0x4f, 0xa2, | ||||
| 	0xc7, 0x34, 0xe6, 0xf7, 0xa1, 0x93, 0x71, 0x6d, 0x58, 0x56, 0x8c, 0x8b, 0x8b, 0x8b, 0xe8, 0x67, | ||||
| 	0x84, 0x10, 0x02, 0xcc, 0x85, 0x32, 0x1a, 0x56, 0x31, 0x21, 0x99, 0x46, 0x94, 0xcc, 0xb9, 0x19, | ||||
| 	0x7d, 0x4c, 0x27, 0x77, 0xa1, 0x9d, 0x64, 0x5c, 0x32, 0xc5, 0xe5, 0xfb, 0xe8, 0xa4, 0x12, 0x51, | ||||
| 	0x00, 0x89, 0xe9, 0xa7, 0xc4, 0x74, 0x07, 0x1a, 0x56, 0x24, 0xd2, 0xe8, 0x33, 0x62, 0x53, 0xc5, | ||||
| 	0x3e, 0xe5, 0x86, 0xb3, 0x51, 0x56, 0x8c, 0xa2, 0x5f, 0x12, 0xa1, 0x67, 0x1e, 0xcd, 0xca, 0xa3, | ||||
| 	0xe7, 0xfd, 0x60, 0xd0, 0x39, 0xf9, 0xe8, 0xe6, 0xb4, 0x18, 0x9e, 0x66, 0x5c, 0x52, 0x9d, 0xef, | ||||
| 	0x41, 0x8b, 0x74, 0x0d, 0x1f, 0x47, 0x9f, 0x93, 0xd5, 0xcf, 0xa0, 0xab, 0x44, 0x62, 0x0b, 0x0c, | ||||
| 	0x35, 0xca, 0x04, 0xa3, 0x97, 0x94, 0x68, 0x3f, 0xbe, 0x05, 0xf1, 0xf5, 0x37, 0x34, 0x9f, 0x54, | ||||
| 	0xc1, 0xd3, 0xc4, 0x3a, 0x2d, 0xd2, 0xe8, 0xac, 0x4a, 0x32, 0x62, 0x9d, 0x15, 0xa3, 0xd1, 0xcc, | ||||
| 	0x8a, 0x5f, 0x91, 0xf8, 0x43, 0x78, 0xf0, 0x1d, 0x37, 0xc9, 0x44, 0xc8, 0x31, 0xbb, 0xd2, 0xf2, | ||||
| 	0xeb, 0x8e, 0x48, 0xa3, 0xdf, 0x55, 0xf9, 0xb1, 0xea, 0xd6, 0x74, 0x2a, 0xd2, 0xe8, 0x35, 0xdd, | ||||
| 	0x88, 0xa1, 0xb7, 0xe2, 0xc6, 0xa5, 0xc0, 0xef, 0x50, 0xe9, 0xe8, 0xab, 0x1b, 0x50, 0x8c, 0x30, | ||||
| 	0x19, 0x46, 0xe7, 0x34, 0x83, 0x9e, 0x42, 0x6b, 0x1e, 0x92, 0x10, 0xa0, 0x18, 0x8f, 0xab, 0xb4, | ||||
| 	0x77, 0x75, 0x77, 0x08, 0x5d, 0x5a, 0x11, 0xc7, 0x76, 0xf4, 0x58, 0xb1, 0xad, 0x94, 0xcd, 0x5e, | ||||
| 	0x1f, 0xee, 0xbc, 0xfe, 0x26, 0xec, 0xc0, 0xc6, 0x7b, 0x9c, 0xd1, 0xcd, 0x76, 0xd8, 0x85, 0xad, | ||||
| 	0x4b, 0x9e, 0x95, 0x55, 0x85, 0x3f, 0x5d, 0x1e, 0xf2, 0x6f, 0x54, 0x71, 0x21, 0x32, 0x7c, 0x25, | ||||
| 	0x2f, 0x8a, 0x7a, 0xe2, 0xb9, 0xda, 0xf4, 0x1b, 0xd4, 0xbf, 0x82, 0x7a, 0x5b, 0x5f, 0xd2, 0xfb, | ||||
| 	0x5e, 0xdb, 0xdd, 0x15, 0xa6, 0xdb, 0xee, 0x0e, 0x60, 0xdb, 0xee, 0xa3, 0x2c, 0x51, 0x68, 0x9b, | ||||
| 	0xaa, 0x2f, 0xe8, 0xbb, 0xd0, 0x56, 0xc8, 0x33, 0x97, 0x77, 0x9b, 0xe4, 0x82, 0xcd, 0x4e, 0x61, | ||||
| 	0x66, 0x4e, 0xb4, 0x55, 0x15, 0x8d, 0x2b, 0x5e, 0x92, 0x35, 0x48, 0x76, 0x00, 0xdb, 0xf4, 0x58, | ||||
| 	0xca, 0xdf, 0x6c, 0x92, 0x74, 0x0f, 0x5a, 0x13, 0xe4, 0x29, 0x25, 0x7b, 0x8b, 0x24, 0x76, 0x88, | ||||
| 	0x95, 0x79, 0xce, 0xd5, 0x2c, 0x6a, 0x53, 0x4c, 0xfe, 0x58, 0x1f, 0xd8, 0xa7, 0xc4, 0xa6, 0xbe, | ||||
| 	0x63, 0x2c, 0x4f, 0x3d, 0x5b, 0x1b, 0xf6, 0xa4, 0x36, 0x26, 0xee, 0xc1, 0xee, 0xa2, 0x93, 0x6e, | ||||
| 	0x68, 0x37, 0xe2, 0x33, 0xf8, 0xf0, 0x26, 0xf0, 0xb5, 0x03, 0xd1, 0x0a, 0xc8, 0x88, 0x7f, 0xdc, | ||||
| 	0xad, 0xf8, 0x79, 0x9d, 0xe6, 0x0b, 0xcc, 0xf0, 0x36, 0x9a, 0x4b, 0x08, 0x9f, 0xd6, 0xb9, 0x2c, | ||||
| 	0x23, 0xac, 0x1f, 0xce, 0x7f, 0x59, 0xd8, 0x69, 0xce, 0xb9, 0xe4, 0xe3, 0x25, 0xdb, 0x95, 0x29, | ||||
| 	0xb7, 0x5a, 0xad, 0x08, 0xd1, 0x43, 0x38, 0xbc, 0x16, 0xa2, 0xf9, 0x42, 0xbf, 0x31, 0x68, 0xd8, | ||||
| 	0x09, 0x7f, 0xfd, 0x98, 0xd6, 0x24, 0x4c, 0x69, 0x07, 0x6c, 0x2c, 0xb2, 0x5f, 0xe6, 0xb0, 0x9e, | ||||
| 	0xfd, 0x17, 0xd0, 0x5b, 0xf1, 0x45, 0xf2, 0x87, 0x62, 0x0d, 0xf5, 0x7d, 0xe8, 0x78, 0x22, 0xd4, | ||||
| 	0xba, 0x29, 0x59, 0xe3, 0xa7, 0x10, 0xaf, 0xc7, 0x58, 0x6f, 0xfa, 0x25, 0x3c, 0x5e, 0xfd, 0x95, | ||||
| 	0xf2, 0xa5, 0x2a, 0xf2, 0x1f, 0x62, 0xff, 0x19, 0x7c, 0x74, 0x0b, 0xd0, 0x7a, 0x12, 0xc7, 0x6e, | ||||
| 	0x2f, 0x70, 0xba, 0x2f, 0xd1, 0xfc, 0x36, 0x2f, 0x8c, 0x48, 0x0a, 0x69, 0xb7, 0xc6, 0xf8, 0xef, | ||||
| 	0x0b, 0x6b, 0x52, 0xfd, 0x28, 0x7c, 0x02, 0x6d, 0xf4, 0xff, 0xed, 0xbc, 0xb7, 0x5d, 0xb7, 0x3f, | ||||
| 	0x5c, 0x7d, 0x77, 0x58, 0xfd, 0xe9, 0x09, 0x68, 0x55, 0xbf, 0xed, 0xd7, 0x14, 0xbd, 0xff, 0xbc, | ||||
| 	0x13, 0xb9, 0xaf, 0x18, 0xf7, 0x31, 0x7b, 0x04, 0x3b, 0x54, 0xfe, 0x34, 0x92, 0x4a, 0x5d, 0x6f, | ||||
| 	0x00, 0xa5, 0xc6, 0x85, 0x0f, 0x9e, 0x43, 0xe8, 0xd2, 0x55, 0x85, 0x09, 0x0a, 0x9b, 0x10, 0x34, | ||||
| 	0xc9, 0xbf, 0xd8, 0x3a, 0x0b, 0xfe, 0x1c, 0xfc, 0xe8, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbe, | ||||
| 	0x80, 0x1e, 0x5f, 0x36, 0x10, 0x00, 0x00, | ||||
| 	// 2171 bytes of a gzipped FileDescriptorProto | ||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0xdd, 0x6e, 0x1b, 0xb9, | ||||
| 	0x15, 0xae, 0xe4, 0x3f, 0xf9, 0x48, 0x72, 0x36, 0x74, 0xe2, 0x4c, 0x94, 0x6c, 0xe2, 0x4c, 0xd2, | ||||
| 	0xc6, 0x68, 0xb3, 0x6a, 0xea, 0x14, 0xbb, 0xc1, 0x36, 0xd8, 0xc6, 0xb1, 0xe3, 0x44, 0x1b, 0x7b, | ||||
| 	0xd7, 0x18, 0x39, 0x41, 0xb1, 0x40, 0x31, 0xa0, 0x66, 0x28, 0x89, 0xf0, 0xfc, 0x68, 0x49, 0xca, | ||||
| 	0xbb, 0xba, 0x6a, 0x9f, 0xa0, 0xe8, 0x03, 0xf4, 0xa6, 0x17, 0xbd, 0xe8, 0x4b, 0xf4, 0xa2, 0x6f, | ||||
| 	0xd0, 0x9b, 0x3e, 0x46, 0x81, 0x02, 0x7d, 0x80, 0xe2, 0x90, 0x9c, 0xd1, 0x8c, 0x25, 0xff, 0xf4, | ||||
| 	0xe7, 0x6e, 0xf8, 0x9d, 0xff, 0x43, 0x9e, 0xc3, 0xc3, 0x81, 0x2d, 0xa9, 0x18, 0x8d, 0x63, 0x26, | ||||
| 	0x25, 0x1d, 0x30, 0xe9, 0x07, 0x11, 0x67, 0x89, 0x92, 0x4c, 0x9c, 0x32, 0xe1, 0xf7, 0x05, 0x67, | ||||
| 	0x49, 0x28, 0xdb, 0x23, 0x91, 0xaa, 0xb4, 0xe5, 0x94, 0x39, 0x7b, 0x54, 0x32, 0x43, 0x71, 0xff, | ||||
| 	0x56, 0x81, 0xf5, 0xdd, 0x43, 0x39, 0xd8, 0xd5, 0xc2, 0xfb, 0x5a, 0xea, 0x50, 0x0e, 0x88, 0x03, | ||||
| 	0x2b, 0x5a, 0x86, 0x87, 0x4e, 0x65, 0xb3, 0xb2, 0xb5, 0xec, 0x65, 0x4b, 0xf2, 0x23, 0xb8, 0x16, | ||||
| 	0x0c, 0xa9, 0xf2, 0x59, 0xa2, 0xc4, 0xc4, 0x57, 0x93, 0x11, 0x73, 0xaa, 0x9b, 0x95, 0xad, 0x25, | ||||
| 	0xaf, 0x89, 0xf0, 0x6b, 0x44, 0x8f, 0x27, 0x23, 0x86, 0x1a, 0xac, 0x41, 0x67, 0x61, 0xb3, 0xb2, | ||||
| 	0xd5, 0xf0, 0xb2, 0x25, 0x79, 0x0e, 0x8e, 0x50, 0x3c, 0x66, 0xcf, 0xb6, 0x7d, 0xeb, 0x2d, 0xae, | ||||
| 	0xa4, 0xa2, 0xf1, 0xc8, 0x59, 0xdc, 0xac, 0x6c, 0xad, 0x78, 0x1b, 0x96, 0xde, 0xd5, 0xe4, 0xe3, | ||||
| 	0x8c, 0x4a, 0x1e, 0xc1, 0x1a, 0x0b, 0x86, 0xa9, 0xaf, 0x52, 0x5f, 0xb2, 0x24, 0x64, 0xc2, 0x59, | ||||
| 	0xda, 0xac, 0x6c, 0xd5, 0xbc, 0x06, 0xa2, 0xc7, 0x69, 0x57, 0x63, 0xee, 0x3f, 0x2a, 0x70, 0x67, | ||||
| 	0x4e, 0x4c, 0x9d, 0x24, 0x48, 0x63, 0x9e, 0x0c, 0xc8, 0x03, 0x68, 0xd8, 0x60, 0xfc, 0xbe, 0x48, | ||||
| 	0x63, 0x1b, 0x60, 0xdd, 0x62, 0xfb, 0x22, 0x8d, 0xaf, 0x1c, 0xe4, 0x53, 0xb8, 0x81, 0x2a, 0xfc, | ||||
| 	0x88, 0xc7, 0x5c, 0xb1, 0xd0, 0xa7, 0x41, 0x90, 0x8e, 0x13, 0xa5, 0x23, 0xae, 0x79, 0x04, 0x69, | ||||
| 	0x07, 0x86, 0xb4, 0x63, 0x28, 0xc5, 0xb4, 0x2c, 0x5e, 0x3d, 0x2d, 0x4b, 0x17, 0xa5, 0xc5, 0x9d, | ||||
| 	0x14, 0xf7, 0x70, 0x27, 0x0c, 0x4d, 0xc8, 0x98, 0xad, 0x2c, 0x4e, 0x95, 0xfa, 0x34, 0xcc, 0xb6, | ||||
| 	0x32, 0x8b, 0xfe, 0x38, 0xdd, 0x09, 0x43, 0xf2, 0x02, 0xee, 0x58, 0xaf, 0x13, 0x1a, 0x33, 0x3f, | ||||
| 	0x15, 0x3e, 0x8b, 0x29, 0x8f, 0x32, 0x11, 0x0c, 0x7b, 0xd5, 0xbb, 0x55, 0x60, 0xf9, 0x5a, 0xbc, | ||||
| 	0x46, 0x06, 0x2d, 0xed, 0xfe, 0xae, 0x94, 0xeb, 0xdc, 0xb6, 0xc7, 0xe4, 0x28, 0x4d, 0x24, 0x23, | ||||
| 	0x77, 0x60, 0x85, 0x09, 0x26, 0xc7, 0x91, 0xd2, 0xc6, 0x97, 0x3e, 0xaf, 0x6c, 0x7b, 0x19, 0x92, | ||||
| 	0x3b, 0xe8, 0xf3, 0x10, 0x6d, 0x31, 0x63, 0x2d, 0x73, 0xb0, 0x13, 0xee, 0x20, 0x46, 0x9e, 0x00, | ||||
| 	0x19, 0x31, 0x21, 0xd3, 0x84, 0xfa, 0xda, 0x43, 0xc3, 0xb9, 0xa0, 0xfd, 0xfa, 0xc8, 0x52, 0xbe, | ||||
| 	0xa2, 0x31, 0xd3, 0xdc, 0xee, 0xcf, 0x61, 0x63, 0xea, 0x8f, 0xc7, 0xe2, 0xf4, 0x94, 0xd9, 0x74, | ||||
| 	0xb4, 0xa0, 0x66, 0xaa, 0x22, 0x3f, 0xd3, 0xf9, 0xda, 0xdd, 0x87, 0x1b, 0x53, 0xa9, 0xb7, 0x3c, | ||||
| 	0xbc, 0x82, 0x0c, 0x21, 0xb0, 0x38, 0xe4, 0xa1, 0x39, 0x18, 0x35, 0x4f, 0x7f, 0xbb, 0x7f, 0xaf, | ||||
| 	0xc2, 0xcd, 0xb3, 0x47, 0x4f, 0x1e, 0x70, 0xa9, 0x88, 0x0b, 0x8d, 0x1e, 0x4f, 0x02, 0xc1, 0x62, | ||||
| 	0x96, 0x28, 0x1a, 0x69, 0x6d, 0x35, 0xaf, 0x84, 0x91, 0xcf, 0x60, 0xc5, 0xd6, 0xad, 0x53, 0xdd, | ||||
| 	0x5c, 0xd8, 0xaa, 0x6f, 0x7f, 0xdc, 0x9e, 0xab, 0xac, 0x6d, 0x93, 0x9c, 0x71, 0x93, 0x2d, 0xf8, | ||||
| 	0x28, 0xa6, 0xdf, 0xdb, 0xa2, 0xf7, 0xa7, 0x47, 0xb0, 0xe9, 0xad, 0xc5, 0xf4, 0x7b, 0xc3, 0xbd, | ||||
| 	0xab, 0x8f, 0x5f, 0x1b, 0xd6, 0x69, 0xa0, 0xf8, 0x29, 0x2b, 0x33, 0x2f, 0x6a, 0xe6, 0xeb, 0x86, | ||||
| 	0x54, 0xe4, 0xff, 0x31, 0x5c, 0xb7, 0x46, 0xcc, 0x19, 0xf7, 0x87, 0x5c, 0xd9, 0xa2, 0xbb, 0xd6, | ||||
| 	0xcf, 0x3c, 0x8a, 0xb9, 0x7a, 0xcb, 0x55, 0xeb, 0x1b, 0x58, 0xb6, 0x69, 0xbb, 0x07, 0x30, 0x8e, | ||||
| 	0xce, 0x24, 0xae, 0x80, 0x90, 0xa7, 0xb0, 0xce, 0xcc, 0x42, 0xb0, 0x88, 0x2a, 0x9e, 0x26, 0x72, | ||||
| 	0xc8, 0x47, 0x3a, 0x93, 0x4d, 0x6f, 0x1e, 0xc9, 0xfd, 0xd3, 0xc2, 0x6c, 0x4d, 0xcb, 0x37, 0x22, | ||||
| 	0x1d, 0x8f, 0x4c, 0x7a, 0x5b, 0x50, 0xeb, 0x09, 0xdc, 0xed, 0x3c, 0xb5, 0xf9, 0x7a, 0x26, 0xf5, | ||||
| 	0xd5, 0x39, 0xa9, 0x3f, 0x80, 0x86, 0xb1, 0x6a, 0x74, 0x3a, 0x0b, 0x3a, 0xff, 0x5b, 0xed, 0x0b, | ||||
| 	0x6c, 0xda, 0x5d, 0xd0, 0x80, 0x57, 0x92, 0x26, 0xef, 0xa1, 0x1e, 0xb3, 0xb8, 0xc7, 0x04, 0xfa, | ||||
| 	0x2e, 0x9d, 0x45, 0xad, 0xec, 0xd9, 0x55, 0x95, 0xc9, 0xc3, 0x5c, 0xd6, 0x2b, 0xea, 0x69, 0x1d, | ||||
| 	0x42, 0xbd, 0xc0, 0x86, 0x31, 0x27, 0xfa, 0xab, 0xb3, 0x67, 0x8a, 0xcb, 0xcb, 0xd7, 0x18, 0xb3, | ||||
| 	0x54, 0x42, 0xaf, 0xb0, 0x36, 0x6c, 0x19, 0x97, 0xb0, 0x96, 0x07, 0x1b, 0xf3, 0xad, 0x92, 0xbb, | ||||
| 	0xb0, 0x3a, 0x8e, 0xba, 0xba, 0x08, 0xf7, 0xec, 0xf6, 0x4d, 0x81, 0x92, 0xdd, 0x6a, 0xd9, 0x2e, | ||||
| 	0xf6, 0xde, 0xbb, 0xd3, 0x30, 0x8f, 0x22, 0x3a, 0x61, 0xe2, 0x2b, 0x1e, 0x9c, 0x60, 0xe5, 0xea, | ||||
| 	0x8d, 0x72, 0x60, 0xa5, 0xbc, 0x4f, 0xd9, 0x92, 0x6c, 0x42, 0x7d, 0x76, 0x97, 0x8a, 0x10, 0xf9, | ||||
| 	0x12, 0x56, 0x13, 0xab, 0x2b, 0xdb, 0xa1, 0x27, 0xed, 0x8b, 0xac, 0xb5, 0xcb, 0x90, 0x37, 0x15, | ||||
| 	0x6f, 0xed, 0xc3, 0x5a, 0x99, 0x78, 0xc1, 0x95, 0x87, 0x01, 0x5b, 0x2e, 0xdb, 0x77, 0xf2, 0xb5, | ||||
| 	0xdb, 0x2d, 0x9e, 0xcb, 0x2e, 0x53, 0xff, 0x95, 0xd2, 0xea, 0x19, 0xa5, 0xbf, 0x84, 0x87, 0x17, | ||||
| 	0x28, 0xcd, 0x9b, 0xab, 0x53, 0x6e, 0xae, 0xcd, 0xbc, 0xb3, 0xba, 0x69, 0xd1, 0x2b, 0x8f, 0x7d, | ||||
| 	0x3b, 0x66, 0xd2, 0x9e, 0xb9, 0x3d, 0xaa, 0x28, 0xf9, 0x14, 0x6e, 0x65, 0x2d, 0x55, 0x2a, 0xaa, | ||||
| 	0x98, 0x2f, 0x0c, 0x0b, 0x0b, 0xad, 0xa2, 0x9b, 0x96, 0xdc, 0x45, 0xaa, 0x97, 0x11, 0xd1, 0x60, | ||||
| 	0xb1, 0x41, 0x2d, 0xe7, 0x1d, 0xc8, 0xfd, 0x57, 0xb5, 0xd8, 0x77, 0x77, 0x87, 0x34, 0x19, 0x30, | ||||
| 	0x14, 0x1e, 0x4b, 0xf2, 0x10, 0x9a, 0x25, 0x63, 0xd6, 0x44, 0xa3, 0x68, 0x82, 0xdc, 0x87, 0xfa, | ||||
| 	0x48, 0x07, 0xe9, 0x17, 0x12, 0x02, 0x06, 0xc2, 0xc3, 0x4a, 0x9e, 0xc1, 0x06, 0x97, 0x3e, 0x1d, | ||||
| 	0xab, 0xd4, 0x1f, 0xb0, 0x84, 0x09, 0x8a, 0xd7, 0x6d, 0xbe, 0x23, 0x35, 0x6f, 0x9d, 0xcb, 0x9d, | ||||
| 	0xb1, 0x4a, 0xdf, 0x64, 0x34, 0x2d, 0xf4, 0x10, 0x9a, 0x43, 0x3e, 0x18, 0xfa, 0x23, 0xc1, 0x53, | ||||
| 	0xc1, 0xd5, 0x44, 0xf7, 0xb9, 0x9a, 0xd7, 0x40, 0xf0, 0xc8, 0x62, 0xe4, 0x13, 0x58, 0xcf, 0xfd, | ||||
| 	0x63, 0xca, 0xef, 0x4d, 0xfc, 0xb1, 0xcc, 0x27, 0x8b, 0xec, 0x82, 0xe9, 0x32, 0xf5, 0x6a, 0xf2, | ||||
| 	0x5e, 0x32, 0x41, 0x7e, 0x56, 0x60, 0xd7, 0xb9, 0xeb, 0x47, 0x74, 0x20, 0x9d, 0x65, 0x0c, 0xea, | ||||
| 	0xf3, 0xca, 0x53, 0xef, 0x7a, 0x31, 0xae, 0x7d, 0xa4, 0x91, 0x6d, 0xb8, 0x99, 0x30, 0x16, 0xfa, | ||||
| 	0x99, 0x9c, 0xb0, 0x1b, 0xe8, 0xac, 0x18, 0xd7, 0x91, 0x78, 0x64, 0x68, 0xf9, 0xde, 0x3e, 0x82, | ||||
| 	0x35, 0x9e, 0xcd, 0x74, 0x3e, 0x0f, 0x23, 0xe6, 0xd4, 0x8c, 0xef, 0x5c, 0x9a, 0x1c, 0x77, 0xc2, | ||||
| 	0x88, 0xb9, 0xc7, 0x70, 0x1b, 0xb3, 0x6e, 0x85, 0x4d, 0xda, 0x73, 0x15, 0x1b, 0xb0, 0x5c, 0x3a, | ||||
| 	0x1d, 0x76, 0x75, 0x69, 0xae, 0xdd, 0x3f, 0xd6, 0x8b, 0x9b, 0x79, 0x54, 0xdc, 0x27, 0x3d, 0x3b, | ||||
| 	0xe1, 0xb6, 0xda, 0xb0, 0x8d, 0xe6, 0xba, 0xc1, 0x4c, 0xb4, 0xcf, 0xcf, 0xde, 0x62, 0xf7, 0xda, | ||||
| 	0xf3, 0x95, 0x9d, 0xbd, 0xc6, 0x5a, 0x7f, 0x86, 0xfc, 0x06, 0xb9, 0xe8, 0xe2, 0x9d, 0x39, 0x50, | ||||
| 	0xd5, 0x39, 0x07, 0xea, 0x27, 0x40, 0x06, 0x38, 0x2d, 0xe8, 0xb0, 0x42, 0x9f, 0x8e, 0x46, 0x3e, | ||||
| 	0x0f, 0xed, 0xa5, 0x78, 0x0d, 0x29, 0xba, 0xa6, 0xc2, 0x9d, 0xd1, 0xa8, 0xa3, 0x27, 0x25, 0xcd, | ||||
| 	0x6c, 0xe7, 0x2e, 0x3e, 0xb2, 0x17, 0x62, 0x03, 0x51, 0x33, 0x6d, 0x75, 0x46, 0x78, 0xcb, 0x16, | ||||
| 	0xb9, 0x46, 0xa9, 0x30, 0x57, 0x61, 0xd3, 0x5b, 0x9b, 0xf2, 0x1d, 0xa5, 0x42, 0xdf, 0xb2, 0xe7, | ||||
| 	0x9e, 0x91, 0x79, 0x07, 0xe4, 0x39, 0x38, 0x69, 0x12, 0xf1, 0x04, 0x75, 0x4b, 0xc9, 0xd3, 0xc4, | ||||
| 	0xe7, 0x89, 0x54, 0x34, 0x09, 0x98, 0xd4, 0x67, 0xa4, 0xe9, 0x6d, 0x18, 0x7a, 0xd7, 0x90, 0x3b, | ||||
| 	0x19, 0xf5, 0xbc, 0xc3, 0x0b, 0xe7, 0x1c, 0xde, 0x33, 0x5b, 0x7f, 0x6d, 0xa6, 0xcc, 0x3e, 0x06, | ||||
| 	0xf8, 0x76, 0xcc, 0xc4, 0xc4, 0x44, 0x77, 0x43, 0xdb, 0x5e, 0xd5, 0x88, 0x0e, 0xec, 0x87, 0xd3, | ||||
| 	0x91, 0x52, 0xa6, 0x63, 0x11, 0x30, 0xe7, 0xb6, 0xde, 0x9c, 0xa6, 0x45, 0xbb, 0x1a, 0x44, 0x33, | ||||
| 	0xf4, 0x94, 0x2a, 0x2a, 0xfc, 0x21, 0x95, 0x43, 0xe7, 0xbe, 0x1e, 0x74, 0xc1, 0x40, 0x6f, 0xa9, | ||||
| 	0x1c, 0x22, 0x43, 0x44, 0xa5, 0xf2, 0xa3, 0x74, 0x90, 0xf6, 0xfb, 0xce, 0x27, 0xda, 0x0e, 0x20, | ||||
| 	0x74, 0xa0, 0x11, 0xf4, 0x23, 0x67, 0x48, 0x9c, 0xb6, 0xf1, 0x23, 0xa3, 0x27, 0xb8, 0x15, 0x9a, | ||||
| 	0x2c, 0x19, 0x4b, 0x7c, 0x93, 0x1a, 0xe7, 0xa7, 0x66, 0x2b, 0x10, 0xef, 0x32, 0x96, 0x7c, 0xad, | ||||
| 	0x51, 0x72, 0x07, 0x56, 0x83, 0x88, 0x26, 0xbe, 0xa0, 0xc9, 0x89, 0xb3, 0xad, 0x59, 0x6a, 0x08, | ||||
| 	0x78, 0x34, 0x39, 0x41, 0xa2, 0xde, 0x51, 0x9d, 0x8c, 0xcf, 0x4c, 0x13, 0x46, 0x40, 0xa7, 0x62, | ||||
| 	0x03, 0x96, 0xf1, 0x9b, 0x87, 0xce, 0x73, 0x1d, 0xa3, 0x5d, 0xe5, 0x87, 0x25, 0xa4, 0x8a, 0xfa, | ||||
| 	0xbd, 0x28, 0xed, 0x39, 0x2f, 0x74, 0x7c, 0xfa, 0xb0, 0x60, 0x7b, 0x7d, 0x15, 0xa5, 0x3d, 0xb2, | ||||
| 	0x67, 0xed, 0x22, 0x97, 0xf3, 0x72, 0xb3, 0xb2, 0x55, 0xdf, 0x7e, 0x7c, 0x71, 0x1d, 0xb4, 0x77, | ||||
| 	0x23, 0x9a, 0xa0, 0xbc, 0x71, 0x50, 0x37, 0xea, 0xdb, 0xa0, 0xbf, 0x7d, 0x45, 0x07, 0xce, 0x8e, | ||||
| 	0xf6, 0x6f, 0x05, 0xd7, 0xc7, 0x74, 0x40, 0xf6, 0xa1, 0x29, 0x78, 0x80, 0xbd, 0x8d, 0x49, 0x96, | ||||
| 	0x04, 0xcc, 0x79, 0xa3, 0x8b, 0xed, 0xc1, 0x25, 0x46, 0xde, 0x7d, 0xf0, 0x1a, 0x28, 0x77, 0x64, | ||||
| 	0xc5, 0xb0, 0xa2, 0x7b, 0x22, 0xa5, 0x61, 0x80, 0xf9, 0xe4, 0xa1, 0xf3, 0xd6, 0xbc, 0x86, 0x72, | ||||
| 	0xac, 0x13, 0x12, 0x17, 0x9a, 0x3a, 0xe2, 0x28, 0xed, 0xf5, 0x26, 0xc8, 0xd3, 0x31, 0x3c, 0x08, | ||||
| 	0x1e, 0x20, 0xd6, 0x09, 0xc9, 0x4b, 0xb8, 0xfb, 0x1d, 0x55, 0xc1, 0x90, 0x27, 0x03, 0x7f, 0xaa, | ||||
| 	0xcf, 0x3e, 0x1b, 0x78, 0xe8, 0x7c, 0xa9, 0x53, 0xdf, 0xca, 0x78, 0x5e, 0x65, 0x2c, 0x3b, 0x19, | ||||
| 	0x07, 0x16, 0xc1, 0x3c, 0x0d, 0xa3, 0x11, 0x0f, 0x9d, 0x77, 0xa6, 0x08, 0x66, 0xa5, 0x91, 0x4a, | ||||
| 	0x5e, 0x40, 0x6b, 0x8e, 0xe4, 0x29, 0x67, 0xdf, 0x31, 0x21, 0x9d, 0x03, 0x2d, 0xeb, 0xcc, 0xc8, | ||||
| 	0x7e, 0x30, 0xf4, 0x73, 0xec, 0x2a, 0xae, 0x22, 0xe6, 0x1c, 0xea, 0x9c, 0xcf, 0xda, 0x3d, 0x46, | ||||
| 	0x6a, 0xeb, 0x00, 0x6a, 0xd9, 0x9e, 0x91, 0xbb, 0x00, 0xe9, 0x60, 0x90, 0xf5, 0x19, 0xd3, 0x16, | ||||
| 	0x6b, 0xe9, 0x60, 0x60, 0x1a, 0x8c, 0x0b, 0xfa, 0xe1, 0xe8, 0x0f, 0x70, 0x4c, 0x42, 0x06, 0x6c, | ||||
| 	0x59, 0x8b, 0x5e, 0x1d, 0x41, 0x33, 0x3a, 0x85, 0xad, 0x27, 0x50, 0x7d, 0xf7, 0x81, 0x7c, 0x04, | ||||
| 	0x0b, 0x27, 0x6c, 0xa2, 0x15, 0xac, 0x7a, 0xf8, 0x49, 0x6e, 0xc0, 0xd2, 0x29, 0x8d, 0xc6, 0x59, | ||||
| 	0xa3, 0x36, 0x0b, 0x77, 0x6f, 0x76, 0x1e, 0x3e, 0x12, 0x69, 0x9f, 0x47, 0xac, 0x93, 0xf4, 0xd3, | ||||
| 	0x62, 0xa1, 0x9a, 0xbe, 0x69, 0xbb, 0x68, 0x33, 0x7f, 0xe5, 0x22, 0xe8, 0xfe, 0xa5, 0x5a, 0x9c, | ||||
| 	0x34, 0x66, 0xd4, 0x5c, 0xed, 0x19, 0x37, 0x6b, 0xab, 0x3a, 0xc7, 0x16, 0x1e, 0x34, 0x7c, 0xbe, | ||||
| 	0xfa, 0x81, 0x60, 0x78, 0x41, 0xdb, 0x5e, 0x5c, 0x47, 0x6c, 0xd7, 0x40, 0x58, 0x8f, 0x82, 0xd1, | ||||
| 	0xc8, 0xd4, 0xe3, 0xa2, 0xa9, 0x47, 0x04, 0x74, 0x3d, 0x62, 0x25, 0x73, 0x35, 0x31, 0xc4, 0x25, | ||||
| 	0x43, 0x44, 0x20, 0xeb, 0x5b, 0xa6, 0xd3, 0x6a, 0xea, 0xb2, 0xa6, 0xae, 0x6a, 0x44, 0x93, 0x1f, | ||||
| 	0x40, 0x43, 0x1f, 0x33, 0x61, 0xc5, 0x57, 0x34, 0x43, 0xdd, 0x62, 0x9a, 0xa5, 0x05, 0xb5, 0x21, | ||||
| 	0xa3, 0xa1, 0x6e, 0x25, 0x35, 0xa3, 0x3d, 0x5b, 0xeb, 0x29, 0x6e, 0x1c, 0xc7, 0x54, 0x4c, 0x9c, | ||||
| 	0x55, 0x53, 0x85, 0x76, 0xe9, 0xfe, 0xa6, 0x38, 0xee, 0x9a, 0x30, 0x8a, 0xb3, 0xfd, 0x05, 0xf3, | ||||
| 	0xdf, 0x5d, 0x58, 0xd5, 0xa7, 0xa1, 0x70, 0x07, 0x4f, 0x01, 0xf2, 0x18, 0xae, 0x95, 0x73, 0x6a, | ||||
| 	0x06, 0xde, 0x65, 0x6f, 0xad, 0x94, 0x54, 0xe9, 0x7e, 0x03, 0x8f, 0x2e, 0x72, 0xe0, 0xf2, 0x59, | ||||
| 	0x11, 0x29, 0xda, 0xae, 0x3d, 0x95, 0x4b, 0x5e, 0xb6, 0x74, 0xbd, 0x62, 0x70, 0x7b, 0x2c, 0x62, | ||||
| 	0x57, 0x0e, 0xee, 0x7c, 0x9d, 0x2f, 0x8b, 0xfe, 0xce, 0xea, 0xbc, 0xc2, 0x6c, 0xfb, 0xd7, 0xd2, | ||||
| 	0x13, 0xe3, 0x90, 0x26, 0x74, 0x30, 0xe3, 0x56, 0x66, 0xbc, 0x52, 0x32, 0x7e, 0x49, 0xce, 0xb7, | ||||
| 	0xe1, 0xe6, 0x99, 0x9c, 0xe7, 0xff, 0x1a, 0x30, 0xf3, 0xeb, 0xe5, 0xcc, 0x9b, 0x9f, 0x13, 0x9f, | ||||
| 	0xc2, 0xad, 0xb3, 0x32, 0xfa, 0x3d, 0xc3, 0x42, 0xfd, 0xea, 0x5b, 0xf6, 0x6e, 0x96, 0xa5, 0xcc, | ||||
| 	0x1f, 0x89, 0x33, 0x69, 0x98, 0x8d, 0xe1, 0x0a, 0x69, 0xf8, 0x15, 0xb4, 0xe6, 0xfc, 0x78, 0x39, | ||||
| 	0x4e, 0x2f, 0xcb, 0xc1, 0x26, 0x64, 0x7f, 0xba, 0xf4, 0xa4, 0x50, 0x2d, 0xfd, 0xfc, 0x42, 0xc8, | ||||
| 	0xfd, 0x02, 0xdc, 0xf3, 0x35, 0x5f, 0xc1, 0xb3, 0x5f, 0xc3, 0xfd, 0xf9, 0xbf, 0x60, 0xf6, 0x45, | ||||
| 	0x1a, 0xff, 0xef, 0xee, 0xed, 0xc2, 0xe3, 0x4b, 0xd4, 0x5f, 0xc1, 0xc7, 0x3b, 0x66, 0x70, 0x36, | ||||
| 	0x4a, 0xde, 0x30, 0xf5, 0x3a, 0x4e, 0x15, 0x0f, 0xd2, 0x04, 0x5f, 0x8d, 0xee, 0x3f, 0x17, 0x8b, | ||||
| 	0xf3, 0x6f, 0x91, 0x44, 0xbe, 0x80, 0x55, 0x66, 0xd7, 0x38, 0xfc, 0xe2, 0x8d, 0xbb, 0xd9, 0x9e, | ||||
| 	0xcf, 0xdb, 0xce, 0x16, 0xde, 0x54, 0x84, 0xfc, 0x02, 0x6a, 0x52, 0xf1, 0xe0, 0x04, 0x2f, 0x26, | ||||
| 	0x33, 0x1d, 0xdf, 0x3f, 0x4f, 0xbc, 0x6b, 0xf8, 0xbc, 0x5c, 0x00, 0x27, 0x6b, 0xd6, 0xef, 0xb3, | ||||
| 	0x40, 0x65, 0xaf, 0xdf, 0x7b, 0xe7, 0x9a, 0xd6, 0x6c, 0x5e, 0xc6, 0xde, 0xfa, 0x43, 0x05, 0x6a, | ||||
| 	0x19, 0x03, 0x21, 0xb0, 0xa8, 0x0b, 0xc0, 0xdc, 0x31, 0xfa, 0x1b, 0x2f, 0x19, 0xf3, 0x27, 0xc8, | ||||
| 	0x94, 0xab, 0x59, 0xe0, 0xa8, 0xa3, 0x5b, 0xb6, 0x9e, 0xb5, 0xc6, 0x32, 0x6f, 0xda, 0xba, 0x91, | ||||
| 	0x1f, 0x50, 0xa9, 0xde, 0x4b, 0xd3, 0xb5, 0xc7, 0x92, 0x95, 0xfe, 0x24, 0xd5, 0xc6, 0x92, 0x99, | ||||
| 	0x1f, 0x48, 0x0f, 0xa1, 0xa9, 0x55, 0x08, 0x16, 0x30, 0x8e, 0x65, 0xb1, 0x34, 0xd5, 0xe0, 0x59, | ||||
| 	0xac, 0x95, 0xc0, 0x8a, 0x8d, 0xf6, 0x3f, 0x70, 0x6e, 0x46, 0xf3, 0xc2, 0xac, 0x66, 0x14, 0x35, | ||||
| 	0x13, 0x84, 0xf1, 0xcb, 0x2c, 0x5a, 0xbf, 0xaf, 0xc0, 0xb2, 0x49, 0xd1, 0xff, 0xdb, 0xde, 0x03, | ||||
| 	0x68, 0xf0, 0xa4, 0xcf, 0x13, 0xae, 0x18, 0x26, 0xcc, 0x3e, 0x38, 0xeb, 0x19, 0xf6, 0x5e, 0xb2, | ||||
| 	0xa9, 0x4b, 0x4b, 0x05, 0x97, 0x5e, 0x2d, 0xbd, 0xad, 0xfc, 0xb6, 0xf2, 0x83, 0x7f, 0x07, 0x00, | ||||
| 	0x00, 0xff, 0xff, 0xc5, 0x50, 0x67, 0x9b, 0xd4, 0x17, 0x00, 0x00, | ||||
| } | ||||
|   | ||||
							
								
								
									
										680
									
								
								vendor/github.com/Philipp15b/go-steam/protocol/protobuf/client_server_login.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										680
									
								
								vendor/github.com/Philipp15b/go-steam/protocol/protobuf/client_server_login.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -52,7 +52,7 @@ func (m *CMsgClientHeartBeat) XXX_DiscardUnknown() { | ||||
| var xxx_messageInfo_CMsgClientHeartBeat proto.InternalMessageInfo | ||||
|  | ||||
| type CMsgClientServerTimestampRequest struct { | ||||
| 	ClientRequestTimestamp *uint64  `protobuf:"varint,1,opt,name=client_request_timestamp" json:"client_request_timestamp,omitempty"` | ||||
| 	ClientRequestTimestamp *uint64  `protobuf:"varint,1,opt,name=client_request_timestamp,json=clientRequestTimestamp" json:"client_request_timestamp,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral   struct{} `json:"-"` | ||||
| 	XXX_unrecognized       []byte   `json:"-"` | ||||
| 	XXX_sizecache          int32    `json:"-"` | ||||
| @@ -91,8 +91,8 @@ func (m *CMsgClientServerTimestampRequest) GetClientRequestTimestamp() uint64 { | ||||
| } | ||||
|  | ||||
| type CMsgClientServerTimestampResponse struct { | ||||
| 	ClientRequestTimestamp *uint64  `protobuf:"varint,1,opt,name=client_request_timestamp" json:"client_request_timestamp,omitempty"` | ||||
| 	ServerTimestampMs      *uint64  `protobuf:"varint,2,opt,name=server_timestamp_ms" json:"server_timestamp_ms,omitempty"` | ||||
| 	ClientRequestTimestamp *uint64  `protobuf:"varint,1,opt,name=client_request_timestamp,json=clientRequestTimestamp" json:"client_request_timestamp,omitempty"` | ||||
| 	ServerTimestampMs      *uint64  `protobuf:"varint,2,opt,name=server_timestamp_ms,json=serverTimestampMs" json:"server_timestamp_ms,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral   struct{} `json:"-"` | ||||
| 	XXX_unrecognized       []byte   `json:"-"` | ||||
| 	XXX_sizecache          int32    `json:"-"` | ||||
| @@ -137,66 +137,141 @@ func (m *CMsgClientServerTimestampResponse) GetServerTimestampMs() uint64 { | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| type CMsgClientSecret struct { | ||||
| 	Version              *uint32  `protobuf:"varint,1,opt,name=version" json:"version,omitempty"` | ||||
| 	Appid                *uint32  `protobuf:"varint,2,opt,name=appid" json:"appid,omitempty"` | ||||
| 	Deviceid             *uint32  `protobuf:"varint,3,opt,name=deviceid" json:"deviceid,omitempty"` | ||||
| 	Nonce                *uint64  `protobuf:"fixed64,4,opt,name=nonce" json:"nonce,omitempty"` | ||||
| 	Hmac                 []byte   `protobuf:"bytes,5,opt,name=hmac" json:"hmac,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientSecret) Reset()         { *m = CMsgClientSecret{} } | ||||
| func (m *CMsgClientSecret) String() string { return proto.CompactTextString(m) } | ||||
| func (*CMsgClientSecret) ProtoMessage()    {} | ||||
| func (*CMsgClientSecret) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{3} | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientSecret) XXX_Unmarshal(b []byte) error { | ||||
| 	return xxx_messageInfo_CMsgClientSecret.Unmarshal(m, b) | ||||
| } | ||||
| func (m *CMsgClientSecret) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	return xxx_messageInfo_CMsgClientSecret.Marshal(b, m, deterministic) | ||||
| } | ||||
| func (m *CMsgClientSecret) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_CMsgClientSecret.Merge(m, src) | ||||
| } | ||||
| func (m *CMsgClientSecret) XXX_Size() int { | ||||
| 	return xxx_messageInfo_CMsgClientSecret.Size(m) | ||||
| } | ||||
| func (m *CMsgClientSecret) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_CMsgClientSecret.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_CMsgClientSecret proto.InternalMessageInfo | ||||
|  | ||||
| func (m *CMsgClientSecret) GetVersion() uint32 { | ||||
| 	if m != nil && m.Version != nil { | ||||
| 		return *m.Version | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientSecret) GetAppid() uint32 { | ||||
| 	if m != nil && m.Appid != nil { | ||||
| 		return *m.Appid | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientSecret) GetDeviceid() uint32 { | ||||
| 	if m != nil && m.Deviceid != nil { | ||||
| 		return *m.Deviceid | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientSecret) GetNonce() uint64 { | ||||
| 	if m != nil && m.Nonce != nil { | ||||
| 		return *m.Nonce | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientSecret) GetHmac() []byte { | ||||
| 	if m != nil { | ||||
| 		return m.Hmac | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type CMsgClientLogon struct { | ||||
| 	ProtocolVersion                   *uint32  `protobuf:"varint,1,opt,name=protocol_version" json:"protocol_version,omitempty"` | ||||
| 	ObfustucatedPrivateIp             *uint32  `protobuf:"varint,2,opt,name=obfustucated_private_ip" json:"obfustucated_private_ip,omitempty"` | ||||
| 	CellId                            *uint32  `protobuf:"varint,3,opt,name=cell_id" json:"cell_id,omitempty"` | ||||
| 	LastSessionId                     *uint32  `protobuf:"varint,4,opt,name=last_session_id" json:"last_session_id,omitempty"` | ||||
| 	ClientPackageVersion              *uint32  `protobuf:"varint,5,opt,name=client_package_version" json:"client_package_version,omitempty"` | ||||
| 	ClientLanguage                    *string  `protobuf:"bytes,6,opt,name=client_language" json:"client_language,omitempty"` | ||||
| 	ClientOsType                      *uint32  `protobuf:"varint,7,opt,name=client_os_type" json:"client_os_type,omitempty"` | ||||
| 	ShouldRememberPassword            *bool    `protobuf:"varint,8,opt,name=should_remember_password,def=0" json:"should_remember_password,omitempty"` | ||||
| 	WineVersion                       *string  `protobuf:"bytes,9,opt,name=wine_version" json:"wine_version,omitempty"` | ||||
| 	PingMsFromCellSearch              *uint32  `protobuf:"varint,10,opt,name=ping_ms_from_cell_search" json:"ping_ms_from_cell_search,omitempty"` | ||||
| 	PublicIp                          *uint32  `protobuf:"varint,20,opt,name=public_ip" json:"public_ip,omitempty"` | ||||
| 	QosLevel                          *uint32  `protobuf:"varint,21,opt,name=qos_level" json:"qos_level,omitempty"` | ||||
| 	ClientSuppliedSteamId             *uint64  `protobuf:"fixed64,22,opt,name=client_supplied_steam_id" json:"client_supplied_steam_id,omitempty"` | ||||
| 	MachineId                         []byte   `protobuf:"bytes,30,opt,name=machine_id" json:"machine_id,omitempty"` | ||||
| 	LauncherType                      *uint32  `protobuf:"varint,31,opt,name=launcher_type,def=0" json:"launcher_type,omitempty"` | ||||
| 	UiMode                            *uint32  `protobuf:"varint,32,opt,name=ui_mode,def=0" json:"ui_mode,omitempty"` | ||||
| 	ChatMode                          *uint32  `protobuf:"varint,33,opt,name=chat_mode,def=0" json:"chat_mode,omitempty"` | ||||
| 	Steam2AuthTicket                  []byte   `protobuf:"bytes,41,opt,name=steam2_auth_ticket" json:"steam2_auth_ticket,omitempty"` | ||||
| 	EmailAddress                      *string  `protobuf:"bytes,42,opt,name=email_address" json:"email_address,omitempty"` | ||||
| 	Rtime32AccountCreation            *uint32  `protobuf:"fixed32,43,opt,name=rtime32_account_creation" json:"rtime32_account_creation,omitempty"` | ||||
| 	AccountName                       *string  `protobuf:"bytes,50,opt,name=account_name" json:"account_name,omitempty"` | ||||
| 	Password                          *string  `protobuf:"bytes,51,opt,name=password" json:"password,omitempty"` | ||||
| 	GameServerToken                   *string  `protobuf:"bytes,52,opt,name=game_server_token" json:"game_server_token,omitempty"` | ||||
| 	LoginKey                          *string  `protobuf:"bytes,60,opt,name=login_key" json:"login_key,omitempty"` | ||||
| 	WasConvertedDeprecatedMsg         *bool    `protobuf:"varint,70,opt,name=was_converted_deprecated_msg,def=0" json:"was_converted_deprecated_msg,omitempty"` | ||||
| 	AnonUserTargetAccountName         *string  `protobuf:"bytes,80,opt,name=anon_user_target_account_name" json:"anon_user_target_account_name,omitempty"` | ||||
| 	ResolvedUserSteamId               *uint64  `protobuf:"fixed64,81,opt,name=resolved_user_steam_id" json:"resolved_user_steam_id,omitempty"` | ||||
| 	EresultSentryfile                 *int32   `protobuf:"varint,82,opt,name=eresult_sentryfile" json:"eresult_sentryfile,omitempty"` | ||||
| 	ShaSentryfile                     []byte   `protobuf:"bytes,83,opt,name=sha_sentryfile" json:"sha_sentryfile,omitempty"` | ||||
| 	AuthCode                          *string  `protobuf:"bytes,84,opt,name=auth_code" json:"auth_code,omitempty"` | ||||
| 	OtpType                           *int32   `protobuf:"varint,85,opt,name=otp_type" json:"otp_type,omitempty"` | ||||
| 	OtpValue                          *uint32  `protobuf:"varint,86,opt,name=otp_value" json:"otp_value,omitempty"` | ||||
| 	OtpIdentifier                     *string  `protobuf:"bytes,87,opt,name=otp_identifier" json:"otp_identifier,omitempty"` | ||||
| 	Steam2TicketRequest               *bool    `protobuf:"varint,88,opt,name=steam2_ticket_request" json:"steam2_ticket_request,omitempty"` | ||||
| 	SonyPsnTicket                     []byte   `protobuf:"bytes,90,opt,name=sony_psn_ticket" json:"sony_psn_ticket,omitempty"` | ||||
| 	SonyPsnServiceId                  *string  `protobuf:"bytes,91,opt,name=sony_psn_service_id" json:"sony_psn_service_id,omitempty"` | ||||
| 	CreateNewPsnLinkedAccountIfNeeded *bool    `protobuf:"varint,92,opt,name=create_new_psn_linked_account_if_needed,def=0" json:"create_new_psn_linked_account_if_needed,omitempty"` | ||||
| 	SonyPsnName                       *string  `protobuf:"bytes,93,opt,name=sony_psn_name" json:"sony_psn_name,omitempty"` | ||||
| 	GameServerAppId                   *int32   `protobuf:"varint,94,opt,name=game_server_app_id" json:"game_server_app_id,omitempty"` | ||||
| 	SteamguardDontRememberComputer    *bool    `protobuf:"varint,95,opt,name=steamguard_dont_remember_computer" json:"steamguard_dont_remember_computer,omitempty"` | ||||
| 	MachineName                       *string  `protobuf:"bytes,96,opt,name=machine_name" json:"machine_name,omitempty"` | ||||
| 	MachineNameUserchosen             *string  `protobuf:"bytes,97,opt,name=machine_name_userchosen" json:"machine_name_userchosen,omitempty"` | ||||
| 	CountryOverride                   *string  `protobuf:"bytes,98,opt,name=country_override" json:"country_override,omitempty"` | ||||
| 	IsSteamBox                        *bool    `protobuf:"varint,99,opt,name=is_steam_box" json:"is_steam_box,omitempty"` | ||||
| 	ClientInstanceId                  *uint64  `protobuf:"varint,100,opt,name=client_instance_id" json:"client_instance_id,omitempty"` | ||||
| 	TwoFactorCode                     *string  `protobuf:"bytes,101,opt,name=two_factor_code" json:"two_factor_code,omitempty"` | ||||
| 	SupportsRateLimitResponse         *bool    `protobuf:"varint,102,opt,name=supports_rate_limit_response" json:"supports_rate_limit_response,omitempty"` | ||||
| 	WebLogonNonce                     *string  `protobuf:"bytes,103,opt,name=web_logon_nonce" json:"web_logon_nonce,omitempty"` | ||||
| 	PriorityReason                    *int32   `protobuf:"varint,104,opt,name=priority_reason" json:"priority_reason,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral              struct{} `json:"-"` | ||||
| 	XXX_unrecognized                  []byte   `json:"-"` | ||||
| 	XXX_sizecache                     int32    `json:"-"` | ||||
| 	ProtocolVersion                   *uint32           `protobuf:"varint,1,opt,name=protocol_version,json=protocolVersion" json:"protocol_version,omitempty"` | ||||
| 	DeprecatedObfustucatedPrivateIp   *uint32           `protobuf:"varint,2,opt,name=deprecated_obfustucated_private_ip,json=deprecatedObfustucatedPrivateIp" json:"deprecated_obfustucated_private_ip,omitempty"` | ||||
| 	CellId                            *uint32           `protobuf:"varint,3,opt,name=cell_id,json=cellId" json:"cell_id,omitempty"` | ||||
| 	LastSessionId                     *uint32           `protobuf:"varint,4,opt,name=last_session_id,json=lastSessionId" json:"last_session_id,omitempty"` | ||||
| 	ClientPackageVersion              *uint32           `protobuf:"varint,5,opt,name=client_package_version,json=clientPackageVersion" json:"client_package_version,omitempty"` | ||||
| 	ClientLanguage                    *string           `protobuf:"bytes,6,opt,name=client_language,json=clientLanguage" json:"client_language,omitempty"` | ||||
| 	ClientOsType                      *uint32           `protobuf:"varint,7,opt,name=client_os_type,json=clientOsType" json:"client_os_type,omitempty"` | ||||
| 	ShouldRememberPassword            *bool             `protobuf:"varint,8,opt,name=should_remember_password,json=shouldRememberPassword,def=0" json:"should_remember_password,omitempty"` | ||||
| 	WineVersion                       *string           `protobuf:"bytes,9,opt,name=wine_version,json=wineVersion" json:"wine_version,omitempty"` | ||||
| 	Deprecated_10                     *uint32           `protobuf:"varint,10,opt,name=deprecated_10,json=deprecated10" json:"deprecated_10,omitempty"` | ||||
| 	ObfuscatedPrivateIp               *CMsgIPAddress    `protobuf:"bytes,11,opt,name=obfuscated_private_ip,json=obfuscatedPrivateIp" json:"obfuscated_private_ip,omitempty"` | ||||
| 	DeprecatedPublicIp                *uint32           `protobuf:"varint,20,opt,name=deprecated_public_ip,json=deprecatedPublicIp" json:"deprecated_public_ip,omitempty"` | ||||
| 	QosLevel                          *uint32           `protobuf:"varint,21,opt,name=qos_level,json=qosLevel" json:"qos_level,omitempty"` | ||||
| 	ClientSuppliedSteamId             *uint64           `protobuf:"fixed64,22,opt,name=client_supplied_steam_id,json=clientSuppliedSteamId" json:"client_supplied_steam_id,omitempty"` | ||||
| 	PublicIp                          *CMsgIPAddress    `protobuf:"bytes,23,opt,name=public_ip,json=publicIp" json:"public_ip,omitempty"` | ||||
| 	MachineId                         []byte            `protobuf:"bytes,30,opt,name=machine_id,json=machineId" json:"machine_id,omitempty"` | ||||
| 	LauncherType                      *uint32           `protobuf:"varint,31,opt,name=launcher_type,json=launcherType,def=0" json:"launcher_type,omitempty"` | ||||
| 	UiMode                            *uint32           `protobuf:"varint,32,opt,name=ui_mode,json=uiMode,def=0" json:"ui_mode,omitempty"` | ||||
| 	ChatMode                          *uint32           `protobuf:"varint,33,opt,name=chat_mode,json=chatMode,def=0" json:"chat_mode,omitempty"` | ||||
| 	Steam2AuthTicket                  []byte            `protobuf:"bytes,41,opt,name=steam2_auth_ticket,json=steam2AuthTicket" json:"steam2_auth_ticket,omitempty"` | ||||
| 	EmailAddress                      *string           `protobuf:"bytes,42,opt,name=email_address,json=emailAddress" json:"email_address,omitempty"` | ||||
| 	Rtime32AccountCreation            *uint32           `protobuf:"fixed32,43,opt,name=rtime32_account_creation,json=rtime32AccountCreation" json:"rtime32_account_creation,omitempty"` | ||||
| 	AccountName                       *string           `protobuf:"bytes,50,opt,name=account_name,json=accountName" json:"account_name,omitempty"` | ||||
| 	Password                          *string           `protobuf:"bytes,51,opt,name=password" json:"password,omitempty"` | ||||
| 	GameServerToken                   *string           `protobuf:"bytes,52,opt,name=game_server_token,json=gameServerToken" json:"game_server_token,omitempty"` | ||||
| 	LoginKey                          *string           `protobuf:"bytes,60,opt,name=login_key,json=loginKey" json:"login_key,omitempty"` | ||||
| 	WasConvertedDeprecatedMsg         *bool             `protobuf:"varint,70,opt,name=was_converted_deprecated_msg,json=wasConvertedDeprecatedMsg,def=0" json:"was_converted_deprecated_msg,omitempty"` | ||||
| 	AnonUserTargetAccountName         *string           `protobuf:"bytes,80,opt,name=anon_user_target_account_name,json=anonUserTargetAccountName" json:"anon_user_target_account_name,omitempty"` | ||||
| 	ResolvedUserSteamId               *uint64           `protobuf:"fixed64,81,opt,name=resolved_user_steam_id,json=resolvedUserSteamId" json:"resolved_user_steam_id,omitempty"` | ||||
| 	EresultSentryfile                 *int32            `protobuf:"varint,82,opt,name=eresult_sentryfile,json=eresultSentryfile" json:"eresult_sentryfile,omitempty"` | ||||
| 	ShaSentryfile                     []byte            `protobuf:"bytes,83,opt,name=sha_sentryfile,json=shaSentryfile" json:"sha_sentryfile,omitempty"` | ||||
| 	AuthCode                          *string           `protobuf:"bytes,84,opt,name=auth_code,json=authCode" json:"auth_code,omitempty"` | ||||
| 	OtpType                           *int32            `protobuf:"varint,85,opt,name=otp_type,json=otpType" json:"otp_type,omitempty"` | ||||
| 	OtpValue                          *uint32           `protobuf:"varint,86,opt,name=otp_value,json=otpValue" json:"otp_value,omitempty"` | ||||
| 	OtpIdentifier                     *string           `protobuf:"bytes,87,opt,name=otp_identifier,json=otpIdentifier" json:"otp_identifier,omitempty"` | ||||
| 	Steam2TicketRequest               *bool             `protobuf:"varint,88,opt,name=steam2_ticket_request,json=steam2TicketRequest" json:"steam2_ticket_request,omitempty"` | ||||
| 	SonyPsnTicket                     []byte            `protobuf:"bytes,90,opt,name=sony_psn_ticket,json=sonyPsnTicket" json:"sony_psn_ticket,omitempty"` | ||||
| 	SonyPsnServiceId                  *string           `protobuf:"bytes,91,opt,name=sony_psn_service_id,json=sonyPsnServiceId" json:"sony_psn_service_id,omitempty"` | ||||
| 	CreateNewPsnLinkedAccountIfNeeded *bool             `protobuf:"varint,92,opt,name=create_new_psn_linked_account_if_needed,json=createNewPsnLinkedAccountIfNeeded,def=0" json:"create_new_psn_linked_account_if_needed,omitempty"` | ||||
| 	SonyPsnName                       *string           `protobuf:"bytes,93,opt,name=sony_psn_name,json=sonyPsnName" json:"sony_psn_name,omitempty"` | ||||
| 	GameServerAppId                   *int32            `protobuf:"varint,94,opt,name=game_server_app_id,json=gameServerAppId" json:"game_server_app_id,omitempty"` | ||||
| 	SteamguardDontRememberComputer    *bool             `protobuf:"varint,95,opt,name=steamguard_dont_remember_computer,json=steamguardDontRememberComputer" json:"steamguard_dont_remember_computer,omitempty"` | ||||
| 	MachineName                       *string           `protobuf:"bytes,96,opt,name=machine_name,json=machineName" json:"machine_name,omitempty"` | ||||
| 	MachineNameUserchosen             *string           `protobuf:"bytes,97,opt,name=machine_name_userchosen,json=machineNameUserchosen" json:"machine_name_userchosen,omitempty"` | ||||
| 	CountryOverride                   *string           `protobuf:"bytes,98,opt,name=country_override,json=countryOverride" json:"country_override,omitempty"` | ||||
| 	IsSteamBox                        *bool             `protobuf:"varint,99,opt,name=is_steam_box,json=isSteamBox" json:"is_steam_box,omitempty"` | ||||
| 	ClientInstanceId                  *uint64           `protobuf:"varint,100,opt,name=client_instance_id,json=clientInstanceId" json:"client_instance_id,omitempty"` | ||||
| 	TwoFactorCode                     *string           `protobuf:"bytes,101,opt,name=two_factor_code,json=twoFactorCode" json:"two_factor_code,omitempty"` | ||||
| 	SupportsRateLimitResponse         *bool             `protobuf:"varint,102,opt,name=supports_rate_limit_response,json=supportsRateLimitResponse" json:"supports_rate_limit_response,omitempty"` | ||||
| 	WebLogonNonce                     *string           `protobuf:"bytes,103,opt,name=web_logon_nonce,json=webLogonNonce" json:"web_logon_nonce,omitempty"` | ||||
| 	PriorityReason                    *int32            `protobuf:"varint,104,opt,name=priority_reason,json=priorityReason" json:"priority_reason,omitempty"` | ||||
| 	EmbeddedClientSecret              *CMsgClientSecret `protobuf:"bytes,105,opt,name=embedded_client_secret,json=embeddedClientSecret" json:"embedded_client_secret,omitempty"` | ||||
| 	DisablePartnerAutogrants          *bool             `protobuf:"varint,106,opt,name=disable_partner_autogrants,json=disablePartnerAutogrants" json:"disable_partner_autogrants,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral              struct{}          `json:"-"` | ||||
| 	XXX_unrecognized                  []byte            `json:"-"` | ||||
| 	XXX_sizecache                     int32             `json:"-"` | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientLogon) Reset()         { *m = CMsgClientLogon{} } | ||||
| func (m *CMsgClientLogon) String() string { return proto.CompactTextString(m) } | ||||
| func (*CMsgClientLogon) ProtoMessage()    {} | ||||
| func (*CMsgClientLogon) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{3} | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{4} | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientLogon) XXX_Unmarshal(b []byte) error { | ||||
| @@ -231,9 +306,9 @@ func (m *CMsgClientLogon) GetProtocolVersion() uint32 { | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientLogon) GetObfustucatedPrivateIp() uint32 { | ||||
| 	if m != nil && m.ObfustucatedPrivateIp != nil { | ||||
| 		return *m.ObfustucatedPrivateIp | ||||
| func (m *CMsgClientLogon) GetDeprecatedObfustucatedPrivateIp() uint32 { | ||||
| 	if m != nil && m.DeprecatedObfustucatedPrivateIp != nil { | ||||
| 		return *m.DeprecatedObfustucatedPrivateIp | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
| @@ -287,16 +362,23 @@ func (m *CMsgClientLogon) GetWineVersion() string { | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientLogon) GetPingMsFromCellSearch() uint32 { | ||||
| 	if m != nil && m.PingMsFromCellSearch != nil { | ||||
| 		return *m.PingMsFromCellSearch | ||||
| func (m *CMsgClientLogon) GetDeprecated_10() uint32 { | ||||
| 	if m != nil && m.Deprecated_10 != nil { | ||||
| 		return *m.Deprecated_10 | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientLogon) GetPublicIp() uint32 { | ||||
| 	if m != nil && m.PublicIp != nil { | ||||
| 		return *m.PublicIp | ||||
| func (m *CMsgClientLogon) GetObfuscatedPrivateIp() *CMsgIPAddress { | ||||
| 	if m != nil { | ||||
| 		return m.ObfuscatedPrivateIp | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientLogon) GetDeprecatedPublicIp() uint32 { | ||||
| 	if m != nil && m.DeprecatedPublicIp != nil { | ||||
| 		return *m.DeprecatedPublicIp | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
| @@ -315,6 +397,13 @@ func (m *CMsgClientLogon) GetClientSuppliedSteamId() uint64 { | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientLogon) GetPublicIp() *CMsgIPAddress { | ||||
| 	if m != nil { | ||||
| 		return m.PublicIp | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientLogon) GetMachineId() []byte { | ||||
| 	if m != nil { | ||||
| 		return m.MachineId | ||||
| @@ -567,40 +656,55 @@ func (m *CMsgClientLogon) GetPriorityReason() int32 { | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientLogon) GetEmbeddedClientSecret() *CMsgClientSecret { | ||||
| 	if m != nil { | ||||
| 		return m.EmbeddedClientSecret | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientLogon) GetDisablePartnerAutogrants() bool { | ||||
| 	if m != nil && m.DisablePartnerAutogrants != nil { | ||||
| 		return *m.DisablePartnerAutogrants | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| type CMsgClientLogonResponse struct { | ||||
| 	Eresult                     *int32   `protobuf:"varint,1,opt,name=eresult,def=2" json:"eresult,omitempty"` | ||||
| 	OutOfGameHeartbeatSeconds   *int32   `protobuf:"varint,2,opt,name=out_of_game_heartbeat_seconds" json:"out_of_game_heartbeat_seconds,omitempty"` | ||||
| 	InGameHeartbeatSeconds      *int32   `protobuf:"varint,3,opt,name=in_game_heartbeat_seconds" json:"in_game_heartbeat_seconds,omitempty"` | ||||
| 	PublicIp                    *uint32  `protobuf:"varint,4,opt,name=public_ip" json:"public_ip,omitempty"` | ||||
| 	Rtime32ServerTime           *uint32  `protobuf:"fixed32,5,opt,name=rtime32_server_time" json:"rtime32_server_time,omitempty"` | ||||
| 	AccountFlags                *uint32  `protobuf:"varint,6,opt,name=account_flags" json:"account_flags,omitempty"` | ||||
| 	CellId                      *uint32  `protobuf:"varint,7,opt,name=cell_id" json:"cell_id,omitempty"` | ||||
| 	EmailDomain                 *string  `protobuf:"bytes,8,opt,name=email_domain" json:"email_domain,omitempty"` | ||||
| 	Steam2Ticket                []byte   `protobuf:"bytes,9,opt,name=steam2_ticket" json:"steam2_ticket,omitempty"` | ||||
| 	EresultExtended             *int32   `protobuf:"varint,10,opt,name=eresult_extended" json:"eresult_extended,omitempty"` | ||||
| 	WebapiAuthenticateUserNonce *string  `protobuf:"bytes,11,opt,name=webapi_authenticate_user_nonce" json:"webapi_authenticate_user_nonce,omitempty"` | ||||
| 	CellIdPingThreshold         *uint32  `protobuf:"varint,12,opt,name=cell_id_ping_threshold" json:"cell_id_ping_threshold,omitempty"` | ||||
| 	UsePics                     *bool    `protobuf:"varint,13,opt,name=use_pics" json:"use_pics,omitempty"` | ||||
| 	VanityUrl                   *string  `protobuf:"bytes,14,opt,name=vanity_url" json:"vanity_url,omitempty"` | ||||
| 	ClientSuppliedSteamid       *uint64  `protobuf:"fixed64,20,opt,name=client_supplied_steamid" json:"client_supplied_steamid,omitempty"` | ||||
| 	IpCountryCode               *string  `protobuf:"bytes,21,opt,name=ip_country_code" json:"ip_country_code,omitempty"` | ||||
| 	ParentalSettings            []byte   `protobuf:"bytes,22,opt,name=parental_settings" json:"parental_settings,omitempty"` | ||||
| 	ParentalSettingSignature    []byte   `protobuf:"bytes,23,opt,name=parental_setting_signature" json:"parental_setting_signature,omitempty"` | ||||
| 	CountLoginfailuresToMigrate *int32   `protobuf:"varint,24,opt,name=count_loginfailures_to_migrate" json:"count_loginfailures_to_migrate,omitempty"` | ||||
| 	CountDisconnectsToMigrate   *int32   `protobuf:"varint,25,opt,name=count_disconnects_to_migrate" json:"count_disconnects_to_migrate,omitempty"` | ||||
| 	OgsDataReportTimeWindow     *int32   `protobuf:"varint,26,opt,name=ogs_data_report_time_window" json:"ogs_data_report_time_window,omitempty"` | ||||
| 	ClientInstanceId            *uint64  `protobuf:"varint,27,opt,name=client_instance_id" json:"client_instance_id,omitempty"` | ||||
| 	ForceClientUpdateCheck      *bool    `protobuf:"varint,28,opt,name=force_client_update_check" json:"force_client_update_check,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral        struct{} `json:"-"` | ||||
| 	XXX_unrecognized            []byte   `json:"-"` | ||||
| 	XXX_sizecache               int32    `json:"-"` | ||||
| 	Eresult                     *int32         `protobuf:"varint,1,opt,name=eresult,def=2" json:"eresult,omitempty"` | ||||
| 	OutOfGameHeartbeatSeconds   *int32         `protobuf:"varint,2,opt,name=out_of_game_heartbeat_seconds,json=outOfGameHeartbeatSeconds" json:"out_of_game_heartbeat_seconds,omitempty"` | ||||
| 	InGameHeartbeatSeconds      *int32         `protobuf:"varint,3,opt,name=in_game_heartbeat_seconds,json=inGameHeartbeatSeconds" json:"in_game_heartbeat_seconds,omitempty"` | ||||
| 	DeprecatedPublicIp          *uint32        `protobuf:"varint,4,opt,name=deprecated_public_ip,json=deprecatedPublicIp" json:"deprecated_public_ip,omitempty"` | ||||
| 	Rtime32ServerTime           *uint32        `protobuf:"fixed32,5,opt,name=rtime32_server_time,json=rtime32ServerTime" json:"rtime32_server_time,omitempty"` | ||||
| 	AccountFlags                *uint32        `protobuf:"varint,6,opt,name=account_flags,json=accountFlags" json:"account_flags,omitempty"` | ||||
| 	CellId                      *uint32        `protobuf:"varint,7,opt,name=cell_id,json=cellId" json:"cell_id,omitempty"` | ||||
| 	EmailDomain                 *string        `protobuf:"bytes,8,opt,name=email_domain,json=emailDomain" json:"email_domain,omitempty"` | ||||
| 	Steam2Ticket                []byte         `protobuf:"bytes,9,opt,name=steam2_ticket,json=steam2Ticket" json:"steam2_ticket,omitempty"` | ||||
| 	EresultExtended             *int32         `protobuf:"varint,10,opt,name=eresult_extended,json=eresultExtended" json:"eresult_extended,omitempty"` | ||||
| 	WebapiAuthenticateUserNonce *string        `protobuf:"bytes,11,opt,name=webapi_authenticate_user_nonce,json=webapiAuthenticateUserNonce" json:"webapi_authenticate_user_nonce,omitempty"` | ||||
| 	CellIdPingThreshold         *uint32        `protobuf:"varint,12,opt,name=cell_id_ping_threshold,json=cellIdPingThreshold" json:"cell_id_ping_threshold,omitempty"` | ||||
| 	DeprecatedUsePics           *bool          `protobuf:"varint,13,opt,name=deprecated_use_pics,json=deprecatedUsePics" json:"deprecated_use_pics,omitempty"` | ||||
| 	VanityUrl                   *string        `protobuf:"bytes,14,opt,name=vanity_url,json=vanityUrl" json:"vanity_url,omitempty"` | ||||
| 	PublicIp                    *CMsgIPAddress `protobuf:"bytes,15,opt,name=public_ip,json=publicIp" json:"public_ip,omitempty"` | ||||
| 	ClientSuppliedSteamid       *uint64        `protobuf:"fixed64,20,opt,name=client_supplied_steamid,json=clientSuppliedSteamid" json:"client_supplied_steamid,omitempty"` | ||||
| 	IpCountryCode               *string        `protobuf:"bytes,21,opt,name=ip_country_code,json=ipCountryCode" json:"ip_country_code,omitempty"` | ||||
| 	ParentalSettings            []byte         `protobuf:"bytes,22,opt,name=parental_settings,json=parentalSettings" json:"parental_settings,omitempty"` | ||||
| 	ParentalSettingSignature    []byte         `protobuf:"bytes,23,opt,name=parental_setting_signature,json=parentalSettingSignature" json:"parental_setting_signature,omitempty"` | ||||
| 	CountLoginfailuresToMigrate *int32         `protobuf:"varint,24,opt,name=count_loginfailures_to_migrate,json=countLoginfailuresToMigrate" json:"count_loginfailures_to_migrate,omitempty"` | ||||
| 	CountDisconnectsToMigrate   *int32         `protobuf:"varint,25,opt,name=count_disconnects_to_migrate,json=countDisconnectsToMigrate" json:"count_disconnects_to_migrate,omitempty"` | ||||
| 	OgsDataReportTimeWindow     *int32         `protobuf:"varint,26,opt,name=ogs_data_report_time_window,json=ogsDataReportTimeWindow" json:"ogs_data_report_time_window,omitempty"` | ||||
| 	ClientInstanceId            *uint64        `protobuf:"varint,27,opt,name=client_instance_id,json=clientInstanceId" json:"client_instance_id,omitempty"` | ||||
| 	ForceClientUpdateCheck      *bool          `protobuf:"varint,28,opt,name=force_client_update_check,json=forceClientUpdateCheck" json:"force_client_update_check,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral        struct{}       `json:"-"` | ||||
| 	XXX_unrecognized            []byte         `json:"-"` | ||||
| 	XXX_sizecache               int32          `json:"-"` | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientLogonResponse) Reset()         { *m = CMsgClientLogonResponse{} } | ||||
| func (m *CMsgClientLogonResponse) String() string { return proto.CompactTextString(m) } | ||||
| func (*CMsgClientLogonResponse) ProtoMessage()    {} | ||||
| func (*CMsgClientLogonResponse) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{4} | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{5} | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientLogonResponse) XXX_Unmarshal(b []byte) error { | ||||
| @@ -644,9 +748,9 @@ func (m *CMsgClientLogonResponse) GetInGameHeartbeatSeconds() int32 { | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientLogonResponse) GetPublicIp() uint32 { | ||||
| 	if m != nil && m.PublicIp != nil { | ||||
| 		return *m.PublicIp | ||||
| func (m *CMsgClientLogonResponse) GetDeprecatedPublicIp() uint32 { | ||||
| 	if m != nil && m.DeprecatedPublicIp != nil { | ||||
| 		return *m.DeprecatedPublicIp | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
| @@ -707,9 +811,9 @@ func (m *CMsgClientLogonResponse) GetCellIdPingThreshold() uint32 { | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientLogonResponse) GetUsePics() bool { | ||||
| 	if m != nil && m.UsePics != nil { | ||||
| 		return *m.UsePics | ||||
| func (m *CMsgClientLogonResponse) GetDeprecatedUsePics() bool { | ||||
| 	if m != nil && m.DeprecatedUsePics != nil { | ||||
| 		return *m.DeprecatedUsePics | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| @@ -721,6 +825,13 @@ func (m *CMsgClientLogonResponse) GetVanityUrl() string { | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientLogonResponse) GetPublicIp() *CMsgIPAddress { | ||||
| 	if m != nil { | ||||
| 		return m.PublicIp | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientLogonResponse) GetClientSuppliedSteamid() uint64 { | ||||
| 	if m != nil && m.ClientSuppliedSteamid != nil { | ||||
| 		return *m.ClientSuppliedSteamid | ||||
| @@ -785,7 +896,7 @@ func (m *CMsgClientLogonResponse) GetForceClientUpdateCheck() bool { | ||||
| } | ||||
|  | ||||
| type CMsgClientRequestWebAPIAuthenticateUserNonce struct { | ||||
| 	TokenType            *int32   `protobuf:"varint,1,opt,name=token_type,def=-1" json:"token_type,omitempty"` | ||||
| 	TokenType            *int32   `protobuf:"varint,1,opt,name=token_type,json=tokenType,def=-1" json:"token_type,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| @@ -799,7 +910,7 @@ func (m *CMsgClientRequestWebAPIAuthenticateUserNonce) String() string { | ||||
| } | ||||
| func (*CMsgClientRequestWebAPIAuthenticateUserNonce) ProtoMessage() {} | ||||
| func (*CMsgClientRequestWebAPIAuthenticateUserNonce) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{5} | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{6} | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientRequestWebAPIAuthenticateUserNonce) XXX_Unmarshal(b []byte) error { | ||||
| @@ -831,8 +942,8 @@ func (m *CMsgClientRequestWebAPIAuthenticateUserNonce) GetTokenType() int32 { | ||||
|  | ||||
| type CMsgClientRequestWebAPIAuthenticateUserNonceResponse struct { | ||||
| 	Eresult                     *int32   `protobuf:"varint,1,opt,name=eresult,def=2" json:"eresult,omitempty"` | ||||
| 	WebapiAuthenticateUserNonce *string  `protobuf:"bytes,11,opt,name=webapi_authenticate_user_nonce" json:"webapi_authenticate_user_nonce,omitempty"` | ||||
| 	TokenType                   *int32   `protobuf:"varint,3,opt,name=token_type,def=-1" json:"token_type,omitempty"` | ||||
| 	WebapiAuthenticateUserNonce *string  `protobuf:"bytes,11,opt,name=webapi_authenticate_user_nonce,json=webapiAuthenticateUserNonce" json:"webapi_authenticate_user_nonce,omitempty"` | ||||
| 	TokenType                   *int32   `protobuf:"varint,3,opt,name=token_type,json=tokenType,def=-1" json:"token_type,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral        struct{} `json:"-"` | ||||
| 	XXX_unrecognized            []byte   `json:"-"` | ||||
| 	XXX_sizecache               int32    `json:"-"` | ||||
| @@ -846,7 +957,7 @@ func (m *CMsgClientRequestWebAPIAuthenticateUserNonceResponse) String() string { | ||||
| } | ||||
| func (*CMsgClientRequestWebAPIAuthenticateUserNonceResponse) ProtoMessage() {} | ||||
| func (*CMsgClientRequestWebAPIAuthenticateUserNonceResponse) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{6} | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{7} | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientRequestWebAPIAuthenticateUserNonceResponse) XXX_Unmarshal(b []byte) error { | ||||
| @@ -901,7 +1012,7 @@ func (m *CMsgClientLogOff) Reset()         { *m = CMsgClientLogOff{} } | ||||
| func (m *CMsgClientLogOff) String() string { return proto.CompactTextString(m) } | ||||
| func (*CMsgClientLogOff) ProtoMessage()    {} | ||||
| func (*CMsgClientLogOff) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{7} | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{8} | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientLogOff) XXX_Unmarshal(b []byte) error { | ||||
| @@ -933,7 +1044,7 @@ func (m *CMsgClientLoggedOff) Reset()         { *m = CMsgClientLoggedOff{} } | ||||
| func (m *CMsgClientLoggedOff) String() string { return proto.CompactTextString(m) } | ||||
| func (*CMsgClientLoggedOff) ProtoMessage()    {} | ||||
| func (*CMsgClientLoggedOff) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{8} | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{9} | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientLoggedOff) XXX_Unmarshal(b []byte) error { | ||||
| @@ -964,8 +1075,8 @@ func (m *CMsgClientLoggedOff) GetEresult() int32 { | ||||
| } | ||||
|  | ||||
| type CMsgClientNewLoginKey struct { | ||||
| 	UniqueId             *uint32  `protobuf:"varint,1,opt,name=unique_id" json:"unique_id,omitempty"` | ||||
| 	LoginKey             *string  `protobuf:"bytes,2,opt,name=login_key" json:"login_key,omitempty"` | ||||
| 	UniqueId             *uint32  `protobuf:"varint,1,opt,name=unique_id,json=uniqueId" json:"unique_id,omitempty"` | ||||
| 	LoginKey             *string  `protobuf:"bytes,2,opt,name=login_key,json=loginKey" json:"login_key,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| @@ -975,7 +1086,7 @@ func (m *CMsgClientNewLoginKey) Reset()         { *m = CMsgClientNewLoginKey{} } | ||||
| func (m *CMsgClientNewLoginKey) String() string { return proto.CompactTextString(m) } | ||||
| func (*CMsgClientNewLoginKey) ProtoMessage()    {} | ||||
| func (*CMsgClientNewLoginKey) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{9} | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{10} | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientNewLoginKey) XXX_Unmarshal(b []byte) error { | ||||
| @@ -1011,7 +1122,7 @@ func (m *CMsgClientNewLoginKey) GetLoginKey() string { | ||||
| } | ||||
|  | ||||
| type CMsgClientNewLoginKeyAccepted struct { | ||||
| 	UniqueId             *uint32  `protobuf:"varint,1,opt,name=unique_id" json:"unique_id,omitempty"` | ||||
| 	UniqueId             *uint32  `protobuf:"varint,1,opt,name=unique_id,json=uniqueId" json:"unique_id,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| @@ -1021,7 +1132,7 @@ func (m *CMsgClientNewLoginKeyAccepted) Reset()         { *m = CMsgClientNewLogi | ||||
| func (m *CMsgClientNewLoginKeyAccepted) String() string { return proto.CompactTextString(m) } | ||||
| func (*CMsgClientNewLoginKeyAccepted) ProtoMessage()    {} | ||||
| func (*CMsgClientNewLoginKeyAccepted) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{10} | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{11} | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientNewLoginKeyAccepted) XXX_Unmarshal(b []byte) error { | ||||
| @@ -1050,18 +1161,18 @@ func (m *CMsgClientNewLoginKeyAccepted) GetUniqueId() uint32 { | ||||
| } | ||||
|  | ||||
| type CMsgClientAccountInfo struct { | ||||
| 	PersonaName                     *string  `protobuf:"bytes,1,opt,name=persona_name" json:"persona_name,omitempty"` | ||||
| 	IpCountry                       *string  `protobuf:"bytes,2,opt,name=ip_country" json:"ip_country,omitempty"` | ||||
| 	CountAuthedComputers            *int32   `protobuf:"varint,5,opt,name=count_authed_computers" json:"count_authed_computers,omitempty"` | ||||
| 	AccountFlags                    *uint32  `protobuf:"varint,7,opt,name=account_flags" json:"account_flags,omitempty"` | ||||
| 	FacebookId                      *uint64  `protobuf:"varint,8,opt,name=facebook_id" json:"facebook_id,omitempty"` | ||||
| 	FacebookName                    *string  `protobuf:"bytes,9,opt,name=facebook_name" json:"facebook_name,omitempty"` | ||||
| 	SteamguardNotifyNewmachines     *bool    `protobuf:"varint,14,opt,name=steamguard_notify_newmachines" json:"steamguard_notify_newmachines,omitempty"` | ||||
| 	SteamguardMachineNameUserChosen *string  `protobuf:"bytes,15,opt,name=steamguard_machine_name_user_chosen" json:"steamguard_machine_name_user_chosen,omitempty"` | ||||
| 	IsPhoneVerified                 *bool    `protobuf:"varint,16,opt,name=is_phone_verified" json:"is_phone_verified,omitempty"` | ||||
| 	TwoFactorState                  *uint32  `protobuf:"varint,17,opt,name=two_factor_state" json:"two_factor_state,omitempty"` | ||||
| 	IsPhoneIdentifying              *bool    `protobuf:"varint,18,opt,name=is_phone_identifying" json:"is_phone_identifying,omitempty"` | ||||
| 	IsPhoneNeedingReverify          *bool    `protobuf:"varint,19,opt,name=is_phone_needing_reverify" json:"is_phone_needing_reverify,omitempty"` | ||||
| 	PersonaName                     *string  `protobuf:"bytes,1,opt,name=persona_name,json=personaName" json:"persona_name,omitempty"` | ||||
| 	IpCountry                       *string  `protobuf:"bytes,2,opt,name=ip_country,json=ipCountry" json:"ip_country,omitempty"` | ||||
| 	CountAuthedComputers            *int32   `protobuf:"varint,5,opt,name=count_authed_computers,json=countAuthedComputers" json:"count_authed_computers,omitempty"` | ||||
| 	AccountFlags                    *uint32  `protobuf:"varint,7,opt,name=account_flags,json=accountFlags" json:"account_flags,omitempty"` | ||||
| 	FacebookId                      *uint64  `protobuf:"varint,8,opt,name=facebook_id,json=facebookId" json:"facebook_id,omitempty"` | ||||
| 	FacebookName                    *string  `protobuf:"bytes,9,opt,name=facebook_name,json=facebookName" json:"facebook_name,omitempty"` | ||||
| 	SteamguardNotifyNewmachines     *bool    `protobuf:"varint,14,opt,name=steamguard_notify_newmachines,json=steamguardNotifyNewmachines" json:"steamguard_notify_newmachines,omitempty"` | ||||
| 	SteamguardMachineNameUserChosen *string  `protobuf:"bytes,15,opt,name=steamguard_machine_name_user_chosen,json=steamguardMachineNameUserChosen" json:"steamguard_machine_name_user_chosen,omitempty"` | ||||
| 	IsPhoneVerified                 *bool    `protobuf:"varint,16,opt,name=is_phone_verified,json=isPhoneVerified" json:"is_phone_verified,omitempty"` | ||||
| 	TwoFactorState                  *uint32  `protobuf:"varint,17,opt,name=two_factor_state,json=twoFactorState" json:"two_factor_state,omitempty"` | ||||
| 	IsPhoneIdentifying              *bool    `protobuf:"varint,18,opt,name=is_phone_identifying,json=isPhoneIdentifying" json:"is_phone_identifying,omitempty"` | ||||
| 	IsPhoneNeedingReverify          *bool    `protobuf:"varint,19,opt,name=is_phone_needing_reverify,json=isPhoneNeedingReverify" json:"is_phone_needing_reverify,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral            struct{} `json:"-"` | ||||
| 	XXX_unrecognized                []byte   `json:"-"` | ||||
| 	XXX_sizecache                   int32    `json:"-"` | ||||
| @@ -1071,7 +1182,7 @@ func (m *CMsgClientAccountInfo) Reset()         { *m = CMsgClientAccountInfo{} } | ||||
| func (m *CMsgClientAccountInfo) String() string { return proto.CompactTextString(m) } | ||||
| func (*CMsgClientAccountInfo) ProtoMessage()    {} | ||||
| func (*CMsgClientAccountInfo) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{11} | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{12} | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientAccountInfo) XXX_Unmarshal(b []byte) error { | ||||
| @@ -1176,10 +1287,89 @@ func (m *CMsgClientAccountInfo) GetIsPhoneNeedingReverify() bool { | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| type CMsgClientChallengeRequest struct { | ||||
| 	Steamid              *uint64  `protobuf:"fixed64,1,opt,name=steamid" json:"steamid,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientChallengeRequest) Reset()         { *m = CMsgClientChallengeRequest{} } | ||||
| func (m *CMsgClientChallengeRequest) String() string { return proto.CompactTextString(m) } | ||||
| func (*CMsgClientChallengeRequest) ProtoMessage()    {} | ||||
| func (*CMsgClientChallengeRequest) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{13} | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientChallengeRequest) XXX_Unmarshal(b []byte) error { | ||||
| 	return xxx_messageInfo_CMsgClientChallengeRequest.Unmarshal(m, b) | ||||
| } | ||||
| func (m *CMsgClientChallengeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	return xxx_messageInfo_CMsgClientChallengeRequest.Marshal(b, m, deterministic) | ||||
| } | ||||
| func (m *CMsgClientChallengeRequest) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_CMsgClientChallengeRequest.Merge(m, src) | ||||
| } | ||||
| func (m *CMsgClientChallengeRequest) XXX_Size() int { | ||||
| 	return xxx_messageInfo_CMsgClientChallengeRequest.Size(m) | ||||
| } | ||||
| func (m *CMsgClientChallengeRequest) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_CMsgClientChallengeRequest.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_CMsgClientChallengeRequest proto.InternalMessageInfo | ||||
|  | ||||
| func (m *CMsgClientChallengeRequest) GetSteamid() uint64 { | ||||
| 	if m != nil && m.Steamid != nil { | ||||
| 		return *m.Steamid | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| type CMsgClientChallengeResponse struct { | ||||
| 	Challenge            *uint64  `protobuf:"fixed64,1,opt,name=challenge" json:"challenge,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientChallengeResponse) Reset()         { *m = CMsgClientChallengeResponse{} } | ||||
| func (m *CMsgClientChallengeResponse) String() string { return proto.CompactTextString(m) } | ||||
| func (*CMsgClientChallengeResponse) ProtoMessage()    {} | ||||
| func (*CMsgClientChallengeResponse) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_c98cb07f62c057af, []int{14} | ||||
| } | ||||
|  | ||||
| func (m *CMsgClientChallengeResponse) XXX_Unmarshal(b []byte) error { | ||||
| 	return xxx_messageInfo_CMsgClientChallengeResponse.Unmarshal(m, b) | ||||
| } | ||||
| func (m *CMsgClientChallengeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	return xxx_messageInfo_CMsgClientChallengeResponse.Marshal(b, m, deterministic) | ||||
| } | ||||
| func (m *CMsgClientChallengeResponse) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_CMsgClientChallengeResponse.Merge(m, src) | ||||
| } | ||||
| func (m *CMsgClientChallengeResponse) XXX_Size() int { | ||||
| 	return xxx_messageInfo_CMsgClientChallengeResponse.Size(m) | ||||
| } | ||||
| func (m *CMsgClientChallengeResponse) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_CMsgClientChallengeResponse.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_CMsgClientChallengeResponse proto.InternalMessageInfo | ||||
|  | ||||
| func (m *CMsgClientChallengeResponse) GetChallenge() uint64 { | ||||
| 	if m != nil && m.Challenge != nil { | ||||
| 		return *m.Challenge | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	proto.RegisterType((*CMsgClientHeartBeat)(nil), "CMsgClientHeartBeat") | ||||
| 	proto.RegisterType((*CMsgClientServerTimestampRequest)(nil), "CMsgClientServerTimestampRequest") | ||||
| 	proto.RegisterType((*CMsgClientServerTimestampResponse)(nil), "CMsgClientServerTimestampResponse") | ||||
| 	proto.RegisterType((*CMsgClientSecret)(nil), "CMsgClientSecret") | ||||
| 	proto.RegisterType((*CMsgClientLogon)(nil), "CMsgClientLogon") | ||||
| 	proto.RegisterType((*CMsgClientLogonResponse)(nil), "CMsgClientLogonResponse") | ||||
| 	proto.RegisterType((*CMsgClientRequestWebAPIAuthenticateUserNonce)(nil), "CMsgClientRequestWebAPIAuthenticateUserNonce") | ||||
| @@ -1189,6 +1379,8 @@ func init() { | ||||
| 	proto.RegisterType((*CMsgClientNewLoginKey)(nil), "CMsgClientNewLoginKey") | ||||
| 	proto.RegisterType((*CMsgClientNewLoginKeyAccepted)(nil), "CMsgClientNewLoginKeyAccepted") | ||||
| 	proto.RegisterType((*CMsgClientAccountInfo)(nil), "CMsgClientAccountInfo") | ||||
| 	proto.RegisterType((*CMsgClientChallengeRequest)(nil), "CMsgClientChallengeRequest") | ||||
| 	proto.RegisterType((*CMsgClientChallengeResponse)(nil), "CMsgClientChallengeResponse") | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| @@ -1196,99 +1388,151 @@ func init() { | ||||
| } | ||||
|  | ||||
| var fileDescriptor_c98cb07f62c057af = []byte{ | ||||
| 	// 1495 bytes of a gzipped FileDescriptorProto | ||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0x5b, 0x73, 0x13, 0x47, | ||||
| 	0x16, 0x5e, 0x01, 0xc2, 0xd6, 0xc1, 0xc6, 0xf2, 0xd8, 0xb2, 0xdb, 0x57, 0x64, 0x71, 0x33, 0xcb, | ||||
| 	0xee, 0xd6, 0xae, 0xa1, 0xf6, 0x81, 0x4a, 0x1e, 0x0c, 0x29, 0x0a, 0x2a, 0x04, 0x08, 0x97, 0x90, | ||||
| 	0xca, 0xad, 0xd3, 0xea, 0x39, 0x33, 0xea, 0xf2, 0x4c, 0xf7, 0xd0, 0xdd, 0x23, 0xa1, 0xb7, 0x3c, | ||||
| 	0xe7, 0xcf, 0xe4, 0x7f, 0xe4, 0xc7, 0xe4, 0x37, 0xa4, 0xfa, 0x8c, 0x46, 0x92, 0xc1, 0x21, 0xc9, | ||||
| 	0xeb, 0xe9, 0xd3, 0xe7, 0xfa, 0x7d, 0x5f, 0x37, 0xdc, 0x70, 0x1e, 0x45, 0x9e, 0xa3, 0x73, 0x22, | ||||
| 	0x45, 0xc7, 0x65, 0xa6, 0x50, 0x7b, 0x87, 0x76, 0x88, 0x96, 0x67, 0x26, 0x55, 0xfa, 0x3f, 0x85, | ||||
| 	0x35, 0xde, 0x6c, 0xb3, 0xd3, 0x7e, 0x7d, 0xe1, 0xb0, 0x3a, 0xe9, 0x75, 0x60, 0xed, 0xc1, 0x17, | ||||
| 	0x2e, 0x7d, 0x40, 0x37, 0x1f, 0xa1, 0xb0, 0xfe, 0x3e, 0x0a, 0xdf, 0xfb, 0x0c, 0xba, 0x33, 0xf3, | ||||
| 	0x4b, 0x0a, 0xf8, 0x4a, 0xe5, 0xe8, 0xbc, 0xc8, 0x8b, 0x17, 0xf8, 0xb6, 0x44, 0xe7, 0xa3, 0x2e, | ||||
| 	0xb0, 0x2a, 0x21, 0xb7, 0x95, 0x85, 0xfb, 0xda, 0x85, 0x35, 0xba, 0x8d, 0xc3, 0x0b, 0xbd, 0x3e, | ||||
| 	0x1c, 0x7c, 0x24, 0x8a, 0x2b, 0x8c, 0x76, 0xf8, 0xe7, 0x61, 0xa2, 0x1d, 0x58, 0x9b, 0xf4, 0x34, | ||||
| 	0x3d, 0xe1, 0xb9, 0x63, 0xe7, 0x28, 0xc7, 0xaf, 0x00, 0x2b, 0xb3, 0x24, 0x4f, 0x4c, 0x6a, 0x74, | ||||
| 	0xc4, 0xa0, 0x4d, 0xdd, 0x49, 0x93, 0xf1, 0x21, 0x5a, 0xa7, 0x8c, 0xa6, 0x50, 0xcb, 0xd1, 0x15, | ||||
| 	0xd8, 0x34, 0xfd, 0xa4, 0x74, 0xbe, 0x94, 0xc2, 0x63, 0xcc, 0x0b, 0xab, 0x86, 0xc2, 0x23, 0x57, | ||||
| 	0x05, 0x85, 0x5b, 0x8e, 0x56, 0x60, 0x41, 0x62, 0x96, 0x71, 0x15, 0xb3, 0xf3, 0x64, 0xd8, 0x84, | ||||
| 	0x95, 0x4c, 0x38, 0xcf, 0x1d, 0xba, 0x10, 0x27, 0x1c, 0x5c, 0xa0, 0x83, 0x7d, 0xd8, 0x98, 0xd4, | ||||
| 	0x5d, 0x08, 0x79, 0x22, 0x52, 0x9c, 0xa6, 0x6a, 0xd6, 0x17, 0x27, 0xe7, 0x99, 0xd0, 0x69, 0x29, | ||||
| 	0x52, 0x64, 0x17, 0xbb, 0x8d, 0xc3, 0x56, 0xb4, 0x01, 0x97, 0x27, 0x07, 0xc6, 0x71, 0x3f, 0x2e, | ||||
| 	0x90, 0x2d, 0xd0, 0x85, 0x9b, 0xc0, 0xdc, 0xc0, 0x94, 0x59, 0xcc, 0x2d, 0xe6, 0x98, 0xf7, 0xd1, | ||||
| 	0xf2, 0x42, 0x38, 0x37, 0x32, 0x36, 0x66, 0x8b, 0xdd, 0xc6, 0xe1, 0xe2, 0xbd, 0x66, 0x22, 0x32, | ||||
| 	0x87, 0xd1, 0x3a, 0x2c, 0x8d, 0x94, 0x9e, 0xe5, 0x6b, 0x51, 0xd8, 0x2e, 0xb0, 0x42, 0xe9, 0x94, | ||||
| 	0xe7, 0x8e, 0x27, 0xd6, 0xe4, 0x9c, 0xda, 0x70, 0x28, 0xac, 0x1c, 0x30, 0xa0, 0x04, 0xab, 0xd0, | ||||
| 	0x2a, 0xca, 0x7e, 0xa6, 0x64, 0x68, 0x77, 0xbd, 0x36, 0xbd, 0x35, 0x8e, 0x67, 0x38, 0xc4, 0x8c, | ||||
| 	0x75, 0xc8, 0x34, 0xdb, 0x87, 0x2b, 0x8b, 0x22, 0x53, 0x18, 0x73, 0x42, 0x4f, 0xe8, 0x7c, 0xa3, | ||||
| 	0xdb, 0x38, 0xbc, 0x18, 0x45, 0x00, 0xb9, 0x90, 0x83, 0x50, 0x82, 0x8a, 0xd9, 0x7e, 0xb7, 0x71, | ||||
| 	0xb8, 0x14, 0x31, 0x58, 0xce, 0x44, 0xa9, 0xe5, 0x20, 0x6c, 0x29, 0xf4, 0x74, 0x25, 0x04, 0xbb, | ||||
| 	0xd7, 0xf8, 0x6f, 0x14, 0xc1, 0x42, 0xa9, 0x78, 0x6e, 0x62, 0x64, 0xdd, 0xda, 0xb6, 0x0e, 0x2d, | ||||
| 	0x39, 0x10, 0xbe, 0xb2, 0x1e, 0xd4, 0xd6, 0x6d, 0x88, 0x28, 0xd3, 0x11, 0x17, 0xa5, 0x1f, 0x70, | ||||
| 	0xaf, 0xe4, 0x09, 0x7a, 0x76, 0x8b, 0xe2, 0x77, 0x60, 0x19, 0x73, 0xa1, 0x32, 0x2e, 0xe2, 0xd8, | ||||
| 	0xa2, 0x73, 0xec, 0x9f, 0x75, 0xd3, 0x36, 0x80, 0xe2, 0xce, 0x11, 0x17, 0x52, 0x9a, 0x52, 0x7b, | ||||
| 	0x2e, 0x2d, 0x0a, 0x1f, 0xc6, 0x72, 0xbb, 0xdb, 0x38, 0x5c, 0x08, 0xc3, 0xaa, 0x4f, 0xb4, 0xc8, | ||||
| 	0x91, 0x1d, 0xd1, 0xbd, 0x36, 0x2c, 0x4e, 0x67, 0x7b, 0x87, 0x2c, 0x5b, 0xb0, 0x9a, 0x8a, 0x1c, | ||||
| 	0x79, 0x8d, 0x34, 0x73, 0x82, 0x9a, 0xdd, 0xa5, 0xa3, 0x55, 0x68, 0x11, 0x99, 0xf8, 0x09, 0x8e, | ||||
| 	0xd9, 0x27, 0x64, 0xba, 0x0d, 0xbb, 0x23, 0xe1, 0xb8, 0x34, 0x7a, 0x88, 0x36, 0x00, 0x29, 0xc6, | ||||
| 	0xc2, 0x62, 0x85, 0xa9, 0xdc, 0xa5, 0xec, 0xe1, 0xfc, 0xbe, 0xae, 0xc3, 0x9e, 0xd0, 0x46, 0xf3, | ||||
| 	0xd2, 0x85, 0xc0, 0xc2, 0xa6, 0xe8, 0xf9, 0xa9, 0x9a, 0x9e, 0x53, 0xcc, 0x7d, 0xd8, 0xb0, 0xe8, | ||||
| 	0x4c, 0x36, 0xc4, 0xb8, 0x72, 0x9d, 0x8e, 0xfd, 0x4b, 0x1a, 0xfb, 0x36, 0x44, 0x68, 0xd1, 0x95, | ||||
| 	0x59, 0x00, 0xa3, 0xf6, 0x76, 0x9c, 0xa8, 0x0c, 0xd9, 0x8b, 0x6e, 0xe3, 0xb0, 0x19, 0x30, 0xe5, | ||||
| 	0x06, 0x62, 0xde, 0xfe, 0x92, 0xc6, 0xb6, 0x0a, 0x2d, 0x9a, 0xa5, 0x0c, 0x83, 0x7e, 0x55, 0xb7, | ||||
| 	0x6e, 0x7c, 0x51, 0x2d, 0xe9, 0x35, 0x5d, 0x5e, 0x85, 0x56, 0xb0, 0x0c, 0x45, 0x56, 0x22, 0xfb, | ||||
| 	0x8a, 0x40, 0xb0, 0x01, 0x97, 0x83, 0x49, 0xc5, 0xa8, 0xbd, 0x4a, 0x14, 0x5a, 0xf6, 0x86, 0x2e, | ||||
| 	0xef, 0x41, 0x67, 0xb2, 0xa2, 0x6a, 0x3b, 0x35, 0x67, 0xd9, 0xd7, 0xa1, 0xe1, 0x80, 0x79, 0x67, | ||||
| 	0xf4, 0x98, 0x17, 0x4e, 0xd7, 0xeb, 0xfb, 0x86, 0xea, 0x08, 0x14, 0xae, 0x0f, 0xc2, 0x84, 0x95, | ||||
| 	0x24, 0xec, 0x7c, 0x4b, 0x41, 0xff, 0x0f, 0x37, 0x69, 0x69, 0xc8, 0x35, 0x8e, 0xc8, 0x25, 0x53, | ||||
| 	0xfa, 0x04, 0xe3, 0xe9, 0x90, 0x54, 0xc2, 0x35, 0x62, 0x8c, 0x31, 0xfb, 0x6e, 0x7e, 0xae, 0x1d, | ||||
| 	0x58, 0x9e, 0x06, 0xa5, 0x39, 0x7e, 0x4f, 0xe1, 0xb6, 0x21, 0x9a, 0xdf, 0xa4, 0x28, 0x42, 0x1f, | ||||
| 	0xec, 0x07, 0x6a, 0xf5, 0x16, 0x1c, 0x50, 0xfd, 0x69, 0x29, 0x6c, 0xcc, 0x63, 0x43, 0xaa, 0x33, | ||||
| 	0x21, 0x9b, 0x34, 0x79, 0x51, 0x7a, 0xb4, 0x8c, 0x53, 0x2f, 0xeb, 0xb0, 0x54, 0xa3, 0x9c, 0x82, | ||||
| 	0xff, 0x48, 0xc1, 0xaf, 0xc0, 0xe6, 0xbc, 0x95, 0x16, 0x25, 0x07, 0xc6, 0xa1, 0x66, 0x82, 0x1c, | ||||
| 	0x18, 0xb4, 0xa9, 0x68, 0x3b, 0xe6, 0x66, 0x88, 0xd6, 0xaa, 0x18, 0x59, 0x9f, 0x4e, 0xd6, 0x61, | ||||
| 	0x49, 0xb9, 0xc9, 0x52, 0xfb, 0xe6, 0x1d, 0x93, 0x94, 0x66, 0x1b, 0xa2, 0x09, 0xdd, 0x94, 0x76, | ||||
| 	0x5e, 0xe8, 0x6a, 0x30, 0x31, 0x09, 0xdf, 0x26, 0xac, 0xf8, 0x91, 0xe1, 0x89, 0x90, 0xde, 0xd8, | ||||
| 	0x6a, 0x87, 0x48, 0xa1, 0xae, 0xc1, 0x6e, 0x20, 0xa7, 0xb1, 0xde, 0x71, 0x1b, 0x06, 0x97, 0xa9, | ||||
| 	0x5c, 0x85, 0x56, 0x2a, 0x4d, 0x65, 0x49, 0xbd, 0x8d, 0x11, 0xf6, 0xc3, 0x43, 0x60, 0x34, 0xd7, | ||||
| 	0x46, 0x4b, 0x64, 0x29, 0x5d, 0xdf, 0x84, 0x95, 0xc2, 0x2a, 0x63, 0x95, 0x1f, 0x73, 0x8b, 0xc2, | ||||
| 	0x19, 0xcd, 0x06, 0x61, 0x3c, 0xbd, 0x5f, 0x9a, 0xb0, 0xf9, 0x9e, 0x98, 0x4e, 0x75, 0x3a, 0x82, | ||||
| 	0x85, 0x09, 0xfc, 0x48, 0x4b, 0x9b, 0xf7, 0x1a, 0x47, 0x01, 0xd9, 0xa6, 0xf4, 0xdc, 0x24, 0x9c, | ||||
| 	0x26, 0x3e, 0x08, 0xef, 0x47, 0x1f, 0x45, 0x00, 0xa8, 0x34, 0x3a, 0xae, 0x34, 0xba, 0x19, 0x1d, | ||||
| 	0xc0, 0x96, 0xd2, 0x7f, 0xe4, 0x72, 0xbe, 0xc6, 0xe0, 0x4c, 0x9b, 0x2a, 0x81, 0xdd, 0x81, 0xb5, | ||||
| 	0x9a, 0xdb, 0x73, 0xf2, 0x4f, 0xea, 0xba, 0x10, 0x76, 0x5f, 0xa3, 0x23, 0xc9, 0x44, 0xea, 0x48, | ||||
| 	0x5b, 0x4f, 0xc9, 0x77, 0x25, 0xaa, 0xeb, 0xb0, 0x54, 0xe9, 0x46, 0x6c, 0x72, 0xa1, 0x34, 0x09, | ||||
| 	0x69, 0x8b, 0x90, 0x33, 0x0f, 0x63, 0x92, 0xd0, 0x20, 0x62, 0xed, 0x9a, 0x61, 0xf8, 0xce, 0xa3, | ||||
| 	0x0e, 0x88, 0x03, 0x2a, 0xef, 0x06, 0xec, 0x8f, 0xb0, 0x2f, 0x0a, 0x45, 0xd2, 0x14, 0x48, 0x11, | ||||
| 	0xb8, 0x5e, 0xd1, 0xb4, 0x9a, 0xec, 0xa5, 0x9a, 0xc3, 0x93, 0xfc, 0x9c, 0xc4, 0xd8, 0x0f, 0x2c, | ||||
| 	0xba, 0x81, 0xc9, 0x62, 0xb6, 0x44, 0xe5, 0xb4, 0x61, 0xb1, 0x74, 0xc8, 0x0b, 0x25, 0x1d, 0x5b, | ||||
| 	0xa6, 0x25, 0x45, 0x00, 0x43, 0xa1, 0xc3, 0x26, 0x4a, 0x9b, 0xb1, 0xcb, 0x35, 0xc8, 0xce, 0x94, | ||||
| 	0x60, 0x15, 0x93, 0x6c, 0x5f, 0x0c, 0x0b, 0x54, 0x05, 0xaf, 0x71, 0x46, 0xc0, 0xe8, 0xd4, 0x2a, | ||||
| 	0x56, 0x08, 0x8b, 0xda, 0x8b, 0xa0, 0xfd, 0xde, 0x2b, 0x9d, 0x3a, 0x52, 0xed, 0xa5, 0xa8, 0x07, | ||||
| 	0xdb, 0xef, 0x1f, 0x71, 0xa7, 0x52, 0x2d, 0x7c, 0x69, 0x91, 0x6d, 0x92, 0xcf, 0x0d, 0xd8, 0xaf, | ||||
| 	0x66, 0x4a, 0x7a, 0x97, 0x08, 0x95, 0x95, 0x16, 0x1d, 0xf7, 0x86, 0xe7, 0x2a, 0x0d, 0x40, 0x63, | ||||
| 	0x8c, 0xc6, 0x71, 0x0d, 0x76, 0x2b, 0xbf, 0x58, 0x39, 0x69, 0xb4, 0x46, 0xe9, 0x4f, 0x79, 0x6d, | ||||
| 	0x91, 0xd7, 0x55, 0xd8, 0x31, 0xa9, 0xe3, 0xb1, 0xf0, 0x82, 0x5b, 0x0c, 0x68, 0xa5, 0x0d, 0xf2, | ||||
| 	0x91, 0xd2, 0xb1, 0x19, 0xb1, 0x6d, 0x72, 0x3a, 0x1b, 0xff, 0x3b, 0x84, 0xff, 0x03, 0xd8, 0x4a, | ||||
| 	0x8c, 0x95, 0x38, 0xf9, 0xd8, 0xf0, 0xb2, 0x88, 0xc3, 0xd4, 0xe5, 0x00, 0xe5, 0x09, 0xdb, 0x0d, | ||||
| 	0xe3, 0xeb, 0x3d, 0x84, 0x7f, 0xcd, 0x00, 0x3b, 0xf9, 0x99, 0xbc, 0xc1, 0xfe, 0xf1, 0xf3, 0xc7, | ||||
| 	0xc7, 0x73, 0x8b, 0x7a, 0xed, 0xd0, 0x3e, 0x0d, 0x6b, 0x8a, 0x36, 0x00, 0x48, 0xda, 0x2b, 0xfd, | ||||
| 	0xab, 0x80, 0x7c, 0xee, 0xdf, 0xff, 0xeb, 0xfd, 0xdc, 0x80, 0xbb, 0x7f, 0x27, 0xd0, 0x47, 0x69, | ||||
| 	0xf1, 0x57, 0xd1, 0x72, 0xba, 0x98, 0xf3, 0xd3, 0x62, 0x22, 0x68, 0x9f, 0x62, 0xe1, 0xb3, 0x24, | ||||
| 	0xe9, 0xdd, 0x9a, 0xff, 0xa8, 0x3d, 0x31, 0x69, 0x8a, 0xf1, 0xb3, 0x24, 0x39, 0x2b, 0x7d, 0xef, | ||||
| 	0x53, 0xe8, 0xcc, 0x5c, 0x9f, 0xe2, 0xe8, 0x49, 0x58, 0xe6, 0xe7, 0x38, 0x0e, 0x24, 0x2b, 0xb5, | ||||
| 	0x7a, 0x5b, 0xd2, 0x88, 0x1b, 0xf5, 0x07, 0x60, 0xf6, 0xb6, 0x05, 0xb6, 0xb6, 0x7a, 0x47, 0xb0, | ||||
| 	0x77, 0xe6, 0xf5, 0x63, 0x29, 0xb1, 0xf0, 0x18, 0x9f, 0x11, 0xa6, 0xf7, 0xdb, 0xb9, 0xf9, 0x9c, | ||||
| 	0xc7, 0x15, 0x33, 0x1f, 0xeb, 0xc4, 0x04, 0x02, 0x16, 0x68, 0x9d, 0xd1, 0xa2, 0x92, 0xd1, 0x06, | ||||
| 	0x75, 0x1e, 0x01, 0xcc, 0x00, 0x5c, 0xe5, 0x25, 0xee, 0x10, 0xa8, 0x68, 0x68, 0xf1, 0x54, 0x8f, | ||||
| 	0x1d, 0x51, 0xbe, 0xf9, 0x21, 0xe5, 0x2b, 0x86, 0xaf, 0xc1, 0xa5, 0x44, 0x48, 0xec, 0x1b, 0x73, | ||||
| 	0x12, 0xea, 0x59, 0x24, 0xe4, 0x74, 0x60, 0x79, 0x6a, 0xa4, 0xb4, 0xd5, 0x1f, 0xe9, 0x3a, 0xec, | ||||
| 	0xcd, 0xc9, 0xbf, 0x36, 0x5e, 0x25, 0xe3, 0xf0, 0xe8, 0x4c, 0x24, 0xdd, 0x11, 0xff, 0x16, 0xa3, | ||||
| 	0xdb, 0x70, 0x75, 0xce, 0xed, 0x03, 0xbd, 0xe7, 0x13, 0xc1, 0x5f, 0xa9, 0x29, 0xa7, 0x1c, 0x2f, | ||||
| 	0x06, 0xa6, 0xfa, 0x91, 0x85, 0xd7, 0x32, 0x66, 0x6d, 0x8a, 0xc3, 0xa0, 0x3d, 0xa7, 0xdf, 0xce, | ||||
| 	0x07, 0x6a, 0xac, 0x52, 0xd1, 0xbb, 0xb0, 0x3e, 0xbd, 0x34, 0x79, 0x64, 0xc7, 0x4a, 0xa7, 0x2c, | ||||
| 	0xa2, 0x7b, 0x41, 0x2f, 0xeb, 0xd3, 0xf0, 0xf0, 0x05, 0xaa, 0x5a, 0xa4, 0xe0, 0x63, 0xb6, 0x16, | ||||
| 	0x5c, 0xee, 0x37, 0x1f, 0x35, 0x7e, 0x6a, 0xfc, 0xe3, 0xf7, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb8, | ||||
| 	0x55, 0x41, 0x55, 0x01, 0x0c, 0x00, 0x00, | ||||
| 	// 2325 bytes of a gzipped FileDescriptorProto | ||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0x5b, 0x77, 0x1b, 0xb7, | ||||
| 	0xd5, 0xfd, 0x98, 0x58, 0x96, 0x08, 0x51, 0xb7, 0xd1, 0x0d, 0x92, 0x7c, 0x91, 0x98, 0xaf, 0x8e, | ||||
| 	0x12, 0x27, 0x5e, 0x8e, 0x9c, 0x95, 0x36, 0xa9, 0xd7, 0x4a, 0x65, 0xb9, 0x4e, 0xb8, 0xa2, 0x0b, | ||||
| 	0x33, 0x92, 0x9c, 0x5e, 0xd2, 0xa2, 0xe0, 0xcc, 0xe1, 0x10, 0xd5, 0x10, 0x18, 0x0f, 0x30, 0x62, | ||||
| 	0xf8, 0xd6, 0xc7, 0xbe, 0xf4, 0xa9, 0x7f, 0xa5, 0x6f, 0xfd, 0x11, 0xfd, 0x4b, 0x5d, 0x38, 0xc0, | ||||
| 	0x0c, 0x87, 0x8e, 0xec, 0x5e, 0x56, 0xdf, 0x34, 0xfb, 0x6c, 0x00, 0x07, 0x38, 0x1b, 0x07, 0x9b, | ||||
| 	0x22, 0x0f, 0xb4, 0x01, 0x3e, 0x1c, 0x82, 0xd6, 0x3c, 0x01, 0xcd, 0xa2, 0x54, 0x80, 0x34, 0x1a, | ||||
| 	0xf2, 0x6b, 0xc8, 0x59, 0xaa, 0x12, 0x21, 0x1f, 0x65, 0xb9, 0x32, 0x6a, 0x9b, 0x4e, 0xf3, 0x7a, | ||||
| 	0x5c, 0x83, 0x8b, 0xb4, 0xd7, 0xc9, 0xea, 0xd1, 0x89, 0x4e, 0x8e, 0x70, 0xe4, 0xd7, 0xc0, 0x73, | ||||
| 	0xf3, 0x0c, 0xb8, 0x69, 0x7f, 0x4f, 0x76, 0x27, 0xf0, 0x39, 0x4e, 0x78, 0x21, 0x86, 0xa0, 0x0d, | ||||
| 	0x1f, 0x66, 0x21, 0xbc, 0x2a, 0x40, 0x9b, 0xe0, 0x67, 0x84, 0xba, 0x05, 0x59, 0xee, 0x10, 0x66, | ||||
| 	0x4a, 0x0a, 0x6d, 0xec, 0x36, 0xf6, 0x6f, 0x85, 0x1b, 0x2e, 0xee, 0x07, 0x54, 0x13, 0xb4, 0xff, | ||||
| 	0xd2, 0x20, 0x7b, 0x6f, 0x99, 0x5e, 0x67, 0x4a, 0x6a, 0xf8, 0xef, 0xe7, 0x0f, 0x1e, 0x91, 0x55, | ||||
| 	0x7f, 0x08, 0xd5, 0x08, 0x36, 0xd4, 0xf4, 0x1d, 0x1c, 0xb4, 0xa2, 0xa7, 0xd7, 0x3b, 0xd1, 0xed, | ||||
| 	0x3f, 0x37, 0xc8, 0x72, 0x3d, 0x9f, 0x28, 0x07, 0x13, 0x50, 0x32, 0x7b, 0x0d, 0xb9, 0x16, 0x4a, | ||||
| 	0xe2, 0x6a, 0x0b, 0x61, 0xf9, 0x19, 0xac, 0x91, 0x19, 0x9e, 0x65, 0x22, 0xc6, 0x09, 0x17, 0x42, | ||||
| 	0xf7, 0x11, 0x6c, 0x93, 0xb9, 0x18, 0xae, 0x45, 0x04, 0x22, 0xa6, 0xef, 0x62, 0xa0, 0xfa, 0xb6, | ||||
| 	0x23, 0xa4, 0x92, 0x11, 0xd0, 0x5b, 0xbb, 0x8d, 0xfd, 0xdb, 0xa1, 0xfb, 0x08, 0x02, 0x72, 0x6b, | ||||
| 	0x30, 0xe4, 0x11, 0x9d, 0xd9, 0x6d, 0xec, 0xb7, 0x42, 0xfc, 0xbb, 0xfd, 0xd7, 0x55, 0xb2, 0x34, | ||||
| 	0x49, 0xe5, 0x58, 0x25, 0x4a, 0x06, 0x1f, 0x90, 0x65, 0x2c, 0x56, 0xa4, 0x52, 0x36, 0x9d, 0xd2, | ||||
| 	0x52, 0x89, 0xbf, 0xf4, 0xa9, 0x7d, 0x43, 0xda, 0x31, 0x64, 0x39, 0x44, 0xdc, 0x40, 0xcc, 0x54, | ||||
| 	0xaf, 0x5f, 0x68, 0x53, 0xb8, 0x8f, 0x2c, 0x17, 0xd7, 0xdc, 0x00, 0x13, 0x99, 0xcf, 0xfb, 0xfe, | ||||
| 	0x84, 0x79, 0x56, 0x23, 0x76, 0x1d, 0xaf, 0x93, 0x05, 0x9b, 0x64, 0x36, 0x82, 0x34, 0x65, 0xd5, | ||||
| 	0x86, 0x6e, 0xdb, 0xcf, 0x4e, 0x1c, 0x3c, 0x20, 0x4b, 0x29, 0xd7, 0x86, 0x69, 0xd0, 0x76, 0x55, | ||||
| 	0x4b, 0xb8, 0x85, 0x84, 0x05, 0x0b, 0x9f, 0x3b, 0xb4, 0x13, 0x07, 0x9f, 0x12, 0x5f, 0x21, 0x96, | ||||
| 	0xf1, 0xe8, 0x8a, 0x27, 0x50, 0xa5, 0x3f, 0x83, 0xf4, 0x35, 0x17, 0xed, 0xba, 0x60, 0xb9, 0x87, | ||||
| 	0xf7, 0xc9, 0x92, 0x1f, 0x95, 0x72, 0x99, 0x14, 0x3c, 0x01, 0x7a, 0x7b, 0xb7, 0xb1, 0xdf, 0x0c, | ||||
| 	0x17, 0x1d, 0x7c, 0xec, 0xd1, 0xe0, 0xff, 0x89, 0x47, 0x98, 0xd2, 0xcc, 0x8c, 0x33, 0xa0, 0xb3, | ||||
| 	0x38, 0x6d, 0xcb, 0xa1, 0x67, 0xfa, 0x62, 0x9c, 0x41, 0xf0, 0x25, 0xa1, 0x7a, 0xa0, 0x8a, 0x34, | ||||
| 	0x66, 0x39, 0x0c, 0x61, 0xd8, 0x83, 0x9c, 0x65, 0x5c, 0xeb, 0x91, 0xca, 0x63, 0x3a, 0xb7, 0xdb, | ||||
| 	0xd8, 0x9f, 0xfb, 0x62, 0xa6, 0xcf, 0x53, 0x0d, 0xe1, 0x86, 0xa3, 0x85, 0x9e, 0xd5, 0xf5, 0xa4, | ||||
| 	0x60, 0x8f, 0xb4, 0x46, 0x42, 0x4e, 0x72, 0x6f, 0x62, 0x32, 0xf3, 0x16, 0x2b, 0x53, 0x7e, 0x8f, | ||||
| 	0x2c, 0xd4, 0x8e, 0xfd, 0x93, 0xc7, 0x94, 0xb8, 0x44, 0x26, 0xe0, 0x27, 0x8f, 0x83, 0x67, 0x64, | ||||
| 	0x1d, 0x0b, 0xf2, 0xa3, 0x72, 0xcc, 0xef, 0x36, 0xf6, 0xe7, 0x0f, 0x16, 0x1f, 0xd9, 0xba, 0x77, | ||||
| 	0xba, 0x87, 0x71, 0x9c, 0x83, 0xd6, 0xe1, 0xea, 0x84, 0x3c, 0x29, 0xc9, 0x63, 0xb2, 0x56, 0x5b, | ||||
| 	0x28, 0x2b, 0x7a, 0xa9, 0x88, 0xec, 0x14, 0x6b, 0xb8, 0x5e, 0x30, 0x89, 0x75, 0x31, 0xd4, 0xc9, | ||||
| 	0x82, 0x1d, 0xd2, 0x7c, 0xa5, 0x34, 0x4b, 0xe1, 0x1a, 0x52, 0xba, 0xee, 0x74, 0xf9, 0x4a, 0xe9, | ||||
| 	0x63, 0xfb, 0x1d, 0xfc, 0xb4, 0xba, 0x62, 0xba, 0xc8, 0xb2, 0x54, 0x40, 0xcc, 0xb0, 0x53, 0xd8, | ||||
| 	0x8a, 0x6e, 0xa0, 0x54, 0xd7, 0x5d, 0xfc, 0xdc, 0x87, 0xcf, 0x6d, 0xb4, 0x13, 0x07, 0x0f, 0x49, | ||||
| 	0x73, 0xb2, 0xf8, 0xe6, 0x8d, 0xf9, 0xcf, 0x65, 0x65, 0x0a, 0x77, 0x09, 0x19, 0xf2, 0x68, 0x60, | ||||
| 	0xcf, 0x50, 0xc4, 0xf4, 0x1e, 0xaa, 0xbd, 0xe9, 0x11, 0x54, 0xd3, 0x42, 0xca, 0x0b, 0x19, 0x0d, | ||||
| 	0xec, 0x7d, 0xb5, 0x55, 0xbc, 0x6f, 0xb3, 0xfc, 0xa2, 0xf1, 0x38, 0x6c, 0x95, 0x38, 0x16, 0x72, | ||||
| 	0x9b, 0xcc, 0x16, 0x82, 0x0d, 0x55, 0x0c, 0x74, 0xb7, 0x64, 0xdc, 0x2e, 0xc4, 0x89, 0x8a, 0x21, | ||||
| 	0xb8, 0x47, 0x9a, 0xd1, 0x80, 0x1b, 0x17, 0xdd, 0x2b, 0xa3, 0x73, 0x16, 0xc3, 0xf8, 0x47, 0x24, | ||||
| 	0xc0, 0x8d, 0x1d, 0x30, 0x5e, 0x98, 0x01, 0x33, 0x22, 0xba, 0x02, 0x43, 0x3f, 0xc0, 0x54, 0x96, | ||||
| 	0x5d, 0xe4, 0xb0, 0x30, 0x83, 0x0b, 0xc4, 0x6d, 0x39, 0x61, 0xc8, 0x45, 0xca, 0xb8, 0xdb, 0x0b, | ||||
| 	0xfd, 0x10, 0x4b, 0xde, 0x42, 0xd0, 0xef, 0xcf, 0xb6, 0xa7, 0xdc, 0xb6, 0x97, 0x27, 0x07, 0x8c, | ||||
| 	0x47, 0x91, 0x2a, 0xa4, 0x61, 0x51, 0x0e, 0xdc, 0x58, 0x89, 0x3c, 0xdc, 0x6d, 0xec, 0xcf, 0x86, | ||||
| 	0x1b, 0x3e, 0x7e, 0xe8, 0xc2, 0x47, 0x3e, 0x6a, 0x05, 0x55, 0x8e, 0x90, 0x7c, 0x08, 0xf4, 0xc0, | ||||
| 	0x09, 0xca, 0x63, 0xa7, 0x7c, 0x68, 0xf7, 0x3a, 0x57, 0x89, 0xf4, 0x09, 0x86, 0xab, 0xef, 0xe0, | ||||
| 	0x43, 0xb2, 0x92, 0xf0, 0x21, 0xb0, 0xb2, 0xc5, 0xa9, 0x2b, 0x90, 0xf4, 0x53, 0x24, 0x2d, 0xd9, | ||||
| 	0x80, 0xef, 0xa7, 0x16, 0xb6, 0xd5, 0xc7, 0x77, 0x80, 0x5d, 0xc1, 0x98, 0x3e, 0x75, 0x13, 0x21, | ||||
| 	0xf0, 0x0d, 0x8c, 0x83, 0x17, 0xe4, 0xce, 0x88, 0x6b, 0x16, 0x29, 0x79, 0x0d, 0xb9, 0xd5, 0x53, | ||||
| 	0x4d, 0x5a, 0x43, 0x9d, 0xd0, 0x17, 0xf5, 0xdb, 0xb1, 0x35, 0xe2, 0xfa, 0xa8, 0x64, 0x3e, 0xaf, | ||||
| 	0x88, 0x27, 0x3a, 0x09, 0x7e, 0x41, 0xee, 0x72, 0xa9, 0x24, 0x2b, 0xb4, 0x4d, 0x87, 0xe7, 0x09, | ||||
| 	0x18, 0x36, 0xb5, 0xc1, 0x2e, 0x2e, 0xbc, 0x65, 0x49, 0x97, 0x1a, 0xf2, 0x0b, 0xa4, 0x1c, 0xd6, | ||||
| 	0xb6, 0xfb, 0x84, 0x6c, 0xe4, 0xa0, 0x55, 0x7a, 0x0d, 0xb1, 0x9b, 0xa5, 0x52, 0xe1, 0xb7, 0xa8, | ||||
| 	0xc2, 0xd5, 0x32, 0x6a, 0x87, 0x97, 0x1a, 0xfc, 0x98, 0x04, 0x90, 0x83, 0x2e, 0x52, 0xdb, 0x88, | ||||
| 	0xa4, 0xc9, 0xc7, 0x7d, 0x91, 0x02, 0x0d, 0x77, 0x1b, 0xfb, 0x33, 0xe1, 0x8a, 0x8f, 0x9c, 0x57, | ||||
| 	0x81, 0xe0, 0x27, 0x64, 0x51, 0x0f, 0x78, 0x9d, 0x7a, 0x8e, 0xe5, 0x5f, 0xd0, 0x03, 0x5e, 0xa3, | ||||
| 	0xed, 0x90, 0x26, 0x4a, 0x24, 0xb2, 0x4a, 0xba, 0x70, 0x27, 0x66, 0x81, 0x23, 0x2b, 0xa3, 0x2d, | ||||
| 	0x32, 0xa7, 0x4c, 0xe6, 0x54, 0x7a, 0x89, 0x0b, 0xcd, 0x2a, 0x93, 0xa1, 0x3a, 0x77, 0x48, 0xd3, | ||||
| 	0x86, 0xae, 0x79, 0x5a, 0x00, 0x7d, 0xe9, 0xee, 0x99, 0x32, 0xd9, 0x4b, 0xfb, 0x6d, 0xd7, 0xb6, | ||||
| 	0x41, 0x11, 0x83, 0x34, 0xa2, 0x2f, 0x20, 0xa7, 0xdf, 0xe1, 0xcc, 0x0b, 0xca, 0x64, 0x9d, 0x0a, | ||||
| 	0x0c, 0x0e, 0xc8, 0xba, 0x57, 0xa9, 0x13, 0x68, 0xf9, 0xf0, 0xd1, 0x5f, 0xd9, 0x4a, 0x84, 0xab, | ||||
| 	0x2e, 0xe8, 0x44, 0x5a, 0xbe, 0xc2, 0x0f, 0xc8, 0x92, 0x56, 0x72, 0xcc, 0x32, 0x2d, 0x4b, 0x59, | ||||
| 	0xff, 0xc6, 0xef, 0x4b, 0xc9, 0x71, 0x57, 0x4b, 0xaf, 0xe9, 0x8f, 0xc9, 0x6a, 0xc5, 0xb3, 0xca, | ||||
| 	0x11, 0x11, 0xde, 0xc6, 0xdf, 0x62, 0x1e, 0xcb, 0x9e, 0x7b, 0xee, 0x02, 0x9d, 0x38, 0xf8, 0x35, | ||||
| 	0x79, 0x1f, 0xd5, 0x0c, 0x4c, 0xc2, 0x08, 0x07, 0xa5, 0x42, 0x5e, 0x41, 0x5c, 0x15, 0x56, 0xf4, | ||||
| 	0x99, 0x04, 0x88, 0x21, 0xa6, 0xdf, 0xd7, 0x65, 0xb2, 0xe7, 0x46, 0x9d, 0xc2, 0xa8, 0xab, 0xe5, | ||||
| 	0x31, 0x0e, 0xf1, 0x85, 0xee, 0xf4, 0x4f, 0x91, 0x1f, 0xb4, 0xc9, 0x42, 0x95, 0x09, 0xca, 0xe3, | ||||
| 	0x77, 0x4e, 0xff, 0x3e, 0x07, 0x14, 0xc4, 0x43, 0x12, 0xd4, 0x35, 0xce, 0x33, 0x7b, 0x78, 0xf4, | ||||
| 	0xf7, 0x78, 0xe4, 0x35, 0x91, 0x1f, 0x66, 0x59, 0x27, 0x0e, 0x3a, 0x64, 0x0f, 0x4f, 0x26, 0x29, | ||||
| 	0x78, 0x1e, 0xb3, 0x58, 0xa1, 0x63, 0xf0, 0xad, 0x3e, 0x52, 0xc3, 0xac, 0x30, 0x90, 0x53, 0x86, | ||||
| 	0x47, 0x78, 0x6f, 0x42, 0x7c, 0xae, 0xac, 0x73, 0x70, 0xb4, 0x23, 0xcf, 0xb2, 0x57, 0xb3, 0x6c, | ||||
| 	0x55, 0x98, 0xda, 0x1f, 0x5c, 0x6a, 0x1e, 0xc3, 0xd4, 0x3e, 0x23, 0x9b, 0x75, 0x0a, 0xea, 0x35, | ||||
| 	0x1a, 0x28, 0x0d, 0x92, 0x72, 0x64, 0xaf, 0xd7, 0xd8, 0x97, 0x55, 0xd0, 0xbe, 0xe2, 0x78, 0x0e, | ||||
| 	0xf9, 0x98, 0xa9, 0x6b, 0xc8, 0x73, 0x11, 0x03, 0xed, 0xb9, 0x5b, 0xeb, 0xf1, 0x33, 0x0f, 0x07, | ||||
| 	0xbb, 0xa4, 0x25, 0xb4, 0xbf, 0x03, 0x3d, 0xf5, 0x03, 0x8d, 0x30, 0x77, 0x22, 0x34, 0x4a, 0xff, | ||||
| 	0x99, 0xfa, 0xc1, 0xf6, 0x33, 0xdf, 0xb8, 0x85, 0xd4, 0x86, 0x4b, 0x57, 0xcc, 0x18, 0x0d, 0xce, | ||||
| 	0xb2, 0x8b, 0x74, 0x7c, 0xc0, 0xbd, 0xd7, 0x66, 0xa4, 0x58, 0x9f, 0x47, 0x46, 0xe5, 0x4e, 0xd9, | ||||
| 	0xe0, 0xf4, 0x67, 0x46, 0xea, 0x05, 0xa2, 0x28, 0xef, 0x2f, 0xc9, 0x1d, 0xfb, 0x0e, 0xa8, 0xdc, | ||||
| 	0x68, 0x96, 0xdb, 0xda, 0xa7, 0x62, 0x28, 0xec, 0x61, 0x3a, 0x47, 0x46, 0xfb, 0x98, 0xc7, 0x56, | ||||
| 	0xc9, 0x09, 0xb9, 0x81, 0x63, 0xcb, 0xa8, 0x2c, 0xdb, 0x03, 0xb2, 0x34, 0x82, 0x9e, 0xb5, 0x9e, | ||||
| 	0x4a, 0x32, 0xe7, 0x78, 0x12, 0xb7, 0xd0, 0x08, 0x7a, 0x68, 0x66, 0x4e, 0xd1, 0xf9, 0xbc, 0x4f, | ||||
| 	0x96, 0xb2, 0x5c, 0xa8, 0x5c, 0x98, 0x31, 0xcb, 0x81, 0x6b, 0x25, 0xe9, 0x00, 0x6b, 0xbb, 0x58, | ||||
| 	0xc2, 0x21, 0xa2, 0xc1, 0x57, 0x64, 0xc3, 0x16, 0x28, 0x8e, 0x21, 0x66, 0xe5, 0x4b, 0x85, 0xf6, | ||||
| 	0x8c, 0x0a, 0x7c, 0x74, 0x56, 0x1e, 0xbd, 0xee, 0xdb, 0xc2, 0xb5, 0x72, 0xc0, 0x94, 0x9b, 0x7b, | ||||
| 	0x4a, 0xb6, 0x63, 0xa1, 0x79, 0x2f, 0x05, 0x96, 0xf1, 0xdc, 0x48, 0x2b, 0xaa, 0xc2, 0xa8, 0x24, | ||||
| 	0xe7, 0xd2, 0x68, 0xfa, 0x47, 0xdc, 0x18, 0xf5, 0x8c, 0xae, 0x23, 0x1c, 0x56, 0xf1, 0xf6, 0xdf, | ||||
| 	0x9a, 0x64, 0xf3, 0x35, 0x57, 0x56, 0xed, 0x79, 0x87, 0xcc, 0xfa, 0x66, 0x83, 0xa6, 0x6c, 0xe6, | ||||
| 	0x8b, 0xc6, 0x41, 0x58, 0x22, 0xb6, 0x35, 0xaa, 0xc2, 0x30, 0xd5, 0x67, 0x28, 0xe7, 0x81, 0x35, | ||||
| 	0xd8, 0x3d, 0xe0, 0xb8, 0x0b, 0x25, 0x63, 0xe7, 0x49, 0x67, 0xc2, 0x2d, 0x55, 0x98, 0xb3, 0xfe, | ||||
| 	0x57, 0x7c, 0x08, 0x5f, 0x97, 0x8c, 0x73, 0x47, 0x08, 0x3e, 0x27, 0x5b, 0x42, 0xbe, 0x69, 0xf4, | ||||
| 	0xbb, 0x38, 0x7a, 0x43, 0xc8, 0x1b, 0x87, 0xbe, 0xc9, 0x2c, 0xdc, 0x7a, 0xa3, 0x59, 0x78, 0x44, | ||||
| 	0x56, 0xcb, 0x37, 0xad, 0x66, 0xa0, 0xd1, 0xad, 0xcd, 0x86, 0x2b, 0x3e, 0x34, 0xf1, 0xeb, 0xf6, | ||||
| 	0xa1, 0x2c, 0xfb, 0x41, 0x3f, 0xe5, 0x89, 0x46, 0xa3, 0xb6, 0x10, 0x96, 0xcf, 0xdb, 0x0b, 0x8b, | ||||
| 	0xd5, 0x6d, 0xe4, 0xec, 0x94, 0x8d, 0xdc, 0x23, 0xee, 0x45, 0x65, 0xb1, 0x1a, 0x72, 0x21, 0xd1, | ||||
| 	0x8d, 0x35, 0xc3, 0x79, 0xc4, 0x9e, 0x23, 0x64, 0x17, 0x98, 0xea, 0x88, 0x68, 0xbe, 0x5a, 0x61, | ||||
| 	0xab, 0xde, 0x09, 0xed, 0xcd, 0x2a, 0x1f, 0x02, 0xf8, 0xc1, 0x80, 0xb4, 0x4d, 0x89, 0xb8, 0x56, | ||||
| 	0xe1, 0xf1, 0x5f, 0x7a, 0x38, 0x38, 0x22, 0xf7, 0x46, 0xd0, 0xe3, 0x99, 0x40, 0x1f, 0x60, 0x1b, | ||||
| 	0xaf, 0x3d, 0x00, 0xf7, 0xe6, 0x38, 0xbd, 0xce, 0x63, 0x12, 0x3b, 0x8e, 0x75, 0x58, 0x23, 0xd9, | ||||
| 	0xab, 0xec, 0xd4, 0xfb, 0x84, 0x6c, 0xf8, 0x0d, 0xb1, 0x4c, 0xc8, 0x84, 0x99, 0x41, 0x0e, 0x7a, | ||||
| 	0xa0, 0xd2, 0x98, 0xb6, 0x70, 0x7f, 0xab, 0x6e, 0x7f, 0x5d, 0x21, 0x93, 0x8b, 0x32, 0x64, 0x8f, | ||||
| 	0xb6, 0x56, 0x8c, 0x42, 0x03, 0xcb, 0x44, 0xa4, 0xe9, 0x02, 0x2a, 0x6f, 0x65, 0x12, 0xba, 0xd4, | ||||
| 	0xd0, 0x15, 0x91, 0xb6, 0xa6, 0xe9, 0x9a, 0x4b, 0x7b, 0x41, 0x8a, 0x3c, 0xa5, 0x8b, 0x98, 0x55, | ||||
| 	0xd3, 0x21, 0x97, 0x79, 0x3a, 0x6d, 0xc0, 0x96, 0xfe, 0x85, 0x01, 0xfb, 0x8c, 0x6c, 0xde, 0x68, | ||||
| 	0xf3, 0x44, 0x8c, 0xc6, 0xf1, 0x66, 0x97, 0x27, 0xb0, 0x6f, 0x88, 0x8c, 0x95, 0x5d, 0x0b, 0xfb, | ||||
| 	0xc6, 0xba, 0xbb, 0xce, 0x22, 0x3b, 0x72, 0x28, 0xf6, 0x8d, 0x87, 0x64, 0x25, 0xe3, 0x39, 0x48, | ||||
| 	0xc3, 0x53, 0xa6, 0xc1, 0x18, 0x21, 0x13, 0x8d, 0xfe, 0xb1, 0x15, 0x2e, 0x97, 0x81, 0x73, 0x8f, | ||||
| 	0xdb, 0x9b, 0xf8, 0x3a, 0x99, 0x69, 0x91, 0x48, 0x6e, 0x8a, 0x1c, 0xd0, 0x4b, 0xb6, 0x42, 0xfa, | ||||
| 	0xda, 0xa8, 0xf3, 0x32, 0x6e, 0x0b, 0xe8, 0xf4, 0x86, 0x2e, 0xa6, 0xcf, 0x45, 0x5a, 0xe4, 0xa0, | ||||
| 	0x99, 0x51, 0x6c, 0x28, 0x12, 0xdb, 0xb3, 0x28, 0xc5, 0xca, 0xef, 0x20, 0xeb, 0xb8, 0x4e, 0xba, | ||||
| 	0x50, 0x27, 0x8e, 0x62, 0xfb, 0x9c, 0x9b, 0x24, 0x16, 0x3a, 0x52, 0x52, 0x42, 0x64, 0xa6, 0xa6, | ||||
| 	0xd8, 0x72, 0x97, 0x12, 0x39, 0xcf, 0x27, 0x94, 0xc9, 0x04, 0x4f, 0xc9, 0x8e, 0x4a, 0x34, 0x8b, | ||||
| 	0xb9, 0xe1, 0x2c, 0x07, 0xdb, 0x0c, 0xf1, 0xa2, 0xb0, 0x91, 0x90, 0xb1, 0x1a, 0xd1, 0x6d, 0x1c, | ||||
| 	0xbf, 0xa9, 0x12, 0xfd, 0x9c, 0x1b, 0x1e, 0x22, 0xc1, 0xde, 0x97, 0xef, 0x30, 0xfc, 0x86, 0xe6, | ||||
| 	0xbd, 0xf3, 0x86, 0xe6, 0xfd, 0x39, 0xd9, 0xea, 0xab, 0x3c, 0x82, 0xb2, 0xff, 0x15, 0x59, 0x6c, | ||||
| 	0x25, 0x1b, 0x0d, 0x20, 0xba, 0xa2, 0x77, 0x50, 0x3e, 0x1b, 0x48, 0x70, 0xcd, 0xe9, 0x12, 0xc3, | ||||
| 	0x47, 0x36, 0xda, 0xfe, 0x96, 0x7c, 0x34, 0xe9, 0x5a, 0xde, 0x30, 0x7c, 0x07, 0xbd, 0xc3, 0x6e, | ||||
| 	0xe7, 0x66, 0x61, 0xef, 0x11, 0x82, 0x6e, 0xd2, 0x19, 0x1c, 0xd7, 0xcd, 0xde, 0xf9, 0xf8, 0x93, | ||||
| 	0xb0, 0x89, 0xa8, 0xb5, 0x39, 0xed, 0xbf, 0x37, 0xc8, 0xa7, 0xff, 0xc9, 0x9c, 0xff, 0x5e, 0x9b, | ||||
| 	0xfc, 0x9f, 0x5c, 0xcb, 0xe9, 0xec, 0xdf, 0xbd, 0x29, 0xfb, 0xa0, 0xfe, 0x3b, 0xff, 0x58, 0x25, | ||||
| 	0x67, 0xfd, 0x7e, 0xfb, 0xa0, 0xfe, 0x1f, 0x90, 0x63, 0x95, 0x24, 0x10, 0x9f, 0xf5, 0xfb, 0x6f, | ||||
| 	0xcd, 0xb7, 0xfd, 0x2d, 0x59, 0x9f, 0x8c, 0x39, 0x85, 0xd1, 0x71, 0x69, 0xa9, 0x77, 0x48, 0xb3, | ||||
| 	0x90, 0xe2, 0x55, 0x81, 0x15, 0x75, 0xbf, 0xd1, 0xe7, 0x1c, 0xd0, 0x89, 0xa7, 0xcd, 0xf8, 0x3b, | ||||
| 	0xd3, 0x66, 0xbc, 0xfd, 0x94, 0xdc, 0xbd, 0x71, 0xca, 0xc3, 0x28, 0x82, 0xcc, 0x40, 0xfc, 0xd6, | ||||
| 	0xa9, 0xdb, 0xff, 0xb8, 0x55, 0xcf, 0xa8, 0x74, 0x5c, 0xb2, 0xaf, 0x6c, 0x93, 0xcd, 0x20, 0xd7, | ||||
| 	0x4a, 0x72, 0xe7, 0x68, 0x1a, 0xae, 0xc9, 0x7a, 0x0c, 0x1d, 0xcd, 0x5d, 0x42, 0x26, 0xd7, 0xdc, | ||||
| 	0x27, 0xd6, 0xac, 0x6e, 0x38, 0xfe, 0x8a, 0xc7, 0xdb, 0x82, 0xb5, 0x89, 0x2b, 0x4b, 0xa5, 0xf1, | ||||
| 	0x5d, 0x98, 0x09, 0xd7, 0x30, 0x8a, 0x35, 0x89, 0x4b, 0x23, 0xa5, 0x7f, 0xfc, 0x34, 0xcc, 0xde, | ||||
| 	0xf0, 0x34, 0xdc, 0x27, 0xf3, 0x7d, 0x1e, 0x41, 0x4f, 0xa9, 0x2b, 0xbb, 0xab, 0x39, 0xbc, 0x02, | ||||
| 	0xa4, 0x84, 0x3a, 0xb1, 0x9d, 0xa5, 0x22, 0x60, 0xfa, 0xee, 0xc7, 0x77, 0xab, 0x04, 0x31, 0xff, | ||||
| 	0x67, 0xe4, 0x6e, 0xcd, 0xff, 0x49, 0x65, 0x44, 0x7f, 0x6c, 0x6d, 0xab, 0xf7, 0x61, 0x1a, 0xbb, | ||||
| 	0xe7, 0x5c, 0xb8, 0x33, 0x21, 0x9d, 0x22, 0xe7, 0x74, 0x42, 0x09, 0x8e, 0xc9, 0x7b, 0xb5, 0x39, | ||||
| 	0x7e, 0x64, 0xf0, 0x98, 0x77, 0x78, 0x4b, 0xb8, 0xfc, 0xfd, 0x09, 0xf5, 0x64, 0xda, 0xeb, 0x1d, | ||||
| 	0x39, 0xaf, 0xf7, 0x21, 0x59, 0x11, 0x9a, 0x65, 0x03, 0xe5, 0xfe, 0x6d, 0x60, 0xdd, 0x7d, 0x4c, | ||||
| 	0x97, 0x31, 0x8b, 0x25, 0xa1, 0xbb, 0x16, 0x7f, 0xe9, 0xe1, 0x60, 0x9f, 0x2c, 0xd7, 0xcc, 0x99, | ||||
| 	0x36, 0xb6, 0x01, 0xad, 0xe0, 0x59, 0x2d, 0x56, 0xee, 0xec, 0xdc, 0xa2, 0xf6, 0x3d, 0xaf, 0x66, | ||||
| 	0xf5, 0x3f, 0x25, 0xc6, 0x42, 0x26, 0x34, 0xc0, 0x89, 0x03, 0x3f, 0x71, 0x67, 0x12, 0x41, 0xf3, | ||||
| 	0x50, 0x8e, 0xb0, 0x6e, 0xdd, 0xf6, 0xda, 0x1c, 0x30, 0xa3, 0x31, 0x5d, 0x75, 0xbd, 0xc3, 0x0f, | ||||
| 	0x3b, 0x75, 0xe1, 0xd0, 0x47, 0xdb, 0x9f, 0x91, 0xed, 0x89, 0xa0, 0x8e, 0x06, 0x3c, 0x4d, 0x41, | ||||
| 	0x26, 0x50, 0xfe, 0xea, 0xa0, 0x64, 0xb6, 0x7c, 0x41, 0x1a, 0xf8, 0x82, 0x94, 0x9f, 0xed, 0x9f, | ||||
| 	0x93, 0x9d, 0x1b, 0xc7, 0xf9, 0x36, 0x70, 0x07, 0x7f, 0xa8, 0x3b, 0xd0, 0x0f, 0x9d, 0x00, 0xcf, | ||||
| 	0x66, 0xbe, 0x6e, 0xfc, 0xa9, 0xf1, 0x7f, 0xff, 0x0c, 0x00, 0x00, 0xff, 0xff, 0xa0, 0x4a, 0xca, | ||||
| 	0x5a, 0xd7, 0x14, 0x00, 0x00, | ||||
| } | ||||
|   | ||||
							
								
								
									
										64
									
								
								vendor/github.com/Philipp15b/go-steam/protocol/protobuf/client_site_license.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										64
									
								
								vendor/github.com/Philipp15b/go-steam/protocol/protobuf/client_site_license.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -21,9 +21,9 @@ var _ = math.Inf | ||||
| const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package | ||||
|  | ||||
| type CMsgClientSiteInfo struct { | ||||
| 	SiteId                 *uint64  `protobuf:"varint,1,opt,name=site_id" json:"site_id,omitempty"` | ||||
| 	SiteName               *string  `protobuf:"bytes,2,opt,name=site_name" json:"site_name,omitempty"` | ||||
| 	AllowCachedCredentials *bool    `protobuf:"varint,3,opt,name=allow_cached_credentials" json:"allow_cached_credentials,omitempty"` | ||||
| 	SiteId                 *uint64  `protobuf:"varint,1,opt,name=site_id,json=siteId" json:"site_id,omitempty"` | ||||
| 	SiteName               *string  `protobuf:"bytes,2,opt,name=site_name,json=siteName" json:"site_name,omitempty"` | ||||
| 	AllowCachedCredentials *bool    `protobuf:"varint,3,opt,name=allow_cached_credentials,json=allowCachedCredentials" json:"allow_cached_credentials,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral   struct{} `json:"-"` | ||||
| 	XXX_unrecognized       []byte   `json:"-"` | ||||
| 	XXX_sizecache          int32    `json:"-"` | ||||
| @@ -283,11 +283,11 @@ func (m *CMsgClientSiteLicenseGetContentCacheInfo) XXX_DiscardUnknown() { | ||||
| var xxx_messageInfo_CMsgClientSiteLicenseGetContentCacheInfo proto.InternalMessageInfo | ||||
|  | ||||
| type CMsgClientSiteLicenseGetContentCacheInfoResponse struct { | ||||
| 	UseCache             *bool    `protobuf:"varint,1,opt,name=use_cache" json:"use_cache,omitempty"` | ||||
| 	Ipv4Address          *uint32  `protobuf:"varint,2,opt,name=ipv4_address" json:"ipv4_address,omitempty"` | ||||
| 	PortNumber           *uint32  `protobuf:"varint,3,opt,name=port_number" json:"port_number,omitempty"` | ||||
| 	P2PGroup             *uint32  `protobuf:"varint,4,opt,name=p2p_group" json:"p2p_group,omitempty"` | ||||
| 	IpAddress            *string  `protobuf:"bytes,5,opt,name=ip_address" json:"ip_address,omitempty"` | ||||
| 	UseCache             *bool    `protobuf:"varint,1,opt,name=use_cache,json=useCache" json:"use_cache,omitempty"` | ||||
| 	Ipv4Address          *uint32  `protobuf:"varint,2,opt,name=ipv4_address,json=ipv4Address" json:"ipv4_address,omitempty"` | ||||
| 	PortNumber           *uint32  `protobuf:"varint,3,opt,name=port_number,json=portNumber" json:"port_number,omitempty"` | ||||
| 	P2PGroup             *uint32  `protobuf:"varint,4,opt,name=p2p_group,json=p2pGroup" json:"p2p_group,omitempty"` | ||||
| 	IpAddress            *string  `protobuf:"bytes,5,opt,name=ip_address,json=ipAddress" json:"ip_address,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| @@ -372,26 +372,30 @@ func init() { | ||||
| } | ||||
|  | ||||
| var fileDescriptor_0a32817a56a37a6e = []byte{ | ||||
| 	// 335 bytes of a gzipped FileDescriptorProto | ||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0x41, 0x4b, 0xfb, 0x40, | ||||
| 	0x14, 0xc4, 0xff, 0xfb, 0xb7, 0xa1, 0xed, 0xd3, 0x20, 0x5d, 0x3d, 0x04, 0x41, 0x08, 0x81, 0x4a, | ||||
| 	0xf0, 0x50, 0xa4, 0x08, 0x82, 0x9e, 0x34, 0x07, 0x15, 0xf4, 0x62, 0x6f, 0x5e, 0xc2, 0x36, 0x79, | ||||
| 	0xb6, 0x8b, 0x9b, 0xdd, 0x25, 0x6f, 0x53, 0xaf, 0x7e, 0x0b, 0xbf, 0xae, 0x64, 0x5b, 0x0a, 0x15, | ||||
| 	0x2d, 0xbd, 0xee, 0xce, 0x6f, 0x66, 0x98, 0x07, 0x43, 0x72, 0x28, 0xaa, 0x0a, 0x89, 0xc4, 0x0c, | ||||
| 	0x29, 0x27, 0xe9, 0x50, 0xc9, 0x02, 0x35, 0x61, 0xa1, 0x24, 0x6a, 0x37, 0xb2, 0xb5, 0x71, 0xe6, | ||||
| 	0x24, 0xda, 0x94, 0x4d, 0x05, 0xe1, 0xf2, 0x27, 0x79, 0x05, 0x9e, 0x3d, 0xd3, 0x2c, 0xf3, 0xea, | ||||
| 	0x89, 0x74, 0xf8, 0xa8, 0xdf, 0x0c, 0x3f, 0x84, 0x6e, 0x6b, 0x95, 0xcb, 0x32, 0x62, 0x31, 0x4b, | ||||
| 	0x3b, 0x7c, 0x00, 0x7d, 0xff, 0xa0, 0x45, 0x85, 0xd1, 0xff, 0x98, 0xa5, 0x7d, 0x1e, 0x43, 0x24, | ||||
| 	0x94, 0x32, 0x1f, 0x79, 0x21, 0x8a, 0x39, 0x96, 0x79, 0x51, 0x63, 0x89, 0xda, 0x49, 0xa1, 0x28, | ||||
| 	0xda, 0x8b, 0x59, 0xda, 0x4b, 0x46, 0x70, 0xba, 0xe9, 0xfd, 0xb4, 0xac, 0x96, 0xcd, 0xb1, 0x78, | ||||
| 	0x37, 0x8d, 0xe3, 0x21, 0x04, 0xc2, 0xda, 0x55, 0x48, 0x98, 0xdc, 0xc0, 0x70, 0xab, 0xfe, 0x05, | ||||
| 	0xc9, 0x1a, 0x4d, 0xc8, 0x39, 0x74, 0xb1, 0x46, 0x6a, 0x94, 0xf3, 0x64, 0x70, 0xcd, 0xc6, 0xc9, | ||||
| 	0x15, 0x9c, 0xfd, 0x0a, 0xdf, 0xa3, 0xbb, 0x5d, 0x08, 0xa9, 0xc4, 0x54, 0xe1, 0x04, 0x85, 0xa3, | ||||
| 	0x9f, 0xa9, 0x13, 0x18, 0xed, 0x06, 0x6e, 0x8b, 0x6f, 0x4d, 0xa9, 0x15, 0xf9, 0x71, 0xc2, 0xe4, | ||||
| 	0x1c, 0xd2, 0xbf, 0x4c, 0x33, 0xa3, 0x1d, 0x6a, 0x97, 0xb5, 0xab, 0xb5, 0x63, 0x27, 0x5f, 0x0c, | ||||
| 	0x2e, 0x76, 0x15, 0xaf, 0x3b, 0x0c, 0xa0, 0xdf, 0x10, 0x2e, 0xb7, 0xf7, 0x2d, 0x7a, 0xfc, 0x18, | ||||
| 	0x0e, 0xa4, 0x5d, 0x5c, 0xe6, 0xa2, 0x2c, 0x6b, 0xa4, 0x55, 0x13, 0x7e, 0x04, 0xfb, 0xd6, 0xd4, | ||||
| 	0x2e, 0xd7, 0x4d, 0x35, 0xc5, 0xda, 0x5f, 0x26, 0x6c, 0x69, 0x3b, 0xb6, 0xf9, 0xac, 0x36, 0x8d, | ||||
| 	0x8d, 0x3a, 0xfe, 0x89, 0x03, 0x48, 0xbb, 0x66, 0x83, 0xf6, 0xc4, 0x77, 0xc1, 0x03, 0xfb, 0x64, | ||||
| 	0xff, 0xbe, 0x03, 0x00, 0x00, 0xff, 0xff, 0x09, 0x2f, 0x9f, 0xe9, 0x65, 0x02, 0x00, 0x00, | ||||
| 	// 393 bytes of a gzipped FileDescriptorProto | ||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x52, 0x4f, 0x8b, 0xd3, 0x40, | ||||
| 	0x14, 0x77, 0x74, 0xe3, 0x26, 0x6f, 0xed, 0x65, 0x10, 0x0d, 0x2e, 0x8b, 0x35, 0xb0, 0x12, 0x3c, | ||||
| 	0x2c, 0x52, 0x14, 0xc4, 0x83, 0xb0, 0x46, 0x58, 0x17, 0xb4, 0x87, 0xe9, 0x07, 0x08, 0xd3, 0xe4, | ||||
| 	0xd9, 0x0e, 0x4e, 0x66, 0x86, 0xbc, 0x49, 0xbd, 0x7a, 0xf0, 0xfb, 0xf9, 0x95, 0x64, 0x26, 0xad, | ||||
| 	0x5a, 0xb0, 0xd2, 0xe3, 0xef, 0xcf, 0xfc, 0xde, 0x2f, 0xef, 0x05, 0x2e, 0xc9, 0xa3, 0xec, 0x3a, | ||||
| 	0x24, 0x92, 0x2b, 0xa4, 0x9a, 0x94, 0x47, 0xad, 0x1a, 0x34, 0x84, 0x8d, 0x56, 0x68, 0xfc, 0x95, | ||||
| 	0xeb, 0xad, 0xb7, 0x4f, 0xf2, 0x7d, 0xdb, 0x52, 0x12, 0x8e, 0x4a, 0xf1, 0x83, 0x01, 0xaf, 0x3e, | ||||
| 	0xd3, 0xaa, 0x8a, 0xf6, 0x85, 0xf2, 0x78, 0x6b, 0xbe, 0x58, 0xfe, 0x18, 0x4e, 0x43, 0x56, 0xad, | ||||
| 	0xda, 0x9c, 0x4d, 0x59, 0x79, 0x22, 0xee, 0x07, 0x78, 0xdb, 0xf2, 0x73, 0xc8, 0xa2, 0x60, 0x64, | ||||
| 	0x87, 0xf9, 0xdd, 0x29, 0x2b, 0x33, 0x91, 0x06, 0x62, 0x2e, 0x3b, 0xe4, 0x6f, 0x20, 0x97, 0x5a, | ||||
| 	0xdb, 0x6f, 0x75, 0x23, 0x9b, 0x35, 0xb6, 0x75, 0xd3, 0x63, 0x8b, 0xc6, 0x2b, 0xa9, 0x29, 0xbf, | ||||
| 	0x37, 0x65, 0x65, 0x2a, 0x1e, 0x45, 0xbd, 0x8a, 0x72, 0xf5, 0x47, 0x2d, 0x5e, 0xc3, 0xc5, 0x7e, | ||||
| 	0x8b, 0x4f, 0xe3, 0x57, 0x54, 0x6b, 0x6c, 0xbe, 0xda, 0xc1, 0xf3, 0x87, 0x90, 0x48, 0xe7, 0xb6, | ||||
| 	0x75, 0x26, 0x62, 0x04, 0xc5, 0x07, 0xb8, 0xfc, 0xef, 0x33, 0x81, 0xe4, 0xac, 0x21, 0xe4, 0xe7, | ||||
| 	0x70, 0x8a, 0x3d, 0xd2, 0xa0, 0x7d, 0x0c, 0x48, 0xde, 0xb2, 0x99, 0xd8, 0x31, 0xc5, 0x3b, 0x78, | ||||
| 	0xfe, 0xcf, 0x94, 0x1b, 0xf4, 0xd7, 0x1b, 0xa9, 0xb4, 0x5c, 0x6a, 0x5c, 0xa0, 0xf4, 0x74, 0xa0, | ||||
| 	0x45, 0x03, 0x57, 0xc7, 0xbd, 0x3f, 0xaa, 0x4e, 0x18, 0x42, 0xc1, 0x1d, 0xd7, 0x3b, 0x11, 0x23, | ||||
| 	0x28, 0x5e, 0x40, 0x79, 0x68, 0x48, 0x65, 0x8d, 0x47, 0xe3, 0xe3, 0x56, 0xc3, 0xf5, 0x8a, 0x9f, | ||||
| 	0x0c, 0x5e, 0x1e, 0x6b, 0xfe, 0xab, 0x53, 0x36, 0x10, 0x8e, 0xa7, 0x8b, 0xad, 0x52, 0x91, 0x0e, | ||||
| 	0x84, 0xd1, 0xc8, 0x9f, 0xc1, 0x03, 0xe5, 0x36, 0xaf, 0x6a, 0xd9, 0xb6, 0x3d, 0xd2, 0xae, 0xda, | ||||
| 	0x59, 0xe0, 0xae, 0x47, 0x8a, 0x3f, 0x85, 0x33, 0x67, 0x7b, 0x5f, 0x9b, 0xa1, 0x5b, 0x62, 0x1f, | ||||
| 	0xef, 0x3d, 0x11, 0x10, 0xa8, 0x79, 0x64, 0xc2, 0x00, 0x37, 0x73, 0xf5, 0xaa, 0xb7, 0x83, 0xcb, | ||||
| 	0x4f, 0xa2, 0x9c, 0xba, 0x99, 0xbb, 0x09, 0x98, 0x5f, 0x00, 0x28, 0xf7, 0x3b, 0x3e, 0x89, 0x3f, | ||||
| 	0x56, 0xa6, 0xdc, 0x36, 0xfc, 0x7d, 0xf2, 0x91, 0x7d, 0x67, 0x77, 0x7e, 0x05, 0x00, 0x00, 0xff, | ||||
| 	0xff, 0x35, 0x87, 0xfb, 0x5f, 0xef, 0x02, 0x00, 0x00, | ||||
| } | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user