Compare commits
	
		
			101 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | b979aff270 | ||
|   | b293e3fa75 | ||
|   | 21eb37e471 | ||
|   | d3b60cc445 | ||
|   | 7466e1d014 | ||
|   | 2a7f28606c | ||
|   | 0450482e6e | ||
|   | ee5d9b43b5 | ||
|   | 3a8857c8c9 | ||
|   | be3dfb251d | ||
|   | 4e11e29f70 | ||
|   | 763bb95cea | ||
|   | 668e7407e6 | ||
|   | c147ba1da1 | ||
|   | 10f044c3dd | ||
|   | ce5140febd | ||
|   | 858cdc86f5 | ||
|   | 9a25297d51 | ||
|   | e24f7f5151 | ||
|   | eff5f1e119 | ||
|   | afcd362cd1 | ||
|   | 0452be0cb3 | ||
|   | 1624f10773 | ||
|   | 8764be7461 | ||
|   | 5dd15ef8e7 | ||
|   | 4ac6366706 | ||
|   | adc0912efa | ||
|   | 536823ce55 | ||
|   | 207cd24edb | ||
|   | b039da1eba | ||
|   | 8fcd0f3b6f | ||
|   | 16fde6935c | ||
|   | 9592cff9fa | ||
|   | 109148988c | ||
|   | cf13fff7d2 | ||
|   | a9d8ac8bc0 | ||
|   | 1a4717b366 | ||
|   | 6cadf12260 | ||
|   | 19d47784bd | ||
|   | b89102c5fc | ||
|   | 4f20ebead3 | ||
|   | a9f89dbc64 | ||
|   | 58ea1e07d2 | ||
|   | 6de4c7e971 | ||
|   | 03dc51ffa2 | ||
|   | aef2dcdfdd | ||
|   | 0494119bf4 | ||
|   | 0a17e21119 | ||
|   | 52e2f926f4 | ||
|   | 611fb279bc | ||
|   | 41b4e64be9 | ||
|   | 0d7315249d | ||
|   | 4913766d58 | ||
|   | 92da8c7044 | ||
|   | 9dba3d5385 | ||
|   | 2d3c26a4b2 | ||
|   | 8eba2d3e50 | ||
|   | a8d4a27de1 | ||
|   | c42167c6f4 | ||
|   | 44d182e2f9 | ||
|   | ad95e35687 | ||
|   | 640a9995f4 | ||
|   | 95625f6871 | ||
|   | 2c20f72a9c | ||
|   | 5ad788e768 | ||
|   | ed98c586c6 | ||
|   | 3e865708d6 | ||
|   | c3bcbd63c0 | ||
|   | 29e29439ee | ||
|   | 0c19716f44 | ||
|   | b24e1bafa1 | ||
|   | 64b899ac89 | ||
|   | aa274e5ab7 | ||
|   | 7b3eaf3ccf | ||
|   | 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 | 
							
								
								
									
										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 | ||||
							
								
								
									
										15
									
								
								.github/workflows/development.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								.github/workflows/development.yml
									
									
									
									
										vendored
									
									
								
							| @@ -16,7 +16,7 @@ jobs: | ||||
|   test-build-upload: | ||||
|     strategy: | ||||
|       matrix: | ||||
|         go-version: [1.14.x, 1.15.x] | ||||
|         go-version: [1.15.x, 1.16.x] | ||||
|         platform: [ubuntu-latest] | ||||
|     runs-on: ${{ matrix.platform }} | ||||
|     steps: | ||||
| @@ -24,6 +24,7 @@ jobs: | ||||
|       uses: actions/setup-go@v2 | ||||
|       with: | ||||
|         go-version: ${{ matrix.go-version }} | ||||
|         stable: false | ||||
|     - name: Checkout code | ||||
|       uses: actions/checkout@v2 | ||||
|       with: | ||||
| @@ -34,23 +35,23 @@ jobs: | ||||
|       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 | ||||
|         GOOS=linux GOARCH=amd64 go build -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 -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 -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') | ||||
|       if: startsWith(matrix.go-version,'1.16') | ||||
|       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') | ||||
|       if: startsWith(matrix.go-version,'1.16') | ||||
|       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') | ||||
|       if: startsWith(matrix.go-version,'1.16') | ||||
|       uses: actions/upload-artifact@v2 | ||||
|       with: | ||||
|         name: matterbridge-darwin-64bit | ||||
|   | ||||
| @@ -91,7 +91,6 @@ linters-settings: | ||||
|     # Correct spellings using locale preferences for US or UK. | ||||
|     # Default is to use a neutral variety of English. | ||||
|     # Setting locale to US will correct the British spelling of 'colour' to 'color'. | ||||
|     locale: US | ||||
|   lll: | ||||
|     # max line length, lines longer will be reported. Default is 120. | ||||
|     # '\t' is counted as 1 character by default, and can be changed with the tab-width option | ||||
|   | ||||
							
								
								
									
										10
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -1,11 +1,9 @@ | ||||
| FROM alpine AS builder | ||||
|  | ||||
| COPY . /go/src/github.com/42wim/matterbridge | ||||
| 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 | ||||
| COPY . /go/src/matterbridge | ||||
| RUN apk --no-cache add go git \ | ||||
|         && cd /go/src/matterbridge \ | ||||
|         && go build -mod vendor -ldflags "-X main.githash=$(git log --pretty=format:'%h' -n 1)" -o /bin/matterbridge | ||||
|  | ||||
| FROM alpine | ||||
| RUN apk --no-cache add ca-certificates mailcap | ||||
|   | ||||
							
								
								
									
										38
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								README.md
									
									
									
									
									
								
							| @@ -70,7 +70,7 @@ And more... | ||||
|   - [Changelog](#changelog) | ||||
|   - [FAQ](#faq) | ||||
|   - [Related projects](#related-projects) | ||||
|   - [Articles](#articles) | ||||
|   - [Articles / Tutorials](#articles--tutorials) | ||||
|   - [Thanks](#thanks) | ||||
|  | ||||
| ## Features | ||||
| @@ -91,15 +91,18 @@ And more... | ||||
| - [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 | ||||
| - [Mattermost](https://github.com/mattermost/mattermost-server/) | ||||
| - [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/) | ||||
| - ~~[Steam](https://store.steampowered.com/)~~ | ||||
|   - Not supported anymore, see [here](https://github.com/Philipp15b/go-steam/issues/94) for more info. | ||||
| - [Telegram](https://telegram.org) | ||||
| - [Twitch](https://twitch.tv) | ||||
| - [VK](https://vk.com/) | ||||
| - [WhatsApp](https://www.whatsapp.com/) | ||||
| - [XMPP](https://xmpp.org) | ||||
| - [Zulip](https://zulipchat.com) | ||||
| @@ -107,11 +110,15 @@ And more... | ||||
| ### 3rd party via matterbridge api | ||||
|  | ||||
| - [Discourse](https://github.com/DeclanHoare/matterbabble) | ||||
| - [Facebook messenger](https://github.com/powerjungle/fbridge-asyncio) | ||||
| - [Facebook messenger](https://github.com/VictorNine/fbridge) | ||||
| - [Minecraft](https://github.com/elytra/MatterLink) | ||||
| - [Minecraft](https://github.com/raws/mattercraft) | ||||
| - [Minecraft](https://gitlab.com/Programie/MatterBukkit) | ||||
| - [Reddit](https://github.com/bonehurtingjuice/mattereddit) | ||||
| - [Counter-Strike, half-life and more](https://forums.alliedmods.net/showthread.php?t=319430) | ||||
| - [MatterAMXX](https://github.com/GabeIggy/MatterAMXX) | ||||
| - [Vintage Story](https://github.com/NikkyAI/vs-matterbridge) | ||||
|  | ||||
| ### API | ||||
|  | ||||
| @@ -120,12 +127,16 @@ More info and examples on the [wiki](https://github.com/42wim/matterbridge/wiki/ | ||||
|  | ||||
| Used by the projects below. Feel free to make a PR to add your project to this list. | ||||
|  | ||||
| - [MatterLink](https://github.com/elytra/MatterLink) (Matterbridge link for Minecraft Server chat) | ||||
| - [MatterLink](https://github.com/elytra/MatterLink) (Matterbridge link for Minecraft Forge server chat, archived) | ||||
| - [MatterCraft](https://github.com/raws/mattercraft) (Matterbridge link for Minecraft Forge server chat) | ||||
| - [MatterBukkit](https://gitlab.com/Programie/MatterBukkit) (Matterbridge link for Minecraft Bukkit/Spigot server chat) | ||||
| - [pyCord](https://github.com/NikkyAI/pyCord) (crossplatform chatbot) | ||||
| - [Mattereddit](https://github.com/bonehurtingjuice/mattereddit) (Reddit chat support) | ||||
| - [fbridge-asyncio](https://github.com/powerjungle/fbridge-asyncio) (Facebook messenger support) | ||||
| - [fbridge](https://github.com/VictorNine/fbridge) (Facebook messenger support) | ||||
| - [matterbabble](https://github.com/DeclanHoare/matterbabble) (Discourse support) | ||||
| - [MatterAMXX](https://forums.alliedmods.net/showthread.php?t=319430) (Counter-Strike, half-life and more via AMXX mod) | ||||
| - [Vintage Story](https://github.com/NikkyAI/vs-matterbridge) | ||||
|  | ||||
| ## Chat with us | ||||
|  | ||||
| @@ -152,22 +163,23 @@ See <https://github.com/42wim/matterbridge/wiki> | ||||
|  | ||||
| ### Binaries | ||||
|  | ||||
| - Latest stable release [v1.18.3](https://github.com/42wim/matterbridge/releases/latest) | ||||
| - Latest stable release [v1.22.1](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. | ||||
| To install or upgrade just download the latest [binary](https://github.com/42wim/matterbridge/releases/latest). On \*nix platforms you may need to make the binary executable - you can do this by running `chmod a+x` on the binary (example: `chmod a+x matterbridge-1.20.0-linux-64bit`). After downloading (and making the binary executable, if necessary), 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) | ||||
| - [scoop](https://github.com/42wim/scoop-bucket) | ||||
|  | ||||
| ## Building | ||||
|  | ||||
| Most people just want to use binaries, you can find those [here](https://github.com/42wim/matterbridge/releases/latest) | ||||
|  | ||||
| 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. | ||||
| Go 1.13+ is required. Make sure you have [Go](https://golang.org/doc/install) properly installed. | ||||
|  | ||||
| ```bash | ||||
| go get github.com/42wim/matterbridge | ||||
| @@ -295,8 +307,11 @@ See [FAQ](https://github.com/42wim/matterbridge/wiki/FAQ) | ||||
| - [fbridge](https://github.com/VictorNine/fbridge) (Facebook messenger support) | ||||
| - [isla](https://github.com/alphachung/isla) (Bot for Discord-Telegram groups used alongside matterbridge) | ||||
| - [matterbabble](https://github.com/DeclanHoare/matterbabble) (Connect Discourse threads to Matterbridge) | ||||
| - [nextcloud talk](https://github.com/nextcloud/talk_matterbridge) (Integrates matterbridge in Nextcloud Talk) | ||||
| - [mattercraft](https://github.com/raws/mattercraft) (Minecraft bridge) | ||||
| - [vs-matterbridge](https://github.com/NikkyAI/vs-matterbridge) (Vintage Story bridge) | ||||
|  | ||||
| ## Articles | ||||
| ## Articles / Tutorials | ||||
|  | ||||
| - [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/> | ||||
| @@ -307,6 +322,8 @@ See [FAQ](https://github.com/42wim/matterbridge/wiki/FAQ) | ||||
| - <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> | ||||
| - <https://nextcloud.com/blog/bridging-chat-services-in-talk/> | ||||
| - Youtube: [whatsapp - telegram bridging](https://www.youtube.com/watch?v=W-VXISoKtNc) | ||||
|  | ||||
| ## Thanks | ||||
|  | ||||
| @@ -324,17 +341,20 @@ Matterbridge wouldn't exist without these libraries: | ||||
| - 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> | ||||
| - vk - <https://github.com/SevereCloud/vksdk> | ||||
| - whatsapp - <https://github.com/Rhymen/go-whatsapp> | ||||
| - xmpp - <https://github.com/mattn/go-xmpp> | ||||
| - zulip - <https://github.com/ifo/gozulipbot> | ||||
| @@ -349,7 +369,7 @@ Matterbridge wouldn't exist without these libraries: | ||||
| [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-slack]: https://join.slack.com/matterbridgechat/shared_invite/MjEwODMxNjU1NDMwLTE0OTk2MTU3NTMtMzZkZmRiNDZhOA | ||||
| [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/ | ||||
|   | ||||
| @@ -26,8 +26,11 @@ const ( | ||||
| 	EventAPIConnected      = "api_connected" | ||||
| 	EventUserTyping        = "user_typing" | ||||
| 	EventGetChannelMembers = "get_channel_members" | ||||
| 	EventNoticeIRC         = "notice_irc" | ||||
| ) | ||||
|  | ||||
| const ParentIDNotFound = "msg-parent-not-found" | ||||
|  | ||||
| type Message struct { | ||||
| 	Text      string    `json:"text"` | ||||
| 	Channel   string    `json:"channel"` | ||||
| @@ -44,6 +47,14 @@ type Message struct { | ||||
| 	Extra     map[string][]interface{} | ||||
| } | ||||
|  | ||||
| func (m Message) ParentNotFound() bool { | ||||
| 	return m.ParentID == ParentIDNotFound | ||||
| } | ||||
|  | ||||
| func (m Message) ParentValid() bool { | ||||
| 	return m.ParentID != "" && !m.ParentNotFound() | ||||
| } | ||||
|  | ||||
| type FileInfo struct { | ||||
| 	Name    string | ||||
| 	Data    *[]byte | ||||
| @@ -117,7 +128,7 @@ 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 | ||||
| @@ -154,7 +165,7 @@ type Protocol struct { | ||||
| 	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 | ||||
| @@ -213,6 +224,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 | ||||
|   | ||||
| @@ -2,13 +2,13 @@ package bdiscord | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge" | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/42wim/matterbridge/bridge/discord/transmitter" | ||||
| 	"github.com/42wim/matterbridge/bridge/helper" | ||||
| 	"github.com/matterbridge/discordgo" | ||||
| ) | ||||
| @@ -20,12 +20,9 @@ type Bdiscord struct { | ||||
|  | ||||
| 	c *discordgo.Session | ||||
|  | ||||
| 	nick            string | ||||
| 	userID          string | ||||
| 	guildID         string | ||||
| 	webhookID       string | ||||
| 	webhookToken    string | ||||
| 	canEditWebhooks bool | ||||
| 	nick    string | ||||
| 	userID  string | ||||
| 	guildID string | ||||
|  | ||||
| 	channelsMutex  sync.RWMutex | ||||
| 	channels       []*discordgo.Channel | ||||
| @@ -34,8 +31,10 @@ type Bdiscord struct { | ||||
| 	membersMutex  sync.RWMutex | ||||
| 	userMemberMap map[string]*discordgo.Member | ||||
| 	nickMemberMap map[string]*discordgo.Member | ||||
| 	webhookCache  map[string]string | ||||
| 	webhookMutex  sync.RWMutex | ||||
|  | ||||
| 	// Webhook specific logic | ||||
| 	useAutoWebhooks bool | ||||
| 	transmitter     *transmitter.Transmitter | ||||
| } | ||||
|  | ||||
| func New(cfg *bridge.Config) bridge.Bridger { | ||||
| @@ -43,24 +42,18 @@ func New(cfg *bridge.Config) bridge.Bridger { | ||||
| 	b.userMemberMap = make(map[string]*discordgo.Member) | ||||
| 	b.nickMemberMap = make(map[string]*discordgo.Member) | ||||
| 	b.channelInfoMap = make(map[string]*config.ChannelInfo) | ||||
| 	b.webhookCache = make(map[string]string) | ||||
| 	if b.GetString("WebhookURL") != "" { | ||||
| 		b.Log.Debug("Configuring Discord Incoming Webhook") | ||||
| 		b.webhookID, b.webhookToken = b.splitURL(b.GetString("WebhookURL")) | ||||
|  | ||||
| 	b.useAutoWebhooks = b.GetBool("AutoWebhooks") | ||||
| 	if b.useAutoWebhooks { | ||||
| 		b.Log.Debug("Using automatic webhooks") | ||||
| 	} | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| func (b *Bdiscord) Connect() error { | ||||
| 	var err error | ||||
| 	var guildFound bool | ||||
| 	token := b.GetString("Token") | ||||
| 	b.Log.Info("Connecting") | ||||
| 	if b.GetString("WebhookURL") == "" { | ||||
| 		b.Log.Info("Connecting using token") | ||||
| 	} else { | ||||
| 		b.Log.Info("Connecting using webhookurl (for posting) and token") | ||||
| 	} | ||||
| 	if !strings.HasPrefix(b.GetString("Token"), "Bot ") { | ||||
| 		token = "Bot " + b.GetString("Token") | ||||
| 	} | ||||
| @@ -82,6 +75,11 @@ func (b *Bdiscord) Connect() error { | ||||
| 	b.c.AddHandler(b.messageDeleteBulk) | ||||
| 	b.c.AddHandler(b.memberAdd) | ||||
| 	b.c.AddHandler(b.memberRemove) | ||||
| 	// Add privileged intent for guild member tracking. This is needed to track nicks | ||||
| 	// for display names and @mention translation | ||||
| 	b.c.Identify.Intents = discordgo.MakeIntent(discordgo.IntentsAllWithoutPrivileged | | ||||
| 		discordgo.IntentsGuildMembers) | ||||
|  | ||||
| 	err = b.c.Open() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| @@ -97,62 +95,107 @@ func (b *Bdiscord) Connect() error { | ||||
| 	serverName := strings.Replace(b.GetString("Server"), "ID:", "", -1) | ||||
| 	b.nick = userinfo.Username | ||||
| 	b.userID = userinfo.ID | ||||
|  | ||||
| 	// Try and find this account's guild, and populate channels | ||||
| 	b.channelsMutex.Lock() | ||||
| 	for _, guild := range guilds { | ||||
| 		if guild.Name == serverName || guild.ID == serverName { | ||||
| 			b.channels, err = b.c.GuildChannels(guild.ID) | ||||
| 			if err != nil { | ||||
| 				break | ||||
| 			} | ||||
| 			b.guildID = guild.ID | ||||
| 			guildFound = true | ||||
| 		// Skip, if the server name does not match the visible name or the ID | ||||
| 		if guild.Name != serverName && guild.ID != serverName { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		// Complain about an ambiguous Server setting. Two Discord servers could have the same title! | ||||
| 		// For IDs, practically this will never happen. It would only trigger if some server's name is also an ID. | ||||
| 		if b.guildID != "" { | ||||
| 			return fmt.Errorf("found multiple Discord servers with the same name %#v, expected to see only one", serverName) | ||||
| 		} | ||||
|  | ||||
| 		// Getting this guild's channel could result in a permission error | ||||
| 		b.channels, err = b.c.GuildChannels(guild.ID) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("could not get %#v's channels: %w", b.GetString("Server"), err) | ||||
| 		} | ||||
|  | ||||
| 		b.guildID = guild.ID | ||||
| 	} | ||||
| 	b.channelsMutex.Unlock() | ||||
| 	if !guildFound { | ||||
| 		msg := fmt.Sprintf("Server \"%s\" not found", b.GetString("Server")) | ||||
| 		err = errors.New(msg) | ||||
| 		b.Log.Error(msg) | ||||
| 		b.Log.Info("Possible values:") | ||||
|  | ||||
| 	// If we couldn't find a guild, we print extra debug information and return a nice error | ||||
| 	if b.guildID == "" { | ||||
| 		err = fmt.Errorf("could not find Discord server %#v", b.GetString("Server")) | ||||
| 		b.Log.Error(err.Error()) | ||||
|  | ||||
| 		// Print all of the possible server values | ||||
| 		b.Log.Info("Possible server values:") | ||||
| 		for _, guild := range guilds { | ||||
| 			b.Log.Infof("Server=\"%s\" # Server name", guild.Name) | ||||
| 			b.Log.Infof("Server=\"%s\" # Server ID", guild.ID) | ||||
| 			b.Log.Infof("\t- Server=%#v # by name", guild.Name) | ||||
| 			b.Log.Infof("\t- Server=%#v # by ID", guild.ID) | ||||
| 		} | ||||
| 	} | ||||
| 	if err != nil { | ||||
|  | ||||
| 		// If there are no results, we should say that | ||||
| 		if len(guilds) == 0 { | ||||
| 			b.Log.Info("\t- (none found)") | ||||
| 		} | ||||
|  | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	b.channelsMutex.RLock() | ||||
| 	if b.GetString("WebhookURL") == "" { | ||||
| 		for _, channel := range b.channels { | ||||
| 			b.Log.Debugf("found channel %#v", channel) | ||||
| 		} | ||||
| 	} else { | ||||
| 		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) | ||||
| 	// Legacy note: WebhookURL used to have an actual webhook URL that we would edit, | ||||
| 	// but we stopped doing that due to Discord making rate limits more aggressive. | ||||
| 	// | ||||
| 	// Even older: the same WebhookURL used to be used by every channel, which is usually unexpected. | ||||
| 	// This is no longer possible. | ||||
| 	if b.GetString("WebhookURL") != "" { | ||||
| 		message := "The global WebhookURL setting has been removed. " | ||||
| 		message += "You can get similar \"webhook editing\" behaviour by replacing this line with `AutoWebhooks=true`. " | ||||
| 		message += "If you rely on the old-OLD (non-editing) behaviour, can move the WebhookURL to specific channel sections." | ||||
| 		b.Log.Errorln(message) | ||||
| 		return fmt.Errorf("use of removed WebhookURL setting") | ||||
| 	} | ||||
|  | ||||
| 			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 | ||||
| 	if b.GetInt("debuglevel") > 0 { | ||||
| 		b.Log.Debug("enabling even more discord debug") | ||||
| 		b.c.Debug = true | ||||
| 	} | ||||
|  | ||||
| 	// Initialise webhook management | ||||
| 	b.transmitter = transmitter.New(b.c, b.guildID, "matterbridge", b.useAutoWebhooks) | ||||
| 	b.transmitter.Log = b.Log | ||||
|  | ||||
| 	var webhookChannelIDs []string | ||||
| 	for _, channel := range b.Channels { | ||||
| 		channelID := b.getChannelID(channel.Name) // note(qaisjp): this readlocks channelsMutex | ||||
|  | ||||
| 		// If a WebhookURL was not explicitly provided for this channel, | ||||
| 		// there are two options: just a regular bot message (ugly) or this is should be webhook sent | ||||
| 		if channel.Options.WebhookURL == "" { | ||||
| 			// If it should be webhook sent, we should enforce this via the transmitter | ||||
| 			if b.useAutoWebhooks { | ||||
| 				webhookChannelIDs = append(webhookChannelIDs, channelID) | ||||
| 			} | ||||
| 			channelsDenied = append(channelsDenied, fmt.Sprintf("%#v", info.Name)) | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		b.canEditWebhooks = len(channelsDenied) == 0 | ||||
| 		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, ", ")) | ||||
| 		whID, whToken, ok := b.splitURL(channel.Options.WebhookURL) | ||||
| 		if !ok { | ||||
| 			return fmt.Errorf("failed to parse WebhookURL %#v for channel %#v", channel.Options.WebhookURL, channel.ID) | ||||
| 		} | ||||
|  | ||||
| 		b.transmitter.AddWebhook(channelID, &discordgo.Webhook{ | ||||
| 			ID:        whID, | ||||
| 			Token:     whToken, | ||||
| 			GuildID:   b.guildID, | ||||
| 			ChannelID: channelID, | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| 	if b.useAutoWebhooks { | ||||
| 		err = b.transmitter.RefreshGuildWebhooks(webhookChannelIDs) | ||||
| 		if err != nil { | ||||
| 			b.Log.WithError(err).Println("transmitter could not refresh guild webhooks") | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	b.channelsMutex.RUnlock() | ||||
|  | ||||
| 	// Obtaining guild members and initializing nickname mapping. | ||||
| 	b.membersMutex.Lock() | ||||
| @@ -191,8 +234,6 @@ func (b *Bdiscord) JoinChannel(channel config.ChannelInfo) error { | ||||
| func (b *Bdiscord) Send(msg config.Message) (string, error) { | ||||
| 	b.Log.Debugf("=> Receiving %#v", msg) | ||||
|  | ||||
| 	origMsgID := msg.ID | ||||
|  | ||||
| 	channelID := b.getChannelID(msg.Channel) | ||||
| 	if channelID == "" { | ||||
| 		return "", fmt.Errorf("Could not find channelID for %v", msg.Channel) | ||||
| @@ -211,79 +252,23 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) { | ||||
| 		msg.Text = "_" + msg.Text + "_" | ||||
| 	} | ||||
|  | ||||
| 	// use initial webhook configured for the entire Discord account | ||||
| 	isGlobalWebhook := true | ||||
| 	wID := b.webhookID | ||||
| 	wToken := b.webhookToken | ||||
|  | ||||
| 	// check if have a channel specific webhook | ||||
| 	b.channelsMutex.RLock() | ||||
| 	if ci, ok := b.channelInfoMap[msg.Channel+b.Account]; ok { | ||||
| 		if ci.Options.WebhookURL != "" { | ||||
| 			wID, wToken = b.splitURL(ci.Options.WebhookURL) | ||||
| 			isGlobalWebhook = false | ||||
| 		} | ||||
| 	// Handle prefix hint for unthreaded messages. | ||||
| 	if msg.ParentNotFound() { | ||||
| 		msg.ParentID = "" | ||||
| 		msg.Text = fmt.Sprintf("[thread]: %s", msg.Text) | ||||
| 	} | ||||
| 	b.channelsMutex.RUnlock() | ||||
|  | ||||
| 	// Use webhook to send the message | ||||
| 	if wID != "" && msg.Event != config.EventMsgDelete { | ||||
| 		// skip events | ||||
| 		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 != "" { | ||||
| 			msg.ID = b.getCacheID(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) | ||||
| 			return "", nil | ||||
| 		} | ||||
|  | ||||
| 		msg.Text = helper.ClipMessage(msg.Text, MessageLength) | ||||
| 		msg.Text = b.replaceUserMentions(msg.Text) | ||||
| 		// discord username must be [0..32] max | ||||
| 		if len(msg.Username) > 32 { | ||||
| 			msg.Username = msg.Username[0:32] | ||||
| 		} | ||||
| 		// 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 | ||||
| 		if isGlobalWebhook && b.canEditWebhooks { | ||||
| 			b.Log.Debugf("Setting webhook channel to \"%s\"", msg.Channel) | ||||
| 			_, err := b.c.WebhookEdit(wID, "", "", channelID) | ||||
| 			if err != nil { | ||||
| 				b.Log.Errorf("Could not set webhook channel: %s", err) | ||||
| 				return "", err | ||||
| 			} | ||||
| 		} | ||||
| 		b.Log.Debugf("Processing webhook sending for message %#v", msg) | ||||
| 		msg, err := b.webhookSend(&msg, wID, wToken) | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("Could not broadcast via webook for message %#v: %s", msg, err) | ||||
| 			return "", err | ||||
| 		} | ||||
| 		if msg == nil { | ||||
| 			return "", nil | ||||
| 		} | ||||
|  | ||||
| 		b.updateCacheID(origMsgID, msg.ID) | ||||
| 		return msg.ID, nil | ||||
| 	useWebhooks := b.shouldMessageUseWebhooks(&msg) | ||||
| 	if useWebhooks && msg.Event != config.EventMsgDelete && msg.ParentID == "" { | ||||
| 		return b.handleEventWebhook(&msg, channelID) | ||||
| 	} | ||||
|  | ||||
| 	return b.handleEventBotUser(&msg, channelID) | ||||
| } | ||||
|  | ||||
| // handleEventDirect handles events via the bot user | ||||
| func (b *Bdiscord) handleEventBotUser(msg *config.Message, channelID string) (string, error) { | ||||
| 	b.Log.Debugf("Broadcasting using token (API)") | ||||
|  | ||||
| 	// Delete message | ||||
| @@ -291,14 +276,13 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) { | ||||
| 		if msg.ID == "" { | ||||
| 			return "", nil | ||||
| 		} | ||||
| 		msg.ID = b.getCacheID(msg.ID) | ||||
| 		err := b.c.ChannelMessageDelete(channelID, msg.ID) | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	// Upload a file if it exists | ||||
| 	if msg.Extra != nil { | ||||
| 		for _, rmsg := range helper.HandleExtra(&msg, b.General) { | ||||
| 		for _, rmsg := range helper.HandleExtra(msg, b.General) { | ||||
| 			rmsg.Text = helper.ClipMessage(rmsg.Text, MessageLength) | ||||
| 			if _, err := b.c.ChannelMessageSend(channelID, rmsg.Username+rmsg.Text); err != nil { | ||||
| 				b.Log.Errorf("Could not send message %#v: %s", rmsg, err) | ||||
| @@ -306,7 +290,7 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) { | ||||
| 		} | ||||
| 		// check if we have files to upload (from slack, telegram or mattermost) | ||||
| 		if len(msg.Extra["file"]) > 0 { | ||||
| 			return b.handleUploadFile(&msg, channelID) | ||||
| 			return b.handleUploadFile(msg, channelID) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -319,54 +303,27 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) { | ||||
| 		return msg.ID, err | ||||
| 	} | ||||
|  | ||||
| 	m := discordgo.MessageSend{ | ||||
| 		Content: msg.Username + msg.Text, | ||||
| 	} | ||||
|  | ||||
| 	if msg.ParentValid() { | ||||
| 		m.Reference = &discordgo.MessageReference{ | ||||
| 			MessageID: msg.ParentID, | ||||
| 			ChannelID: channelID, | ||||
| 			GuildID:   b.guildID, | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Post normal message | ||||
| 	res, err := b.c.ChannelMessageSend(channelID, msg.Username+msg.Text) | ||||
| 	res, err := b.c.ChannelMessageSendComplex(channelID, &m) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	return res.ID, nil | ||||
| } | ||||
|  | ||||
| // useWebhook returns true if we have a webhook defined somewhere | ||||
| func (b *Bdiscord) useWebhook() bool { | ||||
| 	if b.GetString("WebhookURL") != "" { | ||||
| 		return true | ||||
| 	} | ||||
|  | ||||
| 	b.channelsMutex.RLock() | ||||
| 	defer b.channelsMutex.RUnlock() | ||||
|  | ||||
| 	for _, channel := range b.channelInfoMap { | ||||
| 		if channel.Options.WebhookURL != "" { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| // isWebhookID returns true if the specified id is used in a defined webhook | ||||
| func (b *Bdiscord) isWebhookID(id string) bool { | ||||
| 	if b.GetString("WebhookURL") != "" { | ||||
| 		wID, _ := b.splitURL(b.GetString("WebhookURL")) | ||||
| 		if wID == id { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	b.channelsMutex.RLock() | ||||
| 	defer b.channelsMutex.RUnlock() | ||||
|  | ||||
| 	for _, channel := range b.channelInfoMap { | ||||
| 		if channel.Options.WebhookURL != "" { | ||||
| 			wID, _ := b.splitURL(channel.Options.WebhookURL) | ||||
| 			if wID == id { | ||||
| 				return true | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| // handleUploadFile handles native upload of files | ||||
| func (b *Bdiscord) handleUploadFile(msg *config.Message, channelID string) (string, error) { | ||||
| 	var err error | ||||
| @@ -388,83 +345,3 @@ func (b *Bdiscord) handleUploadFile(msg *config.Message, channelID string) (stri | ||||
| 	} | ||||
| 	return "", nil | ||||
| } | ||||
|  | ||||
| // webhookSend send one or more message via webhook, taking care of file | ||||
| // uploads (from slack, telegram or mattermost). | ||||
| // Returns messageID and error. | ||||
| func (b *Bdiscord) webhookSend(msg *config.Message, webhookID, token string) (*discordgo.Message, error) { | ||||
| 	var ( | ||||
| 		res *discordgo.Message | ||||
| 		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. | ||||
| 	if msg.Text != "" { | ||||
| 		res, err = b.c.WebhookExecute( | ||||
| 			webhookID, | ||||
| 			token, | ||||
| 			true, | ||||
| 			&discordgo.WebhookParams{ | ||||
| 				Content:   msg.Text, | ||||
| 				Username:  msg.Username, | ||||
| 				AvatarURL: msg.Avatar, | ||||
| 			}, | ||||
| 		) | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("Could not send text (%s) for message %#v: %s", msg.Text, msg, err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if msg.Extra != nil { | ||||
| 		for _, f := range msg.Extra["file"] { | ||||
| 			fi := f.(config.FileInfo) | ||||
| 			file := discordgo.File{ | ||||
| 				Name:        fi.Name, | ||||
| 				ContentType: "", | ||||
| 				Reader:      bytes.NewReader(*fi.Data), | ||||
| 			} | ||||
| 			content := "" | ||||
| 			if msg.Text == "" { | ||||
| 				content = fi.Comment | ||||
| 			} | ||||
| 			_, e2 := b.c.WebhookExecute( | ||||
| 				webhookID, | ||||
| 				token, | ||||
| 				false, | ||||
| 				&discordgo.WebhookParams{ | ||||
| 					Username:  msg.Username, | ||||
| 					AvatarURL: msg.Avatar, | ||||
| 					File:      &file, | ||||
| 					Content:   content, | ||||
| 				}, | ||||
| 			) | ||||
| 			if e2 != nil { | ||||
| 				b.Log.Errorf("Could not send file %#v for message %#v: %s", file, msg, e2) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	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("") | ||||
| } | ||||
|   | ||||
| @@ -69,7 +69,7 @@ func (b *Bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreat | ||||
| 		return | ||||
| 	} | ||||
| 	// if using webhooks, do not relay if it's ours | ||||
| 	if b.useWebhook() && m.Author.Bot && b.isWebhookID(m.Author.ID) { | ||||
| 	if m.Author.Bot && b.transmitter.HasWebhook(m.Author.ID) { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| @@ -127,6 +127,11 @@ func (b *Bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreat | ||||
| 	// Replace emotes | ||||
| 	rmsg.Text = replaceEmotes(rmsg.Text) | ||||
|  | ||||
| 	// Add our parent id if it exists, and if it's not referring to a message in another channel | ||||
| 	if ref := m.MessageReference; ref != nil && ref.ChannelID == m.ChannelID { | ||||
| 		rmsg.ParentID = ref.MessageID | ||||
| 	} | ||||
|  | ||||
| 	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 | ||||
|   | ||||
| @@ -196,7 +196,7 @@ func (b *Bdiscord) replaceAction(text string) (string, bool) { | ||||
| } | ||||
|  | ||||
| // splitURL splits a webhookURL and returns the ID and token. | ||||
| func (b *Bdiscord) splitURL(url string) (string, string) { | ||||
| func (b *Bdiscord) splitURL(url string) (string, string, bool) { | ||||
| 	const ( | ||||
| 		expectedWebhookSplitCount = 7 | ||||
| 		webhookIdxID              = 5 | ||||
| @@ -204,43 +204,9 @@ func (b *Bdiscord) splitURL(url string) (string, string) { | ||||
| 	) | ||||
| 	webhookURLSplit := strings.Split(url, "/") | ||||
| 	if len(webhookURLSplit) != expectedWebhookSplitCount { | ||||
| 		b.Log.Fatalf("%s is no correct discord WebhookURL", url) | ||||
| 		return "", "", false | ||||
| 	} | ||||
| 	return webhookURLSplit[webhookIdxID], webhookURLSplit[webhookIdxToken] | ||||
| } | ||||
|  | ||||
| // getcacheID tries to find a corresponding msgID in the webhook cache. | ||||
| // if not found returns the original request. | ||||
| func (b *Bdiscord) getCacheID(msgID string) string { | ||||
| 	b.webhookMutex.RLock() | ||||
| 	defer b.webhookMutex.RUnlock() | ||||
| 	for k, v := range b.webhookCache { | ||||
| 		if msgID == k { | ||||
| 			return v | ||||
| 		} | ||||
| 	} | ||||
| 	return msgID | ||||
| } | ||||
|  | ||||
| // updateCacheID updates the cache so that the newID takes the place of | ||||
| // the original ID. This is used for edit/deletes in combination with webhooks | ||||
| // as editing a message via webhook means deleting the message and creating a | ||||
| // new message (with a new ID). This ID needs to be set instead of the original ID | ||||
| func (b *Bdiscord) updateCacheID(origID, newID string) { | ||||
| 	b.webhookMutex.Lock() | ||||
| 	match := false | ||||
| 	for k, v := range b.webhookCache { | ||||
| 		if v == origID { | ||||
| 			delete(b.webhookCache, k) | ||||
| 			b.webhookCache[origID] = newID | ||||
| 			match = true | ||||
| 			continue | ||||
| 		} | ||||
| 	} | ||||
| 	if !match && origID != "" { | ||||
| 		b.webhookCache[origID] = newID | ||||
| 	} | ||||
| 	b.webhookMutex.Unlock() | ||||
| 	return webhookURLSplit[webhookIdxID], webhookURLSplit[webhookIdxToken], true | ||||
| } | ||||
|  | ||||
| func enumerateUsernames(s string) []string { | ||||
|   | ||||
							
								
								
									
										257
									
								
								bridge/discord/transmitter/transmitter.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										257
									
								
								bridge/discord/transmitter/transmitter.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,257 @@ | ||||
| // Package transmitter provides functionality for transmitting | ||||
| // arbitrary webhook messages to Discord. | ||||
| // | ||||
| // The package provides the following functionality: | ||||
| // | ||||
| // - Creating new webhooks, whenever necessary | ||||
| // - Loading webhooks that we have previously created | ||||
| // - Sending new messages | ||||
| // - Editing messages, via message ID | ||||
| // - Deleting messages, via message ID | ||||
| // | ||||
| // The package has been designed for matterbridge, but with other | ||||
| // Go bots in mind. The public API should be matterbridge-agnostic. | ||||
| package transmitter | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/matterbridge/discordgo" | ||||
| 	log "github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| // A Transmitter represents a message manager for a single guild. | ||||
| type Transmitter struct { | ||||
| 	session    *discordgo.Session | ||||
| 	guild      string | ||||
| 	title      string | ||||
| 	autoCreate bool | ||||
|  | ||||
| 	// channelWebhooks maps from a channel ID to a webhook instance | ||||
| 	channelWebhooks map[string]*discordgo.Webhook | ||||
|  | ||||
| 	mutex sync.RWMutex | ||||
|  | ||||
| 	Log *log.Entry | ||||
| } | ||||
|  | ||||
| // ErrWebhookNotFound is returned when a valid webhook for this channel/message combination does not exist | ||||
| var ErrWebhookNotFound = errors.New("webhook for this channel and message does not exist") | ||||
|  | ||||
| // ErrPermissionDenied is returned if the bot does not have permission to manage webhooks. | ||||
| // | ||||
| // Bots can be granted a guild-wide permission and channel-specific permissions to manage webhooks. | ||||
| // Despite potentially having guild-wide permission, channel specific overrides could deny a bot's permission to manage webhooks. | ||||
| var ErrPermissionDenied = errors.New("missing 'Manage Webhooks' permission") | ||||
|  | ||||
| // New returns a new Transmitter given a Discord session, guild ID, and title. | ||||
| func New(session *discordgo.Session, guild string, title string, autoCreate bool) *Transmitter { | ||||
| 	return &Transmitter{ | ||||
| 		session:    session, | ||||
| 		guild:      guild, | ||||
| 		title:      title, | ||||
| 		autoCreate: autoCreate, | ||||
|  | ||||
| 		channelWebhooks: make(map[string]*discordgo.Webhook), | ||||
|  | ||||
| 		Log: log.NewEntry(log.StandardLogger()), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Send transmits a message to the given channel with the provided webhook data, and waits until Discord responds with message data. | ||||
| func (t *Transmitter) Send(channelID string, params *discordgo.WebhookParams) (*discordgo.Message, error) { | ||||
| 	wh, err := t.getOrCreateWebhook(channelID) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	msg, err := t.session.WebhookExecute(wh.ID, wh.Token, true, params) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("execute failed: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return msg, nil | ||||
| } | ||||
|  | ||||
| // Edit will edit a message in a channel, if possible. | ||||
| func (t *Transmitter) Edit(channelID string, messageID string, params *discordgo.WebhookParams) error { | ||||
| 	wh := t.getWebhook(channelID) | ||||
|  | ||||
| 	if wh == nil { | ||||
| 		return ErrWebhookNotFound | ||||
| 	} | ||||
|  | ||||
| 	uri := discordgo.EndpointWebhookToken(wh.ID, wh.Token) + "/messages/" + messageID | ||||
| 	_, err := t.session.RequestWithBucketID("PATCH", uri, params, discordgo.EndpointWebhookToken("", "")) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // HasWebhook checks whether the transmitter is using a particular webhook. | ||||
| func (t *Transmitter) HasWebhook(id string) bool { | ||||
| 	t.mutex.RLock() | ||||
| 	defer t.mutex.RUnlock() | ||||
|  | ||||
| 	for _, wh := range t.channelWebhooks { | ||||
| 		if wh.ID == id { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| // AddWebhook allows you to register a channel's webhook with the transmitter. | ||||
| func (t *Transmitter) AddWebhook(channelID string, webhook *discordgo.Webhook) bool { | ||||
| 	t.Log.Debugf("Manually added webhook %#v to channel %#v", webhook.ID, channelID) | ||||
| 	t.mutex.Lock() | ||||
| 	defer t.mutex.Unlock() | ||||
|  | ||||
| 	_, replaced := t.channelWebhooks[channelID] | ||||
| 	t.channelWebhooks[channelID] = webhook | ||||
| 	return replaced | ||||
| } | ||||
|  | ||||
| // RefreshGuildWebhooks loads "relevant" webhooks into the transmitter, with careful permission handling. | ||||
| // | ||||
| // Notes: | ||||
| // | ||||
| // - A webhook is "relevant" if it was created by this bot -- the ApplicationID should match the bot's ID. | ||||
| // - The term "having permission" means having the "Manage Webhooks" permission. See ErrPermissionDenied for more information. | ||||
| // - This function is additive and will not unload previously loaded webhooks. | ||||
| // - A nil channelIDs slice is treated the same as an empty one. | ||||
| // | ||||
| // If the bot has guild-wide permission: | ||||
| // | ||||
| // 1. it will load any "relevant" webhooks from the entire guild | ||||
| // 2. the given slice is ignored | ||||
| // | ||||
| // If the bot does not have guild-wide permission: | ||||
| // | ||||
| // 1. it will load any "relevant" webhooks in each channel | ||||
| // 2. a single error will be returned if any error occurs (incl. if there is no permission for any of these channels) | ||||
| // | ||||
| // If any channel has more than one "relevant" webhook, it will randomly pick one. | ||||
| func (t *Transmitter) RefreshGuildWebhooks(channelIDs []string) error { | ||||
| 	t.Log.Debugln("Refreshing guild webhooks") | ||||
|  | ||||
| 	botID, err := getDiscordUserID(t.session) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("could not get current user: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// Get all existing webhooks | ||||
| 	hooks, err := t.session.GuildWebhooks(t.guild) | ||||
| 	if err != nil { | ||||
| 		switch { | ||||
| 		case isDiscordPermissionError(err): | ||||
| 			// We fallback on manually fetching hooks from individual channels | ||||
| 			// if we don't have the "Manage Webhooks" permission globally. | ||||
| 			// We can only do this if we were provided channelIDs, though. | ||||
| 			if len(channelIDs) == 0 { | ||||
| 				return ErrPermissionDenied | ||||
| 			} | ||||
| 			t.Log.Debugln("Missing global 'Manage Webhooks' permission, falling back on per-channel permission") | ||||
| 			return t.fetchChannelsHooks(channelIDs, botID) | ||||
| 		default: | ||||
| 			return fmt.Errorf("could not get webhooks: %w", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	t.Log.Debugln("Refreshing guild webhooks using global permission") | ||||
| 	t.assignHooksByAppID(hooks, botID, false) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // createWebhook creates a webhook for a specific channel. | ||||
| func (t *Transmitter) createWebhook(channel string) (*discordgo.Webhook, error) { | ||||
| 	t.mutex.Lock() | ||||
| 	defer t.mutex.Unlock() | ||||
|  | ||||
| 	wh, err := t.session.WebhookCreate(channel, t.title+time.Now().Format(" 3:04:05PM"), "") | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	t.channelWebhooks[channel] = wh | ||||
| 	return wh, nil | ||||
| } | ||||
|  | ||||
| func (t *Transmitter) getWebhook(channel string) *discordgo.Webhook { | ||||
| 	t.mutex.RLock() | ||||
| 	defer t.mutex.RUnlock() | ||||
|  | ||||
| 	return t.channelWebhooks[channel] | ||||
| } | ||||
|  | ||||
| func (t *Transmitter) getOrCreateWebhook(channelID string) (*discordgo.Webhook, error) { | ||||
| 	// If we have a webhook for this channel, immediately return it | ||||
| 	wh := t.getWebhook(channelID) | ||||
| 	if wh != nil { | ||||
| 		return wh, nil | ||||
| 	} | ||||
|  | ||||
| 	// Early exit if we don't want to automatically create one | ||||
| 	if !t.autoCreate { | ||||
| 		return nil, ErrWebhookNotFound | ||||
| 	} | ||||
|  | ||||
| 	t.Log.Infof("Creating a webhook for %s\n", channelID) | ||||
| 	wh, err := t.createWebhook(channelID) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("could not create webhook: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return wh, nil | ||||
| } | ||||
|  | ||||
| // fetchChannelsHooks fetches hooks for the given channelIDs and calls assignHooksByAppID for each channel's hooks | ||||
| func (t *Transmitter) fetchChannelsHooks(channelIDs []string, botID string) error { | ||||
| 	// For each channel, search for relevant hooks | ||||
| 	var failedHooks []string | ||||
| 	for _, channelID := range channelIDs { | ||||
| 		hooks, err := t.session.ChannelWebhooks(channelID) | ||||
| 		if err != nil { | ||||
| 			failedHooks = append(failedHooks, "\n- "+channelID+": "+err.Error()) | ||||
| 			continue | ||||
| 		} | ||||
| 		t.assignHooksByAppID(hooks, botID, true) | ||||
| 	} | ||||
|  | ||||
| 	// Compose an error if any hooks failed | ||||
| 	if len(failedHooks) > 0 { | ||||
| 		return errors.New("failed to fetch hooks:" + strings.Join(failedHooks, "")) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (t *Transmitter) assignHooksByAppID(hooks []*discordgo.Webhook, appID string, channelTargeted bool) { | ||||
| 	logLine := "Picking up webhook" | ||||
| 	if channelTargeted { | ||||
| 		logLine += " (channel targeted)" | ||||
| 	} | ||||
|  | ||||
| 	t.mutex.Lock() | ||||
| 	defer t.mutex.Unlock() | ||||
|  | ||||
| 	for _, wh := range hooks { | ||||
| 		if wh.ApplicationID != appID { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		t.channelWebhooks[wh.ChannelID] = wh | ||||
| 		t.Log.WithFields(log.Fields{ | ||||
| 			"id":      wh.ID, | ||||
| 			"name":    wh.Name, | ||||
| 			"channel": wh.ChannelID, | ||||
| 		}).Println(logLine) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										32
									
								
								bridge/discord/transmitter/utils.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								bridge/discord/transmitter/utils.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| package transmitter | ||||
|  | ||||
| import ( | ||||
| 	"github.com/matterbridge/discordgo" | ||||
| ) | ||||
|  | ||||
| // isDiscordPermissionError returns false for nil, and true if a Discord RESTError with code discordgo.ErrorCodeMissionPermissions | ||||
| func isDiscordPermissionError(err error) bool { | ||||
| 	if err == nil { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	restErr, ok := err.(*discordgo.RESTError) | ||||
| 	if !ok { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	return restErr.Message != nil && restErr.Message.Code == discordgo.ErrCodeMissingPermissions | ||||
| } | ||||
|  | ||||
| // getDiscordUserID gets own user ID from state, and fallback on API request | ||||
| func getDiscordUserID(session *discordgo.Session) (string, error) { | ||||
| 	if user := session.State.User; user != nil { | ||||
| 		return user.ID, nil | ||||
| 	} | ||||
|  | ||||
| 	user, err := session.User("@me") | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return user.ID, nil | ||||
| } | ||||
							
								
								
									
										147
									
								
								bridge/discord/webhook.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								bridge/discord/webhook.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,147 @@ | ||||
| package bdiscord | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/42wim/matterbridge/bridge/helper" | ||||
| 	"github.com/matterbridge/discordgo" | ||||
| ) | ||||
|  | ||||
| // shouldMessageUseWebhooks checks if have a channel specific webhook, if we're not using auto webhooks | ||||
| func (b *Bdiscord) shouldMessageUseWebhooks(msg *config.Message) bool { | ||||
| 	if b.useAutoWebhooks { | ||||
| 		return true | ||||
| 	} | ||||
|  | ||||
| 	b.channelsMutex.RLock() | ||||
| 	defer b.channelsMutex.RUnlock() | ||||
| 	if ci, ok := b.channelInfoMap[msg.Channel+b.Account]; ok { | ||||
| 		if ci.Options.WebhookURL != "" { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| // maybeGetLocalAvatar checks if UseLocalAvatar contains the message's | ||||
| // account or protocol, and if so, returns the Discord avatar (if exists) | ||||
| func (b *Bdiscord) maybeGetLocalAvatar(msg *config.Message) string { | ||||
| 	for _, val := range b.GetStringSlice("UseLocalAvatar") { | ||||
| 		if msg.Protocol != val && msg.Account != val { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		member, err := b.getGuildMemberByNick(msg.Username) | ||||
| 		if err != nil { | ||||
| 			return "" | ||||
| 		} | ||||
|  | ||||
| 		return member.User.AvatarURL("") | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| // webhookSend send one or more message via webhook, taking care of file | ||||
| // uploads (from slack, telegram or mattermost). | ||||
| // Returns messageID and error. | ||||
| func (b *Bdiscord) webhookSend(msg *config.Message, channelID string) (*discordgo.Message, error) { | ||||
| 	var ( | ||||
| 		res *discordgo.Message | ||||
| 		err error | ||||
| 	) | ||||
|  | ||||
| 	// If avatar is unset, mutate the message to include the local avatar (but only if settings say we should do this) | ||||
| 	if msg.Avatar == "" { | ||||
| 		msg.Avatar = b.maybeGetLocalAvatar(msg) | ||||
| 	} | ||||
|  | ||||
| 	// WebhookParams can have either `Content` or `File`. | ||||
|  | ||||
| 	// We can't send empty messages. | ||||
| 	if msg.Text != "" { | ||||
| 		res, err = b.transmitter.Send( | ||||
| 			channelID, | ||||
| 			&discordgo.WebhookParams{ | ||||
| 				Content:   msg.Text, | ||||
| 				Username:  msg.Username, | ||||
| 				AvatarURL: msg.Avatar, | ||||
| 			}, | ||||
| 		) | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("Could not send text (%s) for message %#v: %s", msg.Text, msg, err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if msg.Extra != nil { | ||||
| 		for _, f := range msg.Extra["file"] { | ||||
| 			fi := f.(config.FileInfo) | ||||
| 			file := discordgo.File{ | ||||
| 				Name:        fi.Name, | ||||
| 				ContentType: "", | ||||
| 				Reader:      bytes.NewReader(*fi.Data), | ||||
| 			} | ||||
| 			content := "" | ||||
| 			if msg.Text == "" { | ||||
| 				content = fi.Comment | ||||
| 			} | ||||
| 			_, e2 := b.transmitter.Send( | ||||
| 				channelID, | ||||
| 				&discordgo.WebhookParams{ | ||||
| 					Username:  msg.Username, | ||||
| 					AvatarURL: msg.Avatar, | ||||
| 					File:      &file, | ||||
| 					Content:   content, | ||||
| 				}, | ||||
| 			) | ||||
| 			if e2 != nil { | ||||
| 				b.Log.Errorf("Could not send file %#v for message %#v: %s", file, msg, e2) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return res, err | ||||
| } | ||||
|  | ||||
| func (b *Bdiscord) handleEventWebhook(msg *config.Message, channelID string) (string, error) { | ||||
| 	// skip events | ||||
| 	if msg.Event != "" && msg.Event != config.EventUserAction && msg.Event != config.EventJoinLeave && msg.Event != config.EventTopicChange { | ||||
| 		return "", nil | ||||
| 	} | ||||
|  | ||||
| 	// skip empty messages | ||||
| 	if msg.Text == "" && (msg.Extra == nil || len(msg.Extra["file"]) == 0) { | ||||
| 		b.Log.Debugf("Skipping empty message %#v", msg) | ||||
| 		return "", nil | ||||
| 	} | ||||
|  | ||||
| 	msg.Text = helper.ClipMessage(msg.Text, MessageLength) | ||||
| 	msg.Text = b.replaceUserMentions(msg.Text) | ||||
| 	// discord username must be [0..32] max | ||||
| 	if len(msg.Username) > 32 { | ||||
| 		msg.Username = msg.Username[0:32] | ||||
| 	} | ||||
|  | ||||
| 	if msg.ID != "" { | ||||
| 		b.Log.Debugf("Editing webhook message") | ||||
| 		err := b.transmitter.Edit(channelID, msg.ID, &discordgo.WebhookParams{ | ||||
| 			Content:  msg.Text, | ||||
| 			Username: msg.Username, | ||||
| 		}) | ||||
| 		if err == nil { | ||||
| 			return msg.ID, nil | ||||
| 		} | ||||
| 		b.Log.Errorf("Could not edit webhook message: %s", err) | ||||
| 	} | ||||
|  | ||||
| 	b.Log.Debugf("Processing webhook sending for message %#v", msg) | ||||
| 	discordMsg, err := b.webhookSend(msg, channelID) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("Could not broadcast via webhook for message %#v: %s", msg, err) | ||||
| 		return "", err | ||||
| 	} | ||||
| 	if discordMsg == nil { | ||||
| 		return "", nil | ||||
| 	} | ||||
|  | ||||
| 	return discordMsg.ID, nil | ||||
| } | ||||
| @@ -51,6 +51,30 @@ func DownloadFileAuth(url string, auth string) (*[]byte, error) { | ||||
| 	return &data, nil | ||||
| } | ||||
|  | ||||
| // DownloadFileAuthRocket downloads the given URL using the specified Rocket user ID and authentication token. | ||||
| func DownloadFileAuthRocket(url, token, userID string) (*[]byte, error) { | ||||
| 	var buf bytes.Buffer | ||||
| 	client := &http.Client{ | ||||
| 		Timeout: time.Second * 5, | ||||
| 	} | ||||
| 	req, err := http.NewRequest("GET", url, nil) | ||||
|  | ||||
| 	req.Header.Add("X-Auth-Token", token) | ||||
| 	req.Header.Add("X-User-Id", userID) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	resp, err := client.Do(req) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	defer resp.Body.Close() | ||||
| 	_, err = io.Copy(&buf, resp.Body) | ||||
| 	data := buf.Bytes() | ||||
| 	return &data, err | ||||
| } | ||||
|  | ||||
| // GetSubLines splits messages in newline-delimited lines. If maxLineLength is | ||||
| // specified as non-zero GetSubLines will also clip long lines to the maximum | ||||
| // length and insert a warning marker that the line was clipped. | ||||
| @@ -183,7 +207,7 @@ 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 | parser.NoIntraEmphasis | ||||
| 	extensions := parser.HardLineBreak | parser.NoIntraEmphasis | parser.FencedCode | ||||
| 	markdownParser := parser.NewWithExtensions(extensions) | ||||
| 	renderer := html.NewRenderer(html.RendererOptions{ | ||||
| 		Flags: 0, | ||||
| @@ -224,35 +248,52 @@ func CanConvertTgsToX() error { | ||||
| // 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") | ||||
| 	tmpInFile, err := ioutil.TempFile(os.TempDir(), "matterbridge-lottie-input-*.tgs") | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	tmpFileName := tmpFile.Name() | ||||
| 	tmpInFileName := tmpInFile.Name() | ||||
| 	defer func() { | ||||
| 		if removeErr := os.Remove(tmpFileName); removeErr != nil { | ||||
| 			logger.Errorf("Could not delete temporary file %s: %v", tmpFileName, removeErr) | ||||
| 		if removeErr := os.Remove(tmpInFileName); removeErr != nil { | ||||
| 			logger.Errorf("Could not delete temporary (input) file %s: %v", tmpInFileName, removeErr) | ||||
| 		} | ||||
| 	}() | ||||
| 	// lottie can handle writing to a pipe, but there is no way to do that platform-independently. | ||||
| 	// "/dev/stdout" won't work on Windows, and "-" upsets Cairo for some reason. So we need another file: | ||||
| 	tmpOutFile, err := ioutil.TempFile(os.TempDir(), "matterbridge-lottie-output-*.data") | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	tmpOutFileName := tmpOutFile.Name() | ||||
| 	defer func() { | ||||
| 		if removeErr := os.Remove(tmpOutFileName); removeErr != nil { | ||||
| 			logger.Errorf("Could not delete temporary (output) file %s: %v", tmpOutFileName, removeErr) | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	if _, writeErr := tmpFile.Write(*data); writeErr != nil { | ||||
| 	if _, writeErr := tmpInFile.Write(*data); writeErr != nil { | ||||
| 		return writeErr | ||||
| 	} | ||||
| 	// Must close before calling lottie to avoid data races: | ||||
| 	if closeErr := tmpFile.Close(); closeErr != nil { | ||||
| 	if closeErr := tmpInFile.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 := exec.Command("lottie_convert.py", "--input-format", "lottie", "--output-format", outputFormat, tmpInFileName, tmpOutFileName) | ||||
| 	cmd.Stdout = nil | ||||
| 	cmd.Stderr = nil | ||||
| 	// NB: lottie writes progress into to stderr in all cases. | ||||
| 	stdout, stderr := cmd.Output() | ||||
| 	_, stderr := cmd.Output() | ||||
| 	if stderr != nil { | ||||
| 		// 'stderr' already contains some parts of Stderr, because it was set to 'nil'. | ||||
| 		return stderr | ||||
| 	} | ||||
| 	dataContents, err := ioutil.ReadFile(tmpOutFileName) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	*data = stdout | ||||
| 	*data = dataContents | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -67,6 +67,20 @@ func (b *Birc) handleFiles(msg *config.Message) bool { | ||||
| 	return true | ||||
| } | ||||
|  | ||||
| func (b *Birc) handleInvite(client *girc.Client, event girc.Event) { | ||||
| 	if len(event.Params) != 2 { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	channel := event.Params[1] | ||||
|  | ||||
| 	b.Log.Debugf("got invite for %s", channel) | ||||
|  | ||||
| 	if _, ok := b.channels[channel]; ok { | ||||
| 		b.i.Cmd.Join(channel) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *Birc) handleJoinPart(client *girc.Client, event girc.Event) { | ||||
| 	if len(event.Params) == 0 { | ||||
| 		b.Log.Debugf("handleJoinPart: empty Params? %#v", event) | ||||
| @@ -109,14 +123,15 @@ func (b *Birc) handleNewConnection(client *girc.Client, event girc.Event) { | ||||
| 	i := b.i | ||||
| 	b.Nick = event.Params[0] | ||||
|  | ||||
| 	i.Handlers.Add("PRIVMSG", b.handlePrivMsg) | ||||
| 	i.Handlers.Add("CTCP_ACTION", b.handlePrivMsg) | ||||
| 	i.Handlers.AddBg("PRIVMSG", b.handlePrivMsg) | ||||
| 	i.Handlers.AddBg("CTCP_ACTION", b.handlePrivMsg) | ||||
| 	i.Handlers.Add(girc.RPL_TOPICWHOTIME, b.handleTopicWhoTime) | ||||
| 	i.Handlers.Add(girc.NOTICE, b.handleNotice) | ||||
| 	i.Handlers.Add("JOIN", b.handleJoinPart) | ||||
| 	i.Handlers.Add("PART", b.handleJoinPart) | ||||
| 	i.Handlers.Add("QUIT", b.handleJoinPart) | ||||
| 	i.Handlers.Add("KICK", b.handleJoinPart) | ||||
| 	i.Handlers.AddBg(girc.NOTICE, b.handleNotice) | ||||
| 	i.Handlers.AddBg("JOIN", b.handleJoinPart) | ||||
| 	i.Handlers.AddBg("PART", b.handleJoinPart) | ||||
| 	i.Handlers.AddBg("QUIT", b.handleJoinPart) | ||||
| 	i.Handlers.AddBg("KICK", b.handleJoinPart) | ||||
| 	i.Handlers.Add("INVITE", b.handleInvite) | ||||
| } | ||||
|  | ||||
| func (b *Birc) handleNickServ() { | ||||
| @@ -170,7 +185,14 @@ func (b *Birc) handlePrivMsg(client *girc.Client, event girc.Event) { | ||||
| 	if b.skipPrivMsg(event) { | ||||
| 		return | ||||
| 	} | ||||
| 	rmsg := config.Message{Username: event.Source.Name, Channel: strings.ToLower(event.Params[0]), Account: b.Account, UserID: event.Source.Ident + "@" + event.Source.Host} | ||||
|  | ||||
| 	rmsg := config.Message{ | ||||
| 		Username: event.Source.Name, | ||||
| 		Channel:  strings.ToLower(event.Params[0]), | ||||
| 		Account:  b.Account, | ||||
| 		UserID:   event.Source.Ident + "@" + event.Source.Host, | ||||
| 	} | ||||
|  | ||||
| 	b.Log.Debugf("== Receiving PRIVMSG: %s %s %#v", event.Source.Name, event.Last(), event) | ||||
|  | ||||
| 	// set action event | ||||
| @@ -178,6 +200,11 @@ func (b *Birc) handlePrivMsg(client *girc.Client, event girc.Event) { | ||||
| 		rmsg.Event = config.EventUserAction | ||||
| 	} | ||||
|  | ||||
| 	// set NOTICE event | ||||
| 	if event.Command == "NOTICE" { | ||||
| 		rmsg.Event = config.EventNoticeIRC | ||||
| 	} | ||||
|  | ||||
| 	// strip action, we made an event if it was an action | ||||
| 	rmsg.Text += event.StripAction() | ||||
|  | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import ( | ||||
| 	"crypto/tls" | ||||
| 	"fmt" | ||||
| 	"hash/crc32" | ||||
| 	"io/ioutil" | ||||
| 	"net" | ||||
| 	"sort" | ||||
| 	"strconv" | ||||
| @@ -29,6 +30,7 @@ type Birc struct { | ||||
| 	Local                                     chan config.Message // local queue for flood control | ||||
| 	FirstConnection, authDone                 bool | ||||
| 	MessageDelay, MessageQueue, MessageLength int | ||||
| 	channels                                  map[string]bool | ||||
|  | ||||
| 	*bridge.Config | ||||
| } | ||||
| @@ -39,6 +41,8 @@ func New(cfg *bridge.Config) bridge.Bridger { | ||||
| 	b.Nick = b.GetString("Nick") | ||||
| 	b.names = make(map[string][]string) | ||||
| 	b.connected = make(chan error) | ||||
| 	b.channels = make(map[string]bool) | ||||
|  | ||||
| 	if b.GetInt("MessageDelay") == 0 { | ||||
| 		b.MessageDelay = 1300 | ||||
| 	} else { | ||||
| @@ -111,6 +115,7 @@ func (b *Birc) Disconnect() error { | ||||
| } | ||||
|  | ||||
| func (b *Birc) JoinChannel(channel config.ChannelInfo) error { | ||||
| 	b.channels[channel.Name] = true | ||||
| 	// need to check if we have nickserv auth done before joining channels | ||||
| 	for { | ||||
| 		if b.authDone { | ||||
| @@ -200,22 +205,58 @@ func (b *Birc) doConnect() { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Sanitize nicks for RELAYMSG: replace IRC characters with special meanings with "-" | ||||
| func sanitizeNick(nick string) string { | ||||
| 	sanitize := func(r rune) rune { | ||||
| 		if strings.ContainsRune("!+%@&#$:'\"?*,. ", r) { | ||||
| 			return '-' | ||||
| 		} | ||||
| 		return r | ||||
| 	} | ||||
| 	return strings.Map(sanitize, nick) | ||||
| } | ||||
|  | ||||
| func (b *Birc) doSend() { | ||||
| 	rate := time.Millisecond * time.Duration(b.MessageDelay) | ||||
| 	throttle := time.NewTicker(rate) | ||||
| 	for msg := range b.Local { | ||||
| 		<-throttle.C | ||||
| 		username := msg.Username | ||||
| 		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) | ||||
| 		} | ||||
| 		if msg.Event == config.EventUserAction { | ||||
| 			b.i.Cmd.Action(msg.Channel, username+msg.Text) | ||||
| 		// Optional support for the proposed RELAYMSG extension, described at | ||||
| 		// https://github.com/jlu5/ircv3-specifications/blob/master/extensions/relaymsg.md | ||||
| 		// nolint:nestif | ||||
| 		if (b.i.HasCapability("overdrivenetworks.com/relaymsg") || b.i.HasCapability("draft/relaymsg")) && | ||||
| 			b.GetBool("UseRelayMsg") { | ||||
| 			username = sanitizeNick(username) | ||||
| 			text := msg.Text | ||||
|  | ||||
| 			// Work around girc chomping leading commas on single word messages? | ||||
| 			if strings.HasPrefix(text, ":") && !strings.ContainsRune(text, ' ') { | ||||
| 				text = ":" + text | ||||
| 			} | ||||
|  | ||||
| 			if msg.Event == config.EventUserAction { | ||||
| 				b.i.Cmd.SendRawf("RELAYMSG %s %s :\x01ACTION %s\x01", msg.Channel, username, text) //nolint:errcheck | ||||
| 			} else { | ||||
| 				b.Log.Debugf("Sending RELAYMSG to channel %s: nick=%s", msg.Channel, username) | ||||
| 				b.i.Cmd.SendRawf("RELAYMSG %s %s :%s", msg.Channel, username, text) //nolint:errcheck | ||||
| 			} | ||||
| 		} else { | ||||
| 			b.Log.Debugf("Sending to channel %s", msg.Channel) | ||||
| 			b.i.Cmd.Message(msg.Channel, username+msg.Text) | ||||
| 			if b.GetBool("Colornicks") { | ||||
| 				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) | ||||
| 			} | ||||
| 			switch msg.Event { | ||||
| 			case config.EventUserAction: | ||||
| 				b.i.Cmd.Action(msg.Channel, username+msg.Text) | ||||
| 			case config.EventNoticeIRC: | ||||
| 				b.Log.Debugf("Sending notice to channel %s", msg.Channel) | ||||
| 				b.i.Cmd.Notice(msg.Channel, username+msg.Text) | ||||
| 			default: | ||||
| 				b.Log.Debugf("Sending to channel %s", msg.Channel) | ||||
| 				b.i.Cmd.Message(msg.Channel, username+msg.Text) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -240,6 +281,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"), | ||||
| @@ -249,9 +302,11 @@ 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, | ||||
| 		AllowFlood:    true, | ||||
| 		Debug:         debug, | ||||
| 		SupportedCaps: map[string][]string{"overdrivenetworks.com/relaymsg": nil, "draft/relaymsg": nil}, | ||||
| 	}) | ||||
| 	return i, nil | ||||
| } | ||||
| @@ -277,7 +332,7 @@ func (b *Birc) skipPrivMsg(event girc.Event) bool { | ||||
| 	b.Nick = b.i.GetNick() | ||||
|  | ||||
| 	// freenode doesn't send 001 as first reply | ||||
| 	if event.Command == "NOTICE" { | ||||
| 	if event.Command == "NOTICE" && len(event.Params) != 2 { | ||||
| 		return true | ||||
| 	} | ||||
| 	// don't forward queries to the bot | ||||
| @@ -288,6 +343,15 @@ func (b *Birc) skipPrivMsg(event girc.Event) bool { | ||||
| 	if event.Source.Name == b.Nick { | ||||
| 		return true | ||||
| 	} | ||||
| 	// don't forward messages we sent via RELAYMSG | ||||
| 	if relayedNick, ok := event.Tags.Get("draft/relaymsg"); ok && relayedNick == b.Nick { | ||||
| 		return true | ||||
| 	} | ||||
| 	// This is the old name of the cap sent in spoofed messages; I've kept this in | ||||
| 	// for compatibility reasons | ||||
| 	if relayedNick, ok := event.Tags.Get("relaymsg"); ok && relayedNick == b.Nick { | ||||
| 		return true | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										215
									
								
								bridge/matrix/helpers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								bridge/matrix/helpers.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,215 @@ | ||||
| package bmatrix | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"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. | ||||
| 	// In addition, we also detect if another user have the same username, and if so, we append their mxids to their usernames to differentiate them. | ||||
| 	toDelete := []string{} | ||||
| 	conflict := false | ||||
|  | ||||
| 	b.Lock() | ||||
| 	for mxid, v := range b.NicknameMap { | ||||
| 		// to prevent username reuse across matrix servers - or even on the same server, append | ||||
| 		// the mxid to the username when there is a conflict | ||||
| 		if v.displayName == displayName { | ||||
| 			conflict = true | ||||
| 			// TODO: it would be nice to be able to rename previous messages from this user. | ||||
| 			// The current behavior is that only users with clashing usernames and *that have spoken since the bridge last started* will get their mxids shown, and I don't know if that's the expected behavior. | ||||
| 			v.displayName = fmt.Sprintf("%s (%s)", displayName, mxid) | ||||
| 			b.NicknameMap[mxid] = v | ||||
| 		} | ||||
|  | ||||
| 		if now.Sub(v.lastUpdated) > 10*time.Minute { | ||||
| 			toDelete = append(toDelete, mxid) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if conflict { | ||||
| 		displayName = fmt.Sprintf("%s (%s)", displayName, mxid) | ||||
| 	} | ||||
|  | ||||
| 	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 | ||||
| } | ||||
|  | ||||
| // handleRatelimit handles the ratelimit errors and return if we're ratelimited and the amount of time to sleep | ||||
| func (b *Bmatrix) handleRatelimit(err error) (time.Duration, bool) { | ||||
| 	httpErr := handleError(err) | ||||
| 	if httpErr.Errcode != "M_LIMIT_EXCEEDED" { | ||||
| 		return 0, false | ||||
| 	} | ||||
|  | ||||
| 	b.Log.Debugf("ratelimited: %s", httpErr.Err) | ||||
| 	b.Log.Infof("getting ratelimited by matrix, sleeping approx %d seconds before retrying", httpErr.RetryAfterMs/1000) | ||||
|  | ||||
| 	return time.Duration(httpErr.RetryAfterMs) * time.Millisecond, true | ||||
| } | ||||
|  | ||||
| // retry function will check if we're ratelimited and retries again when backoff time expired | ||||
| // returns original error if not 429 ratelimit | ||||
| func (b *Bmatrix) retry(f func() error) error { | ||||
| 	b.rateMutex.Lock() | ||||
| 	defer b.rateMutex.Unlock() | ||||
|  | ||||
| 	for { | ||||
| 		if err := f(); err != nil { | ||||
| 			if backoff, ok := b.handleRatelimit(err); ok { | ||||
| 				time.Sleep(backoff) | ||||
| 			} else { | ||||
| 				return err | ||||
| 			} | ||||
| 		} else { | ||||
| 			return nil | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -2,9 +2,7 @@ package bmatrix | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"html" | ||||
| 	"mime" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
| @@ -17,13 +15,23 @@ import ( | ||||
| 	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 | ||||
| 	rateMutex   sync.RWMutex | ||||
| 	sync.RWMutex | ||||
| 	htmlTag            *regexp.Regexp | ||||
| 	htmlReplacementTag *regexp.Regexp | ||||
| 	*bridge.Config | ||||
| } | ||||
|  | ||||
| @@ -33,11 +41,34 @@ type httpError struct { | ||||
| 	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.htmlReplacementTag = regexp.MustCompile("<[^>]*>") | ||||
| 	b.RoomMap = make(map[string]string) | ||||
| 	b.NicknameMap = make(map[string]NicknameCacheEntry) | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| @@ -69,25 +100,18 @@ 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 b.retry(func() error { | ||||
| 		resp, err := b.mc.JoinRoom(channel.Name, "", nil) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		return err | ||||
| 	} | ||||
| 		b.Lock() | ||||
| 		b.RoomMap[resp.RoomID] = channel.Name | ||||
| 		b.Unlock() | ||||
|  | ||||
| 	b.Lock() | ||||
| 	b.RoomMap[resp.RoomID] = channel.Name | ||||
| 	b.Unlock() | ||||
|  | ||||
| 	return nil | ||||
| 		return nil | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func (b *Bmatrix) Send(msg config.Message) (string, error) { | ||||
| @@ -96,17 +120,30 @@ 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 { | ||||
| 			return "", err | ||||
| 		} | ||||
| 		return resp.EventID, err | ||||
|  | ||||
| 		msgID := "" | ||||
|  | ||||
| 		err := b.retry(func() error { | ||||
| 			resp, err := b.mc.SendMessageEvent(channel, "m.room.message", m) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
|  | ||||
| 			msgID = resp.EventID | ||||
|  | ||||
| 			return err | ||||
| 		}) | ||||
|  | ||||
| 		return msgID, err | ||||
| 	} | ||||
|  | ||||
| 	// Delete message | ||||
| @@ -114,17 +151,34 @@ func (b *Bmatrix) Send(msg config.Message) (string, error) { | ||||
| 		if msg.ID == "" { | ||||
| 			return "", nil | ||||
| 		} | ||||
| 		resp, err := b.mc.RedactEvent(channel, msg.ID, &matrix.ReqRedact{}) | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
| 		return resp.EventID, err | ||||
|  | ||||
| 		msgID := "" | ||||
|  | ||||
| 		err := b.retry(func() error { | ||||
| 			resp, err := b.mc.RedactEvent(channel, msg.ID, &matrix.ReqRedact{}) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
|  | ||||
| 			msgID = resp.EventID | ||||
|  | ||||
| 			return err | ||||
| 		}) | ||||
|  | ||||
| 		return msgID, err | ||||
| 	} | ||||
|  | ||||
| 	// Upload a file if it exists | ||||
| 	if msg.Extra != nil { | ||||
| 		for _, rmsg := range helper.HandleExtra(&msg, b.General) { | ||||
| 			if _, err := b.mc.SendText(channel, rmsg.Username+rmsg.Text); err != nil { | ||||
| 			rmsg := rmsg | ||||
|  | ||||
| 			err := b.retry(func() error { | ||||
| 				_, err := b.mc.SendText(channel, rmsg.Username+rmsg.Text) | ||||
|  | ||||
| 				return err | ||||
| 			}) | ||||
| 			if err != nil { | ||||
| 				b.Log.Errorf("sendText failed: %s", err) | ||||
| 			} | ||||
| 		} | ||||
| @@ -135,60 +189,105 @@ 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", | ||||
| 		} | ||||
|  | ||||
| 	// Use notices to send join/leave events | ||||
| 	if msg.Event == config.EventJoinLeave { | ||||
| 		resp, err := b.mc.SendNotice(channel, msg.Username+msg.Text) | ||||
| 		err := b.retry(func() error { | ||||
| 			_, err := b.mc.SendMessageEvent(channel, "m.room.message", rmsg) | ||||
|  | ||||
| 			return err | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
|  | ||||
| 		return msg.ID, nil | ||||
| 	} | ||||
|  | ||||
| 	// Use notices to send join/leave events | ||||
| 	if msg.Event == config.EventJoinLeave { | ||||
| 		m := matrix.TextMessage{ | ||||
| 			MsgType:       "m.notice", | ||||
| 			Body:          username.plain + msg.Text, | ||||
| 			FormattedBody: username.formatted + msg.Text, | ||||
| 		} | ||||
|  | ||||
| 		var ( | ||||
| 			resp *matrix.RespSendEvent | ||||
| 			err  error | ||||
| 		) | ||||
|  | ||||
| 		err = b.retry(func() error { | ||||
| 			resp, err = b.mc.SendMessageEvent(channel, "m.room.message", m) | ||||
|  | ||||
| 			return err | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
|  | ||||
| 		return resp.EventID, err | ||||
| 	} | ||||
|  | ||||
| 	if b.GetBool("HTMLDisable") { | ||||
| 		resp, err := b.mc.SendText(channel, msg.Username+msg.Text) | ||||
| 		var ( | ||||
| 			resp *matrix.RespSendEvent | ||||
| 			err  error | ||||
| 		) | ||||
|  | ||||
| 		err = b.retry(func() error { | ||||
| 			resp, err = b.mc.SendText(channel, username.plain+msg.Text) | ||||
|  | ||||
| 			return err | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
|  | ||||
| 		return resp.EventID, err | ||||
| 	} | ||||
|  | ||||
| 	var username string | ||||
| 	var plainUsername string | ||||
| 	// check if we have a </tag>. if we have, we don't escape HTML. #696 | ||||
| 	if b.htmlTag.MatchString(msg.Username) { | ||||
| 		username = msg.Username | ||||
| 		// remove the HTML formatting for beautiful push messages #1188 | ||||
| 		plainUsername = b.htmlReplacementTag.ReplaceAllString(msg.Username, "") | ||||
| 	} else { | ||||
| 		username = html.EscapeString(msg.Username) | ||||
| 		plainUsername = msg.Username | ||||
| 	} | ||||
|  | ||||
| 	// Post normal message with HTML support (eg riot.im) | ||||
| 	resp, err := b.mc.SendFormattedText(channel, plainUsername+msg.Text, username+helper.ParseMarkdown(msg.Text)) | ||||
| 	var ( | ||||
| 		resp *matrix.RespSendEvent | ||||
| 		err  error | ||||
| 	) | ||||
|  | ||||
| 	err = b.retry(func() error { | ||||
| 		resp, err = b.mc.SendFormattedText(channel, username.plain+msg.Text, | ||||
| 			username.formatted+helper.ParseMarkdown(msg.Text)) | ||||
|  | ||||
| 		return err | ||||
| 	}) | ||||
| 	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 "" | ||||
| 	return resp.EventID, err | ||||
| } | ||||
|  | ||||
| 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 { | ||||
| @@ -198,6 +297,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 { | ||||
| @@ -211,7 +349,7 @@ func (b *Bmatrix) handleEvent(ev *matrix.Event) { | ||||
|  | ||||
| 		// Create our message | ||||
| 		rmsg := config.Message{ | ||||
| 			Username: ev.Sender[1:], | ||||
| 			Username: b.getDisplayName(ev.Sender), | ||||
| 			Channel:  channel, | ||||
| 			Account:  b.Account, | ||||
| 			UserID:   ev.Sender, | ||||
| @@ -246,6 +384,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) | ||||
| @@ -256,6 +399,11 @@ func (b *Bmatrix) handleEvent(ev *matrix.Event) { | ||||
|  | ||||
| 		b.Log.Debugf("<= Sending message from %s on %s to gateway", ev.Sender, b.Account) | ||||
| 		b.Remote <- rmsg | ||||
|  | ||||
| 		// not crucial, so no ratelimit check here | ||||
| 		if err := b.mc.MarkRead(ev.RoomID, ev.ID); err != nil { | ||||
| 			b.Log.Errorf("couldn't mark message as read %s", err.Error()) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -330,27 +478,30 @@ 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.retry(func() error { | ||||
| 		_, err := b.mc.SendFormattedText(channel, username.plain+fi.Comment, username.formatted+fi.Comment) | ||||
|  | ||||
| 		return err | ||||
| 	}) | ||||
| 	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))) | ||||
|  | ||||
| 	var res *matrix.RespMediaUpload | ||||
|  | ||||
| 	err = b.retry(func() error { | ||||
| 		res, err = b.mc.UploadToContentRepo(content, mtype, int64(len(*fi.Data))) | ||||
|  | ||||
| 		return err | ||||
| 	}) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("file upload failed: %#v", err) | ||||
| 		return | ||||
| @@ -359,99 +510,60 @@ func (b *Bmatrix) handleUploadFile(msg *config.Message, channel string, fi *conf | ||||
| 	switch { | ||||
| 	case strings.Contains(mtype, "video"): | ||||
| 		b.Log.Debugf("sendVideo %s", res.ContentURI) | ||||
| 		_, err = b.mc.SendVideo(channel, fi.Name, res.ContentURI) | ||||
| 		err = b.retry(func() error { | ||||
| 			_, err = b.mc.SendVideo(channel, fi.Name, res.ContentURI) | ||||
|  | ||||
| 			return err | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("sendVideo failed: %#v", err) | ||||
| 		} | ||||
| 	case strings.Contains(mtype, "image"): | ||||
| 		b.Log.Debugf("sendImage %s", res.ContentURI) | ||||
| 		_, err = b.mc.SendImage(channel, fi.Name, res.ContentURI) | ||||
| 		err = b.retry(func() error { | ||||
| 			_, err = b.mc.SendImage(channel, fi.Name, res.ContentURI) | ||||
|  | ||||
| 			return err | ||||
| 		}) | ||||
| 		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.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) | ||||
| 		} | ||||
| 	case strings.Contains(mtype, "audio"): | ||||
| 		b.Log.Debugf("sendAudio %s", res.ContentURI) | ||||
| 		_, 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)), | ||||
| 			}, | ||||
| 		err = b.retry(func() error { | ||||
| 			_, 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)), | ||||
| 				}, | ||||
| 			}) | ||||
|  | ||||
| 			return err | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("sendAudio failed: %#v", err) | ||||
| 		} | ||||
| 	default: | ||||
| 		b.Log.Debugf("sendFile %s", res.ContentURI) | ||||
| 		err = b.retry(func() error { | ||||
| 			_, 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)), | ||||
| 				}, | ||||
| 			}) | ||||
|  | ||||
| 			return err | ||||
| 		}) | ||||
| 		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 | ||||
| } | ||||
|  | ||||
| // 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 | ||||
| } | ||||
|  | ||||
| func handleError(err error) *httpError { | ||||
| 	mErr, ok := err.(matrix.HTTPError) | ||||
| 	if !ok { | ||||
| 		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 | ||||
| } | ||||
|   | ||||
							
								
								
									
										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) | ||||
| } | ||||
| @@ -108,7 +108,7 @@ func (b *Bmattermost) handleMatterClient(messages chan *config.Message) { | ||||
| 			Channel:  message.Channel, | ||||
| 			Text:     message.Text, | ||||
| 			ID:       message.Post.Id, | ||||
| 			ParentID: message.Post.ParentId, | ||||
| 			ParentID: message.Post.RootId, // ParentID is obsolete with mattermost | ||||
| 			Extra:    make(map[string][]interface{}), | ||||
| 		} | ||||
|  | ||||
|   | ||||
| @@ -122,11 +122,20 @@ func (b *Bmattermost) Send(msg config.Message) (string, error) { | ||||
| 	} | ||||
|  | ||||
| 	// Handle prefix hint for unthreaded messages. | ||||
| 	if msg.ParentID == "msg-parent-not-found" { | ||||
| 	if msg.ParentNotFound() { | ||||
| 		msg.ParentID = "" | ||||
| 		msg.Text = fmt.Sprintf("[thread]: %s", msg.Text) | ||||
| 	} | ||||
|  | ||||
| 	// we only can reply to the root of the thread, not to a specific ID (like discord for example does) | ||||
| 	if msg.ParentID != "" { | ||||
| 		post, res := b.mc.Client.GetPost(msg.ParentID, "") | ||||
| 		if res.Error != nil { | ||||
| 			b.Log.Errorf("getting post %s failed: %s", msg.ParentID, res.Error.DetailedError) | ||||
| 		} | ||||
| 		msg.ParentID = post.RootId | ||||
| 	} | ||||
|  | ||||
| 	// Upload a file if it exists | ||||
| 	if msg.Extra != nil { | ||||
| 		for _, rmsg := range helper.HandleExtra(&msg, b.General) { | ||||
|   | ||||
| @@ -86,13 +86,16 @@ func (b *Bmsteams) JoinChannel(channel config.ChannelInfo) error { | ||||
|  | ||||
| func (b *Bmsteams) Send(msg config.Message) (string, error) { | ||||
| 	b.Log.Debugf("=> Receiving %#v", msg) | ||||
| 	if msg.ParentID != "" && msg.ParentID != "msg-parent-not-found" { | ||||
| 	if msg.ParentValid() { | ||||
| 		return b.sendReply(msg) | ||||
| 	} | ||||
| 	if msg.ParentID == "msg-parent-not-found" { | ||||
|  | ||||
| 	// Handle prefix hint for unthreaded messages. | ||||
| 	if msg.ParentNotFound() { | ||||
| 		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} | ||||
|   | ||||
							
								
								
									
										96
									
								
								bridge/mumble/handlers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								bridge/mumble/handlers.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| 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 | ||||
| 	} | ||||
| 	// If the text message is received before receiving a ServerSync | ||||
| 	// and UserState, Client.Self or Self.Channel are nil | ||||
| 	if event.Client.Self == nil || event.Client.Self.Channel == nil { | ||||
| 		b.Log.Warn("Connection bootstrap not finished, discarding text message") | ||||
| 		return | ||||
| 	} | ||||
| 	// 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) | ||||
| 	} | ||||
| } | ||||
| @@ -9,7 +9,6 @@ import ( | ||||
| 	"github.com/42wim/matterbridge/bridge" | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
|  | ||||
| 	talk "gomod.garykim.dev/nc-talk" | ||||
| 	"gomod.garykim.dev/nc-talk/ocs" | ||||
| 	"gomod.garykim.dev/nc-talk/room" | ||||
| 	"gomod.garykim.dev/nc-talk/user" | ||||
| @@ -61,8 +60,12 @@ func (b *Btalk) Disconnect() error { | ||||
| } | ||||
|  | ||||
| func (b *Btalk) JoinChannel(channel config.ChannelInfo) error { | ||||
| 	tr, err := room.NewTalkRoom(b.user, channel.Name) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	newRoom := Broom{ | ||||
| 		room: talk.NewRoom(b.user, channel.Name), | ||||
| 		room: tr, | ||||
| 	} | ||||
| 	newRoom.ctx, newRoom.ctxCancel = context.WithCancel(context.Background()) | ||||
| 	c, err := newRoom.room.ReceiveMessages(newRoom.ctx) | ||||
| @@ -70,8 +73,23 @@ func (b *Btalk) JoinChannel(channel config.ChannelInfo) error { | ||||
| 		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 | ||||
|  | ||||
| 			if msg.Error != nil { | ||||
| 				b.Log.Errorf("Fatal message poll error: %s\n", msg.Error) | ||||
|  | ||||
| 				return | ||||
| 			} | ||||
|  | ||||
| 			// ignore messages that are one of the following | ||||
| 			// * not a message from a user | ||||
| 			// * from ourselves | ||||
| @@ -81,7 +99,7 @@ func (b *Btalk) JoinChannel(channel config.ChannelInfo) error { | ||||
| 			remoteMessage := config.Message{ | ||||
| 				Text:     formatRichObjectString(msg.Message, msg.MessageParameters), | ||||
| 				Channel:  newRoom.room.Token, | ||||
| 				Username: msg.ActorDisplayName, | ||||
| 				Username: DisplayName(msg, guestSuffix), | ||||
| 				UserID:   msg.ActorID, | ||||
| 				Account:  b.Account, | ||||
| 			} | ||||
| @@ -90,6 +108,15 @@ func (b *Btalk) JoinChannel(channel config.ChannelInfo) error { | ||||
| 			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 | ||||
| 		} | ||||
| @@ -125,6 +152,31 @@ func (b *Btalk) getRoom(token string) *Broom { | ||||
| 	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 { | ||||
| @@ -135,7 +187,7 @@ func formatRichObjectString(message string, parameters map[string]ocs.RichObject | ||||
| 			text = "@" + text | ||||
| 		case ocs.ROSTypeFile: | ||||
| 			if parameter.Link != "" { | ||||
| 				text = parameter.Link | ||||
| 				text = parameter.Name | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| @@ -144,3 +196,15 @@ func formatRichObjectString(message string, parameters map[string]ocs.RichObject | ||||
|  | ||||
| 	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 | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,10 @@ | ||||
| package brocketchat | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/42wim/matterbridge/bridge/helper" | ||||
| 	"github.com/matterbridge/Rocket.Chat.Go.SDK/models" | ||||
| ) | ||||
|  | ||||
| @@ -58,6 +61,7 @@ func (b *Brocketchat) handleStatusEvent(ev models.Message, rmsg *config.Message) | ||||
|  | ||||
| func (b *Brocketchat) handleRocketClient(messages chan *config.Message) { | ||||
| 	for message := range b.messageChan { | ||||
| 		message := message | ||||
| 		// skip messages with same ID, apparently messages get duplicated for an unknown reason | ||||
| 		if _, ok := b.cache.Get(message.ID); ok { | ||||
| 			continue | ||||
| @@ -76,8 +80,11 @@ func (b *Brocketchat) handleRocketClient(messages chan *config.Message) { | ||||
| 			Account:  b.Account, | ||||
| 			UserID:   message.User.ID, | ||||
| 			ID:       message.ID, | ||||
| 			Extra:    make(map[string][]interface{}), | ||||
| 		} | ||||
|  | ||||
| 		b.handleAttachments(&message, 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) { | ||||
| @@ -86,6 +93,38 @@ func (b *Brocketchat) handleRocketClient(messages chan *config.Message) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *Brocketchat) handleAttachments(message *models.Message, rmsg *config.Message) { | ||||
| 	if rmsg.Text == "" { | ||||
| 		for _, attachment := range message.Attachments { | ||||
| 			if attachment.Title != "" { | ||||
| 				rmsg.Text = attachment.Title + "\n" | ||||
| 			} | ||||
| 			if attachment.Title != "" && attachment.Text != "" { | ||||
| 				rmsg.Text += "\n" | ||||
| 			} | ||||
| 			if attachment.Text != "" { | ||||
| 				rmsg.Text += attachment.Text | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for i := range message.Attachments { | ||||
| 		if err := b.handleDownloadFile(rmsg, &message.Attachments[i]); err != nil { | ||||
| 			b.Log.Errorf("Could not download incoming file: %#v", err) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *Brocketchat) handleDownloadFile(rmsg *config.Message, file *models.Attachment) error { | ||||
| 	downloadURL := b.GetString("server") + file.TitleLink | ||||
| 	data, err := helper.DownloadFileAuthRocket(downloadURL, b.user.Token, b.user.ID) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("download %s failed %#v", downloadURL, err) | ||||
| 	} | ||||
| 	helper.HandleDownloadData(b.Log, rmsg, file.Title, rmsg.Text, downloadURL, data, b.General) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Brocketchat) handleUploadFile(msg *config.Message) error { | ||||
| 	for _, f := range msg.Extra["file"] { | ||||
| 		fi := f.(config.FileInfo) | ||||
|   | ||||
| @@ -299,7 +299,7 @@ func (b *Bslack) sendRTM(msg config.Message) (string, error) { | ||||
| 	} | ||||
|  | ||||
| 	// Handle prefix hint for unthreaded messages. | ||||
| 	if msg.ParentID == "msg-parent-not-found" { | ||||
| 	if msg.ParentNotFound() { | ||||
| 		msg.ParentID = "" | ||||
| 		msg.Text = fmt.Sprintf("[thread]: %s", msg.Text) | ||||
| 	} | ||||
|   | ||||
| @@ -2,7 +2,7 @@ package btelegram | ||||
|  | ||||
| import ( | ||||
| 	"html" | ||||
| 	"regexp" | ||||
| 	"path/filepath" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"unicode/utf16" | ||||
| @@ -181,13 +181,15 @@ func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) { | ||||
| // sends a EVENT_AVATAR_DOWNLOAD message to the gateway if successful. | ||||
| // logs an error message if it fails | ||||
| func (b *Btelegram) handleDownloadAvatar(userid int, channel string) { | ||||
| 	rmsg := config.Message{Username: "system", | ||||
| 		Text:    "avatar", | ||||
| 		Channel: channel, | ||||
| 		Account: b.Account, | ||||
| 		UserID:  strconv.Itoa(userid), | ||||
| 		Event:   config.EventAvatarDownload, | ||||
| 		Extra:   make(map[string][]interface{})} | ||||
| 	rmsg := config.Message{ | ||||
| 		Username: "system", | ||||
| 		Text:     "avatar", | ||||
| 		Channel:  channel, | ||||
| 		Account:  b.Account, | ||||
| 		UserID:   strconv.Itoa(userid), | ||||
| 		Event:    config.EventAvatarDownload, | ||||
| 		Extra:    make(map[string][]interface{}), | ||||
| 	} | ||||
|  | ||||
| 	if _, ok := b.avatarMap[strconv.Itoa(userid)]; !ok { | ||||
| 		photos, err := b.c.GetUserProfilePhotos(tgbotapi.UserProfilePhotosConfig{UserID: userid, Limit: 1}) | ||||
| @@ -311,6 +313,11 @@ func (b *Btelegram) handleDownload(rmsg *config.Message, message *tgbotapi.Messa | ||||
| 		b.maybeConvertWebp(&name, data) | ||||
| 	} | ||||
|  | ||||
| 	// rename .oga to .ogg  https://github.com/42wim/matterbridge/issues/906#issuecomment-741793512 | ||||
| 	if strings.HasSuffix(name, ".oga") && message.Audio != nil { | ||||
| 		name = strings.Replace(name, ".oga", ".ogg", 1) | ||||
| 	} | ||||
|  | ||||
| 	helper.HandleDownloadData(b.Log, rmsg, name, message.Caption, "", data, b.General) | ||||
| 	return nil | ||||
| } | ||||
| @@ -384,21 +391,32 @@ func (b *Btelegram) handleUploadFile(msg *config.Message, chatid int64) string { | ||||
| 			Name:  fi.Name, | ||||
| 			Bytes: *fi.Data, | ||||
| 		} | ||||
| 		re := regexp.MustCompile(".(jpg|png)$") | ||||
| 		if re.MatchString(fi.Name) { | ||||
| 			c = tgbotapi.NewPhotoUpload(chatid, file) | ||||
| 		} else { | ||||
| 			c = tgbotapi.NewDocumentUpload(chatid, file) | ||||
| 		switch filepath.Ext(fi.Name) { | ||||
| 		case ".jpg", ".jpe", ".png": | ||||
| 			pc := tgbotapi.NewPhotoUpload(chatid, file) | ||||
| 			pc.Caption, pc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment) | ||||
| 			c = pc | ||||
| 		case ".mp4", ".m4v": | ||||
| 			vc := tgbotapi.NewVideoUpload(chatid, file) | ||||
| 			vc.Caption, vc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment) | ||||
| 			c = vc | ||||
| 		case ".mp3", ".oga": | ||||
| 			ac := tgbotapi.NewAudioUpload(chatid, file) | ||||
| 			ac.Caption, ac.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment) | ||||
| 			c = ac | ||||
| 		case ".ogg": | ||||
| 			voc := tgbotapi.NewVoiceUpload(chatid, file) | ||||
| 			voc.Caption, voc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment) | ||||
| 			c = voc | ||||
| 		default: | ||||
| 			dc := tgbotapi.NewDocumentUpload(chatid, file) | ||||
| 			dc.Caption, dc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment) | ||||
| 			c = dc | ||||
| 		} | ||||
| 		_, err := b.c.Send(c) | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("file upload failed: %#v", err) | ||||
| 		} | ||||
| 		if fi.Comment != "" { | ||||
| 			if _, err := b.sendMessage(chatid, msg.Username, fi.Comment); err != nil { | ||||
| 				b.Log.Errorf("posting file comment %s failed: %s", fi.Comment, err) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
| @@ -408,7 +426,7 @@ func (b *Btelegram) handleQuote(message, quoteNick, quoteMessage string) string | ||||
| 	if format == "" { | ||||
| 		format = "{MESSAGE} (re @{QUOTENICK}: {QUOTEMESSAGE})" | ||||
| 	} | ||||
| 	quoteMessagelength := len(quoteMessage) | ||||
| 	quoteMessagelength := len([]rune(quoteMessage)) | ||||
| 	if b.GetInt("QuoteLengthLimit") != 0 && quoteMessagelength >= b.GetInt("QuoteLengthLimit") { | ||||
| 		runes := []rune(quoteMessage) | ||||
| 		quoteMessage = string(runes[0:b.GetInt("QuoteLengthLimit")]) | ||||
|   | ||||
| @@ -69,6 +69,28 @@ func (b *Btelegram) JoinChannel(channel config.ChannelInfo) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func TGGetParseMode(b *Btelegram, username string, text string) (textout string, parsemode string) { | ||||
| 	textout = username + text | ||||
| 	if b.GetString("MessageFormat") == HTMLFormat { | ||||
| 		b.Log.Debug("Using mode HTML") | ||||
| 		parsemode = tgbotapi.ModeHTML | ||||
| 	} | ||||
| 	if b.GetString("MessageFormat") == "Markdown" { | ||||
| 		b.Log.Debug("Using mode markdown") | ||||
| 		parsemode = tgbotapi.ModeMarkdown | ||||
| 	} | ||||
| 	if b.GetString("MessageFormat") == MarkdownV2 { | ||||
| 		b.Log.Debug("Using mode MarkdownV2") | ||||
| 		parsemode = MarkdownV2 | ||||
| 	} | ||||
| 	if strings.ToLower(b.GetString("MessageFormat")) == HTMLNick { | ||||
| 		b.Log.Debug("Using mode HTML - nick only") | ||||
| 		textout = username + html.EscapeString(text) | ||||
| 		parsemode = tgbotapi.ModeHTML | ||||
| 	} | ||||
| 	return textout, parsemode | ||||
| } | ||||
|  | ||||
| func (b *Btelegram) Send(msg config.Message) (string, error) { | ||||
| 	b.Log.Debugf("=> Receiving %#v", msg) | ||||
|  | ||||
| @@ -131,24 +153,7 @@ func (b *Btelegram) getFileDirectURL(id string) string { | ||||
|  | ||||
| func (b *Btelegram) sendMessage(chatid int64, username, text string) (string, error) { | ||||
| 	m := tgbotapi.NewMessage(chatid, "") | ||||
| 	m.Text = username + text | ||||
| 	if b.GetString("MessageFormat") == HTMLFormat { | ||||
| 		b.Log.Debug("Using mode HTML") | ||||
| 		m.ParseMode = tgbotapi.ModeHTML | ||||
| 	} | ||||
| 	if b.GetString("MessageFormat") == "Markdown" { | ||||
| 		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.Text, m.ParseMode = TGGetParseMode(b, username, text) | ||||
|  | ||||
| 	m.DisableWebPagePreview = b.GetBool("DisableWebPagePreview") | ||||
|  | ||||
|   | ||||
							
								
								
									
										327
									
								
								bridge/vk/vk.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										327
									
								
								bridge/vk/vk.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,327 @@ | ||||
| package bvk | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"regexp" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/42wim/matterbridge/bridge" | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/42wim/matterbridge/bridge/helper" | ||||
|  | ||||
| 	"github.com/SevereCloud/vksdk/v2/api" | ||||
| 	"github.com/SevereCloud/vksdk/v2/events" | ||||
| 	longpoll "github.com/SevereCloud/vksdk/v2/longpoll-bot" | ||||
| 	"github.com/SevereCloud/vksdk/v2/object" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	audioMessage = "audio_message" | ||||
| 	document     = "doc" | ||||
| 	photo        = "photo" | ||||
| 	video        = "video" | ||||
| 	graffiti     = "graffiti" | ||||
| 	sticker      = "sticker" | ||||
| 	wall         = "wall" | ||||
| ) | ||||
|  | ||||
| type user struct { | ||||
| 	lastname, firstname, avatar string | ||||
| } | ||||
|  | ||||
| type Bvk struct { | ||||
| 	c            *api.VK | ||||
| 	usernamesMap map[int]user // cache of user names and avatar URLs | ||||
| 	*bridge.Config | ||||
| } | ||||
|  | ||||
| func New(cfg *bridge.Config) bridge.Bridger { | ||||
| 	return &Bvk{usernamesMap: make(map[int]user), Config: cfg} | ||||
| } | ||||
|  | ||||
| func (b *Bvk) Connect() error { | ||||
| 	b.Log.Info("Connecting") | ||||
| 	b.c = api.NewVK(b.GetString("Token")) | ||||
| 	lp, err := longpoll.NewLongPoll(b.c, b.GetInt("GroupID")) | ||||
| 	if err != nil { | ||||
| 		b.Log.Debugf("%#v", err) | ||||
|  | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	lp.MessageNew(func(ctx context.Context, obj events.MessageNewObject) { | ||||
| 		b.handleMessage(obj.Message, false) | ||||
| 	}) | ||||
|  | ||||
| 	b.Log.Info("Connection succeeded") | ||||
|  | ||||
| 	go func() { | ||||
| 		err := lp.Run() | ||||
| 		if err != nil { | ||||
| 			b.Log.Fatal("Enable longpoll in group management") | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Bvk) Disconnect() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Bvk) JoinChannel(channel config.ChannelInfo) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Bvk) Send(msg config.Message) (string, error) { | ||||
| 	b.Log.Debugf("=> Receiving %#v", msg) | ||||
|  | ||||
| 	peerID, err := strconv.Atoi(msg.Channel) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	params := api.Params{} | ||||
|  | ||||
| 	text := msg.Username + msg.Text | ||||
|  | ||||
| 	if msg.Extra != nil { | ||||
| 		if len(msg.Extra["file"]) > 0 { | ||||
| 			// generate attachments string | ||||
| 			attachment, urls := b.uploadFiles(msg.Extra, peerID) | ||||
| 			params["attachment"] = attachment | ||||
| 			text += urls | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	params["message"] = text | ||||
|  | ||||
| 	if msg.ID == "" { | ||||
| 		// New message | ||||
| 		params["random_id"] = time.Now().Unix() | ||||
| 		params["peer_ids"] = msg.Channel | ||||
|  | ||||
| 		res, e := b.c.MessagesSendPeerIDs(params) | ||||
| 		if e != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
|  | ||||
| 		return strconv.Itoa(res[0].ConversationMessageID), nil | ||||
| 	} | ||||
| 	// Edit message | ||||
| 	messageID, err := strconv.ParseInt(msg.ID, 10, 64) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	params["peer_id"] = peerID | ||||
| 	params["conversation_message_id"] = messageID | ||||
|  | ||||
| 	_, err = b.c.MessagesEdit(params) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	return msg.ID, nil | ||||
| } | ||||
|  | ||||
| func (b *Bvk) getUser(id int) user { | ||||
| 	u, found := b.usernamesMap[id] | ||||
| 	if !found { | ||||
| 		b.Log.Debug("Fetching username for ", id) | ||||
|  | ||||
| 		if id >= 0 { | ||||
| 			result, _ := b.c.UsersGet(api.Params{ | ||||
| 				"user_ids": id, | ||||
| 				"fields":   "photo_200", | ||||
| 			}) | ||||
|  | ||||
| 			resUser := result[0] | ||||
| 			u = user{lastname: resUser.LastName, firstname: resUser.FirstName, avatar: resUser.Photo200} | ||||
| 			b.usernamesMap[id] = u | ||||
| 		} else { | ||||
| 			result, _ := b.c.GroupsGetByID(api.Params{ | ||||
| 				"group_id": id * -1, | ||||
| 			}) | ||||
|  | ||||
| 			resGroup := result[0] | ||||
| 			u = user{lastname: resGroup.Name, avatar: resGroup.Photo200} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return u | ||||
| } | ||||
|  | ||||
| func (b *Bvk) handleMessage(msg object.MessagesMessage, isFwd bool) { | ||||
| 	b.Log.Debug("ChatID: ", msg.PeerID) | ||||
| 	// fetch user info | ||||
| 	u := b.getUser(msg.FromID) | ||||
|  | ||||
| 	rmsg := config.Message{ | ||||
| 		Text:     msg.Text, | ||||
| 		Username: u.firstname + " " + u.lastname, | ||||
| 		Avatar:   u.avatar, | ||||
| 		Channel:  strconv.Itoa(msg.PeerID), | ||||
| 		Account:  b.Account, | ||||
| 		UserID:   strconv.Itoa(msg.FromID), | ||||
| 		ID:       strconv.Itoa(msg.ConversationMessageID), | ||||
| 		Extra:    make(map[string][]interface{}), | ||||
| 	} | ||||
|  | ||||
| 	if msg.ReplyMessage != nil { | ||||
| 		ur := b.getUser(msg.ReplyMessage.FromID) | ||||
| 		rmsg.Text = "Re: " + ur.firstname + " " + ur.lastname + "\n" + rmsg.Text | ||||
| 	} | ||||
|  | ||||
| 	if isFwd { | ||||
| 		rmsg.Username = "Fwd: " + rmsg.Username | ||||
| 	} | ||||
|  | ||||
| 	if len(msg.Attachments) > 0 { | ||||
| 		urls, text := b.getFiles(msg.Attachments) | ||||
|  | ||||
| 		if text != "" { | ||||
| 			rmsg.Text += "\n" + text | ||||
| 		} | ||||
|  | ||||
| 		// download | ||||
| 		b.downloadFiles(&rmsg, urls) | ||||
| 	} | ||||
|  | ||||
| 	if len(msg.FwdMessages) > 0 { | ||||
| 		rmsg.Text += strconv.Itoa(len(msg.FwdMessages)) + " forwarded messages" | ||||
| 	} | ||||
|  | ||||
| 	b.Remote <- rmsg | ||||
|  | ||||
| 	if len(msg.FwdMessages) > 0 { | ||||
| 		// recursive processing of forwarded messages | ||||
| 		for _, m := range msg.FwdMessages { | ||||
| 			m.PeerID = msg.PeerID | ||||
| 			b.handleMessage(m, true) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *Bvk) uploadFiles(extra map[string][]interface{}, peerID int) (string, string) { | ||||
| 	var attachments []string | ||||
| 	text := "" | ||||
|  | ||||
| 	for _, f := range extra["file"] { | ||||
| 		fi := f.(config.FileInfo) | ||||
|  | ||||
| 		if fi.Comment != "" { | ||||
| 			text += fi.Comment + "\n" | ||||
| 		} | ||||
| 		a, err := b.uploadFile(fi, peerID) | ||||
| 		if err != nil { | ||||
| 			b.Log.Error("File upload error ", fi.Name) | ||||
| 		} | ||||
|  | ||||
| 		attachments = append(attachments, a) | ||||
| 	} | ||||
|  | ||||
| 	return strings.Join(attachments, ","), text | ||||
| } | ||||
|  | ||||
| func (b *Bvk) uploadFile(file config.FileInfo, peerID int) (string, error) { | ||||
| 	r := bytes.NewReader(*file.Data) | ||||
|  | ||||
| 	photoRE := regexp.MustCompile(".(jpg|jpe|png)$") | ||||
| 	if photoRE.MatchString(file.Name) { | ||||
| 		p, err := b.c.UploadMessagesPhoto(peerID, r) | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
|  | ||||
| 		return photo + strconv.Itoa(p[0].OwnerID) + "_" + strconv.Itoa(p[0].ID), nil | ||||
| 	} | ||||
|  | ||||
| 	var doctype string | ||||
| 	if strings.Contains(file.Name, ".ogg") { | ||||
| 		doctype = audioMessage | ||||
| 	} else { | ||||
| 		doctype = document | ||||
| 	} | ||||
|  | ||||
| 	doc, err := b.c.UploadMessagesDoc(peerID, doctype, file.Name, "", r) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	switch doc.Type { | ||||
| 	case audioMessage: | ||||
| 		return document + strconv.Itoa(doc.AudioMessage.OwnerID) + "_" + strconv.Itoa(doc.AudioMessage.ID), nil | ||||
| 	case document: | ||||
| 		return document + strconv.Itoa(doc.Doc.OwnerID) + "_" + strconv.Itoa(doc.Doc.ID), nil | ||||
| 	} | ||||
|  | ||||
| 	return "", nil | ||||
| } | ||||
|  | ||||
| func (b *Bvk) getFiles(attachments []object.MessagesMessageAttachment) ([]string, string) { | ||||
| 	var urls []string | ||||
| 	var text []string | ||||
|  | ||||
| 	for _, a := range attachments { | ||||
| 		switch a.Type { | ||||
| 		case photo: | ||||
| 			var resolution float64 = 0 | ||||
| 			url := a.Photo.Sizes[0].URL | ||||
| 			for _, size := range a.Photo.Sizes { | ||||
| 				r := size.Height * size.Width | ||||
| 				if resolution < r { | ||||
| 					resolution = r | ||||
| 					url = size.URL | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			urls = append(urls, url) | ||||
|  | ||||
| 		case document: | ||||
| 			urls = append(urls, a.Doc.URL) | ||||
|  | ||||
| 		case graffiti: | ||||
| 			urls = append(urls, a.Graffiti.URL) | ||||
|  | ||||
| 		case audioMessage: | ||||
| 			urls = append(urls, a.AudioMessage.DocsDocPreviewAudioMessage.LinkOgg) | ||||
|  | ||||
| 		case sticker: | ||||
| 			var resolution float64 = 0 | ||||
| 			url := a.Sticker.Images[0].URL | ||||
| 			for _, size := range a.Sticker.Images { | ||||
| 				r := size.Height * size.Width | ||||
| 				if resolution < r { | ||||
| 					resolution = r | ||||
| 					url = size.URL | ||||
| 				} | ||||
| 			} | ||||
| 			urls = append(urls, url+".png") | ||||
| 		case video: | ||||
| 			text = append(text, "https://vk.com/video"+strconv.Itoa(a.Video.OwnerID)+"_"+strconv.Itoa(a.Video.ID)) | ||||
|  | ||||
| 		case wall: | ||||
| 			text = append(text, "https://vk.com/wall"+strconv.Itoa(a.Wall.FromID)+"_"+strconv.Itoa(a.Wall.ID)) | ||||
|  | ||||
| 		default: | ||||
| 			text = append(text, "This attachment is not supported ("+a.Type+")") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return urls, strings.Join(text, "\n") | ||||
| } | ||||
|  | ||||
| func (b *Bvk) downloadFiles(rmsg *config.Message, urls []string) { | ||||
| 	for _, url := range urls { | ||||
| 		data, err := helper.DownloadFile(url) | ||||
| 		if err == nil { | ||||
| 			urlPart := strings.Split(url, "/") | ||||
| 			name := strings.Split(urlPart[len(urlPart)-1], "?")[0] | ||||
| 			helper.HandleDownloadData(b.Log, rmsg, name, "", url, data, b.General) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -24,7 +24,8 @@ Check: | ||||
| func (b *Bwhatsapp) HandleError(err error) { | ||||
| 	// ignore received invalid data errors. https://github.com/42wim/matterbridge/issues/843 | ||||
| 	// 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") { | ||||
| 	if strings.Contains(err.Error(), "error processing data: received invalid data") || | ||||
| 		strings.Contains(err.Error(), "invalid string with tag 174") { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| @@ -47,16 +48,22 @@ func (b *Bwhatsapp) reconnect(err error) { | ||||
| 		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 | ||||
| 		} | ||||
| 	} | ||||
| @@ -64,7 +71,7 @@ func (b *Bwhatsapp) reconnect(err error) { | ||||
|  | ||||
| // HandleTextMessage sent from WhatsApp, relay it to the brige | ||||
| func (b *Bwhatsapp) HandleTextMessage(message whatsapp.TextMessage) { | ||||
| 	if message.Info.FromMe { // || !strings.Contains(strings.ToLower(message.Text), "@echo") { | ||||
| 	if message.Info.FromMe { | ||||
| 		return | ||||
| 	} | ||||
| 	// whatsapp sends last messages to show context , cut them | ||||
| @@ -72,12 +79,10 @@ func (b *Bwhatsapp) HandleTextMessage(message whatsapp.TextMessage) { | ||||
| 		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 | ||||
| 		} | ||||
| @@ -101,108 +106,209 @@ func (b *Bwhatsapp) HandleTextMessage(message whatsapp.TextMessage) { | ||||
| 			if mention == "" { | ||||
| 				mention = "someone" | ||||
| 			} | ||||
|  | ||||
| 			message.Text = strings.Replace(message.Text, "@"+numberAndSuffix[0], "@"+mention, 1) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	b.Log.Debugf("<= Sending message from %s on %s to gateway", senderJID, b.Account) | ||||
| 	rmsg := config.Message{ | ||||
| 		UserID:    senderJID, | ||||
| 		Username:  senderName, | ||||
| 		Text:      message.Text, | ||||
| 		Timestamp: messageTime, | ||||
| 		Channel:   groupJID, | ||||
| 		Account:   b.Account, | ||||
| 		Protocol:  b.Protocol, | ||||
| 		Extra:     make(map[string][]interface{}), | ||||
| 		UserID:   senderJID, | ||||
| 		Username: senderName, | ||||
| 		Text:     message.Text, | ||||
| 		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} | ||||
| 		ID: message.Info.Id, | ||||
| 	} | ||||
|  | ||||
| 	if avatarURL, exists := b.userAvatars[senderJID]; exists { | ||||
| 		rmsg.Avatar = avatarURL | ||||
| 	} | ||||
|  | ||||
| 	b.Log.Debugf("<= Sending message from %s on %s to gateway", senderJID, b.Account) | ||||
| 	b.Log.Debugf("<= Message is %#v", rmsg) | ||||
|  | ||||
| 	b.Remote <- rmsg | ||||
| } | ||||
|  | ||||
| // 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") { | ||||
| 	if message.Info.FromMe || message.Info.Timestamp < b.startedAt { | ||||
| 		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 | ||||
| 	//   senderJid = *message.Info.Source.Participant | ||||
| 	// } | ||||
| 	if len(message.Info.SenderJid) == 0 && 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) | ||||
| 	senderName := b.getSenderName(message.Info.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} | ||||
| 		UserID:   senderJID, | ||||
| 		Username: senderName, | ||||
| 		Channel:  message.Info.RemoteJid, | ||||
| 		Account:  b.Account, | ||||
| 		Protocol: b.Protocol, | ||||
| 		Extra:    make(map[string][]interface{}), | ||||
| 		ID:       message.Info.Id, | ||||
| 	} | ||||
|  | ||||
| 	if avatarURL, exists := b.userAvatars[senderJID]; exists { | ||||
| 		rmsg.Avatar = avatarURL | ||||
| 	} | ||||
|  | ||||
| 	// Download and unencrypt content | ||||
| 	data, err := message.Download() | ||||
| 	fileExt, err := mime.ExtensionsByType(message.Type) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("%v", err) | ||||
| 		b.Log.Errorf("Mimetype detection error: %s", err) | ||||
|  | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// Get file extension by mimetype | ||||
| 	// rename .jfif to .jpg https://github.com/42wim/matterbridge/issues/1292 | ||||
| 	if fileExt[0] == ".jfif" { | ||||
| 		fileExt[0] = ".jpg" | ||||
| 	} | ||||
|  | ||||
| 	filename := fmt.Sprintf("%v%v", message.Info.Id, fileExt[0]) | ||||
|  | ||||
| 	b.Log.Debugf("Trying to download %s with type %s", filename, message.Type) | ||||
|  | ||||
| 	data, err := message.Download() | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("Download image failed: %s", err) | ||||
|  | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// Move file to bridge storage | ||||
| 	helper.HandleDownloadData(b.Log, &rmsg, filename, message.Caption, "", &data, b.General) | ||||
|  | ||||
| 	b.Log.Debugf("<= Sending message from %s on %s to gateway", senderJID, b.Account) | ||||
| 	b.Log.Debugf("<= Message is %#v", rmsg) | ||||
|  | ||||
| 	b.Remote <- rmsg | ||||
| } | ||||
|  | ||||
| // HandleVideoMessage downloads video messages | ||||
| func (b *Bwhatsapp) HandleVideoMessage(message whatsapp.VideoMessage) { | ||||
| 	if message.Info.FromMe || message.Info.Timestamp < b.startedAt { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	senderJID := message.Info.SenderJid | ||||
| 	if len(message.Info.SenderJid) == 0 && message.Info.Source != nil && message.Info.Source.Participant != nil { | ||||
| 		senderJID = *message.Info.Source.Participant | ||||
| 	} | ||||
|  | ||||
| 	senderName := b.getSenderName(message.Info.SenderJid) | ||||
| 	if senderName == "" { | ||||
| 		senderName = "Someone" // don't expose telephone number | ||||
| 	} | ||||
|  | ||||
| 	rmsg := config.Message{ | ||||
| 		UserID:   senderJID, | ||||
| 		Username: senderName, | ||||
| 		Channel:  message.Info.RemoteJid, | ||||
| 		Account:  b.Account, | ||||
| 		Protocol: b.Protocol, | ||||
| 		Extra:    make(map[string][]interface{}), | ||||
| 		ID:       message.Info.Id, | ||||
| 	} | ||||
|  | ||||
| 	if avatarURL, exists := b.userAvatars[senderJID]; exists { | ||||
| 		rmsg.Avatar = avatarURL | ||||
| 	} | ||||
|  | ||||
| 	fileExt, err := mime.ExtensionsByType(message.Type) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("%v", err) | ||||
| 		b.Log.Errorf("Mimetype detection error: %s", err) | ||||
|  | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	filename := fmt.Sprintf("%v%v", message.Info.Id, fileExt[0]) | ||||
|  | ||||
| 	b.Log.Debugf("<= Image downloaded and unencrypted") | ||||
| 	b.Log.Debugf("Trying to download %s with size %#v and type %s", filename, message.Length, message.Type) | ||||
|  | ||||
| 	data, err := message.Download() | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("Download video failed: %s", err) | ||||
|  | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// 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.Log.Debugf("<= Sending message from %s on %s to gateway", senderJID, b.Account) | ||||
| 	b.Log.Debugf("<= Message is %#v", rmsg) | ||||
|  | ||||
| 	b.Remote <- rmsg | ||||
| } | ||||
|  | ||||
| //func (b *Bwhatsapp) HandleVideoMessage(message whatsapp.VideoMessage) { | ||||
| //	fmt.Println(message) // TODO implement | ||||
| //} | ||||
| // | ||||
| //func (b *Bwhatsapp) HandleJsonMessage(message string) { | ||||
| //	fmt.Println(message) // TODO implement | ||||
| //} | ||||
| // TODO HandleRawMessage | ||||
| // TODO HandleAudioMessage | ||||
| // HandleAudioMessage downloads audio messages | ||||
| func (b *Bwhatsapp) HandleAudioMessage(message whatsapp.AudioMessage) { | ||||
| 	if message.Info.FromMe || message.Info.Timestamp < b.startedAt { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	senderJID := message.Info.SenderJid | ||||
| 	if len(message.Info.SenderJid) == 0 && message.Info.Source != nil && message.Info.Source.Participant != nil { | ||||
| 		senderJID = *message.Info.Source.Participant | ||||
| 	} | ||||
|  | ||||
| 	senderName := b.getSenderName(message.Info.SenderJid) | ||||
| 	if senderName == "" { | ||||
| 		senderName = "Someone" // don't expose telephone number | ||||
| 	} | ||||
|  | ||||
| 	rmsg := config.Message{ | ||||
| 		UserID:   senderJID, | ||||
| 		Username: senderName, | ||||
| 		Channel:  message.Info.RemoteJid, | ||||
| 		Account:  b.Account, | ||||
| 		Protocol: b.Protocol, | ||||
| 		Extra:    make(map[string][]interface{}), | ||||
| 		ID:       message.Info.Id, | ||||
| 	} | ||||
|  | ||||
| 	if avatarURL, exists := b.userAvatars[senderJID]; exists { | ||||
| 		rmsg.Avatar = avatarURL | ||||
| 	} | ||||
|  | ||||
| 	fileExt, err := mime.ExtensionsByType(message.Type) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("Mimetype detection error: %s", err) | ||||
|  | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if len(fileExt) == 0 { | ||||
| 		fileExt = append(fileExt, ".ogg") | ||||
| 	} | ||||
|  | ||||
| 	filename := fmt.Sprintf("%v%v", message.Info.Id, fileExt[0]) | ||||
|  | ||||
| 	b.Log.Debugf("Trying to download %s with size %#v and type %s", filename, message.Length, message.Type) | ||||
|  | ||||
| 	data, err := message.Download() | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("Download audio failed: %s", err) | ||||
|  | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// Move file to bridge storage | ||||
| 	helper.HandleDownloadData(b.Log, &rmsg, filename, "audio message", "", &data, b.General) | ||||
|  | ||||
| 	b.Log.Debugf("<= Sending message from %s on %s to gateway", senderJID, b.Account) | ||||
| 	b.Log.Debugf("<= Message is %#v", rmsg) | ||||
|  | ||||
| 	b.Remote <- rmsg | ||||
| } | ||||
|   | ||||
| @@ -6,22 +6,24 @@ import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"strings" | ||||
|  | ||||
| 	qrcodeTerminal "github.com/Baozisoftware/qrcode-terminal-go" | ||||
| 	"github.com/Rhymen/go-whatsapp" | ||||
| ) | ||||
|  | ||||
| type ProfilePicInfo struct { | ||||
| 	URL string `json:"eurl"` | ||||
| 	Tag string `json:"tag"` | ||||
|  | ||||
| 	Status int16 `json:"status"` | ||||
| 	URL    string `json:"eurl"` | ||||
| 	Tag    string `json:"tag"` | ||||
| 	Status int16  `json:"status"` | ||||
| } | ||||
|  | ||||
| func qrFromTerminal(invert bool) chan string { | ||||
| 	qr := make(chan string) | ||||
|  | ||||
| 	go func() { | ||||
| 		terminal := qrcodeTerminal.New() | ||||
|  | ||||
| 		if invert { | ||||
| 			terminal = qrcodeTerminal.New2(qrcodeTerminal.ConsoleColors.BrightWhite, qrcodeTerminal.ConsoleColors.BrightBlack, qrcodeTerminal.QRCodeRecoveryLevels.Medium) | ||||
| 		} | ||||
| @@ -44,13 +46,12 @@ func (b *Bwhatsapp) readSession() (whatsapp.Session, error) { | ||||
| 	if err != nil { | ||||
| 		return session, err | ||||
| 	} | ||||
|  | ||||
| 	defer file.Close() | ||||
|  | ||||
| 	decoder := gob.NewDecoder(file) | ||||
| 	err = decoder.Decode(&session) | ||||
| 	if err != nil { | ||||
| 		return session, err | ||||
| 	} | ||||
| 	return session, nil | ||||
|  | ||||
| 	return session, decoder.Decode(&session) | ||||
| } | ||||
|  | ||||
| func (b *Bwhatsapp) writeSession(session whatsapp.Session) error { | ||||
| @@ -65,11 +66,31 @@ func (b *Bwhatsapp) writeSession(session whatsapp.Session) error { | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer file.Close() | ||||
| 	encoder := gob.NewEncoder(file) | ||||
| 	err = encoder.Encode(session) | ||||
|  | ||||
| 	return err | ||||
| 	defer file.Close() | ||||
|  | ||||
| 	encoder := gob.NewEncoder(file) | ||||
|  | ||||
| 	return encoder.Encode(session) | ||||
| } | ||||
|  | ||||
| func (b *Bwhatsapp) restoreSession() (*whatsapp.Session, error) { | ||||
| 	session, err := b.readSession() | ||||
| 	if err != nil { | ||||
| 		b.Log.Warn(err.Error()) | ||||
| 	} | ||||
|  | ||||
| 	b.Log.Debugln("Restoring WhatsApp session..") | ||||
|  | ||||
| 	session, err = b.conn.RestoreWithSession(session) | ||||
| 	if err != nil { | ||||
| 		// restore session connection timed out (I couldn't get over it without logging in again) | ||||
| 		return nil, errors.New("failed to restore session: " + err.Error()) | ||||
| 	} | ||||
|  | ||||
| 	b.Log.Debugln("Session restored successfully!") | ||||
|  | ||||
| 	return &session, nil | ||||
| } | ||||
|  | ||||
| func (b *Bwhatsapp) getSenderName(senderJid string) string { | ||||
| @@ -114,6 +135,7 @@ func (b *Bwhatsapp) getSenderNotify(senderJid string) string { | ||||
| 	if sender, exists := b.users[senderJid]; exists { | ||||
| 		return sender.Notify | ||||
| 	} | ||||
|  | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| @@ -122,11 +144,20 @@ func (b *Bwhatsapp) GetProfilePicThumb(jid string) (*ProfilePicInfo, error) { | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("failed to get avatar: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	content := <-data | ||||
| 	info := &ProfilePicInfo{} | ||||
|  | ||||
| 	err = json.Unmarshal([]byte(content), info) | ||||
| 	if err != nil { | ||||
| 		return info, fmt.Errorf("failed to unmarshal avatar info: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	return info, nil | ||||
| } | ||||
|  | ||||
| func isGroupJid(identifier string) bool { | ||||
| 	return strings.HasSuffix(identifier, "@g.us") || | ||||
| 		strings.HasSuffix(identifier, "@temp") || | ||||
| 		strings.HasSuffix(identifier, "@broadcast") | ||||
| } | ||||
|   | ||||
| @@ -28,7 +28,6 @@ const ( | ||||
| type Bwhatsapp struct { | ||||
| 	*bridge.Config | ||||
|  | ||||
| 	// https://github.com/Rhymen/go-whatsapp/blob/c31092027237441cffba1b9cb148eadf7c83c3d2/session.go#L18-L21 | ||||
| 	session   *whatsapp.Session | ||||
| 	conn      *whatsapp.Conn | ||||
| 	startedAt uint64 | ||||
| @@ -40,6 +39,7 @@ type Bwhatsapp struct { | ||||
| // New Create a new WhatsApp bridge. This will be called for each [whatsapp.<server>] entry you have in the config file | ||||
| func New(cfg *bridge.Config) bridge.Bridger { | ||||
| 	number := cfg.GetString(cfgNumber) | ||||
|  | ||||
| 	if number == "" { | ||||
| 		cfg.Log.Fatalf("Missing configuration for WhatsApp bridge: Number") | ||||
| 	} | ||||
| @@ -50,24 +50,19 @@ func New(cfg *bridge.Config) bridge.Bridger { | ||||
| 		users:       make(map[string]whatsapp.Contact), | ||||
| 		userAvatars: make(map[string]string), | ||||
| 	} | ||||
|  | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| // Connect to WhatsApp. Required implementation of the Bridger interface | ||||
| // https://github.com/42wim/matterbridge/blob/2cfd880cdb0df29771bf8f31df8d990ab897889d/bridge/bridge.go#L11-L16 | ||||
| func (b *Bwhatsapp) Connect() error { | ||||
| 	b.RLock() // TODO do we need locking for Whatsapp? | ||||
| 	defer b.RUnlock() | ||||
|  | ||||
| 	number := b.GetString(cfgNumber) | ||||
| 	if number == "" { | ||||
| 		return errors.New("WhatsApp's telephone Number need to be configured") | ||||
| 		return errors.New("whatsapp's telephone number need to be configured") | ||||
| 	} | ||||
|  | ||||
| 	// https://github.com/Rhymen/go-whatsapp#creating-a-connection | ||||
| 	b.Log.Debugln("Connecting to WhatsApp..") | ||||
| 	conn, err := whatsapp.NewConn(20 * time.Second) | ||||
| 	conn.SetClientVersion(0, 4, 2080) | ||||
| 	if err != nil { | ||||
| 		return errors.New("failed to connect to WhatsApp: " + err.Error()) | ||||
| 	} | ||||
| @@ -78,35 +73,18 @@ func (b *Bwhatsapp) Connect() error { | ||||
| 	b.Log.Debugln("WhatsApp connection successful") | ||||
|  | ||||
| 	// load existing session in order to keep it between restarts | ||||
| 	if b.session == nil { | ||||
| 		var session whatsapp.Session | ||||
| 		session, err = b.readSession() | ||||
|  | ||||
| 		if err == nil { | ||||
| 			b.Log.Debugln("Restoring WhatsApp session..") | ||||
|  | ||||
| 			// https://github.com/Rhymen/go-whatsapp#restore | ||||
| 			session, err = b.conn.RestoreWithSession(session) | ||||
| 			if err != nil { | ||||
| 				// TODO return or continue to normal login? | ||||
| 				// restore session connection timed out (I couldn't get over it without logging in again) | ||||
| 				return errors.New("failed to restore session: " + err.Error()) | ||||
| 			} | ||||
|  | ||||
| 			b.session = &session | ||||
| 			b.Log.Debugln("Session restored successfully!") | ||||
| 		} else { | ||||
| 			b.Log.Warn(err.Error()) | ||||
| 		} | ||||
| 	b.session, err = b.restoreSession() | ||||
| 	if err != nil { | ||||
| 		b.Log.Warn(err.Error()) | ||||
| 	} | ||||
|  | ||||
| 	// login to a new session | ||||
| 	if b.session == nil { | ||||
| 		err = b.Login() | ||||
| 		if err != nil { | ||||
| 		if err = b.Login(); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	b.startedAt = uint64(time.Now().Unix()) | ||||
|  | ||||
| 	_, err = b.conn.Contacts() | ||||
| @@ -114,6 +92,13 @@ func (b *Bwhatsapp) Connect() error { | ||||
| 		return fmt.Errorf("error on update of contacts: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	// see https://github.com/Rhymen/go-whatsapp/issues/137#issuecomment-480316013 | ||||
| 	for len(b.conn.Store.Contacts) == 0 { | ||||
| 		b.conn.Contacts() // nolint:errcheck | ||||
|  | ||||
| 		<-time.After(1 * time.Second) | ||||
| 	} | ||||
|  | ||||
| 	// map all the users | ||||
| 	for id, contact := range b.conn.Store.Contacts { | ||||
| 		if !isGroupJid(id) && id != "status@broadcast" { | ||||
| @@ -130,12 +115,13 @@ func (b *Bwhatsapp) Connect() error { | ||||
| 			info, err := b.GetProfilePicThumb(jid) | ||||
| 			if err != nil { | ||||
| 				b.Log.Warnf("Could not get profile photo of %s: %v", jid, err) | ||||
|  | ||||
| 			} else { | ||||
| 				// TODO any race conditions here? | ||||
| 				b.Lock() | ||||
| 				b.userAvatars[jid] = info.URL | ||||
| 				b.Unlock() | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		b.Log.Debug("Finished getting avatars..") | ||||
| 	}() | ||||
|  | ||||
| @@ -152,8 +138,10 @@ func (b *Bwhatsapp) Login() error { | ||||
| 	session, err := b.conn.Login(qrChan) | ||||
| 	if err != nil { | ||||
| 		b.Log.Warnln("Failed to log in:", err) | ||||
|  | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	b.session = &session | ||||
|  | ||||
| 	b.Log.Infof("Logged into session: %#v", session) | ||||
| @@ -164,74 +152,62 @@ func (b *Bwhatsapp) Login() error { | ||||
| 		fmt.Fprintf(os.Stderr, "error saving session: %v\n", err) | ||||
| 	} | ||||
|  | ||||
| 	// TODO change connection strings to configured ones longClientName:"github.com/rhymen/go-whatsapp", shortClientName:"go-whatsapp"}" prefix=whatsapp | ||||
| 	// TODO get also a nice logo | ||||
|  | ||||
| 	// TODO notification about unplugged and dead battery | ||||
| 	// conn.Info: Wid, Pushname, Connected, Battery, Plugged | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Disconnect is called while reconnecting to the bridge | ||||
| // TODO 42wim Documentation would be helpful on when reconnects happen and what should be done in this function | ||||
| // Required implementation of the Bridger interface | ||||
| // https://github.com/42wim/matterbridge/blob/2cfd880cdb0df29771bf8f31df8d990ab897889d/bridge/bridge.go#L11-L16 | ||||
| func (b *Bwhatsapp) Disconnect() error { | ||||
| 	// We could Logout, but that would close the session completely and would require a new QR code scan | ||||
| 	// https://github.com/Rhymen/go-whatsapp/blob/c31092027237441cffba1b9cb148eadf7c83c3d2/session.go#L377-L381 | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func isGroupJid(identifier string) bool { | ||||
| 	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' | ||||
| // Required implementation of the Bridger interface | ||||
| // https://github.com/42wim/matterbridge/blob/2cfd880cdb0df29771bf8f31df8d990ab897889d/bridge/bridge.go#L11-L16 | ||||
| func (b *Bwhatsapp) JoinChannel(channel config.ChannelInfo) error { | ||||
| 	byJid := isGroupJid(channel.Name) | ||||
|  | ||||
| 	// see https://github.com/Rhymen/go-whatsapp/issues/137#issuecomment-480316013 | ||||
| 	for len(b.conn.Store.Contacts) == 0 { | ||||
| 		b.conn.Contacts() // nolint:errcheck | ||||
| 		<-time.After(1 * time.Second) | ||||
| 	} | ||||
|  | ||||
| 	// verify if we are member of the given group | ||||
| 	if byJid { | ||||
| 		// channel.Name specifies static group jID, not the name | ||||
| 		if _, exists := b.conn.Store.Contacts[channel.Name]; !exists { | ||||
| 			return fmt.Errorf("account doesn't belong to group with jid %s", channel.Name) | ||||
| 		} | ||||
| 	} else { | ||||
| 		// channel.Name specifies group name that might change, warn about it | ||||
| 		var jids []string | ||||
| 		for id, contact := range b.conn.Store.Contacts { | ||||
| 			if isGroupJid(id) && contact.Name == channel.Name { | ||||
| 				jids = append(jids, id) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		switch len(jids) { | ||||
| 		case 0: | ||||
| 			// didn't match any group - print out possibilites | ||||
| 			// TODO sort | ||||
| 			// copy b; | ||||
| 			//sort.Slice(people, func(i, j int) bool { | ||||
| 			//	return people[i].Age > people[j].Age | ||||
| 			//}) | ||||
| 			for id, contact := range b.conn.Store.Contacts { | ||||
| 				if isGroupJid(id) { | ||||
| 					b.Log.Infof("%s %s", contact.Jid, contact.Name) | ||||
| 				} | ||||
| 			} | ||||
| 			return fmt.Errorf("please specify group's JID from the list above instead of the name '%s'", channel.Name) | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 		case 1: | ||||
| 			return fmt.Errorf("group name might change. Please configure gateway with channel=\"%v\" instead of channel=\"%v\"", jids[0], channel.Name) | ||||
|  | ||||
| 		default: | ||||
| 			return fmt.Errorf("there is more than one group with name '%s'. Please specify one of JIDs as channel name: %v", channel.Name, jids) | ||||
| 	// channel.Name specifies group name that might change, warn about it | ||||
| 	var jids []string | ||||
| 	for id, contact := range b.conn.Store.Contacts { | ||||
| 		if isGroupJid(id) && contact.Name == channel.Name { | ||||
| 			jids = append(jids, id) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| 	switch len(jids) { | ||||
| 	case 0: | ||||
| 		// didn't match any group - print out possibilites | ||||
| 		for id, contact := range b.conn.Store.Contacts { | ||||
| 			if isGroupJid(id) { | ||||
| 				b.Log.Infof("%s %s", contact.Jid, contact.Name) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return fmt.Errorf("please specify group's JID from the list above instead of the name '%s'", channel.Name) | ||||
| 	case 1: | ||||
| 		return fmt.Errorf("group name might change. Please configure gateway with channel=\"%v\" instead of channel=\"%v\"", jids[0], channel.Name) | ||||
| 	default: | ||||
| 		return fmt.Errorf("there is more than one group with name '%s'. Please specify one of JIDs as channel name: %v", channel.Name, jids) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Post a document message from the bridge to WhatsApp | ||||
| @@ -305,14 +281,12 @@ func (b *Bwhatsapp) Send(msg config.Message) (string, error) { | ||||
| 		if msg.ID == "" { | ||||
| 			// No message ID in case action is executed on a message sent before the bridge was started | ||||
| 			// and then the bridge cache doesn't have this message ID mapped | ||||
|  | ||||
| 			// TODO 42wim Doesn't the app get clogged with a ton of IDs after some time of running? | ||||
| 			// WhatsApp allows to set any ID so in that case we could use external IDs and don't do mapping | ||||
| 			// but external IDs are not set | ||||
| 			return "", nil | ||||
| 		} | ||||
| 		// TODO delete message on WhatsApp https://github.com/Rhymen/go-whatsapp/issues/100 | ||||
| 		return "", nil | ||||
|  | ||||
| 		_, err := b.conn.RevokeMessage(msg.Channel, msg.ID, true) | ||||
|  | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	// Edit message | ||||
| @@ -320,7 +294,6 @@ func (b *Bwhatsapp) Send(msg config.Message) (string, error) { | ||||
| 		b.Log.Debugf("updating message with id %s", msg.ID) | ||||
|  | ||||
| 		msg.Text += " (edited)" | ||||
| 		// TODO handle edit as a message reply with updated text | ||||
| 	} | ||||
|  | ||||
| 	// Handle Upload a file | ||||
| @@ -350,16 +323,7 @@ func (b *Bwhatsapp) Send(msg config.Message) (string, error) { | ||||
|  | ||||
| 	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 | ||||
| 	return b.conn.Send(message) | ||||
| } | ||||
|  | ||||
| // 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 | ||||
|   | ||||
| @@ -1,8 +1,12 @@ | ||||
| package bxmpp | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"crypto/tls" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 	"time" | ||||
| @@ -86,14 +90,21 @@ func (b *Bxmpp) Send(msg config.Message) (string, error) { | ||||
| 	} | ||||
|  | ||||
| 	// Upload a file (in XMPP case send the upload URL because XMPP has no native upload support). | ||||
| 	var err error | ||||
| 	if msg.Extra != nil { | ||||
| 		for _, rmsg := range helper.HandleExtra(&msg, b.General) { | ||||
| 			b.Log.Debugf("=> Sending attachement message %#v", rmsg) | ||||
| 			if _, err := b.xc.Send(xmpp.Chat{ | ||||
| 				Type:   "groupchat", | ||||
| 				Remote: rmsg.Channel + "@" + b.GetString("Muc"), | ||||
| 				Text:   rmsg.Username + rmsg.Text, | ||||
| 			}); err != nil { | ||||
| 			if b.GetString("WebhookURL") != "" { | ||||
| 				err = b.postSlackCompatibleWebhook(msg) | ||||
| 			} else { | ||||
| 				_, err = b.xc.Send(xmpp.Chat{ | ||||
| 					Type:   "groupchat", | ||||
| 					Remote: rmsg.Channel + "@" + b.GetString("Muc"), | ||||
| 					Text:   rmsg.Username + rmsg.Text, | ||||
| 				}) | ||||
| 			} | ||||
|  | ||||
| 			if err != nil { | ||||
| 				b.Log.WithError(err).Error("Unable to send message with share URL.") | ||||
| 			} | ||||
| 		} | ||||
| @@ -102,13 +113,24 @@ func (b *Bxmpp) Send(msg config.Message) (string, error) { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if b.GetString("WebhookURL") != "" { | ||||
| 		b.Log.Debugf("Sending message using Webhook") | ||||
| 		err := b.postSlackCompatibleWebhook(msg) | ||||
| 		if err != nil { | ||||
| 			b.Log.Errorf("Failed to send message using webhook: %s", err) | ||||
| 			return "", err | ||||
| 		} | ||||
|  | ||||
| 		return "", nil | ||||
| 	} | ||||
|  | ||||
| 	// Post normal message. | ||||
| 	var msgReplaceID string | ||||
| 	msgID := xid.New().String() | ||||
| 	if msg.ID != "" { | ||||
| 		msgID = msg.ID | ||||
| 		msgReplaceID = msg.ID | ||||
| 	} | ||||
| 	// Post normal message. | ||||
| 	b.Log.Debugf("=> Sending message %#v", msg) | ||||
| 	if _, err := b.xc.Send(xmpp.Chat{ | ||||
| 		Type:      "groupchat", | ||||
| @@ -122,6 +144,30 @@ func (b *Bxmpp) Send(msg config.Message) (string, error) { | ||||
| 	return msgID, nil | ||||
| } | ||||
|  | ||||
| func (b *Bxmpp) postSlackCompatibleWebhook(msg config.Message) error { | ||||
| 	type XMPPWebhook struct { | ||||
| 		Username string `json:"username"` | ||||
| 		Text     string `json:"text"` | ||||
| 	} | ||||
| 	webhookBody, err := json.Marshal(XMPPWebhook{ | ||||
| 		Username: msg.Username, | ||||
| 		Text:     msg.Text, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("Failed to marshal webhook: %s", err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	resp, err := http.Post(b.GetString("WebhookURL")+"/"+url.QueryEscape(msg.Channel), "application/json", bytes.NewReader(webhookBody)) | ||||
| 	if err != nil { | ||||
| 		b.Log.Errorf("Failed to POST webhook: %s", err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	resp.Body.Close() | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Bxmpp) createXMPP() error { | ||||
| 	if !strings.Contains(b.GetString("Jid"), "@") { | ||||
| 		return fmt.Errorf("the Jid %s doesn't contain an @", b.GetString("Jid")) | ||||
| @@ -138,14 +184,14 @@ func (b *Bxmpp) createXMPP() error { | ||||
| 		User:                         b.GetString("Jid"), | ||||
| 		Password:                     b.GetString("Password"), | ||||
| 		NoTLS:                        true, | ||||
| 		StartTLS:                     true, | ||||
| 		StartTLS:                     !b.GetBool("NoTLS"), | ||||
| 		TLSConfig:                    tc, | ||||
| 		Debug:                        b.GetBool("debug"), | ||||
| 		Session:                      true, | ||||
| 		Status:                       "", | ||||
| 		StatusMessage:                "", | ||||
| 		Resource:                     "", | ||||
| 		InsecureAllowUnencryptedAuth: false, | ||||
| 		InsecureAllowUnencryptedAuth: b.GetBool("NoTLS"), | ||||
| 	} | ||||
| 	var err error | ||||
| 	b.xc, err = options.NewClient() | ||||
| @@ -378,6 +424,11 @@ func (b *Bxmpp) skipMessage(message xmpp.Chat) bool { | ||||
| 		return true | ||||
| 	} | ||||
|  | ||||
| 	// Ignore messages posted by our webhook | ||||
| 	if b.GetString("WebhookURL") != "" && strings.Contains(message.ID, "webhookbot") { | ||||
| 		return true | ||||
| 	} | ||||
|  | ||||
| 	// skip delayed messages | ||||
| 	return !message.Stamp.IsZero() && time.Since(message.Stamp).Minutes() > 5 | ||||
| } | ||||
|   | ||||
							
								
								
									
										1344
									
								
								changelog.md
									
									
									
									
									
								
							
							
						
						
									
										1344
									
								
								changelog.md
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										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/bvk.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								gateway/bridgemap/bvk.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // +build !novk | ||||
|  | ||||
| package bridgemap | ||||
|  | ||||
| import ( | ||||
| 	bvk "github.com/42wim/matterbridge/bridge/vk" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	FullMap["vk"] = bvk.New | ||||
| } | ||||
| @@ -1,6 +1,7 @@ | ||||
| package gateway | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"regexp" | ||||
| @@ -13,7 +14,7 @@ import ( | ||||
| 	"github.com/d5/tengo/v2" | ||||
| 	"github.com/d5/tengo/v2/stdlib" | ||||
| 	lru "github.com/hashicorp/golang-lru" | ||||
| 	"github.com/matterbridge/emoji" | ||||
| 	"github.com/kyokomi/emoji/v2" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| @@ -126,7 +127,7 @@ func (gw *Gateway) AddConfig(cfg *config.Gateway) error { | ||||
| 		gw.logger.Errorf("mapChannels() failed: %s", err) | ||||
| 	} | ||||
| 	for _, br := range append(gw.MyConfig.In, append(gw.MyConfig.InOut, gw.MyConfig.Out...)...) { | ||||
| 		br := br //scopelint | ||||
| 		br := br // scopelint | ||||
| 		err := gw.AddBridge(&br) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| @@ -336,20 +337,21 @@ func (gw *Gateway) modifyUsername(msg *config.Message, dest *bridge.Bridge) stri | ||||
| 			} | ||||
| 			i++ | ||||
| 		} | ||||
| 		nick = strings.Replace(nick, "{NOPINGNICK}", msg.Username[:i]+""+msg.Username[i:], -1) | ||||
| 		nick = strings.ReplaceAll(nick, "{NOPINGNICK}", msg.Username[:i]+"\u200b"+msg.Username[i:]) | ||||
| 	} | ||||
|  | ||||
| 	nick = strings.Replace(nick, "{BRIDGE}", br.Name, -1) | ||||
| 	nick = strings.Replace(nick, "{PROTOCOL}", br.Protocol, -1) | ||||
| 	nick = strings.Replace(nick, "{GATEWAY}", gw.Name, -1) | ||||
| 	nick = strings.Replace(nick, "{LABEL}", br.GetString("Label"), -1) | ||||
| 	nick = strings.Replace(nick, "{NICK}", msg.Username, -1) | ||||
| 	nick = strings.Replace(nick, "{CHANNEL}", msg.Channel, -1) | ||||
| 	nick = strings.ReplaceAll(nick, "{BRIDGE}", br.Name) | ||||
| 	nick = strings.ReplaceAll(nick, "{PROTOCOL}", br.Protocol) | ||||
| 	nick = strings.ReplaceAll(nick, "{GATEWAY}", gw.Name) | ||||
| 	nick = strings.ReplaceAll(nick, "{LABEL}", br.GetString("Label")) | ||||
| 	nick = strings.ReplaceAll(nick, "{NICK}", msg.Username) | ||||
| 	nick = strings.ReplaceAll(nick, "{USERID}", msg.UserID) | ||||
| 	nick = strings.ReplaceAll(nick, "{CHANNEL}", msg.Channel) | ||||
| 	tengoNick, err := gw.modifyUsernameTengo(msg, br) | ||||
| 	if err != nil { | ||||
| 		gw.logger.Errorf("modifyUsernameTengo error: %s", err) | ||||
| 	} | ||||
| 	nick = strings.Replace(nick, "{TENGO}", tengoNick, -1) //nolint:gocritic | ||||
| 	nick = strings.ReplaceAll(nick, "{TENGO}", tengoNick) | ||||
| 	return nick | ||||
| } | ||||
|  | ||||
| @@ -363,14 +365,28 @@ 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) | ||||
| 	} | ||||
|  | ||||
| 	// replace :emoji: to unicode | ||||
| 	emoji.ReplacePadding = "" | ||||
| 	msg.Text = emoji.Sprint(msg.Text) | ||||
|  | ||||
| 	br := gw.Bridges[msg.Account] | ||||
| @@ -416,9 +432,15 @@ func (gw *Gateway) SendMessage( | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Only send irc notices to irc | ||||
| 	if msg.Event == config.EventNoticeIRC && dest.Protocol != "irc" { | ||||
| 		return "", nil | ||||
| 	} | ||||
|  | ||||
| 	// 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 | ||||
| @@ -438,22 +460,34 @@ func (gw *Gateway) SendMessage( | ||||
| 	} | ||||
|  | ||||
| 	// if the parentID is still empty and we have a parentID set in the original message | ||||
| 	// this means that we didn't find it in the cache so set it "msg-parent-not-found" | ||||
| 	// this means that we didn't find it in the cache so set it to a "msg-parent-not-found" constant | ||||
| 	if msg.ParentID == "" && rmsg.ParentID != "" { | ||||
| 		msg.ParentID = "msg-parent-not-found" | ||||
| 		msg.ParentID = config.ParentIDNotFound | ||||
| 	} | ||||
|  | ||||
| 	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 | ||||
| @@ -463,7 +497,7 @@ func (gw *Gateway) SendMessage( | ||||
| 	if mID != "" { | ||||
| 		gw.logger.Debugf("mID %s: %s", dest.Account, mID) | ||||
| 		return mID, nil | ||||
| 		//brMsgIDs = append(brMsgIDs, &BrMsgID{dest, dest.Protocol + " " + mID, channel.ID}) | ||||
| 		// brMsgIDs = append(brMsgIDs, &BrMsgID{dest, dest.Protocol + " " + mID, channel.ID}) | ||||
| 	} | ||||
| 	return "", nil | ||||
| } | ||||
| @@ -505,7 +539,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 | ||||
| 	} | ||||
| @@ -517,6 +551,7 @@ func modifyMessageTengo(filename string, msg *config.Message) error { | ||||
| 	s.SetImports(stdlib.GetModuleMap(stdlib.AllModuleNames()...)) | ||||
| 	_ = s.Add("msgText", msg.Text) | ||||
| 	_ = s.Add("msgUsername", msg.Username) | ||||
| 	_ = s.Add("msgUserID", msg.UserID) | ||||
| 	_ = s.Add("msgAccount", msg.Account) | ||||
| 	_ = s.Add("msgChannel", msg.Channel) | ||||
| 	c, err := s.Compile() | ||||
| @@ -545,6 +580,7 @@ func (gw *Gateway) modifyUsernameTengo(msg *config.Message, br *bridge.Bridge) ( | ||||
| 	_ = s.Add("result", "") | ||||
| 	_ = s.Add("msgText", msg.Text) | ||||
| 	_ = s.Add("msgUsername", msg.Username) | ||||
| 	_ = s.Add("msgUserID", msg.UserID) | ||||
| 	_ = s.Add("nick", msg.Username) | ||||
| 	_ = s.Add("msgAccount", msg.Account) | ||||
| 	_ = s.Add("msgChannel", msg.Channel) | ||||
| @@ -564,22 +600,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 := tengo.NewScript(res) | ||||
|  | ||||
| 	s.SetImports(stdlib.GetModuleMap(stdlib.AllModuleNames()...)) | ||||
| 	_ = s.Add("inAccount", origmsg.Account) | ||||
| 	_ = s.Add("inProtocol", origmsg.Protocol) | ||||
| @@ -593,14 +635,20 @@ 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("msgUserID", msg.UserID) | ||||
| 	_ = 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 | ||||
| 		} | ||||
|   | ||||
| @@ -160,7 +160,7 @@ func (r *Router) handleReceive() { | ||||
| 				// For some bridges we always add/update the message ID. | ||||
| 				// This is necessary as msgIDs will change if a bridge returns | ||||
| 				// a different ID in response to edits. | ||||
| 				if !exists || msg.Protocol == "discord" { | ||||
| 				if !exists { | ||||
| 					gw.Messages.Add(msg.Protocol+" "+msg.ID, msgIDs) | ||||
| 				} | ||||
| 			} | ||||
|   | ||||
							
								
								
									
										59
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								go.mod
									
									
									
									
									
								
							| @@ -3,54 +3,59 @@ module github.com/42wim/matterbridge | ||||
| 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.1.1-0.20200818115958-f07a700b9819 | ||||
| 	github.com/d5/tengo/v2 v2.6.0 | ||||
| 	github.com/Jeffail/gabs v1.4.0 // indirect | ||||
| 	github.com/Philipp15b/go-steam v1.0.1-0.20200727090957-6ae9b3c0a560 | ||||
| 	github.com/Rhymen/go-whatsapp v0.1.2-0.20210126174449-3c094ebae0ce | ||||
| 	github.com/SevereCloud/vksdk/v2 v2.9.0 | ||||
| 	github.com/d5/tengo/v2 v2.7.0 | ||||
| 	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-20200824053859-8c8b3816f167 | ||||
| 	github.com/google/gops v0.3.11 | ||||
| 	github.com/gomarkdown/markdown v0.0.0-20210208175418-bda154fe17d8 | ||||
| 	github.com/google/gops v0.3.17 | ||||
| 	github.com/gopackage/ddp v0.0.0-20170117053602-652027933df4 // indirect | ||||
| 	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/kyokomi/emoji/v2 v2.2.8 | ||||
| 	github.com/labstack/echo/v4 v4.2.1 | ||||
| 	github.com/lrstanley/girc v0.0.0-20190801035559-4fc93959e1a7 | ||||
| 	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/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16 | ||||
| 	github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20210403163225-761e8622445d | ||||
| 	github.com/matterbridge/discordgo v0.21.2-0.20210201201054-fb39a175b4f7 | ||||
| 	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.25.2 | ||||
| 	github.com/mattn/godown v0.0.0-20200217152941-afc959f6a561 | ||||
| 	github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect | ||||
| 	github.com/missdeer/golib v1.0.3 | ||||
| 	github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474 // indirect | ||||
| 	github.com/mattermost/mattermost-server/v5 v5.30.1 | ||||
| 	github.com/mattn/godown v0.0.1 | ||||
| 	github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect | ||||
| 	github.com/missdeer/golib v1.0.4 | ||||
| 	github.com/mreiferson/go-httpclient v0.0.0-20201222173833-5e475fde3a4d // indirect | ||||
| 	github.com/mrexodia/wray v0.0.0-20160318003008-78a2c1f284ff // indirect | ||||
| 	github.com/nelsonken/gomf v0.0.0-20180504123937-a9dd2f9deae9 | ||||
| 	github.com/paulrosania/go-charset v0.0.0-20190326053356-55c9d7a5834c | ||||
| 	github.com/rs/xid v1.2.1 | ||||
| 	github.com/russross/blackfriday v1.5.2 | ||||
| 	github.com/rs/xid v1.3.0 | ||||
| 	github.com/russross/blackfriday v1.6.0 | ||||
| 	github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca | ||||
| 	github.com/shazow/ssh-chat v1.8.3-0.20200308224626-80ddf1f43a98 | ||||
| 	github.com/sirupsen/logrus v1.6.0 | ||||
| 	github.com/slack-go/slack v0.6.6 | ||||
| 	github.com/shazow/ssh-chat v1.10.1 | ||||
| 	github.com/sirupsen/logrus v1.8.1 | ||||
| 	github.com/slack-go/slack v0.8.2 | ||||
| 	github.com/spf13/afero v1.3.4 // indirect | ||||
| 	github.com/spf13/cast v1.3.1 // indirect | ||||
| 	github.com/spf13/viper v1.7.1 | ||||
| 	github.com/stretchr/testify v1.6.1 | ||||
| 	github.com/stretchr/testify v1.7.0 | ||||
| 	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/image v0.0.0-20200801110659-972c09e46d76 | ||||
| 	golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 | ||||
| 	gomod.garykim.dev/nc-talk v0.1.3 | ||||
| 	github.com/zfjagann/golang-ring v0.0.0-20210116075443-7c86fdb43134 | ||||
| 	golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb | ||||
| 	golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 | ||||
| 	gomod.garykim.dev/nc-talk v0.1.7 | ||||
| 	gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376 | ||||
| 	layeh.com/gumble v0.0.0-20200818122324-146f9205029b | ||||
| ) | ||||
|  | ||||
| go 1.13 | ||||
| go 1.15 | ||||
|   | ||||
| @@ -16,7 +16,7 @@ import ( | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	version = "1.18.3" | ||||
| 	version = "1.22.1" | ||||
| 	githash string | ||||
|  | ||||
| 	flagConfig  = flag.String("conf", "matterbridge.toml", "config file") | ||||
|   | ||||
| @@ -103,6 +103,12 @@ ColorNicks=false | ||||
| #OPTIONAL (default empty) | ||||
| RunCommands=["PRIVMSG user hello","PRIVMSG chanserv something"] | ||||
|  | ||||
| #PingDelay specifies how long to wait to send a ping to the irc server. | ||||
| #You can use s for second, m for minute | ||||
| #String | ||||
| #OPTIONAL (default 1m) | ||||
| PingDelay="1m" | ||||
|  | ||||
| #StripMarkdown strips markdown from messages | ||||
| #OPTIONAL (default false) | ||||
| StripMarkdown=false | ||||
| @@ -187,6 +193,19 @@ ShowTopicChange=false | ||||
| #OPTIONAL (default 0) | ||||
| JoinDelay=0 | ||||
|  | ||||
| #Use the optional RELAYMSG extension for username spoofing on IRC. | ||||
| #This requires an IRCd that supports the draft/relaymsg specification: currently this includes | ||||
| #Oragono 2.4.0+ and InspIRCd 3 with the m_relaymsg contrib module. | ||||
| #See https://github.com/42wim/matterbridge/issues/667#issuecomment-634214165 for more details. | ||||
| #Spoofed nicks will use the configured RemoteNickFormat, replacing reserved IRC characters | ||||
| #(!+%@&#$:'"?*,.) with a hyphen (-). | ||||
| #On most configurations, the RemoteNickFormat must include a separator character such as "/". | ||||
| #You should make sure that the settings here match your IRCd. | ||||
| #This option overrides ColorNicks. | ||||
| #OPTIONAL (default false) | ||||
| UseRelayMsg=false | ||||
| #RemoteNickFormat="{NICK}/{PROTOCOL}" | ||||
|  | ||||
| ################################################################### | ||||
| #XMPP section | ||||
| ################################################################### | ||||
| @@ -221,6 +240,10 @@ Nick="xmppbot" | ||||
| #OPTIONAL (default false) | ||||
| SkipTLSVerify=true | ||||
|  | ||||
| #Enable to use plaintext connection to your XMPP server. | ||||
| #OPTIONAL (default false) | ||||
| NoTLS=true | ||||
|  | ||||
| ## RELOADABLE SETTINGS | ||||
| ## Settings below can be reloaded by editing the file | ||||
|  | ||||
| @@ -287,6 +310,11 @@ StripNick=false | ||||
| #OPTIONAL (default false) | ||||
| ShowTopicChange=false | ||||
|  | ||||
| #Enable sending messages using a webhook instead of regular MUC messages. | ||||
| #Only works with a prosody server using mod_slack_webhook. Does not support editing. | ||||
| #OPTIONAL (default "") | ||||
| WebhookURL="https://yourdomain/prosody/msg/someid" | ||||
|  | ||||
| ################################################################### | ||||
| #mattermost section | ||||
| ################################################################### | ||||
| @@ -836,10 +864,11 @@ UseUserName=false | ||||
| # UseDiscriminator appends the `#xxxx` discriminator when used with UseUserName | ||||
| UseDiscriminator=false | ||||
|  | ||||
| # WebhookURL sends messages in the style of puppets. | ||||
| # This only works if you have one discord channel, if you have multiple discord channels you'll have to specify it in the gateway config | ||||
| # Example: "https://discordapp.com/api/webhooks/1234/abcd_xyzw" | ||||
| WebhookURL="" | ||||
| # AutoWebhooks automatically configures message sending in the style of puppets. | ||||
| # This is an easier alternative to manually configuring "WebhookURL" for each gateway, | ||||
| # as turning this on will automatically load or create webhooks for each channel. | ||||
| # This feature requires the "Manage Webhooks" permission (either globally or as per-channel). | ||||
| AutoWebhooks=false | ||||
|  | ||||
| # EditDisable disables sending of edits to other bridges | ||||
| EditDisable=false | ||||
| @@ -1221,6 +1250,9 @@ HTMLDisable=false | ||||
| ## RELOADABLE SETTINGS | ||||
| ## Settings below can be reloaded by editing the file | ||||
|  | ||||
| # UseUserName shows the username instead of the server nickname | ||||
| UseUserName=false | ||||
|  | ||||
| #Whether to prefix messages from other bridges to matrix with the sender's nick. | ||||
| #Useful if username overrides for incoming webhooks isn't enabled on the | ||||
| #matrix server. If you set PrefixMessagesWithNick to true, each message | ||||
| @@ -1405,6 +1437,67 @@ Login = "talkuser" | ||||
| # Password of the bot | ||||
| Password = "talkuserpass" | ||||
|  | ||||
| # Suffix for Guest Users | ||||
| GuestSuffix = " (Guest)" | ||||
|  | ||||
| ################################################################### | ||||
| # | ||||
| # Mumble | ||||
| # | ||||
| ################################################################### | ||||
|  | ||||
| [mumble.bridge] | ||||
|  | ||||
| # Host and port of your Mumble server | ||||
| Server = "mumble.yourdomain.me:64738" | ||||
|  | ||||
| # Nickname to log in as | ||||
| Nick = "matterbridge" | ||||
|  | ||||
| # Some servers require a password | ||||
| # OPTIONAL (default empty) | ||||
| Password = "serverpasswordhere" | ||||
|  | ||||
| # User comment to set on the Mumble user, visible to other users. | ||||
| # OPTIONAL (default empty) | ||||
| UserComment="I am bridging text messages between this channel and #general on irc.yourdomain.me" | ||||
|  | ||||
| # Self-signed TLS client certificate + private key used to connect to | ||||
| # Mumble.  This is required if you want to register the matterbridge | ||||
| # user on your Mumble server, so its nick becomes reserved. | ||||
| # You can generate a keypair using e.g. | ||||
| # | ||||
| #     openssl req -x509 -newkey rsa:2048 -nodes -days 10000 \ | ||||
| #             -keyout mumble.key -out mumble.crt | ||||
| # | ||||
| # To actually register the matterbridege user, connect to Mumble as an | ||||
| # admin, right click on the user and click "Register". | ||||
| # | ||||
| # OPTIONAL (default empty) | ||||
| TLSClientCertificate="mumble.crt" | ||||
| TLSClientKey="mumble.key" | ||||
|  | ||||
| # TLS CA certificate used to validate the Mumble server. | ||||
| # OPTIONAL (defaults to Go system CA) | ||||
| TLSCACertificate=mumble-ca.crt | ||||
|  | ||||
| # Enable to not verify the certificate on your Mumble server. | ||||
| # e.g. when using selfsigned certificates | ||||
| # OPTIONAL (default false) | ||||
| SkipTLSVerify=false | ||||
|  | ||||
| ################################################################### | ||||
| #VK | ||||
| ################################################################### | ||||
| [vk.myvk] | ||||
| #Group access token | ||||
| #See https://vk.com/dev/bots_docs | ||||
| Token="Yourtokenhere" | ||||
|  | ||||
| #Group ID | ||||
| #For example in URL https://vk.com/public168963511 group ID is 168963511 | ||||
| GroupID=123456789 | ||||
|  | ||||
| ################################################################### | ||||
| # | ||||
| # WhatsApp | ||||
| @@ -1570,7 +1663,8 @@ RemoteNickFormat="{NICK}" | ||||
| ## Settings below can be reloaded by editing the file | ||||
|  | ||||
| #RemoteNickFormat defines how remote users appear on this bridge | ||||
| #The string "{NICK}" (case sensitive) will be replaced by the actual nick / username. | ||||
| #The string "{NICK}" (case sensitive) will be replaced by the actual nick. | ||||
| #The string "{USERID}" (case sensitive) will be replaced by the user ID. | ||||
| #The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge | ||||
| #The string "{LABEL}" (case sensitive) will be replaced by label= field of the sending bridge | ||||
| #The string "{PROTOCOL}" (case sensitive) will be replaced by the protocol used by the bridge | ||||
| @@ -1645,7 +1739,7 @@ LogFile="/var/log/matterbridge.log" | ||||
| #This script will receive every incoming message and can be used to modify the Username and the Text of that message. | ||||
| #The script will have the following global variables: | ||||
| #to modify: msgUsername and msgText | ||||
| #to read: msgChannel and msgAccount | ||||
| #to read: msgUserID, msgChannel, msgAccount | ||||
| # | ||||
| #The script is reloaded on every message, so you can modify the script on the fly. | ||||
| # | ||||
| @@ -1669,9 +1763,12 @@ InMessage="example.tengo" | ||||
| #read-only: | ||||
| #inAccount, inProtocol, inChannel, inGateway, inEvent | ||||
| #outAccount, outProtocol, outChannel, outGateway, outEvent | ||||
| #msgUserID | ||||
| # | ||||
| #read-write: | ||||
| #msgText, msgUsername | ||||
| #msgText, msgUsername, msgDrop | ||||
| # | ||||
| #msgDrop is a bool which is default false, when set true this message will be dropped | ||||
| # | ||||
| #The script is reloaded on every message, so you can modify the script on the fly. | ||||
| # | ||||
| @@ -1684,7 +1781,7 @@ OutMessage="example.tengo" | ||||
| #RemoteNickFormat allows you to specify the location of a tengo (https://github.com/d5/tengo/) script. | ||||
| #The script will have the following global variables: | ||||
| #to modify: result | ||||
| #to read: channel, bridge, gateway, protocol, nick | ||||
| #to read: channel, bridge, gateway, protocol, nick, msgUserID | ||||
| # | ||||
| #The result will be set in {TENGO} in the RemoteNickFormat key of every bridge where {TENGO} is specified | ||||
| # | ||||
| @@ -1745,10 +1842,12 @@ enable=true | ||||
|     # ------------------------------------------------------------------------------------------------------------------------------------- | ||||
|     #   msteams  |      threadId      |    19:82abcxx@thread.skype    | You'll find the threadId in the URL | ||||
|     # ------------------------------------------------------------------------------------------------------------------------------------- | ||||
|     #   mumble   |    channel id      |              42               | The channel ID, as shown in the channel's "Edit" window | ||||
|     # ------------------------------------------------------------------------------------------------------------------------------------- | ||||
|     # rocketchat |      channel       |            #channel           | # is required for private channels too | ||||
|     # ------------------------------------------------------------------------------------------------------------------------------------- | ||||
|     #   slack    |   channel name     |            general            | Do not include the # symbol | ||||
|     #            |    channel id      |           ID:C123456          | The underlying ID of a channel. This doesn't work with | ||||
|     #            |    channel id      |           ID:C123456          | The underlying ID of a channel. This doesn't work with webhooks. | ||||
|     # ------------------------------------------------------------------------------------------------------------------------------------- | ||||
|     #   steam    |      chatid        |         example needed        | The number in the URL when you click "enter chat room" in the browser | ||||
|     # ------------------------------------------------------------------------------------------------------------------------------------- | ||||
| @@ -1756,6 +1855,8 @@ enable=true | ||||
|     # ------------------------------------------------------------------------------------------------------------------------------------- | ||||
|     #  telegram  |      chatid        |          -123456789           | A large negative number. see https://www.linkedin.com/pulse/telegram-bots-beginners-marco-frau | ||||
|     # ------------------------------------------------------------------------------------------------------------------------------------- | ||||
|     #  vk        |      peerid        |          2000000002           | A number that starts form 2000000000. Use --debug and send any message in chat to get PeerID in the logs  | ||||
|     # ------------------------------------------------------------------------------------------------------------------------------------- | ||||
|     #  whatsapp  |     group JID      | 48111222333-123455678999@g.us | A unique group JID. If you specify an empty string, bridge will list all the possibilities | ||||
|     #            |    "Group Name"    |         "Family Chat"         | if you specify a group name, the bridge will find hint the JID to specify. Names can change over time and are not stable. | ||||
|     # ------------------------------------------------------------------------------------------------------------------------------------- | ||||
| @@ -1795,13 +1896,16 @@ enable=true | ||||
|         #OPTIONAL - your irc / xmpp channel key | ||||
|         key="yourkey" | ||||
|  | ||||
|     # Discord specific gateway options | ||||
|     [[gateway.inout]] | ||||
|     account="discord.game" | ||||
|     channel="mygreatgame" | ||||
|  | ||||
|         #OPTIONAL - webhookurl only works for discord (it needs a different URL for each cahnnel) | ||||
|         [gateway.inout.options] | ||||
|         webhookurl="https://discordapp.com/api/webhooks/123456789123456789/C9WPqExYWONPDZabcdef-def1434FGFjstasJX9pYht73y" | ||||
|         # WebhookURL sends messages in the style of "puppets". You must configure a webhook URL for each channel you want to bridge. | ||||
|         # If you have more than one channel and don't wnat to configure each channel manually, see the "AutoWebhooks" option in the gateway config. | ||||
|         # Example: "https://discord.com/api/webhooks/1234/abcd_xyzw" | ||||
|         WebhookURL="" | ||||
|  | ||||
|     [[gateway.inout]] | ||||
|     account="zulip.streamchat" | ||||
|   | ||||
							
								
								
									
										77
									
								
								vendor/github.com/Jeffail/gabs/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										77
									
								
								vendor/github.com/Jeffail/gabs/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -7,21 +7,17 @@ It does nothing spectacular except for being fabulous. | ||||
|  | ||||
| https://godoc.org/github.com/Jeffail/gabs | ||||
|  | ||||
| ## How to install: | ||||
| ## Install | ||||
|  | ||||
| ``` bash | ||||
| go get github.com/Jeffail/gabs | ||||
| ``` | ||||
|  | ||||
| ## How to use | ||||
| ## Use | ||||
|  | ||||
| ### Parsing and searching JSON | ||||
|  | ||||
| ``` go | ||||
| ... | ||||
|  | ||||
| import "github.com/Jeffail/gabs" | ||||
|  | ||||
| jsonParsed, err := gabs.ParseJSON([]byte(`{ | ||||
| 	"outter":{ | ||||
| 		"inner":{ | ||||
| @@ -29,7 +25,10 @@ jsonParsed, err := gabs.ParseJSON([]byte(`{ | ||||
| 			"value2":22 | ||||
| 		}, | ||||
| 		"alsoInner":{ | ||||
| 			"value1":20 | ||||
| 			"value1":20, | ||||
| 			"array1":[ | ||||
| 				30, 40 | ||||
| 			] | ||||
| 		} | ||||
| 	} | ||||
| }`)) | ||||
| @@ -43,26 +42,26 @@ value, ok = jsonParsed.Path("outter.inner.value1").Data().(float64) | ||||
| value, ok = jsonParsed.Search("outter", "inner", "value1").Data().(float64) | ||||
| // value == 10.0, ok == true | ||||
|  | ||||
| gObj, err := jsonParsed.JSONPointer("/outter/alsoInner/array1/1") | ||||
| if err != nil { | ||||
| 	panic(err) | ||||
| } | ||||
| value, ok = gObj.Data().(float64) | ||||
| // value == 40.0, ok == true | ||||
|  | ||||
| value, ok = jsonParsed.Path("does.not.exist").Data().(float64) | ||||
| // value == 0.0, ok == false | ||||
|  | ||||
| exists := jsonParsed.Exists("outter", "inner", "value1") | ||||
| // exists == true | ||||
|  | ||||
| exists := jsonParsed.Exists("does", "not", "exist") | ||||
| // exists == false | ||||
|  | ||||
| exists := jsonParsed.ExistsP("does.not.exist") | ||||
| // exists == false | ||||
|  | ||||
| ... | ||||
| ``` | ||||
|  | ||||
| ### Iterating objects | ||||
|  | ||||
| ``` go | ||||
| ... | ||||
|  | ||||
| jsonParsed, _ := gabs.ParseJSON([]byte(`{"object":{ "first": 1, "second": 2, "third": 3 }}`)) | ||||
|  | ||||
| // S is shorthand for Search | ||||
| @@ -70,24 +69,25 @@ children, _ := jsonParsed.S("object").ChildrenMap() | ||||
| for key, child := range children { | ||||
| 	fmt.Printf("key: %v, value: %v\n", key, child.Data().(string)) | ||||
| } | ||||
|  | ||||
| ... | ||||
| ``` | ||||
|  | ||||
| ### Iterating arrays | ||||
|  | ||||
| ``` go | ||||
| ... | ||||
|  | ||||
| jsonParsed, _ := gabs.ParseJSON([]byte(`{"array":[ "first", "second", "third" ]}`)) | ||||
| jsonParsed, err := gabs.ParseJSON([]byte(`{"array":[ "first", "second", "third" ]}`)) | ||||
| if err != nil { | ||||
| 	panic(err) | ||||
| } | ||||
|  | ||||
| // S is shorthand for Search | ||||
| children, _ := jsonParsed.S("array").Children() | ||||
| children, err := jsonParsed.S("array").Children() | ||||
| if err != nil { | ||||
| 	panic(err) | ||||
| } | ||||
|  | ||||
| for _, child := range children { | ||||
| 	fmt.Println(child.Data().(string)) | ||||
| } | ||||
|  | ||||
| ... | ||||
| ``` | ||||
|  | ||||
| Will print: | ||||
| @@ -108,12 +108,11 @@ objects within the array, this returns a JSON array containing the results for | ||||
| each element. | ||||
|  | ||||
| ``` go | ||||
| ... | ||||
|  | ||||
| jsonParsed, _ := gabs.ParseJSON([]byte(`{"array":[ {"value":1}, {"value":2}, {"value":3} ]}`)) | ||||
| jsonParsed, err := gabs.ParseJSON([]byte(`{"array":[ {"value":1}, {"value":2}, {"value":3} ]}`)) | ||||
| if err != nil { | ||||
| 	panic(err) | ||||
| } | ||||
| fmt.Println(jsonParsed.Path("array.value").String()) | ||||
|  | ||||
| ... | ||||
| ``` | ||||
|  | ||||
| Will print: | ||||
| @@ -125,8 +124,6 @@ Will print: | ||||
| ### Generating JSON | ||||
|  | ||||
| ``` go | ||||
| ... | ||||
|  | ||||
| jsonObj := gabs.New() | ||||
| // or gabs.Consume(jsonObject) to work on an existing map[string]interface{} | ||||
|  | ||||
| @@ -135,8 +132,6 @@ jsonObj.SetP(20, "outter.inner.value2") | ||||
| jsonObj.Set(30, "outter", "inner2", "value3") | ||||
|  | ||||
| fmt.Println(jsonObj.String()) | ||||
|  | ||||
| ... | ||||
| ``` | ||||
|  | ||||
| Will print: | ||||
| @@ -148,11 +143,7 @@ Will print: | ||||
| To pretty-print: | ||||
|  | ||||
| ``` go | ||||
| ... | ||||
|  | ||||
| fmt.Println(jsonObj.StringIndent("", "  ")) | ||||
|  | ||||
| ... | ||||
| ``` | ||||
|  | ||||
| Will print: | ||||
| @@ -174,8 +165,6 @@ Will print: | ||||
| ### Generating Arrays | ||||
|  | ||||
| ``` go | ||||
| ... | ||||
|  | ||||
| jsonObj := gabs.New() | ||||
|  | ||||
| jsonObj.Array("foo", "array") | ||||
| @@ -186,8 +175,6 @@ jsonObj.ArrayAppend(20, "foo", "array") | ||||
| jsonObj.ArrayAppend(30, "foo", "array") | ||||
|  | ||||
| fmt.Println(jsonObj.String()) | ||||
|  | ||||
| ... | ||||
| ``` | ||||
|  | ||||
| Will print: | ||||
| @@ -199,8 +186,6 @@ Will print: | ||||
| Working with arrays by index: | ||||
|  | ||||
| ``` go | ||||
| ... | ||||
|  | ||||
| jsonObj := gabs.New() | ||||
|  | ||||
| // Create an array with the length of 3 | ||||
| @@ -217,8 +202,6 @@ jsonObj.S("foo").Index(2).SetIndex(2, 1) | ||||
| jsonObj.S("foo").Index(2).SetIndex(3, 2) | ||||
|  | ||||
| fmt.Println(jsonObj.String()) | ||||
|  | ||||
| ... | ||||
| ``` | ||||
|  | ||||
| Will print: | ||||
| @@ -232,8 +215,6 @@ Will print: | ||||
| This is the easiest part: | ||||
|  | ||||
| ``` go | ||||
| ... | ||||
|  | ||||
| jsonParsedObj, _ := gabs.ParseJSON([]byte(`{ | ||||
| 	"outter":{ | ||||
| 		"values":{ | ||||
| @@ -246,15 +227,11 @@ jsonParsedObj, _ := gabs.ParseJSON([]byte(`{ | ||||
|  | ||||
| jsonOutput := jsonParsedObj.String() | ||||
| // Becomes `{"outter":{"values":{"first":10,"second":11}},"outter2":"hello world"}` | ||||
|  | ||||
| ... | ||||
| ``` | ||||
|  | ||||
| And to serialize a specific segment is as simple as: | ||||
|  | ||||
| ``` go | ||||
| ... | ||||
|  | ||||
| jsonParsedObj := gabs.ParseJSON([]byte(`{ | ||||
| 	"outter":{ | ||||
| 		"values":{ | ||||
| @@ -267,8 +244,6 @@ jsonParsedObj := gabs.ParseJSON([]byte(`{ | ||||
|  | ||||
| jsonOutput := jsonParsedObj.Search("outter").String() | ||||
| // Becomes `{"values":{"first":10,"second":11}}` | ||||
|  | ||||
| ... | ||||
| ``` | ||||
|  | ||||
| ### Merge two containers | ||||
|   | ||||
							
								
								
									
										344
									
								
								vendor/github.com/Jeffail/gabs/gabs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										344
									
								
								vendor/github.com/Jeffail/gabs/gabs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -20,58 +20,85 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| THE SOFTWARE. | ||||
| */ | ||||
|  | ||||
| // Package gabs implements a simplified wrapper around creating and parsing JSON. | ||||
| // Package gabs implements a simplified wrapper around creating and parsing | ||||
| // unknown or dynamic JSON. | ||||
| package gabs | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| //-------------------------------------------------------------------------------------------------- | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| var ( | ||||
| 	// ErrOutOfBounds - Index out of bounds. | ||||
| 	// ErrOutOfBounds indicates an index was out of bounds. | ||||
| 	ErrOutOfBounds = errors.New("out of bounds") | ||||
|  | ||||
| 	// ErrNotObjOrArray - The target is not an object or array type. | ||||
| 	// ErrNotObjOrArray is returned when a target is not an object or array type | ||||
| 	// but needs to be for the intended operation. | ||||
| 	ErrNotObjOrArray = errors.New("not an object or array") | ||||
|  | ||||
| 	// ErrNotObj - The target is not an object type. | ||||
| 	// ErrNotObj is returned when a target is not an object but needs to be for | ||||
| 	// the intended operation. | ||||
| 	ErrNotObj = errors.New("not an object") | ||||
|  | ||||
| 	// ErrNotArray - The target is not an array type. | ||||
| 	// ErrNotArray is returned when a target is not an array but needs to be for | ||||
| 	// the intended operation. | ||||
| 	ErrNotArray = errors.New("not an array") | ||||
|  | ||||
| 	// ErrPathCollision - Creating a path failed because an element collided with an existing value. | ||||
| 	// ErrPathCollision is returned when creating a path failed because an | ||||
| 	// element collided with an existing value. | ||||
| 	ErrPathCollision = errors.New("encountered value collision whilst building path") | ||||
|  | ||||
| 	// ErrInvalidInputObj - The input value was not a map[string]interface{}. | ||||
| 	// ErrInvalidInputObj is returned when the input value was not a | ||||
| 	// map[string]interface{}. | ||||
| 	ErrInvalidInputObj = errors.New("invalid input object") | ||||
|  | ||||
| 	// ErrInvalidInputText - The input data could not be parsed. | ||||
| 	// ErrInvalidInputText is returned when the input data could not be parsed. | ||||
| 	ErrInvalidInputText = errors.New("input text could not be parsed") | ||||
|  | ||||
| 	// ErrInvalidPath - The filepath was not valid. | ||||
| 	// ErrInvalidPath is returned when the filepath was not valid. | ||||
| 	ErrInvalidPath = errors.New("invalid file path") | ||||
|  | ||||
| 	// ErrInvalidBuffer - The input buffer contained an invalid JSON string | ||||
| 	// ErrInvalidBuffer is returned when the input buffer contained an invalid | ||||
| 	// JSON string. | ||||
| 	ErrInvalidBuffer = errors.New("input buffer contained invalid JSON") | ||||
| ) | ||||
|  | ||||
| //-------------------------------------------------------------------------------------------------- | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| // Container - an internal structure that holds a reference to the core interface map of the parsed | ||||
| // json. Use this container to move context. | ||||
| func resolveJSONPointerHierarchy(path string) ([]string, error) { | ||||
| 	if len(path) < 1 { | ||||
| 		return nil, errors.New("failed to resolve JSON pointer: path must not be empty") | ||||
| 	} | ||||
| 	if path[0] != '/' { | ||||
| 		return nil, errors.New("failed to resolve JSON pointer: path must begin with '/'") | ||||
| 	} | ||||
| 	hierarchy := strings.Split(path, "/")[1:] | ||||
| 	for i, v := range hierarchy { | ||||
| 		v = strings.Replace(v, "~1", "/", -1) | ||||
| 		v = strings.Replace(v, "~0", "~", -1) | ||||
| 		hierarchy[i] = v | ||||
| 	} | ||||
| 	return hierarchy, nil | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| // Container references a specific element within a JSON structure. | ||||
| type Container struct { | ||||
| 	object interface{} | ||||
| } | ||||
|  | ||||
| // Data - Return the contained data as an interface{}. | ||||
| // Data returns the underlying interface{} of the target element in the JSON | ||||
| // structure. | ||||
| func (g *Container) Data() interface{} { | ||||
| 	if g == nil { | ||||
| 		return nil | ||||
| @@ -79,17 +106,18 @@ func (g *Container) Data() interface{} { | ||||
| 	return g.object | ||||
| } | ||||
|  | ||||
| //-------------------------------------------------------------------------------------------------- | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| // Path - Search for a value using dot notation. | ||||
| // Path searches the JSON structure following a path in dot notation. | ||||
| func (g *Container) Path(path string) *Container { | ||||
| 	return g.Search(strings.Split(path, ".")...) | ||||
| } | ||||
|  | ||||
| // Search - Attempt to find and return an object within the JSON structure by specifying the | ||||
| // hierarchy of field names to locate the target. If the search encounters an array and has not | ||||
| // reached the end target then it will iterate each object of the array for the target and return | ||||
| // all of the results in a JSON array. | ||||
| // Search attempts to find and return an object within the JSON structure by | ||||
| // following a provided hierarchy of field names to locate the target. If the | ||||
| // search encounters an array and has not reached the end target then it will | ||||
| // iterate each object of the array for the target and return all of the results | ||||
| // in a JSON array. | ||||
| func (g *Container) Search(hierarchy ...string) *Container { | ||||
| 	var object interface{} | ||||
|  | ||||
| @@ -120,22 +148,55 @@ func (g *Container) Search(hierarchy ...string) *Container { | ||||
| 	return &Container{object} | ||||
| } | ||||
|  | ||||
| // S - Shorthand method, does the same thing as Search. | ||||
| // JSONPointer parses a JSON pointer path (https://tools.ietf.org/html/rfc6901) | ||||
| // and either returns a *gabs.Container containing the result or an error if the | ||||
| // referenced item could not be found. | ||||
| func (g *Container) JSONPointer(path string) (*Container, error) { | ||||
| 	hierarchy, err := resolveJSONPointerHierarchy(path) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	object := g.Data() | ||||
| 	for target := 0; target < len(hierarchy); target++ { | ||||
| 		pathSeg := hierarchy[target] | ||||
| 		if mmap, ok := object.(map[string]interface{}); ok { | ||||
| 			object, ok = mmap[pathSeg] | ||||
| 			if !ok { | ||||
| 				return nil, fmt.Errorf("failed to resolve JSON pointer: index '%v' value '%v' was not found", target, pathSeg) | ||||
| 			} | ||||
| 		} else if marray, ok := object.([]interface{}); ok { | ||||
| 			index, err := strconv.Atoi(pathSeg) | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("failed to resolve JSON pointer: could not parse index '%v' value '%v' into array index: %v", target, pathSeg, err) | ||||
| 			} | ||||
| 			if len(marray) <= index { | ||||
| 				return nil, fmt.Errorf("failed to resolve JSON pointer: index '%v' value '%v' exceeded target array size of '%v'", target, pathSeg, len(marray)) | ||||
| 			} | ||||
| 			object = marray[index] | ||||
| 		} else { | ||||
| 			return &Container{nil}, fmt.Errorf("failed to resolve JSON pointer: index '%v' field '%v' was not found", target, pathSeg) | ||||
| 		} | ||||
| 	} | ||||
| 	return &Container{object}, nil | ||||
| } | ||||
|  | ||||
| // S is a shorthand alias for Search. | ||||
| func (g *Container) S(hierarchy ...string) *Container { | ||||
| 	return g.Search(hierarchy...) | ||||
| } | ||||
|  | ||||
| // Exists - Checks whether a path exists. | ||||
| // Exists checks whether a path exists. | ||||
| func (g *Container) Exists(hierarchy ...string) bool { | ||||
| 	return g.Search(hierarchy...) != nil | ||||
| } | ||||
|  | ||||
| // ExistsP - Checks whether a dot notation path exists. | ||||
| // ExistsP checks whether a dot notation path exists. | ||||
| func (g *Container) ExistsP(path string) bool { | ||||
| 	return g.Exists(strings.Split(path, ".")...) | ||||
| } | ||||
|  | ||||
| // Index - Attempt to find and return an object within a JSON array by index. | ||||
| // Index attempts to find and return an element within a JSON array by an index. | ||||
| func (g *Container) Index(index int) *Container { | ||||
| 	if array, ok := g.Data().([]interface{}); ok { | ||||
| 		if index >= len(array) { | ||||
| @@ -146,9 +207,9 @@ func (g *Container) Index(index int) *Container { | ||||
| 	return &Container{nil} | ||||
| } | ||||
|  | ||||
| // Children - Return a slice of all the children of the array. This also works for objects, however, | ||||
| // the children returned for an object will NOT be in order and you lose the names of the returned | ||||
| // objects this way. | ||||
| // Children returns a slice of all children of an array element. This also works | ||||
| // for objects, however, the children returned for an object will be in a random | ||||
| // order and you lose the names of the returned objects this way. | ||||
| func (g *Container) Children() ([]*Container, error) { | ||||
| 	if array, ok := g.Data().([]interface{}); ok { | ||||
| 		children := make([]*Container, len(array)) | ||||
| @@ -167,7 +228,7 @@ func (g *Container) Children() ([]*Container, error) { | ||||
| 	return nil, ErrNotObjOrArray | ||||
| } | ||||
|  | ||||
| // ChildrenMap - Return a map of all the children of an object. | ||||
| // ChildrenMap returns a map of all the children of an object element. | ||||
| func (g *Container) ChildrenMap() (map[string]*Container, error) { | ||||
| 	if mmap, ok := g.Data().(map[string]interface{}); ok { | ||||
| 		children := map[string]*Container{} | ||||
| @@ -179,11 +240,11 @@ func (g *Container) ChildrenMap() (map[string]*Container, error) { | ||||
| 	return nil, ErrNotObj | ||||
| } | ||||
|  | ||||
| //-------------------------------------------------------------------------------------------------- | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| // Set - Set the value of a field at a JSON path, any parts of the path that do not exist will be | ||||
| // constructed, and if a collision occurs with a non object type whilst iterating the path an error | ||||
| // is returned. | ||||
| // Set the value of a field at a JSON path, any parts of the path that do not | ||||
| // exist will be constructed, and if a collision occurs with a non object type | ||||
| // whilst iterating the path an error is returned. | ||||
| func (g *Container) Set(value interface{}, path ...string) (*Container, error) { | ||||
| 	if len(path) == 0 { | ||||
| 		g.object = value | ||||
| @@ -209,12 +270,14 @@ func (g *Container) Set(value interface{}, path ...string) (*Container, error) { | ||||
| 	return &Container{object}, nil | ||||
| } | ||||
|  | ||||
| // SetP - Does the same as Set, but using a dot notation JSON path. | ||||
| // SetP sets the value of a field at a JSON path using dot notation, any parts | ||||
| // of the path that do not exist will be constructed, and if a collision occurs | ||||
| // with a non object type whilst iterating the path an error is returned. | ||||
| func (g *Container) SetP(value interface{}, path string) (*Container, error) { | ||||
| 	return g.Set(value, strings.Split(path, ".")...) | ||||
| } | ||||
|  | ||||
| // SetIndex - Set a value of an array element based on the index. | ||||
| // SetIndex attempts to set a value of an array element based on an index. | ||||
| func (g *Container) SetIndex(value interface{}, index int) (*Container, error) { | ||||
| 	if array, ok := g.Data().([]interface{}); ok { | ||||
| 		if index >= len(array) { | ||||
| @@ -226,60 +289,112 @@ func (g *Container) SetIndex(value interface{}, index int) (*Container, error) { | ||||
| 	return &Container{nil}, ErrNotArray | ||||
| } | ||||
|  | ||||
| // Object - Create a new JSON object at a path. Returns an error if the path contains a collision | ||||
| // with a non object type. | ||||
| // SetJSONPointer parses a JSON pointer path | ||||
| // (https://tools.ietf.org/html/rfc6901) and sets the leaf to a value. Returns | ||||
| // an error if the pointer could not be resolved due to missing fields. | ||||
| func (g *Container) SetJSONPointer(value interface{}, path string) error { | ||||
| 	hierarchy, err := resolveJSONPointerHierarchy(path) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if len(hierarchy) == 0 { | ||||
| 		g.object = value | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	object := g.object | ||||
|  | ||||
| 	for target := 0; target < len(hierarchy); target++ { | ||||
| 		pathSeg := hierarchy[target] | ||||
| 		if mmap, ok := object.(map[string]interface{}); ok { | ||||
| 			if target == len(hierarchy)-1 { | ||||
| 				object = value | ||||
| 				mmap[pathSeg] = object | ||||
| 			} else if object = mmap[pathSeg]; object == nil { | ||||
| 				return fmt.Errorf("failed to resolve JSON pointer: index '%v' value '%v' was not found", target, pathSeg) | ||||
| 			} | ||||
| 		} else if marray, ok := object.([]interface{}); ok { | ||||
| 			index, err := strconv.Atoi(pathSeg) | ||||
| 			if err != nil { | ||||
| 				return fmt.Errorf("failed to resolve JSON pointer: could not parse index '%v' value '%v' into array index: %v", target, pathSeg, err) | ||||
| 			} | ||||
| 			if len(marray) <= index { | ||||
| 				return fmt.Errorf("failed to resolve JSON pointer: index '%v' value '%v' exceeded target array size of '%v'", target, pathSeg, len(marray)) | ||||
| 			} | ||||
| 			if target == len(hierarchy)-1 { | ||||
| 				object = value | ||||
| 				marray[index] = object | ||||
| 			} else if object = marray[index]; object == nil { | ||||
| 				return fmt.Errorf("failed to resolve JSON pointer: index '%v' value '%v' was not found", target, pathSeg) | ||||
| 			} | ||||
| 		} else { | ||||
| 			return fmt.Errorf("failed to resolve JSON pointer: index '%v' value '%v' was not found", target, pathSeg) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Object creates a new JSON object at a target path. Returns an error if the | ||||
| // path contains a collision with a non object type. | ||||
| func (g *Container) Object(path ...string) (*Container, error) { | ||||
| 	return g.Set(map[string]interface{}{}, path...) | ||||
| } | ||||
|  | ||||
| // ObjectP - Does the same as Object, but using a dot notation JSON path. | ||||
| // ObjectP creates a new JSON object at a target path using dot notation. | ||||
| // Returns an error if the path contains a collision with a non object type. | ||||
| func (g *Container) ObjectP(path string) (*Container, error) { | ||||
| 	return g.Object(strings.Split(path, ".")...) | ||||
| } | ||||
|  | ||||
| // ObjectI - Create a new JSON object at an array index. Returns an error if the object is not an | ||||
| // array or the index is out of bounds. | ||||
| // ObjectI creates a new JSON object at an array index. Returns an error if the | ||||
| // object is not an array or the index is out of bounds. | ||||
| func (g *Container) ObjectI(index int) (*Container, error) { | ||||
| 	return g.SetIndex(map[string]interface{}{}, index) | ||||
| } | ||||
|  | ||||
| // Array - Create a new JSON array at a path. Returns an error if the path contains a collision with | ||||
| // a non object type. | ||||
| // Array creates a new JSON array at a path. Returns an error if the path | ||||
| // contains a collision with a non object type. | ||||
| func (g *Container) Array(path ...string) (*Container, error) { | ||||
| 	return g.Set([]interface{}{}, path...) | ||||
| } | ||||
|  | ||||
| // ArrayP - Does the same as Array, but using a dot notation JSON path. | ||||
| // ArrayP creates a new JSON array at a path using dot notation. Returns an | ||||
| // error if the path contains a collision with a non object type. | ||||
| func (g *Container) ArrayP(path string) (*Container, error) { | ||||
| 	return g.Array(strings.Split(path, ".")...) | ||||
| } | ||||
|  | ||||
| // ArrayI - Create a new JSON array at an array index. Returns an error if the object is not an | ||||
| // array or the index is out of bounds. | ||||
| // ArrayI creates a new JSON array within an array at an index. Returns an error | ||||
| // if the element is not an array or the index is out of bounds. | ||||
| func (g *Container) ArrayI(index int) (*Container, error) { | ||||
| 	return g.SetIndex([]interface{}{}, index) | ||||
| } | ||||
|  | ||||
| // ArrayOfSize - Create a new JSON array of a particular size at a path. Returns an error if the | ||||
| // path contains a collision with a non object type. | ||||
| // ArrayOfSize creates a new JSON array of a particular size at a path. Returns | ||||
| // an error if the path contains a collision with a non object type. | ||||
| func (g *Container) ArrayOfSize(size int, path ...string) (*Container, error) { | ||||
| 	a := make([]interface{}, size) | ||||
| 	return g.Set(a, path...) | ||||
| } | ||||
|  | ||||
| // ArrayOfSizeP - Does the same as ArrayOfSize, but using a dot notation JSON path. | ||||
| // ArrayOfSizeP creates a new JSON array of a particular size at a path using | ||||
| // dot notation. Returns an error if the path contains a collision with a non | ||||
| // object type. | ||||
| func (g *Container) ArrayOfSizeP(size int, path string) (*Container, error) { | ||||
| 	return g.ArrayOfSize(size, strings.Split(path, ".")...) | ||||
| } | ||||
|  | ||||
| // ArrayOfSizeI - Create a new JSON array of a particular size at an array index. Returns an error | ||||
| // if the object is not an array or the index is out of bounds. | ||||
| // ArrayOfSizeI create a new JSON array of a particular size within an array at | ||||
| // an index. Returns an error if the element is not an array or the index is out | ||||
| // of bounds. | ||||
| func (g *Container) ArrayOfSizeI(size, index int) (*Container, error) { | ||||
| 	a := make([]interface{}, size) | ||||
| 	return g.SetIndex(a, index) | ||||
| } | ||||
|  | ||||
| // Delete - Delete an element at a JSON path, an error is returned if the element does not exist. | ||||
| // Delete an element at a path, an error is returned if the element does not | ||||
| // exist. | ||||
| func (g *Container) Delete(path ...string) error { | ||||
| 	var object interface{} | ||||
|  | ||||
| @@ -304,45 +419,40 @@ func (g *Container) Delete(path ...string) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // DeleteP - Does the same as Delete, but using a dot notation JSON path. | ||||
| // DeleteP deletes an element at a path using dot notation, an error is returned | ||||
| // if the element does not exist. | ||||
| func (g *Container) DeleteP(path string) error { | ||||
| 	return g.Delete(strings.Split(path, ".")...) | ||||
| } | ||||
|  | ||||
| // Merge - Merges two gabs-containers | ||||
| func (g *Container) Merge(toMerge *Container) error { | ||||
| // MergeFn merges two objects using a provided function to resolve collisions. | ||||
| // | ||||
| // The collision function receives two interface{} arguments, destination (the | ||||
| // original object) and source (the object being merged into the destination). | ||||
| // Which ever value is returned becomes the new value in the destination object | ||||
| // at the location of the collision. | ||||
| func (g *Container) MergeFn(source *Container, collisionFn func(destination, source interface{}) interface{}) error { | ||||
| 	var recursiveFnc func(map[string]interface{}, []string) error | ||||
| 	recursiveFnc = func(mmap map[string]interface{}, path []string) error { | ||||
| 		for key, value := range mmap { | ||||
| 			newPath := append(path, key) | ||||
| 			if g.Exists(newPath...) { | ||||
| 				target := g.Search(newPath...) | ||||
| 				existingData := g.Search(newPath...).Data() | ||||
| 				switch t := value.(type) { | ||||
| 				case map[string]interface{}: | ||||
| 					switch targetV := target.Data().(type) { | ||||
| 					switch existingVal := existingData.(type) { | ||||
| 					case map[string]interface{}: | ||||
| 						if err := recursiveFnc(t, newPath); err != nil { | ||||
| 							return err | ||||
| 						} | ||||
| 					case []interface{}: | ||||
| 						g.Set(append(targetV, t), newPath...) | ||||
| 					default: | ||||
| 						newSlice := append([]interface{}{}, targetV) | ||||
| 						g.Set(append(newSlice, t), newPath...) | ||||
| 					} | ||||
| 				case []interface{}: | ||||
| 					for _, valueOfSlice := range t { | ||||
| 						if err := g.ArrayAppend(valueOfSlice, newPath...); err != nil { | ||||
| 						if _, err := g.Set(collisionFn(existingVal, t), newPath...); err != nil { | ||||
| 							return err | ||||
| 						} | ||||
| 					} | ||||
| 				default: | ||||
| 					switch targetV := target.Data().(type) { | ||||
| 					case []interface{}: | ||||
| 						g.Set(append(targetV, t), newPath...) | ||||
| 					default: | ||||
| 						newSlice := append([]interface{}{}, targetV) | ||||
| 						g.Set(append(newSlice, t), newPath...) | ||||
| 					if _, err := g.Set(collisionFn(existingData, t), newPath...); err != nil { | ||||
| 						return err | ||||
| 					} | ||||
| 				} | ||||
| 			} else { | ||||
| @@ -354,21 +464,48 @@ func (g *Container) Merge(toMerge *Container) error { | ||||
| 		} | ||||
| 		return nil | ||||
| 	} | ||||
| 	if mmap, ok := toMerge.Data().(map[string]interface{}); ok { | ||||
| 	if mmap, ok := source.Data().(map[string]interface{}); ok { | ||||
| 		return recursiveFnc(mmap, []string{}) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| //-------------------------------------------------------------------------------------------------- | ||||
| // Merge a source object into an existing destination object. When a collision | ||||
| // is found within the merged structures (both a source and destination object | ||||
| // contain the same non-object keys) the result will be an array containing both | ||||
| // values, where values that are already arrays will be expanded into the | ||||
| // resulting array. | ||||
| // | ||||
| // It is possible to merge structures will different collision behaviours with | ||||
| // MergeFn. | ||||
| func (g *Container) Merge(source *Container) error { | ||||
| 	return g.MergeFn(source, func(dest, source interface{}) interface{} { | ||||
| 		destArr, destIsArray := dest.([]interface{}) | ||||
| 		sourceArr, sourceIsArray := source.([]interface{}) | ||||
| 		if destIsArray { | ||||
| 			if sourceIsArray { | ||||
| 				return append(destArr, sourceArr...) | ||||
| 			} | ||||
| 			return append(destArr, source) | ||||
| 		} | ||||
| 		if sourceIsArray { | ||||
| 			return append(append([]interface{}{}, dest), sourceArr...) | ||||
| 		} | ||||
| 		return []interface{}{dest, source} | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /* | ||||
| Array modification/search - Keeping these options simple right now, no need for anything more | ||||
| complicated since you can just cast to []interface{}, modify and then reassign with Set. | ||||
| Array modification/search - Keeping these options simple right now, no need for | ||||
| anything more complicated since you can just cast to []interface{}, modify and | ||||
| then reassign with Set. | ||||
| */ | ||||
|  | ||||
| // ArrayAppend - Append a value onto a JSON array. If the target is not a JSON array then it will be | ||||
| // converted into one, with its contents as the first element of the array. | ||||
| // ArrayAppend attempts to append a value onto a JSON array at a path. If the | ||||
| // target is not a JSON array then it will be converted into one, with its | ||||
| // original contents set to the first element of the array. | ||||
| func (g *Container) ArrayAppend(value interface{}, path ...string) error { | ||||
| 	if array, ok := g.Search(path...).Data().([]interface{}); ok { | ||||
| 		array = append(array, value) | ||||
| @@ -386,12 +523,15 @@ func (g *Container) ArrayAppend(value interface{}, path ...string) error { | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // ArrayAppendP - Append a value onto a JSON array using a dot notation JSON path. | ||||
| // ArrayAppendP attempts to append a value onto a JSON array at a path using dot | ||||
| // notation. If the target is not a JSON array then it will be converted into | ||||
| // one, with its original contents set to the first element of the array. | ||||
| func (g *Container) ArrayAppendP(value interface{}, path string) error { | ||||
| 	return g.ArrayAppend(value, strings.Split(path, ".")...) | ||||
| } | ||||
|  | ||||
| // ArrayRemove - Remove an element from a JSON array. | ||||
| // ArrayRemove attempts to remove an element identified by an index from a JSON | ||||
| // array at a path. | ||||
| func (g *Container) ArrayRemove(index int, path ...string) error { | ||||
| 	if index < 0 { | ||||
| 		return ErrOutOfBounds | ||||
| @@ -409,12 +549,14 @@ func (g *Container) ArrayRemove(index int, path ...string) error { | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // ArrayRemoveP - Remove an element from a JSON array using a dot notation JSON path. | ||||
| // ArrayRemoveP attempts to remove an element identified by an index from a JSON | ||||
| // array at a path using dot notation. | ||||
| func (g *Container) ArrayRemoveP(index int, path string) error { | ||||
| 	return g.ArrayRemove(index, strings.Split(path, ".")...) | ||||
| } | ||||
|  | ||||
| // ArrayElement - Access an element from a JSON array. | ||||
| // ArrayElement attempts to access an element by an index from a JSON array at a | ||||
| // path. | ||||
| func (g *Container) ArrayElement(index int, path ...string) (*Container, error) { | ||||
| 	if index < 0 { | ||||
| 		return &Container{nil}, ErrOutOfBounds | ||||
| @@ -429,12 +571,13 @@ func (g *Container) ArrayElement(index int, path ...string) (*Container, error) | ||||
| 	return &Container{nil}, ErrOutOfBounds | ||||
| } | ||||
|  | ||||
| // ArrayElementP - Access an element from a JSON array using a dot notation JSON path. | ||||
| // ArrayElementP attempts to access an element by an index from a JSON array at | ||||
| // a path using dot notation. | ||||
| func (g *Container) ArrayElementP(index int, path string) (*Container, error) { | ||||
| 	return g.ArrayElement(index, strings.Split(path, ".")...) | ||||
| } | ||||
|  | ||||
| // ArrayCount - Count the number of elements in a JSON array. | ||||
| // ArrayCount counts the number of elements in a JSON array at a path. | ||||
| func (g *Container) ArrayCount(path ...string) (int, error) { | ||||
| 	if array, ok := g.Search(path...).Data().([]interface{}); ok { | ||||
| 		return len(array), nil | ||||
| @@ -442,14 +585,15 @@ func (g *Container) ArrayCount(path ...string) (int, error) { | ||||
| 	return 0, ErrNotArray | ||||
| } | ||||
|  | ||||
| // ArrayCountP - Count the number of elements in a JSON array using a dot notation JSON path. | ||||
| // ArrayCountP counts the number of elements in a JSON array at a path using dot | ||||
| // notation. | ||||
| func (g *Container) ArrayCountP(path string) (int, error) { | ||||
| 	return g.ArrayCount(strings.Split(path, ".")...) | ||||
| } | ||||
|  | ||||
| //-------------------------------------------------------------------------------------------------- | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| // Bytes - Converts the contained object back to a JSON []byte blob. | ||||
| // Bytes marshals an element to a JSON []byte blob. | ||||
| func (g *Container) Bytes() []byte { | ||||
| 	if g.Data() != nil { | ||||
| 		if bytes, err := json.Marshal(g.object); err == nil { | ||||
| @@ -459,7 +603,8 @@ func (g *Container) Bytes() []byte { | ||||
| 	return []byte("{}") | ||||
| } | ||||
|  | ||||
| // BytesIndent - Converts the contained object to a JSON []byte blob formatted with prefix, indent. | ||||
| // BytesIndent marshals an element to a JSON []byte blob formatted with a prefix | ||||
| // and indent string. | ||||
| func (g *Container) BytesIndent(prefix string, indent string) []byte { | ||||
| 	if g.object != nil { | ||||
| 		if bytes, err := json.MarshalIndent(g.object, prefix, indent); err == nil { | ||||
| @@ -469,12 +614,13 @@ func (g *Container) BytesIndent(prefix string, indent string) []byte { | ||||
| 	return []byte("{}") | ||||
| } | ||||
|  | ||||
| // String - Converts the contained object to a JSON formatted string. | ||||
| // String marshals an element to a JSON formatted string. | ||||
| func (g *Container) String() string { | ||||
| 	return string(g.Bytes()) | ||||
| } | ||||
|  | ||||
| // StringIndent - Converts the contained object back to a JSON formatted string with prefix, indent. | ||||
| // StringIndent marshals an element to a JSON string formatted with a prefix and | ||||
| // indent string. | ||||
| func (g *Container) StringIndent(prefix string, indent string) string { | ||||
| 	return string(g.BytesIndent(prefix, indent)) | ||||
| } | ||||
| @@ -496,10 +642,9 @@ func EncodeOptIndent(prefix string, indent string) EncodeOpt { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // EncodeJSON - Encodes the contained object back to a JSON formatted []byte | ||||
| // using a variant list of modifier functions for the encoder being used. | ||||
| // Functions for modifying the output are prefixed with EncodeOpt, e.g. | ||||
| // EncodeOptHTMLEscape. | ||||
| // EncodeJSON marshals an element to a JSON formatted []byte using a variant | ||||
| // list of modifier functions for the encoder being used. Functions for | ||||
| // modifying the output are prefixed with EncodeOpt, e.g. EncodeOptHTMLEscape. | ||||
| func (g *Container) EncodeJSON(encodeOpts ...EncodeOpt) []byte { | ||||
| 	var b bytes.Buffer | ||||
| 	encoder := json.NewEncoder(&b) | ||||
| @@ -517,17 +662,18 @@ func (g *Container) EncodeJSON(encodeOpts ...EncodeOpt) []byte { | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // New - Create a new gabs JSON object. | ||||
| // New creates a new gabs JSON object. | ||||
| func New() *Container { | ||||
| 	return &Container{map[string]interface{}{}} | ||||
| } | ||||
|  | ||||
| // Consume - Gobble up an already converted JSON object, or a fresh map[string]interface{} object. | ||||
| // Consume an already unmarshalled JSON object (or a new map[string]interface{}) | ||||
| // into a *Container. | ||||
| func Consume(root interface{}) (*Container, error) { | ||||
| 	return &Container{root}, nil | ||||
| } | ||||
|  | ||||
| // ParseJSON - Convert a string into a representation of the parsed JSON. | ||||
| // ParseJSON unmarshals a JSON byte slice into a *Container. | ||||
| func ParseJSON(sample []byte) (*Container, error) { | ||||
| 	var gabs Container | ||||
|  | ||||
| @@ -538,7 +684,7 @@ func ParseJSON(sample []byte) (*Container, error) { | ||||
| 	return &gabs, nil | ||||
| } | ||||
|  | ||||
| // ParseJSONDecoder - Convert a json.Decoder into a representation of the parsed JSON. | ||||
| // ParseJSONDecoder applies a json.Decoder to a *Container. | ||||
| func ParseJSONDecoder(decoder *json.Decoder) (*Container, error) { | ||||
| 	var gabs Container | ||||
|  | ||||
| @@ -549,7 +695,7 @@ func ParseJSONDecoder(decoder *json.Decoder) (*Container, error) { | ||||
| 	return &gabs, nil | ||||
| } | ||||
|  | ||||
| // ParseJSONFile - Read a file and convert into a representation of the parsed JSON. | ||||
| // ParseJSONFile reads a file and unmarshals the contents into a *Container. | ||||
| func ParseJSONFile(path string) (*Container, error) { | ||||
| 	if len(path) > 0 { | ||||
| 		cBytes, err := ioutil.ReadFile(path) | ||||
| @@ -567,7 +713,7 @@ func ParseJSONFile(path string) (*Container, error) { | ||||
| 	return nil, ErrInvalidPath | ||||
| } | ||||
|  | ||||
| // ParseJSONBuffer - Read the contents of a buffer into a representation of the parsed JSON. | ||||
| // ParseJSONBuffer reads a buffer and unmarshals the contents into a *Container. | ||||
| func ParseJSONBuffer(buffer io.Reader) (*Container, error) { | ||||
| 	var gabs Container | ||||
| 	jsonDecoder := json.NewDecoder(buffer) | ||||
| @@ -578,4 +724,4 @@ func ParseJSONBuffer(buffer io.Reader) (*Container, error) { | ||||
| 	return &gabs, nil | ||||
| } | ||||
|  | ||||
| //-------------------------------------------------------------------------------------------------- | ||||
| //------------------------------------------------------------------------------ | ||||
|   | ||||
							
								
								
									
										1
									
								
								vendor/github.com/Jeffail/gabs/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/Jeffail/gabs/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| module github.com/Jeffail/gabs | ||||
							
								
								
									
										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, | ||||
| } | ||||
|   | ||||
							
								
								
									
										180
									
								
								vendor/github.com/Philipp15b/go-steam/protocol/protobuf/content_manifest.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										180
									
								
								vendor/github.com/Philipp15b/go-steam/protocol/protobuf/content_manifest.pb.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -20,6 +20,46 @@ var _ = math.Inf | ||||
| // proto package protobuf to be updated. | ||||
| const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package | ||||
|  | ||||
| type EContentDeltaChunkDataLocation int32 | ||||
|  | ||||
| const ( | ||||
| 	EContentDeltaChunkDataLocation_k_EContentDeltaChunkDataLocationInProtobuf    EContentDeltaChunkDataLocation = 0 | ||||
| 	EContentDeltaChunkDataLocation_k_EContentDeltaChunkDataLocationAfterProtobuf EContentDeltaChunkDataLocation = 1 | ||||
| ) | ||||
|  | ||||
| var EContentDeltaChunkDataLocation_name = map[int32]string{ | ||||
| 	0: "k_EContentDeltaChunkDataLocationInProtobuf", | ||||
| 	1: "k_EContentDeltaChunkDataLocationAfterProtobuf", | ||||
| } | ||||
|  | ||||
| var EContentDeltaChunkDataLocation_value = map[string]int32{ | ||||
| 	"k_EContentDeltaChunkDataLocationInProtobuf":    0, | ||||
| 	"k_EContentDeltaChunkDataLocationAfterProtobuf": 1, | ||||
| } | ||||
|  | ||||
| func (x EContentDeltaChunkDataLocation) Enum() *EContentDeltaChunkDataLocation { | ||||
| 	p := new(EContentDeltaChunkDataLocation) | ||||
| 	*p = x | ||||
| 	return p | ||||
| } | ||||
|  | ||||
| func (x EContentDeltaChunkDataLocation) String() string { | ||||
| 	return proto.EnumName(EContentDeltaChunkDataLocation_name, int32(x)) | ||||
| } | ||||
|  | ||||
| func (x *EContentDeltaChunkDataLocation) UnmarshalJSON(data []byte) error { | ||||
| 	value, err := proto.UnmarshalJSONEnum(EContentDeltaChunkDataLocation_value, data, "EContentDeltaChunkDataLocation") | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	*x = EContentDeltaChunkDataLocation(value) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (EContentDeltaChunkDataLocation) EnumDescriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_e3cda137a29253ba, []int{0} | ||||
| } | ||||
|  | ||||
| type ContentManifestPayload struct { | ||||
| 	Mappings             []*ContentManifestPayload_FileMapping `protobuf:"bytes,1,rep,name=mappings" json:"mappings,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{}                              `json:"-"` | ||||
| @@ -63,8 +103,8 @@ type ContentManifestPayload_FileMapping struct { | ||||
| 	Filename             *string                                         `protobuf:"bytes,1,opt,name=filename" json:"filename,omitempty"` | ||||
| 	Size                 *uint64                                         `protobuf:"varint,2,opt,name=size" json:"size,omitempty"` | ||||
| 	Flags                *uint32                                         `protobuf:"varint,3,opt,name=flags" json:"flags,omitempty"` | ||||
| 	ShaFilename          []byte                                          `protobuf:"bytes,4,opt,name=sha_filename" json:"sha_filename,omitempty"` | ||||
| 	ShaContent           []byte                                          `protobuf:"bytes,5,opt,name=sha_content" json:"sha_content,omitempty"` | ||||
| 	ShaFilename          []byte                                          `protobuf:"bytes,4,opt,name=sha_filename,json=shaFilename" json:"sha_filename,omitempty"` | ||||
| 	ShaContent           []byte                                          `protobuf:"bytes,5,opt,name=sha_content,json=shaContent" json:"sha_content,omitempty"` | ||||
| 	Chunks               []*ContentManifestPayload_FileMapping_ChunkData `protobuf:"bytes,6,rep,name=chunks" json:"chunks,omitempty"` | ||||
| 	Linktarget           *string                                         `protobuf:"bytes,7,opt,name=linktarget" json:"linktarget,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{}                                        `json:"-"` | ||||
| @@ -150,8 +190,8 @@ type ContentManifestPayload_FileMapping_ChunkData struct { | ||||
| 	Sha                  []byte   `protobuf:"bytes,1,opt,name=sha" json:"sha,omitempty"` | ||||
| 	Crc                  *uint32  `protobuf:"fixed32,2,opt,name=crc" json:"crc,omitempty"` | ||||
| 	Offset               *uint64  `protobuf:"varint,3,opt,name=offset" json:"offset,omitempty"` | ||||
| 	CbOriginal           *uint32  `protobuf:"varint,4,opt,name=cb_original" json:"cb_original,omitempty"` | ||||
| 	CbCompressed         *uint32  `protobuf:"varint,5,opt,name=cb_compressed" json:"cb_compressed,omitempty"` | ||||
| 	CbOriginal           *uint32  `protobuf:"varint,4,opt,name=cb_original,json=cbOriginal" json:"cb_original,omitempty"` | ||||
| 	CbCompressed         *uint32  `protobuf:"varint,5,opt,name=cb_compressed,json=cbCompressed" json:"cb_compressed,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| @@ -222,15 +262,15 @@ func (m *ContentManifestPayload_FileMapping_ChunkData) GetCbCompressed() uint32 | ||||
| } | ||||
|  | ||||
| type ContentManifestMetadata struct { | ||||
| 	DepotId              *uint32  `protobuf:"varint,1,opt,name=depot_id" json:"depot_id,omitempty"` | ||||
| 	GidManifest          *uint64  `protobuf:"varint,2,opt,name=gid_manifest" json:"gid_manifest,omitempty"` | ||||
| 	CreationTime         *uint32  `protobuf:"varint,3,opt,name=creation_time" json:"creation_time,omitempty"` | ||||
| 	FilenamesEncrypted   *bool    `protobuf:"varint,4,opt,name=filenames_encrypted" json:"filenames_encrypted,omitempty"` | ||||
| 	CbDiskOriginal       *uint64  `protobuf:"varint,5,opt,name=cb_disk_original" json:"cb_disk_original,omitempty"` | ||||
| 	CbDiskCompressed     *uint64  `protobuf:"varint,6,opt,name=cb_disk_compressed" json:"cb_disk_compressed,omitempty"` | ||||
| 	UniqueChunks         *uint32  `protobuf:"varint,7,opt,name=unique_chunks" json:"unique_chunks,omitempty"` | ||||
| 	CrcEncrypted         *uint32  `protobuf:"varint,8,opt,name=crc_encrypted" json:"crc_encrypted,omitempty"` | ||||
| 	CrcClear             *uint32  `protobuf:"varint,9,opt,name=crc_clear" json:"crc_clear,omitempty"` | ||||
| 	DepotId              *uint32  `protobuf:"varint,1,opt,name=depot_id,json=depotId" json:"depot_id,omitempty"` | ||||
| 	GidManifest          *uint64  `protobuf:"varint,2,opt,name=gid_manifest,json=gidManifest" json:"gid_manifest,omitempty"` | ||||
| 	CreationTime         *uint32  `protobuf:"varint,3,opt,name=creation_time,json=creationTime" json:"creation_time,omitempty"` | ||||
| 	FilenamesEncrypted   *bool    `protobuf:"varint,4,opt,name=filenames_encrypted,json=filenamesEncrypted" json:"filenames_encrypted,omitempty"` | ||||
| 	CbDiskOriginal       *uint64  `protobuf:"varint,5,opt,name=cb_disk_original,json=cbDiskOriginal" json:"cb_disk_original,omitempty"` | ||||
| 	CbDiskCompressed     *uint64  `protobuf:"varint,6,opt,name=cb_disk_compressed,json=cbDiskCompressed" json:"cb_disk_compressed,omitempty"` | ||||
| 	UniqueChunks         *uint32  `protobuf:"varint,7,opt,name=unique_chunks,json=uniqueChunks" json:"unique_chunks,omitempty"` | ||||
| 	CrcEncrypted         *uint32  `protobuf:"varint,8,opt,name=crc_encrypted,json=crcEncrypted" json:"crc_encrypted,omitempty"` | ||||
| 	CrcClear             *uint32  `protobuf:"varint,9,opt,name=crc_clear,json=crcClear" json:"crc_clear,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| @@ -364,10 +404,11 @@ func (m *ContentManifestSignature) GetSignature() []byte { | ||||
| } | ||||
|  | ||||
| type ContentDeltaChunks struct { | ||||
| 	DepotId              *uint32                          `protobuf:"varint,1,opt,name=depot_id" json:"depot_id,omitempty"` | ||||
| 	ManifestIdSource     *uint64                          `protobuf:"varint,2,opt,name=manifest_id_source" json:"manifest_id_source,omitempty"` | ||||
| 	ManifestIdTarget     *uint64                          `protobuf:"varint,3,opt,name=manifest_id_target" json:"manifest_id_target,omitempty"` | ||||
| 	DepotId              *uint32                          `protobuf:"varint,1,opt,name=depot_id,json=depotId" json:"depot_id,omitempty"` | ||||
| 	ManifestIdSource     *uint64                          `protobuf:"varint,2,opt,name=manifest_id_source,json=manifestIdSource" json:"manifest_id_source,omitempty"` | ||||
| 	ManifestIdTarget     *uint64                          `protobuf:"varint,3,opt,name=manifest_id_target,json=manifestIdTarget" json:"manifest_id_target,omitempty"` | ||||
| 	DeltaChunks          []*ContentDeltaChunks_DeltaChunk `protobuf:"bytes,4,rep,name=deltaChunks" json:"deltaChunks,omitempty"` | ||||
| 	ChunkDataLocation    *EContentDeltaChunkDataLocation  `protobuf:"varint,5,opt,name=chunk_data_location,json=chunkDataLocation,enum=EContentDeltaChunkDataLocation,def=0" json:"chunk_data_location,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{}                         `json:"-"` | ||||
| 	XXX_unrecognized     []byte                           `json:"-"` | ||||
| 	XXX_sizecache        int32                            `json:"-"` | ||||
| @@ -398,6 +439,8 @@ func (m *ContentDeltaChunks) XXX_DiscardUnknown() { | ||||
|  | ||||
| var xxx_messageInfo_ContentDeltaChunks proto.InternalMessageInfo | ||||
|  | ||||
| const Default_ContentDeltaChunks_ChunkDataLocation EContentDeltaChunkDataLocation = EContentDeltaChunkDataLocation_k_EContentDeltaChunkDataLocationInProtobuf | ||||
|  | ||||
| func (m *ContentDeltaChunks) GetDepotId() uint32 { | ||||
| 	if m != nil && m.DepotId != nil { | ||||
| 		return *m.DepotId | ||||
| @@ -426,12 +469,20 @@ func (m *ContentDeltaChunks) GetDeltaChunks() []*ContentDeltaChunks_DeltaChunk { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (m *ContentDeltaChunks) GetChunkDataLocation() EContentDeltaChunkDataLocation { | ||||
| 	if m != nil && m.ChunkDataLocation != nil { | ||||
| 		return *m.ChunkDataLocation | ||||
| 	} | ||||
| 	return Default_ContentDeltaChunks_ChunkDataLocation | ||||
| } | ||||
|  | ||||
| type ContentDeltaChunks_DeltaChunk struct { | ||||
| 	ShaSource            []byte   `protobuf:"bytes,1,opt,name=sha_source" json:"sha_source,omitempty"` | ||||
| 	ShaTarget            []byte   `protobuf:"bytes,2,opt,name=sha_target" json:"sha_target,omitempty"` | ||||
| 	SizeOriginal         *uint32  `protobuf:"varint,3,opt,name=size_original" json:"size_original,omitempty"` | ||||
| 	PatchMethod          *uint32  `protobuf:"varint,4,opt,name=patch_method" json:"patch_method,omitempty"` | ||||
| 	ShaSource            []byte   `protobuf:"bytes,1,opt,name=sha_source,json=shaSource" json:"sha_source,omitempty"` | ||||
| 	ShaTarget            []byte   `protobuf:"bytes,2,opt,name=sha_target,json=shaTarget" json:"sha_target,omitempty"` | ||||
| 	SizeOriginal         *uint32  `protobuf:"varint,3,opt,name=size_original,json=sizeOriginal" json:"size_original,omitempty"` | ||||
| 	PatchMethod          *uint32  `protobuf:"varint,4,opt,name=patch_method,json=patchMethod" json:"patch_method,omitempty"` | ||||
| 	Chunk                []byte   `protobuf:"bytes,5,opt,name=chunk" json:"chunk,omitempty"` | ||||
| 	SizeDelta            *uint32  `protobuf:"varint,6,opt,name=size_delta,json=sizeDelta" json:"size_delta,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| @@ -497,7 +548,15 @@ func (m *ContentDeltaChunks_DeltaChunk) GetChunk() []byte { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (m *ContentDeltaChunks_DeltaChunk) GetSizeDelta() uint32 { | ||||
| 	if m != nil && m.SizeDelta != nil { | ||||
| 		return *m.SizeDelta | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	proto.RegisterEnum("EContentDeltaChunkDataLocation", EContentDeltaChunkDataLocation_name, EContentDeltaChunkDataLocation_value) | ||||
| 	proto.RegisterType((*ContentManifestPayload)(nil), "ContentManifestPayload") | ||||
| 	proto.RegisterType((*ContentManifestPayload_FileMapping)(nil), "ContentManifestPayload.FileMapping") | ||||
| 	proto.RegisterType((*ContentManifestPayload_FileMapping_ChunkData)(nil), "ContentManifestPayload.FileMapping.ChunkData") | ||||
| @@ -510,37 +569,52 @@ func init() { | ||||
| func init() { proto.RegisterFile("content_manifest.proto", fileDescriptor_e3cda137a29253ba) } | ||||
|  | ||||
| var fileDescriptor_e3cda137a29253ba = []byte{ | ||||
| 	// 508 bytes of a gzipped FileDescriptorProto | ||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xcd, 0x8e, 0xd3, 0x30, | ||||
| 	0x10, 0xc7, 0x49, 0xbf, 0x3b, 0x6d, 0x50, 0xf1, 0xb2, 0x8b, 0x55, 0x24, 0x54, 0x95, 0x4b, 0x2f, | ||||
| 	0x9b, 0x03, 0x88, 0x23, 0x17, 0x76, 0x85, 0xb8, 0x54, 0x42, 0xe2, 0x01, 0x2c, 0xd7, 0x76, 0x53, | ||||
| 	0xab, 0x89, 0x1d, 0x6c, 0xe7, 0xb0, 0x9c, 0xb8, 0xf0, 0x18, 0xbc, 0x21, 0x12, 0xaf, 0x80, 0xec, | ||||
| 	0x38, 0x4d, 0x55, 0xf6, 0xb0, 0xb7, 0xcc, 0x47, 0x3c, 0xbf, 0xf9, 0xcf, 0x1f, 0x6e, 0x98, 0x56, | ||||
| 	0x4e, 0x28, 0x47, 0x4a, 0xaa, 0xe4, 0x5e, 0x58, 0x97, 0x55, 0x46, 0x3b, 0xbd, 0xfe, 0xdb, 0x83, | ||||
| 	0x9b, 0xbb, 0xa6, 0xb4, 0x8d, 0x95, 0xaf, 0xf4, 0xa1, 0xd0, 0x94, 0xa3, 0x0f, 0x30, 0x29, 0x69, | ||||
| 	0x55, 0x49, 0x95, 0x5b, 0x9c, 0xac, 0xfa, 0x9b, 0xd9, 0xbb, 0xb7, 0xd9, 0xe3, 0xad, 0xd9, 0x67, | ||||
| 	0x59, 0x88, 0x6d, 0xd3, 0xbb, 0xfc, 0xdd, 0x83, 0xd9, 0x59, 0x8c, 0x16, 0x30, 0xd9, 0xcb, 0x42, | ||||
| 	0x28, 0x5a, 0x0a, 0x9c, 0xac, 0x92, 0xcd, 0x14, 0xcd, 0x61, 0x60, 0xe5, 0x0f, 0x81, 0x7b, 0xab, | ||||
| 	0x64, 0x33, 0x40, 0x29, 0x0c, 0xf7, 0x05, 0xcd, 0x2d, 0xee, 0xaf, 0x92, 0x4d, 0x8a, 0x5e, 0xc2, | ||||
| 	0xdc, 0x1e, 0x28, 0x39, 0xfd, 0x32, 0x58, 0x25, 0x9b, 0x39, 0xba, 0x82, 0x99, 0xcf, 0xc6, 0x25, | ||||
| 	0xf0, 0x30, 0x24, 0x3f, 0xc2, 0x88, 0x1d, 0x6a, 0x75, 0xb4, 0x78, 0x14, 0xf0, 0x6e, 0x9f, 0x80, | ||||
| 	0x97, 0xdd, 0xf9, 0x3f, 0xee, 0xa9, 0xa3, 0x08, 0x01, 0x14, 0x52, 0x1d, 0x1d, 0x35, 0xb9, 0x70, | ||||
| 	0x78, 0xec, 0xd1, 0x96, 0x14, 0xa6, 0x5d, 0xc3, 0x0c, 0xfa, 0xf6, 0x40, 0x03, 0xf4, 0xdc, 0x07, | ||||
| 	0xcc, 0xb0, 0xc0, 0x3c, 0x46, 0xcf, 0x61, 0xa4, 0xf7, 0x7b, 0x2b, 0x5c, 0x80, 0x1e, 0x78, 0x3c, | ||||
| 	0xb6, 0x23, 0xda, 0xc8, 0x5c, 0x2a, 0x5a, 0x04, 0xe6, 0x14, 0x5d, 0x43, 0xca, 0x76, 0x84, 0xe9, | ||||
| 	0xb2, 0x32, 0xc2, 0x5a, 0xc1, 0x03, 0x75, 0xba, 0xfe, 0x93, 0xc0, 0xab, 0x0b, 0xce, 0xad, 0x70, | ||||
| 	0x94, 0xfb, 0x89, 0x0b, 0x98, 0x70, 0x51, 0x69, 0x47, 0x24, 0x0f, 0x63, 0x83, 0x1c, 0xb9, 0xe4, | ||||
| 	0xa7, 0xab, 0x45, 0xcd, 0xfc, 0xd3, 0x46, 0x50, 0x27, 0xb5, 0x22, 0x4e, 0x96, 0x22, 0x6a, 0xf7, | ||||
| 	0x1a, 0xae, 0x5a, 0xdd, 0x2c, 0x11, 0x8a, 0x99, 0x87, 0xca, 0x09, 0x1e, 0x70, 0x26, 0x08, 0xc3, | ||||
| 	0x82, 0xed, 0x08, 0x97, 0xf6, 0xd8, 0x81, 0x0e, 0xc3, 0x6b, 0x4b, 0x40, 0x6d, 0xe5, 0x8c, 0x76, | ||||
| 	0xd4, 0x4e, 0xaa, 0x95, 0xfc, 0x5e, 0x0b, 0x12, 0xa5, 0x1e, 0x9f, 0x76, 0x33, 0xec, 0x6c, 0xc6, | ||||
| 	0x24, 0xa4, 0x5f, 0xc0, 0xd4, 0xa7, 0x59, 0x21, 0xa8, 0xc1, 0xd3, 0xb0, 0xee, 0x2d, 0xe0, 0x8b, | ||||
| 	0x6d, 0xbf, 0xc9, 0x5c, 0x51, 0x57, 0x1b, 0xe1, 0xdb, 0x6d, 0x1b, 0x34, 0x32, 0xaf, 0x7f, 0xf5, | ||||
| 	0x00, 0xc5, 0xfe, 0x7b, 0x51, 0x38, 0x1a, 0xae, 0x61, 0x1f, 0x11, 0x66, 0x09, 0xa8, 0x15, 0x85, | ||||
| 	0x48, 0x4e, 0xac, 0xae, 0x0d, 0x6b, 0x2d, 0x75, 0x51, 0x8b, 0x17, 0x6e, 0x4e, 0xf5, 0x1e, 0x66, | ||||
| 	0xbc, 0x7b, 0x18, 0x0f, 0x82, 0x73, 0xde, 0x64, 0xff, 0xcf, 0xcc, 0xba, 0xef, 0x65, 0x05, 0xd0, | ||||
| 	0x45, 0xde, 0x38, 0xde, 0x8c, 0x71, 0x64, 0x63, 0x8f, 0x98, 0x8b, 0xa3, 0x7a, 0x21, 0x77, 0x0d, | ||||
| 	0xa9, 0xf7, 0x79, 0x27, 0xf7, 0xc9, 0xe1, 0x15, 0x75, 0xec, 0x40, 0x4a, 0xe1, 0x0e, 0x9a, 0x47, | ||||
| 	0xb7, 0xa4, 0x30, 0x0c, 0x0a, 0x37, 0xde, 0xfe, 0x34, 0xfc, 0x92, 0xfc, 0x4c, 0x9e, 0xfd, 0x0b, | ||||
| 	0x00, 0x00, 0xff, 0xff, 0x00, 0x92, 0x22, 0xd7, 0xb7, 0x03, 0x00, 0x00, | ||||
| 	// 742 bytes of a gzipped FileDescriptorProto | ||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x4f, 0x6f, 0xd3, 0x4e, | ||||
| 	0x10, 0xad, 0x9b, 0xff, 0x93, 0xa4, 0xca, 0x6f, 0xfb, 0x53, 0x31, 0x01, 0xda, 0x34, 0xbd, 0x44, | ||||
| 	0x55, 0x6b, 0x44, 0x4f, 0x88, 0x0b, 0x7f, 0xd2, 0x56, 0x54, 0x22, 0xa2, 0xda, 0xf6, 0xbe, 0xda, | ||||
| 	0xac, 0x37, 0xf1, 0x2a, 0x8e, 0x1d, 0xbc, 0x9b, 0x43, 0xcb, 0x05, 0x89, 0x33, 0x9c, 0xf8, 0x4e, | ||||
| 	0x7c, 0x17, 0xc4, 0x87, 0x40, 0xbb, 0x5e, 0xdb, 0x51, 0x8a, 0x0a, 0xdc, 0x3c, 0x33, 0x6f, 0xd6, | ||||
| 	0xef, 0xbd, 0x99, 0x5d, 0xd8, 0x61, 0x71, 0xa4, 0x78, 0xa4, 0xc8, 0x9c, 0x46, 0x62, 0xc2, 0xa5, | ||||
| 	0xf2, 0x16, 0x49, 0xac, 0xe2, 0xfe, 0x8f, 0x12, 0xec, 0x0c, 0xd3, 0xd2, 0xc8, 0x56, 0x2e, 0xe9, | ||||
| 	0x4d, 0x18, 0x53, 0x1f, 0xbd, 0x84, 0xfa, 0x9c, 0x2e, 0x16, 0x22, 0x9a, 0x4a, 0xd7, 0xe9, 0x95, | ||||
| 	0x06, 0xcd, 0x93, 0x03, 0xef, 0xf7, 0x50, 0xef, 0x5c, 0x84, 0x7c, 0x94, 0x62, 0x71, 0xde, 0xd4, | ||||
| 	0xfd, 0x5a, 0x82, 0xe6, 0x4a, 0x05, 0x75, 0xa1, 0x3e, 0x11, 0x21, 0x8f, 0xe8, 0x9c, 0xbb, 0x4e, | ||||
| 	0xcf, 0x19, 0x34, 0x70, 0x1e, 0x23, 0x04, 0x65, 0x29, 0x6e, 0xb9, 0xbb, 0xd9, 0x73, 0x06, 0x65, | ||||
| 	0x6c, 0xbe, 0xd1, 0xff, 0x50, 0x99, 0x84, 0x74, 0x2a, 0xdd, 0x52, 0xcf, 0x19, 0xb4, 0x71, 0x1a, | ||||
| 	0xa0, 0x7d, 0x68, 0xc9, 0x80, 0x92, 0xfc, 0xa4, 0x72, 0xcf, 0x19, 0xb4, 0x70, 0x53, 0x06, 0xf4, | ||||
| 	0x3c, 0x3b, 0x6c, 0x0f, 0x74, 0x48, 0xac, 0x64, 0xb7, 0x62, 0x10, 0x20, 0x03, 0x6a, 0xe9, 0xa3, | ||||
| 	0x33, 0xa8, 0xb2, 0x60, 0x19, 0xcd, 0xa4, 0x5b, 0x35, 0xc2, 0x8e, 0xff, 0x42, 0x98, 0x37, 0xd4, | ||||
| 	0x1d, 0xa7, 0x54, 0x51, 0x6c, 0x9b, 0xd1, 0x2e, 0x40, 0x28, 0xa2, 0x99, 0xa2, 0xc9, 0x94, 0x2b, | ||||
| 	0xb7, 0x66, 0x24, 0xad, 0x64, 0xba, 0x5f, 0x1c, 0x68, 0xe4, 0x5d, 0xa8, 0x03, 0x25, 0x19, 0x50, | ||||
| 	0xa3, 0xbc, 0x85, 0xf5, 0xa7, 0xce, 0xb0, 0x84, 0x19, 0xcd, 0x35, 0xac, 0x3f, 0xd1, 0x0e, 0x54, | ||||
| 	0xe3, 0xc9, 0x44, 0x72, 0x65, 0x34, 0x97, 0xb1, 0x8d, 0xb4, 0x22, 0x36, 0x26, 0x71, 0x22, 0xa6, | ||||
| 	0x22, 0xa2, 0xa1, 0xd1, 0xdc, 0xc6, 0xc0, 0xc6, 0xef, 0x6d, 0x06, 0x1d, 0x40, 0x9b, 0x8d, 0x09, | ||||
| 	0x8b, 0xe7, 0x8b, 0x84, 0x4b, 0xc9, 0x7d, 0x23, 0xba, 0x8d, 0x5b, 0x6c, 0x3c, 0xcc, 0x73, 0xfd, | ||||
| 	0x9f, 0x9b, 0xf0, 0x60, 0x4d, 0xe8, 0x88, 0x2b, 0xea, 0x6b, 0x76, 0x0f, 0xa1, 0xee, 0xf3, 0x45, | ||||
| 	0xac, 0x88, 0xf0, 0x0d, 0xc5, 0x36, 0xae, 0x99, 0xf8, 0xc2, 0xd7, 0x8e, 0x4f, 0x85, 0x9f, 0x6f, | ||||
| 	0x8e, 0x9d, 0x51, 0x73, 0x2a, 0xfc, 0xec, 0x14, 0xf3, 0xfb, 0x84, 0x53, 0x25, 0xe2, 0x88, 0x28, | ||||
| 	0x31, 0xe7, 0x76, 0x64, 0xad, 0x2c, 0x79, 0x2d, 0xe6, 0x1c, 0x3d, 0x85, 0xed, 0x6c, 0x6a, 0x92, | ||||
| 	0xf0, 0x88, 0x25, 0x37, 0x0b, 0xc5, 0x7d, 0x23, 0xa6, 0x8e, 0x51, 0x5e, 0x3a, 0xcb, 0x2a, 0x68, | ||||
| 	0x00, 0x1d, 0x36, 0x26, 0xbe, 0x90, 0xb3, 0x42, 0x7a, 0xc5, 0xfc, 0x7c, 0x8b, 0x8d, 0x4f, 0x85, | ||||
| 	0x9c, 0xe5, 0xf2, 0x8f, 0x00, 0x65, 0xc8, 0x15, 0x0f, 0xaa, 0x06, 0xdb, 0x49, 0xb1, 0x85, 0x0f, | ||||
| 	0x9a, 0xed, 0x32, 0x12, 0x1f, 0x96, 0x9c, 0xd8, 0x2d, 0xa8, 0xa5, 0x6c, 0xd3, 0xe4, 0x30, 0x1d, | ||||
| 	0xae, 0x91, 0xc4, 0x56, 0x78, 0xd6, 0x33, 0x49, 0xac, 0x60, 0xf8, 0x08, 0x1a, 0x1a, 0xc4, 0x42, | ||||
| 	0x4e, 0x13, 0xb7, 0x61, 0x00, 0x75, 0x96, 0xb0, 0xa1, 0x8e, 0xfb, 0xcf, 0xc1, 0x5d, 0x73, 0xfb, | ||||
| 	0x4a, 0x4c, 0x23, 0xaa, 0x96, 0x09, 0x47, 0x8f, 0xa1, 0x21, 0xb3, 0xc0, 0xae, 0x44, 0x91, 0xe8, | ||||
| 	0x7f, 0x2b, 0x03, 0xb2, 0xad, 0xa7, 0x3c, 0x54, 0xd4, 0x52, 0xba, 0x67, 0x46, 0x47, 0x80, 0xb2, | ||||
| 	0xf9, 0x10, 0xe1, 0x13, 0x19, 0x2f, 0x13, 0x96, 0xdd, 0xa6, 0x4e, 0x56, 0xb9, 0xf0, 0xaf, 0x4c, | ||||
| 	0x7e, 0x1d, 0x6d, 0x17, 0xb8, 0xb4, 0x8e, 0xbe, 0x36, 0x79, 0xf4, 0x0a, 0x9a, 0x7e, 0xc1, 0xc2, | ||||
| 	0x2d, 0x9b, 0x2b, 0xb3, 0xeb, 0xdd, 0x25, 0xe8, 0x15, 0xdf, 0x78, 0xb5, 0x05, 0x7d, 0x84, 0x6d, | ||||
| 	0xe3, 0x34, 0xd1, 0xab, 0x46, 0xc2, 0x98, 0x99, 0xa5, 0x30, 0xb3, 0xdc, 0x3a, 0xd9, 0xf3, 0xce, | ||||
| 	0xee, 0x1c, 0xa5, 0x2f, 0xcc, 0x3b, 0x0b, 0x7b, 0x71, 0x38, 0x23, 0xf7, 0x23, 0x2e, 0xa2, 0x4b, | ||||
| 	0xfd, 0x98, 0x8d, 0x97, 0x13, 0xfc, 0x1f, 0x5b, 0x2f, 0x76, 0xbf, 0x3b, 0x00, 0x45, 0x1f, 0x7a, | ||||
| 	0x02, 0xfa, 0x25, 0xc8, 0x1c, 0xca, 0xac, 0x0f, 0xa8, 0xb5, 0xc6, 0x96, 0xad, 0x25, 0x9b, 0x79, | ||||
| 	0xd9, 0x7a, 0x71, 0x00, 0x6d, 0xfd, 0x36, 0x15, 0xfb, 0x68, 0x17, 0x5d, 0x27, 0xf3, 0x6d, 0xdc, | ||||
| 	0x87, 0xd6, 0x82, 0x2a, 0x16, 0x90, 0x39, 0x57, 0x41, 0xec, 0xdb, 0xeb, 0xda, 0x34, 0xb9, 0x91, | ||||
| 	0x49, 0xe9, 0xb7, 0xcd, 0x30, 0xb5, 0x8f, 0x53, 0x1a, 0x98, 0x9f, 0xeb, 0xd3, 0x8d, 0x77, 0x66, | ||||
| 	0x7d, 0xdb, 0x7a, 0x2d, 0x6e, 0xb9, 0xe1, 0x7f, 0xf8, 0xd9, 0x81, 0xdd, 0xfb, 0x9d, 0x40, 0x1e, | ||||
| 	0xfc, 0x83, 0x5b, 0x9d, 0x0d, 0xf4, 0x0c, 0x8e, 0xff, 0x84, 0x7f, 0x3d, 0x51, 0x3c, 0xc9, 0x5b, | ||||
| 	0x9c, 0x37, 0x95, 0xb7, 0xce, 0x27, 0x67, 0xe3, 0x57, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa3, 0x9c, | ||||
| 	0xf1, 0x49, 0x52, 0x06, 0x00, 0x00, | ||||
| } | ||||
|   | ||||
							
								
								
									
										669
									
								
								vendor/github.com/Philipp15b/go-steam/protocol/steamlang/enums.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										669
									
								
								vendor/github.com/Philipp15b/go-steam/protocol/steamlang/enums.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -400,6 +400,7 @@ const ( | ||||
| 	EMsg_FBSBootstrapperGetPackageChunkResponse                   EMsg = 1131 | ||||
| 	EMsg_FBSBootstrapperPackageTransferProgress                   EMsg = 1132 | ||||
| 	EMsg_FBSRestartBootstrapper                                   EMsg = 1133 | ||||
| 	EMsg_FBSPauseFrozenDumps                                      EMsg = 1134 | ||||
| 	EMsg_BaseFileXfer                                             EMsg = 1200 | ||||
| 	EMsg_FileXferRequest                                          EMsg = 1200 | ||||
| 	EMsg_FileXferResponse                                         EMsg = 1201 | ||||
| @@ -416,6 +417,8 @@ const ( | ||||
| 	EMsg_BaseBS                                                   EMsg = 1400 | ||||
| 	EMsg_BSPurchaseStart                                          EMsg = 1401 | ||||
| 	EMsg_BSPurchaseResponse                                       EMsg = 1402 | ||||
| 	EMsg_BSAuthenticateCCTrans                                    EMsg = 1403 | ||||
| 	EMsg_BSAuthenticateCCTransResponse                            EMsg = 1404 | ||||
| 	EMsg_BSSettleComplete                                         EMsg = 1406 | ||||
| 	EMsg_BSInitPayPalTxn                                          EMsg = 1408 | ||||
| 	EMsg_BSInitPayPalTxnResponse                                  EMsg = 1409 | ||||
| @@ -979,6 +982,8 @@ const ( | ||||
| 	EMsg_AMFundedPayment                                          EMsg = 4418 | ||||
| 	EMsg_AMFundedPaymentResponse                                  EMsg = 4419 | ||||
| 	EMsg_AMRequestPersonaUpdateForChatServer                      EMsg = 4420 | ||||
| 	EMsg_AMPerfectWorldPayment                                    EMsg = 4421 | ||||
| 	EMsg_AMPerfectWorldPaymentResponse                            EMsg = 4422 | ||||
| 	EMsg_BasePSRange                                              EMsg = 5000 | ||||
| 	EMsg_PSCreateShoppingCart                                     EMsg = 5001 | ||||
| 	EMsg_PSCreateShoppingCartResponse                             EMsg = 5002 | ||||
| @@ -1238,6 +1243,9 @@ const ( | ||||
| 	EMsg_ClientNetworkingCertRequestResponse                      EMsg = 5622 | ||||
| 	EMsg_ClientChallengeRequest                                   EMsg = 5623 | ||||
| 	EMsg_ClientChallengeResponse                                  EMsg = 5624 | ||||
| 	EMsg_BadgeCraftedNotification                                 EMsg = 5625 | ||||
| 	EMsg_ClientNetworkingMobileCertRequest                        EMsg = 5626 | ||||
| 	EMsg_ClientNetworkingMobileCertRequestResponse                EMsg = 5627 | ||||
| 	EMsg_BaseMDS                                                  EMsg = 5800 | ||||
| 	EMsg_AMToMDSGetDepotDecryptionKey                             EMsg = 5812 | ||||
| 	EMsg_MDSToAMGetDepotDecryptionKeyResponse                     EMsg = 5813 | ||||
| @@ -1303,6 +1311,8 @@ const ( | ||||
| 	EMsg_ClientMMSSetRatelimitPolicyOnClient                      EMsg = 6625 | ||||
| 	EMsg_ClientMMSGetLobbyStatus                                  EMsg = 6626 | ||||
| 	EMsg_ClientMMSGetLobbyStatusResponse                          EMsg = 6627 | ||||
| 	EMsg_MMSGetLobbyList                                          EMsg = 6628 | ||||
| 	EMsg_MMSGetLobbyListResponse                                  EMsg = 6629 | ||||
| 	EMsg_NonStdMsgBase                                            EMsg = 6800 | ||||
| 	EMsg_NonStdMsgMemcached                                       EMsg = 6801 | ||||
| 	EMsg_NonStdMsgHTTPServer                                      EMsg = 6802 | ||||
| @@ -1318,6 +1328,7 @@ const ( | ||||
| 	EMsg_NonStdMsgSteam2Emulator                                  EMsg = 6812 | ||||
| 	EMsg_NonStdMsgRTMPServer                                      EMsg = 6813 | ||||
| 	EMsg_NonStdMsgWebSocket                                       EMsg = 6814 | ||||
| 	EMsg_NonStdMsgRedis                                           EMsg = 6815 | ||||
| 	EMsg_UDSBase                                                  EMsg = 7000 | ||||
| 	EMsg_ClientUDSP2PSessionStarted                               EMsg = 7001 | ||||
| 	EMsg_ClientUDSP2PSessionEnded                                 EMsg = 7002 | ||||
| @@ -2072,6 +2083,7 @@ var EMsg_name = map[EMsg]string{ | ||||
| 	1131:  "EMsg_FBSBootstrapperGetPackageChunkResponse", | ||||
| 	1132:  "EMsg_FBSBootstrapperPackageTransferProgress", | ||||
| 	1133:  "EMsg_FBSRestartBootstrapper", | ||||
| 	1134:  "EMsg_FBSPauseFrozenDumps", | ||||
| 	1200:  "EMsg_BaseFileXfer", | ||||
| 	1201:  "EMsg_FileXferResponse", | ||||
| 	1202:  "EMsg_FileXferData", | ||||
| @@ -2086,7 +2098,8 @@ var EMsg_name = map[EMsg]string{ | ||||
| 	1400:  "EMsg_BaseBS", | ||||
| 	1401:  "EMsg_BSPurchaseStart", | ||||
| 	1402:  "EMsg_BSPurchaseResponse", | ||||
| 	1404:  "EMsg_BSSettleNOVA", | ||||
| 	1403:  "EMsg_BSAuthenticateCCTrans", | ||||
| 	1404:  "EMsg_BSAuthenticateCCTransResponse", | ||||
| 	1406:  "EMsg_BSSettleComplete", | ||||
| 	1407:  "EMsg_BSBannedRequest", | ||||
| 	1408:  "EMsg_BSInitPayPalTxn", | ||||
| @@ -2772,6 +2785,8 @@ var EMsg_name = map[EMsg]string{ | ||||
| 	4418:  "EMsg_AMFundedPayment", | ||||
| 	4419:  "EMsg_AMFundedPaymentResponse", | ||||
| 	4420:  "EMsg_AMRequestPersonaUpdateForChatServer", | ||||
| 	4421:  "EMsg_AMPerfectWorldPayment", | ||||
| 	4422:  "EMsg_AMPerfectWorldPaymentResponse", | ||||
| 	5000:  "EMsg_BasePSRange", | ||||
| 	5001:  "EMsg_PSCreateShoppingCart", | ||||
| 	5002:  "EMsg_PSCreateShoppingCartResponse", | ||||
| @@ -3041,6 +3056,9 @@ var EMsg_name = map[EMsg]string{ | ||||
| 	5622:  "EMsg_ClientNetworkingCertRequestResponse", | ||||
| 	5623:  "EMsg_ClientChallengeRequest", | ||||
| 	5624:  "EMsg_ClientChallengeResponse", | ||||
| 	5625:  "EMsg_BadgeCraftedNotification", | ||||
| 	5626:  "EMsg_ClientNetworkingMobileCertRequest", | ||||
| 	5627:  "EMsg_ClientNetworkingMobileCertRequestResponse", | ||||
| 	5800:  "EMsg_BaseMDS", | ||||
| 	5801:  "EMsg_ClientMDSLoginRequest", | ||||
| 	5802:  "EMsg_ClientMDSLoginResponse", | ||||
| @@ -3136,6 +3154,8 @@ var EMsg_name = map[EMsg]string{ | ||||
| 	6625:  "EMsg_ClientMMSSetRatelimitPolicyOnClient", | ||||
| 	6626:  "EMsg_ClientMMSGetLobbyStatus", | ||||
| 	6627:  "EMsg_ClientMMSGetLobbyStatusResponse", | ||||
| 	6628:  "EMsg_MMSGetLobbyList", | ||||
| 	6629:  "EMsg_MMSGetLobbyListResponse", | ||||
| 	6800:  "EMsg_NonStdMsgBase", | ||||
| 	6801:  "EMsg_NonStdMsgMemcached", | ||||
| 	6802:  "EMsg_NonStdMsgHTTPServer", | ||||
| @@ -3151,6 +3171,7 @@ var EMsg_name = map[EMsg]string{ | ||||
| 	6812:  "EMsg_NonStdMsgSteam2Emulator", | ||||
| 	6813:  "EMsg_NonStdMsgRTMPServer", | ||||
| 	6814:  "EMsg_NonStdMsgWebSocket", | ||||
| 	6815:  "EMsg_NonStdMsgRedis", | ||||
| 	7000:  "EMsg_UDSBase", | ||||
| 	7001:  "EMsg_ClientUDSP2PSessionStarted", | ||||
| 	7002:  "EMsg_ClientUDSP2PSessionEnded", | ||||
| @@ -3487,119 +3508,122 @@ func (e EMsg) String() string { | ||||
| type EResult int32 | ||||
|  | ||||
| const ( | ||||
| 	EResult_Invalid                                 EResult = 0 | ||||
| 	EResult_OK                                      EResult = 1 | ||||
| 	EResult_Fail                                    EResult = 2 | ||||
| 	EResult_NoConnection                            EResult = 3 | ||||
| 	EResult_InvalidPassword                         EResult = 5 | ||||
| 	EResult_LoggedInElsewhere                       EResult = 6 | ||||
| 	EResult_InvalidProtocolVer                      EResult = 7 | ||||
| 	EResult_InvalidParam                            EResult = 8 | ||||
| 	EResult_FileNotFound                            EResult = 9 | ||||
| 	EResult_Busy                                    EResult = 10 | ||||
| 	EResult_InvalidState                            EResult = 11 | ||||
| 	EResult_InvalidName                             EResult = 12 | ||||
| 	EResult_InvalidEmail                            EResult = 13 | ||||
| 	EResult_DuplicateName                           EResult = 14 | ||||
| 	EResult_AccessDenied                            EResult = 15 | ||||
| 	EResult_Timeout                                 EResult = 16 | ||||
| 	EResult_Banned                                  EResult = 17 | ||||
| 	EResult_AccountNotFound                         EResult = 18 | ||||
| 	EResult_InvalidSteamID                          EResult = 19 | ||||
| 	EResult_ServiceUnavailable                      EResult = 20 | ||||
| 	EResult_NotLoggedOn                             EResult = 21 | ||||
| 	EResult_Pending                                 EResult = 22 | ||||
| 	EResult_EncryptionFailure                       EResult = 23 | ||||
| 	EResult_InsufficientPrivilege                   EResult = 24 | ||||
| 	EResult_LimitExceeded                           EResult = 25 | ||||
| 	EResult_Revoked                                 EResult = 26 | ||||
| 	EResult_Expired                                 EResult = 27 | ||||
| 	EResult_AlreadyRedeemed                         EResult = 28 | ||||
| 	EResult_DuplicateRequest                        EResult = 29 | ||||
| 	EResult_AlreadyOwned                            EResult = 30 | ||||
| 	EResult_IPNotFound                              EResult = 31 | ||||
| 	EResult_PersistFailed                           EResult = 32 | ||||
| 	EResult_LockingFailed                           EResult = 33 | ||||
| 	EResult_LogonSessionReplaced                    EResult = 34 | ||||
| 	EResult_ConnectFailed                           EResult = 35 | ||||
| 	EResult_HandshakeFailed                         EResult = 36 | ||||
| 	EResult_IOFailure                               EResult = 37 | ||||
| 	EResult_RemoteDisconnect                        EResult = 38 | ||||
| 	EResult_ShoppingCartNotFound                    EResult = 39 | ||||
| 	EResult_Blocked                                 EResult = 40 | ||||
| 	EResult_Ignored                                 EResult = 41 | ||||
| 	EResult_NoMatch                                 EResult = 42 | ||||
| 	EResult_AccountDisabled                         EResult = 43 | ||||
| 	EResult_ServiceReadOnly                         EResult = 44 | ||||
| 	EResult_AccountNotFeatured                      EResult = 45 | ||||
| 	EResult_AdministratorOK                         EResult = 46 | ||||
| 	EResult_ContentVersion                          EResult = 47 | ||||
| 	EResult_TryAnotherCM                            EResult = 48 | ||||
| 	EResult_PasswordRequiredToKickSession           EResult = 49 | ||||
| 	EResult_AlreadyLoggedInElsewhere                EResult = 50 | ||||
| 	EResult_Suspended                               EResult = 51 | ||||
| 	EResult_Cancelled                               EResult = 52 | ||||
| 	EResult_DataCorruption                          EResult = 53 | ||||
| 	EResult_DiskFull                                EResult = 54 | ||||
| 	EResult_RemoteCallFailed                        EResult = 55 | ||||
| 	EResult_PasswordUnset                           EResult = 56 | ||||
| 	EResult_ExternalAccountUnlinked                 EResult = 57 | ||||
| 	EResult_PSNTicketInvalid                        EResult = 58 | ||||
| 	EResult_ExternalAccountAlreadyLinked            EResult = 59 | ||||
| 	EResult_RemoteFileConflict                      EResult = 60 | ||||
| 	EResult_IllegalPassword                         EResult = 61 | ||||
| 	EResult_SameAsPreviousValue                     EResult = 62 | ||||
| 	EResult_AccountLogonDenied                      EResult = 63 | ||||
| 	EResult_CannotUseOldPassword                    EResult = 64 | ||||
| 	EResult_InvalidLoginAuthCode                    EResult = 65 | ||||
| 	EResult_AccountLogonDeniedNoMail                EResult = 66 | ||||
| 	EResult_HardwareNotCapableOfIPT                 EResult = 67 | ||||
| 	EResult_IPTInitError                            EResult = 68 | ||||
| 	EResult_ParentalControlRestricted               EResult = 69 | ||||
| 	EResult_FacebookQueryError                      EResult = 70 | ||||
| 	EResult_ExpiredLoginAuthCode                    EResult = 71 | ||||
| 	EResult_IPLoginRestrictionFailed                EResult = 72 | ||||
| 	EResult_AccountLockedDown                       EResult = 73 | ||||
| 	EResult_AccountLogonDeniedVerifiedEmailRequired EResult = 74 | ||||
| 	EResult_NoMatchingURL                           EResult = 75 | ||||
| 	EResult_BadResponse                             EResult = 76 | ||||
| 	EResult_RequirePasswordReEntry                  EResult = 77 | ||||
| 	EResult_ValueOutOfRange                         EResult = 78 | ||||
| 	EResult_UnexpectedError                         EResult = 79 | ||||
| 	EResult_Disabled                                EResult = 80 | ||||
| 	EResult_InvalidCEGSubmission                    EResult = 81 | ||||
| 	EResult_RestrictedDevice                        EResult = 82 | ||||
| 	EResult_RegionLocked                            EResult = 83 | ||||
| 	EResult_RateLimitExceeded                       EResult = 84 | ||||
| 	EResult_AccountLoginDeniedNeedTwoFactor         EResult = 85 | ||||
| 	EResult_ItemDeleted                             EResult = 86 | ||||
| 	EResult_AccountLoginDeniedThrottle              EResult = 87 | ||||
| 	EResult_TwoFactorCodeMismatch                   EResult = 88 | ||||
| 	EResult_TwoFactorActivationCodeMismatch         EResult = 89 | ||||
| 	EResult_AccountAssociatedToMultiplePartners     EResult = 90 | ||||
| 	EResult_NotModified                             EResult = 91 | ||||
| 	EResult_NoMobileDevice                          EResult = 92 | ||||
| 	EResult_TimeNotSynced                           EResult = 93 | ||||
| 	EResult_SMSCodeFailed                           EResult = 94 | ||||
| 	EResult_AccountLimitExceeded                    EResult = 95 | ||||
| 	EResult_AccountActivityLimitExceeded            EResult = 96 | ||||
| 	EResult_PhoneActivityLimitExceeded              EResult = 97 | ||||
| 	EResult_RefundToWallet                          EResult = 98 | ||||
| 	EResult_EmailSendFailure                        EResult = 99 | ||||
| 	EResult_NotSettled                              EResult = 100 | ||||
| 	EResult_NeedCaptcha                             EResult = 101 | ||||
| 	EResult_GSLTDenied                              EResult = 102 | ||||
| 	EResult_GSOwnerDenied                           EResult = 103 | ||||
| 	EResult_InvalidItemType                         EResult = 104 | ||||
| 	EResult_IPBanned                                EResult = 105 | ||||
| 	EResult_GSLTExpired                             EResult = 106 | ||||
| 	EResult_InsufficientFunds                       EResult = 107 | ||||
| 	EResult_TooManyPending                          EResult = 108 | ||||
| 	EResult_NoSiteLicensesFound                     EResult = 109 | ||||
| 	EResult_WGNetworkSendExceeded                   EResult = 110 | ||||
| 	EResult_AccountNotFriends                       EResult = 111 | ||||
| 	EResult_LimitedUserAccount                      EResult = 112 | ||||
| 	EResult_CantRemoveItem                          EResult = 113 | ||||
| 	EResult_Invalid                                  EResult = 0 | ||||
| 	EResult_OK                                       EResult = 1 | ||||
| 	EResult_Fail                                     EResult = 2 | ||||
| 	EResult_NoConnection                             EResult = 3 | ||||
| 	EResult_InvalidPassword                          EResult = 5 | ||||
| 	EResult_LoggedInElsewhere                        EResult = 6 | ||||
| 	EResult_InvalidProtocolVer                       EResult = 7 | ||||
| 	EResult_InvalidParam                             EResult = 8 | ||||
| 	EResult_FileNotFound                             EResult = 9 | ||||
| 	EResult_Busy                                     EResult = 10 | ||||
| 	EResult_InvalidState                             EResult = 11 | ||||
| 	EResult_InvalidName                              EResult = 12 | ||||
| 	EResult_InvalidEmail                             EResult = 13 | ||||
| 	EResult_DuplicateName                            EResult = 14 | ||||
| 	EResult_AccessDenied                             EResult = 15 | ||||
| 	EResult_Timeout                                  EResult = 16 | ||||
| 	EResult_Banned                                   EResult = 17 | ||||
| 	EResult_AccountNotFound                          EResult = 18 | ||||
| 	EResult_InvalidSteamID                           EResult = 19 | ||||
| 	EResult_ServiceUnavailable                       EResult = 20 | ||||
| 	EResult_NotLoggedOn                              EResult = 21 | ||||
| 	EResult_Pending                                  EResult = 22 | ||||
| 	EResult_EncryptionFailure                        EResult = 23 | ||||
| 	EResult_InsufficientPrivilege                    EResult = 24 | ||||
| 	EResult_LimitExceeded                            EResult = 25 | ||||
| 	EResult_Revoked                                  EResult = 26 | ||||
| 	EResult_Expired                                  EResult = 27 | ||||
| 	EResult_AlreadyRedeemed                          EResult = 28 | ||||
| 	EResult_DuplicateRequest                         EResult = 29 | ||||
| 	EResult_AlreadyOwned                             EResult = 30 | ||||
| 	EResult_IPNotFound                               EResult = 31 | ||||
| 	EResult_PersistFailed                            EResult = 32 | ||||
| 	EResult_LockingFailed                            EResult = 33 | ||||
| 	EResult_LogonSessionReplaced                     EResult = 34 | ||||
| 	EResult_ConnectFailed                            EResult = 35 | ||||
| 	EResult_HandshakeFailed                          EResult = 36 | ||||
| 	EResult_IOFailure                                EResult = 37 | ||||
| 	EResult_RemoteDisconnect                         EResult = 38 | ||||
| 	EResult_ShoppingCartNotFound                     EResult = 39 | ||||
| 	EResult_Blocked                                  EResult = 40 | ||||
| 	EResult_Ignored                                  EResult = 41 | ||||
| 	EResult_NoMatch                                  EResult = 42 | ||||
| 	EResult_AccountDisabled                          EResult = 43 | ||||
| 	EResult_ServiceReadOnly                          EResult = 44 | ||||
| 	EResult_AccountNotFeatured                       EResult = 45 | ||||
| 	EResult_AdministratorOK                          EResult = 46 | ||||
| 	EResult_ContentVersion                           EResult = 47 | ||||
| 	EResult_TryAnotherCM                             EResult = 48 | ||||
| 	EResult_PasswordRequiredToKickSession            EResult = 49 | ||||
| 	EResult_AlreadyLoggedInElsewhere                 EResult = 50 | ||||
| 	EResult_Suspended                                EResult = 51 | ||||
| 	EResult_Cancelled                                EResult = 52 | ||||
| 	EResult_DataCorruption                           EResult = 53 | ||||
| 	EResult_DiskFull                                 EResult = 54 | ||||
| 	EResult_RemoteCallFailed                         EResult = 55 | ||||
| 	EResult_PasswordUnset                            EResult = 56 | ||||
| 	EResult_ExternalAccountUnlinked                  EResult = 57 | ||||
| 	EResult_PSNTicketInvalid                         EResult = 58 | ||||
| 	EResult_ExternalAccountAlreadyLinked             EResult = 59 | ||||
| 	EResult_RemoteFileConflict                       EResult = 60 | ||||
| 	EResult_IllegalPassword                          EResult = 61 | ||||
| 	EResult_SameAsPreviousValue                      EResult = 62 | ||||
| 	EResult_AccountLogonDenied                       EResult = 63 | ||||
| 	EResult_CannotUseOldPassword                     EResult = 64 | ||||
| 	EResult_InvalidLoginAuthCode                     EResult = 65 | ||||
| 	EResult_AccountLogonDeniedNoMail                 EResult = 66 | ||||
| 	EResult_HardwareNotCapableOfIPT                  EResult = 67 | ||||
| 	EResult_IPTInitError                             EResult = 68 | ||||
| 	EResult_ParentalControlRestricted                EResult = 69 | ||||
| 	EResult_FacebookQueryError                       EResult = 70 | ||||
| 	EResult_ExpiredLoginAuthCode                     EResult = 71 | ||||
| 	EResult_IPLoginRestrictionFailed                 EResult = 72 | ||||
| 	EResult_AccountLockedDown                        EResult = 73 | ||||
| 	EResult_AccountLogonDeniedVerifiedEmailRequired  EResult = 74 | ||||
| 	EResult_NoMatchingURL                            EResult = 75 | ||||
| 	EResult_BadResponse                              EResult = 76 | ||||
| 	EResult_RequirePasswordReEntry                   EResult = 77 | ||||
| 	EResult_ValueOutOfRange                          EResult = 78 | ||||
| 	EResult_UnexpectedError                          EResult = 79 | ||||
| 	EResult_Disabled                                 EResult = 80 | ||||
| 	EResult_InvalidCEGSubmission                     EResult = 81 | ||||
| 	EResult_RestrictedDevice                         EResult = 82 | ||||
| 	EResult_RegionLocked                             EResult = 83 | ||||
| 	EResult_RateLimitExceeded                        EResult = 84 | ||||
| 	EResult_AccountLoginDeniedNeedTwoFactor          EResult = 85 | ||||
| 	EResult_ItemDeleted                              EResult = 86 | ||||
| 	EResult_AccountLoginDeniedThrottle               EResult = 87 | ||||
| 	EResult_TwoFactorCodeMismatch                    EResult = 88 | ||||
| 	EResult_TwoFactorActivationCodeMismatch          EResult = 89 | ||||
| 	EResult_AccountAssociatedToMultiplePartners      EResult = 90 | ||||
| 	EResult_NotModified                              EResult = 91 | ||||
| 	EResult_NoMobileDevice                           EResult = 92 | ||||
| 	EResult_TimeNotSynced                            EResult = 93 | ||||
| 	EResult_SMSCodeFailed                            EResult = 94 | ||||
| 	EResult_AccountLimitExceeded                     EResult = 95 | ||||
| 	EResult_AccountActivityLimitExceeded             EResult = 96 | ||||
| 	EResult_PhoneActivityLimitExceeded               EResult = 97 | ||||
| 	EResult_RefundToWallet                           EResult = 98 | ||||
| 	EResult_EmailSendFailure                         EResult = 99 | ||||
| 	EResult_NotSettled                               EResult = 100 | ||||
| 	EResult_NeedCaptcha                              EResult = 101 | ||||
| 	EResult_GSLTDenied                               EResult = 102 | ||||
| 	EResult_GSOwnerDenied                            EResult = 103 | ||||
| 	EResult_InvalidItemType                          EResult = 104 | ||||
| 	EResult_IPBanned                                 EResult = 105 | ||||
| 	EResult_GSLTExpired                              EResult = 106 | ||||
| 	EResult_InsufficientFunds                        EResult = 107 | ||||
| 	EResult_TooManyPending                           EResult = 108 | ||||
| 	EResult_NoSiteLicensesFound                      EResult = 109 | ||||
| 	EResult_WGNetworkSendExceeded                    EResult = 110 | ||||
| 	EResult_AccountNotFriends                        EResult = 111 | ||||
| 	EResult_LimitedUserAccount                       EResult = 112 | ||||
| 	EResult_CantRemoveItem                           EResult = 113 | ||||
| 	EResult_AccountHasBeenDeleted                    EResult = 114 | ||||
| 	EResult_AccountHasAnExistingUserCancelledLicense EResult = 115 | ||||
| 	EResult_DeniedDueToCommunityCooldown             EResult = 116 | ||||
| ) | ||||
|  | ||||
| var EResult_name = map[EResult]string{ | ||||
| @@ -3716,6 +3740,9 @@ var EResult_name = map[EResult]string{ | ||||
| 	111: "EResult_AccountNotFriends", | ||||
| 	112: "EResult_LimitedUserAccount", | ||||
| 	113: "EResult_CantRemoveItem", | ||||
| 	114: "EResult_AccountHasBeenDeleted", | ||||
| 	115: "EResult_AccountHasAnExistingUserCancelledLicense", | ||||
| 	116: "EResult_DeniedDueToCommunityCooldown", | ||||
| } | ||||
|  | ||||
| func (e EResult) String() string { | ||||
| @@ -3743,7 +3770,6 @@ const ( | ||||
| 	EUniverse_Beta     EUniverse = 2 | ||||
| 	EUniverse_Internal EUniverse = 3 | ||||
| 	EUniverse_Dev      EUniverse = 4 | ||||
| 	EUniverse_Max      EUniverse = 5 | ||||
| ) | ||||
|  | ||||
| var EUniverse_name = map[EUniverse]string{ | ||||
| @@ -3752,7 +3778,6 @@ var EUniverse_name = map[EUniverse]string{ | ||||
| 	2: "EUniverse_Beta", | ||||
| 	3: "EUniverse_Internal", | ||||
| 	4: "EUniverse_Dev", | ||||
| 	5: "EUniverse_Max", | ||||
| } | ||||
|  | ||||
| func (e EUniverse) String() string { | ||||
| @@ -3836,7 +3861,6 @@ const ( | ||||
| 	EPersonaState_LookingToTrade EPersonaState = 5 | ||||
| 	EPersonaState_LookingToPlay  EPersonaState = 6 | ||||
| 	EPersonaState_Invisible      EPersonaState = 7 | ||||
| 	EPersonaState_Max            EPersonaState = 8 | ||||
| ) | ||||
|  | ||||
| var EPersonaState_name = map[EPersonaState]string{ | ||||
| @@ -3848,7 +3872,6 @@ var EPersonaState_name = map[EPersonaState]string{ | ||||
| 	5: "EPersonaState_LookingToTrade", | ||||
| 	6: "EPersonaState_LookingToPlay", | ||||
| 	7: "EPersonaState_Invisible", | ||||
| 	8: "EPersonaState_Max", | ||||
| } | ||||
|  | ||||
| func (e EPersonaState) String() string { | ||||
| @@ -3882,7 +3905,6 @@ const ( | ||||
| 	EAccountType_Chat           EAccountType = 8 | ||||
| 	EAccountType_ConsoleUser    EAccountType = 9 | ||||
| 	EAccountType_AnonUser       EAccountType = 10 | ||||
| 	EAccountType_Max            EAccountType = 11 | ||||
| ) | ||||
|  | ||||
| var EAccountType_name = map[EAccountType]string{ | ||||
| @@ -3897,7 +3919,6 @@ var EAccountType_name = map[EAccountType]string{ | ||||
| 	8:  "EAccountType_Chat", | ||||
| 	9:  "EAccountType_ConsoleUser", | ||||
| 	10: "EAccountType_AnonUser", | ||||
| 	11: "EAccountType_Max", | ||||
| } | ||||
|  | ||||
| func (e EAccountType) String() string { | ||||
| @@ -3927,7 +3948,6 @@ const ( | ||||
| 	EFriendRelationship_RequestInitiator EFriendRelationship = 4 | ||||
| 	EFriendRelationship_Ignored          EFriendRelationship = 5 | ||||
| 	EFriendRelationship_IgnoredFriend    EFriendRelationship = 6 | ||||
| 	EFriendRelationship_Max              EFriendRelationship = 8 | ||||
| ) | ||||
|  | ||||
| var EFriendRelationship_name = map[EFriendRelationship]string{ | ||||
| @@ -3939,7 +3959,6 @@ var EFriendRelationship_name = map[EFriendRelationship]string{ | ||||
| 	5: "EFriendRelationship_Ignored", | ||||
| 	6: "EFriendRelationship_IgnoredFriend", | ||||
| 	7: "EFriendRelationship_SuggestedFriend", | ||||
| 	8: "EFriendRelationship_Max", | ||||
| } | ||||
|  | ||||
| func (e EFriendRelationship) String() string { | ||||
| @@ -4212,6 +4231,7 @@ const ( | ||||
| 	EPersonaStateFlag_HasRichPresence      EPersonaStateFlag = 1 | ||||
| 	EPersonaStateFlag_InJoinableGame       EPersonaStateFlag = 2 | ||||
| 	EPersonaStateFlag_Golden               EPersonaStateFlag = 4 | ||||
| 	EPersonaStateFlag_RemotePlayTogether   EPersonaStateFlag = 8 | ||||
| 	EPersonaStateFlag_ClientTypeWeb        EPersonaStateFlag = 256 | ||||
| 	EPersonaStateFlag_ClientTypeMobile     EPersonaStateFlag = 512 | ||||
| 	EPersonaStateFlag_ClientTypeTenfoot    EPersonaStateFlag = 1024 | ||||
| @@ -4224,6 +4244,7 @@ var EPersonaStateFlag_name = map[EPersonaStateFlag]string{ | ||||
| 	1:    "EPersonaStateFlag_HasRichPresence", | ||||
| 	2:    "EPersonaStateFlag_InJoinableGame", | ||||
| 	4:    "EPersonaStateFlag_Golden", | ||||
| 	8:    "EPersonaStateFlag_RemotePlayTogether", | ||||
| 	256:  "EPersonaStateFlag_OnlineUsingWeb", | ||||
| 	512:  "EPersonaStateFlag_OnlineUsingMobile", | ||||
| 	1024: "EPersonaStateFlag_OnlineUsingBigPicture", | ||||
| @@ -4524,6 +4545,7 @@ const ( | ||||
| 	EPaymentMethod_Valve                  EPaymentMethod = 129 | ||||
| 	EPaymentMethod_MasterComp             EPaymentMethod = 130 | ||||
| 	EPaymentMethod_Promotional            EPaymentMethod = 131 | ||||
| 	EPaymentMethod_MasterSubscription     EPaymentMethod = 134 | ||||
| 	EPaymentMethod_OEMTicket              EPaymentMethod = 256 | ||||
| 	EPaymentMethod_Split                  EPaymentMethod = 512 | ||||
| 	EPaymentMethod_Complimentary          EPaymentMethod = 1024 | ||||
| @@ -4613,6 +4635,7 @@ var EPaymentMethod_name = map[EPaymentMethod]string{ | ||||
| 	129:  "EPaymentMethod_Valve", | ||||
| 	130:  "EPaymentMethod_SteamPressMaster", | ||||
| 	131:  "EPaymentMethod_StorePromotion", | ||||
| 	134:  "EPaymentMethod_MasterSubscription", | ||||
| 	256:  "EPaymentMethod_OEMTicket", | ||||
| 	512:  "EPaymentMethod_Split", | ||||
| 	1024: "EPaymentMethod_Complimentary", | ||||
| @@ -4706,6 +4729,22 @@ const ( | ||||
| 	EPurchaseResultDetail_PurchaseCannotBeReplayed                EPurchaseResultDetail = 65 | ||||
| 	EPurchaseResultDetail_DelayedCompletion                       EPurchaseResultDetail = 66 | ||||
| 	EPurchaseResultDetail_BundleTypeCannotBeGifted                EPurchaseResultDetail = 67 | ||||
| 	EPurchaseResultDetail_BlockedByUSGov                          EPurchaseResultDetail = 68 | ||||
| 	EPurchaseResultDetail_ItemsReservedForCommercialUse           EPurchaseResultDetail = 69 | ||||
| 	EPurchaseResultDetail_GiftAlreadyOwned                        EPurchaseResultDetail = 70 | ||||
| 	EPurchaseResultDetail_GiftInvalidForRecipientRegion           EPurchaseResultDetail = 71 | ||||
| 	EPurchaseResultDetail_GiftPricingImbalance                    EPurchaseResultDetail = 72 | ||||
| 	EPurchaseResultDetail_GiftRecipientNotSpecified               EPurchaseResultDetail = 73 | ||||
| 	EPurchaseResultDetail_ItemsNotAllowedForCommercialUse         EPurchaseResultDetail = 74 | ||||
| 	EPurchaseResultDetail_BusinessStoreCountryCodeMismatch        EPurchaseResultDetail = 75 | ||||
| 	EPurchaseResultDetail_UserAssociatedWithManyCafes             EPurchaseResultDetail = 76 | ||||
| 	EPurchaseResultDetail_UserNotAssociatedWithCafe               EPurchaseResultDetail = 77 | ||||
| 	EPurchaseResultDetail_AddressInvalid                          EPurchaseResultDetail = 78 | ||||
| 	EPurchaseResultDetail_CreditCardNumberInvalid                 EPurchaseResultDetail = 79 | ||||
| 	EPurchaseResultDetail_CannotShipToMilitaryPostOffice          EPurchaseResultDetail = 80 | ||||
| 	EPurchaseResultDetail_BillingNameInvalidResemblesCreditCard   EPurchaseResultDetail = 81 | ||||
| 	EPurchaseResultDetail_PaymentMethodTemporarilyUnavailable     EPurchaseResultDetail = 82 | ||||
| 	EPurchaseResultDetail_PaymentMethodNotSupportedForProduct     EPurchaseResultDetail = 83 | ||||
| ) | ||||
|  | ||||
| var EPurchaseResultDetail_name = map[EPurchaseResultDetail]string{ | ||||
| @@ -4777,6 +4816,22 @@ var EPurchaseResultDetail_name = map[EPurchaseResultDetail]string{ | ||||
| 	65: "EPurchaseResultDetail_PurchaseCannotBeReplayed", | ||||
| 	66: "EPurchaseResultDetail_DelayedCompletion", | ||||
| 	67: "EPurchaseResultDetail_BundleTypeCannotBeGifted", | ||||
| 	68: "EPurchaseResultDetail_BlockedByUSGov", | ||||
| 	69: "EPurchaseResultDetail_ItemsReservedForCommercialUse", | ||||
| 	70: "EPurchaseResultDetail_GiftAlreadyOwned", | ||||
| 	71: "EPurchaseResultDetail_GiftInvalidForRecipientRegion", | ||||
| 	72: "EPurchaseResultDetail_GiftPricingImbalance", | ||||
| 	73: "EPurchaseResultDetail_GiftRecipientNotSpecified", | ||||
| 	74: "EPurchaseResultDetail_ItemsNotAllowedForCommercialUse", | ||||
| 	75: "EPurchaseResultDetail_BusinessStoreCountryCodeMismatch", | ||||
| 	76: "EPurchaseResultDetail_UserAssociatedWithManyCafes", | ||||
| 	77: "EPurchaseResultDetail_UserNotAssociatedWithCafe", | ||||
| 	78: "EPurchaseResultDetail_AddressInvalid", | ||||
| 	79: "EPurchaseResultDetail_CreditCardNumberInvalid", | ||||
| 	80: "EPurchaseResultDetail_CannotShipToMilitaryPostOffice", | ||||
| 	81: "EPurchaseResultDetail_BillingNameInvalidResemblesCreditCard", | ||||
| 	82: "EPurchaseResultDetail_PaymentMethodTemporarilyUnavailable", | ||||
| 	83: "EPurchaseResultDetail_PaymentMethodNotSupportedForProduct", | ||||
| } | ||||
|  | ||||
| func (e EPurchaseResultDetail) String() string { | ||||
| @@ -5275,7 +5330,8 @@ const ( | ||||
| 	EAppInfoSection_Store             EAppInfoSection = 16 | ||||
| 	EAppInfoSection_Localization      EAppInfoSection = 17 | ||||
| 	EAppInfoSection_Broadcastgamedata EAppInfoSection = 18 | ||||
| 	EAppInfoSection_Max               EAppInfoSection = 19 | ||||
| 	EAppInfoSection_Computed          EAppInfoSection = 19 | ||||
| 	EAppInfoSection_Albummetadata     EAppInfoSection = 20 | ||||
| ) | ||||
|  | ||||
| var EAppInfoSection_name = map[EAppInfoSection]string{ | ||||
| @@ -5298,7 +5354,8 @@ var EAppInfoSection_name = map[EAppInfoSection]string{ | ||||
| 	16: "EAppInfoSection_Store", | ||||
| 	17: "EAppInfoSection_Localization", | ||||
| 	18: "EAppInfoSection_Broadcastgamedata", | ||||
| 	19: "EAppInfoSection_Max", | ||||
| 	19: "EAppInfoSection_Computed", | ||||
| 	20: "EAppInfoSection_Albummetadata", | ||||
| } | ||||
|  | ||||
| func (e EAppInfoSection) String() string { | ||||
| @@ -5330,7 +5387,7 @@ const ( | ||||
| 	EContentDownloadSourceType_SLS        EContentDownloadSourceType = 6 | ||||
| 	EContentDownloadSourceType_SteamCache EContentDownloadSourceType = 7 | ||||
| 	EContentDownloadSourceType_OpenCache  EContentDownloadSourceType = 8 | ||||
| 	EContentDownloadSourceType_Max        EContentDownloadSourceType = 9 | ||||
| 	EContentDownloadSourceType_LANCache   EContentDownloadSourceType = 9 | ||||
| ) | ||||
|  | ||||
| var EContentDownloadSourceType_name = map[EContentDownloadSourceType]string{ | ||||
| @@ -5343,7 +5400,7 @@ var EContentDownloadSourceType_name = map[EContentDownloadSourceType]string{ | ||||
| 	6: "EContentDownloadSourceType_SLS", | ||||
| 	7: "EContentDownloadSourceType_SteamCache", | ||||
| 	8: "EContentDownloadSourceType_OpenCache", | ||||
| 	9: "EContentDownloadSourceType_Max", | ||||
| 	9: "EContentDownloadSourceType_LANCache", | ||||
| } | ||||
|  | ||||
| func (e EContentDownloadSourceType) String() string { | ||||
| @@ -5373,7 +5430,6 @@ const ( | ||||
| 	EPlatformType_OSX     EPlatformType = 4 | ||||
| 	EPlatformType_PS3     EPlatformType = 5 | ||||
| 	EPlatformType_Linux32 EPlatformType = 6 | ||||
| 	EPlatformType_Max     EPlatformType = 7 | ||||
| ) | ||||
|  | ||||
| var EPlatformType_name = map[EPlatformType]string{ | ||||
| @@ -5384,7 +5440,6 @@ var EPlatformType_name = map[EPlatformType]string{ | ||||
| 	4: "EPlatformType_OSX", | ||||
| 	5: "EPlatformType_PS3", | ||||
| 	6: "EPlatformType_Linux32", | ||||
| 	7: "EPlatformType_Max", | ||||
| } | ||||
|  | ||||
| func (e EPlatformType) String() string { | ||||
| @@ -5462,6 +5517,7 @@ const ( | ||||
| 	EOSType_MacOS1012      EOSType = -85 | ||||
| 	EOSType_Macos1013      EOSType = -84 | ||||
| 	EOSType_Macos1014      EOSType = -83 | ||||
| 	EOSType_Macos1015      EOSType = -82 | ||||
| 	EOSType_MacOSMax       EOSType = -1 | ||||
| 	EOSType_LinuxUnknown   EOSType = -203 | ||||
| 	EOSType_Linux22        EOSType = -202 | ||||
| @@ -5501,7 +5557,6 @@ const ( | ||||
| 	EOSType_Windows10      EOSType = 16 | ||||
| 	EOSType_Win2016        EOSType = 17 | ||||
| 	EOSType_WinMAX         EOSType = 18 | ||||
| 	EOSType_Max            EOSType = 26 | ||||
| ) | ||||
|  | ||||
| var EOSType_name = map[EOSType]string{ | ||||
| @@ -5560,6 +5615,7 @@ var EOSType_name = map[EOSType]string{ | ||||
| 	-85:  "EOSType_MacOS1012", | ||||
| 	-84:  "EOSType_Macos1013", | ||||
| 	-83:  "EOSType_Macos1014", | ||||
| 	-82:  "EOSType_Macos1015", | ||||
| 	-203: "EOSType_LinuxUnknown", | ||||
| 	-202: "EOSType_Linux22", | ||||
| 	-201: "EOSType_Linux24", | ||||
| @@ -5597,7 +5653,6 @@ var EOSType_name = map[EOSType]string{ | ||||
| 	16:   "EOSType_Win10", | ||||
| 	17:   "EOSType_Win2016", | ||||
| 	18:   "EOSType_WinMAX", | ||||
| 	26:   "EOSType_Max", | ||||
| } | ||||
|  | ||||
| func (e EOSType) String() string { | ||||
| @@ -5734,7 +5789,19 @@ const ( | ||||
| 	EServerType_TimeMachine         EServerType = 111 | ||||
| 	EServerType_VACDBMaster         EServerType = 112 | ||||
| 	EServerType_ContentServerConfig EServerType = 113 | ||||
| 	EServerType_Max                 EServerType = 114 | ||||
| 	EServerType_Minigame            EServerType = 114 | ||||
| 	EServerType_MLTrain             EServerType = 115 | ||||
| 	EServerType_VACTest             EServerType = 116 | ||||
| 	EServerType_TaxService          EServerType = 117 | ||||
| 	EServerType_MLInference         EServerType = 118 | ||||
| 	EServerType_UGSAggregate        EServerType = 119 | ||||
| 	EServerType_TURN                EServerType = 120 | ||||
| 	EServerType_RemoteClient        EServerType = 121 | ||||
| 	EServerType_BroadcastOrigin     EServerType = 122 | ||||
| 	EServerType_BroadcastChannel    EServerType = 123 | ||||
| 	EServerType_SteamAR             EServerType = 124 | ||||
| 	EServerType_China               EServerType = 125 | ||||
| 	EServerType_CrashDump           EServerType = 126 | ||||
| ) | ||||
|  | ||||
| var EServerType_name = map[EServerType]string{ | ||||
| @@ -5856,7 +5923,19 @@ var EServerType_name = map[EServerType]string{ | ||||
| 	111: "EServerType_TimeMachine", | ||||
| 	112: "EServerType_VACDBMaster", | ||||
| 	113: "EServerType_ContentServerConfig", | ||||
| 	114: "EServerType_Max", | ||||
| 	114: "EServerType_Minigame", | ||||
| 	115: "EServerType_MLTrain", | ||||
| 	116: "EServerType_VACTest", | ||||
| 	117: "EServerType_TaxService", | ||||
| 	118: "EServerType_MLInference", | ||||
| 	119: "EServerType_UGSAggregate", | ||||
| 	120: "EServerType_TURN", | ||||
| 	121: "EServerType_RemoteClient", | ||||
| 	122: "EServerType_BroadcastOrigin", | ||||
| 	123: "EServerType_BroadcastChannel", | ||||
| 	124: "EServerType_SteamAR", | ||||
| 	125: "EServerType_China", | ||||
| 	126: "EServerType_CrashDump", | ||||
| } | ||||
|  | ||||
| func (e EServerType) String() string { | ||||
| @@ -6102,7 +6181,6 @@ const ( | ||||
| 	ECurrencyCode_QAR     ECurrencyCode = 39 | ||||
| 	ECurrencyCode_CRC     ECurrencyCode = 40 | ||||
| 	ECurrencyCode_UYU     ECurrencyCode = 41 | ||||
| 	ECurrencyCode_Max     ECurrencyCode = 42 | ||||
| ) | ||||
|  | ||||
| var ECurrencyCode_name = map[ECurrencyCode]string{ | ||||
| @@ -6147,7 +6225,6 @@ var ECurrencyCode_name = map[ECurrencyCode]string{ | ||||
| 	39: "ECurrencyCode_QAR", | ||||
| 	40: "ECurrencyCode_CRC", | ||||
| 	41: "ECurrencyCode_UYU", | ||||
| 	42: "ECurrencyCode_Max", | ||||
| } | ||||
|  | ||||
| func (e ECurrencyCode) String() string { | ||||
| @@ -6302,7 +6379,6 @@ const ( | ||||
| 	EWorkshopFileType_SteamworksAccessInvite EWorkshopFileType = 13 | ||||
| 	EWorkshopFileType_SteamVideo             EWorkshopFileType = 14 | ||||
| 	EWorkshopFileType_GameManagedItem        EWorkshopFileType = 15 | ||||
| 	EWorkshopFileType_Max                    EWorkshopFileType = 16 | ||||
| ) | ||||
|  | ||||
| var EWorkshopFileType_name = map[EWorkshopFileType]string{ | ||||
| @@ -6322,7 +6398,6 @@ var EWorkshopFileType_name = map[EWorkshopFileType]string{ | ||||
| 	13: "EWorkshopFileType_SteamworksAccessInvite", | ||||
| 	14: "EWorkshopFileType_SteamVideo", | ||||
| 	15: "EWorkshopFileType_GameManagedItem", | ||||
| 	16: "EWorkshopFileType_Max", | ||||
| } | ||||
|  | ||||
| func (e EWorkshopFileType) String() string { | ||||
| @@ -6548,21 +6623,19 @@ const ( | ||||
| 	ESystemIMType_GiftRevoked              ESystemIMType = 7 | ||||
| 	ESystemIMType_SupportMessage           ESystemIMType = 8 | ||||
| 	ESystemIMType_SupportMessageClearAlert ESystemIMType = 9 | ||||
| 	ESystemIMType_Max                      ESystemIMType = 10 | ||||
| ) | ||||
|  | ||||
| var ESystemIMType_name = map[ESystemIMType]string{ | ||||
| 	0:  "ESystemIMType_RawText", | ||||
| 	1:  "ESystemIMType_InvalidCard", | ||||
| 	2:  "ESystemIMType_RecurringPurchaseFailed", | ||||
| 	3:  "ESystemIMType_CardWillExpire", | ||||
| 	4:  "ESystemIMType_SubscriptionExpired", | ||||
| 	5:  "ESystemIMType_GuestPassReceived", | ||||
| 	6:  "ESystemIMType_GuestPassGranted", | ||||
| 	7:  "ESystemIMType_GiftRevoked", | ||||
| 	8:  "ESystemIMType_SupportMessage", | ||||
| 	9:  "ESystemIMType_SupportMessageClearAlert", | ||||
| 	10: "ESystemIMType_Max", | ||||
| 	0: "ESystemIMType_RawText", | ||||
| 	1: "ESystemIMType_InvalidCard", | ||||
| 	2: "ESystemIMType_RecurringPurchaseFailed", | ||||
| 	3: "ESystemIMType_CardWillExpire", | ||||
| 	4: "ESystemIMType_SubscriptionExpired", | ||||
| 	5: "ESystemIMType_GuestPassReceived", | ||||
| 	6: "ESystemIMType_GuestPassGranted", | ||||
| 	7: "ESystemIMType_GiftRevoked", | ||||
| 	8: "ESystemIMType_SupportMessage", | ||||
| 	9: "ESystemIMType_SupportMessageClearAlert", | ||||
| } | ||||
|  | ||||
| func (e ESystemIMType) String() string { | ||||
| @@ -6618,15 +6691,15 @@ func (e EChatFlags) String() string { | ||||
| type ERemoteStoragePlatform int32 | ||||
|  | ||||
| const ( | ||||
| 	ERemoteStoragePlatform_None      ERemoteStoragePlatform = 0 | ||||
| 	ERemoteStoragePlatform_Windows   ERemoteStoragePlatform = 1 | ||||
| 	ERemoteStoragePlatform_OSX       ERemoteStoragePlatform = 2 | ||||
| 	ERemoteStoragePlatform_PS3       ERemoteStoragePlatform = 4 | ||||
| 	ERemoteStoragePlatform_Linux     ERemoteStoragePlatform = 8 | ||||
| 	ERemoteStoragePlatform_Reserved2 ERemoteStoragePlatform = 16 | ||||
| 	ERemoteStoragePlatform_Android   ERemoteStoragePlatform = 32 | ||||
| 	ERemoteStoragePlatform_IPhoneOS  ERemoteStoragePlatform = 64 | ||||
| 	ERemoteStoragePlatform_All       ERemoteStoragePlatform = -1 | ||||
| 	ERemoteStoragePlatform_None     ERemoteStoragePlatform = 0 | ||||
| 	ERemoteStoragePlatform_Windows  ERemoteStoragePlatform = 1 | ||||
| 	ERemoteStoragePlatform_OSX      ERemoteStoragePlatform = 2 | ||||
| 	ERemoteStoragePlatform_PS3      ERemoteStoragePlatform = 4 | ||||
| 	ERemoteStoragePlatform_Linux    ERemoteStoragePlatform = 8 | ||||
| 	ERemoteStoragePlatform_Switch   ERemoteStoragePlatform = 16 | ||||
| 	ERemoteStoragePlatform_Android  ERemoteStoragePlatform = 32 | ||||
| 	ERemoteStoragePlatform_IPhoneOS ERemoteStoragePlatform = 64 | ||||
| 	ERemoteStoragePlatform_All      ERemoteStoragePlatform = -1 | ||||
| ) | ||||
|  | ||||
| var ERemoteStoragePlatform_name = map[ERemoteStoragePlatform]string{ | ||||
| @@ -6635,7 +6708,7 @@ var ERemoteStoragePlatform_name = map[ERemoteStoragePlatform]string{ | ||||
| 	2:  "ERemoteStoragePlatform_OSX", | ||||
| 	4:  "ERemoteStoragePlatform_PS3", | ||||
| 	8:  "ERemoteStoragePlatform_Linux", | ||||
| 	16: "ERemoteStoragePlatform_Reserved2", | ||||
| 	16: "ERemoteStoragePlatform_Switch", | ||||
| 	32: "ERemoteStoragePlatform_Android", | ||||
| 	64: "ERemoteStoragePlatform_IPhoneOS", | ||||
| 	-1: "ERemoteStoragePlatform_All", | ||||
| @@ -6780,7 +6853,6 @@ const ( | ||||
| 	EClientStat_P2PGameConnections  EClientStat = 2 | ||||
| 	EClientStat_P2PVoiceConnections EClientStat = 3 | ||||
| 	EClientStat_BytesDownloaded     EClientStat = 4 | ||||
| 	EClientStat_Max                 EClientStat = 5 | ||||
| ) | ||||
|  | ||||
| var EClientStat_name = map[EClientStat]string{ | ||||
| @@ -6789,7 +6861,6 @@ var EClientStat_name = map[EClientStat]string{ | ||||
| 	2: "EClientStat_P2PGameConnections", | ||||
| 	3: "EClientStat_P2PVoiceConnections", | ||||
| 	4: "EClientStat_BytesDownloaded", | ||||
| 	5: "EClientStat_Max", | ||||
| } | ||||
|  | ||||
| func (e EClientStat) String() string { | ||||
| @@ -7106,6 +7177,7 @@ type EPublishedFileInappropriateResult int32 | ||||
| const ( | ||||
| 	EPublishedFileInappropriateResult_NotScanned   EPublishedFileInappropriateResult = 0 | ||||
| 	EPublishedFileInappropriateResult_VeryUnlikely EPublishedFileInappropriateResult = 1 | ||||
| 	EPublishedFileInappropriateResult_Unlikely     EPublishedFileInappropriateResult = 30 | ||||
| 	EPublishedFileInappropriateResult_Possible     EPublishedFileInappropriateResult = 50 | ||||
| 	EPublishedFileInappropriateResult_Likely       EPublishedFileInappropriateResult = 75 | ||||
| 	EPublishedFileInappropriateResult_VeryLikely   EPublishedFileInappropriateResult = 100 | ||||
| @@ -7114,6 +7186,7 @@ const ( | ||||
| var EPublishedFileInappropriateResult_name = map[EPublishedFileInappropriateResult]string{ | ||||
| 	0:   "EPublishedFileInappropriateResult_NotScanned", | ||||
| 	1:   "EPublishedFileInappropriateResult_VeryUnlikely", | ||||
| 	30:  "EPublishedFileInappropriateResult_Unlikely", | ||||
| 	50:  "EPublishedFileInappropriateResult_Possible", | ||||
| 	75:  "EPublishedFileInappropriateResult_Likely", | ||||
| 	100: "EPublishedFileInappropriateResult_VeryLikely", | ||||
| @@ -7723,6 +7796,282 @@ func (e ETradeOfferConfirmationMethod) String() string { | ||||
| 	return strings.Join(flags, " | ") | ||||
| } | ||||
|  | ||||
| type ELobbyType int32 | ||||
|  | ||||
| const ( | ||||
| 	ELobbyType_Private       ELobbyType = 0 | ||||
| 	ELobbyType_FriendsOnly   ELobbyType = 1 | ||||
| 	ELobbyType_Public        ELobbyType = 2 | ||||
| 	ELobbyType_Invisible     ELobbyType = 3 | ||||
| 	ELobbyType_PrivateUnique ELobbyType = 4 | ||||
| ) | ||||
|  | ||||
| var ELobbyType_name = map[ELobbyType]string{ | ||||
| 	0: "ELobbyType_Private", | ||||
| 	1: "ELobbyType_FriendsOnly", | ||||
| 	2: "ELobbyType_Public", | ||||
| 	3: "ELobbyType_Invisible", | ||||
| 	4: "ELobbyType_PrivateUnique", | ||||
| } | ||||
|  | ||||
| func (e ELobbyType) String() string { | ||||
| 	if s, ok := ELobbyType_name[e]; ok { | ||||
| 		return s | ||||
| 	} | ||||
| 	var flags []string | ||||
| 	for k, v := range ELobbyType_name { | ||||
| 		if e&k != 0 { | ||||
| 			flags = append(flags, v) | ||||
| 		} | ||||
| 	} | ||||
| 	if len(flags) == 0 { | ||||
| 		return fmt.Sprintf("%d", e) | ||||
| 	} | ||||
| 	sort.Strings(flags) | ||||
| 	return strings.Join(flags, " | ") | ||||
| } | ||||
|  | ||||
| type ELobbyFilterType int32 | ||||
|  | ||||
| const ( | ||||
| 	ELobbyFilterType_String         ELobbyFilterType = 0 | ||||
| 	ELobbyFilterType_Numerical      ELobbyFilterType = 1 | ||||
| 	ELobbyFilterType_SlotsAvailable ELobbyFilterType = 2 | ||||
| 	ELobbyFilterType_NearValue      ELobbyFilterType = 3 | ||||
| 	ELobbyFilterType_Distance       ELobbyFilterType = 4 | ||||
| ) | ||||
|  | ||||
| var ELobbyFilterType_name = map[ELobbyFilterType]string{ | ||||
| 	0: "ELobbyFilterType_String", | ||||
| 	1: "ELobbyFilterType_Numerical", | ||||
| 	2: "ELobbyFilterType_SlotsAvailable", | ||||
| 	3: "ELobbyFilterType_NearValue", | ||||
| 	4: "ELobbyFilterType_Distance", | ||||
| } | ||||
|  | ||||
| func (e ELobbyFilterType) String() string { | ||||
| 	if s, ok := ELobbyFilterType_name[e]; ok { | ||||
| 		return s | ||||
| 	} | ||||
| 	var flags []string | ||||
| 	for k, v := range ELobbyFilterType_name { | ||||
| 		if e&k != 0 { | ||||
| 			flags = append(flags, v) | ||||
| 		} | ||||
| 	} | ||||
| 	if len(flags) == 0 { | ||||
| 		return fmt.Sprintf("%d", e) | ||||
| 	} | ||||
| 	sort.Strings(flags) | ||||
| 	return strings.Join(flags, " | ") | ||||
| } | ||||
|  | ||||
| type ELobbyComparison int32 | ||||
|  | ||||
| const ( | ||||
| 	ELobbyComparison_EqualToOrLessThan    ELobbyComparison = -2 | ||||
| 	ELobbyComparison_LessThan             ELobbyComparison = -1 | ||||
| 	ELobbyComparison_Equal                ELobbyComparison = 0 | ||||
| 	ELobbyComparison_GreaterThan          ELobbyComparison = 1 | ||||
| 	ELobbyComparison_EqualToOrGreaterThan ELobbyComparison = 2 | ||||
| 	ELobbyComparison_NotEqual             ELobbyComparison = 3 | ||||
| ) | ||||
|  | ||||
| var ELobbyComparison_name = map[ELobbyComparison]string{ | ||||
| 	-2: "ELobbyComparison_EqualToOrLessThan", | ||||
| 	-1: "ELobbyComparison_LessThan", | ||||
| 	0:  "ELobbyComparison_Equal", | ||||
| 	1:  "ELobbyComparison_GreaterThan", | ||||
| 	2:  "ELobbyComparison_EqualToOrGreaterThan", | ||||
| 	3:  "ELobbyComparison_NotEqual", | ||||
| } | ||||
|  | ||||
| func (e ELobbyComparison) String() string { | ||||
| 	if s, ok := ELobbyComparison_name[e]; ok { | ||||
| 		return s | ||||
| 	} | ||||
| 	var flags []string | ||||
| 	for k, v := range ELobbyComparison_name { | ||||
| 		if e&k != 0 { | ||||
| 			flags = append(flags, v) | ||||
| 		} | ||||
| 	} | ||||
| 	if len(flags) == 0 { | ||||
| 		return fmt.Sprintf("%d", e) | ||||
| 	} | ||||
| 	sort.Strings(flags) | ||||
| 	return strings.Join(flags, " | ") | ||||
| } | ||||
|  | ||||
| type ELobbyDistanceFilter int32 | ||||
|  | ||||
| const ( | ||||
| 	ELobbyDistanceFilter_Close     ELobbyDistanceFilter = 0 | ||||
| 	ELobbyDistanceFilter_Default   ELobbyDistanceFilter = 1 | ||||
| 	ELobbyDistanceFilter_Far       ELobbyDistanceFilter = 2 | ||||
| 	ELobbyDistanceFilter_Worldwide ELobbyDistanceFilter = 3 | ||||
| ) | ||||
|  | ||||
| var ELobbyDistanceFilter_name = map[ELobbyDistanceFilter]string{ | ||||
| 	0: "ELobbyDistanceFilter_Close", | ||||
| 	1: "ELobbyDistanceFilter_Default", | ||||
| 	2: "ELobbyDistanceFilter_Far", | ||||
| 	3: "ELobbyDistanceFilter_Worldwide", | ||||
| } | ||||
|  | ||||
| func (e ELobbyDistanceFilter) String() string { | ||||
| 	if s, ok := ELobbyDistanceFilter_name[e]; ok { | ||||
| 		return s | ||||
| 	} | ||||
| 	var flags []string | ||||
| 	for k, v := range ELobbyDistanceFilter_name { | ||||
| 		if e&k != 0 { | ||||
| 			flags = append(flags, v) | ||||
| 		} | ||||
| 	} | ||||
| 	if len(flags) == 0 { | ||||
| 		return fmt.Sprintf("%d", e) | ||||
| 	} | ||||
| 	sort.Strings(flags) | ||||
| 	return strings.Join(flags, " | ") | ||||
| } | ||||
|  | ||||
| type ESteamIPv6ConnectivityProtocol int32 | ||||
|  | ||||
| const ( | ||||
| 	ESteamIPv6ConnectivityProtocol_Invalid ESteamIPv6ConnectivityProtocol = 0 | ||||
| 	ESteamIPv6ConnectivityProtocol_Http    ESteamIPv6ConnectivityProtocol = 1 | ||||
| 	ESteamIPv6ConnectivityProtocol_Udp     ESteamIPv6ConnectivityProtocol = 2 | ||||
| ) | ||||
|  | ||||
| var ESteamIPv6ConnectivityProtocol_name = map[ESteamIPv6ConnectivityProtocol]string{ | ||||
| 	0: "ESteamIPv6ConnectivityProtocol_Invalid", | ||||
| 	1: "ESteamIPv6ConnectivityProtocol_Http", | ||||
| 	2: "ESteamIPv6ConnectivityProtocol_Udp", | ||||
| } | ||||
|  | ||||
| func (e ESteamIPv6ConnectivityProtocol) String() string { | ||||
| 	if s, ok := ESteamIPv6ConnectivityProtocol_name[e]; ok { | ||||
| 		return s | ||||
| 	} | ||||
| 	var flags []string | ||||
| 	for k, v := range ESteamIPv6ConnectivityProtocol_name { | ||||
| 		if e&k != 0 { | ||||
| 			flags = append(flags, v) | ||||
| 		} | ||||
| 	} | ||||
| 	if len(flags) == 0 { | ||||
| 		return fmt.Sprintf("%d", e) | ||||
| 	} | ||||
| 	sort.Strings(flags) | ||||
| 	return strings.Join(flags, " | ") | ||||
| } | ||||
|  | ||||
| type ESteamIPv6ConnectivityState int32 | ||||
|  | ||||
| const ( | ||||
| 	ESteamIPv6ConnectivityState_Unknown ESteamIPv6ConnectivityState = 0 | ||||
| 	ESteamIPv6ConnectivityState_Good    ESteamIPv6ConnectivityState = 1 | ||||
| 	ESteamIPv6ConnectivityState_Bad     ESteamIPv6ConnectivityState = 2 | ||||
| ) | ||||
|  | ||||
| var ESteamIPv6ConnectivityState_name = map[ESteamIPv6ConnectivityState]string{ | ||||
| 	0: "ESteamIPv6ConnectivityState_Unknown", | ||||
| 	1: "ESteamIPv6ConnectivityState_Good", | ||||
| 	2: "ESteamIPv6ConnectivityState_Bad", | ||||
| } | ||||
|  | ||||
| func (e ESteamIPv6ConnectivityState) String() string { | ||||
| 	if s, ok := ESteamIPv6ConnectivityState_name[e]; ok { | ||||
| 		return s | ||||
| 	} | ||||
| 	var flags []string | ||||
| 	for k, v := range ESteamIPv6ConnectivityState_name { | ||||
| 		if e&k != 0 { | ||||
| 			flags = append(flags, v) | ||||
| 		} | ||||
| 	} | ||||
| 	if len(flags) == 0 { | ||||
| 		return fmt.Sprintf("%d", e) | ||||
| 	} | ||||
| 	sort.Strings(flags) | ||||
| 	return strings.Join(flags, " | ") | ||||
| } | ||||
|  | ||||
| type ESteamRealm int32 | ||||
|  | ||||
| const ( | ||||
| 	ESteamRealm_Unknown     ESteamRealm = 0 | ||||
| 	ESteamRealm_SteamGlobal ESteamRealm = 1 | ||||
| 	ESteamRealm_SteamChina  ESteamRealm = 2 | ||||
| ) | ||||
|  | ||||
| var ESteamRealm_name = map[ESteamRealm]string{ | ||||
| 	0: "ESteamRealm_Unknown", | ||||
| 	1: "ESteamRealm_SteamGlobal", | ||||
| 	2: "ESteamRealm_SteamChina", | ||||
| } | ||||
|  | ||||
| func (e ESteamRealm) String() string { | ||||
| 	if s, ok := ESteamRealm_name[e]; ok { | ||||
| 		return s | ||||
| 	} | ||||
| 	var flags []string | ||||
| 	for k, v := range ESteamRealm_name { | ||||
| 		if e&k != 0 { | ||||
| 			flags = append(flags, v) | ||||
| 		} | ||||
| 	} | ||||
| 	if len(flags) == 0 { | ||||
| 		return fmt.Sprintf("%d", e) | ||||
| 	} | ||||
| 	sort.Strings(flags) | ||||
| 	return strings.Join(flags, " | ") | ||||
| } | ||||
|  | ||||
| type ELauncherType int32 | ||||
|  | ||||
| const ( | ||||
| 	ELauncherType_Default      ELauncherType = 0 | ||||
| 	ELauncherType_PerfectWorld ELauncherType = 1 | ||||
| 	ELauncherType_Nexon        ELauncherType = 2 | ||||
| 	ELauncherType_CmdLine      ELauncherType = 3 | ||||
| 	ELauncherType_CSGO         ELauncherType = 4 | ||||
| 	ELauncherType_ClientUI     ELauncherType = 5 | ||||
| 	ELauncherType_Headless     ELauncherType = 6 | ||||
| 	ELauncherType_SteamChina   ELauncherType = 7 | ||||
| 	ELauncherType_SingleApp    ELauncherType = 8 | ||||
| ) | ||||
|  | ||||
| var ELauncherType_name = map[ELauncherType]string{ | ||||
| 	0: "ELauncherType_Default", | ||||
| 	1: "ELauncherType_PerfectWorld", | ||||
| 	2: "ELauncherType_Nexon", | ||||
| 	3: "ELauncherType_CmdLine", | ||||
| 	4: "ELauncherType_CSGO", | ||||
| 	5: "ELauncherType_ClientUI", | ||||
| 	6: "ELauncherType_Headless", | ||||
| 	7: "ELauncherType_SteamChina", | ||||
| 	8: "ELauncherType_SingleApp", | ||||
| } | ||||
|  | ||||
| func (e ELauncherType) String() string { | ||||
| 	if s, ok := ELauncherType_name[e]; ok { | ||||
| 		return s | ||||
| 	} | ||||
| 	var flags []string | ||||
| 	for k, v := range ELauncherType_name { | ||||
| 		if e&k != 0 { | ||||
| 			flags = append(flags, v) | ||||
| 		} | ||||
| 	} | ||||
| 	if len(flags) == 0 { | ||||
| 		return fmt.Sprintf("%d", e) | ||||
| 	} | ||||
| 	sort.Strings(flags) | ||||
| 	return strings.Join(flags, " | ") | ||||
| } | ||||
|  | ||||
| type EUdpPacketType uint8 | ||||
|  | ||||
| const ( | ||||
|   | ||||
							
								
								
									
										27
									
								
								vendor/github.com/Philipp15b/go-steam/social.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/Philipp15b/go-steam/social.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -84,14 +84,14 @@ func (s *Social) SetPersonaState(state EPersonaState) { | ||||
|  | ||||
| // Sends a chat message to ether a room or friend | ||||
| func (s *Social) SendMessage(to SteamId, entryType EChatEntryType, message string) { | ||||
| 	//Friend | ||||
| 	// Friend | ||||
| 	if to.GetAccountType() == int32(EAccountType_Individual) || to.GetAccountType() == int32(EAccountType_ConsoleUser) { | ||||
| 		s.client.Write(NewClientMsgProtobuf(EMsg_ClientFriendMsg, &CMsgClientFriendMsg{ | ||||
| 			Steamid:       proto.Uint64(to.ToUint64()), | ||||
| 			ChatEntryType: proto.Int32(int32(entryType)), | ||||
| 			Message:       []byte(message), | ||||
| 		})) | ||||
| 		//Chat room | ||||
| 		// Chat room | ||||
| 	} else if to.GetAccountType() == int32(EAccountType_Clan) || to.GetAccountType() == int32(EAccountType_Chat) { | ||||
| 		chatId := to.ClanToChat() | ||||
| 		s.client.Write(NewClientMsg(&MsgClientChatMsg{ | ||||
| @@ -119,9 +119,9 @@ func (s *Social) RemoveFriend(id SteamId) { | ||||
|  | ||||
| // Ignores or unignores a friend on Steam | ||||
| func (s *Social) IgnoreFriend(id SteamId, setIgnore bool) { | ||||
| 	ignore := uint8(1) //True | ||||
| 	ignore := uint8(1) // True | ||||
| 	if !setIgnore { | ||||
| 		ignore = uint8(0) //False | ||||
| 		ignore = uint8(0) // False | ||||
| 	} | ||||
| 	s.client.Write(NewClientMsg(&MsgClientSetIgnoreFriend{ | ||||
| 		MySteamId:     s.client.SteamId(), | ||||
| @@ -244,7 +244,7 @@ func (s *Social) HandlePacket(packet *Packet) { | ||||
| } | ||||
|  | ||||
| func (s *Social) handleAccountInfo(packet *Packet) { | ||||
| 	//Just fire the personainfo, Auth handles the callback | ||||
| 	// Just fire the personainfo, Auth handles the callback | ||||
| 	flags := EClientPersonaStateFlag_PlayerName | EClientPersonaStateFlag_Presence | EClientPersonaStateFlag_SourceID | ||||
| 	s.RequestFriendInfo(s.client.SteamId(), EClientPersonaStateFlag(flags)) | ||||
| } | ||||
| @@ -302,7 +302,7 @@ func (s *Social) handlePersonaState(packet *Packet) { | ||||
| 	flags := EClientPersonaStateFlag(list.GetStatusFlags()) | ||||
| 	for _, friend := range list.GetFriends() { | ||||
| 		id := SteamId(friend.GetFriendid()) | ||||
| 		if id == s.client.SteamId() { //this is our client id | ||||
| 		if id == s.client.SteamId() { // this is our client id | ||||
| 			s.mutex.Lock() | ||||
| 			if friend.GetPlayerName() != "" { | ||||
| 				s.name = friend.GetPlayerName() | ||||
| @@ -364,7 +364,6 @@ func (s *Social) handlePersonaState(packet *Packet) { | ||||
| 			ClanRank:               friend.GetClanRank(), | ||||
| 			ClanTag:                friend.GetClanTag(), | ||||
| 			OnlineSessionInstances: friend.GetOnlineSessionInstances(), | ||||
| 			PublishedSessionId:     friend.GetPublishedInstanceId(), | ||||
| 			PersonaSetByUser:       friend.GetPersonaSetByUser(), | ||||
| 		}) | ||||
| 	} | ||||
| @@ -407,7 +406,7 @@ func (s *Social) handleClanState(packet *Packet) { | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| 	//Add stuff to group | ||||
| 	// Add stuff to group | ||||
| 	clanid := SteamId(body.GetSteamidClan()) | ||||
| 	if body.NameInfo != nil { | ||||
| 		info := body.NameInfo | ||||
| @@ -473,14 +472,14 @@ func (s *Social) handleChatEnter(packet *Packet) { | ||||
| 	payload := packet.ReadClientMsg(body).Payload | ||||
| 	reader := bytes.NewBuffer(payload) | ||||
| 	name, _ := ReadString(reader) | ||||
| 	ReadByte(reader) //0 | ||||
| 	ReadByte(reader) // 0 | ||||
| 	count := body.NumMembers | ||||
| 	chatId := SteamId(body.SteamIdChat) | ||||
| 	clanId := SteamId(body.SteamIdClan) | ||||
| 	s.Chats.Add(socialcache.Chat{SteamId: chatId, GroupId: clanId}) | ||||
| 	for i := 0; i < int(count); i++ { | ||||
| 		id, chatPerm, clanPerm := readChatMember(reader) | ||||
| 		ReadBytes(reader, 6) //No idea what this is | ||||
| 		ReadBytes(reader, 6) // No idea what this is | ||||
| 		s.Chats.AddChatMember(chatId, socialcache.ChatMember{ | ||||
| 			SteamId:         SteamId(id), | ||||
| 			ChatPermissions: chatPerm, | ||||
| @@ -508,7 +507,7 @@ func (s *Social) handleChatMemberInfo(packet *Packet) { | ||||
| 		actedOn, _ := ReadUint64(reader) | ||||
| 		state, _ := ReadInt32(reader) | ||||
| 		actedBy, _ := ReadUint64(reader) | ||||
| 		ReadByte(reader) //0 | ||||
| 		ReadByte(reader) // 0 | ||||
| 		stateChange := EChatMemberStateChange(state) | ||||
| 		if stateChange == EChatMemberStateChange_Entered { | ||||
| 			_, chatPerm, clanPerm := readChatMember(reader) | ||||
| @@ -537,13 +536,13 @@ func (s *Social) handleChatMemberInfo(packet *Packet) { | ||||
| func readChatMember(r io.Reader) (SteamId, EChatPermission, EClanPermission) { | ||||
| 	ReadString(r) // MessageObject | ||||
| 	ReadByte(r)   // 7 | ||||
| 	ReadString(r) //steamid | ||||
| 	ReadString(r) // steamid | ||||
| 	id, _ := ReadUint64(r) | ||||
| 	ReadByte(r)   // 2 | ||||
| 	ReadString(r) //Permissions | ||||
| 	ReadString(r) // Permissions | ||||
| 	chat, _ := ReadInt32(r) | ||||
| 	ReadByte(r)   // 2 | ||||
| 	ReadString(r) //Details | ||||
| 	ReadString(r) // Details | ||||
| 	clan, _ := ReadInt32(r) | ||||
| 	return SteamId(id), EChatPermission(chat), EClanPermission(clan) | ||||
| } | ||||
|   | ||||
							
								
								
									
										1
									
								
								vendor/github.com/Philipp15b/go-steam/social_events.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/Philipp15b/go-steam/social_events.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -48,7 +48,6 @@ type PersonaStateEvent struct { | ||||
| 	ClanRank               uint32 | ||||
| 	ClanTag                string | ||||
| 	OnlineSessionInstances uint32 | ||||
| 	PublishedSessionId     uint32 | ||||
| 	PersonaSetByUser       bool | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										4
									
								
								vendor/github.com/Rhymen/go-whatsapp/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/Rhymen/go-whatsapp/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -74,6 +74,10 @@ func (myHandler) HandleBatteryMessage(msg whatsapp.BatteryMessage) { | ||||
| 	fmt.Println(message) | ||||
| } | ||||
|  | ||||
| func (myHandler) HandleNewContact(contact whatsapp.Contact) { | ||||
| 	fmt.Println(contact) | ||||
| } | ||||
|  | ||||
| wac.AddHandler(myHandler{}) | ||||
| ``` | ||||
| The message handlers are all optional, you don't need to implement anything but the error handler to implement the interface. The ImageMessage, VideoMessage, AudioMessage and DocumentMessage provide a Download function to get the media data. | ||||
|   | ||||
							
								
								
									
										5
									
								
								vendor/github.com/Rhymen/go-whatsapp/binary/token/token.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/Rhymen/go-whatsapp/binary/token/token.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -24,7 +24,10 @@ var SingleByteTokens = [...]string{"", "", "", "200", "400", "404", "500", "501" | ||||
| 	"invite", "gif", "vcard", "frequent", "privacy", "blacklist", "whitelist", | ||||
| 	"verify", "location", "document", "elapsed", "revoke_invite", "expiration", | ||||
| 	"unsubscribe", "disable", "vname", "old_jid", "new_jid", "announcement", | ||||
| 	"locked", "prop", "label", "color", "call", "offer", "call-id"} | ||||
| 	"locked", "prop", "label", "color", "call", "offer", "call-id", | ||||
| 	"quick_reply", "sticker", "pay_t", "accept", "reject", "sticker_pack", | ||||
| 	"invalid", "canceled", "missed", "connected", "result", "audio", | ||||
| 	"video", "recent"} | ||||
|  | ||||
| var doubleByteTokens = [...]string{} | ||||
|  | ||||
|   | ||||
							
								
								
									
										82
									
								
								vendor/github.com/Rhymen/go-whatsapp/conn.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										82
									
								
								vendor/github.com/Rhymen/go-whatsapp/conn.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -116,31 +116,59 @@ Creates a new connection with a given timeout. The websocket connection to the W | ||||
| The goroutine for handling incoming messages is started | ||||
| */ | ||||
| func NewConn(timeout time.Duration) (*Conn, error) { | ||||
| 	wac := &Conn{ | ||||
| 		handler:    make([]Handler, 0), | ||||
| 		msgCount:   0, | ||||
| 		msgTimeout: timeout, | ||||
| 		Store:      newStore(), | ||||
|  | ||||
| 		longClientName:  "github.com/rhymen/go-whatsapp", | ||||
| 		shortClientName: "go-whatsapp", | ||||
| 		clientVersion:   "0.1.0", | ||||
| 	} | ||||
| 	return wac, wac.connect() | ||||
| 	return NewConnWithOptions(&Options{ | ||||
| 		Timeout: timeout, | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // NewConnWithProxy Create a new connect with a given timeout and a http proxy. | ||||
| func NewConnWithProxy(timeout time.Duration, proxy func(*http.Request) (*url.URL, error)) (*Conn, error) { | ||||
| 	return NewConnWithOptions(&Options{ | ||||
| 		Timeout: timeout, | ||||
| 		Proxy: proxy, | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // NewConnWithOptions Create a new connect with a given options. | ||||
| type Options struct { | ||||
| 	Proxy            func(*http.Request) (*url.URL, error) | ||||
| 	Timeout          time.Duration | ||||
| 	Handler          []Handler | ||||
| 	ShortClientName  string | ||||
| 	LongClientName   string | ||||
| 	ClientVersion    string | ||||
| 	Store            *Store | ||||
| } | ||||
| func NewConnWithOptions(opt *Options) (*Conn, error) { | ||||
| 	if opt == nil { | ||||
| 		return nil, ErrOptionsNotProvided | ||||
| 	} | ||||
| 	wac := &Conn{ | ||||
| 		handler:    make([]Handler, 0), | ||||
| 		msgCount:   0, | ||||
| 		msgTimeout: timeout, | ||||
| 		msgTimeout: opt.Timeout, | ||||
| 		Store:      newStore(), | ||||
|  | ||||
| 		longClientName:  "github.com/rhymen/go-whatsapp", | ||||
| 		longClientName:  "github.com/Rhymen/go-whatsapp", | ||||
| 		shortClientName: "go-whatsapp", | ||||
| 		clientVersion:   "0.1.0", | ||||
| 		Proxy:           proxy, | ||||
| 	} | ||||
| 	if opt.Handler != nil { | ||||
| 		wac.handler = opt.Handler | ||||
| 	} | ||||
| 	if opt.Store != nil { | ||||
| 		wac.Store = opt.Store | ||||
| 	} | ||||
| 	if opt.Proxy != nil { | ||||
| 		wac.Proxy = opt.Proxy | ||||
| 	} | ||||
| 	if len(opt.ShortClientName) != 0 { | ||||
| 		wac.shortClientName = opt.ShortClientName | ||||
| 	} | ||||
| 	if len(opt.LongClientName) != 0 { | ||||
| 		wac.longClientName = opt.LongClientName | ||||
| 	} | ||||
| 	if len(opt.ClientVersion) != 0 { | ||||
| 		wac.clientVersion = opt.ClientVersion | ||||
| 	} | ||||
| 	return wac, wac.connect() | ||||
| } | ||||
| @@ -249,10 +277,26 @@ func (wac *Conn) keepAlive(minIntervalMs int, maxIntervalMs int) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (wac *Conn) GetConnected() bool { | ||||
| 	return  wac.connected | ||||
| // IsConnected returns whether the server connection is established or not | ||||
| func (wac *Conn) IsConnected() bool { | ||||
| 	return wac.connected | ||||
| } | ||||
|  | ||||
| func (wac *Conn) GetLoggedIn() bool { | ||||
| 	return  wac.loggedIn | ||||
| // GetConnected returns whether the server connection is established or not | ||||
| // | ||||
| // Deprecated: function name is not go idiomatic, use IsConnected instead | ||||
| func (wac *Conn) GetConnected() bool { | ||||
| 	return wac.connected | ||||
| } | ||||
|  | ||||
| //IsLoggedIn returns whether the you are logged in or not | ||||
| func (wac *Conn) IsLoggedIn() bool { | ||||
| 	return wac.loggedIn | ||||
| } | ||||
|  | ||||
| // GetLoggedIn returns whether the you are logged in or not | ||||
| // | ||||
| // Deprecated: function name is not go idiomatic, use IsLoggedIn instead. | ||||
| func (wac *Conn) GetLoggedIn() bool { | ||||
| 	return wac.loggedIn | ||||
| } | ||||
|   | ||||
							
								
								
									
										47
									
								
								vendor/github.com/Rhymen/go-whatsapp/contact.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										47
									
								
								vendor/github.com/Rhymen/go-whatsapp/contact.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -2,9 +2,11 @@ package whatsapp | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"github.com/Rhymen/go-whatsapp/binary" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/Rhymen/go-whatsapp/binary" | ||||
| ) | ||||
|  | ||||
| type Presence string | ||||
| @@ -241,3 +243,46 @@ func buildParticipantNodes(participants []string) []binary.Node { | ||||
| 	} | ||||
| 	return p | ||||
| } | ||||
|  | ||||
| func (wac *Conn) BlockContact(jid string) (<-chan string, error) { | ||||
| 	return wac.handleBlockContact("add", jid) | ||||
| } | ||||
|  | ||||
| func (wac *Conn) UnblockContact(jid string) (<-chan string, error) { | ||||
| 	return wac.handleBlockContact("remove", jid) | ||||
| } | ||||
|  | ||||
| func (wac *Conn) handleBlockContact(action, jid string) (<-chan string, error) { | ||||
| 	ts := time.Now().Unix() | ||||
| 	tag := fmt.Sprintf("%d.--%d", ts, wac.msgCount) | ||||
|  | ||||
| 	netsplit := strings.Split(jid, "@") | ||||
| 	cusjid := netsplit[0] + "@c.us" | ||||
|  | ||||
| 	n := binary.Node{ | ||||
| 		Description: "action", | ||||
| 		Attributes: map[string]string{ | ||||
| 			"type":  "set", | ||||
| 			"epoch": strconv.Itoa(wac.msgCount), | ||||
| 		}, | ||||
| 		Content: []interface{}{ | ||||
| 			binary.Node{ | ||||
| 				Description: "block", | ||||
| 				Attributes: map[string]string{ | ||||
| 					"type": action, | ||||
| 				}, | ||||
| 				Content: []binary.Node{ | ||||
| 					{ | ||||
| 						Description: "user", | ||||
| 						Attributes: map[string]string{ | ||||
| 							"jid": cusjid, | ||||
| 						}, | ||||
| 						Content: nil, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	return wac.writeBinary(n, contact, ignore, tag) | ||||
| } | ||||
|   | ||||
							
								
								
									
										30
									
								
								vendor/github.com/Rhymen/go-whatsapp/errors.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/Rhymen/go-whatsapp/errors.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -7,21 +7,21 @@ import ( | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	ErrAlreadyConnected           = errors.New("already connected") | ||||
| 	ErrAlreadyLoggedIn            = errors.New("already logged in") | ||||
| 	ErrInvalidSession             = errors.New("invalid session") | ||||
| 	ErrLoginInProgress            = errors.New("login or restore already running") | ||||
| 	ErrNotConnected               = errors.New("not connected") | ||||
| 	ErrInvalidWsData              = errors.New("received invalid data") | ||||
| 	ErrInvalidWsState             = errors.New("can't handle binary data when not logged in") | ||||
| 	ErrConnectionTimeout          = errors.New("connection timed out") | ||||
| 	ErrMissingMessageTag          = errors.New("no messageTag specified or to short") | ||||
| 	ErrInvalidHmac                = errors.New("invalid hmac") | ||||
| 	ErrInvalidServerResponse      = errors.New("invalid response received from server") | ||||
| 	ErrServerRespondedWith404     = errors.New("server responded with status 404") | ||||
| 	ErrMediaDownloadFailedWith404 = errors.New("download failed with status code 404") | ||||
| 	ErrMediaDownloadFailedWith410 = errors.New("download failed with status code 410") | ||||
| 	ErrInvalidWebsocket           = errors.New("invalid websocket") | ||||
| 	ErrAlreadyConnected          = errors.New("already connected") | ||||
| 	ErrAlreadyLoggedIn           = errors.New("already logged in") | ||||
| 	ErrInvalidSession            = errors.New("invalid session") | ||||
| 	ErrLoginInProgress           = errors.New("login or restore already running") | ||||
| 	ErrNotConnected              = errors.New("not connected") | ||||
| 	ErrInvalidWsData             = errors.New("received invalid data") | ||||
| 	ErrInvalidWsState            = errors.New("can't handle binary data when not logged in") | ||||
| 	ErrConnectionTimeout         = errors.New("connection timed out") | ||||
| 	ErrMissingMessageTag         = errors.New("no messageTag specified or to short") | ||||
| 	ErrInvalidHmac               = errors.New("invalid hmac") | ||||
| 	ErrInvalidServerResponse     = errors.New("invalid response received from server") | ||||
| 	ErrServerRespondedWith404    = errors.New("server responded with status 404") | ||||
| 	ErrInvalidWebsocket          = errors.New("invalid websocket") | ||||
| 	ErrMessageTypeNotImplemented = errors.New("message type not implemented") | ||||
| 	ErrOptionsNotProvided        = errors.New("new conn options not provided") | ||||
| ) | ||||
|  | ||||
| type ErrConnectionFailed struct { | ||||
|   | ||||
							
								
								
									
										1
									
								
								vendor/github.com/Rhymen/go-whatsapp/go.sum
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/Rhymen/go-whatsapp/go.sum
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -32,5 +32,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6Zh | ||||
| golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= | ||||
| golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= | ||||
|   | ||||
							
								
								
									
										23
									
								
								vendor/github.com/Rhymen/go-whatsapp/handler.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/Rhymen/go-whatsapp/handler.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -141,6 +141,14 @@ type BatteryMessageHandler interface { | ||||
| 	HandleBatteryMessage(battery BatteryMessage) | ||||
| } | ||||
|  | ||||
| /** | ||||
| The NewContactHandler interface needs to be implemented to receive the contact's name for the first time. | ||||
| */ | ||||
| type NewContactHandler interface { | ||||
| 	Handler | ||||
| 	HandleNewContact(contact Contact) | ||||
| } | ||||
|  | ||||
| /* | ||||
| AddHandler adds an handler to the list of handler that receive dispatched messages. | ||||
| The provided handler must at least implement the Handler interface. Additionally implemented | ||||
| @@ -304,6 +312,17 @@ func (wac *Conn) handleWithCustomHandlers(message interface{}, handlers []Handle | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	 | ||||
| 	case Contact: | ||||
| 		for _, h := range handlers { | ||||
| 			if x, ok := h.(NewContactHandler); ok { | ||||
| 				if wac.shouldCallSynchronously(h) { | ||||
| 					x.HandleNewContact(m) | ||||
| 				} else { | ||||
| 					go x.HandleNewContact(m) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 	case *proto.WebMessageInfo: | ||||
| 		for _, h := range handlers { | ||||
| @@ -397,6 +416,10 @@ func (wac *Conn) dispatch(msg interface{}) { | ||||
| 						wac.handle(v) | ||||
| 						wac.handle(ParseProtoMessage(v)) | ||||
| 					} | ||||
|  | ||||
| 					if v, ok := con[a].(binary.Node); ok { | ||||
| 						wac.handle(ParseNodeMessage(v)) | ||||
| 					} | ||||
| 				} | ||||
| 			} else if con, ok := message.Content.([]binary.Node); ok { | ||||
| 				for a := range con { | ||||
|   | ||||
							
								
								
									
										65
									
								
								vendor/github.com/Rhymen/go-whatsapp/media.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										65
									
								
								vendor/github.com/Rhymen/go-whatsapp/media.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -10,6 +10,7 @@ import ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"net" | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| 	"time" | ||||
| @@ -38,7 +39,7 @@ func Download(url string, mediaKey []byte, appInfo MediaType, fileLength int) ([ | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if len(data) != fileLength { | ||||
| 		return nil, fmt.Errorf("file length does not match") | ||||
| 		return nil, fmt.Errorf("file length does not match. Expected: %v, got: %v", fileLength, len(data)) | ||||
| 	} | ||||
| 	return data, nil | ||||
| } | ||||
| @@ -71,16 +72,10 @@ func downloadMedia(url string) (file []byte, mac []byte, err error) { | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	if resp.StatusCode != 200 { | ||||
| 		if resp.StatusCode == 404 { | ||||
| 			return nil, nil, ErrMediaDownloadFailedWith404 | ||||
| 		} | ||||
| 		if resp.StatusCode == 410 { | ||||
| 			return nil, nil, ErrMediaDownloadFailedWith410 | ||||
| 		} | ||||
| 	defer resp.Body.Close() | ||||
| 	if resp.StatusCode != http.StatusOK { | ||||
| 		return nil, nil, fmt.Errorf("download failed with status code %d", resp.StatusCode) | ||||
| 	} | ||||
| 	defer resp.Body.Close() | ||||
| 	if resp.ContentLength <= 10 { | ||||
| 		return nil, nil, fmt.Errorf("file to short") | ||||
| 	} | ||||
| @@ -93,21 +88,21 @@ func downloadMedia(url string) (file []byte, mac []byte, err error) { | ||||
| 	return data[:n-10], data[n-10 : n], nil | ||||
| } | ||||
|  | ||||
|                                                                                  | ||||
| type MediaConn struct {                                                          | ||||
|         Status int `json:"status"`                                               | ||||
|         MediaConn struct {                                                       | ||||
|                 Auth string `json:"auth"`                                        | ||||
|                 TTL int `json:"ttl"`                                             | ||||
|                 Hosts []struct {                                                 | ||||
|                         Hostname string `json:"hostname"`                        | ||||
|                         IPs []interface{}  `json:"ips"`                                               | ||||
|                 } `json:"hosts"`                                                 | ||||
|         } `json:"media_conn"`                                                    | ||||
| type MediaConn struct { | ||||
| 	Status    int `json:"status"` | ||||
| 	MediaConn struct { | ||||
| 		Auth  string `json:"auth"` | ||||
| 		TTL   int    `json:"ttl"` | ||||
| 		Hosts []struct { | ||||
| 			Hostname string `json:"hostname"` | ||||
| 			IPs      []struct { | ||||
| 				IP4 net.IP `json:"ip4"` | ||||
| 				IP6 net.IP `json:"ip6"` | ||||
| 			} `json:"ips"` | ||||
| 		} `json:"hosts"` | ||||
| 	} `json:"media_conn"` | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| func (wac *Conn) queryMediaConn() (hostname, auth string, ttl int, err error) { | ||||
| 	queryReq := []interface{}{"query", "mediaConn"} | ||||
| 	ch, err := wac.writeJson(queryReq) | ||||
| @@ -125,18 +120,24 @@ func (wac *Conn) queryMediaConn() (hostname, auth string, ttl int, err error) { | ||||
| 		return "", "", 0, fmt.Errorf("query media conn timed out") | ||||
| 	} | ||||
|  | ||||
| 	if resp.Status != 200 { | ||||
| 	if resp.Status != http.StatusOK { | ||||
| 		return "", "", 0, fmt.Errorf("query media conn responded with %d", resp.Status) | ||||
| 	} | ||||
|  | ||||
| 	return resp.MediaConn.Hosts[0].Hostname, resp.MediaConn.Auth, resp.MediaConn.TTL, nil | ||||
| 	for _, h := range resp.MediaConn.Hosts { | ||||
| 		if h.Hostname != "" { | ||||
| 			return h.Hostname, resp.MediaConn.Auth, resp.MediaConn.TTL, nil | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return "", "", 0, fmt.Errorf("query media conn responded with no host") | ||||
| } | ||||
|  | ||||
| var mediaTypeMap = map[MediaType]string{ | ||||
| 	MediaImage: "/mms/image", | ||||
| 	MediaVideo: "/mms/video", | ||||
| 	MediaImage:    "/mms/image", | ||||
| 	MediaVideo:    "/mms/video", | ||||
| 	MediaDocument: "/mms/document", | ||||
| 	MediaAudio: "/mms/audio", | ||||
| 	MediaAudio:    "/mms/audio", | ||||
| } | ||||
|  | ||||
| func (wac *Conn) Upload(reader io.Reader, appInfo MediaType) (downloadURL string, mediaKey []byte, fileEncSha256 []byte, fileSha256 []byte, fileLength uint64, err error) { | ||||
| @@ -173,6 +174,10 @@ func (wac *Conn) Upload(reader io.Reader, appInfo MediaType) (downloadURL string | ||||
| 	fileEncSha256 = sha.Sum(nil) | ||||
|  | ||||
| 	hostname, auth, _, err := wac.queryMediaConn() | ||||
| 	if err != nil { | ||||
| 		return "", nil, nil, nil, 0, err | ||||
| 	} | ||||
|  | ||||
| 	token := base64.URLEncoding.EncodeToString(fileEncSha256) | ||||
| 	q := url.Values{ | ||||
| 		"auth":  []string{auth}, | ||||
| @@ -188,7 +193,7 @@ func (wac *Conn) Upload(reader io.Reader, appInfo MediaType) (downloadURL string | ||||
|  | ||||
| 	body := bytes.NewReader(append(enc, mac...)) | ||||
|  | ||||
| 	req, err := http.NewRequest("POST", uploadURL.String(), body) | ||||
| 	req, err := http.NewRequest(http.MethodPost, uploadURL.String(), body) | ||||
| 	if err != nil { | ||||
| 		return "", nil, nil, nil, 0, err | ||||
| 	} | ||||
| @@ -208,7 +213,9 @@ func (wac *Conn) Upload(reader io.Reader, appInfo MediaType) (downloadURL string | ||||
| 	} | ||||
|  | ||||
| 	var jsonRes map[string]string | ||||
| 	json.NewDecoder(res.Body).Decode(&jsonRes) | ||||
| 	if err := json.NewDecoder(res.Body).Decode(&jsonRes); err != nil { | ||||
| 		return "", nil, nil, nil, 0, err | ||||
| 	} | ||||
|  | ||||
| 	return jsonRes["url"], mediaKey, fileEncSha256, fileSha256, fileLength, nil | ||||
| } | ||||
|   | ||||
							
								
								
									
										25
									
								
								vendor/github.com/Rhymen/go-whatsapp/message.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/Rhymen/go-whatsapp/message.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -238,7 +238,7 @@ func getMessageInfo(msg *proto.WebMessageInfo) MessageInfo { | ||||
| 	return MessageInfo{ | ||||
| 		Id:        msg.GetKey().GetId(), | ||||
| 		RemoteJid: msg.GetKey().GetRemoteJid(), | ||||
| 		SenderJid: msg.GetKey().GetParticipant(), | ||||
| 		SenderJid: msg.GetParticipant(), | ||||
| 		FromMe:    msg.GetKey().GetFromMe(), | ||||
| 		Timestamp: msg.GetMessageTimestamp(), | ||||
| 		Status:    MessageStatus(msg.GetStatus()), | ||||
| @@ -838,19 +838,16 @@ func ParseProtoMessage(msg *proto.WebMessageInfo) interface{} { | ||||
|  | ||||
| 	default: | ||||
| 		//cannot match message | ||||
|  | ||||
| 		return ErrMessageTypeNotImplemented | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
| BatteryMessage represents a battery level and charging state. | ||||
| */ | ||||
| type BatteryMessage struct { | ||||
| 	Plugged bool | ||||
| 	Powersave bool | ||||
| 	Plugged    bool | ||||
| 	Powersave  bool | ||||
| 	Percentage int | ||||
| } | ||||
|  | ||||
| @@ -859,19 +856,29 @@ func getBatteryMessage(msg map[string]string) BatteryMessage { | ||||
| 	powersave, _ := strconv.ParseBool(msg["powersave"]) | ||||
| 	percentage, _ := strconv.Atoi(msg["value"]) | ||||
| 	batteryMessage := BatteryMessage{ | ||||
| 		Plugged: plugged, | ||||
| 		Powersave: powersave, | ||||
| 		Plugged:    plugged, | ||||
| 		Powersave:  powersave, | ||||
| 		Percentage: percentage, | ||||
| 	} | ||||
|  | ||||
| 	return batteryMessage | ||||
| } | ||||
|  | ||||
| func getNewContact(msg map[string]string) Contact { | ||||
| 	contact := Contact{ | ||||
| 		Jid:    msg["jid"], | ||||
| 		Notify: msg["notify"], | ||||
| 	} | ||||
|  | ||||
| 	return contact | ||||
| } | ||||
|  | ||||
| func ParseNodeMessage(msg binary.Node) interface{} { | ||||
| 	switch msg.Description { | ||||
| 	case "battery": | ||||
| 		return getBatteryMessage(msg.Attributes) | ||||
| 	case "user": | ||||
| 		return getNewContact(msg.Attributes) | ||||
| 	default: | ||||
| 		//cannot match message | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										21
									
								
								vendor/github.com/Rhymen/go-whatsapp/read.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/Rhymen/go-whatsapp/read.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -7,6 +7,7 @@ import ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"net/http" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/Rhymen/go-whatsapp/binary" | ||||
| @@ -62,6 +63,10 @@ func (wac *Conn) processReadData(msgType int, msg []byte) error { | ||||
| 		data[0] = "!" | ||||
| 	} | ||||
|  | ||||
| 	if len(data) == 2 && len(data[1]) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	if len(data) != 2 || len(data[1]) == 0 { | ||||
| 		return ErrInvalidWsData | ||||
| 	} | ||||
| @@ -78,10 +83,8 @@ func (wac *Conn) processReadData(msgType int, msg []byte) error { | ||||
| 		// chan string to something like chan map[string]interface{}. The unmarshalling | ||||
| 		// in several places, especially in session.go, would then be gone. | ||||
| 		listener <- data[1] | ||||
|  | ||||
| 		wac.listener.Lock() | ||||
| 		delete(wac.listener.m, data[0]) | ||||
| 		wac.listener.Unlock() | ||||
| 		close(listener) | ||||
| 		wac.removeListener(data[0]) | ||||
| 	} else if msgType == websocket.BinaryMessage { | ||||
| 		wac.loginSessionLock.RLock() | ||||
| 		sess := wac.session | ||||
| @@ -107,16 +110,16 @@ func (wac *Conn) decryptBinaryMessage(msg []byte) (*binary.Node, error) { | ||||
| 		var response struct { | ||||
| 			Status int `json:"status"` | ||||
| 		} | ||||
| 		err := json.Unmarshal(msg, &response) | ||||
| 		if err == nil { | ||||
| 			if response.Status == 404 { | ||||
|  | ||||
| 		if err := json.Unmarshal(msg, &response); err == nil { | ||||
| 			if response.Status == http.StatusNotFound { | ||||
| 				return nil, ErrServerRespondedWith404 | ||||
| 			} | ||||
| 			return nil, errors.New(fmt.Sprintf("server responded with %d", response.Status)) | ||||
| 		} else { | ||||
| 			return nil, ErrInvalidServerResponse | ||||
| 		} | ||||
|  | ||||
| 		return nil, ErrInvalidServerResponse | ||||
|  | ||||
| 	} | ||||
| 	h2.Write([]byte(msg[32:])) | ||||
| 	if !hmac.Equal(h2.Sum(nil), msg[:32]) { | ||||
|   | ||||
							
								
								
									
										6
									
								
								vendor/github.com/Rhymen/go-whatsapp/session.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/Rhymen/go-whatsapp/session.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -18,7 +18,7 @@ import ( | ||||
| ) | ||||
|  | ||||
| //represents the WhatsAppWeb client version | ||||
| var waVersion = []int{2, 2033, 7} | ||||
| var waVersion = []int{2, 2039, 9} | ||||
|  | ||||
| /* | ||||
| Session contains session individual information. To be able to resume the connection without scanning the qr code | ||||
| @@ -141,11 +141,11 @@ func CheckCurrentServerVersion() ([]int, error) { | ||||
| SetClientName sets the long and short client names that are sent to WhatsApp when logging in and displayed in the | ||||
| WhatsApp Web device list. As the values are only sent when logging in, changing them after logging in is not possible. | ||||
| */ | ||||
| func (wac *Conn) SetClientName(long, short string) error { | ||||
| func (wac *Conn) SetClientName(long, short string, version string) error { | ||||
| 	if wac.session != nil && (wac.session.EncKey != nil || wac.session.MacKey != nil) { | ||||
| 		return fmt.Errorf("cannot change client name after logging in") | ||||
| 	} | ||||
| 	wac.longClientName, wac.shortClientName = long, short | ||||
| 	wac.longClientName, wac.shortClientName, wac.clientVersion = long, short, version | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										73
									
								
								vendor/github.com/Rhymen/go-whatsapp/write.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										73
									
								
								vendor/github.com/Rhymen/go-whatsapp/write.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -15,15 +15,30 @@ import ( | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
|  | ||||
| func (wac *Conn) addListener(ch chan string, messageTag string) { | ||||
| 	wac.listener.Lock() | ||||
| 	wac.listener.m[messageTag] = ch | ||||
| 	wac.listener.Unlock() | ||||
| } | ||||
|  | ||||
| func (wac *Conn) removeListener(answerMessageTag string) { | ||||
| 	wac.listener.Lock() | ||||
| 	delete(wac.listener.m, answerMessageTag) | ||||
| 	wac.listener.Unlock() | ||||
| } | ||||
|  | ||||
| //writeJson enqueues a json message into the writeChan | ||||
| func (wac *Conn) writeJson(data []interface{}) (<-chan string, error) { | ||||
|  | ||||
| 	ch := make(chan string, 1) | ||||
|  | ||||
| 	wac.writerLock.Lock() | ||||
| 	defer wac.writerLock.Unlock() | ||||
|  | ||||
| 	d, err := json.Marshal(data) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 		close(ch) | ||||
| 		return ch, err | ||||
| 	} | ||||
|  | ||||
| 	ts := time.Now().Unix() | ||||
| @@ -35,9 +50,13 @@ func (wac *Conn) writeJson(data []interface{}) (<-chan string, error) { | ||||
| 		wac.timeTag = tss[len(tss)-3:] | ||||
| 	} | ||||
|  | ||||
| 	ch, err := wac.write(websocket.TextMessage, messageTag, bytes) | ||||
| 	wac.addListener(ch, messageTag) | ||||
|  | ||||
| 	err = wac.write(websocket.TextMessage, bytes) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 		close(ch) | ||||
| 		wac.removeListener(messageTag) | ||||
| 		return ch, err | ||||
| 	} | ||||
|  | ||||
| 	wac.msgCount++ | ||||
| @@ -45,8 +64,12 @@ func (wac *Conn) writeJson(data []interface{}) (<-chan string, error) { | ||||
| } | ||||
|  | ||||
| func (wac *Conn) writeBinary(node binary.Node, metric metric, flag flag, messageTag string) (<-chan string, error) { | ||||
|  | ||||
| 	ch := make(chan string, 1) | ||||
|  | ||||
| 	if len(messageTag) < 2 { | ||||
| 		return nil, ErrMissingMessageTag | ||||
| 		close(ch) | ||||
| 		return ch, ErrMissingMessageTag | ||||
| 	} | ||||
|  | ||||
| 	wac.writerLock.Lock() | ||||
| @@ -54,16 +77,21 @@ func (wac *Conn) writeBinary(node binary.Node, metric metric, flag flag, message | ||||
|  | ||||
| 	data, err := wac.encryptBinaryMessage(node) | ||||
| 	if err != nil { | ||||
| 		return nil, errors.Wrap(err, "encryptBinaryMessage(node) failed") | ||||
| 		close(ch) | ||||
| 		return ch, errors.Wrap(err, "encryptBinaryMessage(node) failed") | ||||
| 	} | ||||
|  | ||||
| 	bytes := []byte(messageTag + ",") | ||||
| 	bytes = append(bytes, byte(metric), byte(flag)) | ||||
| 	bytes = append(bytes, data...) | ||||
|  | ||||
| 	ch, err := wac.write(websocket.BinaryMessage, messageTag, bytes) | ||||
| 	wac.addListener(ch, messageTag) | ||||
|  | ||||
| 	err = wac.write(websocket.BinaryMessage, bytes) | ||||
| 	if err != nil { | ||||
| 		return nil, errors.Wrap(err, "failed to write message") | ||||
| 		close(ch) | ||||
| 		wac.removeListener(messageTag) | ||||
| 		return ch, errors.Wrap(err, "failed to write message") | ||||
| 	} | ||||
|  | ||||
| 	wac.msgCount++ | ||||
| @@ -71,9 +99,15 @@ func (wac *Conn) writeBinary(node binary.Node, metric metric, flag flag, message | ||||
| } | ||||
|  | ||||
| func (wac *Conn) sendKeepAlive() error { | ||||
|  | ||||
| 	respChan := make(chan string, 1) | ||||
| 	wac.addListener(respChan, "!") | ||||
|  | ||||
| 	bytes := []byte("?,,") | ||||
| 	respChan, err := wac.write(websocket.TextMessage, "!", bytes) | ||||
| 	err := wac.write(websocket.TextMessage, bytes) | ||||
| 	if err != nil { | ||||
| 		close(respChan) | ||||
| 		wac.removeListener("!") | ||||
| 		return errors.Wrap(err, "error sending keepAlive") | ||||
| 	} | ||||
|  | ||||
| @@ -122,32 +156,21 @@ func (wac *Conn) sendAdminTest() (bool, error) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (wac *Conn) write(messageType int, answerMessageTag string, data []byte) (<-chan string, error) { | ||||
| 	var ch chan string | ||||
| 	if answerMessageTag != "" { | ||||
| 		ch = make(chan string, 1) | ||||
|  | ||||
| 		wac.listener.Lock() | ||||
| 		wac.listener.m[answerMessageTag] = ch | ||||
| 		wac.listener.Unlock() | ||||
| 	} | ||||
| func (wac *Conn) write(messageType int, data []byte) error { | ||||
|  | ||||
| 	if wac == nil || wac.ws == nil { | ||||
| 		return nil, ErrInvalidWebsocket | ||||
| 		return ErrInvalidWebsocket | ||||
| 	} | ||||
|  | ||||
| 	wac.ws.Lock() | ||||
| 	err := wac.ws.conn.WriteMessage(messageType, data) | ||||
| 	wac.ws.Unlock() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		if answerMessageTag != "" { | ||||
| 			wac.listener.Lock() | ||||
| 			delete(wac.listener.m, answerMessageTag) | ||||
| 			wac.listener.Unlock() | ||||
| 		} | ||||
| 		return nil, errors.Wrap(err, "error writing to websocket") | ||||
| 		return errors.Wrap(err, "error writing to websocket") | ||||
| 	} | ||||
| 	return ch, nil | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (wac *Conn) encryptBinaryMessage(node binary.Node) (data []byte, err error) { | ||||
|   | ||||
							
								
								
									
										5
									
								
								vendor/github.com/SevereCloud/vksdk/v2/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/SevereCloud/vksdk/v2/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| _vendor/ | ||||
| vendor/ | ||||
| *.out | ||||
| coverage.txt | ||||
| *.test | ||||
							
								
								
									
										84
									
								
								vendor/github.com/SevereCloud/vksdk/v2/.golangci.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								vendor/github.com/SevereCloud/vksdk/v2/.golangci.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| --- | ||||
| linters: | ||||
|   disable-all: true | ||||
|   enable: | ||||
|     - bodyclose | ||||
|     - deadcode | ||||
|     - errcheck | ||||
|     - gochecknoglobals | ||||
|     - goconst | ||||
|     - gocritic | ||||
|     - gofmt | ||||
|     - goimports | ||||
|     - golint | ||||
|     - goprintffuncname | ||||
|     - gosec | ||||
|     - gosimple | ||||
|     - govet | ||||
|     - ineffassign | ||||
|     - interfacer | ||||
|     - maligned | ||||
|     - misspell | ||||
|     - nakedret | ||||
|     - prealloc | ||||
|     - staticcheck | ||||
|     - structcheck | ||||
|     - stylecheck | ||||
|     - typecheck | ||||
|     - unconvert | ||||
|     - unparam | ||||
|     - unused | ||||
|     - varcheck | ||||
|     - whitespace | ||||
|     - wsl | ||||
|     - godot | ||||
|     - asciicheck | ||||
|     - nolintlint | ||||
|     - gofumpt | ||||
|     - goerr113 | ||||
|     - tparallel | ||||
|     - errorlint | ||||
|     - paralleltest | ||||
|  | ||||
| # - wrapcheck # TODO: v3 Fix | ||||
| # - testpackage # TODO: Fix testpackage | ||||
| # - nestif # TODO: Fix nestif | ||||
|  | ||||
| # don't enable: | ||||
| # - depguard | ||||
| # - dogsled | ||||
| # - dupl | ||||
| # - funlen | ||||
| # - gochecknoinits | ||||
| # - gocognit | ||||
| # - gocyclo | ||||
| # - godox | ||||
| # - gomnd | ||||
| # - lll | ||||
| # - rowserrcheck | ||||
| # - scopelint | ||||
| # - gomodguard | ||||
| # - exhaustive | ||||
| # - nlreturn | ||||
| # - gci | ||||
| # - exhaustivestruct | ||||
|  | ||||
| issues: | ||||
|   exclude-rules: | ||||
|     - path: _test\.go | ||||
|       linters: | ||||
|         - gocyclo | ||||
|         - errcheck | ||||
|         - dupl | ||||
|         - gosec | ||||
|  | ||||
|     - linters: | ||||
|         - errcheck | ||||
|       source: ".((os\\.)?std(out|err)\\..*|.*Close|.*Flush|os\\.Remove(All)?| | ||||
|         .*printf?|os\\.(Un)?Setenv)." | ||||
|  | ||||
|     - linters: | ||||
|         - stylecheck | ||||
|       text: "ST1003:.*(Ts|ts).*TS" | ||||
|  | ||||
|   exclude-use-default: false | ||||
							
								
								
									
										2
									
								
								vendor/github.com/SevereCloud/vksdk/v2/.markdownlint.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/SevereCloud/vksdk/v2/.markdownlint.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| --- | ||||
| no-hard-tabs: false | ||||
							
								
								
									
										20
									
								
								vendor/github.com/SevereCloud/vksdk/v2/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/SevereCloud/vksdk/v2/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| --- | ||||
| language: go | ||||
|  | ||||
| cache: | ||||
|   directories: | ||||
|     - $HOME/.cache/go-build | ||||
|     - $HOME/gopath/pkg/mod | ||||
|  | ||||
| go: | ||||
|   - 1.x | ||||
|  | ||||
| before_script: | ||||
|   - git fetch --depth=1 origin +refs/tags/*:refs/tags/* | ||||
|   - git describe --tags $(git rev-list --tags --max-count=1) --always | ||||
|  | ||||
| script: | ||||
|   - go test -v -race -coverprofile=coverage.txt -covermode=atomic -p=1 ./... | ||||
|  | ||||
| after_success: | ||||
|   - bash <(curl -s https://codecov.io/bash) | ||||
							
								
								
									
										92
									
								
								vendor/github.com/SevereCloud/vksdk/v2/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								vendor/github.com/SevereCloud/vksdk/v2/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| # Contributing | ||||
|  | ||||
| ## Настройки | ||||
|  | ||||
| `vksdk` написан на [Go](https://golang.org/). | ||||
|  | ||||
| Требования: | ||||
|  | ||||
| - [Go 1.13+](https://golang.org/doc/install) | ||||
| - [golangci-lint](https://github.com/golangci/golangci-lint) | ||||
| - [global .gitignore](https://help.github.com/en/articles/ignoring-files#create-a-global-gitignore) | ||||
|  | ||||
| Сделайте fork и клонируйте `vksdk` куда угодно: | ||||
|  | ||||
| ```sh | ||||
| git clone git@github.com:<your name>/vksdk.git | ||||
| ``` | ||||
|  | ||||
| Создайте новую ветку | ||||
|  | ||||
| ```sh | ||||
| git checkout -b <name_of_your_new_branch> | ||||
| ``` | ||||
|  | ||||
| ## Тестирование изменений | ||||
|  | ||||
| Для начала проверьте ваш код с помощью | ||||
| [golangci-lint](https://github.com/golangci/golangci-lint) | ||||
|  | ||||
| ```sh | ||||
| golangci-lint run | ||||
| ``` | ||||
|  | ||||
| Затем можно запускать тесты | ||||
|  | ||||
| ```sh | ||||
| # SERVICE_TOKEN="" | ||||
| # GROUP_TOKEN="" | ||||
| # CLIENT_SECRET="" | ||||
| # USER_TOKEN="" | ||||
| # WIDGET_TOKEN="" | ||||
| # CLIENT_ID="123456" | ||||
| # GROUP_ID="123456" | ||||
| # ACCOUNT_ID="123456" | ||||
| go test ./... | ||||
| ``` | ||||
|  | ||||
| Задавать токены не обязательно - тесты с их использованием будут пропущены. | ||||
| **Не** рекомендуется задавать свой `USER_TOKEN`, так как тесты делают много | ||||
| страшных вещей. | ||||
|  | ||||
| Настройки для VSCode `.vscode/setting.json` | ||||
|  | ||||
| ```json | ||||
| { | ||||
|     "go.testEnvVars": { | ||||
|         "SERVICE_TOKEN": "", | ||||
|         "WIDGET_TOKEN": "", | ||||
|         "GROUP_TOKEN": "", | ||||
|         "CLIENT_SECRET": "", | ||||
|         "USER_TOKEN": "", | ||||
|         "CLIENT_ID": "123456", | ||||
|         "GROUP_ID": "123456", | ||||
|         "ACCOUNT_ID": "123456" | ||||
|     } | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Создание коммита | ||||
|  | ||||
| Сообщения коммитов должны быть хорошо отформатированы, и чтобы сделать их | ||||
| «стандартизированным», мы используем | ||||
| [Conventional Commits](https://www.conventionalcommits.org/ru). | ||||
|  | ||||
| ```sh | ||||
| git add . | ||||
| git commit | ||||
| ``` | ||||
|  | ||||
| ## Отправьте pull request | ||||
|  | ||||
| Отправьте изменения в ваш репозиторий | ||||
|  | ||||
| ```sh | ||||
| git push origin <name_of_your_new_branch> | ||||
| ``` | ||||
|  | ||||
| Затем откройте [pull request](https://github.com/SevereCloud/vksdk/pulls) | ||||
| с веткой: | ||||
|  | ||||
| - `master` если это багфикс | ||||
| - `dev-v1.2.3` если это новая фича | ||||
							
								
								
									
										21
									
								
								vendor/github.com/SevereCloud/vksdk/v2/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/SevereCloud/vksdk/v2/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| The MIT License (MIT) | ||||
|  | ||||
| Copyright (c) 2020 Daniil Suvorov | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
|  | ||||
| The above copyright notice and this permission notice shall be included in | ||||
| all copies or substantial portions of the Software. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| THE SOFTWARE. | ||||
							
								
								
									
										121
									
								
								vendor/github.com/SevereCloud/vksdk/v2/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								vendor/github.com/SevereCloud/vksdk/v2/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,121 @@ | ||||
| # VK SDK for Golang | ||||
|  | ||||
| [](https://travis-ci.com/SevereCloud/vksdk) | ||||
| [](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2?tab=subdirectories) | ||||
| [](https://vk.com/dev/) | ||||
| [](https://codecov.io/gh/SevereCloud/vksdk) | ||||
| [](https://vk.me/join/AJQ1d6Or8Q00Y_CSOESfbqGt) | ||||
| [](https://github.com/SevereCloud/vksdk/releases) | ||||
| [](https://github.com/SevereCloud/vksdk/blob/master/LICENSE) | ||||
|  | ||||
| **VK SDK for Golang** ready implementation of the main VK API functions for Go. | ||||
|  | ||||
| [Russian documentation](https://github.com/SevereCloud/vksdk/wiki) | ||||
|  | ||||
| ## Features | ||||
|  | ||||
| Version API 5.126. | ||||
|  | ||||
| - [API](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/api) | ||||
|   - 400+ methods | ||||
|   - Ability to change the request handler | ||||
|   - Ability to modify HTTP client | ||||
|   - Request Limiter | ||||
|   - Token pool | ||||
| - [Callback API](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/callback) | ||||
|   - Tracking tool for users activity in your VK communities | ||||
|   - Supports all events | ||||
|   - Auto setting callback | ||||
| - [Bots Long Poll API](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/longpoll-bot) | ||||
|   - Allows you to work with community events in real time | ||||
|   - Supports all events | ||||
|   - Ability to modify HTTP client | ||||
| - [User Long Poll API](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/longpoll-user) | ||||
|   - Allows you to work with user events in real time | ||||
|   - Ability to modify HTTP client | ||||
| - [Streaming API](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/streaming) | ||||
|   - Receiving public data from VK by specified keywords | ||||
|   - Ability to modify HTTP client | ||||
| - [FOAF](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/foaf) | ||||
|   - Machine-readable ontology describing persons | ||||
|   - Works with users and groups | ||||
|   - The only place to get page creation date | ||||
| - [VK Mini Apps](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/vkapps) | ||||
|   - Checking launch parameters | ||||
|   - Intermediate http handler | ||||
| - [Payments API](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/payments) | ||||
|   - Processes payment notifications | ||||
| - [Marusia Skills](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/marusia) | ||||
|   - For creating Marusia Skills | ||||
|  | ||||
| ## Install | ||||
|  | ||||
| ```bash | ||||
| # go mod init mymodulename | ||||
| go get github.com/SevereCloud/vksdk/v2@latest | ||||
| ``` | ||||
|  | ||||
| ## Use by | ||||
|  | ||||
| - [Joe](https://github.com/go-joe/joe) adapter: <https://github.com/tdakkota/joe-vk-adapter> | ||||
| - [Logrus](https://github.com/sirupsen/logrus) hook: <https://github.com/SevereCloud/vkrus> | ||||
|  | ||||
| ### Example | ||||
|  | ||||
| ```go | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"log" | ||||
|  | ||||
| 	"github.com/SevereCloud/vksdk/v2/api" | ||||
| 	"github.com/SevereCloud/vksdk/v2/api/params" | ||||
| 	"github.com/SevereCloud/vksdk/v2/events" | ||||
| 	"github.com/SevereCloud/vksdk/v2/longpoll-bot" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	token := "<TOKEN>" // use os.Getenv("TOKEN") | ||||
| 	vk := api.NewVK(token) | ||||
|  | ||||
| 	// get information about the group | ||||
| 	group, err := vk.GroupsGetByID(nil) | ||||
| 	if err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	// Initializing Long Poll | ||||
| 	lp, err := longpoll.NewLongPoll(vk, group[0].ID) | ||||
| 	if err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	// New message event | ||||
| 	lp.MessageNew(func(_ context.Context, obj events.MessageNewObject) { | ||||
| 		log.Printf("%d: %s", obj.Message.PeerID, obj.Message.Text) | ||||
|  | ||||
| 		if obj.Message.Text == "ping" { | ||||
| 			b := params.NewMessagesSendBuilder() | ||||
| 			b.Message("pong") | ||||
| 			b.RandomID(0) | ||||
| 			b.PeerID(obj.Message.PeerID) | ||||
|  | ||||
| 			_, err := vk.MessagesSend(b.Params) | ||||
| 			if err != nil { | ||||
| 				log.Fatal(err) | ||||
| 			} | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	// Run Bots Long Poll | ||||
| 	log.Println("Start Long Poll") | ||||
| 	if err := lp.Run(); err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## LICENSE | ||||
|  | ||||
| [](https://app.fossa.io/projects/git%2Bgithub.com%2FSevereCloud%2Fvksdk?ref=badge_large) | ||||
							
								
								
									
										555
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										555
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,555 @@ | ||||
| # API | ||||
|  | ||||
| [](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/api) | ||||
| [](https://vk.com/dev/first_guide) | ||||
|  | ||||
| Данная библиотека поддерживает версию API **5.122**. | ||||
|  | ||||
| ## Запросы | ||||
|  | ||||
| В начале необходимо инициализировать api с помощью [ключа доступа](https://vk.com/dev/access_token): | ||||
|  | ||||
| ```go | ||||
| vk := api.NewVK("<TOKEN>") | ||||
| ``` | ||||
|  | ||||
| ### Запросы к API | ||||
|  | ||||
| - `users.get` -> `vk.UsersGet(api.Params{})` | ||||
| - `groups.get` с extended=1 -> `vk.GroupsGetExtended(api.Params{})` | ||||
|  | ||||
| Список всех методов можно найти на | ||||
| [данной странице](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/api?tab=doc#VK). | ||||
|  | ||||
| Пример запроса [`users.get`](https://vk.com/dev/users.get) | ||||
|  | ||||
| ```go | ||||
| users, err := vk.UsersGet(api.Params{ | ||||
| 	"user_ids": 1, | ||||
| }) | ||||
| if err != nil { | ||||
| 	log.Fatal(err) | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ### Параметры | ||||
|  | ||||
| [](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/api/params) | ||||
|  | ||||
| Модуль params предназначен для генерации параметров запроса. | ||||
|  | ||||
| ```go | ||||
| // import "github.com/SevereCloud/vksdk/v2/api/params" | ||||
|  | ||||
| b := params.NewMessageSendBuilder() | ||||
| b.PeerID(123) | ||||
| b.Random(0) | ||||
| b.DontParseLinks(false) | ||||
| b.Message("Test message") | ||||
|  | ||||
| res, err = api.MessageSend(b.Params) | ||||
| ``` | ||||
|  | ||||
| ### Обработка ошибок | ||||
|  | ||||
| [](https://vk.com/dev/errors) | ||||
|  | ||||
| Обработка ошибок полностью поддерживает методы | ||||
| [go 1.13](https://blog.golang.org/go1.13-errors) | ||||
|  | ||||
| ```go | ||||
| if errors.Is(err, api.ErrAuth) { | ||||
| 	log.Println("User authorization failed") | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```go | ||||
| var e *api.Error | ||||
| if errors.As(err, &e) { | ||||
| 	switch e.Code { | ||||
| 	case api.ErrCaptcha: | ||||
| 		log.Println("Требуется ввод кода с картинки (Captcha)") | ||||
| 		log.Printf("sid %s img %s", e.CaptchaSID, e.CaptchaImg) | ||||
| 	case 1: | ||||
| 		log.Println("Код ошибки 1") | ||||
| 	default: | ||||
| 		log.Printf("Ошибка %d %s", e.Code, e.Text) | ||||
| 	} | ||||
| } | ||||
| ``` | ||||
|  | ||||
| Для Execute существует отдельная ошибка `ExecuteErrors` | ||||
|  | ||||
| ### Запрос любого метода | ||||
|  | ||||
| Пример запроса [users.get](https://vk.com/dev/users.get) | ||||
|  | ||||
| ```go | ||||
| // Определяем структуру, которую вернет API | ||||
| var response []object.UsersUser | ||||
| var err api.Error | ||||
|  | ||||
| params := api.Params{ | ||||
| 	"user_ids": 1, | ||||
| } | ||||
|  | ||||
| // Делаем запрос | ||||
| err = vk.RequestUnmarshal("users.get", &response, params) | ||||
| if err != nil { | ||||
| 	log.Fatal(err) | ||||
| } | ||||
|  | ||||
| log.Print(response) | ||||
| ``` | ||||
|  | ||||
| ### Execute | ||||
|  | ||||
| [](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/api#VK.Execute) | ||||
| [](https://vk.com/dev/execute) | ||||
|  | ||||
| Универсальный метод, который позволяет запускать последовательность других | ||||
| методов, сохраняя и фильтруя промежуточные результаты. | ||||
|  | ||||
| ```go | ||||
| var response struct { | ||||
| 	Text string `json:"text"` | ||||
| } | ||||
|  | ||||
| err = vk.Execute(`return {text: "hello"};`, &response) | ||||
| if err != nil { | ||||
| 	log.Fatal(err) | ||||
| } | ||||
|  | ||||
| log.Print(response.Text) | ||||
| ``` | ||||
|  | ||||
| ### Обработчик запросов | ||||
|  | ||||
| Обработчик `vk.Handler` должен возвращать структуру ответа от VK API и ошибку. | ||||
| В качестве параметров принимать название метода и параметры. | ||||
|  | ||||
| ```go | ||||
| vk.Handler = func(method string, params ...api.Params) (api.Response, error) { | ||||
| 	// ... | ||||
| } | ||||
| ``` | ||||
|  | ||||
| Это может потребоваться, если вы можете поставить свой обработчик с | ||||
| [fasthttp](https://github.com/valyala/fasthttp) и логгером. | ||||
|  | ||||
| Стандартный обработчик использует [encoding/json](https://pkg.go.dev/net/http) | ||||
| и [net/http](https://pkg.go.dev/net/http). В стандартном обработчике можно | ||||
| настроить ограничитель запросов и HTTP клиент. | ||||
|  | ||||
| #### Ограничитель запросов | ||||
|  | ||||
| К методам API ВКонтакте (за исключением методов из секций secure и ads) с | ||||
| ключом доступа пользователя или сервисным ключом доступа можно обращаться не | ||||
| чаще 3 раз в секунду. Для ключа доступа сообщества ограничение составляет 20 | ||||
| запросов в секунду. Если логика Вашего приложения подразумевает вызов | ||||
| нескольких методов подряд, имеет смысл обратить внимание на метод execute. Он | ||||
| позволяет совершить до 25 обращений к разным методам в рамках одного запроса. | ||||
|  | ||||
| Для методов секции ads действуют собственные ограничения, ознакомиться с ними | ||||
| Вы можете на [этой странице](https://vk.com/dev/ads_limits). | ||||
|  | ||||
| Максимальное число обращений к методам секции secure зависит от числа | ||||
| пользователей, установивших приложение. Если приложение установило меньше 10 | ||||
| 000 человек, то можно совершать 5 запросов в секунду, до 100 000 — 8 запросов, | ||||
| до 1 000 000 — 20 запросов, больше 1 млн. — 35 запросов в секунду. | ||||
|  | ||||
| Если Вы превысите частотное ограничение, сервер вернет ошибку с кодом | ||||
| **6: "Too many requests per second."**. | ||||
|  | ||||
| С помощью параметра `vk.Limit` можно установить ограничение на определенное | ||||
| количество запросов в секунду | ||||
|  | ||||
| ### HTTP client | ||||
|  | ||||
| В модуле реализована возможность изменять HTTP клиент с помощью параметра | ||||
| `vk.Client` | ||||
|  | ||||
| Пример прокси | ||||
|  | ||||
| ```go | ||||
|  | ||||
| dialer, _ := proxy.SOCKS5("tcp", "127.0.0.1:9050", nil, proxy.Direct) | ||||
| httpTransport := &http.Transport{ | ||||
| 	Dial:              dialer.Dial, | ||||
| } | ||||
| httpTransport.Dial = dialer.Dial | ||||
|  | ||||
| client := &http.Client{ | ||||
| 	Transport: httpTransport, | ||||
| } | ||||
|  | ||||
| vk.Client = client | ||||
| ``` | ||||
|  | ||||
| ### Ошибка с Captcha | ||||
|  | ||||
| [](https://vk.com/dev/captcha_error) | ||||
|  | ||||
| Если какое-либо действие (например, отправка сообщения) выполняется | ||||
| пользователем слишком часто, то запрос к API может возвращать ошибку | ||||
| "Captcha needed". При этом пользователю понадобится ввести код с изображения | ||||
| и отправить запрос повторно с передачей введенного кода Captcha в параметрах | ||||
| запроса. | ||||
|  | ||||
| **Код ошибки**: 14   | ||||
| **Текст ошибки**: Captcha needed | ||||
|  | ||||
| Если возникает данная ошибка, то в сообщении об ошибке передаются также | ||||
| следующие параметры: | ||||
|  | ||||
| - `err.CaptchaSID` - идентификатор captcha | ||||
| - `err.CaptchaImg` - ссылка на изображение, которое нужно показать | ||||
|   пользователю, чтобы он ввел текст с этого изображения. | ||||
|  | ||||
| В этом случае следует запросить пользователя ввести текст с изображения | ||||
| `err.CaptchaImg` и повторить запрос, добавив в него параметры: | ||||
|  | ||||
| - `captcha_sid` - полученный идентификатор | ||||
| - `captcha_key` - текст, который ввел пользователь | ||||
|  | ||||
| ## Загрузка файлов | ||||
|  | ||||
| [](https://vk.com/dev/upload_files) | ||||
|  | ||||
| ### 1. Загрузка фотографий в альбом | ||||
|  | ||||
| Допустимые форматы: JPG, PNG, GIF. | ||||
| Файл объемом не более 50 МБ, соотношение сторон не менее 1:20 | ||||
|  | ||||
| Загрузка фотографий в альбом для текущего пользователя: | ||||
|  | ||||
| ```go | ||||
| photosPhoto, err = vk.UploadPhoto(albumID, response.Body) | ||||
| ``` | ||||
|  | ||||
| Загрузка фотографий в альбом для группы: | ||||
|  | ||||
| ```go | ||||
| photosPhoto, err = vk.UploadPhotoGroup(groupID, albumID, response.Body) | ||||
| ``` | ||||
|  | ||||
| ### 2. Загрузка фотографий на стену | ||||
|  | ||||
| Допустимые форматы: JPG, PNG, GIF. | ||||
| Файл объемом не более 50 МБ, соотношение сторон не менее 1:20 | ||||
|  | ||||
| ```go | ||||
| photosPhoto, err = vk.UploadWallPhoto(response.Body) | ||||
| ``` | ||||
|  | ||||
| Загрузка фотографий в альбом для группы: | ||||
|  | ||||
| ```go | ||||
| photosPhoto, err = vk.UploadWallPhotoGroup(groupID, response.Body) | ||||
| ``` | ||||
|  | ||||
| ### 3. Загрузка главной фотографии пользователя или сообщества | ||||
|  | ||||
| Допустимые форматы: JPG, PNG, GIF. | ||||
| Ограничения: размер не менее 200x200px, соотношение сторон от 0.25 до 3, | ||||
| сумма высоты и ширины не более 14000px, файл объемом не более 50 МБ, | ||||
| соотношение сторон не менее 1:20. | ||||
|  | ||||
| Загрузка главной фотографии пользователя | ||||
|  | ||||
| ```go | ||||
| photosPhoto, err = vk.UploadUserPhoto(file) | ||||
| ``` | ||||
|  | ||||
| Загрузка фотографии пользователя или сообщества с миниатюрой | ||||
|  | ||||
| ```go | ||||
| photosPhoto, err = vk.UploadOwnerPhoto(ownerID, squareСrop,file) | ||||
| ``` | ||||
|  | ||||
| Для загрузки главной фотографии сообщества необходимо передать его идентификатор | ||||
| со знаком «минус» в параметре `ownerID`. | ||||
|  | ||||
| Дополнительно Вы можете передать параметр `squareСrop` в формате "x,y,w" (без | ||||
| кавычек), где x и y — координаты верхнего правого угла миниатюры, а w — сторона | ||||
| квадрата. Тогда для фотографии также будет подготовлена квадратная миниатюра. | ||||
|  | ||||
| Загрузка фотографии пользователя или сообщества без миниатюры: | ||||
|  | ||||
| ```go | ||||
| photosPhoto, err = vk.UploadOwnerPhoto(ownerID, "", file) | ||||
| ``` | ||||
|  | ||||
| ### 4. Загрузка фотографии в личное сообщение | ||||
|  | ||||
| Допустимые форматы: JPG, PNG, GIF. | ||||
| Ограничения: сумма высоты и ширины не более 14000px, файл объемом | ||||
| не более 50 МБ, соотношение сторон не менее 1:20. | ||||
|  | ||||
| ```go | ||||
| photosPhoto, err = vk.UploadMessagesPhoto(peerID, file) | ||||
| ``` | ||||
|  | ||||
| ### 5. Загрузка главной фотографии для чата | ||||
|  | ||||
| Допустимые форматы: JPG, PNG, GIF. | ||||
| Ограничения: размер не менее 200x200px, соотношение сторон от 0.25 до 3, сумма | ||||
| высоты и ширины не более 14000px, файл объемом не более 50 МБ, соотношение | ||||
| сторон не менее 1:20. | ||||
|  | ||||
| Без обрезки: | ||||
|  | ||||
| ```go | ||||
| messageInfo, err = vk.UploadChatPhoto(peerID, file) | ||||
| ``` | ||||
|  | ||||
| С обрезкой: | ||||
|  | ||||
| ```go | ||||
| messageInfo, err = vk.UploadChatPhotoCrop(peerID, cropX, cropY, cropWidth, file) | ||||
| ``` | ||||
|  | ||||
| ### 6. Загрузка фотографии для товара | ||||
|  | ||||
| Допустимые форматы: JPG, PNG, GIF. | ||||
| Ограничения: минимальный размер фото — 400x400px, сумма высоты и ширины | ||||
| не более 14000px, файл объемом не более 50 МБ, соотношение сторон не менее 1:20. | ||||
|  | ||||
| Если Вы хотите загрузить основную фотографию товара, необходимо передать | ||||
| параметр `mainPhoto = true`.  Если фотография не основная, она не будет обрезаться. | ||||
|  | ||||
| Без обрезки: | ||||
|  | ||||
| ```go | ||||
| photosPhoto, err = vk.UploadMarketPhoto(groupID, mainPhoto, file) | ||||
| ``` | ||||
|  | ||||
| Основную фотографию с обрезкой: | ||||
|  | ||||
| ```go | ||||
| photosPhoto, err = vk.UploadMarketPhotoCrop(groupID, cropX, cropY, cropWidth, file) | ||||
| ``` | ||||
|  | ||||
| ### 7. Загрузка фотографии для подборки товаров | ||||
|  | ||||
| Допустимые форматы: JPG, PNG, GIF. | ||||
| Ограничения: минимальный размер фото — 1280x720px, сумма высоты и ширины | ||||
| не более 14000px, файл объемом не более 50 МБ, соотношение сторон не менее 1:20. | ||||
|  | ||||
| ```go | ||||
| photosPhoto, err = vk.UploadMarketAlbumPhoto(groupID, file) | ||||
| ``` | ||||
|  | ||||
| ### 9. Загрузка видеозаписей | ||||
|  | ||||
| Допустимые форматы: AVI, MP4, 3GP, MPEG, MOV, MP3, FLV, WMV. | ||||
|  | ||||
| [Параметры](https://vk.com/dev/video.save) | ||||
|  | ||||
| ```go | ||||
| videoUploadResponse, err = vk.UploadVideo(params, file) | ||||
| ``` | ||||
|  | ||||
| После загрузки видеозапись проходит обработку и в списке видеозаписей может | ||||
| появиться спустя некоторое время. | ||||
|  | ||||
| ### 10. Загрузка документов | ||||
|  | ||||
| Допустимые форматы: любые форматы за исключением mp3 и исполняемых файлов. | ||||
| Ограничения: файл объемом не более 200 МБ. | ||||
|  | ||||
| `title` - название файла с расширением | ||||
|  | ||||
| `tags` - метки для поиска | ||||
|  | ||||
| `typeDoc` - тип документа. | ||||
|  | ||||
| - doc - обычный документ; | ||||
| - audio_message - голосовое сообщение | ||||
|  | ||||
| Загрузить документ: | ||||
|  | ||||
| ```go | ||||
| docsDoc, err = vk.UploadDoc(title, tags, file) | ||||
| ``` | ||||
|  | ||||
| Загрузить документ в группу: | ||||
|  | ||||
| ```go | ||||
| docsDoc, err = vk.UploadGroupDoc(groupID, title, tags, file) | ||||
| ``` | ||||
|  | ||||
| Загрузить документ, для последующей отправки документа на стену: | ||||
|  | ||||
| ```go | ||||
| docsDoc, err = vk.UploadWallDoc(title, tags, file) | ||||
| ``` | ||||
|  | ||||
| Загрузить документ в группу, для последующей отправки документа на стену: | ||||
|  | ||||
| ```go | ||||
| docsDoc, err = vk.UploadGroupWallDoc(groupID, title, tags, file) | ||||
| ``` | ||||
|  | ||||
| Загрузить документ в личное сообщение: | ||||
|  | ||||
| ```go | ||||
| docsDoc, err = vk.UploadMessagesDoc(peerID, typeDoc, title, tags, file) | ||||
| ``` | ||||
|  | ||||
| ### 11. Загрузка обложки сообщества | ||||
|  | ||||
| Допустимые форматы: JPG, PNG, GIF. | ||||
| Ограничения: минимальный размер фото — 795x200px, сумма высоты и ширины | ||||
| не более 14000px, файл объемом не более 50 МБ. Рекомендуемый размер: 1590x400px. | ||||
| В сутки можно загрузить не более 1500 обложек. | ||||
|  | ||||
| Необходимо указать координаты обрезки фотографии в параметрах | ||||
| `cropX`, `cropY`, `cropX2`, `cropY2`. | ||||
|  | ||||
| ```go | ||||
| photo, err = vk.UploadOwnerCoverPhoto(groupID, cropX, cropY, cropX2, cropY2, file) | ||||
| ``` | ||||
|  | ||||
| ### 12. Загрузка аудиосообщения | ||||
|  | ||||
| Допустимые форматы: Ogg Opus. | ||||
| Ограничения: sample rate 16kHz, variable bitrate 16 kbit/s, длительность | ||||
| не более 5 минут. | ||||
|  | ||||
| ```go | ||||
| docsDoc, err = vk.UploadMessagesDoc(peerID, "audio_message", title, tags, file) | ||||
| ``` | ||||
|  | ||||
| ### 13. Загрузка истории | ||||
|  | ||||
| Допустимые форматы: JPG, PNG, GIF. | ||||
| Ограничения: сумма высоты и ширины не более 14000px, файл объемом | ||||
| не более 10МБ. Формат видео: h264 video, aac audio, | ||||
| максимальное разрешение 720х1280, 30fps. | ||||
|  | ||||
| Загрузить историю с фотографией. [Параметры](https://vk.com/dev/stories.getPhotoUploadServer) | ||||
|  | ||||
| ```go | ||||
| uploadInfo, err = vk.UploadStoriesPhoto(params, file) | ||||
| ``` | ||||
|  | ||||
| Загрузить историю с видео. [Параметры](https://vk.com/dev/stories.getVideoUploadServer) | ||||
|  | ||||
| ```go | ||||
| uploadInfo, err = vk.UploadStoriesVideo(params, file) | ||||
| ``` | ||||
|  | ||||
| ### Загрузка фоновой фотографии в опрос | ||||
|  | ||||
| Допустимые форматы: JPG, PNG, GIF. | ||||
| Ограничения: сумма высоты и ширины не более 14000px, файл объемом не более 50 МБ, | ||||
| соотношение сторон не менее 1:20. | ||||
|  | ||||
| ```go | ||||
| photosPhoto, err = vk.UploadPollsPhoto(file) | ||||
| ``` | ||||
|  | ||||
| ```go | ||||
| photosPhoto, err = vk.UploadOwnerPollsPhoto(ownerID, file) | ||||
| ``` | ||||
|  | ||||
| Для загрузки фотографии сообщества необходимо передать его идентификатор со | ||||
| знаком «минус» в параметре `ownerID`. | ||||
|  | ||||
| ### Загрузка фотографии для карточки | ||||
|  | ||||
| Для карточек используются квадратные изображения минимальным размером 400х400. | ||||
| В случае загрузки неквадратного изображения, оно будет обрезано до квадратного. | ||||
| Допустимые форматы: JPG, PNG, BMP, TIFF или GIF. | ||||
| Ограничения: файл объемом не более 5 МБ. | ||||
|  | ||||
| ```go | ||||
| photo, err = vk.UploadPrettyCardsPhoto(file) | ||||
| ``` | ||||
|  | ||||
| ### Загрузка обложки для формы | ||||
|  | ||||
| Для форм сбора заявок используются прямоугольные изображения размером 1200х300. | ||||
| В случае загрузки изображения другого размера, оно будет автоматически обрезано | ||||
| до требуемого. | ||||
| Допустимые форматы: JPG, PNG, BMP, TIFF или GIF. | ||||
| Ограничения: файл объемом не более 5 МБ. | ||||
|  | ||||
| ```go | ||||
| photo, err = vk.UploadLeadFormsPhoto(file) | ||||
| ``` | ||||
|  | ||||
| Полученные данные можно использовать в методах | ||||
| [leadForms.create](https://vk.com/dev/leadForms.create) | ||||
| и | ||||
| [leadForms.edit](https://vk.com/dev/leadForms.edit). | ||||
|  | ||||
| Полученные данные можно использовать в методах | ||||
| [prettyCards.create](https://vk.com/dev/prettyCards.create) | ||||
| и | ||||
| [prettyCards.edit](https://vk.com/dev/prettyCards.edit). | ||||
|  | ||||
| ### Загрузки фотографии в коллекцию приложения для виджетов приложений сообществ | ||||
|  | ||||
| `imageType` (string) - тип изображения. | ||||
|  | ||||
| Возможные значения: | ||||
|  | ||||
| - 24x24 | ||||
| - 50x50 | ||||
| - 160x160 | ||||
| - 160x240 | ||||
| - 510x128 | ||||
|  | ||||
| ```go | ||||
| image, err = vk.UploadAppImage(imageType, file) | ||||
| ``` | ||||
|  | ||||
| ### Загрузки фотографии в коллекцию сообщества для виджетов приложений сообществ | ||||
|  | ||||
| `imageType` (string) - тип изображения. | ||||
|  | ||||
| Возможные значения: | ||||
|  | ||||
| - 24x24 | ||||
| - 50x50 | ||||
| - 160x160 | ||||
| - 160x240 | ||||
| - 510x128 | ||||
|  | ||||
| ```go | ||||
| image, err = vk.UploadGroupAppImage(imageType, file) | ||||
| ``` | ||||
|  | ||||
| #### Примеры | ||||
|  | ||||
| Загрузка фотографии в альбом: | ||||
|  | ||||
| ```go | ||||
| response, err := os.Open("photo.jpeg") | ||||
| if err != nil { | ||||
| 	log.Fatal(err) | ||||
| } | ||||
| defer response.Body.Close() | ||||
|  | ||||
| photo, err = vk.UploadPhoto(albumID, response.Body) | ||||
| if err != nil { | ||||
| 	log.Fatal(err) | ||||
| } | ||||
| ``` | ||||
|  | ||||
| Загрузка фотографии в альбом из интернета: | ||||
|  | ||||
| ```go | ||||
| response, err := http.Get("https://sun9-45.userapi.com/c638629/v638629852/2afba/o-dvykjSIB4.jpg") | ||||
| if err != nil { | ||||
| 	log.Fatal(err) | ||||
| } | ||||
| defer response.Body.Close() | ||||
|  | ||||
| photo, err = vk.UploadPhoto(albumID, response.Body) | ||||
| if err != nil { | ||||
| 	log.Fatal(err) | ||||
| } | ||||
| ``` | ||||
							
								
								
									
										196
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/account.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/account.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,196 @@ | ||||
| package api // import "github.com/SevereCloud/vksdk/v2/api" | ||||
|  | ||||
| import ( | ||||
| 	"github.com/SevereCloud/vksdk/v2/object" | ||||
| ) | ||||
|  | ||||
| // AccountBan account.ban. | ||||
| // | ||||
| // https://vk.com/dev/account.ban | ||||
| func (vk *VK) AccountBan(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("account.ban", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AccountChangePasswordResponse struct. | ||||
| type AccountChangePasswordResponse struct { | ||||
| 	Token string `json:"token"` | ||||
| } | ||||
|  | ||||
| // AccountChangePassword changes a user password after access is successfully restored with the auth.restore method. | ||||
| // | ||||
| // https://vk.com/dev/account.changePassword | ||||
| func (vk *VK) AccountChangePassword(params Params) (response AccountChangePasswordResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("account.changePassword", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AccountGetActiveOffersResponse struct. | ||||
| type AccountGetActiveOffersResponse struct { | ||||
| 	Count int                   `json:"count"` | ||||
| 	Items []object.AccountOffer `json:"items"` | ||||
| } | ||||
|  | ||||
| // AccountGetActiveOffers returns a list of active ads (offers). | ||||
| // If the user fulfill their conditions, he will be able to get | ||||
| // the appropriate number of votes to his balance. | ||||
| // | ||||
| // https://vk.com/dev/account.getActiveOffers | ||||
| func (vk *VK) AccountGetActiveOffers(params Params) (response AccountGetActiveOffersResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("account.getActiveOffers", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AccountGetAppPermissions gets settings of the user in this application. | ||||
| // | ||||
| // https://vk.com/dev/account.getAppPermissions | ||||
| func (vk *VK) AccountGetAppPermissions(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("account.getAppPermissions", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AccountGetBannedResponse struct. | ||||
| type AccountGetBannedResponse struct { | ||||
| 	Count int   `json:"count"` | ||||
| 	Items []int `json:"items"` | ||||
| 	object.ExtendedResponse | ||||
| } | ||||
|  | ||||
| // AccountGetBanned returns a user's blacklist. | ||||
| // | ||||
| // https://vk.com/dev/account.getBanned | ||||
| func (vk *VK) AccountGetBanned(params Params) (response AccountGetBannedResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("account.getBanned", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AccountGetCountersResponse struct. | ||||
| type AccountGetCountersResponse object.AccountAccountCounters | ||||
|  | ||||
| // AccountGetCounters returns non-null values of user counters. | ||||
| // | ||||
| // https://vk.com/dev/account.getCounters | ||||
| func (vk *VK) AccountGetCounters(params Params) (response AccountGetCountersResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("account.getCounters", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AccountGetInfoResponse struct. | ||||
| type AccountGetInfoResponse object.AccountInfo | ||||
|  | ||||
| // AccountGetInfo returns current account info. | ||||
| // | ||||
| // https://vk.com/dev/account.getInfo | ||||
| func (vk *VK) AccountGetInfo(params Params) (response AccountGetInfoResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("account.getInfo", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AccountGetProfileInfoResponse struct. | ||||
| type AccountGetProfileInfoResponse object.AccountUserSettings | ||||
|  | ||||
| // AccountGetProfileInfo returns the current account info. | ||||
| // | ||||
| // https://vk.com/dev/account.getProfileInfo | ||||
| func (vk *VK) AccountGetProfileInfo(params Params) (response AccountGetProfileInfoResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("account.getProfileInfo", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AccountGetPushSettingsResponse struct. | ||||
| type AccountGetPushSettingsResponse object.AccountPushSettings | ||||
|  | ||||
| // AccountGetPushSettings account.getPushSettings Gets settings of push notifications. | ||||
| // | ||||
| // https://vk.com/dev/account.getPushSettings | ||||
| func (vk *VK) AccountGetPushSettings(params Params) (response AccountGetPushSettingsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("account.getPushSettings", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AccountRegisterDevice subscribes an iOS/Android/Windows/Mac based device to receive push notifications. | ||||
| // | ||||
| // https://vk.com/dev/account.registerDevice | ||||
| func (vk *VK) AccountRegisterDevice(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("account.registerDevice", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AccountSaveProfileInfoResponse struct. | ||||
| type AccountSaveProfileInfoResponse struct { | ||||
| 	Changed     object.BaseBoolInt        `json:"changed"` | ||||
| 	NameRequest object.AccountNameRequest `json:"name_request"` | ||||
| } | ||||
|  | ||||
| // AccountSaveProfileInfo edits current profile info. | ||||
| // | ||||
| // https://vk.com/dev/account.saveProfileInfo | ||||
| func (vk *VK) AccountSaveProfileInfo(params Params) (response AccountSaveProfileInfoResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("account.saveProfileInfo", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AccountSetInfo allows to edit the current account info. | ||||
| // | ||||
| // https://vk.com/dev/account.setInfo | ||||
| func (vk *VK) AccountSetInfo(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("account.setInfo", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AccountSetNameInMenu sets an application screen name | ||||
| // (up to 17 characters), that is shown to the user in the left menu. | ||||
| // | ||||
| // https://vk.com/dev/account.setNameInMenu | ||||
| func (vk *VK) AccountSetNameInMenu(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("account.setNameInMenu", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AccountSetOffline marks a current user as offline. | ||||
| // | ||||
| // https://vk.com/dev/account.setOffline | ||||
| func (vk *VK) AccountSetOffline(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("account.setOffline", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AccountSetOnline marks the current user as online for 5 minutes. | ||||
| // | ||||
| // https://vk.com/dev/account.setOnline | ||||
| func (vk *VK) AccountSetOnline(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("account.setOnline", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AccountSetPushSettings change push settings. | ||||
| // | ||||
| // https://vk.com/dev/account.setPushSettings | ||||
| func (vk *VK) AccountSetPushSettings(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("account.setPushSettings", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AccountSetSilenceMode mutes push notifications for the set period of time. | ||||
| // | ||||
| // https://vk.com/dev/account.setSilenceMode | ||||
| func (vk *VK) AccountSetSilenceMode(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("account.setSilenceMode", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AccountUnban account.unban. | ||||
| // | ||||
| // https://vk.com/dev/account.unban | ||||
| func (vk *VK) AccountUnban(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("account.unban", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AccountUnregisterDevice unsubscribes a device from push notifications. | ||||
| // | ||||
| // https://vk.com/dev/account.unregisterDevice | ||||
| func (vk *VK) AccountUnregisterDevice(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("account.unregisterDevice", &response, params) | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										581
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/ads.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										581
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/ads.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,581 @@ | ||||
| package api // import "github.com/SevereCloud/vksdk/v2/api" | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
|  | ||||
| 	"github.com/SevereCloud/vksdk/v2/object" | ||||
| ) | ||||
|  | ||||
| // AdsAddOfficeUsersItem struct. | ||||
| type AdsAddOfficeUsersItem struct { | ||||
| 	OK    object.BaseBoolInt | ||||
| 	Error AdsError | ||||
| } | ||||
|  | ||||
| // UnmarshalJSON func. | ||||
| func (r *AdsAddOfficeUsersItem) UnmarshalJSON(data []byte) (err error) { | ||||
| 	if r.OK.UnmarshalJSON(data) != nil { | ||||
| 		return json.Unmarshal(data, &r.Error) | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AdsAddOfficeUsersResponse struct. | ||||
| type AdsAddOfficeUsersResponse []AdsAddOfficeUsersItem | ||||
|  | ||||
| // AdsAddOfficeUsers adds managers and/or supervisors to advertising account. | ||||
| // | ||||
| // https://vk.com/dev/ads.addOfficeUsers | ||||
| func (vk *VK) AdsAddOfficeUsers(params Params) (response AdsAddOfficeUsersResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.addOfficeUsers", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AdsCheckLinkResponse struct. | ||||
| type AdsCheckLinkResponse struct { | ||||
| 	// link status | ||||
| 	Status object.AdsLinkStatus `json:"status"` | ||||
|  | ||||
| 	// (if status = disallowed) — description of the reason | ||||
| 	Description string `json:"description,omitempty"` | ||||
|  | ||||
| 	// (if the end link differs from original and status = allowed) — end link. | ||||
| 	RedirectURL string `json:"redirect_url,omitempty"` | ||||
| } | ||||
|  | ||||
| // AdsCheckLink allows to check the ad link. | ||||
| // | ||||
| // https://vk.com/dev/ads.checkLink | ||||
| func (vk *VK) AdsCheckLink(params Params) (response AdsCheckLinkResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.checkLink", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AdsCreateAdsResponse struct. | ||||
| type AdsCreateAdsResponse []struct { | ||||
| 	ID int `json:"id"` | ||||
| 	AdsError | ||||
| } | ||||
|  | ||||
| // AdsCreateAds creates ads. | ||||
| // | ||||
| // Please note! Maximum allowed number of ads created in one request is 5. | ||||
| // Minimum size of ad audience is 50 people. | ||||
| // | ||||
| // https://vk.com/dev/ads.createAds | ||||
| func (vk *VK) AdsCreateAds(params Params) (response AdsCreateAdsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.createAds", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AdsCreateCampaignsResponse struct. | ||||
| type AdsCreateCampaignsResponse []struct { | ||||
| 	ID int `json:"id"` | ||||
| 	AdsError | ||||
| } | ||||
|  | ||||
| // AdsCreateCampaigns creates advertising campaigns. | ||||
| // | ||||
| // Please note! Allowed number of campaigns created in one request is 50. | ||||
| // | ||||
| // https://vk.com/dev/ads.createCampaigns | ||||
| func (vk *VK) AdsCreateCampaigns(params Params) (response AdsCreateCampaignsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.createCampaigns", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AdsCreateClientsResponse struct. | ||||
| type AdsCreateClientsResponse []struct { | ||||
| 	ID int `json:"id"` | ||||
| 	AdsError | ||||
| } | ||||
|  | ||||
| // AdsCreateClients creates clients of an advertising agency. | ||||
| // | ||||
| // Available only for advertising agencies. | ||||
| // | ||||
| // Please note! Allowed number of clients created in one request is 50. | ||||
| // | ||||
| // https://vk.com/dev/ads.createClients | ||||
| func (vk *VK) AdsCreateClients(params Params) (response AdsCreateClientsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.createClients", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AdsCreateLookalikeRequestResponse struct. | ||||
| type AdsCreateLookalikeRequestResponse struct { | ||||
| 	RequestID int `json:"request_id"` | ||||
| } | ||||
|  | ||||
| // AdsCreateLookalikeRequest creates a request to find a similar audience. | ||||
| // | ||||
| // https://vk.com/dev/ads.createLookalikeRequest | ||||
| func (vk *VK) AdsCreateLookalikeRequest(params Params) (response AdsCreateLookalikeRequestResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.createLookalikeRequest", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AdsCreateTargetGroupResponse struct. | ||||
| type AdsCreateTargetGroupResponse struct { | ||||
| 	ID int `json:"id"` | ||||
| } | ||||
|  | ||||
| // AdsCreateTargetGroup Creates a group to re-target ads for users who visited | ||||
| // advertiser's site (viewed information about the product, registered, etc.). | ||||
| // | ||||
| // When executed successfully this method returns user accounting code on | ||||
| // advertiser's site. You shall add this code to the site page, so users | ||||
| // registered in VK will be added to the created target group after they visit | ||||
| // this page. | ||||
| // | ||||
| // Use ads.importTargetContacts method to import existing user contacts to | ||||
| // the group. | ||||
| // | ||||
| // Please note! Maximum allowed number of groups for one advertising | ||||
| // account is 100. | ||||
| // | ||||
| // https://vk.com/dev/ads.createTargetGroup | ||||
| func (vk *VK) AdsCreateTargetGroup(params Params) (response AdsCreateTargetGroupResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.createTargetGroup", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AdsCreateTargetPixelResponse struct. | ||||
| type AdsCreateTargetPixelResponse struct { | ||||
| 	ID    int    `json:"id"` | ||||
| 	Pixel string `json:"pixel"` | ||||
| } | ||||
|  | ||||
| // AdsCreateTargetPixel Creates retargeting pixel. | ||||
| // | ||||
| // Method returns pixel code for users accounting on the advertiser site. | ||||
| // Authorized VK users who visited the page with pixel code on it will be | ||||
| // added to retargeting audience with corresponding rules. You can also use | ||||
| // Open API, ads.importTargetContacts method and loading from file. | ||||
| // | ||||
| // Maximum pixels number per advertising account is 25. | ||||
| // | ||||
| // https://vk.com/dev/ads.createTargetPixel | ||||
| func (vk *VK) AdsCreateTargetPixel(params Params) (response AdsCreateTargetPixelResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.createTargetPixel", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AdsDeleteAdsResponse struct. | ||||
| // | ||||
| // Each response is 0 — deleted successfully, or an error code. | ||||
| type AdsDeleteAdsResponse []ErrorType | ||||
|  | ||||
| // AdsDeleteAds archives ads. | ||||
| // | ||||
| // Warning! Maximum allowed number of ads archived in one request is 100. | ||||
| // | ||||
| // https://vk.com/dev/ads.deleteAds | ||||
| func (vk *VK) AdsDeleteAds(params Params) (response AdsDeleteAdsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.deleteAds", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AdsDeleteCampaignsResponse struct. | ||||
| // | ||||
| // Each response is 0 — deleted successfully, or an error code. | ||||
| type AdsDeleteCampaignsResponse []ErrorType | ||||
|  | ||||
| // AdsDeleteCampaigns archives advertising campaigns. | ||||
| // | ||||
| // | ||||
| // Warning! Maximum allowed number of campaigns archived in one request is 100. | ||||
| // | ||||
| // https://vk.com/dev/ads.deleteCampaigns | ||||
| func (vk *VK) AdsDeleteCampaigns(params Params) (response AdsDeleteCampaignsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.deleteCampaigns", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AdsDeleteClientsResponse struct. | ||||
| // | ||||
| // Each response is 0 — deleted successfully, or an error code. | ||||
| type AdsDeleteClientsResponse []ErrorType | ||||
|  | ||||
| // AdsDeleteClients archives clients of an advertising agency. | ||||
| // | ||||
| // Available only for advertising agencies. | ||||
| // | ||||
| // Please note! Maximum allowed number of clients edited in one request is 10. | ||||
| // | ||||
| // https://vk.com/dev/ads.deleteClients | ||||
| func (vk *VK) AdsDeleteClients(params Params) (response AdsDeleteClientsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.deleteClients", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AdsDeleteTargetGroup deletes target group. | ||||
| // | ||||
| // https://vk.com/dev/ads.deleteTargetGroup | ||||
| func (vk *VK) AdsDeleteTargetGroup(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.deleteTargetGroup", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AdsDeleteTargetPixel deletes target pixel. | ||||
| // | ||||
| // https://vk.com/dev/ads.deleteTargetPixel | ||||
| func (vk *VK) AdsDeleteTargetPixel(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.deleteTargetPixel", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AdsGetAccountsResponse struct. | ||||
| type AdsGetAccountsResponse []object.AdsAccount | ||||
|  | ||||
| // AdsGetAccounts returns a list of advertising accounts. | ||||
| // | ||||
| // https://vk.com/dev/ads.getAccounts | ||||
| func (vk *VK) AdsGetAccounts(params Params) (response AdsGetAccountsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.getAccounts", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AdsGetAdsResponse struct. | ||||
| type AdsGetAdsResponse []object.AdsAd | ||||
|  | ||||
| // AdsGetAds returns a list of ads. | ||||
| // | ||||
| // https://vk.com/dev/ads.getAds | ||||
| func (vk *VK) AdsGetAds(params Params) (response AdsGetAdsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.getAds", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AdsGetAdsLayoutResponse struct. | ||||
| type AdsGetAdsLayoutResponse []object.AdsAdLayout | ||||
|  | ||||
| // AdsGetAdsLayout returns descriptions of ad layouts. | ||||
| // | ||||
| // https://vk.com/dev/ads.getAdsLayout | ||||
| func (vk *VK) AdsGetAdsLayout(params Params) (response AdsGetAdsLayoutResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.getAdsLayout", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // TODO: AdsGetAdsTargetingResponse struct. | ||||
| // type AdsGetAdsTargetingResponse struct{} | ||||
|  | ||||
| // TODO: AdsGetAdsTargeting ... | ||||
| // | ||||
| // https://vk.com/dev/ads.getAdsTargeting | ||||
| // func (vk *VK) AdsGetAdsTargeting(params Params) (response AdsGetAdsTargetingResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.getAdsTargeting", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsGetBudgetResponse struct. | ||||
| // type AdsGetBudgetResponse struct{} | ||||
|  | ||||
| // TODO: AdsGetBudget ... | ||||
| // | ||||
| // https://vk.com/dev/ads.getBudget | ||||
| // func (vk *VK) AdsGetBudget(params Params) (response AdsGetBudgetResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.getBudget", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsGetCampaignsResponse struct. | ||||
| // type AdsGetCampaignsResponse struct{} | ||||
|  | ||||
| // TODO: AdsGetCampaigns ... | ||||
| // | ||||
| // https://vk.com/dev/ads.getCampaigns | ||||
| // func (vk *VK) AdsGetCampaigns(params Params) (response AdsGetCampaignsResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.getCampaigns", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsGetCategoriesResponse struct. | ||||
| // type AdsGetCategoriesResponse struct{} | ||||
|  | ||||
| // TODO: AdsGetCategories ... | ||||
| // | ||||
| // https://vk.com/dev/ads.getCategories | ||||
| // func (vk *VK) AdsGetCategories(params Params) (response AdsGetCategoriesResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.getCategories", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsGetClientsResponse struct. | ||||
| // type AdsGetClientsResponse struct{} | ||||
|  | ||||
| // TODO: AdsGetClients ... | ||||
| // | ||||
| // https://vk.com/dev/ads.getClients | ||||
| // func (vk *VK) AdsGetClients(params Params) (response AdsGetClientsResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.getClients", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsGetDemographicsResponse struct. | ||||
| // type AdsGetDemographicsResponse struct{} | ||||
|  | ||||
| // TODO: AdsGetDemographics ... | ||||
| // | ||||
| // https://vk.com/dev/ads.getDemographics | ||||
| // func (vk *VK) AdsGetDemographics(params Params) (response AdsGetDemographicsResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.getDemographics", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsGetFloodStatsResponse struct. | ||||
| // type AdsGetFloodStatsResponse struct{} | ||||
|  | ||||
| // TODO: AdsGetFloodStats ... | ||||
| // | ||||
| // https://vk.com/dev/ads.getFloodStats | ||||
| // func (vk *VK) AdsGetFloodStats(params Params) (response AdsGetFloodStatsResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.getFloodStats", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsGetLookalikeRequestsResponse struct. | ||||
| // type AdsGetLookalikeRequestsResponse struct{} | ||||
|  | ||||
| // TODO: AdsGetLookalikeRequests ... | ||||
| // | ||||
| // https://vk.com/dev/ads.getLookalikeRequests | ||||
| // func (vk *VK) AdsGetLookalikeRequests(params Params) (response AdsGetLookalikeRequestsResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.getLookalikeRequests", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // AdsGetMusiciansResponse struct. | ||||
| type AdsGetMusiciansResponse struct { | ||||
| 	Items []object.BaseObjectWithName | ||||
| } | ||||
|  | ||||
| // AdsGetMusicians returns a list of musicians. | ||||
| // | ||||
| // https://vk.com/dev/ads.getMusicians | ||||
| func (vk *VK) AdsGetMusicians(params Params) (response AdsGetMusiciansResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.getMusicians", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // TODO: AdsGetOfficeUsersResponse struct. | ||||
| // type AdsGetOfficeUsersResponse struct{} | ||||
|  | ||||
| // TODO: AdsGetOfficeUsers ... | ||||
| // | ||||
| // https://vk.com/dev/ads.getOfficeUsers | ||||
| // func (vk *VK) AdsGetOfficeUsers(params Params) (response AdsGetOfficeUsersResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.getOfficeUsers", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsGetPostsReachResponse struct. | ||||
| // type AdsGetPostsReachResponse struct{} | ||||
|  | ||||
| // TODO: AdsGetPostsReach ... | ||||
| // | ||||
| // https://vk.com/dev/ads.getPostsReach | ||||
| // func (vk *VK) AdsGetPostsReach(params Params) (response AdsGetPostsReachResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.getPostsReach", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsGetRejectionReasonResponse struct. | ||||
| // type AdsGetRejectionReasonResponse struct{} | ||||
|  | ||||
| // TODO: AdsGetRejectionReason ... | ||||
| // | ||||
| // https://vk.com/dev/ads.getRejectionReason | ||||
| // func (vk *VK) AdsGetRejectionReason(params Params) (response AdsGetRejectionReasonResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.getRejectionReason", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsGetStatisticsResponse struct. | ||||
| // type AdsGetStatisticsResponse struct{} | ||||
|  | ||||
| // TODO: AdsGetStatistics ... | ||||
| // | ||||
| // https://vk.com/dev/ads.getStatistics | ||||
| // func (vk *VK) AdsGetStatistics(params Params) (response AdsGetStatisticsResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.getStatistics", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsGetSuggestionsResponse struct. | ||||
| // type AdsGetSuggestionsResponse struct{} | ||||
|  | ||||
| // TODO: AdsGetSuggestions ... | ||||
| // | ||||
| // https://vk.com/dev/ads.getSuggestions | ||||
| // func (vk *VK) AdsGetSuggestions(params Params) (response AdsGetSuggestionsResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.getSuggestions", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // AdsGetTargetGroupsResponse struct. | ||||
| type AdsGetTargetGroupsResponse []object.AdsTargetGroup | ||||
|  | ||||
| // AdsGetTargetGroups returns a list of target groups. | ||||
| // | ||||
| // https://vk.com/dev/ads.getTargetGroups | ||||
| func (vk *VK) AdsGetTargetGroups(params Params) (response AdsGetTargetGroupsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.getTargetGroups", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // TODO: AdsGetTargetPixelsResponse struct. | ||||
| // type AdsGetTargetPixelsResponse struct{} | ||||
|  | ||||
| // TODO: AdsGetTargetPixels ... | ||||
| // | ||||
| // https://vk.com/dev/ads.getTargetPixels | ||||
| // func (vk *VK) AdsGetTargetPixels(params Params) (response AdsGetTargetPixelsResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.getTargetPixels", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsGetTargetingStatsResponse struct. | ||||
| // type AdsGetTargetingStatsResponse struct{} | ||||
|  | ||||
| // TODO: AdsGetTargetingStats ... | ||||
| // | ||||
| // https://vk.com/dev/ads.getTargetingStats | ||||
| // func (vk *VK) AdsGetTargetingStats(params Params) (response AdsGetTargetingStatsResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.getTargetingStats", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsGetUploadURLResponse struct. | ||||
| // type AdsGetUploadURLResponse struct{} | ||||
|  | ||||
| // TODO: AdsGetUploadURL ... | ||||
| // | ||||
| // https://vk.com/dev/ads.getUploadURL | ||||
| // func (vk *VK) AdsGetUploadURL(params Params) (response AdsGetUploadURLResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.getUploadURL", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsGetVideoUploadURLResponse struct. | ||||
| // type AdsGetVideoUploadURLResponse struct{} | ||||
|  | ||||
| // TODO: AdsGetVideoUploadURL ... | ||||
| // | ||||
| // https://vk.com/dev/ads.getVideoUploadURL | ||||
| // func (vk *VK) AdsGetVideoUploadURL(params Params) (response AdsGetVideoUploadURLResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.getVideoUploadURL", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsImportTargetContactsResponse struct. | ||||
| // type AdsImportTargetContactsResponse struct{} | ||||
|  | ||||
| // TODO: AdsImportTargetContacts ... | ||||
| // | ||||
| // https://vk.com/dev/ads.importTargetContacts | ||||
| // func (vk *VK) AdsImportTargetContacts(params Params) (response AdsImportTargetContactsResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.importTargetContacts", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsRemoveOfficeUsersResponse struct. | ||||
| // type AdsRemoveOfficeUsersResponse struct{} | ||||
|  | ||||
| // TODO: AdsRemoveOfficeUsers ... | ||||
| // | ||||
| // https://vk.com/dev/ads.removeOfficeUsers | ||||
| // func (vk *VK) AdsRemoveOfficeUsers(params Params) (response AdsRemoveOfficeUsersResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.removeOfficeUsers", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // AdsRemoveTargetContacts accepts the request to exclude the advertiser's | ||||
| // contacts from the retargeting audience. | ||||
| // | ||||
| // The maximum allowed number of contacts to be excluded by a single | ||||
| // request is 1000. | ||||
| // | ||||
| // Contacts are excluded within a few hours of the request. | ||||
| // | ||||
| // https://vk.com/dev/ads.removeTargetContacts | ||||
| func (vk *VK) AdsRemoveTargetContacts(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.removeTargetContacts", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // TODO: AdsSaveLookalikeRequestResultResponse struct. | ||||
| // type AdsSaveLookalikeRequestResultResponse struct{} | ||||
|  | ||||
| // TODO: AdsSaveLookalikeRequestResult ... | ||||
| // | ||||
| // https://vk.com/dev/ads.saveLookalikeRequestResult | ||||
| // func (vk *VK) AdsSaveLookalikeRequestResult(params Params) ( | ||||
| // 		response AdsSaveLookalikeRequestResultResponse, | ||||
| // 		err error, | ||||
| // 	) { | ||||
| // 	err = vk.RequestUnmarshal("ads.saveLookalikeRequestResult", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsShareTargetGroupResponse struct. | ||||
| // type AdsShareTargetGroupResponse struct{} | ||||
|  | ||||
| // TODO: AdsShareTargetGroup ... | ||||
| // | ||||
| // https://vk.com/dev/ads.shareTargetGroup | ||||
| // func (vk *VK) AdsShareTargetGroup(params Params) (response AdsShareTargetGroupResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.shareTargetGroup", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsUpdateAdsResponse struct. | ||||
| // type AdsUpdateAdsResponse struct{} | ||||
|  | ||||
| // TODO: AdsUpdateAds ... | ||||
| // | ||||
| // https://vk.com/dev/ads.updateAds | ||||
| // func (vk *VK) AdsUpdateAds(params Params) (response AdsUpdateAdsResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.updateAds", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsUpdateCampaignsResponse struct. | ||||
| // type AdsUpdateCampaignsResponse struct{} | ||||
|  | ||||
| // TODO: AdsUpdateCampaigns ... | ||||
| // | ||||
| // https://vk.com/dev/ads.updateCampaigns | ||||
| // func (vk *VK) AdsUpdateCampaigns(params Params) (response AdsUpdateCampaignsResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.updateCampaigns", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // TODO: AdsUpdateClientsResponse struct. | ||||
| // type AdsUpdateClientsResponse struct{} | ||||
|  | ||||
| // TODO: AdsUpdateClients ... | ||||
| // | ||||
| // https://vk.com/dev/ads.updateClients | ||||
| // func (vk *VK) AdsUpdateClients(params Params) (response AdsUpdateClientsResponse, err error) { | ||||
| // 	err = vk.RequestUnmarshal("ads.updateClients", &response, params) | ||||
| // 	return | ||||
| // } | ||||
|  | ||||
| // AdsUpdateTargetGroup edits target group. | ||||
| // | ||||
| // https://vk.com/dev/ads.updateTargetGroup | ||||
| func (vk *VK) AdsUpdateTargetGroup(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads.updateTargetGroup", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AdsUpdateTargetPixel edits target pixel. | ||||
| // | ||||
| // https://vk.com/dev/ads.updateTargetPixel | ||||
| func (vk *VK) AdsUpdateTargetPixel(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("ads. updateTargetPixel", &response, params) | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										359
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/api.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										359
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/api.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,359 @@ | ||||
| /* | ||||
| Package api implements VK API. | ||||
|  | ||||
| See more https://vk.com/dev/api_requests | ||||
| */ | ||||
| package api // import "github.com/SevereCloud/vksdk/v2/api" | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"mime" | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| 	"reflect" | ||||
| 	"sync" | ||||
| 	"sync/atomic" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/SevereCloud/vksdk/v2" | ||||
| 	"github.com/SevereCloud/vksdk/v2/internal" | ||||
| 	"github.com/SevereCloud/vksdk/v2/object" | ||||
| ) | ||||
|  | ||||
| // Api constants. | ||||
| const ( | ||||
| 	Version   = vksdk.API | ||||
| 	MethodURL = "https://api.vk.com/method/" | ||||
| ) | ||||
|  | ||||
| // VKontakte API methods (except for methods from secure and ads sections) | ||||
| // with user access key or service access key can be accessed | ||||
| // no more than 3 times per second. The community access key is limited | ||||
| // to 20 requests per second. | ||||
| // | ||||
| // Maximum amount of calls to the secure section methods depends | ||||
| // on the app's users amount. If an app has less than | ||||
| // 10 000 users, 5 requests per second, | ||||
| // up to 100 000 – 8 requests, | ||||
| // up to 1 000 000 – 20 requests, | ||||
| // 1 000 000+ – 35 requests. | ||||
| // | ||||
| // The ads section methods are subject to their own limitations, | ||||
| // you can read them on this page - https://vk.com/dev/ads_limits | ||||
| // | ||||
| // If one of this limits is exceeded, the server will return following error: | ||||
| // "Too many requests per second". (errors.TooMany). | ||||
| // | ||||
| // If your app's logic implies many requests in a row, check the execute method. | ||||
| // It allows for up to 25 requests for different methods in a single request. | ||||
| // | ||||
| // In addition to restrictions on the frequency of calls, there are also | ||||
| // quantitative restrictions on calling the same type of methods. | ||||
| // | ||||
| // After exceeding the quantitative limit, access to a particular method may | ||||
| // require entering a captcha (see https://vk.com/dev/captcha_error), | ||||
| // and may also be temporarily restricted (in this case, the server does | ||||
| // not return a response to the call of a particular method, but handles | ||||
| // any other requests without problems). | ||||
| // | ||||
| // If this error occurs, the following parameters are also passed in | ||||
| // the error message: | ||||
| // | ||||
| // CaptchaSID - identifier captcha. | ||||
| // | ||||
| // CaptchaImg - a link to the image that you want to show the user | ||||
| // to enter text from that image. | ||||
| // | ||||
| // In this case, you should ask the user to enter text from | ||||
| // the CaptchaImg image and repeat the request by adding parameters to it: | ||||
| // | ||||
| // captcha_sid - the obtained identifier; | ||||
| // | ||||
| // captcha_key - text entered by the user. | ||||
| // | ||||
| // More info: https://vk.com/dev/api_requests | ||||
| const ( | ||||
| 	LimitUserToken  = 3 | ||||
| 	LimitGroupToken = 20 | ||||
| ) | ||||
|  | ||||
| // VK struct. | ||||
| type VK struct { | ||||
| 	accessTokens []string | ||||
| 	lastToken    uint32 | ||||
| 	MethodURL    string | ||||
| 	Version      string | ||||
| 	Client       *http.Client | ||||
| 	Limit        int | ||||
| 	UserAgent    string | ||||
| 	Handler      func(method string, params ...Params) (Response, error) | ||||
|  | ||||
| 	mux      sync.Mutex | ||||
| 	lastTime time.Time | ||||
| 	rps      int | ||||
| } | ||||
|  | ||||
| // Response struct. | ||||
| type Response struct { | ||||
| 	Response      json.RawMessage `json:"response"` | ||||
| 	Error         Error           `json:"error"` | ||||
| 	ExecuteErrors ExecuteErrors   `json:"execute_errors"` | ||||
| } | ||||
|  | ||||
| // NewVK returns a new VK. | ||||
| // | ||||
| // The VKSDK will use the http.DefaultClient. | ||||
| // This means that if the http.DefaultClient is modified by other components | ||||
| // of your application the modifications will be picked up by the SDK as well. | ||||
| // | ||||
| // In some cases this might be intended, but it is a better practice | ||||
| // to create a custom HTTP Client to share explicitly through | ||||
| // your application. You can configure the VKSDK to use the custom | ||||
| // HTTP Client by setting the VK.Client value. | ||||
| // | ||||
| // This set limit 20 requests per second for one token. | ||||
| func NewVK(tokens ...string) *VK { | ||||
| 	var vk VK | ||||
|  | ||||
| 	vk.accessTokens = tokens | ||||
| 	vk.Version = Version | ||||
|  | ||||
| 	vk.Handler = vk.defaultHandler | ||||
|  | ||||
| 	vk.MethodURL = MethodURL | ||||
| 	vk.Client = http.DefaultClient | ||||
| 	vk.Limit = LimitGroupToken | ||||
| 	vk.UserAgent = internal.UserAgent | ||||
|  | ||||
| 	return &vk | ||||
| } | ||||
|  | ||||
| // getToken return next token (simple round-robin). | ||||
| func (vk *VK) getToken() string { | ||||
| 	i := atomic.AddUint32(&vk.lastToken, 1) | ||||
| 	return vk.accessTokens[(int(i)-1)%len(vk.accessTokens)] | ||||
| } | ||||
|  | ||||
| // Params type. | ||||
| type Params map[string]interface{} | ||||
|  | ||||
| // Lang - determines the language for the data to be displayed on. For | ||||
| // example country and city names. If you use a non-cyrillic language, | ||||
| // cyrillic symbols will be transliterated automatically. | ||||
| // Numeric format from account.getInfo is supported as well. | ||||
| // | ||||
| // 	p.Lang(object.LangRU) | ||||
| // | ||||
| // See all language code in module object. | ||||
| func (p Params) Lang(v int) Params { | ||||
| 	p["lang"] = v | ||||
| 	return p | ||||
| } | ||||
|  | ||||
| // TestMode allows to send requests from a native app without switching it on | ||||
| // for all users. | ||||
| func (p Params) TestMode(v bool) Params { | ||||
| 	p["test_mode"] = v | ||||
| 	return p | ||||
| } | ||||
|  | ||||
| // CaptchaSID received ID. | ||||
| // | ||||
| // See https://vk.com/dev/captcha_error | ||||
| func (p Params) CaptchaSID(v string) Params { | ||||
| 	p["captcha_sid"] = v | ||||
| 	return p | ||||
| } | ||||
|  | ||||
| // CaptchaKey text input. | ||||
| // | ||||
| // See https://vk.com/dev/captcha_error | ||||
| func (p Params) CaptchaKey(v string) Params { | ||||
| 	p["captcha_key"] = v | ||||
| 	return p | ||||
| } | ||||
|  | ||||
| // Confirm parameter. | ||||
| // | ||||
| // See https://vk.com/dev/need_confirmation | ||||
| func (p Params) Confirm(v bool) Params { | ||||
| 	p["confirm"] = v | ||||
| 	return p | ||||
| } | ||||
|  | ||||
| // WithContext parameter. | ||||
| func (p Params) WithContext(ctx context.Context) Params { | ||||
| 	p[":context"] = ctx | ||||
| 	return p | ||||
| } | ||||
|  | ||||
| func buildQuery(sliceParams ...Params) (context.Context, url.Values) { | ||||
| 	query := url.Values{} | ||||
| 	ctx := context.Background() | ||||
|  | ||||
| 	for _, params := range sliceParams { | ||||
| 		for key, value := range params { | ||||
| 			if key != ":context" { | ||||
| 				query.Set(key, FmtValue(value, 0)) | ||||
| 			} else { | ||||
| 				ctx = value.(context.Context) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return ctx, query | ||||
| } | ||||
|  | ||||
| // defaultHandler provides access to VK API methods. | ||||
| func (vk *VK) defaultHandler(method string, sliceParams ...Params) (Response, error) { | ||||
| 	u := vk.MethodURL + method | ||||
| 	ctx, query := buildQuery(sliceParams...) | ||||
| 	attempt := 0 | ||||
|  | ||||
| 	for { | ||||
| 		var response Response | ||||
|  | ||||
| 		attempt++ | ||||
|  | ||||
| 		// Rate limiting | ||||
| 		if vk.Limit > 0 { | ||||
| 			vk.mux.Lock() | ||||
|  | ||||
| 			sleepTime := time.Second - time.Since(vk.lastTime) | ||||
| 			if sleepTime < 0 { | ||||
| 				vk.lastTime = time.Now() | ||||
| 				vk.rps = 0 | ||||
| 			} else if vk.rps == vk.Limit*len(vk.accessTokens) { | ||||
| 				time.Sleep(sleepTime) | ||||
| 				vk.lastTime = time.Now() | ||||
| 				vk.rps = 0 | ||||
| 			} | ||||
| 			vk.rps++ | ||||
|  | ||||
| 			vk.mux.Unlock() | ||||
| 		} | ||||
|  | ||||
| 		rawBody := bytes.NewBufferString(query.Encode()) | ||||
|  | ||||
| 		req, err := http.NewRequestWithContext(ctx, "POST", u, rawBody) | ||||
| 		if err != nil { | ||||
| 			return response, err | ||||
| 		} | ||||
|  | ||||
| 		req.Header.Set("User-Agent", vk.UserAgent) | ||||
| 		req.Header.Set("Content-Type", "application/x-www-form-urlencoded") | ||||
|  | ||||
| 		resp, err := vk.Client.Do(req) | ||||
| 		if err != nil { | ||||
| 			return response, err | ||||
| 		} | ||||
|  | ||||
| 		mediatype, _, _ := mime.ParseMediaType(resp.Header.Get("Content-Type")) | ||||
| 		if mediatype != "application/json" { | ||||
| 			_ = resp.Body.Close() | ||||
| 			return response, &InvalidContentType{mediatype} | ||||
| 		} | ||||
|  | ||||
| 		err = json.NewDecoder(resp.Body).Decode(&response) | ||||
| 		if err != nil { | ||||
| 			_ = resp.Body.Close() | ||||
| 			return response, err | ||||
| 		} | ||||
|  | ||||
| 		_ = resp.Body.Close() | ||||
|  | ||||
| 		switch response.Error.Code { | ||||
| 		case ErrNoType: | ||||
| 			return response, nil | ||||
| 		case ErrTooMany: | ||||
| 			if attempt < vk.Limit { | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			return response, &response.Error | ||||
| 		} | ||||
|  | ||||
| 		return response, &response.Error | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Request provides access to VK API methods. | ||||
| func (vk *VK) Request(method string, sliceParams ...Params) ([]byte, error) { | ||||
| 	token := vk.getToken() | ||||
|  | ||||
| 	reqParams := Params{ | ||||
| 		"access_token": token, | ||||
| 		"v":            vk.Version, | ||||
| 	} | ||||
|  | ||||
| 	sliceParams = append(sliceParams, reqParams) | ||||
|  | ||||
| 	resp, err := vk.Handler(method, sliceParams...) | ||||
|  | ||||
| 	return resp.Response, err | ||||
| } | ||||
|  | ||||
| // RequestUnmarshal provides access to VK API methods. | ||||
| func (vk *VK) RequestUnmarshal(method string, obj interface{}, sliceParams ...Params) error { | ||||
| 	rawResponse, err := vk.Request(method, sliceParams...) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return json.Unmarshal(rawResponse, &obj) | ||||
| } | ||||
|  | ||||
| func fmtReflectValue(value reflect.Value, depth int) string { | ||||
| 	switch f := value; value.Kind() { | ||||
| 	case reflect.Invalid: | ||||
| 		return "" | ||||
| 	case reflect.Bool: | ||||
| 		return fmtBool(f.Bool()) | ||||
| 	case reflect.Array, reflect.Slice: | ||||
| 		s := "" | ||||
|  | ||||
| 		for i := 0; i < f.Len(); i++ { | ||||
| 			if i > 0 { | ||||
| 				s += "," | ||||
| 			} | ||||
|  | ||||
| 			s += FmtValue(f.Index(i).Interface(), depth) | ||||
| 		} | ||||
|  | ||||
| 		return s | ||||
| 	case reflect.Ptr: | ||||
| 		// pointer to array or slice or struct? ok at top level | ||||
| 		// but not embedded (avoid loops) | ||||
| 		if depth == 0 && f.Pointer() != 0 { | ||||
| 			switch a := f.Elem(); a.Kind() { | ||||
| 			case reflect.Array, reflect.Slice, reflect.Struct, reflect.Map: | ||||
| 				return FmtValue(a.Interface(), depth+1) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return fmt.Sprint(value) | ||||
| } | ||||
|  | ||||
| // FmtValue return vk format string. | ||||
| func FmtValue(value interface{}, depth int) string { | ||||
| 	if value == nil { | ||||
| 		return "" | ||||
| 	} | ||||
|  | ||||
| 	switch f := value.(type) { | ||||
| 	case bool: | ||||
| 		return fmtBool(f) | ||||
| 	case object.Attachment: | ||||
| 		return f.ToAttachment() | ||||
| 	case object.JSONObject: | ||||
| 		return f.ToJSON() | ||||
| 	case reflect.Value: | ||||
| 		return fmtReflectValue(f, depth) | ||||
| 	} | ||||
|  | ||||
| 	return fmtReflectValue(reflect.ValueOf(value), depth) | ||||
| } | ||||
							
								
								
									
										149
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/apps.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/apps.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,149 @@ | ||||
| package api // import "github.com/SevereCloud/vksdk/v2/api" | ||||
|  | ||||
| import ( | ||||
| 	"github.com/SevereCloud/vksdk/v2/object" | ||||
| ) | ||||
|  | ||||
| // AppsDeleteAppRequests deletes all request notifications from the current app. | ||||
| // | ||||
| // https://vk.com/dev/apps.deleteAppRequests | ||||
| func (vk *VK) AppsDeleteAppRequests(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("apps.deleteAppRequests", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AppsGetResponse struct. | ||||
| type AppsGetResponse struct { | ||||
| 	Count int              `json:"count"` | ||||
| 	Items []object.AppsApp `json:"items"` | ||||
| 	object.ExtendedResponse | ||||
| } | ||||
|  | ||||
| // AppsGet returns applications data. | ||||
| // | ||||
| // https://vk.com/dev/apps.get | ||||
| func (vk *VK) AppsGet(params Params) (response AppsGetResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("apps.get", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AppsGetCatalogResponse struct. | ||||
| type AppsGetCatalogResponse struct { | ||||
| 	Count int              `json:"count"` | ||||
| 	Items []object.AppsApp `json:"items"` | ||||
| 	object.ExtendedResponse | ||||
| } | ||||
|  | ||||
| // AppsGetCatalog returns a list of applications (apps) available to users in the App Catalog. | ||||
| // | ||||
| // https://vk.com/dev/apps.getCatalog | ||||
| func (vk *VK) AppsGetCatalog(params Params) (response AppsGetCatalogResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("apps.getCatalog", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AppsGetFriendsListResponse struct. | ||||
| type AppsGetFriendsListResponse struct { | ||||
| 	Count int   `json:"count"` | ||||
| 	Items []int `json:"items"` | ||||
| } | ||||
|  | ||||
| // AppsGetFriendsList creates friends list for requests and invites in current app. | ||||
| // | ||||
| // 	extended=0 | ||||
| // | ||||
| // https://vk.com/dev/apps.getFriendsList | ||||
| func (vk *VK) AppsGetFriendsList(params Params) (response AppsGetFriendsListResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("apps.getFriendsList", &response, params, Params{"extended": false}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AppsGetFriendsListExtendedResponse struct. | ||||
| type AppsGetFriendsListExtendedResponse struct { | ||||
| 	Count int                `json:"count"` | ||||
| 	Items []object.UsersUser `json:"items"` | ||||
| } | ||||
|  | ||||
| // AppsGetFriendsListExtended creates friends list for requests and invites in current app. | ||||
| // | ||||
| // 	extended=1 | ||||
| // | ||||
| // https://vk.com/dev/apps.getFriendsList | ||||
| func (vk *VK) AppsGetFriendsListExtended(params Params) (response AppsGetFriendsListExtendedResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("apps.getFriendsList", &response, params, Params{"extended": true}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AppsGetLeaderboardResponse struct. | ||||
| type AppsGetLeaderboardResponse struct { | ||||
| 	Count int                      `json:"count"` | ||||
| 	Items []object.AppsLeaderboard `json:"items"` | ||||
| } | ||||
|  | ||||
| // AppsGetLeaderboard returns players rating in the game. | ||||
| // | ||||
| // 	extended=0 | ||||
| // | ||||
| // https://vk.com/dev/apps.getLeaderboard | ||||
| func (vk *VK) AppsGetLeaderboard(params Params) (response AppsGetLeaderboardResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("apps.getLeaderboard", &response, params, Params{"extended": false}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AppsGetLeaderboardExtendedResponse struct. | ||||
| type AppsGetLeaderboardExtendedResponse struct { | ||||
| 	Count int `json:"count"` | ||||
| 	Items []struct { | ||||
| 		Score  int `json:"score"` | ||||
| 		UserID int `json:"user_id"` | ||||
| 	} `json:"items"` | ||||
| 	Profiles []object.UsersUser `json:"profiles"` | ||||
| } | ||||
|  | ||||
| // AppsGetLeaderboardExtended returns players rating in the game. | ||||
| // | ||||
| // 	extended=1 | ||||
| // | ||||
| // https://vk.com/dev/apps.getLeaderboard | ||||
| func (vk *VK) AppsGetLeaderboardExtended(params Params) (response AppsGetLeaderboardExtendedResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("apps.getLeaderboard", &response, params, Params{"extended": true}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AppsGetScopesResponse struct. | ||||
| type AppsGetScopesResponse struct { | ||||
| 	Count int                `json:"count"` | ||||
| 	Items []object.AppsScope `json:"items"` | ||||
| } | ||||
|  | ||||
| // AppsGetScopes ... | ||||
| // | ||||
| // TODO: write docs. | ||||
| // | ||||
| // https://vk.com/dev/apps.getScopes | ||||
| func (vk *VK) AppsGetScopes(params Params) (response AppsGetScopesResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("apps.getScopes", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AppsGetScore returns user score in app. | ||||
| // | ||||
| // NOTE: vk wtf!? | ||||
| // | ||||
| // https://vk.com/dev/apps.getScore | ||||
| func (vk *VK) AppsGetScore(params Params) (response string, err error) { | ||||
| 	err = vk.RequestUnmarshal("apps.getScore", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AppsSendRequest sends a request to another user in an app that uses VK authorization. | ||||
| // | ||||
| // https://vk.com/dev/apps.sendRequest | ||||
| func (vk *VK) AppsSendRequest(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("apps.sendRequest", &response, params) | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										100
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/appwidgets.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/appwidgets.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| package api // import "github.com/SevereCloud/vksdk/v2/api" | ||||
|  | ||||
| import ( | ||||
| 	"github.com/SevereCloud/vksdk/v2/object" | ||||
| ) | ||||
|  | ||||
| // AppWidgetsGetAppImageUploadServerResponse struct. | ||||
| type AppWidgetsGetAppImageUploadServerResponse struct { | ||||
| 	UploadURL string `json:"upload_url"` | ||||
| } | ||||
|  | ||||
| // AppWidgetsGetAppImageUploadServer returns a URL for uploading a | ||||
| // photo to the app collection for community app widgets. | ||||
| // | ||||
| // https://vk.com/dev/appWidgets.getAppImageUploadServer | ||||
| func (vk *VK) AppWidgetsGetAppImageUploadServer(params Params) ( | ||||
| 	response AppWidgetsGetAppImageUploadServerResponse, | ||||
| 	err error, | ||||
| ) { | ||||
| 	err = vk.RequestUnmarshal("appWidgets.getAppImageUploadServer", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AppWidgetsGetAppImagesResponse struct. | ||||
| type AppWidgetsGetAppImagesResponse struct { | ||||
| 	Count int                      `json:"count"` | ||||
| 	Items []object.AppWidgetsImage `json:"items"` | ||||
| } | ||||
|  | ||||
| // AppWidgetsGetAppImages returns an app collection of images for community app widgets. | ||||
| // | ||||
| // https://vk.com/dev/appWidgets.getAppImages | ||||
| func (vk *VK) AppWidgetsGetAppImages(params Params) (response AppWidgetsGetAppImagesResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("appWidgets.getAppImages", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AppWidgetsGetGroupImageUploadServerResponse struct. | ||||
| type AppWidgetsGetGroupImageUploadServerResponse struct { | ||||
| 	UploadURL string `json:"upload_url"` | ||||
| } | ||||
|  | ||||
| // AppWidgetsGetGroupImageUploadServer returns a URL for uploading | ||||
| // a photo to the community collection for community app widgets. | ||||
| // | ||||
| // https://vk.com/dev/appWidgets.getGroupImageUploadServer | ||||
| func (vk *VK) AppWidgetsGetGroupImageUploadServer(params Params) ( | ||||
| 	response AppWidgetsGetGroupImageUploadServerResponse, | ||||
| 	err error, | ||||
| ) { | ||||
| 	err = vk.RequestUnmarshal("appWidgets.getGroupImageUploadServer", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AppWidgetsGetGroupImagesResponse struct. | ||||
| type AppWidgetsGetGroupImagesResponse struct { | ||||
| 	Count int                      `json:"count"` | ||||
| 	Items []object.AppWidgetsImage `json:"items"` | ||||
| } | ||||
|  | ||||
| // AppWidgetsGetGroupImages returns a community collection of images for community app widgets. | ||||
| // | ||||
| // https://vk.com/dev/appWidgets.getGroupImages | ||||
| func (vk *VK) AppWidgetsGetGroupImages(params Params) (response AppWidgetsGetGroupImagesResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("appWidgets.getGroupImages", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AppWidgetsGetImagesByID returns an image for community app widgets by its ID. | ||||
| // | ||||
| // https://vk.com/dev/appWidgets.getImagesById | ||||
| func (vk *VK) AppWidgetsGetImagesByID(params Params) (response object.AppWidgetsImage, err error) { | ||||
| 	err = vk.RequestUnmarshal("appWidgets.getImagesById", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AppWidgetsSaveAppImage allows to save image into app collection for community app widgets. | ||||
| // | ||||
| // https://vk.com/dev/appWidgets.saveAppImage | ||||
| func (vk *VK) AppWidgetsSaveAppImage(params Params) (response object.AppWidgetsImage, err error) { | ||||
| 	err = vk.RequestUnmarshal("appWidgets.saveAppImage", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AppWidgetsSaveGroupImage allows to save image into community collection for community app widgets. | ||||
| // | ||||
| // https://vk.com/dev/appWidgets.saveGroupImage | ||||
| func (vk *VK) AppWidgetsSaveGroupImage(params Params) (response object.AppWidgetsImage, err error) { | ||||
| 	err = vk.RequestUnmarshal("appWidgets.saveGroupImage", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AppWidgetsUpdate allows to update community app widget. | ||||
| // | ||||
| // https://vk.com/dev/appWidgets.update | ||||
| func (vk *VK) AppWidgetsUpdate(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("appWidgets.update", &response, params) | ||||
|  | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										26
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/auth.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/auth.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| package api // import "github.com/SevereCloud/vksdk/v2/api" | ||||
|  | ||||
| // AuthCheckPhone checks a user's phone number for correctness. | ||||
| // | ||||
| // https://vk.com/dev/auth.checkPhone | ||||
| // | ||||
| // Deprecated: This method is deprecated and may be disabled soon, please avoid | ||||
| // using it. | ||||
| func (vk *VK) AuthCheckPhone(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("auth.checkPhone", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // AuthRestoreResponse struct. | ||||
| type AuthRestoreResponse struct { | ||||
| 	Success int    `json:"success"` | ||||
| 	SID     string `json:"sid"` | ||||
| } | ||||
|  | ||||
| // AuthRestore allows to restore account access using a code received via SMS. | ||||
| // | ||||
| // https://vk.com/dev/auth.restore | ||||
| func (vk *VK) AuthRestore(params Params) (response AuthRestoreResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("auth.restore", &response, params) | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										173
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/board.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/board.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,173 @@ | ||||
| package api // import "github.com/SevereCloud/vksdk/v2/api" | ||||
|  | ||||
| import ( | ||||
| 	"github.com/SevereCloud/vksdk/v2/object" | ||||
| ) | ||||
|  | ||||
| // BoardAddTopic creates a new topic on a community's discussion board. | ||||
| // | ||||
| // https://vk.com/dev/board.addTopic | ||||
| func (vk *VK) BoardAddTopic(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("board.addTopic", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // BoardCloseTopic closes a topic on a community's discussion board so that comments cannot be posted. | ||||
| // | ||||
| // https://vk.com/dev/board.closeTopic | ||||
| func (vk *VK) BoardCloseTopic(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("board.closeTopic", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // BoardCreateComment adds a comment on a topic on a community's discussion board. | ||||
| // | ||||
| // https://vk.com/dev/board.createComment | ||||
| func (vk *VK) BoardCreateComment(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("board.createComment", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // BoardDeleteComment deletes a comment on a topic on a community's discussion board. | ||||
| // | ||||
| // https://vk.com/dev/board.deleteComment | ||||
| func (vk *VK) BoardDeleteComment(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("board.deleteComment", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // BoardDeleteTopic deletes a topic from a community's discussion board. | ||||
| // | ||||
| // https://vk.com/dev/board.deleteTopic | ||||
| func (vk *VK) BoardDeleteTopic(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("board.deleteTopic", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // BoardEditComment edits a comment on a topic on a community's discussion board. | ||||
| // | ||||
| // https://vk.com/dev/board.editComment | ||||
| func (vk *VK) BoardEditComment(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("board.editComment", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // BoardEditTopic edits the title of a topic on a community's discussion board. | ||||
| // | ||||
| // https://vk.com/dev/board.editTopic | ||||
| func (vk *VK) BoardEditTopic(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("board.editTopic", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // BoardFixTopic pins a topic (fixes its place) to the top of a community's discussion board. | ||||
| // | ||||
| // https://vk.com/dev/board.fixTopic | ||||
| func (vk *VK) BoardFixTopic(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("board.fixTopic", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // BoardGetCommentsResponse struct. | ||||
| type BoardGetCommentsResponse struct { | ||||
| 	Count      int                        `json:"count"` | ||||
| 	Items      []object.BoardTopicComment `json:"items"` | ||||
| 	Poll       object.BoardTopicPoll      `json:"poll"` | ||||
| 	RealOffset int                        `json:"real_offset"` | ||||
| } | ||||
|  | ||||
| // BoardGetComments returns a list of comments on a topic on a community's discussion board. | ||||
| // | ||||
| // 	extended=0 | ||||
| // | ||||
| // https://vk.com/dev/board.getComments | ||||
| func (vk *VK) BoardGetComments(params Params) (response BoardGetCommentsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("board.getComments", &response, params, Params{"extended": false}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // BoardGetCommentsExtendedResponse struct. | ||||
| type BoardGetCommentsExtendedResponse struct { | ||||
| 	Count      int                        `json:"count"` | ||||
| 	Items      []object.BoardTopicComment `json:"items"` | ||||
| 	Poll       object.BoardTopicPoll      `json:"poll"` | ||||
| 	RealOffset int                        `json:"real_offset"` | ||||
| 	Profiles   []object.UsersUser         `json:"profiles"` | ||||
| 	Groups     []object.GroupsGroup       `json:"groups"` | ||||
| } | ||||
|  | ||||
| // BoardGetCommentsExtended returns a list of comments on a topic on a community's discussion board. | ||||
| // | ||||
| // 	extended=1 | ||||
| // | ||||
| // https://vk.com/dev/board.getComments | ||||
| func (vk *VK) BoardGetCommentsExtended(params Params) (response BoardGetCommentsExtendedResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("board.getComments", &response, params, Params{"extended": true}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // BoardGetTopicsResponse struct. | ||||
| type BoardGetTopicsResponse struct { | ||||
| 	Count        int                 `json:"count"` | ||||
| 	Items        []object.BoardTopic `json:"items"` | ||||
| 	DefaultOrder float64             `json:"default_order"` // BUG(VK): default_order int https://vk.com/bug136682 | ||||
| 	CanAddTopics object.BaseBoolInt  `json:"can_add_topics"` | ||||
| } | ||||
|  | ||||
| // BoardGetTopics returns a list of topics on a community's discussion board. | ||||
| // | ||||
| // 	extended=0 | ||||
| // | ||||
| // https://vk.com/dev/board.getTopics | ||||
| func (vk *VK) BoardGetTopics(params Params) (response BoardGetTopicsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("board.getTopics", &response, params, Params{"extended": false}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // BoardGetTopicsExtendedResponse struct. | ||||
| type BoardGetTopicsExtendedResponse struct { | ||||
| 	Count        int                  `json:"count"` | ||||
| 	Items        []object.BoardTopic  `json:"items"` | ||||
| 	DefaultOrder float64              `json:"default_order"` // BUG(VK): default_order int https://vk.com/bug136682 | ||||
| 	CanAddTopics object.BaseBoolInt   `json:"can_add_topics"` | ||||
| 	Profiles     []object.UsersUser   `json:"profiles"` | ||||
| 	Groups       []object.GroupsGroup `json:"groups"` | ||||
| } | ||||
|  | ||||
| // BoardGetTopicsExtended returns a list of topics on a community's discussion board. | ||||
| // | ||||
| // 	extended=1 | ||||
| // | ||||
| // https://vk.com/dev/board.getTopics | ||||
| func (vk *VK) BoardGetTopicsExtended(params Params) (response BoardGetTopicsExtendedResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("board.getTopics", &response, params, Params{"extended": true}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // BoardOpenTopic re-opens a previously closed topic on a community's discussion board. | ||||
| // | ||||
| // https://vk.com/dev/board.openTopic | ||||
| func (vk *VK) BoardOpenTopic(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("board.openTopic", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // BoardRestoreComment restores a comment deleted from a topic on a community's discussion board. | ||||
| // | ||||
| // https://vk.com/dev/board.restoreComment | ||||
| func (vk *VK) BoardRestoreComment(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("board.restoreComment", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // BoardUnfixTopic unpins a pinned topic from the top of a community's discussion board. | ||||
| // | ||||
| // https://vk.com/dev/board.unfixTopic | ||||
| func (vk *VK) BoardUnfixTopic(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("board.unfixTopic", &response, params) | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										7
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/captcha.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/captcha.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| package api | ||||
|  | ||||
| // CaptchaForce api method. | ||||
| func (vk *VK) CaptchaForce(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("captcha.force", &response, params) | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										163
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/database.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/database.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,163 @@ | ||||
| package api // import "github.com/SevereCloud/vksdk/v2/api" | ||||
|  | ||||
| import ( | ||||
| 	"github.com/SevereCloud/vksdk/v2/object" | ||||
| ) | ||||
|  | ||||
| // DatabaseGetChairsResponse struct. | ||||
| type DatabaseGetChairsResponse struct { | ||||
| 	Count int                 `json:"count"` | ||||
| 	Items []object.BaseObject `json:"items"` | ||||
| } | ||||
|  | ||||
| // DatabaseGetChairs returns list of chairs on a specified faculty. | ||||
| // | ||||
| // https://vk.com/dev/database.getChairs | ||||
| func (vk *VK) DatabaseGetChairs(params Params) (response DatabaseGetChairsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("database.getChairs", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DatabaseGetCitiesResponse struct. | ||||
| type DatabaseGetCitiesResponse struct { | ||||
| 	Count int                   `json:"count"` | ||||
| 	Items []object.DatabaseCity `json:"items"` | ||||
| } | ||||
|  | ||||
| // DatabaseGetCities returns a list of cities. | ||||
| // | ||||
| // https://vk.com/dev/database.getCities | ||||
| func (vk *VK) DatabaseGetCities(params Params) (response DatabaseGetCitiesResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("database.getCities", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DatabaseGetCitiesByIDResponse struct. | ||||
| type DatabaseGetCitiesByIDResponse []object.DatabaseCity | ||||
|  | ||||
| // DatabaseGetCitiesByID returns information about cities by their IDs. | ||||
| // | ||||
| // https://vk.com/dev/database.getCitiesByID | ||||
| func (vk *VK) DatabaseGetCitiesByID(params Params) (response DatabaseGetCitiesByIDResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("database.getCitiesById", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DatabaseGetCountriesResponse struct. | ||||
| type DatabaseGetCountriesResponse struct { | ||||
| 	Count int                 `json:"count"` | ||||
| 	Items []object.BaseObject `json:"items"` | ||||
| } | ||||
|  | ||||
| // DatabaseGetCountries returns a list of countries. | ||||
| // | ||||
| // https://vk.com/dev/database.getCountries | ||||
| func (vk *VK) DatabaseGetCountries(params Params) (response DatabaseGetCountriesResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("database.getCountries", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DatabaseGetCountriesByIDResponse struct. | ||||
| type DatabaseGetCountriesByIDResponse []object.BaseObject | ||||
|  | ||||
| // DatabaseGetCountriesByID returns information about countries by their IDs. | ||||
| // | ||||
| // https://vk.com/dev/database.getCountriesByID | ||||
| func (vk *VK) DatabaseGetCountriesByID(params Params) (response DatabaseGetCountriesByIDResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("database.getCountriesById", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DatabaseGetFacultiesResponse struct. | ||||
| type DatabaseGetFacultiesResponse struct { | ||||
| 	Count int                      `json:"count"` | ||||
| 	Items []object.DatabaseFaculty `json:"items"` | ||||
| } | ||||
|  | ||||
| // DatabaseGetFaculties returns a list of faculties (i.e., university departments). | ||||
| // | ||||
| // https://vk.com/dev/database.getFaculties | ||||
| func (vk *VK) DatabaseGetFaculties(params Params) (response DatabaseGetFacultiesResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("database.getFaculties", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DatabaseGetMetroStationsResponse struct. | ||||
| type DatabaseGetMetroStationsResponse struct { | ||||
| 	Count int                           `json:"count"` | ||||
| 	Items []object.DatabaseMetroStation `json:"items"` | ||||
| } | ||||
|  | ||||
| // DatabaseGetMetroStations returns the list of metro stations. | ||||
| // | ||||
| // https://vk.com/dev/database.getMetroStations | ||||
| func (vk *VK) DatabaseGetMetroStations(params Params) (response DatabaseGetMetroStationsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("database.getMetroStations", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DatabaseGetMetroStationsByIDResponse struct. | ||||
| type DatabaseGetMetroStationsByIDResponse []object.DatabaseMetroStation | ||||
|  | ||||
| // DatabaseGetMetroStationsByID returns information about one or several metro stations by their identifiers. | ||||
| // | ||||
| // https://vk.com/dev/database.getMetroStationsById | ||||
| func (vk *VK) DatabaseGetMetroStationsByID(params Params) (response DatabaseGetMetroStationsByIDResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("database.getMetroStationsById", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DatabaseGetRegionsResponse struct. | ||||
| type DatabaseGetRegionsResponse struct { | ||||
| 	Count int                     `json:"count"` | ||||
| 	Items []object.DatabaseRegion `json:"items"` | ||||
| } | ||||
|  | ||||
| // DatabaseGetRegions returns a list of regions. | ||||
| // | ||||
| // https://vk.com/dev/database.getRegions | ||||
| func (vk *VK) DatabaseGetRegions(params Params) (response DatabaseGetRegionsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("database.getRegions", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DatabaseGetSchoolClassesResponse struct. | ||||
| type DatabaseGetSchoolClassesResponse [][]interface{} | ||||
|  | ||||
| // DatabaseGetSchoolClasses returns a list of school classes specified for the country. | ||||
| // | ||||
| // BUG(VK): database.getSchoolClasses bad return. | ||||
| // | ||||
| // https://vk.com/dev/database.getSchoolClasses | ||||
| func (vk *VK) DatabaseGetSchoolClasses(params Params) (response DatabaseGetSchoolClassesResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("database.getSchoolClasses", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DatabaseGetSchoolsResponse struct. | ||||
| type DatabaseGetSchoolsResponse struct { | ||||
| 	Count int                     `json:"count"` | ||||
| 	Items []object.DatabaseSchool `json:"items"` | ||||
| } | ||||
|  | ||||
| // DatabaseGetSchools returns a list of schools. | ||||
| // | ||||
| // https://vk.com/dev/database.getSchools | ||||
| func (vk *VK) DatabaseGetSchools(params Params) (response DatabaseGetSchoolsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("database.getSchools", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DatabaseGetUniversitiesResponse struct. | ||||
| type DatabaseGetUniversitiesResponse struct { | ||||
| 	Count int                         `json:"count"` | ||||
| 	Items []object.DatabaseUniversity `json:"items"` | ||||
| } | ||||
|  | ||||
| // DatabaseGetUniversities returns a list of higher education institutions. | ||||
| // | ||||
| // https://vk.com/dev/database.getUniversities | ||||
| func (vk *VK) DatabaseGetUniversities(params Params) (response DatabaseGetUniversitiesResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("database.getUniversities", &response, params) | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										137
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/docs.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/docs.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,137 @@ | ||||
| package api // import "github.com/SevereCloud/vksdk/v2/api" | ||||
|  | ||||
| import ( | ||||
| 	"github.com/SevereCloud/vksdk/v2/object" | ||||
| ) | ||||
|  | ||||
| // DocsAdd copies a document to a user's or community's document list. | ||||
| // | ||||
| // https://vk.com/dev/docs.add | ||||
| func (vk *VK) DocsAdd(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("docs.add", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DocsDelete deletes a user or community document. | ||||
| // | ||||
| // https://vk.com/dev/docs.delete | ||||
| func (vk *VK) DocsDelete(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("docs.delete", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DocsEdit edits a document. | ||||
| // | ||||
| // https://vk.com/dev/docs.edit | ||||
| func (vk *VK) DocsEdit(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("docs.edit", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DocsGetResponse struct. | ||||
| type DocsGetResponse struct { | ||||
| 	Count int              `json:"count"` | ||||
| 	Items []object.DocsDoc `json:"items"` | ||||
| } | ||||
|  | ||||
| // DocsGet returns detailed information about user or community documents. | ||||
| // | ||||
| // https://vk.com/dev/docs.get | ||||
| func (vk *VK) DocsGet(params Params) (response DocsGetResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("docs.get", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DocsGetByIDResponse struct. | ||||
| type DocsGetByIDResponse []object.DocsDoc | ||||
|  | ||||
| // DocsGetByID returns information about documents by their IDs. | ||||
| // | ||||
| // https://vk.com/dev/docs.getById | ||||
| func (vk *VK) DocsGetByID(params Params) (response DocsGetByIDResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("docs.getById", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DocsGetMessagesUploadServerResponse struct. | ||||
| type DocsGetMessagesUploadServerResponse struct { | ||||
| 	UploadURL string `json:"upload_url"` | ||||
| } | ||||
|  | ||||
| // DocsGetMessagesUploadServer returns the server address for document upload. | ||||
| // | ||||
| // https://vk.com/dev/docs.getMessagesUploadServer | ||||
| func (vk *VK) DocsGetMessagesUploadServer(params Params) (response DocsGetMessagesUploadServerResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("docs.getMessagesUploadServer", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DocsGetTypesResponse struct. | ||||
| type DocsGetTypesResponse struct { | ||||
| 	Count int                   `json:"count"` | ||||
| 	Items []object.DocsDocTypes `json:"items"` | ||||
| } | ||||
|  | ||||
| // DocsGetTypes returns documents types available for current user. | ||||
| // | ||||
| // https://vk.com/dev/docs.getTypes | ||||
| func (vk *VK) DocsGetTypes(params Params) (response DocsGetTypesResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("docs.getTypes", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DocsGetUploadServerResponse struct. | ||||
| type DocsGetUploadServerResponse struct { | ||||
| 	UploadURL string `json:"upload_url"` | ||||
| } | ||||
|  | ||||
| // DocsGetUploadServer returns the server address for document upload. | ||||
| // | ||||
| // https://vk.com/dev/docs.getUploadServer | ||||
| func (vk *VK) DocsGetUploadServer(params Params) (response DocsGetUploadServerResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("docs.getUploadServer", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DocsGetWallUploadServerResponse struct. | ||||
| type DocsGetWallUploadServerResponse struct { | ||||
| 	UploadURL string `json:"upload_url"` | ||||
| } | ||||
|  | ||||
| // DocsGetWallUploadServer returns the server address for document upload onto a user's or community's wall. | ||||
| // | ||||
| // https://vk.com/dev/docs.getWallUploadServer | ||||
| func (vk *VK) DocsGetWallUploadServer(params Params) (response DocsGetWallUploadServerResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("docs.getWallUploadServer", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DocsSaveResponse struct. | ||||
| type DocsSaveResponse struct { | ||||
| 	Type         string                      `json:"type"` | ||||
| 	AudioMessage object.MessagesAudioMessage `json:"audio_message"` | ||||
| 	Doc          object.DocsDoc              `json:"doc"` | ||||
| 	Graffiti     object.MessagesGraffiti     `json:"graffiti"` | ||||
| } | ||||
|  | ||||
| // DocsSave saves a document after uploading it to a server. | ||||
| // | ||||
| // https://vk.com/dev/docs.save | ||||
| func (vk *VK) DocsSave(params Params) (response DocsSaveResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("docs.save", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DocsSearchResponse struct. | ||||
| type DocsSearchResponse struct { | ||||
| 	Count int              `json:"count"` | ||||
| 	Items []object.DocsDoc `json:"items"` | ||||
| } | ||||
|  | ||||
| // DocsSearch returns a list of documents matching the search criteria. | ||||
| // | ||||
| // https://vk.com/dev/docs.search | ||||
| func (vk *VK) DocsSearch(params Params) (response DocsSearchResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("docs.search", &response, params) | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										49
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/donut.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/donut.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| package api | ||||
|  | ||||
| import "github.com/SevereCloud/vksdk/v2/object" | ||||
|  | ||||
| // DonutGetFriendsResponse struct. | ||||
| type DonutGetFriendsResponse struct { | ||||
| 	Count int                `json:"count"` | ||||
| 	Items []object.UsersUser `json:"items"` | ||||
| } | ||||
|  | ||||
| // DonutGetFriends method. | ||||
| // | ||||
| // https://vk.com/dev/donut.getFriends | ||||
| func (vk *VK) DonutGetFriends(params Params) (response DonutGetFriendsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("donut.getFriends", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DonutGetSubscription method. | ||||
| // | ||||
| // https://vk.com/dev/donut.getSubscription | ||||
| func (vk *VK) DonutGetSubscription(params Params) (response object.DonutDonatorSubscriptionInfo, err error) { | ||||
| 	err = vk.RequestUnmarshal("donut.getSubscription", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DonutGetSubscriptionsResponse struct. | ||||
| type DonutGetSubscriptionsResponse struct { | ||||
| 	Subscriptions []object.DonutDonatorSubscriptionInfo `json:"subscriptions"` | ||||
| 	Count         int                                   `json:"count"` | ||||
| 	Profiles      []object.UsersUser                    `json:"profiles"` | ||||
| 	Groups        []object.GroupsGroup                  `json:"groups"` | ||||
| } | ||||
|  | ||||
| // DonutGetSubscriptions method. | ||||
| // | ||||
| // https://vk.com/dev/donut.getSubscriptions | ||||
| func (vk *VK) DonutGetSubscriptions(params Params) (response DonutGetSubscriptionsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("donut.getSubscriptions", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DonutIsDon method. | ||||
| // | ||||
| // https://vk.com/dev/donut.isDon | ||||
| func (vk *VK) DonutIsDon(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("donut.isDon", &response, params) | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										19
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/downloadedGames.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/downloadedGames.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| package api // import "github.com/SevereCloud/vksdk/v2/api" | ||||
|  | ||||
| import ( | ||||
| 	"github.com/SevereCloud/vksdk/v2/object" | ||||
| ) | ||||
|  | ||||
| // DownloadedGamesGetPaidStatusResponse struct. | ||||
| type DownloadedGamesGetPaidStatusResponse struct { | ||||
| 	IsPaid object.BaseBoolInt `json:"is_paid"` | ||||
| } | ||||
|  | ||||
| // DownloadedGamesGetPaidStatus method. | ||||
| // | ||||
| // https://vk.com/dev/downloadedGames.getPaidStatus | ||||
| func (vk *VK) DownloadedGamesGetPaidStatus(params Params) (response DownloadedGamesGetPaidStatusResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("downloadedGames.getPaidStatus", &response, params, Params{"extended": false}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										927
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										927
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,927 @@ | ||||
| package api | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/SevereCloud/vksdk/v2/object" | ||||
| ) | ||||
|  | ||||
| // ErrorType is the type of an error. | ||||
| type ErrorType int | ||||
|  | ||||
| // Error returns the message of a ErrorType. | ||||
| func (e ErrorType) Error() string { | ||||
| 	return fmt.Sprintf("api: error with code %d", e) | ||||
| } | ||||
|  | ||||
| // Error codes. See https://vk.com/dev/errors | ||||
| const ( | ||||
| 	ErrNoType ErrorType = 0 // NoType error | ||||
|  | ||||
| 	// Unknown error occurred | ||||
| 	// | ||||
| 	// Try again later. | ||||
| 	ErrUnknown ErrorType = 1 | ||||
|  | ||||
| 	// Application is disabled. Enable your application or use test mode | ||||
| 	// | ||||
| 	// You need to switch on the app in Settings | ||||
| 	// https://vk.com/editapp?id={Your API_ID} | ||||
| 	// or use the test mode (test_mode=1). | ||||
| 	ErrDisabled ErrorType = 2 | ||||
|  | ||||
| 	// Unknown method passed. | ||||
| 	// | ||||
| 	// Check the method name: http://vk.com/dev/methods | ||||
| 	ErrMethod    ErrorType = 3 | ||||
| 	ErrSignature ErrorType = 4 // Incorrect signature | ||||
|  | ||||
| 	// User authorization failed | ||||
| 	// | ||||
| 	// Make sure that you use a correct authorization type. | ||||
| 	ErrAuth ErrorType = 5 | ||||
|  | ||||
| 	// Too many requests per second | ||||
| 	// | ||||
| 	// Decrease the request frequency or use the execute method. | ||||
| 	// More details on frequency limits here: | ||||
| 	// https://vk.com/dev/api_requests | ||||
| 	ErrTooMany ErrorType = 6 | ||||
|  | ||||
| 	// Permission to perform this action is denied | ||||
| 	// | ||||
| 	// Make sure that your have received required permissions during the | ||||
| 	// authorization. | ||||
| 	// You can do it with the account.getAppPermissions method. | ||||
| 	// https://vk.com/dev/permissions | ||||
| 	ErrPermission ErrorType = 7 | ||||
|  | ||||
| 	// Invalid request | ||||
| 	// | ||||
| 	// Check the request syntax and used parameters list (it can be found on | ||||
| 	// a method description page). | ||||
| 	ErrRequest ErrorType = 8 | ||||
|  | ||||
| 	// Flood control | ||||
| 	// | ||||
| 	// You need to decrease the count of identical requests. For more efficient | ||||
| 	// work you may use execute. | ||||
| 	ErrFlood ErrorType = 9 | ||||
|  | ||||
| 	// Internal server error | ||||
| 	// | ||||
| 	// Try again later. | ||||
| 	ErrServer ErrorType = 10 | ||||
|  | ||||
| 	// In test mode application should be disabled or user should be authorized | ||||
| 	// | ||||
| 	// Switch the app off in Settings: | ||||
| 	// | ||||
| 	// 	https://vk.com/editapp?id={Your API_ID} | ||||
| 	// | ||||
| 	ErrEnabledInTest ErrorType = 11 | ||||
|  | ||||
| 	// Unable to compile code. | ||||
| 	ErrCompile ErrorType = 12 | ||||
|  | ||||
| 	// Runtime error occurred during code invocation. | ||||
| 	ErrRuntime ErrorType = 13 | ||||
|  | ||||
| 	// Captcha needed. | ||||
| 	// | ||||
| 	// See https://vk.com/dev/captcha_error | ||||
| 	ErrCaptcha ErrorType = 14 | ||||
|  | ||||
| 	// Access denied | ||||
| 	// | ||||
| 	// Make sure that you use correct identifiers and the content is available | ||||
| 	// for the user in the full version of the site. | ||||
| 	ErrAccess ErrorType = 15 | ||||
|  | ||||
| 	// HTTP authorization failed | ||||
| 	// | ||||
| 	// To avoid this error check if a user has the 'Use secure connection' | ||||
| 	// option enabled with the account.getInfo method. | ||||
| 	ErrAuthHTTPS ErrorType = 16 | ||||
|  | ||||
| 	// Validation required | ||||
| 	// | ||||
| 	// Make sure that you don't use a token received with | ||||
| 	// http://vk.com/dev/auth_mobile for a request from the server. | ||||
| 	// It's restricted. | ||||
| 	// | ||||
| 	// https://vk.com/dev/need_validation | ||||
| 	ErrAuthValidation ErrorType = 17 | ||||
| 	ErrUserDeleted    ErrorType = 18 // User was deleted or banned | ||||
| 	ErrBlocked        ErrorType = 19 // Content blocked | ||||
|  | ||||
| 	// Permission to perform this action is denied for non-standalone | ||||
| 	// applications. | ||||
| 	ErrMethodPermission ErrorType = 20 | ||||
|  | ||||
| 	// Permission to perform this action is allowed only for standalone and | ||||
| 	// OpenAPI applications. | ||||
| 	ErrMethodAds ErrorType = 21 | ||||
| 	ErrUpload    ErrorType = 22 // Upload error | ||||
|  | ||||
| 	// This method was disabled. | ||||
| 	// | ||||
| 	// All the methods available now are listed here: http://vk.com/dev/methods | ||||
| 	ErrMethodDisabled ErrorType = 23 | ||||
|  | ||||
| 	// Confirmation required | ||||
| 	// | ||||
| 	// In some cases VK requires to request action confirmation from the user | ||||
| 	// (for Standalone apps only). | ||||
| 	// | ||||
| 	// Following parameter is transmitted with the error message as well: | ||||
| 	// | ||||
| 	// confirmation_text – text of the message to be shown in the default | ||||
| 	// confirmation window. | ||||
| 	// | ||||
| 	// The app should display the default confirmation window | ||||
| 	// with text from confirmation_text and two buttons: "Continue" and | ||||
| 	// "Cancel". | ||||
| 	// If user confirms the action repeat the request with an extra parameter: | ||||
| 	// | ||||
| 	// 	confirm = 1. | ||||
| 	// | ||||
| 	// https://vk.com/dev/need_confirmation | ||||
| 	ErrNeedConfirmation      ErrorType = 24 | ||||
| 	ErrNeedTokenConfirmation ErrorType = 25 // Token confirmation required | ||||
| 	ErrGroupAuth             ErrorType = 27 // Group authorization failed | ||||
| 	ErrAppAuth               ErrorType = 28 // Application authorization failed | ||||
|  | ||||
| 	// Rate limit reached. | ||||
| 	// | ||||
| 	// More details on rate limits here: https://vk.com/dev/data_limits | ||||
| 	ErrRateLimit      ErrorType = 29 | ||||
| 	ErrPrivateProfile ErrorType = 30 // This profile is private | ||||
|  | ||||
| 	// Method execution was interrupted due to timeout. | ||||
| 	ErrExecutionTimeout ErrorType = 36 | ||||
|  | ||||
| 	// User was banned. | ||||
| 	ErrUserBanned ErrorType = 37 | ||||
|  | ||||
| 	// Unknown application. | ||||
| 	ErrUnknownApplication ErrorType = 38 | ||||
|  | ||||
| 	// Unknown user. | ||||
| 	ErrUnknownUser ErrorType = 39 | ||||
|  | ||||
| 	// Unknown group. | ||||
| 	ErrUnknownGroup ErrorType = 40 | ||||
|  | ||||
| 	// One of the parameters specified was missing or invalid | ||||
| 	// | ||||
| 	// Check the required parameters list and their format on a method | ||||
| 	// description page. | ||||
| 	ErrParam ErrorType = 100 | ||||
|  | ||||
| 	// Invalid application API ID | ||||
| 	// | ||||
| 	// Find the app in the administrated list in settings: | ||||
| 	// http://vk.com/apps?act=settings | ||||
| 	// And set the correct API_ID in the request. | ||||
| 	ErrParamAPIID   ErrorType = 101 | ||||
| 	ErrLimits       ErrorType = 103 // Out of limits | ||||
| 	ErrNotFound     ErrorType = 104 // Not found | ||||
| 	ErrSaveFile     ErrorType = 105 // Couldn't save file | ||||
| 	ErrActionFailed ErrorType = 106 // Unable to process action | ||||
|  | ||||
| 	// Invalid user id | ||||
| 	// | ||||
| 	// Make sure that you use a correct id. You can get an id using a screen | ||||
| 	// name with the utils.resolveScreenName method. | ||||
| 	ErrParamUserID  ErrorType = 113 | ||||
| 	ErrParamAlbumID ErrorType = 114 // Invalid album id | ||||
| 	ErrParamServer  ErrorType = 118 // Invalid server | ||||
| 	ErrParamTitle   ErrorType = 119 // Invalid title | ||||
| 	ErrParamPhotos  ErrorType = 122 // Invalid photos | ||||
| 	ErrParamHash    ErrorType = 121 // Invalid hash | ||||
| 	ErrParamPhoto   ErrorType = 129 // Invalid photo | ||||
| 	ErrParamGroupID ErrorType = 125 // Invalid group id | ||||
| 	ErrParamPageID  ErrorType = 140 // Page not found | ||||
| 	ErrAccessPage   ErrorType = 141 // Access to page denied | ||||
|  | ||||
| 	// The mobile number of the user is unknown. | ||||
| 	ErrMobileNotActivated ErrorType = 146 | ||||
|  | ||||
| 	// Application has insufficient funds. | ||||
| 	ErrInsufficientFunds ErrorType = 147 | ||||
|  | ||||
| 	// Access to the menu of the user denied. | ||||
| 	ErrAccessMenu ErrorType = 148 | ||||
|  | ||||
| 	// Invalid timestamp | ||||
| 	// | ||||
| 	// You may get a correct value with the utils.getServerTime method. | ||||
| 	ErrParamTimestamp ErrorType = 150 | ||||
| 	ErrFriendsListID  ErrorType = 171 // Invalid list id | ||||
|  | ||||
| 	// Reached the maximum number of lists. | ||||
| 	ErrFriendsListLimit ErrorType = 173 | ||||
|  | ||||
| 	// Cannot add user himself as friend. | ||||
| 	ErrFriendsAddYourself ErrorType = 174 | ||||
|  | ||||
| 	// Cannot add this user to friends as they have put you on their blacklist. | ||||
| 	ErrFriendsAddInEnemy ErrorType = 175 | ||||
|  | ||||
| 	// Cannot add this user to friends as you put him on blacklist. | ||||
| 	ErrFriendsAddEnemy ErrorType = 176 | ||||
|  | ||||
| 	// Cannot add this user to friends as user not found. | ||||
| 	ErrFriendsAddNotFound ErrorType = 177 | ||||
| 	ErrParamNoteID        ErrorType = 180 // Note not found | ||||
| 	ErrAccessNote         ErrorType = 181 // Access to note denied | ||||
| 	ErrAccessNoteComment  ErrorType = 182 // You can't comment this note | ||||
| 	ErrAccessComment      ErrorType = 183 // Access to comment denied | ||||
|  | ||||
| 	// Access to album denied | ||||
| 	// | ||||
| 	// Make sure you use correct ids (owner_id is always positive for users, | ||||
| 	// negative for communities) and the current user has access to the | ||||
| 	// requested content in the full version of the site. | ||||
| 	ErrAccessAlbum ErrorType = 200 | ||||
|  | ||||
| 	// Access to audio denied | ||||
| 	// | ||||
| 	// Make sure you use correct ids (owner_id is always positive for users, | ||||
| 	// negative for communities) and the current user has access to the | ||||
| 	// requested content in the full version of the site. | ||||
| 	ErrAccessAudio ErrorType = 201 | ||||
|  | ||||
| 	// Access to group denied | ||||
| 	// | ||||
| 	// Make sure that the current user is a member or admin of the community | ||||
| 	// (for closed and private groups and events). | ||||
| 	ErrAccessGroup ErrorType = 203 | ||||
|  | ||||
| 	// Access denied. | ||||
| 	ErrAccessVideo ErrorType = 204 | ||||
|  | ||||
| 	// Access denied. | ||||
| 	ErrAccessMarket ErrorType = 205 | ||||
|  | ||||
| 	// Access to wall's post denied. | ||||
| 	ErrWallAccessPost ErrorType = 210 | ||||
|  | ||||
| 	// Access to wall's comment denied. | ||||
| 	ErrWallAccessComment ErrorType = 211 | ||||
|  | ||||
| 	// Access to post comments denied. | ||||
| 	ErrWallAccessReplies ErrorType = 212 | ||||
|  | ||||
| 	// Access to status replies denied. | ||||
| 	ErrWallAccessAddReply ErrorType = 213 | ||||
|  | ||||
| 	// Access to adding post denied. | ||||
| 	ErrWallAddPost ErrorType = 214 | ||||
|  | ||||
| 	// Advertisement post was recently added. | ||||
| 	ErrWallAdsPublished ErrorType = 219 | ||||
|  | ||||
| 	// Too many recipients. | ||||
| 	ErrWallTooManyRecipients ErrorType = 220 | ||||
|  | ||||
| 	// User disabled track name broadcast. | ||||
| 	ErrStatusNoAudio ErrorType = 221 | ||||
|  | ||||
| 	// Hyperlinks are forbidden. | ||||
| 	ErrWallLinksForbidden ErrorType = 222 | ||||
|  | ||||
| 	// Too many replies. | ||||
| 	ErrWallReplyOwnerFlood ErrorType = 223 | ||||
|  | ||||
| 	// Too many ads posts. | ||||
| 	ErrWallAdsPostLimitReached ErrorType = 224 | ||||
|  | ||||
| 	// Donut is disabled. | ||||
| 	ErrDonutDisabled ErrorType = 225 | ||||
|  | ||||
| 	// Reaction can not be applied to the object. | ||||
| 	ErrLikesReactionCanNotBeApplied ErrorType = 232 | ||||
|  | ||||
| 	// Access to poll denied. | ||||
| 	ErrPollsAccess ErrorType = 250 | ||||
|  | ||||
| 	// Invalid answer id. | ||||
| 	ErrPollsAnswerID ErrorType = 252 | ||||
|  | ||||
| 	// Invalid poll id. | ||||
| 	ErrPollsPollID ErrorType = 251 | ||||
|  | ||||
| 	// Access denied, please vote first. | ||||
| 	ErrPollsAccessWithoutVote ErrorType = 253 | ||||
|  | ||||
| 	// Access to the groups list is denied due to the user's privacy settings. | ||||
| 	ErrAccessGroups ErrorType = 260 | ||||
|  | ||||
| 	// This album is full | ||||
| 	// | ||||
| 	// You need to delete the odd objects from the album or use another album. | ||||
| 	ErrAlbumFull   ErrorType = 300 | ||||
| 	ErrAlbumsLimit ErrorType = 302 // Albums number limit is reached | ||||
|  | ||||
| 	// Permission denied. You must enable votes processing in application | ||||
| 	// settings | ||||
| 	// | ||||
| 	// Check the app settings: | ||||
| 	// | ||||
| 	// 	http://vk.com/editapp?id={Your API_ID}§ion=payments | ||||
| 	// | ||||
| 	ErrVotesPermission ErrorType = 500 | ||||
|  | ||||
| 	// Not enough votes. | ||||
| 	ErrVotes ErrorType = 503 | ||||
|  | ||||
| 	// Not enough money on owner's balance. | ||||
| 	ErrNotEnoughMoney ErrorType = 504 | ||||
|  | ||||
| 	// Permission denied. You have no access to operations specified with | ||||
| 	// given object(s). | ||||
| 	ErrAdsPermission ErrorType = 600 | ||||
|  | ||||
| 	// Permission denied. You have requested too many actions this day. Try | ||||
| 	// later. | ||||
| 	ErrWeightedFlood ErrorType = 601 | ||||
|  | ||||
| 	// Some part of the request has not been completed. | ||||
| 	ErrAdsPartialSuccess ErrorType = 602 | ||||
|  | ||||
| 	// Some ads error occurred. | ||||
| 	ErrAdsSpecific ErrorType = 603 | ||||
|  | ||||
| 	// Invalid domain. | ||||
| 	ErrAdsDomainInvalid ErrorType = 604 | ||||
|  | ||||
| 	// Domain is forbidden. | ||||
| 	ErrAdsDomainForbidden ErrorType = 605 | ||||
|  | ||||
| 	// Domain is reserved. | ||||
| 	ErrAdsDomainReserved ErrorType = 606 | ||||
|  | ||||
| 	// Domain is occupied. | ||||
| 	ErrAdsDomainOccupied ErrorType = 607 | ||||
|  | ||||
| 	// Domain is active. | ||||
| 	ErrAdsDomainActive ErrorType = 608 | ||||
|  | ||||
| 	// Domain app is invalid. | ||||
| 	ErrAdsDomainAppInvalid ErrorType = 609 | ||||
|  | ||||
| 	// Domain app is forbidden. | ||||
| 	ErrAdsDomainAppForbidden ErrorType = 610 | ||||
|  | ||||
| 	// Application must be verified. | ||||
| 	ErrAdsApplicationMustBeVerified ErrorType = 611 | ||||
|  | ||||
| 	// Application must be in domains list of site of ad unit. | ||||
| 	ErrAdsApplicationMustBeInDomainsList ErrorType = 612 | ||||
|  | ||||
| 	// Application is blocked. | ||||
| 	ErrAdsApplicationBlocked ErrorType = 613 | ||||
|  | ||||
| 	// Domain of type specified is forbidden in current office type. | ||||
| 	ErrAdsDomainTypeForbiddenInCurrentOffice ErrorType = 614 | ||||
|  | ||||
| 	// Domain group is invalid. | ||||
| 	ErrAdsDomainGroupInvalid ErrorType = 615 | ||||
|  | ||||
| 	// Domain group is forbidden. | ||||
| 	ErrAdsDomainGroupForbidden ErrorType = 616 | ||||
|  | ||||
| 	// Domain app is blocked. | ||||
| 	ErrAdsDomainAppBlocked ErrorType = 617 | ||||
|  | ||||
| 	// Domain group is not open. | ||||
| 	ErrAdsDomainGroupNotOpen ErrorType = 618 | ||||
|  | ||||
| 	// Domain group is not possible to be joined to adsweb. | ||||
| 	ErrAdsDomainGroupNotPossibleJoined ErrorType = 619 | ||||
|  | ||||
| 	// Domain group is blocked. | ||||
| 	ErrAdsDomainGroupBlocked ErrorType = 620 | ||||
|  | ||||
| 	// Domain group has restriction: links are forbidden. | ||||
| 	ErrAdsDomainGroupLinksForbidden ErrorType = 621 | ||||
|  | ||||
| 	// Domain group has restriction: excluded from search. | ||||
| 	ErrAdsDomainGroupExcludedFromSearch ErrorType = 622 | ||||
|  | ||||
| 	// Domain group has restriction: cover is forbidden. | ||||
| 	ErrAdsDomainGroupCoverForbidden ErrorType = 623 | ||||
|  | ||||
| 	// Domain group has wrong category. | ||||
| 	ErrAdsDomainGroupWrongCategory ErrorType = 624 | ||||
|  | ||||
| 	// Domain group has wrong name. | ||||
| 	ErrAdsDomainGroupWrongName ErrorType = 625 | ||||
|  | ||||
| 	// Domain group has low posts reach. | ||||
| 	ErrAdsDomainGroupLowPostsReach ErrorType = 626 | ||||
|  | ||||
| 	// Domain group has wrong class. | ||||
| 	ErrAdsDomainGroupWrongClass ErrorType = 627 | ||||
|  | ||||
| 	// Domain group is created recently. | ||||
| 	ErrAdsDomainGroupCreatedRecently ErrorType = 628 | ||||
|  | ||||
| 	// Object deleted. | ||||
| 	ErrAdsObjectDeleted ErrorType = 629 | ||||
|  | ||||
| 	// Lookalike request with same source already in progress. | ||||
| 	ErrAdsLookalikeRequestAlreadyInProgress ErrorType = 630 | ||||
|  | ||||
| 	// Max count of lookalike requests per day reached. | ||||
| 	ErrAdsLookalikeRequestsLimit ErrorType = 631 | ||||
|  | ||||
| 	// Given audience is too small. | ||||
| 	ErrAdsAudienceTooSmall ErrorType = 632 | ||||
|  | ||||
| 	// Given audience is too large. | ||||
| 	ErrAdsAudienceTooLarge ErrorType = 633 | ||||
|  | ||||
| 	// Lookalike request audience save already in progress. | ||||
| 	ErrAdsLookalikeAudienceSaveAlreadyInProgress ErrorType = 634 | ||||
|  | ||||
| 	// Max count of lookalike request audience saves per day reached. | ||||
| 	ErrAdsLookalikeSavesLimit ErrorType = 635 | ||||
|  | ||||
| 	// Max count of retargeting groups reached. | ||||
| 	ErrAdsRetargetingGroupsLimit ErrorType = 636 | ||||
|  | ||||
| 	// Domain group has active nemesis punishment. | ||||
| 	ErrAdsDomainGroupActiveNemesisPunishment ErrorType = 637 | ||||
|  | ||||
| 	// Cannot edit creator role. | ||||
| 	ErrGroupChangeCreator ErrorType = 700 | ||||
|  | ||||
| 	// User should be in club. | ||||
| 	ErrGroupNotInClub ErrorType = 701 | ||||
|  | ||||
| 	// Too many officers in club. | ||||
| 	ErrGroupTooManyOfficers ErrorType = 702 | ||||
|  | ||||
| 	// You need to enable 2FA for this action. | ||||
| 	ErrGroupNeed2fa ErrorType = 703 | ||||
|  | ||||
| 	// User needs to enable 2FA for this action. | ||||
| 	ErrGroupHostNeed2fa ErrorType = 704 | ||||
|  | ||||
| 	// Too many addresses in club. | ||||
| 	ErrGroupTooManyAddresses ErrorType = 706 | ||||
|  | ||||
| 	// "Application is not installed in community. | ||||
| 	ErrGroupAppIsNotInstalledInCommunity ErrorType = 711 | ||||
|  | ||||
| 	// Invite link is invalid - expired, deleted or not exists. | ||||
| 	ErrGroupInvalidInviteLink ErrorType = 714 | ||||
|  | ||||
| 	// This video is already added. | ||||
| 	ErrVideoAlreadyAdded ErrorType = 800 | ||||
|  | ||||
| 	// Comments for this video are closed. | ||||
| 	ErrVideoCommentsClosed ErrorType = 801 | ||||
|  | ||||
| 	// Can't send messages for users from blacklist. | ||||
| 	ErrMessagesUserBlocked ErrorType = 900 | ||||
|  | ||||
| 	// Can't send messages for users without permission. | ||||
| 	ErrMessagesDenySend ErrorType = 901 | ||||
|  | ||||
| 	// Can't send messages to this user due to their privacy settings. | ||||
| 	ErrMessagesPrivacy ErrorType = 902 | ||||
|  | ||||
| 	// Value of ts or pts is too old. | ||||
| 	ErrMessagesTooOldPts ErrorType = 907 | ||||
|  | ||||
| 	// Value of ts or pts is too new. | ||||
| 	ErrMessagesTooNewPts ErrorType = 908 | ||||
|  | ||||
| 	// Can't edit this message, because it's too old. | ||||
| 	ErrMessagesEditExpired ErrorType = 909 | ||||
|  | ||||
| 	// Can't sent this message, because it's too big. | ||||
| 	ErrMessagesTooBig ErrorType = 910 | ||||
|  | ||||
| 	// Keyboard format is invalid. | ||||
| 	ErrMessagesKeyboardInvalid ErrorType = 911 | ||||
|  | ||||
| 	// This is a chat bot feature, change this status in settings. | ||||
| 	ErrMessagesChatBotFeature ErrorType = 912 | ||||
|  | ||||
| 	// Too many forwarded messages. | ||||
| 	ErrMessagesTooLongForwards ErrorType = 913 | ||||
|  | ||||
| 	// Message is too long. | ||||
| 	ErrMessagesTooLongMessage ErrorType = 914 | ||||
|  | ||||
| 	// You don't have access to this chat. | ||||
| 	ErrMessagesChatUserNoAccess ErrorType = 917 | ||||
|  | ||||
| 	// You can't see invite link for this chat. | ||||
| 	ErrMessagesCantSeeInviteLink ErrorType = 919 | ||||
|  | ||||
| 	// Can't edit this kind of message. | ||||
| 	ErrMessagesEditKindDisallowed ErrorType = 920 | ||||
|  | ||||
| 	// Can't forward these messages. | ||||
| 	ErrMessagesCantFwd ErrorType = 921 | ||||
|  | ||||
| 	// Can't delete this message for everybody. | ||||
| 	ErrMessagesCantDeleteForAll ErrorType = 924 | ||||
|  | ||||
| 	// You are not admin of this chat. | ||||
| 	ErrMessagesChatNotAdmin ErrorType = 925 | ||||
|  | ||||
| 	// Chat does not exist. | ||||
| 	ErrMessagesChatNotExist ErrorType = 927 | ||||
|  | ||||
| 	// You can't change invite link for this chat. | ||||
| 	ErrMessagesCantChangeInviteLink ErrorType = 931 | ||||
|  | ||||
| 	// Your community can't interact with this peer. | ||||
| 	ErrMessagesGroupPeerAccess ErrorType = 932 | ||||
|  | ||||
| 	// User not found in chat. | ||||
| 	ErrMessagesChatUserNotInChat ErrorType = 935 | ||||
|  | ||||
| 	// Contact not found. | ||||
| 	ErrMessagesContactNotFound ErrorType = 936 | ||||
|  | ||||
| 	// Message request already send. | ||||
| 	ErrMessagesMessageRequestAlreadySend ErrorType = 939 | ||||
|  | ||||
| 	// Too many posts in messages. | ||||
| 	ErrMessagesTooManyPosts ErrorType = 940 | ||||
|  | ||||
| 	// Cannot pin one-time story. | ||||
| 	ErrMessagesCantPinOneTimeStory ErrorType = 942 | ||||
|  | ||||
| 	// Cannot use this intent. | ||||
| 	ErrMessagesCantUseIntent ErrorType = 943 | ||||
|  | ||||
| 	// Limits overflow for this intent. | ||||
| 	ErrMessagesLimitIntent ErrorType = 944 | ||||
|  | ||||
| 	// Chat was disabled. | ||||
| 	ErrMessagesChatDisabled ErrorType = 945 | ||||
|  | ||||
| 	// Chat not support. | ||||
| 	ErrMessagesChatNotSupported ErrorType = 946 | ||||
|  | ||||
| 	// Can't add user to chat, because user has no access to group. | ||||
| 	ErrMessagesMemberAccessToGroupDenied ErrorType = 947 | ||||
|  | ||||
| 	// Can't edit pinned message yet. | ||||
| 	ErrMessagesEditPinned ErrorType = 949 | ||||
|  | ||||
| 	// Can't send message, reply timed out. | ||||
| 	ErrMessagesReplyTimedOut ErrorType = 950 | ||||
|  | ||||
| 	// Invalid phone number. | ||||
| 	ErrParamPhone ErrorType = 1000 | ||||
|  | ||||
| 	// This phone number is used by another user. | ||||
| 	ErrPhoneAlreadyUsed ErrorType = 1004 | ||||
|  | ||||
| 	// Too many auth attempts, try again later. | ||||
| 	ErrAuthFloodError ErrorType = 1105 | ||||
|  | ||||
| 	// Processing.. Try later. | ||||
| 	ErrAuthDelay ErrorType = 1112 | ||||
|  | ||||
| 	// Invalid document id. | ||||
| 	ErrParamDocID ErrorType = 1150 | ||||
|  | ||||
| 	// Access to document deleting is denied. | ||||
| 	ErrParamDocDeleteAccess ErrorType = 1151 | ||||
|  | ||||
| 	// Invalid document title. | ||||
| 	ErrParamDocTitle ErrorType = 1152 | ||||
|  | ||||
| 	// Access to document is denied. | ||||
| 	ErrParamDocAccess ErrorType = 1153 | ||||
|  | ||||
| 	// Original photo was changed. | ||||
| 	ErrPhotoChanged ErrorType = 1160 | ||||
|  | ||||
| 	// Too many feed lists. | ||||
| 	ErrTooManyLists ErrorType = 1170 | ||||
|  | ||||
| 	// This achievement is already unlocked. | ||||
| 	ErrAppsAlreadyUnlocked ErrorType = 1251 | ||||
|  | ||||
| 	// Subscription not found. | ||||
| 	ErrAppsSubscriptionNotFound ErrorType = 1256 | ||||
|  | ||||
| 	// Subscription is in invalid status. | ||||
| 	ErrAppsSubscriptionInvalidStatus ErrorType = 1257 | ||||
|  | ||||
| 	// Invalid screen name. | ||||
| 	ErrInvalidAddress ErrorType = 1260 | ||||
|  | ||||
| 	// Catalog is not available for this user. | ||||
| 	ErrCommunitiesCatalogDisabled ErrorType = 1310 | ||||
|  | ||||
| 	// Catalog categories are not available for this user. | ||||
| 	ErrCommunitiesCategoriesDisabled ErrorType = 1311 | ||||
|  | ||||
| 	// Too late for restore. | ||||
| 	ErrMarketRestoreTooLate ErrorType = 1400 | ||||
|  | ||||
| 	// Comments for this market are closed. | ||||
| 	ErrMarketCommentsClosed ErrorType = 1401 | ||||
|  | ||||
| 	// Album not found. | ||||
| 	ErrMarketAlbumNotFound ErrorType = 1402 | ||||
|  | ||||
| 	// Item not found. | ||||
| 	ErrMarketItemNotFound ErrorType = 1403 | ||||
|  | ||||
| 	// Item already added to album. | ||||
| 	ErrMarketItemAlreadyAdded ErrorType = 1404 | ||||
|  | ||||
| 	// Too many items. | ||||
| 	ErrMarketTooManyItems ErrorType = 1405 | ||||
|  | ||||
| 	// Too many items in album. | ||||
| 	ErrMarketTooManyItemsInAlbum ErrorType = 1406 | ||||
|  | ||||
| 	// Too many albums. | ||||
| 	ErrMarketTooManyAlbums ErrorType = 1407 | ||||
|  | ||||
| 	// Item has bad links in description. | ||||
| 	ErrMarketItemHasBadLinks ErrorType = 1408 | ||||
|  | ||||
| 	// Shop not enabled. | ||||
| 	ErrMarketShopNotEnabled ErrorType = 1409 | ||||
|  | ||||
| 	// Variant not found. | ||||
| 	ErrMarketVariantNotFound ErrorType = 1416 | ||||
|  | ||||
| 	// Property not found. | ||||
| 	ErrMarketPropertyNotFound ErrorType = 1417 | ||||
|  | ||||
| 	// Grouping must have two or more items. | ||||
| 	ErrMarketGroupingMustContainMoreThanOneItem ErrorType = 1425 | ||||
|  | ||||
| 	// Item must have distinct properties. | ||||
| 	ErrMarketGroupingItemsMustHaveDistinctProperties ErrorType = 1426 | ||||
|  | ||||
| 	// Cart is empty. | ||||
| 	ErrMarketOrdersNoCartItems ErrorType = 1427 | ||||
|  | ||||
| 	// Specify width, length, height and weight all together. | ||||
| 	ErrMarketInvalidDimensions ErrorType = 1429 | ||||
|  | ||||
| 	// VK Pay status can not be changed. | ||||
| 	ErrMarketCantChangeVkpayStatus ErrorType = 1430 | ||||
|  | ||||
| 	// Market was already enabled in this group. | ||||
| 	ErrMarketShopAlreadyEnabled ErrorType = 1431 | ||||
|  | ||||
| 	// Market was already disabled in this group. | ||||
| 	ErrMarketShopAlreadyDisabled ErrorType = 1432 | ||||
|  | ||||
| 	// Invalid image crop format. | ||||
| 	ErrMarketPhotosCropInvalidFormat ErrorType = 1433 | ||||
|  | ||||
| 	// Crop bottom right corner is outside of the image. | ||||
| 	ErrMarketPhotosCropOverflow ErrorType = 1434 | ||||
|  | ||||
| 	// Crop size is less than the minimum. | ||||
| 	ErrMarketPhotosCropSizeTooLow ErrorType = 1435 | ||||
|  | ||||
| 	// Cart is empty. | ||||
| 	ErrMarketCartEmpty ErrorType = 1427 | ||||
|  | ||||
| 	// Specify width, length, height and weight all together. | ||||
| 	ErrMarketSpecifyDimensions ErrorType = 1429 | ||||
|  | ||||
| 	// VK Pay status can not be changed. | ||||
| 	ErrVKPayStatus ErrorType = 1430 | ||||
|  | ||||
| 	// Market was already enabled in this group. | ||||
| 	ErrMarketAlreadyEnabled ErrorType = 1431 | ||||
|  | ||||
| 	// Market was already disabled in this group. | ||||
| 	ErrMarketAlreadyDisabled ErrorType = 1432 | ||||
|  | ||||
| 	// Story has already expired. | ||||
| 	ErrStoryExpired ErrorType = 1600 | ||||
|  | ||||
| 	// Incorrect reply privacy. | ||||
| 	ErrStoryIncorrectReplyPrivacy ErrorType = 1602 | ||||
|  | ||||
| 	// Card not found. | ||||
| 	ErrPrettyCardsCardNotFound ErrorType = 1900 | ||||
|  | ||||
| 	// Too many cards. | ||||
| 	ErrPrettyCardsTooManyCards ErrorType = 1901 | ||||
|  | ||||
| 	// Card is connected to post. | ||||
| 	ErrPrettyCardsCardIsConnectedToPost ErrorType = 1902 | ||||
|  | ||||
| 	// Servers number limit is reached. | ||||
| 	ErrCallbackServersLimit ErrorType = 2000 | ||||
|  | ||||
| 	// Specified link is incorrect (can't find source). | ||||
| 	ErrWallCheckLinkCantDetermineSource ErrorType = 3102 | ||||
|  | ||||
| 	// Recaptcha needed. | ||||
| 	ErrRecaptcha ErrorType = 3300 | ||||
|  | ||||
| 	// Phone validation needed. | ||||
| 	ErrPhoneValidation ErrorType = 3301 | ||||
|  | ||||
| 	// Password validation needed. | ||||
| 	ErrPasswordValidation ErrorType = 3302 | ||||
|  | ||||
| 	// Otp app validation needed. | ||||
| 	ErrOtpAppValidation ErrorType = 3303 | ||||
|  | ||||
| 	// Email confirmation needed. | ||||
| 	ErrEmailConfirmation ErrorType = 3304 | ||||
|  | ||||
| 	// Assert votes. | ||||
| 	ErrAssertVotes ErrorType = 3305 | ||||
|  | ||||
| 	// Token extension required. | ||||
| 	ErrTokenExtension ErrorType = 3609 | ||||
|  | ||||
| 	// User is deactivated. | ||||
| 	ErrUserDeactivated ErrorType = 3610 | ||||
|  | ||||
| 	// Service is deactivated for user. | ||||
| 	ErrServiceDeactivated ErrorType = 3611 | ||||
|  | ||||
| 	// Can't set AliExpress tag to this type of object. | ||||
| 	ErrAliExpressTag ErrorType = 3800 | ||||
| ) | ||||
|  | ||||
| // ErrorSubtype is the subtype of an error. | ||||
| type ErrorSubtype int | ||||
|  | ||||
| // Error returns the message of a ErrorSubtype. | ||||
| func (e ErrorSubtype) Error() string { | ||||
| 	return fmt.Sprintf("api: error with subcode %d", e) | ||||
| } | ||||
|  | ||||
| // Error struct VK. | ||||
| type Error struct { | ||||
| 	Code       ErrorType    `json:"error_code"` | ||||
| 	Subcode    ErrorSubtype `json:"error_subcode"` | ||||
| 	Message    string       `json:"error_msg"` | ||||
| 	Text       string       `json:"error_text"` | ||||
| 	CaptchaSID string       `json:"captcha_sid"` | ||||
| 	CaptchaImg string       `json:"captcha_img"` | ||||
|  | ||||
| 	// In some cases VK requires to request action confirmation from the user | ||||
| 	// (for Standalone apps only). Following error will be returned: | ||||
| 	// | ||||
| 	// Error code: 24 | ||||
| 	// Error text: Confirmation required | ||||
| 	// | ||||
| 	// Following parameter is transmitted with the error message as well: | ||||
| 	// | ||||
| 	// confirmation_text – text of the message to be shown in the default | ||||
| 	// confirmation window. | ||||
| 	// | ||||
| 	// The app should display the default confirmation window with text from | ||||
| 	// confirmation_text and two buttons: "Continue" and "Cancel". If user | ||||
| 	// confirms the action repeat the request with an extra parameter: | ||||
| 	// confirm = 1. | ||||
| 	// | ||||
| 	// See https://vk.com/dev/need_confirmation | ||||
| 	ConfirmationText string `json:"confirmation_text"` | ||||
|  | ||||
| 	// In some cases VK requires a user validation procedure. . As a result | ||||
| 	// starting from API version 5.0 (for the older versions captcha_error | ||||
| 	// will be requested) following error will be returned as a reply to any | ||||
| 	// API request: | ||||
| 	// | ||||
| 	// Error code: 17 | ||||
| 	// Error text: Validation Required | ||||
| 	// | ||||
| 	// Following parameter is transmitted with an error message: | ||||
| 	// redirect_uri – a special address to open in a browser to pass the | ||||
| 	// validation procedure. | ||||
| 	// | ||||
| 	// After passing the validation a user will be redirected to the service | ||||
| 	// page: | ||||
| 	// | ||||
| 	// https://oauth.vk.com/blank.html#{Data required for validation} | ||||
| 	// | ||||
| 	// In case of successful validation following parameters will be | ||||
| 	// transmitted after #: | ||||
| 	// | ||||
| 	// https://oauth.vk.com/blank.html#success=1&access_token={NEW USER TOKEN}&user_id={USER ID} | ||||
| 	// | ||||
| 	// If a token was not received by https a new secret will be transmitted | ||||
| 	// as well. | ||||
| 	// | ||||
| 	// In case of unsuccessful validation following address is transmitted: | ||||
| 	// | ||||
| 	// https://oauth.vk.com/blank.html#fail=1 | ||||
| 	// | ||||
| 	// See https://vk.com/dev/need_validation | ||||
| 	RedirectURI   string                    `json:"redirect_uri"` | ||||
| 	RequestParams []object.BaseRequestParam `json:"request_params"` | ||||
| } | ||||
|  | ||||
| // Error returns the message of a Error. | ||||
| func (e Error) Error() string { | ||||
| 	return "api: " + e.Message | ||||
| } | ||||
|  | ||||
| // Is unwraps its first argument sequentially looking for an error that matches | ||||
| // the second. | ||||
| func (e Error) Is(target error) bool { | ||||
| 	var tError *Error | ||||
| 	if errors.As(target, &tError) { | ||||
| 		return e.Code == tError.Code && e.Message == tError.Message | ||||
| 	} | ||||
|  | ||||
| 	var tErrorType ErrorType | ||||
| 	if errors.As(target, &tErrorType) { | ||||
| 		return e.Code == tErrorType | ||||
| 	} | ||||
|  | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| // ExecuteError struct. | ||||
| // | ||||
| // TODO: v3 Code is ErrorType. | ||||
| type ExecuteError struct { | ||||
| 	Method string `json:"method"` | ||||
| 	Code   int    `json:"error_code"` | ||||
| 	Msg    string `json:"error_msg"` | ||||
| } | ||||
|  | ||||
| // ExecuteErrors type. | ||||
| type ExecuteErrors []ExecuteError | ||||
|  | ||||
| // Error returns the message of a ExecuteErrors. | ||||
| func (e ExecuteErrors) Error() string { | ||||
| 	return fmt.Sprintf("api: execute errors (%d)", len(e)) | ||||
| } | ||||
|  | ||||
| // InvalidContentType type. | ||||
| type InvalidContentType struct { | ||||
| 	ContentType string | ||||
| } | ||||
|  | ||||
| // Error returns the message of a InvalidContentType. | ||||
| func (e InvalidContentType) Error() string { | ||||
| 	return "api: invalid content-type" | ||||
| } | ||||
|  | ||||
| // UploadError type. | ||||
| type UploadError struct { | ||||
| 	Err      string `json:"error"` | ||||
| 	Code     int    `json:"error_code"` | ||||
| 	Descr    string `json:"error_descr"` | ||||
| 	IsLogged bool   `json:"error_is_logged"` | ||||
| } | ||||
|  | ||||
| // Error returns the message of a UploadError. | ||||
| func (e UploadError) Error() string { | ||||
| 	if e.Err != "" { | ||||
| 		return "api: " + e.Err | ||||
| 	} | ||||
|  | ||||
| 	return fmt.Sprintf("api: upload code %d", e.Code) | ||||
| } | ||||
|  | ||||
| // AdsError struct. | ||||
| type AdsError struct { | ||||
| 	Code ErrorType `json:"error_code"` | ||||
| 	Desc string    `json:"error_desc"` | ||||
| } | ||||
|  | ||||
| // Error returns the message of a AdsError. | ||||
| func (e AdsError) Error() string { | ||||
| 	return "api: " + e.Desc | ||||
| } | ||||
|  | ||||
| // Is unwraps its first argument sequentially looking for an error that matches | ||||
| // the second. | ||||
| func (e AdsError) Is(target error) bool { | ||||
| 	var tAdsError *AdsError | ||||
| 	if errors.As(target, &tAdsError) { | ||||
| 		return e.Code == tAdsError.Code && e.Desc == tAdsError.Desc | ||||
| 	} | ||||
|  | ||||
| 	var tErrorType ErrorType | ||||
| 	if errors.As(target, &tErrorType) { | ||||
| 		return e.Code == tErrorType | ||||
| 	} | ||||
|  | ||||
| 	return false | ||||
| } | ||||
							
								
								
									
										52
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/execute.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/execute.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| package api | ||||
|  | ||||
| import "encoding/json" | ||||
|  | ||||
| // ExecuteWithArgs a universal method for calling a sequence of other methods | ||||
| // while saving and filtering interim results. | ||||
| // | ||||
| // The Args map variable allows you to retrieve the parameters passed during | ||||
| // the request and avoids code formatting. | ||||
| // | ||||
| // 	return Args.code; // return parameter "code" | ||||
| // 	return Args.v; // return parameter "v" | ||||
| // | ||||
| // https://vk.com/dev/execute | ||||
| func (vk *VK) ExecuteWithArgs(code string, params Params, obj interface{}) error { | ||||
| 	token := vk.getToken() | ||||
|  | ||||
| 	reqParams := Params{ | ||||
| 		"code":         code, | ||||
| 		"access_token": token, | ||||
| 		"v":            vk.Version, | ||||
| 	} | ||||
|  | ||||
| 	resp, err := vk.Handler("execute", params, reqParams) | ||||
|  | ||||
| 	jsonErr := json.Unmarshal(resp.Response, &obj) | ||||
| 	if jsonErr != nil { | ||||
| 		return jsonErr | ||||
| 	} | ||||
|  | ||||
| 	if resp.ExecuteErrors != nil { | ||||
| 		return &resp.ExecuteErrors | ||||
| 	} | ||||
|  | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // Execute a universal method for calling a sequence of other methods while | ||||
| // saving and filtering interim results. | ||||
| // | ||||
| // https://vk.com/dev/execute | ||||
| func (vk *VK) Execute(code string, obj interface{}) error { | ||||
| 	return vk.ExecuteWithArgs(code, Params{}, obj) | ||||
| } | ||||
|  | ||||
| func fmtBool(value bool) string { | ||||
| 	if value { | ||||
| 		return "1" | ||||
| 	} | ||||
|  | ||||
| 	return "0" | ||||
| } | ||||
							
								
								
									
										231
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/fave.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/fave.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,231 @@ | ||||
| package api // import "github.com/SevereCloud/vksdk/v2/api" | ||||
|  | ||||
| import ( | ||||
| 	"github.com/SevereCloud/vksdk/v2/object" | ||||
| ) | ||||
|  | ||||
| // FaveAddArticle adds a link to user faves. | ||||
| // | ||||
| // https://vk.com/dev/fave.addArticle | ||||
| func (vk *VK) FaveAddArticle(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.addArticle", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveAddLink adds a link to user faves. | ||||
| // | ||||
| // https://vk.com/dev/fave.addLink | ||||
| func (vk *VK) FaveAddLink(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.addLink", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveAddPage method. | ||||
| // | ||||
| // https://vk.com/dev/fave.addPage | ||||
| func (vk *VK) FaveAddPage(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.addPage", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveAddPost method. | ||||
| // | ||||
| // https://vk.com/dev/fave.addPost | ||||
| func (vk *VK) FaveAddPost(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.addPost", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveAddProduct method. | ||||
| // | ||||
| // https://vk.com/dev/fave.addProduct | ||||
| func (vk *VK) FaveAddProduct(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.addProduct", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveAddTagResponse struct. | ||||
| type FaveAddTagResponse object.FaveTag | ||||
|  | ||||
| // FaveAddTag method. | ||||
| // | ||||
| // https://vk.com/dev/fave.addTag | ||||
| func (vk *VK) FaveAddTag(params Params) (response FaveAddTagResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.addTag", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveAddVideo method. | ||||
| // | ||||
| // https://vk.com/dev/fave.addVideo | ||||
| func (vk *VK) FaveAddVideo(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.addVideo", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveEditTag method. | ||||
| // | ||||
| // https://vk.com/dev/fave.editTag | ||||
| func (vk *VK) FaveEditTag(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.editTag", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveGetResponse struct. | ||||
| type FaveGetResponse struct { | ||||
| 	Count int               `json:"count"` | ||||
| 	Items []object.FaveItem `json:"items"` | ||||
| } | ||||
|  | ||||
| // FaveGet method. | ||||
| // | ||||
| // 	extended=0 | ||||
| // | ||||
| // https://vk.com/dev/fave.get | ||||
| func (vk *VK) FaveGet(params Params) (response FaveGetResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.get", &response, params, Params{"extended": false}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveGetExtendedResponse struct. | ||||
| type FaveGetExtendedResponse struct { | ||||
| 	Count int               `json:"count"` | ||||
| 	Items []object.FaveItem `json:"items"` | ||||
| 	object.ExtendedResponse | ||||
| } | ||||
|  | ||||
| // FaveGetExtended method. | ||||
| // | ||||
| // 	extended=1 | ||||
| // | ||||
| // https://vk.com/dev/fave.get | ||||
| func (vk *VK) FaveGetExtended(params Params) (response FaveGetExtendedResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.get", &response, params, Params{"extended": true}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveGetPagesResponse struct. | ||||
| type FaveGetPagesResponse struct { | ||||
| 	Count int               `json:"count"` | ||||
| 	Items []object.FavePage `json:"items"` | ||||
| } | ||||
|  | ||||
| // FaveGetPages method. | ||||
| // | ||||
| // https://vk.com/dev/fave.getPages | ||||
| func (vk *VK) FaveGetPages(params Params) (response FaveGetPagesResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.getPages", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveGetTagsResponse struct. | ||||
| type FaveGetTagsResponse struct { | ||||
| 	Count int              `json:"count"` | ||||
| 	Items []object.FaveTag `json:"items"` | ||||
| } | ||||
|  | ||||
| // FaveGetTags method. | ||||
| // | ||||
| // https://vk.com/dev/fave.getTags | ||||
| func (vk *VK) FaveGetTags(params Params) (response FaveGetTagsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.getTags", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveMarkSeen method. | ||||
| // | ||||
| // https://vk.com/dev/fave.markSeen | ||||
| func (vk *VK) FaveMarkSeen(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.markSeen", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveRemoveArticle method. | ||||
| // | ||||
| // https://vk.com/dev/fave.removeArticle | ||||
| func (vk *VK) FaveRemoveArticle(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.removeArticle", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveRemoveLink removes link from the user's faves. | ||||
| // | ||||
| // https://vk.com/dev/fave.removeLink | ||||
| func (vk *VK) FaveRemoveLink(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.removeLink", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveRemovePage method. | ||||
| // | ||||
| // https://vk.com/dev/fave.removePage | ||||
| func (vk *VK) FaveRemovePage(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.removePage", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveRemovePost method. | ||||
| // | ||||
| // https://vk.com/dev/fave.removePost | ||||
| func (vk *VK) FaveRemovePost(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.removePost", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveRemoveProduct method. | ||||
| // | ||||
| // https://vk.com/dev/fave.removeProduct | ||||
| func (vk *VK) FaveRemoveProduct(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.removeProduct", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveRemoveTag method. | ||||
| // | ||||
| // https://vk.com/dev/fave.removeTag | ||||
| func (vk *VK) FaveRemoveTag(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.removeTag", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveRemoveVideo method. | ||||
| // | ||||
| // https://vk.com/dev/fave.removeVideo | ||||
| func (vk *VK) FaveRemoveVideo(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.removeVideo", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveReorderTags method. | ||||
| // | ||||
| // https://vk.com/dev/fave.reorderTags | ||||
| func (vk *VK) FaveReorderTags(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.reorderTags", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveSetPageTags method. | ||||
| // | ||||
| // https://vk.com/dev/fave.setPageTags | ||||
| func (vk *VK) FaveSetPageTags(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.setPageTags", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveSetTags method. | ||||
| // | ||||
| // https://vk.com/dev/fave.setTags | ||||
| func (vk *VK) FaveSetTags(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.setTags", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FaveTrackPageInteraction method. | ||||
| // | ||||
| // https://vk.com/dev/fave.trackPageInteraction | ||||
| func (vk *VK) FaveTrackPageInteraction(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("fave.trackPageInteraction", &response, params) | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										295
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/friends.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										295
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/friends.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,295 @@ | ||||
| package api // import "github.com/SevereCloud/vksdk/v2/api" | ||||
|  | ||||
| import ( | ||||
| 	"github.com/SevereCloud/vksdk/v2/object" | ||||
| ) | ||||
|  | ||||
| // FriendsAdd approves or creates a friend request. | ||||
| // | ||||
| // https://vk.com/dev/friends.add | ||||
| func (vk *VK) FriendsAdd(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("friends.add", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsAddListResponse struct. | ||||
| type FriendsAddListResponse struct { | ||||
| 	ListID int `json:"list_id"` | ||||
| } | ||||
|  | ||||
| // FriendsAddList creates a new friend list for the current user. | ||||
| // | ||||
| // https://vk.com/dev/friends.addList | ||||
| func (vk *VK) FriendsAddList(params Params) (response FriendsAddListResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("friends.addList", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsAreFriendsResponse struct. | ||||
| type FriendsAreFriendsResponse []object.FriendsFriendStatus | ||||
|  | ||||
| // FriendsAreFriends checks the current user's friendship status with other specified users. | ||||
| // | ||||
| // https://vk.com/dev/friends.areFriends | ||||
| func (vk *VK) FriendsAreFriends(params Params) (response FriendsAreFriendsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("friends.areFriends", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsDeleteResponse struct. | ||||
| type FriendsDeleteResponse struct { | ||||
| 	Success           object.BaseBoolInt `json:"success"` | ||||
| 	FriendDeleted     object.BaseBoolInt `json:"friend_deleted"` | ||||
| 	OutRequestDeleted object.BaseBoolInt `json:"out_request_deleted"` | ||||
| 	InRequestDeleted  object.BaseBoolInt `json:"in_request_deleted"` | ||||
| 	SuggestionDeleted object.BaseBoolInt `json:"suggestion_deleted"` | ||||
| } | ||||
|  | ||||
| // FriendsDelete declines a friend request or deletes a user from the current user's friend list. | ||||
| // | ||||
| // https://vk.com/dev/friends.delete | ||||
| func (vk *VK) FriendsDelete(params Params) (response FriendsDeleteResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("friends.delete", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsDeleteAllRequests marks all incoming friend requests as viewed. | ||||
| // | ||||
| // https://vk.com/dev/friends.deleteAllRequests | ||||
| func (vk *VK) FriendsDeleteAllRequests(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("friends.deleteAllRequests", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsDeleteList deletes a friend list of the current user. | ||||
| // | ||||
| // https://vk.com/dev/friends.deleteList | ||||
| func (vk *VK) FriendsDeleteList(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("friends.deleteList", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsEdit edits the friend lists of the selected user. | ||||
| // | ||||
| // https://vk.com/dev/friends.edit | ||||
| func (vk *VK) FriendsEdit(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("friends.edit", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsEditList edits a friend list of the current user. | ||||
| // | ||||
| // https://vk.com/dev/friends.editList | ||||
| func (vk *VK) FriendsEditList(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("friends.editList", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsGetResponse struct. | ||||
| type FriendsGetResponse struct { | ||||
| 	Count int   `json:"count"` | ||||
| 	Items []int `json:"items"` | ||||
| } | ||||
|  | ||||
| // FriendsGet returns a list of user IDs or detailed information about a user's friends. | ||||
| // | ||||
| // https://vk.com/dev/friends.get | ||||
| func (vk *VK) FriendsGet(params Params) (response FriendsGetResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("friends.get", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsGetFieldsResponse struct. | ||||
| type FriendsGetFieldsResponse struct { | ||||
| 	Count int                          `json:"count"` | ||||
| 	Items []object.FriendsUserXtrLists `json:"items"` | ||||
| } | ||||
|  | ||||
| // FriendsGetFields returns a list of user IDs or detailed information about a user's friends. | ||||
| // | ||||
| // https://vk.com/dev/friends.get | ||||
| func (vk *VK) FriendsGetFields(params Params) (response FriendsGetFieldsResponse, err error) { | ||||
| 	reqParams := make(Params) | ||||
| 	if v, prs := params["fields"]; v == "" || !prs { | ||||
| 		reqParams["fields"] = "id" | ||||
| 	} | ||||
|  | ||||
| 	err = vk.RequestUnmarshal("friends.get", &response, params, reqParams) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsGetAppUsersResponse struct. | ||||
| type FriendsGetAppUsersResponse []int | ||||
|  | ||||
| // FriendsGetAppUsers returns a list of IDs of the current user's friends who installed the application. | ||||
| // | ||||
| // https://vk.com/dev/friends.getAppUsers | ||||
| func (vk *VK) FriendsGetAppUsers(params Params) (response FriendsGetAppUsersResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("friends.getAppUsers", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsGetByPhonesResponse struct. | ||||
| type FriendsGetByPhonesResponse []object.FriendsUserXtrPhone | ||||
|  | ||||
| // FriendsGetByPhones returns a list of the current user's friends | ||||
| // whose phone numbers, validated or specified in a profile, are in a given list. | ||||
| // | ||||
| // https://vk.com/dev/friends.getByPhones | ||||
| func (vk *VK) FriendsGetByPhones(params Params) (response FriendsGetByPhonesResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("friends.getByPhones", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsGetListsResponse struct. | ||||
| type FriendsGetListsResponse struct { | ||||
| 	Count int                         `json:"count"` | ||||
| 	Items []object.FriendsFriendsList `json:"items"` | ||||
| } | ||||
|  | ||||
| // FriendsGetLists returns a list of the user's friend lists. | ||||
| // | ||||
| // https://vk.com/dev/friends.getLists | ||||
| func (vk *VK) FriendsGetLists(params Params) (response FriendsGetListsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("friends.getLists", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsGetMutualResponse struct. | ||||
| type FriendsGetMutualResponse []int | ||||
|  | ||||
| // FriendsGetMutual returns a list of user IDs of the mutual friends of two users. | ||||
| // | ||||
| // https://vk.com/dev/friends.getMutual | ||||
| func (vk *VK) FriendsGetMutual(params Params) (response FriendsGetMutualResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("friends.getMutual", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsGetOnline returns a list of user IDs of a user's friends who are online. | ||||
| // | ||||
| // 	online_mobile=0 | ||||
| // | ||||
| // https://vk.com/dev/friends.getOnline | ||||
| func (vk *VK) FriendsGetOnline(params Params) (response []int, err error) { | ||||
| 	err = vk.RequestUnmarshal("friends.getOnline", &response, params, Params{"online_mobile": false}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsGetOnlineOnlineMobileResponse struct. | ||||
| type FriendsGetOnlineOnlineMobileResponse struct { | ||||
| 	Online       []int `json:"online"` | ||||
| 	OnlineMobile []int `json:"online_mobile"` | ||||
| } | ||||
|  | ||||
| // FriendsGetOnlineOnlineMobile returns a list of user IDs of a user's friends who are online. | ||||
| // | ||||
| // 	online_mobile=1 | ||||
| // | ||||
| // https://vk.com/dev/friends.getOnline | ||||
| func (vk *VK) FriendsGetOnlineOnlineMobile(params Params) (response FriendsGetOnlineOnlineMobileResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("friends.getOnline", &response, params, Params{"online_mobile": true}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsGetRecentResponse struct. | ||||
| type FriendsGetRecentResponse []int | ||||
|  | ||||
| // FriendsGetRecent returns a list of user IDs of the current user's recently added friends. | ||||
| // | ||||
| // https://vk.com/dev/friends.getRecent | ||||
| func (vk *VK) FriendsGetRecent(params Params) (response FriendsGetRecentResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("friends.getRecent", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsGetRequestsResponse struct. | ||||
| type FriendsGetRequestsResponse struct { | ||||
| 	Count int   `json:"count"` // Total requests number | ||||
| 	Items []int `json:"items"` | ||||
| } | ||||
|  | ||||
| // FriendsGetRequests returns information about the current user's incoming and outgoing friend requests. | ||||
| // | ||||
| // https://vk.com/dev/friends.getRequests | ||||
| func (vk *VK) FriendsGetRequests(params Params) (response FriendsGetRequestsResponse, err error) { | ||||
| 	reqParams := Params{ | ||||
| 		"need_mutual": false, | ||||
| 		"extended":    false, | ||||
| 	} | ||||
|  | ||||
| 	err = vk.RequestUnmarshal("friends.getRequests", &response, params, reqParams) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsGetRequestsNeedMutualResponse struct. | ||||
| type FriendsGetRequestsNeedMutualResponse struct { | ||||
| 	Count int                      `json:"count"` // Total requests number | ||||
| 	Items []object.FriendsRequests `json:"items"` | ||||
| } | ||||
|  | ||||
| // FriendsGetRequestsNeedMutual returns information about the current user's incoming and outgoing friend requests. | ||||
| // | ||||
| // https://vk.com/dev/friends.getRequests | ||||
| func (vk *VK) FriendsGetRequestsNeedMutual(params Params) (response FriendsGetRequestsNeedMutualResponse, err error) { | ||||
| 	reqParams := Params{ | ||||
| 		"extended":    false, | ||||
| 		"need_mutual": true, | ||||
| 	} | ||||
|  | ||||
| 	err = vk.RequestUnmarshal("friends.getRequests", &response, params, reqParams) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsGetRequestsExtendedResponse struct. | ||||
| type FriendsGetRequestsExtendedResponse struct { | ||||
| 	Count int                                `json:"count"` | ||||
| 	Items []object.FriendsRequestsXtrMessage `json:"items"` | ||||
| } | ||||
|  | ||||
| // FriendsGetRequestsExtended returns information about the current user's incoming and outgoing friend requests. | ||||
| // | ||||
| // https://vk.com/dev/friends.getRequests | ||||
| func (vk *VK) FriendsGetRequestsExtended(params Params) (response FriendsGetRequestsExtendedResponse, err error) { | ||||
| 	reqParams := Params{ | ||||
| 		"need_mutual": false, | ||||
| 		"extended":    true, | ||||
| 	} | ||||
|  | ||||
| 	err = vk.RequestUnmarshal("friends.getRequests", &response, params, reqParams) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsGetSuggestionsResponse struct. | ||||
| type FriendsGetSuggestionsResponse struct { | ||||
| 	Count int                `json:"count"` | ||||
| 	Items []object.UsersUser `json:"items"` | ||||
| } | ||||
|  | ||||
| // FriendsGetSuggestions returns a list of profiles of users whom the current user may know. | ||||
| // | ||||
| // https://vk.com/dev/friends.getSuggestions | ||||
| func (vk *VK) FriendsGetSuggestions(params Params) (response FriendsGetSuggestionsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("friends.getSuggestions", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // FriendsSearchResponse struct. | ||||
| type FriendsSearchResponse struct { | ||||
| 	Count int                `json:"count"` | ||||
| 	Items []object.UsersUser `json:"items"` | ||||
| } | ||||
|  | ||||
| // FriendsSearch returns a list of friends matching the search criteria. | ||||
| // | ||||
| // https://vk.com/dev/friends.search | ||||
| func (vk *VK) FriendsSearch(params Params) (response FriendsSearchResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("friends.search", &response, params) | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										32
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/gifts.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/gifts.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| package api // import "github.com/SevereCloud/vksdk/v2/api" | ||||
|  | ||||
| import "github.com/SevereCloud/vksdk/v2/object" | ||||
|  | ||||
| // GiftsGetResponse struct. | ||||
| type GiftsGetResponse struct { | ||||
| 	Count int                `json:"count"` | ||||
| 	Items []object.GiftsGift `json:"items"` | ||||
| } | ||||
|  | ||||
| // GiftsGet returns a list of user gifts. | ||||
| // | ||||
| // https://vk.com/dev/gifts.get | ||||
| func (vk *VK) GiftsGet(params Params) (response GiftsGetResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("gifts.get", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GiftsGetCatalogResponse struct. | ||||
| type GiftsGetCatalogResponse []struct { | ||||
| 	Name  string             `json:"name"` | ||||
| 	Title string             `json:"title"` | ||||
| 	Items []object.GiftsGift `json:"items"` | ||||
| } | ||||
|  | ||||
| // GiftsGetCatalog returns catalog. | ||||
| // | ||||
| // https://vk.com/dev/gifts.get | ||||
| func (vk *VK) GiftsGetCatalog(params Params) (response GiftsGetCatalogResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("gifts.getCatalog", &response, params) | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										712
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/groups.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										712
									
								
								vendor/github.com/SevereCloud/vksdk/v2/api/groups.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,712 @@ | ||||
| package api // import "github.com/SevereCloud/vksdk/v2/api" | ||||
|  | ||||
| import ( | ||||
| 	"github.com/SevereCloud/vksdk/v2/object" | ||||
| ) | ||||
|  | ||||
| // GroupsAddAddressResponse struct. | ||||
| type GroupsAddAddressResponse object.GroupsAddress | ||||
|  | ||||
| // GroupsAddAddress groups.addAddress. | ||||
| // | ||||
| // https://vk.com/dev/groups.addAddress | ||||
| func (vk *VK) GroupsAddAddress(params Params) (response GroupsAddAddressResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.addAddress", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsAddCallbackServerResponse struct. | ||||
| type GroupsAddCallbackServerResponse struct { | ||||
| 	ServerID int `json:"server_id"` | ||||
| } | ||||
|  | ||||
| // GroupsAddCallbackServer callback API server to the community. | ||||
| // | ||||
| // https://vk.com/dev/groups.addCallbackServer | ||||
| func (vk *VK) GroupsAddCallbackServer(params Params) (response GroupsAddCallbackServerResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.addCallbackServer", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsAddLinkResponse struct. | ||||
| type GroupsAddLinkResponse object.GroupsGroupLink | ||||
|  | ||||
| // GroupsAddLink allows to add a link to the community. | ||||
| // | ||||
| // https://vk.com/dev/groups.addLink | ||||
| func (vk *VK) GroupsAddLink(params Params) (response GroupsAddLinkResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.addLink", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsApproveRequest allows to approve join request to the community. | ||||
| // | ||||
| // https://vk.com/dev/groups.approveRequest | ||||
| func (vk *VK) GroupsApproveRequest(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.approveRequest", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsBan adds a user or a group to the community blacklist. | ||||
| // | ||||
| // https://vk.com/dev/groups.ban | ||||
| func (vk *VK) GroupsBan(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.ban", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsCreateResponse struct. | ||||
| type GroupsCreateResponse object.GroupsGroup | ||||
|  | ||||
| // GroupsCreate creates a new community. | ||||
| // | ||||
| // https://vk.com/dev/groups.create | ||||
| func (vk *VK) GroupsCreate(params Params) (response GroupsCreateResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.create", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsDeleteAddress groups.deleteAddress. | ||||
| // | ||||
| // https://vk.com/dev/groups.deleteAddress | ||||
| func (vk *VK) GroupsDeleteAddress(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.deleteAddress", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsDeleteCallbackServer callback API server from the community. | ||||
| // | ||||
| // https://vk.com/dev/groups.deleteCallbackServer | ||||
| func (vk *VK) GroupsDeleteCallbackServer(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.deleteCallbackServer", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsDeleteLink allows to delete a link from the community. | ||||
| // | ||||
| // https://vk.com/dev/groups.deleteLink | ||||
| func (vk *VK) GroupsDeleteLink(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.deleteLink", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsDisableOnline disables "online" status in the community. | ||||
| // | ||||
| // https://vk.com/dev/groups.disableOnline | ||||
| func (vk *VK) GroupsDisableOnline(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.disableOnline", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsEdit edits a community. | ||||
| // | ||||
| // https://vk.com/dev/groups.edit | ||||
| func (vk *VK) GroupsEdit(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.edit", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsEditAddressResponse struct. | ||||
| type GroupsEditAddressResponse object.GroupsAddress | ||||
|  | ||||
| // GroupsEditAddress groups.editAddress. | ||||
| // | ||||
| // https://vk.com/dev/groups.editAddress | ||||
| func (vk *VK) GroupsEditAddress(params Params) (response GroupsEditAddressResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.editAddress", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsEditCallbackServer edits Callback API server in the community. | ||||
| // | ||||
| // https://vk.com/dev/groups.editCallbackServer | ||||
| func (vk *VK) GroupsEditCallbackServer(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.editCallbackServer", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsEditLink allows to edit a link in the community. | ||||
| // | ||||
| // https://vk.com/dev/groups.editLink | ||||
| func (vk *VK) GroupsEditLink(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.editLink", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsEditManager allows to add, remove or edit the community manager . | ||||
| // | ||||
| // https://vk.com/dev/groups.editManager | ||||
| func (vk *VK) GroupsEditManager(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.editManager", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsEnableOnline enables "online" status in the community. | ||||
| // | ||||
| // https://vk.com/dev/groups.enableOnline | ||||
| func (vk *VK) GroupsEnableOnline(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.enableOnline", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetResponse struct. | ||||
| type GroupsGetResponse struct { | ||||
| 	Count int   `json:"count"` | ||||
| 	Items []int `json:"items"` | ||||
| } | ||||
|  | ||||
| // GroupsGet returns a list of the communities to which a user belongs. | ||||
| // | ||||
| // 	extended=0 | ||||
| // | ||||
| // https://vk.com/dev/groups.get | ||||
| func (vk *VK) GroupsGet(params Params) (response GroupsGetResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.get", &response, params, Params{"extended": false}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetExtendedResponse struct. | ||||
| type GroupsGetExtendedResponse struct { | ||||
| 	Count int                  `json:"count"` | ||||
| 	Items []object.GroupsGroup `json:"items"` | ||||
| } | ||||
|  | ||||
| // GroupsGetExtended returns a list of the communities to which a user belongs. | ||||
| // | ||||
| // 	extended=1 | ||||
| // | ||||
| // https://vk.com/dev/groups.get | ||||
| func (vk *VK) GroupsGetExtended(params Params) (response GroupsGetExtendedResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.get", &response, params, Params{"extended": true}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetAddressesResponse struct. | ||||
| type GroupsGetAddressesResponse struct { | ||||
| 	Count int                    `json:"count"` | ||||
| 	Items []object.GroupsAddress `json:"items"` | ||||
| } | ||||
|  | ||||
| // GroupsGetAddresses groups.getAddresses. | ||||
| // | ||||
| // https://vk.com/dev/groups.getAddresses | ||||
| func (vk *VK) GroupsGetAddresses(params Params) (response GroupsGetAddressesResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.getAddresses", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetBannedResponse struct. | ||||
| type GroupsGetBannedResponse struct { | ||||
| 	Count int                            `json:"count"` | ||||
| 	Items []object.GroupsOwnerXtrBanInfo `json:"items"` | ||||
| } | ||||
|  | ||||
| // GroupsGetBanned returns a list of users on a community blacklist. | ||||
| // | ||||
| // https://vk.com/dev/groups.getBanned | ||||
| func (vk *VK) GroupsGetBanned(params Params) (response GroupsGetBannedResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.getBanned", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetByIDResponse struct. | ||||
| type GroupsGetByIDResponse []object.GroupsGroup | ||||
|  | ||||
| // GroupsGetByID returns information about communities by their IDs. | ||||
| // | ||||
| // https://vk.com/dev/groups.getById | ||||
| func (vk *VK) GroupsGetByID(params Params) (response GroupsGetByIDResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.getById", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetCallbackConfirmationCodeResponse struct. | ||||
| type GroupsGetCallbackConfirmationCodeResponse struct { | ||||
| 	Code string `json:"code"` | ||||
| } | ||||
|  | ||||
| // GroupsGetCallbackConfirmationCode returns Callback API confirmation code for the community. | ||||
| // | ||||
| // https://vk.com/dev/groups.getCallbackConfirmationCode | ||||
| func (vk *VK) GroupsGetCallbackConfirmationCode(params Params) ( | ||||
| 	response GroupsGetCallbackConfirmationCodeResponse, | ||||
| 	err error, | ||||
| ) { | ||||
| 	err = vk.RequestUnmarshal("groups.getCallbackConfirmationCode", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetCallbackServersResponse struct. | ||||
| type GroupsGetCallbackServersResponse struct { | ||||
| 	Count int                           `json:"count"` | ||||
| 	Items []object.GroupsCallbackServer `json:"items"` | ||||
| } | ||||
|  | ||||
| // GroupsGetCallbackServers receives a list of Callback API servers from the community. | ||||
| // | ||||
| // https://vk.com/dev/groups.getCallbackServers | ||||
| func (vk *VK) GroupsGetCallbackServers(params Params) (response GroupsGetCallbackServersResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.getCallbackServers", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetCallbackSettingsResponse struct. | ||||
| type GroupsGetCallbackSettingsResponse object.GroupsCallbackSettings | ||||
|  | ||||
| // GroupsGetCallbackSettings returns Callback API notifications settings. | ||||
| // | ||||
| // BUG(VK): MessageEdit always 0 https://vk.com/bugtracker?act=show&id=86762 | ||||
| // | ||||
| // https://vk.com/dev/groups.getCallbackSettings | ||||
| func (vk *VK) GroupsGetCallbackSettings(params Params) (response GroupsGetCallbackSettingsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.getCallbackSettings", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetCatalogResponse struct. | ||||
| type GroupsGetCatalogResponse struct { | ||||
| 	Count int                  `json:"count"` | ||||
| 	Items []object.GroupsGroup `json:"items"` | ||||
| } | ||||
|  | ||||
| // GroupsGetCatalog returns communities list for a catalog category. | ||||
| // | ||||
| // https://vk.com/dev/groups.getCatalog | ||||
| func (vk *VK) GroupsGetCatalog(params Params) (response GroupsGetCatalogResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.getCatalog", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetCatalogInfoResponse struct. | ||||
| type GroupsGetCatalogInfoResponse struct { | ||||
| 	Enabled    object.BaseBoolInt           `json:"enabled"` | ||||
| 	Categories []object.GroupsGroupCategory `json:"categories"` | ||||
| } | ||||
|  | ||||
| // GroupsGetCatalogInfo returns categories list for communities catalog. | ||||
| // | ||||
| // 	extended=0 | ||||
| // | ||||
| // https://vk.com/dev/groups.getCatalogInfo | ||||
| func (vk *VK) GroupsGetCatalogInfo(params Params) (response GroupsGetCatalogInfoResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.getCatalogInfo", &response, params, Params{"extended": false}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetCatalogInfoExtendedResponse struct. | ||||
| type GroupsGetCatalogInfoExtendedResponse struct { | ||||
| 	Enabled    object.BaseBoolInt               `json:"enabled"` | ||||
| 	Categories []object.GroupsGroupCategoryFull `json:"categories"` | ||||
| } | ||||
|  | ||||
| // GroupsGetCatalogInfoExtended returns categories list for communities catalog. | ||||
| // | ||||
| // 	extended=1 | ||||
| // | ||||
| // https://vk.com/dev/groups.getCatalogInfo | ||||
| func (vk *VK) GroupsGetCatalogInfoExtended(params Params) (response GroupsGetCatalogInfoExtendedResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.getCatalogInfo", &response, params, Params{"extended": true}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetInvitedUsersResponse struct. | ||||
| type GroupsGetInvitedUsersResponse struct { | ||||
| 	Count int                `json:"count"` | ||||
| 	Items []object.UsersUser `json:"items"` | ||||
| } | ||||
|  | ||||
| // GroupsGetInvitedUsers returns invited users list of a community. | ||||
| // | ||||
| // https://vk.com/dev/groups.getInvitedUsers | ||||
| func (vk *VK) GroupsGetInvitedUsers(params Params) (response GroupsGetInvitedUsersResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.getInvitedUsers", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetInvitesResponse struct. | ||||
| type GroupsGetInvitesResponse struct { | ||||
| 	Count int                              `json:"count"` | ||||
| 	Items []object.GroupsGroupXtrInvitedBy `json:"items"` | ||||
| } | ||||
|  | ||||
| // GroupsGetInvites returns a list of invitations to join communities and events. | ||||
| // | ||||
| // https://vk.com/dev/groups.getInvites | ||||
| func (vk *VK) GroupsGetInvites(params Params) (response GroupsGetInvitesResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.getInvites", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetInvitesExtendedResponse struct. | ||||
| type GroupsGetInvitesExtendedResponse struct { | ||||
| 	Count int                              `json:"count"` | ||||
| 	Items []object.GroupsGroupXtrInvitedBy `json:"items"` | ||||
| 	object.ExtendedResponse | ||||
| } | ||||
|  | ||||
| // GroupsGetInvitesExtended returns a list of invitations to join communities and events. | ||||
| // | ||||
| // https://vk.com/dev/groups.getInvites | ||||
| func (vk *VK) GroupsGetInvitesExtended(params Params) (response GroupsGetInvitesExtendedResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.getInvites", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetLongPollServerResponse struct. | ||||
| type GroupsGetLongPollServerResponse object.GroupsLongPollServer | ||||
|  | ||||
| // GroupsGetLongPollServer returns data for Bots Long Poll API connection. | ||||
| // | ||||
| // https://vk.com/dev/groups.getLongPollServer | ||||
| func (vk *VK) GroupsGetLongPollServer(params Params) (response GroupsGetLongPollServerResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.getLongPollServer", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetLongPollSettingsResponse struct. | ||||
| type GroupsGetLongPollSettingsResponse object.GroupsLongPollSettings | ||||
|  | ||||
| // GroupsGetLongPollSettings returns Bots Long Poll API settings. | ||||
| // | ||||
| // https://vk.com/dev/groups.getLongPollSettings | ||||
| func (vk *VK) GroupsGetLongPollSettings(params Params) (response GroupsGetLongPollSettingsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.getLongPollSettings", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetMembersResponse struct. | ||||
| type GroupsGetMembersResponse struct { | ||||
| 	Count int   `json:"count"` | ||||
| 	Items []int `json:"items"` | ||||
| } | ||||
|  | ||||
| // GroupsGetMembers returns a list of community members. | ||||
| // | ||||
| // https://vk.com/dev/groups.getMembers | ||||
| func (vk *VK) GroupsGetMembers(params Params) (response GroupsGetMembersResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.getMembers", &response, params, Params{"filter": ""}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetMembersFieldsResponse struct. | ||||
| type GroupsGetMembersFieldsResponse struct { | ||||
| 	Count int                `json:"count"` | ||||
| 	Items []object.UsersUser `json:"items"` | ||||
| } | ||||
|  | ||||
| // GroupsGetMembersFields returns a list of community members. | ||||
| // | ||||
| // https://vk.com/dev/groups.getMembers | ||||
| func (vk *VK) GroupsGetMembersFields(params Params) (response GroupsGetMembersFieldsResponse, err error) { | ||||
| 	reqParams := make(Params) | ||||
| 	if v, prs := params["fields"]; v == "" || !prs { | ||||
| 		reqParams["fields"] = "id" | ||||
| 	} | ||||
|  | ||||
| 	err = vk.RequestUnmarshal("groups.getMembers", &response, params, reqParams) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetMembersFilterManagersResponse struct. | ||||
| type GroupsGetMembersFilterManagersResponse struct { | ||||
| 	Count int                                   `json:"count"` | ||||
| 	Items []object.GroupsMemberRoleXtrUsersUser `json:"items"` | ||||
| } | ||||
|  | ||||
| // GroupsGetMembersFilterManagers returns a list of community members. | ||||
| // | ||||
| // 	filter=managers | ||||
| // | ||||
| // https://vk.com/dev/groups.getMembers | ||||
| func (vk *VK) GroupsGetMembersFilterManagers(params Params) ( | ||||
| 	response GroupsGetMembersFilterManagersResponse, | ||||
| 	err error, | ||||
| ) { | ||||
| 	err = vk.RequestUnmarshal("groups.getMembers", &response, params, Params{"filter": "managers"}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetOnlineStatusResponse struct. | ||||
| type GroupsGetOnlineStatusResponse object.GroupsOnlineStatus | ||||
|  | ||||
| // GroupsGetOnlineStatus returns a community's online status. | ||||
| // | ||||
| // https://vk.com/dev/groups.getOnlineStatus | ||||
| func (vk *VK) GroupsGetOnlineStatus(params Params) (response GroupsGetOnlineStatusResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.getOnlineStatus", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetRequestsResponse struct. | ||||
| type GroupsGetRequestsResponse struct { | ||||
| 	Count int   `json:"count"` | ||||
| 	Items []int `json:"items"` | ||||
| } | ||||
|  | ||||
| // GroupsGetRequests returns a list of requests to the community. | ||||
| // | ||||
| // https://vk.com/dev/groups.getRequests | ||||
| func (vk *VK) GroupsGetRequests(params Params) (response GroupsGetRequestsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.getRequests", &response, params, Params{"fields": ""}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetRequestsFieldsResponse struct. | ||||
| type GroupsGetRequestsFieldsResponse struct { | ||||
| 	Count int                `json:"count"` | ||||
| 	Items []object.UsersUser `json:"items"` | ||||
| } | ||||
|  | ||||
| // GroupsGetRequestsFields returns a list of requests to the community. | ||||
| // | ||||
| // https://vk.com/dev/groups.getRequests | ||||
| func (vk *VK) GroupsGetRequestsFields(params Params) (response GroupsGetRequestsFieldsResponse, err error) { | ||||
| 	reqParams := make(Params) | ||||
| 	if v, prs := params["fields"]; v == "" || !prs { | ||||
| 		reqParams["fields"] = "id" | ||||
| 	} | ||||
|  | ||||
| 	err = vk.RequestUnmarshal("groups.getRequests", &response, params, reqParams) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetSettingsResponse struct. | ||||
| type GroupsGetSettingsResponse object.GroupsGroupSettings | ||||
|  | ||||
| // GroupsGetSettings returns community settings. | ||||
| // | ||||
| // https://vk.com/dev/groups.getSettings | ||||
| func (vk *VK) GroupsGetSettings(params Params) (response GroupsGetSettingsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.getSettings", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetTagListResponse struct. | ||||
| type GroupsGetTagListResponse []object.GroupsTag | ||||
|  | ||||
| // GroupsGetTagList returns community tags list. | ||||
| // | ||||
| // https://vk.com/dev/groups.getTagList | ||||
| func (vk *VK) GroupsGetTagList(params Params) (response GroupsGetTagListResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.getTagList", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsGetTokenPermissionsResponse struct. | ||||
| type GroupsGetTokenPermissionsResponse object.GroupsTokenPermissions | ||||
|  | ||||
| // GroupsGetTokenPermissions returns permissions scope for the community's access_token. | ||||
| // | ||||
| // https://vk.com/dev/groups.getTokenPermissions | ||||
| func (vk *VK) GroupsGetTokenPermissions(params Params) (response GroupsGetTokenPermissionsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.getTokenPermissions", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsInvite allows to invite friends to the community. | ||||
| // | ||||
| // https://vk.com/dev/groups.invite | ||||
| func (vk *VK) GroupsInvite(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.invite", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsIsMember returns information specifying whether a user is a member of a community. | ||||
| // | ||||
| // 	extended=0 | ||||
| // | ||||
| // https://vk.com/dev/groups.isMember | ||||
| func (vk *VK) GroupsIsMember(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.isMember", &response, params, Params{"extended": false}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsIsMemberExtendedResponse struct. | ||||
| type GroupsIsMemberExtendedResponse struct { | ||||
| 	Invitation object.BaseBoolInt `json:"invitation"` // Information whether user has been invited to the group | ||||
| 	Member     object.BaseBoolInt `json:"member"`     // Information whether user is a member of the group | ||||
| 	Request    object.BaseBoolInt `json:"request"`    // Information whether user has send request to the group | ||||
| 	CanInvite  object.BaseBoolInt `json:"can_invite"` // Information whether user can be invite | ||||
| 	CanRecall  object.BaseBoolInt `json:"can_recall"` // Information whether user's invite to the group can be recalled | ||||
| } | ||||
|  | ||||
| // GroupsIsMemberExtended returns information specifying whether a user is a member of a community. | ||||
| // | ||||
| // 	extended=1 | ||||
| // | ||||
| // https://vk.com/dev/groups.isMember | ||||
| func (vk *VK) GroupsIsMemberExtended(params Params) (response GroupsIsMemberExtendedResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.isMember", &response, params, Params{"extended": true}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsIsMemberUserIDsExtendedResponse struct. | ||||
| type GroupsIsMemberUserIDsExtendedResponse []object.GroupsMemberStatusFull | ||||
|  | ||||
| // GroupsIsMemberUserIDsExtended returns information specifying whether a user is a member of a community. | ||||
| // | ||||
| // 	extended=1 | ||||
| // 	need user_ids | ||||
| // | ||||
| // https://vk.com/dev/groups.isMember | ||||
| func (vk *VK) GroupsIsMemberUserIDsExtended(params Params) (response GroupsIsMemberUserIDsExtendedResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.isMember", &response, params, Params{"extended": true}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsIsMemberUserIDsResponse struct. | ||||
| type GroupsIsMemberUserIDsResponse []object.GroupsMemberStatus | ||||
|  | ||||
| // GroupsIsMemberUserIDs returns information specifying whether a user is a member of a community. | ||||
| // | ||||
| // 	extended=0 | ||||
| // 	need user_ids | ||||
| // | ||||
| // https://vk.com/dev/groups.isMember | ||||
| func (vk *VK) GroupsIsMemberUserIDs(params Params) (response GroupsIsMemberUserIDsResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.isMember", &response, params, Params{"extended": false}) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsJoin with this method you can join the group or public page, and also confirm your participation in an event. | ||||
| // | ||||
| // https://vk.com/dev/groups.join | ||||
| func (vk *VK) GroupsJoin(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.join", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsLeave with this method you can leave a group, public page, or event. | ||||
| // | ||||
| // https://vk.com/dev/groups.leave | ||||
| func (vk *VK) GroupsLeave(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.leave", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsRemoveUser removes a user from the community. | ||||
| // | ||||
| // https://vk.com/dev/groups.removeUser | ||||
| func (vk *VK) GroupsRemoveUser(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.removeUser", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsReorderLink allows to reorder links in the community. | ||||
| // | ||||
| // https://vk.com/dev/groups.reorderLink | ||||
| func (vk *VK) GroupsReorderLink(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.reorderLink", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsSearchResponse struct. | ||||
| type GroupsSearchResponse struct { | ||||
| 	Count int                  `json:"count"` | ||||
| 	Items []object.GroupsGroup `json:"items"` | ||||
| } | ||||
|  | ||||
| // GroupsSearch returns a list of communities matching the search criteria. | ||||
| // | ||||
| // https://vk.com/dev/groups.search | ||||
| func (vk *VK) GroupsSearch(params Params) (response GroupsSearchResponse, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.search", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsSetCallbackSettings allow to set notifications settings for Callback API. | ||||
| // | ||||
| // https://vk.com/dev/groups.setCallbackSettings | ||||
| func (vk *VK) GroupsSetCallbackSettings(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.setCallbackSettings", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsSetLongPollSettings allows to set Bots Long Poll API settings in the community. | ||||
| // | ||||
| // https://vk.com/dev/groups.setLongPollSettings | ||||
| func (vk *VK) GroupsSetLongPollSettings(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.setLongPollSettings", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsSetSettings sets community settings. | ||||
| // | ||||
| // https://vk.com/dev/groups.setSettings | ||||
| func (vk *VK) GroupsSetSettings(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.setSettings", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsSetUserNote allows to create or edit a note about a user as part | ||||
| // of the user's correspondence with the community. | ||||
| // | ||||
| // https://vk.com/dev/groups.setUserNote | ||||
| func (vk *VK) GroupsSetUserNote(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.setUserNote", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsTagAdd allows to add a new tag to the community. | ||||
| // | ||||
| // https://vk.com/dev/groups.tagAdd | ||||
| func (vk *VK) GroupsTagAdd(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.tagAdd", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsTagBind allows to "bind" and "unbind" community tags to conversations. | ||||
| // | ||||
| // https://vk.com/dev/groups.tagBind | ||||
| func (vk *VK) GroupsTagBind(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.tagBind", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsTagDelete allows to remove a community tag | ||||
| // | ||||
| // The remote tag will be automatically "unbind" from all conversations to | ||||
| // which it was "bind" earlier. | ||||
| // | ||||
| // https://vk.com/dev/groups.tagDelete | ||||
| func (vk *VK) GroupsTagDelete(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.tagDelete", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsTagUpdate allows to change an existing tag. | ||||
| // | ||||
| // https://vk.com/dev/groups.tagUpdate | ||||
| func (vk *VK) GroupsTagUpdate(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.tagUpdate", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsToggleMarket method. | ||||
| // | ||||
| // https://vk.com/dev/groups.toggleMarket | ||||
| func (vk *VK) GroupsToggleMarket(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.toggleMarket", &response, params) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GroupsUnban groups.unban. | ||||
| // | ||||
| // https://vk.com/dev/groups.unban | ||||
| func (vk *VK) GroupsUnban(params Params) (response int, err error) { | ||||
| 	err = vk.RequestUnmarshal("groups.unban", &response, params) | ||||
| 	return | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user